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  */
58 is_character_joint() const {
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  */
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  */
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  */
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  */
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  */
225 apply_control(PandaNode *node) {
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  */
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  */
247 get_forced_channel() const {
248  return nullptr;
249 }
250 
251 
252 /**
253  * Writes a brief description of the group and all of its descendants.
254  */
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  */
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  */
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  */
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  */
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  */
503 determine_effective_channels(const CycleData *root_cdata) {
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  */
629 write_datagram(BamWriter *manager, Datagram &me) {
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  */
666 complete_pointers(TypedWritable **p_list, BamReader *manager) {
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  */
681 make_PartGroup(const FactoryParams &params) {
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  */
697 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Parent class for all animation channels.
This is the base class for AnimChannel and AnimBundle.
Definition: animGroup.h:33
get_child
Returns the nth child of the group.
Definition: animGroup.h:45
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
get_num_children
Returns the number of child nodes of the group.
Definition: animGroup.h:45
virtual TypeHandle get_value_type() const
Returns the TypeHandle associated with the ValueType we are concerned with.
Definition: animGroup.cxx:176
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
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
A dynamic array with an unlimited number of bits.
Definition: bitArray.h:40
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
bool get_bool()
Extracts a boolean value.
std::string get_string()
Extracts a variable-length string.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:219
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
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
A base class for all things which can have a name.
Definition: namable.h:26
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:46
This is the base class for PartRoot and MovingPart.
Definition: partGroup.h:43
get_num_children
Returns the number of child nodes of the group.
Definition: partGroup.h:72
void sort_descendants()
Sorts the children nodes at each level of the hierarchy into alphabetical order.
Definition: partGroup.cxx:167
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
PartGroup * copy_subgraph() const
Allocates and returns a new copy of this node and of all of its children.
Definition: partGroup.cxx:75
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
virtual PartGroup * make_copy() const
Allocates and returns a new copy of the node.
Definition: partGroup.cxx:67
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
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
bool apply_freeze(const TransformState *transform)
Freezes this particular joint so that it will always hold the specified transform.
Definition: partGroup.cxx:185
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
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
virtual bool clear_forced_channel()
Undoes the effect of a previous call to apply_freeze() or apply_control().
Definition: partGroup.cxx:237
get_child
Returns the nth child of the group.
Definition: partGroup.h:72
static void register_with_read_factory()
Factory method to generate a PartGroup object.
Definition: partGroup.cxx:695
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
static TypedWritable * make_PartGroup(const FactoryParams &params)
Factory method to generate a PartGroup object.
Definition: partGroup.cxx:681
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
virtual bool is_character_joint() const
Returns true if this part is a CharacterJoint, false otherwise.
Definition: partGroup.cxx:58
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
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 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
virtual TypeHandle get_value_type() const
Returns the TypeHandle associated with the ValueType we are concerned with.
Definition: partGroup.cxx:281
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
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
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
This class is used to define a subset of part names to apply to the PartBundle::bind_anim() operation...
Definition: partSubset.h:25
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
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 thread; that is, a lightweight process.
Definition: thread.h:46
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
Indicates a coordinate-system transform on vertices.
get_scale
Returns the scale component of the transform.
get_hpr
Returns the rotation component of the transform as a trio of Euler angles.
get_pos
Returns the pos component of the transform.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
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().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.