Panda3D
Loading...
Searching...
No Matches
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
28using std::ostream;
29
30TypeHandle 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 */
36PartGroup::
37PartGroup(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 */
49PartGroup::
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 */
58is_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 */
67make_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 */
75copy_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 */
97get_num_children() const {
98 return _children.size();
99}
100
101
102/**
103 * Returns the nth child of the group.
104 */
106get_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 */
118get_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 */
136find_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.
153class PartGroupAlphabeticalOrder {
154public:
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 */
185apply_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 */
198apply_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 */
211apply_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 */
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 */
247get_forced_channel() const {
248 return nullptr;
249}
250
251
252/**
253 * Writes a brief description of the group and all of its descendants.
254 */
256write(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 */
268write_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 */
281get_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 */
294check_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 */
470do_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 */
490do_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 */
503determine_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 */
514void PartGroup::
515write_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 */
527void PartGroup::
528write_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 */
541void PartGroup::
542pick_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 */
554void PartGroup::
555bind_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 */
608void PartGroup::
609find_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 */
629write_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 */
642void PartGroup::
643fillin(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 */
666complete_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 */
681make_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 */
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.
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.
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.
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.
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...
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.
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.
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.
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.
virtual bool apply_freeze_scalar(PN_stdfloat value)
Freezes this particular joint so that it will always hold the specified transform.
bool apply_freeze(const TransformState *transform)
Freezes this particular joint so that it will always hold the specified transform.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
virtual bool apply_control(PandaNode *node)
Specifies a node to influence this particular joint so that it will always hold the node's transform.
virtual bool clear_forced_channel()
Undoes the effect of a previous call to apply_freeze() or apply_control().
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.
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...
static TypedWritable * make_PartGroup(const FactoryParams &params)
Factory method to generate a PartGroup object.
virtual AnimChannelBase * get_forced_channel() const
Returns the AnimChannelBase that has been forced to this joint by a previous call to apply_freeze() o...
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...
virtual void determine_effective_channels(const CycleData *root_cdata)
Should be called whenever the ChannelBlend values have changed, this recursively updates the _effecti...
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...
virtual TypeHandle get_value_type() const
Returns the TypeHandle associated with the ValueType we are concerned with.
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.
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.
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...
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.
bool matches_include(const std::string &joint_name) const
Returns true if the indicated name matches a name on the include list, false otherwise.
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.
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 our own Panda specialization on the default STL list.
Definition plist.h:35
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.