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  */
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  */
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  */
91 fail_anim(PartBundle *part) {
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  */
114 wait_pending() {
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  */
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::
147 get_pending_done_event() const {
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  */
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  */
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 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the root of an AnimChannel hierarchy.
Definition: animBundle.h:29
Parent class for all animation channels.
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().
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
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 mark_channels(bool frame_blend_flag)
Marks this point as the point of reference for the next call to channel_has_changed().
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
void wait_pending()
Blocks the current thread until the AnimControl has finished loading and is fully bound.
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
std::string get_pending_done_event() const
Returns the event name that will be thrown when the AnimControl is finished binding asynchronously.
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.
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().
bool has_anim() const
Returns true if the AnimControl was successfully loaded, or false if there was a problem.
Definition: animControl.I:30
PartBundle * get_part() const
Returns the PartBundle bound in with this AnimControl.
get_frame
Returns the current integer frame number.
Definition: animInterface.h:70
get_frac
Returns the fractional part of the current frame.
Definition: animInterface.h:72
A dynamic array with an unlimited number of bits.
Definition: bitArray.h:40
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
void wait()
Waits on the condition.
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
A base class for all things which can have a name.
Definition: namable.h:26
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:46
virtual void control_activated(AnimControl *control)
Called by the AnimControl whenever it starts an animation.
Definition: partBundle.cxx:533
void control_removed(AnimControl *control)
Called by the AnimControl when it destructs.
Definition: partBundle.cxx:552
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.