Panda3D
partGroup.cxx
1 // Filename: partGroup.cxx
2 // Created by: drose (22Feb99)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "partGroup.h"
16 #include "animGroup.h"
17 #include "config_chan.h"
18 #include "partSubset.h"
19 
20 #include "indent.h"
21 #include "datagram.h"
22 #include "datagramIterator.h"
23 #include "bamReader.h"
24 #include "bamWriter.h"
25 #include "transformState.h"
26 
27 #include <algorithm>
28 
29 TypeHandle PartGroup::_type_handle;
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: PartGroup::Constructor
33 // Access: Published
34 // Description: Creates the PartGroup, and adds it to the indicated
35 // parent. The only way to delete it subsequently is to
36 // delete the entire hierarchy.
37 ////////////////////////////////////////////////////////////////////
38 PartGroup::
39 PartGroup(PartGroup *parent, const string &name) :
40  Namable(name),
41  _children(get_class_type())
42 {
43  nassertv(parent != NULL);
44 
45  parent->_children.push_back(this);
46 }
47 
48 ////////////////////////////////////////////////////////////////////
49 // Function: PartGroup::Destructor
50 // Access: Published
51 // Description:
52 ////////////////////////////////////////////////////////////////////
53 PartGroup::
54 ~PartGroup() {
55 }
56 
57 ////////////////////////////////////////////////////////////////////
58 // Function: PartGroup::is_character_joint
59 // Access: Published, Virtual
60 // Description: Returns true if this part is a CharacterJoint, false
61 // otherwise. This is a tiny optimization over
62 // is_of_type(CharacterType::get_class_type()).
63 ////////////////////////////////////////////////////////////////////
64 bool PartGroup::
66  return false;
67 }
68 
69 ////////////////////////////////////////////////////////////////////
70 // Function: PartGroup::make_copy
71 // Access: Published, Virtual
72 // Description: Allocates and returns a new copy of the node.
73 // Children are not copied, but see copy_subgraph().
74 ////////////////////////////////////////////////////////////////////
76 make_copy() const {
77  return new PartGroup(*this);
78 }
79 
80 ////////////////////////////////////////////////////////////////////
81 // Function: PartGroup::copy_subgraph
82 // Access: Published
83 // Description: Allocates and returns a new copy of this node and of
84 // all of its children.
85 ////////////////////////////////////////////////////////////////////
87 copy_subgraph() const {
88  PartGroup *root = make_copy();
89 
90  if (root->get_type() != get_type()) {
91  chan_cat.warning()
92  << "Don't know how to copy " << get_type() << "\n";
93  }
94 
95  Children::const_iterator ci;
96  for (ci = _children.begin(); ci != _children.end(); ++ci) {
97  PartGroup *child = (*ci)->copy_subgraph();
98  root->_children.push_back(child);
99  }
100 
101  return root;
102 }
103 
104 
105 ////////////////////////////////////////////////////////////////////
106 // Function: PartGroup::get_num_children
107 // Access: Published
108 // Description: Returns the number of child nodes of the group.
109 ////////////////////////////////////////////////////////////////////
110 int PartGroup::
112  return _children.size();
113 }
114 
115 
116 ////////////////////////////////////////////////////////////////////
117 // Function: PartGroup::get_child
118 // Access: Published
119 // Description: Returns the nth child of the group.
120 ////////////////////////////////////////////////////////////////////
122 get_child(int n) const {
123  nassertr(n >= 0 && n < (int)_children.size(), NULL);
124  return _children[n];
125 }
126 
127 ////////////////////////////////////////////////////////////////////
128 // Function: PartGroup::get_child_named
129 // Access: Published
130 // Description: Returns the first child found with the indicated
131 // name, or NULL if no such child exists. This method
132 // searches only the children of this particular
133 // PartGroup; it does not recursively search the entire
134 // graph. See also find_child().
135 ////////////////////////////////////////////////////////////////////
137 get_child_named(const string &name) const {
138  Children::const_iterator ci;
139  for (ci = _children.begin(); ci != _children.end(); ++ci) {
140  PartGroup *child = (*ci);
141  if (child->get_name() == name) {
142  return child;
143  }
144  }
145 
146  return (PartGroup *)NULL;
147 }
148 
149 ////////////////////////////////////////////////////////////////////
150 // Function: PartGroup::find_child
151 // Access: Published
152 // Description: Returns the first descendant found with the indicated
153 // name, or NULL if no such descendant exists. This
154 // method searches the entire graph beginning at this
155 // PartGroup; see also get_child_named().
156 ////////////////////////////////////////////////////////////////////
158 find_child(const string &name) const {
159  Children::const_iterator ci;
160  for (ci = _children.begin(); ci != _children.end(); ++ci) {
161  PartGroup *child = (*ci);
162  if (child->get_name() == name) {
163  return child;
164  }
165  PartGroup *result = child->find_child(name);
166  if (result != (PartGroup *)NULL) {
167  return result;
168  }
169  }
170 
171  return (PartGroup *)NULL;
172 }
173 
174 // An STL object to sort a list of children into alphabetical order.
176 public:
177  bool operator()(const PT(PartGroup) &a, const PT(PartGroup) &b) const {
178  return a->get_name() < b->get_name();
179  }
180 };
181 
182 ////////////////////////////////////////////////////////////////////
183 // Function: PartGroup::sort_descendants
184 // Access: Published
185 // Description: Sorts the children nodes at each level of the
186 // hierarchy into alphabetical order. This should be
187 // done after creating the hierarchy, to guarantee that
188 // the correct names will match up together when the
189 // AnimBundle is later bound to a PlayerRoot.
190 ////////////////////////////////////////////////////////////////////
191 void PartGroup::
193  stable_sort(_children.begin(), _children.end(), PartGroupAlphabeticalOrder());
194 
195  Children::iterator ci;
196  for (ci = _children.begin(); ci != _children.end(); ++ci) {
197  (*ci)->sort_descendants();
198  }
199 }
200 
201 ////////////////////////////////////////////////////////////////////
202 // Function: PartGroup::apply_freeze
203 // Access: Published
204 // Description: Freezes this particular joint so that it will always
205 // hold the specified transform. Returns true if this
206 // is a joint that can be so frozen, false otherwise.
207 //
208 // This is normally only called internally by
209 // PartBundle::freeze_joint(), but you may also call it
210 // directly.
211 ////////////////////////////////////////////////////////////////////
212 bool PartGroup::
213 apply_freeze(const TransformState *transform) {
214  return apply_freeze_matrix(transform->get_pos(), transform->get_hpr(), transform->get_scale()) || apply_freeze_scalar(transform->get_pos()[0]);
215 }
216 
217 ////////////////////////////////////////////////////////////////////
218 // Function: PartGroup::apply_freeze_matrix
219 // Access: Published, Virtual
220 // Description: Freezes this particular joint so that it will always
221 // hold the specified transform. Returns true if this
222 // is a joint that can be so frozen, false otherwise.
223 //
224 // This is normally only called internally by
225 // PartBundle::freeze_joint(), but you may also call it
226 // directly.
227 ////////////////////////////////////////////////////////////////////
228 bool PartGroup::
229 apply_freeze_matrix(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale) {
230  return false;
231 }
232 
233 ////////////////////////////////////////////////////////////////////
234 // Function: PartGroup::apply_freeze_scalar
235 // Access: Published, Virtual
236 // Description: Freezes this particular joint so that it will always
237 // hold the specified transform. Returns true if this
238 // is a joint that can be so frozen, false otherwise.
239 //
240 // This is normally only called internally by
241 // PartBundle::freeze_joint(), but you may also call it
242 // directly.
243 ////////////////////////////////////////////////////////////////////
244 bool PartGroup::
245 apply_freeze_scalar(PN_stdfloat value) {
246  return false;
247 }
248 
249 
250 ////////////////////////////////////////////////////////////////////
251 // Function: PartGroup::apply_control
252 // Access: Published, Virtual
253 // Description: Specifies a node to influence this particular joint
254 // so that it will always hold the node's transform.
255 // Returns true if this is a joint that can be so
256 // controlled, false otherwise.
257 //
258 // This is normally only called internally by
259 // PartBundle::control_joint(), but you may also call it
260 // directly.
261 ////////////////////////////////////////////////////////////////////
262 bool PartGroup::
264  return false;
265 }
266 
267 ////////////////////////////////////////////////////////////////////
268 // Function: PartGroup::clear_forced_channel
269 // Access: Published, Virtual
270 // Description: Undoes the effect of a previous call to
271 // apply_freeze() or apply_control(). Returns true if
272 // the joint was modified, false otherwise.
273 //
274 // This is normally only called internally by
275 // PartBundle::release_joint(), but you may also call it
276 // directly.
277 ////////////////////////////////////////////////////////////////////
278 bool PartGroup::
280  return false;
281 }
282 
283 ////////////////////////////////////////////////////////////////////
284 // Function: PartGroup::get_forced_channel
285 // Access: Published, Virtual
286 // Description: Returns the AnimChannelBase that has been forced to
287 // this joint by a previous call to apply_freeze() or
288 // apply_control(), or NULL if no such channel has been
289 // applied.
290 ////////////////////////////////////////////////////////////////////
293  return NULL;
294 }
295 
296 
297 ////////////////////////////////////////////////////////////////////
298 // Function: PartGroup::write
299 // Access: Published, Virtual
300 // Description: Writes a brief description of the group and all of
301 // its descendants.
302 ////////////////////////////////////////////////////////////////////
303 void PartGroup::
304 write(ostream &out, int indent_level) const {
305  indent(out, indent_level)
306  << get_type() << " " << get_name() << " {\n";
307  write_descendants(out, indent_level + 2);
308  indent(out, indent_level) << "}\n";
309 }
310 
311 ////////////////////////////////////////////////////////////////////
312 // Function: PartGroup::write_with_value
313 // Access: Published, Virtual
314 // Description: Writes a brief description of the group, showing its
315 // current value, and that of all of its descendants.
316 ////////////////////////////////////////////////////////////////////
317 void PartGroup::
318 write_with_value(ostream &out, int indent_level) const {
319  indent(out, indent_level)
320  << get_type() << " " << get_name() << " {\n";
321  write_descendants_with_value(out, indent_level + 2);
322  indent(out, indent_level) << "}\n";
323 }
324 
325 ////////////////////////////////////////////////////////////////////
326 // Function: PartGroup::get_value_type
327 // Access: Public, Virtual
328 // Description: Returns the TypeHandle associated with the ValueType
329 // we are concerned with. This is provided to allow a
330 // bit of run-time checking that joints and channels are
331 // matching properly in type.
332 ////////////////////////////////////////////////////////////////////
334 get_value_type() const {
335  return TypeHandle::none();
336 }
337 
338 ////////////////////////////////////////////////////////////////////
339 // Function: PartGroup::check_hierarchy
340 // Access: Public
341 // Description: Walks the part hierarchy in tandem with the indicated
342 // anim hierarchy, and returns true if the hierarchies
343 // match, false otherwise.
344 //
345 // If hierarchy_match_flags is 0, only an exact match is
346 // accepted; otherwise, it may contain a union of
347 // PartGroup::HierarchyMatchFlags values indicating
348 // conditions that will be tolerated (but warnings will
349 // still be issued).
350 ////////////////////////////////////////////////////////////////////
351 bool PartGroup::
352 check_hierarchy(const AnimGroup *anim, const PartGroup *,
353  int hierarchy_match_flags) const {
355  if (anim->get_value_type() != get_value_type()) {
356  if (chan_cat.is_error()) {
357  chan_cat.error()
358  << "Part " << get_name() << " expects type " << get_value_type()
359  << " while matching anim node has type " << anim->get_value_type()
360  << ".\n";
361  }
362  return false;
363  }
364 
365  if (chan_cat.is_info()) {
366  // If we're issuing error messages, check ahead of time if the set
367  // of children agrees. If it does not, we'll write a one-line
368  // warning, and then list the set of children that differ.
369 
370  bool match = true;
371  if (anim->get_num_children() != get_num_children()) {
372  // If the only difference is "morph", ignore it. We treat
373  // "morph" as a special case, because it's common for the model
374  // and animation files to differ meaninglessly here. Any
375  // differences here remain unreported.
376  if (anim->get_num_children() == get_num_children() + 1 &&
377  anim->get_child_named("morph") != NULL &&
378  get_child_named("morph") == NULL) {
379  // Anim has "morph" and model does not, but there are no other
380  // differences.
381 
382  } else if (get_num_children() == anim->get_num_children() + 1 &&
383  get_child_named("morph") != NULL &&
384  anim->get_child_named("morph") == NULL) {
385  // Model has "morph" and anim does not, but there are no other
386  // differences.
387 
388  } else {
389  chan_cat.info()
390  << "Part " << get_name() << " has " << get_num_children()
391  << " children, while matching anim node has "
392  << anim->get_num_children() << ":\n";
393  match = false;
394  }
395 
396  } else {
397  for (int i = 0; match && i < get_num_children(); i++) {
398  PartGroup *pc = get_child(i);
399  AnimGroup *ac = anim->get_child(i);
400 
401  match = (pc->get_name() == ac->get_name());
402  }
403  if (!match) {
404  chan_cat.info()
405  << "Part " << get_name() << " has a different set of children "
406  << " than matching anim node:\n";
407  }
408  }
409  if (!match) {
410  int i = 0, j = 0;
411  while (i < get_num_children() &&
412  j < anim->get_num_children()) {
413  PartGroup *pc = get_child(i);
414  AnimGroup *ac = anim->get_child(j);
415 
416  if (pc->get_name() < ac->get_name()) {
417  chan_cat.info()
418  << " part has " << pc->get_name()
419  << ", not in anim.\n";
420  i++;
421  } else if (ac->get_name() < pc->get_name()) {
422  chan_cat.info()
423  << " anim has " << ac->get_name()
424  << ", not in part.\n";
425  j++;
426  } else {
427  // chan_cat.info() << " part and anim both have " << ac->get_name() << "\n";
428  i++;
429  j++;
430  }
431  }
432 
433  while (i < get_num_children()) {
434  PartGroup *pc = get_child(i);
435  chan_cat.info()
436  << " part has " << pc->get_name()
437  << ", not in anim.\n";
438  i++;
439  }
440 
441  while (j < anim->get_num_children()) {
442  AnimGroup *ac = anim->get_child(j);
443  chan_cat.info()
444  << " anim has " << ac->get_name()
445  << ", not in part.\n";
446  j++;
447  }
448  }
449  }
450 
451  // Now walk the list of children and check the matching
452  // sub-hierarchies only.
453 
454  int i = 0, j = 0;
455  while (i < get_num_children() &&
456  j < anim->get_num_children()) {
457  PartGroup *pc = get_child(i);
458  AnimGroup *ac = anim->get_child(j);
459 
460  if (pc->get_name() < ac->get_name()) {
461  if (pc->get_name() == "morph") {
462  // Model has "morph", not in anim. Ignore.
463  } else {
464  if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
465  return false;
466  }
467  }
468  i++;
469  } else if (ac->get_name() < pc->get_name()) {
470  if (ac->get_name() == "morph") {
471  // Anim has "morph", not in model. Ignore.
472  } else {
473  if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
474  return false;
475  }
476  }
477  j++;
478  } else {
479  if (!pc->check_hierarchy(ac, this, hierarchy_match_flags)) {
480  return false;
481  }
482  i++;
483  j++;
484  }
485  }
486 
487  while (i < get_num_children()) {
488  // There's at least one extra part.
489  PartGroup *pc = get_child(i);
490 
491  if (pc->get_name() == "morph") {
492  // Model has "morph", not in anim. Ignore.
493  } else {
494  if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
495  return false;
496  }
497  }
498  i++;
499  }
500 
501  while (j < anim->get_num_children()) {
502  // There's at least one extra anim channel.
503  AnimGroup *ac = anim->get_child(j);
504 
505  if (ac->get_name() == "morph") {
506  // Anim has "morph", not in model. Ignore.
507  } else {
508  if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
509  return false;
510  }
511  }
512  j++;
513  }
514 
515  return true;
516 }
517 
518 
519 ////////////////////////////////////////////////////////////////////
520 // Function: PartGroup::do_update
521 // Access: Public, Virtual
522 // Description: Recursively update this particular part and all of
523 // its descendents for the current frame. This is not
524 // really public and is not intended to be called
525 // directly; it is called from the top of the tree by
526 // PartBundle::update().
527 //
528 // The return value is true if any part has changed,
529 // false otherwise.
530 ////////////////////////////////////////////////////////////////////
531 bool PartGroup::
532 do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *,
533  bool parent_changed, bool anim_changed, Thread *current_thread) {
534  bool any_changed = false;
535 
536  Children::iterator ci;
537  for (ci = _children.begin(); ci != _children.end(); ++ci) {
538  if ((*ci)->do_update(root, root_cdata, this, parent_changed,
539  anim_changed, current_thread)) {
540  any_changed = true;
541  }
542  }
543 
544  return any_changed;
545 }
546 
547 ////////////////////////////////////////////////////////////////////
548 // Function: PartGroup::do_xform
549 // Access: Public, Virtual
550 // Description: Called by PartBundle::xform(), this indicates the
551 // indicated transform is being applied to the root
552 // joint.
553 ////////////////////////////////////////////////////////////////////
554 void PartGroup::
555 do_xform(const LMatrix4 &mat, const LMatrix4 &inv_mat) {
556  Children::const_iterator ci;
557 
558  for (ci = _children.begin(); ci != _children.end(); ++ci) {
559  (*ci)->do_xform(mat, inv_mat);
560  }
561 }
562 
563 ////////////////////////////////////////////////////////////////////
564 // Function: PartGroup::determine_effective_channels
565 // Access: Public, Virtual
566 // Description: Should be called whenever the ChannelBlend values
567 // have changed, this recursively updates the
568 // _effective_channel member in each part.
569 ////////////////////////////////////////////////////////////////////
570 void PartGroup::
572  Children::iterator ci;
573  for (ci = _children.begin(); ci != _children.end(); ++ci) {
574  (*ci)->determine_effective_channels(root_cdata);
575  }
576 }
577 
578 
579 ////////////////////////////////////////////////////////////////////
580 // Function: PartGroup::write_descendants
581 // Access: Protected
582 // Description: Writes a brief description of all of the group's
583 // descendants.
584 ////////////////////////////////////////////////////////////////////
585 void PartGroup::
586 write_descendants(ostream &out, int indent_level) const {
587  Children::const_iterator ci;
588 
589  for (ci = _children.begin(); ci != _children.end(); ++ci) {
590  (*ci)->write(out, indent_level);
591  }
592 }
593 
594 ////////////////////////////////////////////////////////////////////
595 // Function: PartGroup::write_descendants_with_value
596 // Access: Protected
597 // Description: Writes a brief description of all of the group's
598 // descendants and their values.
599 ////////////////////////////////////////////////////////////////////
600 void PartGroup::
601 write_descendants_with_value(ostream &out, int indent_level) const {
602  Children::const_iterator ci;
603 
604  for (ci = _children.begin(); ci != _children.end(); ++ci) {
605  (*ci)->write_with_value(out, indent_level);
606  }
607 }
608 
609 ////////////////////////////////////////////////////////////////////
610 // Function: PartGroup::pick_channel_index
611 // Access: Protected, Virtual
612 // Description: Walks the part hierarchy, looking for a suitable
613 // channel index number to use. Available index numbers
614 // are the elements of the holes set, as well as next to
615 // infinity.
616 ////////////////////////////////////////////////////////////////////
617 void PartGroup::
618 pick_channel_index(plist<int> &holes, int &next) const {
619  Children::const_iterator ci;
620  for (ci = _children.begin(); ci != _children.end(); ++ci) {
621  (*ci)->pick_channel_index(holes, next);
622  }
623 }
624 
625 
626 ////////////////////////////////////////////////////////////////////
627 // Function: PartGroup::bind_hierarchy
628 // Access: Protected, Virtual
629 // Description: Binds the indicated anim hierarchy to the part
630 // hierarchy, at the given channel index number.
631 ////////////////////////////////////////////////////////////////////
632 void PartGroup::
633 bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index,
634  bool is_included, BitArray &bound_joints,
635  const PartSubset &subset) {
637  if (subset.matches_include(get_name())) {
638  is_included = true;
639  } else if (subset.matches_exclude(get_name())) {
640  is_included = false;
641  }
642 
643  int i = 0, j = 0;
644  int part_num_children = get_num_children();
645  int anim_num_children = (anim == NULL) ? 0 : anim->get_num_children();
646 
647  while (i < part_num_children && j < anim_num_children) {
648  PartGroup *pc = get_child(i);
649  AnimGroup *ac = anim->get_child(j);
650 
651  if (pc->get_name() < ac->get_name()) {
652  // Here's a part, not in the anim. Bind it to the special NULL
653  // anim.
654  pc->bind_hierarchy(NULL, channel_index, joint_index, is_included,
655  bound_joints, subset);
656  i++;
657 
658  } else if (ac->get_name() < pc->get_name()) {
659  // Here's an anim, not in the part. Ignore it.
660  j++;
661 
662  } else {
663  // Here's a matched part and anim pair.
664  pc->bind_hierarchy(ac, channel_index, joint_index, is_included,
665  bound_joints, subset);
666  i++;
667  j++;
668  }
669  }
670 
671  // Now pick up any more parts, not in the anim.
672  while (i < part_num_children) {
673  PartGroup *pc = get_child(i);
674  pc->bind_hierarchy(NULL, channel_index, joint_index, is_included,
675  bound_joints, subset);
676  i++;
677  }
678 }
679 
680 ////////////////////////////////////////////////////////////////////
681 // Function: PartGroup::find_bound_joints
682 // Access: Protected, Virtual
683 // Description: Similar to bind_hierarchy, but does not actually
684 // perform any binding. All it does is compute the
685 // BitArray bount_joints according to the specified
686 // subset. This is useful in preparation for
687 // asynchronous binding--in this case, we may need to
688 // know bound_joints immediately, without having to wait
689 // for the animation itself to load and bind.
690 ////////////////////////////////////////////////////////////////////
691 void PartGroup::
692 find_bound_joints(int &joint_index, bool is_included, BitArray &bound_joints,
693  const PartSubset &subset) {
694  if (subset.matches_include(get_name())) {
695  is_included = true;
696  } else if (subset.matches_exclude(get_name())) {
697  is_included = false;
698  }
699 
700  int part_num_children = get_num_children();
701  for (int i = 0; i < part_num_children; ++i) {
702  PartGroup *pc = get_child(i);
703  pc->find_bound_joints(joint_index, is_included, bound_joints, subset);
704  }
705 }
706 
707 ////////////////////////////////////////////////////////////////////
708 // Function: PartGroup::write_datagram
709 // Access: Public
710 // Description: Function to write the important information in
711 // the particular object to a Datagram
712 ////////////////////////////////////////////////////////////////////
713 void PartGroup::
715  me.add_string(get_name());
716  me.add_uint16(_children.size());
717  for (size_t i = 0; i < _children.size(); i++) {
718  manager->write_pointer(me, _children[i]);
719  }
720 }
721 
722 ////////////////////////////////////////////////////////////////////
723 // Function: PartGroup::fillin
724 // Access: Protected
725 // Description: Function that reads out of the datagram (or asks
726 // manager to read) all of the data that is needed to
727 // re-create this object and stores it in the appropiate
728 // place
729 ////////////////////////////////////////////////////////////////////
730 void PartGroup::
731 fillin(DatagramIterator &scan, BamReader *manager) {
732  set_name(scan.get_string());
733 
734  if (manager->get_file_minor_ver() == 11) {
735  // Skip over the old freeze-joint information, no longer stored here
736  scan.get_bool();
737  LMatrix4 mat;
738  mat.read_datagram(scan);
739  }
740 
741  int num_children = scan.get_uint16();
742  _children.reserve(num_children);
743  for (int i = 0; i < num_children; i++) {
744  manager->read_pointer(scan);
745  _children.push_back(NULL);
746  }
747 }
748 
749 ////////////////////////////////////////////////////////////////////
750 // Function: PartGroup::complete_pointers
751 // Access: Public
752 // Description: Takes in a vector of pointers to TypedWritable
753 // objects that correspond to all the requests for
754 // pointers that this object made to BamReader.
755 ////////////////////////////////////////////////////////////////////
756 int PartGroup::
758  int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
759 
760  Children::iterator ci;
761  for (ci = _children.begin(); ci != _children.end(); ++ci) {
762  (*ci) = DCAST(PartGroup, p_list[pi++]);
763  }
764 
765  return pi;
766 }
767 
768 ////////////////////////////////////////////////////////////////////
769 // Function: PartGroup::make_PartGroup
770 // Access: Protected
771 // Description: Factory method to generate a PartGroup object
772 ////////////////////////////////////////////////////////////////////
775  PartGroup *me = new PartGroup;
776  DatagramIterator scan;
777  BamReader *manager;
778 
779  parse_params(params, scan, manager);
780  me->fillin(scan, manager);
781  return me;
782 }
783 
784 ////////////////////////////////////////////////////////////////////
785 // Function: PartGroup::register_with_factory
786 // Access: Public, Static
787 // Description: Factory method to generate a PartGroup object
788 ////////////////////////////////////////////////////////////////////
789 void PartGroup::
792 }
793 
bool matches_exclude(const string &joint_name) const
Returns true if the indicated name matches a name on the exclude list, false otherwise.
Definition: partSubset.cxx:165
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
bool matches_include(const string &joint_name) const
Returns true if the indicated name matches a name on the include list, false otherwise.
Definition: partSubset.cxx:146
virtual AnimChannelBase * get_forced_channel() const
Returns the AnimChannelBase that has been forced to this joint by a previous call to apply_freeze() o...
Definition: partGroup.cxx:292
bool get_bool()
Extracts a boolean value.
void add_string(const string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:351
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
Definition: typeHandle.I:274
void sort_descendants()
Sorts the children nodes at each level of the hierarchy into alphabetical order.
Definition: partGroup.cxx:192
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
int get_num_children() const
Returns the number of child nodes of the group.
Definition: animGroup.cxx:104
virtual void write_with_value(ostream &out, int indent_level) const
Writes a brief description of the group, showing its current value, and that of all of its descendant...
Definition: partGroup.cxx:318
virtual bool do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *parent, bool parent_changed, bool anim_changed, Thread *current_thread)
Recursively update this particular part and all of its descendents for the current frame...
Definition: partGroup.cxx:532
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
int get_num_children() const
Returns the number of child nodes of the group.
Definition: partGroup.cxx:111
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
virtual void do_xform(const LMatrix4 &mat, const LMatrix4 &inv_mat)
Called by PartBundle::xform(), this indicates the indicated transform is being applied to the root jo...
Definition: partGroup.cxx:555
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
Definition: thread.I:263
virtual void write(ostream &out, int indent_level) const
Writes a brief description of the group and all of its descendants.
Definition: partGroup.cxx:304
string get_string()
Extracts a variable-length string.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:105
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
PartGroup * find_child(const string &name) const
Returns the first descendant found with the indicated name, or NULL if no such descendant exists...
Definition: partGroup.cxx:158
A dynamic array with an unlimited number of bits.
Definition: bitArray.h:42
Parent class for all animation channels.
PartGroup * get_child(int n) const
Returns the nth child of the group.
Definition: partGroup.cxx:122
A base class for all things which can have a name.
Definition: namable.h:29
virtual TypeHandle get_value_type() const
Returns the TypeHandle associated with the ValueType we are concerned with.
Definition: animGroup.cxx:204
This is the base class for AnimChannel and AnimBundle.
Definition: animGroup.h:36
AnimGroup * get_child_named(const string &name) const
Returns the first child found with the indicated name, or NULL if no such child exists.
Definition: animGroup.cxx:130
AnimGroup * get_child(int n) const
Returns the nth child of the group.
Definition: animGroup.cxx:115
virtual void determine_effective_channels(const CycleData *root_cdata)
Should be called whenever the ChannelBlend values have changed, this recursively updates the _effecti...
Definition: partGroup.cxx:571
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
virtual bool apply_freeze_matrix(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale)
Freezes this particular joint so that it will always hold the specified transform.
Definition: partGroup.cxx:229
bool apply_freeze(const TransformState *transform)
Freezes this particular joint so that it will always hold the specified transform.
Definition: partGroup.cxx:213
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
virtual TypeHandle get_value_type() const
Returns the TypeHandle associated with the ValueType we are concerned with.
Definition: partGroup.cxx:334
virtual bool apply_control(PandaNode *node)
Specifies a node to influence this particular joint so that it will always hold the node&#39;s transform...
Definition: partGroup.cxx:263
void read_datagram(DatagramIterator &source)
Reads the matrix from the Datagram using get_stdfloat().
Definition: lmatrix.cxx:1162
virtual bool is_character_joint() const
Returns true if this part is a CharacterJoint, false otherwise.
Definition: partGroup.cxx:65
This class is used to define a subset of part names to apply to the PartBundle::bind_anim() operation...
Definition: partSubset.h:28
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:181
PartGroup * get_child_named(const string &name) const
Returns the first child found with the indicated name, or NULL if no such child exists.
Definition: partGroup.cxx:137
static void register_with_read_factory()
Factory method to generate a PartGroup object.
Definition: partGroup.cxx:790
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
A thread; that is, a lightweight process.
Definition: thread.h:51
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:49
virtual bool clear_forced_channel()
Undoes the effect of a previous call to apply_freeze() or apply_control().
Definition: partGroup.cxx:279
bool check_hierarchy(const AnimGroup *anim, const PartGroup *parent, int hierarchy_match_flags=0) const
Walks the part hierarchy in tandem with the indicated anim hierarchy, and returns true if the hierarc...
Definition: partGroup.cxx:352
PartGroup * copy_subgraph() const
Allocates and returns a new copy of this node and of all of its children.
Definition: partGroup.cxx:87
A class to retrieve the individual data elements previously stored in a Datagram. ...
static TypedWritable * make_PartGroup(const FactoryParams &params)
Factory method to generate a PartGroup object.
Definition: partGroup.cxx:774
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
virtual PartGroup * make_copy() const
Allocates and returns a new copy of the node.
Definition: partGroup.cxx:76
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
Definition: partGroup.cxx:714
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Takes in a vector of pointers to TypedWritable objects that correspond to all the requests for pointe...
Definition: partGroup.cxx:757
virtual bool apply_freeze_scalar(PN_stdfloat value)
Freezes this particular joint so that it will always hold the specified transform.
Definition: partGroup.cxx:245
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:279
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:658
This is the base class for PartRoot and MovingPart.
Definition: partGroup.h:45