Panda3D
animControl.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 animControl.cxx
10  * @author drose
11  * @date 1999-02-19
12  */
13 
14 #include "animControl.h"
15 #include "animChannelBase.h"
16 #include "partBundle.h"
17 #include "config_chan.h"
18 #include "dcast.h"
19 #include "mutexHolder.h"
20 #include "throw_event.h"
21 
22 TypeHandle AnimControl::_type_handle;
23 
24 /**
25  * This constructor is used to create a temporarily uninitialized AnimControl
26  * that will serve as a placeholder for an animation while the animation is
27  * being loaded during an asynchronous load-and-bind operation.
28  */
30 AnimControl(const std::string &name, PartBundle *part,
31  double frame_rate, int num_frames) :
32  Namable(name),
33  _pending_lock(name),
34  _pending_cvar(_pending_lock),
35  _bound_joints(BitArray::all_on()),
36  _part(part)
37 {
38 #ifdef DO_MEMORY_USAGE
39  MemoryUsage::update_type(this, get_class_type());
40 #endif
41 
42  _pending = true;
43  _anim = nullptr;
44  _channel_index = -1;
45  set_frame_rate(frame_rate);
46  set_num_frames(num_frames);
47 
48  _marked_frame = -1;
49 }
50 
51 /**
52  * This can only be called once for a given AnimControl. It is used to supply
53  * the AnimBundle and related information.
54  */
55 void AnimControl::
56 setup_anim(PartBundle *part, AnimBundle *anim, int channel_index,
57  const BitArray &bound_joints) {
58  MutexHolder holder(_pending_lock);
59  nassertv(_pending && part == _part);
60  nassertv(_anim == nullptr);
61  _anim = anim;
62  _channel_index = channel_index;
63  _bound_joints = bound_joints;
64  set_frame_rate(_anim->get_base_frame_rate());
65  set_num_frames(_anim->get_num_frames());
66 
67  // Now the AnimControl is fully set up.
68  _marked_frame = -1;
69  _pending = false;
70  _pending_cvar.notify_all();
71  if (!_pending_done_event.empty()) {
72  throw_event(_pending_done_event);
73  }
74 }
75 
76 /**
77  * Called to initialize the AnimControl with its array of bound_joints, before
78  * setup_anim() has completed.
79  */
80 void AnimControl::
81 set_bound_joints(const BitArray &bound_joints) {
82  MutexHolder holder(_pending_lock);
83  _bound_joints = bound_joints;
84 }
85 
86 /**
87  * This can only be called once for a given AnimControl. It indicates the
88  * attempt to bind it asynchronously has failed.
89  */
90 void AnimControl::
92  MutexHolder holder(_pending_lock);
93  nassertv(_pending && part == _part);
94  _pending = false;
95  _pending_cvar.notify_all();
96  if (!_pending_done_event.empty()) {
97  throw_event(_pending_done_event);
98  }
99 }
100 
101 /**
102  *
103  */
104 AnimControl::
105 ~AnimControl() {
106  get_part()->control_removed(this);
107 }
108 
109 /**
110  * Blocks the current thread until the AnimControl has finished loading and is
111  * fully bound.
112  */
113 void AnimControl::
115  MutexHolder holder(_pending_lock);
116  if (_pending) {
117  // TODO: we should elevate the priority of the associated BindAnimRequest
118  // while we're waiting for it, so it will jump to the front of the queue.
119  chan_cat.info()
120  << "Blocking " << *Thread::get_current_thread()
121  << " until " << get_name() << " is bound\n";
122  while (_pending) {
123  _pending_cvar.wait();
124  }
125  }
126 }
127 
128 /**
129  * Specifies an event name that will be thrown when the AnimControl is
130  * finished binding asynchronously. If the AnimControl has already finished
131  * binding, the event will be thrown immediately.
132  */
133 void AnimControl::
134 set_pending_done_event(const std::string &done_event) {
135  MutexHolder holder(_pending_lock);
136  _pending_done_event = done_event;
137  if (!_pending) {
138  throw_event(_pending_done_event);
139  }
140 }
141 
142 /**
143  * Returns the event name that will be thrown when the AnimControl is finished
144  * binding asynchronously.
145  */
146 std::string AnimControl::
148  MutexHolder holder(_pending_lock);
149  return _pending_done_event;
150 }
151 
152 /**
153  * Returns the PartBundle bound in with this AnimControl.
154  */
156 get_part() const {
157  return DCAST(PartBundle, _part);
158 }
159 
160 /**
161  *
162  */
163 void AnimControl::
164 output(std::ostream &out) const {
165  out << "AnimControl(" << get_name() << ", " << get_part()->get_name()
166  << ": ";
167  AnimInterface::output(out);
168  out << ")";
169 
170  if (is_pending()) {
171  out << " (pending bind)";
172  } else if (!has_anim()) {
173  out << " (failed bind)";
174  }
175 }
176 
177 /**
178  * Returns true if the indicated channel value has changed since the last call
179  * to mark_channels().
180  */
181 bool AnimControl::
182 channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const {
183  if (_marked_frame < 0) {
184  return true;
185  }
186 
187  int this_frame = get_frame();
188  double this_frac = 0.0;
189  if (frame_blend_flag) {
190  this_frac = get_frac();
191  }
192  return channel->has_changed(_marked_frame, _marked_frac,
193  this_frame, this_frac);
194 }
195 
196 /**
197  * Marks this point as the point of reference for the next call to
198  * channel_has_changed().
199  */
200 void AnimControl::
201 mark_channels(bool frame_blend_flag) {
202  _marked_frame = get_frame();
203  _marked_frac = 0.0;
204  if (frame_blend_flag) {
205  _marked_frac = get_frac();
206  }
207 }
208 
209 /**
210  * This is provided as a callback method for when the user calls one of the
211  * play/loop/pose type methods to start the animation playing.
212  */
213 void AnimControl::
214 animation_activated() {
215  get_part()->control_activated(this);
216 }
void set_pending_done_event(const std::string &done_event)
Specifies an event name that will be thrown when the AnimControl is finished binding asynchronously.
void wait()
Waits on the condition.
This is the root of an AnimChannel hierarchy.
Definition: animBundle.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const
Returns true if the indicated channel value has changed since the last call to mark_channels().
get_frac
Returns the fractional part of the current frame.
Definition: animInterface.h:72
virtual bool has_changed(int last_frame, double last_frac, int this_frame, double this_frac)
Returns true if the value has changed since the last call to has_changed().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PartBundle * get_part() const
Returns the PartBundle bound in with this AnimControl.
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
A dynamic array with an unlimited number of bits.
Definition: bitArray.h:39
Parent class for all animation channels.
A base class for all things which can have a name.
Definition: namable.h:26
std::string get_pending_done_event() const
Returns the event name that will be thrown when the AnimControl is finished binding asynchronously.
void control_removed(AnimControl *control)
Called by the AnimControl when it destructs.
Definition: partBundle.cxx:552
void setup_anim(PartBundle *part, AnimBundle *anim, int channel_index, const BitArray &bound_joints)
This can only be called once for a given AnimControl.
Definition: animControl.cxx:56
void set_bound_joints(const BitArray &bound_joints)
Called to initialize the AnimControl with its array of bound_joints, before setup_anim() has complete...
Definition: animControl.cxx:81
void wait_pending()
Blocks the current thread until the AnimControl has finished loading and is fully bound.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_frame
Returns the current integer frame number.
Definition: animInterface.h:70
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
bool has_anim() const
Returns true if the AnimControl was successfully loaded, or false if there was a problem.
Definition: animControl.I:30
virtual void control_activated(AnimControl *control)
Called by the AnimControl whenever it starts an animation.
Definition: partBundle.cxx:533
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:46
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void mark_channels(bool frame_blend_flag)
Marks this point as the point of reference for the next call to channel_has_changed().
AnimControl(const std::string &name, PartBundle *part, double frame_rate, int num_frames)
This constructor is used to create a temporarily uninitialized AnimControl that will serve as a place...
Definition: animControl.cxx:30
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
void fail_anim(PartBundle *part)
This can only be called once for a given AnimControl.
Definition: animControl.cxx:91
bool is_pending() const
Returns true if the AnimControl is being bound asynchronously, and has not yet finished.
Definition: animControl.I:21
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.