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