Panda3D

movingPartBase.cxx

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 }
 All Classes Functions Variables Enumerations