00001 // Filename: nodePathComponent.cxx 00002 // Created by: drose (25Feb02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "nodePathComponent.h" 00020 00021 00022 // We start the key counters off at 1, since 0 is reserved for an 00023 // empty NodePath (and also for an unassigned key). 00024 int NodePathComponent::_next_key = 1; 00025 TypeHandle NodePathComponent::_type_handle; 00026 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: NodePathComponent::CData::make_copy 00030 // Access: Public, Virtual 00031 // Description: 00032 //////////////////////////////////////////////////////////////////// 00033 CycleData *NodePathComponent::CData:: 00034 make_copy() const { 00035 return new CData(*this); 00036 } 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: NodePathComponent::get_key 00040 // Access: Public 00041 // Description: Returns an index number that is guaranteed to be 00042 // unique for this particular NodePathComponent, and not 00043 // to be reused for the lifetime of the application 00044 // (barring integer overflow). 00045 //////////////////////////////////////////////////////////////////// 00046 int NodePathComponent:: 00047 get_key() const { 00048 if (is_collapsed()) { 00049 return get_collapsed()->get_key(); 00050 } 00051 if (_key == 0) { 00052 // The first time someone asks for a particular component's key, 00053 // we make it up on the spot. This helps keep us from wasting 00054 // index numbers generating a unique number for *every* component 00055 // in the world (we only have 4.2 billion 32-bit integers, after 00056 // all) 00057 ((NodePathComponent *)this)->_key = _next_key++; 00058 } 00059 return _key; 00060 } 00061 00062 //////////////////////////////////////////////////////////////////// 00063 // Function: NodePathComponent::is_top_node 00064 // Access: Public 00065 // Description: Returns true if this component represents the top 00066 // node in the path. 00067 //////////////////////////////////////////////////////////////////// 00068 bool NodePathComponent:: 00069 is_top_node() const { 00070 if (is_collapsed()) { 00071 return get_collapsed()->is_top_node(); 00072 } 00073 CDReader cdata(_cycler); 00074 return (cdata->_next == (NodePathComponent *)NULL); 00075 } 00076 00077 //////////////////////////////////////////////////////////////////// 00078 // Function: NodePathComponent::get_length 00079 // Access: Public 00080 // Description: Returns the length of the path to this node. 00081 //////////////////////////////////////////////////////////////////// 00082 int NodePathComponent:: 00083 get_length() const { 00084 if (is_collapsed()) { 00085 return get_collapsed()->get_length(); 00086 } 00087 CDReader cdata(_cycler); 00088 return cdata->_length; 00089 } 00090 00091 //////////////////////////////////////////////////////////////////// 00092 // Function: NodePathComponent::get_next 00093 // Access: Public 00094 // Description: Returns the next component in the path. 00095 //////////////////////////////////////////////////////////////////// 00096 NodePathComponent *NodePathComponent:: 00097 get_next() const { 00098 if (is_collapsed()) { 00099 return get_collapsed()->get_next(); 00100 } 00101 00102 CDReader cdata(_cycler); 00103 NodePathComponent *next = cdata->_next; 00104 00105 // If the next component has been collapsed, transparently update 00106 // the pointer to get the actual node, and store the new pointer, 00107 // before we return. Collapsing can happen at any time to any 00108 // component in the path and we have to deal with it. 00109 if (next != (NodePathComponent *)NULL && next->is_collapsed()) { 00110 next = next->uncollapse(); 00111 00112 CDWriter cdata_w(((NodePathComponent *)this)->_cycler, cdata); 00113 cdata_w->_next = next; 00114 } 00115 00116 return next; 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: NodePathComponent::fix_length 00121 // Access: Public 00122 // Description: Checks that the length indicated by the component is 00123 // one more than the length of its predecessor. If this 00124 // is broken, fixes it and returns true indicating the 00125 // component has been changed; otherwise, returns false. 00126 //////////////////////////////////////////////////////////////////// 00127 bool NodePathComponent:: 00128 fix_length() { 00129 int length_should_be = 1; 00130 if (!is_top_node()) { 00131 length_should_be = get_next()->get_length() + 1; 00132 } 00133 if (get_length() == length_should_be) { 00134 return false; 00135 } 00136 00137 CDWriter cdata(_cycler); 00138 cdata->_length = length_should_be; 00139 return true; 00140 } 00141 00142 //////////////////////////////////////////////////////////////////// 00143 // Function: NodePathComponent::uncollapse 00144 // Access: Public 00145 // Description: Returns this component pointer if the component is 00146 // not collapsed; or if it has been collapsed, returns 00147 // the pointer it has been collapsed into. 00148 // 00149 // Collapsing can happen at any time to any component in 00150 // the path and we have to deal with it. It happens 00151 // when a node is removed further up the path that 00152 // results in two instances becoming the same thing. 00153 //////////////////////////////////////////////////////////////////// 00154 NodePathComponent *NodePathComponent:: 00155 uncollapse() { 00156 NodePathComponent *comp = this; 00157 00158 while (comp->is_collapsed()) { 00159 comp = comp->get_collapsed(); 00160 } 00161 00162 return comp; 00163 } 00164 00165 //////////////////////////////////////////////////////////////////// 00166 // Function: NodePathComponent::output 00167 // Access: Public 00168 // Description: The recursive implementation of NodePath::output(), 00169 // this writes the names of each node component in order 00170 // from beginning to end, by first walking to the end of 00171 // the linked list and then outputting from there. 00172 //////////////////////////////////////////////////////////////////// 00173 void NodePathComponent:: 00174 output(ostream &out) const { 00175 PandaNode *node = this->get_node(); 00176 NodePathComponent *next = this->get_next(); 00177 if (next != (NodePathComponent *)NULL) { 00178 // This is not the head of the list; keep going up. 00179 next->output(out); 00180 out << "/"; 00181 00182 PandaNode *parent_node = next->get_node(); 00183 if (parent_node->find_stashed(node) >= 0) { 00184 // The node is stashed. 00185 out << "@@"; 00186 00187 } else if (node->find_parent(parent_node) < 0) { 00188 // Oops, there's an error. This shouldn't happen. 00189 out << ".../"; 00190 } 00191 } 00192 00193 // Now output this component. 00194 if (node->has_name()) { 00195 out << node->get_name(); 00196 } else { 00197 out << "-" << node->get_type(); 00198 } 00199 // out << "[" << this->get_length() << "]"; 00200 } 00201 00202 //////////////////////////////////////////////////////////////////// 00203 // Function: NodePathComponent::set_next 00204 // Access: Private 00205 // Description: Sets the next pointer in the path. 00206 //////////////////////////////////////////////////////////////////// 00207 void NodePathComponent:: 00208 set_next(NodePathComponent *next) { 00209 if (is_collapsed()) { 00210 get_collapsed()->set_next(next); 00211 } else { 00212 nassertv(next != (NodePathComponent *)NULL); 00213 CDWriter cdata(_cycler); 00214 cdata->_next = next; 00215 } 00216 } 00217 00218 //////////////////////////////////////////////////////////////////// 00219 // Function: NodePathComponent::set_top_node 00220 // Access: Private 00221 // Description: Severs any connection to the next pointer in the 00222 // path and makes this component a top node. 00223 //////////////////////////////////////////////////////////////////// 00224 void NodePathComponent:: 00225 set_top_node() { 00226 if (is_collapsed()) { 00227 get_collapsed()->set_top_node(); 00228 } else { 00229 CDWriter cdata(_cycler); 00230 cdata->_next = (NodePathComponent *)NULL; 00231 } 00232 } 00233 00234 //////////////////////////////////////////////////////////////////// 00235 // Function: NodePathComponent::collapse_with 00236 // Access: Private 00237 // Description: Indicates that this component pointer is no longer 00238 // valid, and that the indicated component should be 00239 // used instead. This is done whenever two 00240 // NodePathComponents have been collapsed together due 00241 // to an instance being removed higher up in the graph. 00242 //////////////////////////////////////////////////////////////////// 00243 void NodePathComponent:: 00244 collapse_with(NodePathComponent *next) { 00245 nassertv(!is_collapsed()); 00246 nassertv(next != (NodePathComponent *)NULL); 00247 CDWriter cdata(_cycler); 00248 00249 // We indicate a component has been collapsed by setting its length 00250 // to zero. 00251 cdata->_next = next; 00252 cdata->_length = 0; 00253 00254 if (_key != 0 && next->_key == 0) { 00255 // If we had a key set and the other one didn't, it inherits our 00256 // key. Otherwise, we inherit the other's key. 00257 next->_key = _key; 00258 } 00259 }