Panda3D
|
00001 // Filename: movingPartBase.cxx 00002 // Created by: drose (22Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "movingPartBase.h" 00016 #include "animControl.h" 00017 #include "animChannelBase.h" 00018 #include "bitArray.h" 00019 #include "config_chan.h" 00020 #include "dcast.h" 00021 #include "indent.h" 00022 00023 TypeHandle MovingPartBase::_type_handle; 00024 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: MovingPartBase::Constructor 00028 // Access: Public 00029 // Description: 00030 //////////////////////////////////////////////////////////////////// 00031 MovingPartBase:: 00032 MovingPartBase(PartGroup *parent, const string &name) : 00033 PartGroup(parent, name), 00034 _num_effective_channels(0), 00035 _effective_control(NULL) 00036 { 00037 } 00038 00039 //////////////////////////////////////////////////////////////////// 00040 // Function: MovingPartBase::Constructor 00041 // Access: Protected 00042 // Description: 00043 //////////////////////////////////////////////////////////////////// 00044 MovingPartBase:: 00045 MovingPartBase() : 00046 _num_effective_channels(0), 00047 _effective_control(NULL) 00048 { 00049 } 00050 00051 //////////////////////////////////////////////////////////////////// 00052 // Function: MovingPartBase::clear_forced_channel 00053 // Access: Published, Virtual 00054 // Description: Undoes the effect of a previous call to 00055 // apply_freeze() or apply_control(). Returns true if 00056 // the joint was modified, false otherwise. 00057 //////////////////////////////////////////////////////////////////// 00058 bool MovingPartBase:: 00059 clear_forced_channel() { 00060 if (_forced_channel != (AnimChannelBase *)NULL) { 00061 _forced_channel.clear(); 00062 return true; 00063 } 00064 return false; 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: MovingPartBase::get_forced_channel 00069 // Access: Published, Virtual 00070 // Description: Returns the AnimChannelBase that has been forced to 00071 // this joint by a previous call to apply_freeze() or 00072 // apply_control(), or NULL if no such channel has been 00073 // applied. 00074 //////////////////////////////////////////////////////////////////// 00075 AnimChannelBase *MovingPartBase:: 00076 get_forced_channel() const { 00077 return _forced_channel; 00078 } 00079 00080 //////////////////////////////////////////////////////////////////// 00081 // Function: MovingPartBase::write 00082 // Access: Published, Virtual 00083 // Description: Writes a brief description of the channel and all of 00084 // its descendants. 00085 //////////////////////////////////////////////////////////////////// 00086 void MovingPartBase:: 00087 write(ostream &out, int indent_level) const { 00088 indent(out, indent_level) << get_value_type() << " " << get_name(); 00089 if (_children.empty()) { 00090 out << "\n"; 00091 } else { 00092 out << " {\n"; 00093 write_descendants(out, indent_level + 2); 00094 indent(out, indent_level) << "}\n"; 00095 } 00096 } 00097 00098 //////////////////////////////////////////////////////////////////// 00099 // Function: MovingPartBase::write_with_value 00100 // Access: Published, Virtual 00101 // Description: Writes a brief description of the channel and all of 00102 // its descendants, along with their values. 00103 //////////////////////////////////////////////////////////////////// 00104 void MovingPartBase:: 00105 write_with_value(ostream &out, int indent_level) const { 00106 indent(out, indent_level) << get_value_type() << " " << get_name() << "\n"; 00107 indent(out, indent_level); 00108 output_value(out); 00109 00110 if (_children.empty()) { 00111 out << "\n"; 00112 } else { 00113 out << " {\n"; 00114 write_descendants_with_value(out, indent_level + 2); 00115 indent(out, indent_level) << "}\n"; 00116 } 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: MovingPartBase::do_update 00121 // Access: Public, Virtual 00122 // Description: Recursively update this particular part and all of 00123 // its descendents for the current frame. This is not 00124 // really public and is not intended to be called 00125 // directly; it is called from the top of the tree by 00126 // PartBundle::update(). 00127 // 00128 // The return value is true if any part has changed, 00129 // false otherwise. 00130 //////////////////////////////////////////////////////////////////// 00131 bool MovingPartBase:: 00132 do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *parent, 00133 bool parent_changed, bool anim_changed, 00134 Thread *current_thread) { 00135 bool any_changed = false; 00136 bool needs_update = anim_changed; 00137 00138 // See if any of the channel values have changed since last time. 00139 00140 if (!needs_update) { 00141 if (_forced_channel != (AnimChannelBase *)NULL) { 00142 needs_update = _forced_channel->has_changed(0, 0.0, 0, 0.0); 00143 00144 } else if (_effective_control != (AnimControl *)NULL) { 00145 const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata; 00146 needs_update = _effective_control->channel_has_changed(_effective_channel, cdata->_frame_blend_flag); 00147 00148 } else { 00149 const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata; 00150 PartBundle::ChannelBlend::const_iterator bci; 00151 for (bci = cdata->_blend.begin(); 00152 !needs_update && bci != cdata->_blend.end(); 00153 ++bci) { 00154 AnimControl *control = (*bci).first; 00155 00156 AnimChannelBase *channel = NULL; 00157 int channel_index = control->get_channel_index(); 00158 if (channel_index >= 0 && channel_index < (int)_channels.size()) { 00159 channel = _channels[channel_index]; 00160 } 00161 if (channel != (AnimChannelBase*)NULL) { 00162 needs_update = control->channel_has_changed(channel, cdata->_frame_blend_flag); 00163 } 00164 } 00165 } 00166 } 00167 00168 if (needs_update) { 00169 // Ok, get the latest value. 00170 get_blend_value(root); 00171 } 00172 00173 if (parent_changed || needs_update) { 00174 any_changed = update_internals(root, parent, needs_update, parent_changed, 00175 current_thread); 00176 } 00177 00178 // Now recurse. 00179 Children::iterator ci; 00180 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00181 if ((*ci)->do_update(root, root_cdata, this, 00182 parent_changed || needs_update, 00183 anim_changed, current_thread)) { 00184 any_changed = true; 00185 } 00186 } 00187 00188 return any_changed; 00189 } 00190 00191 00192 //////////////////////////////////////////////////////////////////// 00193 // Function: MovingPartBase::update_internals 00194 // Access: Public, Virtual 00195 // Description: This is called by do_update() whenever the part or 00196 // some ancestor has changed values. It is a hook for 00197 // derived classes to update whatever cache they may 00198 // have that depends on these. 00199 // 00200 // The return value is true if the part has changed as a 00201 // result of the update, or false otherwise. 00202 //////////////////////////////////////////////////////////////////// 00203 bool MovingPartBase:: 00204 update_internals(PartBundle *, PartGroup *, bool, bool, Thread *) { 00205 return true; 00206 } 00207 00208 //////////////////////////////////////////////////////////////////// 00209 // Function: MovingPartBase::pick_channel_index 00210 // Access: Protected 00211 // Description: Walks the part hierarchy, looking for a suitable 00212 // channel index number to use. Available index numbers 00213 // are the elements of the holes set, as well as next to 00214 // infinity. 00215 //////////////////////////////////////////////////////////////////// 00216 void MovingPartBase:: 00217 pick_channel_index(plist<int> &holes, int &next) const { 00218 // Verify each of the holes. 00219 00220 plist<int>::iterator ii, ii_next; 00221 ii = holes.begin(); 00222 while (ii != holes.end()) { 00223 ii_next = ii; 00224 ++ii_next; 00225 00226 int hole = (*ii); 00227 nassertv(hole >= 0 && hole < next); 00228 if (hole < (int)_channels.size() || 00229 _channels[hole] != (AnimChannelBase *)NULL) { 00230 // We can't accept this hole; we're using it! 00231 holes.erase(ii); 00232 } 00233 ii = ii_next; 00234 } 00235 00236 // Now do we have any more to restrict? 00237 if (next < (int)_channels.size()) { 00238 int i; 00239 for (i = next; i < (int)_channels.size(); i++) { 00240 if (_channels[i] == (AnimChannelBase*)NULL) { 00241 // Here's a hole we do have. 00242 holes.push_back(i); 00243 } 00244 } 00245 next = _channels.size(); 00246 } 00247 00248 PartGroup::pick_channel_index(holes, next); 00249 } 00250 00251 00252 00253 //////////////////////////////////////////////////////////////////// 00254 // Function: MovingPartBase::bind_hierarchy 00255 // Access: Protected, Virtual 00256 // Description: Binds the indicated anim hierarchy to the part 00257 // hierarchy, at the given channel index number. 00258 //////////////////////////////////////////////////////////////////// 00259 void MovingPartBase:: 00260 bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index, 00261 bool is_included, BitArray &bound_joints, 00262 const PartSubset &subset) { 00263 if (subset.matches_include(get_name())) { 00264 is_included = true; 00265 } else if (subset.matches_exclude(get_name())) { 00266 is_included = false; 00267 } 00268 00269 if (chan_cat.is_debug()) { 00270 if (anim == (AnimGroup *)NULL) { 00271 chan_cat.debug() 00272 << "binding " << *this << " to NULL, is_included = " 00273 << is_included << "\n"; 00274 } else { 00275 chan_cat.debug() 00276 << "binding " << *this << " to " << *anim << ", is_included = " 00277 << is_included << "\n"; 00278 } 00279 } 00280 while ((int)_channels.size() <= channel_index) { 00281 _channels.push_back((AnimChannelBase*)NULL); 00282 } 00283 00284 nassertv(_channels[channel_index] == (AnimChannelBase*)NULL); 00285 00286 if (is_included) { 00287 if (anim == (AnimGroup*)NULL) { 00288 // If we're binding to the NULL anim, it means actually to create 00289 // a default AnimChannel that just returns the part's initial 00290 // value. 00291 _channels[channel_index] = make_default_channel(); 00292 } else { 00293 _channels[channel_index] = DCAST(AnimChannelBase, anim); 00294 } 00295 00296 // Record that we have bound this joint in the bound_joints 00297 // BitArray. 00298 bound_joints.set_bit(joint_index); 00299 } else { 00300 // Record that we have *not* bound this particular joint. 00301 bound_joints.clear_bit(joint_index); 00302 } 00303 ++joint_index; 00304 00305 PartGroup::bind_hierarchy(anim, channel_index, joint_index, 00306 is_included, bound_joints, subset); 00307 } 00308 00309 //////////////////////////////////////////////////////////////////// 00310 // Function: MovingPartBase::find_bound_joints 00311 // Access: Protected, Virtual 00312 // Description: Similar to bind_hierarchy, but does not actually 00313 // perform any binding. All it does is compute the 00314 // BitArray bount_joints according to the specified 00315 // subset. This is useful in preparation for 00316 // asynchronous binding--in this case, we may need to 00317 // know bound_joints immediately, without having to wait 00318 // for the animation itself to load and bind. 00319 //////////////////////////////////////////////////////////////////// 00320 void MovingPartBase:: 00321 find_bound_joints(int &joint_index, bool is_included, BitArray &bound_joints, 00322 const PartSubset &subset) { 00323 if (subset.matches_include(get_name())) { 00324 is_included = true; 00325 } else if (subset.matches_exclude(get_name())) { 00326 is_included = false; 00327 } 00328 00329 bound_joints.set_bit_to(joint_index, is_included); 00330 ++joint_index; 00331 00332 PartGroup::find_bound_joints(joint_index, is_included, bound_joints, subset); 00333 } 00334 00335 //////////////////////////////////////////////////////////////////// 00336 // Function: MovingPartBase::determine_effective_channels 00337 // Access: Protected, Virtual 00338 // Description: Should be called whenever the ChannelBlend values 00339 // have changed, this recursively updates the 00340 // _effective_channel member in each part. 00341 //////////////////////////////////////////////////////////////////// 00342 void MovingPartBase:: 00343 determine_effective_channels(const CycleData *root_cdata) { 00344 _effective_control = NULL; 00345 _effective_channel = NULL; 00346 _num_effective_channels = 0; 00347 00348 AnimControl *effective_control = NULL; 00349 AnimChannelBase *effective_channel = NULL; 00350 int num_effective_channels = 0; 00351 00352 const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata; 00353 PartBundle::ChannelBlend::const_iterator cbi; 00354 for (cbi = cdata->_blend.begin(); 00355 cbi != cdata->_blend.end(); 00356 ++cbi) { 00357 AnimControl *control = (*cbi).first; 00358 int channel_index = control->get_channel_index(); 00359 if (channel_index >= 0 && channel_index < (int)_channels.size()) { 00360 if (_channels[channel_index] != (AnimChannelBase *)NULL) { 00361 effective_control = control; 00362 effective_channel = _channels[channel_index]; 00363 ++num_effective_channels; 00364 } 00365 } 00366 } 00367 00368 _num_effective_channels = num_effective_channels; 00369 if (num_effective_channels == 1) { 00370 _effective_control = effective_control; 00371 _effective_channel = effective_channel; 00372 } 00373 00374 PartGroup::determine_effective_channels(root_cdata); 00375 } 00376 00377 //////////////////////////////////////////////////////////////////// 00378 // Function: MovingPartBase::write_datagram 00379 // Access: Public, Virtual 00380 // Description: Writes the contents of this object to the datagram 00381 // for shipping out to a Bam file. 00382 //////////////////////////////////////////////////////////////////// 00383 void MovingPartBase:: 00384 write_datagram(BamWriter *manager, Datagram &dg) { 00385 PartGroup::write_datagram(manager, dg); 00386 00387 manager->write_pointer(dg, _forced_channel); 00388 } 00389 00390 //////////////////////////////////////////////////////////////////// 00391 // Function: MovingPartBase::complete_pointers 00392 // Access: Public, Virtual 00393 // Description: Receives an array of pointers, one for each time 00394 // manager->read_pointer() was called in fillin(). 00395 // Returns the number of pointers processed. 00396 // 00397 // This is the callback function that is made by the 00398 // BamReader at some later point, after all of the 00399 // required pointers have been filled in. It is 00400 // necessary because there might be forward references 00401 // in a bam file; when we call read_pointer() in 00402 // fillin(), the object may not have been read from the 00403 // file yet, so we do not have a pointer available at 00404 // that time. Thus, instead of returning a pointer, 00405 // read_pointer() simply reserves a later callback. 00406 // This function provides that callback. The calling 00407 // object is responsible for keeping track of the number 00408 // of times it called read_pointer() and extracting the 00409 // same number of pointers out of the supplied vector, 00410 // and storing them appropriately within the object. 00411 //////////////////////////////////////////////////////////////////// 00412 int MovingPartBase:: 00413 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00414 int pi = PartGroup::complete_pointers(p_list, manager); 00415 00416 if (manager->get_file_minor_ver() >= 20) { 00417 _forced_channel = DCAST(AnimChannelBase, p_list[pi++]); 00418 } 00419 00420 return pi; 00421 } 00422 00423 //////////////////////////////////////////////////////////////////// 00424 // Function: MovingPartBase::fillin 00425 // Access: Protected 00426 // Description: This internal function is called by make_from_bam to 00427 // read in all of the relevant data from the BamFile for 00428 // the new MovingPartBase. 00429 //////////////////////////////////////////////////////////////////// 00430 void MovingPartBase:: 00431 fillin(DatagramIterator &scan, BamReader *manager) { 00432 PartGroup::fillin(scan, manager); 00433 00434 if (manager->get_file_minor_ver() >= 20) { 00435 manager->read_pointer(scan); 00436 } 00437 }