Panda3D
maxNodeDesc.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 maxNodeDesc.cxx
10  * @author crevilla
11  * from mayaNodeDesc.cxx created by: drose (06Jun03)
12  */
13 
14 #include "maxEgg.h"
15 
16 TypeHandle MaxNodeDesc::_type_handle;
17 
18 /**
19  * Creates a MaxNodeDesc. The name is copied from the given max node. Use
20  * from_INode to actually associate the desc with a given max node.
21  */
23 MaxNodeDesc(MaxNodeDesc *parent, INode *max_node) :
24  _parent(parent) {
25 
26  if (max_node != nullptr) {
27  const TCHAR *max_name = max_node->GetName();
28 #ifdef _UNICODE
29  char name_mb [1024];
30  name_mb[1023] = 0;
31  wcstombs(name_mb, max_name, 1023);
32  set_name(name_mb);
33 #else
34  set_name(max_name);
35 #endif
36  }
37 
38  _max_node = nullptr;
39  _egg_group = nullptr;
40  _egg_table = nullptr;
41  _anim = nullptr;
42  _joint_type = JT_none;
43  _joint_entry = nullptr;
44 
45  // Add ourselves to our parent.
46  if (_parent != nullptr) {
47  _parent->_children.push_back(this);
48  }
49 }
50 
51 /**
52  *
53  */
54 MaxNodeDesc::
55 ~MaxNodeDesc() {}
56 
57 /**
58  * Indicates an associated between the MaxNodeDesc and some Max Node instance.
59  */
60 void MaxNodeDesc::
61 from_INode(INode *max_node) {
62  if (_max_node == nullptr) {
63  _max_node = max_node;
64 
65  // This is how I decided to check to see if this max node is a joint. It
66  // works in all instances I've seen so far, but this may be a good
67  // starting place to look if joints are not being picked up correctly in
68  // the future.
69 
70  // Check to see if the node's controller is a biped If so treat it as a
71  // joint Get the node's transform control
72  Control *c = max_node->GetTMController();
73  if (_max_node->GetBoneNodeOnOff() ||
74  (c && //c exists and it's type is a biped
75  ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
76  (c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
77  (c->ClassID() == FOOTPRINT_CLASS_ID)))) {
78 
79  // This node is a joint.
80  _joint_type = JT_node_joint;
81  if (_parent != nullptr) {
82  _parent->mark_joint_parent();
83  }
84  }
85  }
86 }
87 
88 /**
89  * Returns true if a Max INode has been associated with this node, false
90  * otherwise.
91  */
92 bool MaxNodeDesc::
93 has_max_node() const {
94  return (_max_node != nullptr);
95 }
96 
97 /**
98  * Returns the INode associated with this node. It is an error to call this
99  * unless has_max_node() returned true.
100  */
101 INode *MaxNodeDesc::
102 get_max_node() const {
103  nassertr(_max_node != nullptr, _max_node);
104  return _max_node;
105 }
106 
107 
108 void MaxNodeDesc::
109 set_joint(bool onoff) {
110  if (onoff)
111  _joint_type = JT_joint;
112  else
113  _joint_type = JT_none;
114 }
115 
116 /**
117  * Returns true if the node should be treated as a joint by the converter.
118  */
119 bool MaxNodeDesc::
120 is_joint() const {
121  return _joint_type == JT_joint || _joint_type == JT_pseudo_joint;
122 }
123 
124 /**
125  * Returns true if the node is the parent or ancestor of a joint.
126  */
127 bool MaxNodeDesc::
129  return _joint_type == JT_joint_parent;
130 }
131 
132 /**
133  * Returns true if the node is the parent or ancestor of a joint.
134  */
135 bool MaxNodeDesc::
136 is_node_joint() const {
137  return _joint_type == JT_node_joint;
138 }
139 
140 /**
141  * Recursively clears the egg pointers from this node and all children.
142  */
143 void MaxNodeDesc::
144 clear_egg() {
145  _egg_group = nullptr;
146  _egg_table = nullptr;
147  _anim = nullptr;
148 
149  Children::const_iterator ci;
150  for (ci = _children.begin(); ci != _children.end(); ++ci) {
151  MaxNodeDesc *child = (*ci);
152  child->clear_egg();
153  }
154 }
155 
156 /**
157  * Indicates that this node has at least one child that is a joint or a
158  * pseudo-joint.
159  */
160 void MaxNodeDesc::
161 mark_joint_parent() {
162  if (_joint_type == JT_none) {
163  _joint_type = JT_joint_parent;
164  if (_parent != nullptr) {
165  _parent->mark_joint_parent();
166  }
167  }
168 }
169 
170 /**
171  * Walks the hierarchy, looking for non-joint nodes that are both children and
172  * parents of a joint. These nodes are deemed to be pseudo joints, since the
173  * converter must treat them as joints.
174  */
175 void MaxNodeDesc::
176 check_pseudo_joints(bool joint_above) {
177  if (_joint_type == JT_joint_parent && joint_above) {
178  // This is one such node: it is the parent of a joint (JT_joint_parent is
179  // set), and it is the child of a joint (joint_above is set).
180  _joint_type = JT_pseudo_joint;
181  }
182 
183  if (_joint_type == JT_joint) {
184  // If this node is itself a joint, then joint_above is true for all child
185  // nodes.
186  joint_above = true;
187  }
188 
189  // Don't bother traversing further if _joint_type is none, since that means
190  // this node has no joint children.
191  if (_joint_type != JT_none) {
192  Children::const_iterator ci;
193  for (ci = _children.begin(); ci != _children.end(); ++ci) {
194  MaxNodeDesc *child = (*ci);
195  child->check_pseudo_joints(joint_above);
196  }
197  }
198 }
bool is_joint() const
Returns true if the node should be treated as a joint by the converter.
bool is_node_joint() const
Returns true if the node is the parent or ancestor of a joint.
void from_INode(INode *max_node)
Indicates an associated between the MaxNodeDesc and some Max Node instance.
Definition: maxNodeDesc.cxx:61
bool is_joint_parent() const
Returns true if the node is the parent or ancestor of a joint.
MaxNodeDesc(MaxNodeDesc *parent=nullptr, INode *max_node=nullptr)
Creates a MaxNodeDesc.
Definition: maxNodeDesc.cxx:23
Describes a single instance of a node in the Max scene graph, relating it to the corresponding egg st...
Definition: maxNodeDesc.h:22
INode * get_max_node() const
Returns the INode associated with this node.
bool has_max_node() const
Returns true if a Max INode has been associated with this node, false otherwise.
Definition: maxNodeDesc.cxx:93
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81