Panda3D
Loading...
Searching...
No Matches
auto_bind.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 auto_bind.cxx
10 * @author drose
11 * @date 1999-02-23
12 */
13
14#include "auto_bind.h"
15#include "animBundleNode.h"
16#include "partBundleNode.h"
17#include "config_chan.h"
18#include "string_utils.h"
19#include "partGroup.h"
20
21using std::string;
22
25
28
29
30/**
31 * A support function for auto_bind(), below. Given a set of AnimBundles and
32 * a set of PartBundles that all share the same name, perform whatever
33 * bindings make sense.
34 */
35static void
36bind_anims(const PartBundles &parts, const AnimBundles &anims,
37 AnimControlCollection &controls,
38 int hierarchy_match_flags) {
39 PartBundles::const_iterator pbi;
40
41 for (pbi = parts.begin(); pbi != parts.end(); ++pbi) {
42 PartBundle *part = (*pbi);
43 AnimBundles::const_iterator abi;
44 for (abi = anims.begin(); abi != anims.end(); ++abi) {
45 AnimBundle *anim = (*abi);
46 if (chan_cat.is_info()) {
47 chan_cat.info()
48 << "Attempting to bind " << *part << " to " << *anim << "\n";
49 }
50
51 PT(AnimControl) control =
52 part->bind_anim(anim, hierarchy_match_flags);
53 string name = (*abi)->get_name();
54 if (name.empty()) {
55 name = anim->get_name();
56 }
57 if (control != nullptr) {
58 if (controls.find_anim(name) != nullptr) {
59 // That name's already used; synthesize another one.
60 int index = 0;
61 string new_name;
62 do {
63 index++;
64 new_name = name + '.' + format_string(index);
65 } while (controls.find_anim(new_name) != nullptr);
66 name = new_name;
67 }
68
69 controls.store_anim(control, name);
70 }
71
72 if (chan_cat.is_info()) {
73 if (control == nullptr) {
74 chan_cat.info()
75 << "Bind failed.\n";
76 } else {
77 chan_cat.info()
78 << "Bind succeeded, index "
79 << control->get_channel_index() << "; accessible as "
80 << name << "\n";
81 }
82 }
83 }
84 }
85}
86
87/**
88 * A support function for auto_bind(), below. Walks through the hierarchy and
89 * finds all of the PartBundles and AnimBundles.
90 */
91static void
92r_find_bundles(PandaNode *node, Anims &anims, Parts &parts) {
93 if (node->is_of_type(AnimBundleNode::get_class_type())) {
94 AnimBundleNode *bn = DCAST(AnimBundleNode, node);
95 AnimBundle *bundle = bn->get_bundle();
96 anims[bundle->get_name()].insert(bundle);
97
98 } else if (node->is_of_type(PartBundleNode::get_class_type())) {
99 PartBundleNode *bn = DCAST(PartBundleNode, node);
100 int num_bundles = bn->get_num_bundles();
101 for (int i = 0; i < num_bundles; ++i) {
102 PartBundle *bundle = bn->get_bundle(i);
103 parts[bundle->get_name()].insert(bundle);
104 }
105 }
106
108 int num_children = cr.get_num_children();
109 for (int i = 0; i < num_children; i++) {
110 r_find_bundles(cr.get_child(i), anims, parts);
111 }
112}
113
114
115/**
116 * Walks the scene graph or subgraph beginning at the indicated node, and
117 * attempts to bind any AnimBundles found to their matching PartBundles, when
118 * possible.
119 *
120 * The list of all resulting AnimControls created is filled into controls.
121 */
122void
124 int hierarchy_match_flags) {
125 // First, locate all the bundles in the subgraph.
126 Anims anims;
127 AnimBundles extra_anims;
128 Parts parts;
129 PartBundles extra_parts;
130 r_find_bundles(root_node, anims, parts);
131
132 if (chan_cat.is_debug()) {
133 int anim_count = 0;
134 Anims::const_iterator ai;
135 for (ai = anims.begin(); ai != anims.end(); ++ai) {
136 anim_count += (int)(*ai).second.size();
137 }
138 chan_cat.debug()
139 << "Found " << anim_count << " anims:\n";
140 for (ai = anims.begin(); ai != anims.end(); ++ai) {
141 chan_cat.debug(false)
142 << " " << (*ai).first;
143 if ((*ai).second.size() != 1) {
144 chan_cat.debug(false)
145 << "*" << ((*ai).second.size());
146 }
147 }
148 chan_cat.debug(false)
149 << "\n";
150
151 int part_count = 0;
152 Parts::const_iterator pi;
153 for (pi = parts.begin(); pi != parts.end(); ++pi) {
154 part_count += (int)(*pi).second.size();
155 }
156 chan_cat.debug()
157 << "Found " << part_count << " parts:\n";
158 for (pi = parts.begin(); pi != parts.end(); ++pi) {
159 chan_cat.debug(false)
160 << " " << (*pi).first;
161 if ((*pi).second.size() != 1) {
162 chan_cat.debug(false)
163 << "*" << ((*pi).second.size());
164 }
165 }
166 chan_cat.debug(false)
167 << "\n";
168 }
169
170 // Now, match up the bundles by name.
171
172 Anims::const_iterator ai = anims.begin();
173 Parts::const_iterator pi = parts.begin();
174
175 while (ai != anims.end() && pi != parts.end()) {
176 if ((*ai).first < (*pi).first) {
177 // Here's an anim with no matching parts.
178 if (hierarchy_match_flags & PartGroup::HMF_ok_wrong_root_name) {
179 AnimBundles::const_iterator abi;
180 for (abi = (*ai).second.begin(); abi != (*ai).second.end(); ++abi) {
181 extra_anims.insert(*abi);
182 }
183 }
184 ++ai;
185
186 } else if ((*pi).first < (*ai).first) {
187 // And here's a part with no matching anims.
188 if (hierarchy_match_flags & PartGroup::HMF_ok_wrong_root_name) {
189 PartBundles::const_iterator pbi;
190 for (pbi = (*pi).second.begin(); pbi != (*pi).second.end(); ++pbi) {
191 extra_parts.insert(*pbi);
192 }
193 }
194 ++pi;
195
196 } else {
197 // But here we have (at least one) match!
198 bind_anims((*pi).second, (*ai).second, controls,
199 hierarchy_match_flags);
200 ++pi;
201
202 // We don't increment the anim counter yet. That way, the same anim may
203 // bind to multiple parts, if they all share the same name.
204 }
205 }
206
207 if (hierarchy_match_flags & PartGroup::HMF_ok_wrong_root_name) {
208 // Continue searching through the remaining anims and parts.
209
210 while (ai != anims.end()) {
211 // Here's an anim with no matching parts.
212 if (hierarchy_match_flags & PartGroup::HMF_ok_wrong_root_name) {
213 AnimBundles::const_iterator abi;
214 for (abi = (*ai).second.begin(); abi != (*ai).second.end(); ++abi) {
215 extra_anims.insert(*abi);
216 }
217 }
218 ++ai;
219 }
220
221 while (pi != parts.end()) {
222 // And here's a part with no matching anims.
223 if (hierarchy_match_flags & PartGroup::HMF_ok_wrong_root_name) {
224 PartBundles::const_iterator pbi;
225 for (pbi = (*pi).second.begin(); pbi != (*pi).second.end(); ++pbi) {
226 extra_parts.insert(*pbi);
227 }
228 }
229 ++pi;
230 }
231
232 bind_anims(extra_parts, extra_anims, controls,
233 hierarchy_match_flags);
234 }
235}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void auto_bind(PandaNode *root_node, AnimControlCollection &controls, int hierarchy_match_flags)
Walks the scene graph or subgraph beginning at the indicated node, and attempts to bind any AnimBundl...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a node that contains a pointer to an AnimBundle.
This is the root of an AnimChannel hierarchy.
Definition animBundle.h:29
This is a named collection of AnimControl pointers.
AnimControl * find_anim(const std::string &name) const
Returns the AnimControl associated with the given name, or NULL if no such control has been associate...
void store_anim(AnimControl *control, const std::string &name)
Associates the given AnimControl with this collection under the given name.
Controls the timing of a character animation.
Definition animControl.h:38
PandaNode * get_child(size_t n) const
Returns the nth child of the node.
Definition pandaNode.I:962
size_t get_num_children() const
Returns the number of children of the node.
Definition pandaNode.I:953
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
get_children
Returns an object that can be used to walk through the list of children of the node.
Definition pandaNode.h:782
This is a node that contains a pointer to an PartBundle.
This is the root of a MovingPart hierarchy.
Definition partBundle.h:46
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
This is our own Panda specialization on the default STL map.
Definition pmap.h:49
This is our own Panda specialization on the default STL set.
Definition pset.h:49
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.