mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-18 12:43:44 -04:00
control effect, etc., needs to be cycled
This commit is contained in:
parent
e122b6b78c
commit
069fb87e7b
@ -104,16 +104,19 @@ do_update(PartBundle *root, PartGroup *parent,
|
||||
|
||||
// See if any of the channel values have changed since last time.
|
||||
|
||||
PartBundle::control_iterator bci;
|
||||
for (bci = root->control_begin();
|
||||
!needs_update && bci != root->control_end();
|
||||
++bci) {
|
||||
AnimControl *control = (*bci);
|
||||
int channel_index = control->get_channel_index();
|
||||
nassertr(channel_index >= 0 && channel_index < (int)_channels.size(), false);
|
||||
AnimChannelBase *channel = _channels[channel_index];
|
||||
if (channel != (AnimChannelBase*)NULL) {
|
||||
needs_update = control->channel_has_changed(channel);
|
||||
{
|
||||
PartBundle::CDReader cdata(root->_cycler);
|
||||
PartBundle::ChannelBlend::const_iterator bci;
|
||||
for (bci = cdata->_blend.begin();
|
||||
!needs_update && bci != cdata->_blend.end();
|
||||
++bci) {
|
||||
AnimControl *control = (*bci).first;
|
||||
int channel_index = control->get_channel_index();
|
||||
nassertr(channel_index >= 0 && channel_index < (int)_channels.size(), false);
|
||||
AnimChannelBase *channel = _channels[channel_index];
|
||||
if (channel != (AnimChannelBase*)NULL) {
|
||||
needs_update = control->channel_has_changed(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,15 +63,15 @@ make_initial_channel() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MovingPartMatrix::
|
||||
get_blend_value(const PartBundle *root) {
|
||||
const PartBundle::ChannelBlend &blend = root->get_blend_map();
|
||||
PartBundle::CDReader cdata(root->_cycler);
|
||||
|
||||
if (blend.empty()) {
|
||||
if (cdata->_blend.empty()) {
|
||||
// No channel is bound; supply the default value.
|
||||
_value = _initial_value;
|
||||
|
||||
} else if (blend.size() == 1) {
|
||||
} else if (cdata->_blend.size() == 1) {
|
||||
// A single value, the normal case.
|
||||
AnimControl *control = (*blend.begin()).first;
|
||||
AnimControl *control = (*cdata->_blend.begin()).first;
|
||||
|
||||
int channel_index = control->get_channel_index();
|
||||
nassertv(channel_index >= 0 && channel_index < (int)_channels.size());
|
||||
@ -87,7 +87,7 @@ get_blend_value(const PartBundle *root) {
|
||||
} else {
|
||||
// A blend of two or more values.
|
||||
|
||||
switch (root->get_blend_type()) {
|
||||
switch (cdata->_blend_type) {
|
||||
case PartBundle::BT_single:
|
||||
case PartBundle::BT_linear:
|
||||
{
|
||||
@ -96,7 +96,7 @@ get_blend_value(const PartBundle *root) {
|
||||
float net = 0.0f;
|
||||
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = blend.begin(); cbi != blend.end(); ++cbi) {
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
float effect = (*cbi).second;
|
||||
nassertv(effect != 0.0f);
|
||||
@ -135,7 +135,7 @@ get_blend_value(const PartBundle *root) {
|
||||
float net = 0.0f;
|
||||
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = blend.begin(); cbi != blend.end(); ++cbi) {
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
float effect = (*cbi).second;
|
||||
nassertv(effect != 0.0f);
|
||||
@ -184,7 +184,7 @@ get_blend_value(const PartBundle *root) {
|
||||
float net = 0.0f;
|
||||
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = blend.begin(); cbi != blend.end(); ++cbi) {
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
float effect = (*cbi).second;
|
||||
nassertv(effect != 0.0f);
|
||||
@ -232,7 +232,7 @@ get_blend_value(const PartBundle *root) {
|
||||
float net = 0.0f;
|
||||
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = blend.begin(); cbi != blend.end(); ++cbi) {
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
float effect = (*cbi).second;
|
||||
nassertv(effect != 0.0f);
|
||||
|
@ -48,15 +48,15 @@ MovingPartScalar::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MovingPartScalar::
|
||||
get_blend_value(const PartBundle *root) {
|
||||
const PartBundle::ChannelBlend &blend = root->get_blend_map();
|
||||
PartBundle::CDReader cdata(root->_cycler);
|
||||
|
||||
if (blend.empty()) {
|
||||
if (cdata->_blend.empty()) {
|
||||
// No channel is bound; supply the default value.
|
||||
_value = _initial_value;
|
||||
|
||||
} else if (blend.size() == 1) {
|
||||
} else if (cdata->_blend.size() == 1) {
|
||||
// A single value, the normal case.
|
||||
AnimControl *control = (*blend.begin()).first;
|
||||
AnimControl *control = (*cdata->_blend.begin()).first;
|
||||
|
||||
int channel_index = control->get_channel_index();
|
||||
nassertv(channel_index >= 0 && channel_index < (int)_channels.size());
|
||||
@ -75,7 +75,7 @@ get_blend_value(const PartBundle *root) {
|
||||
float net = 0.0f;
|
||||
|
||||
PartBundle::ChannelBlend::const_iterator cbi;
|
||||
for (cbi = blend.begin(); cbi != blend.end(); ++cbi) {
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
float effect = (*cbi).second;
|
||||
nassertv(effect != 0.0f);
|
||||
|
@ -25,7 +25,8 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundle::BlendType PartBundle::
|
||||
get_blend_type() const {
|
||||
return _blend_type;
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_blend_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -39,50 +40,41 @@ get_node() const {
|
||||
return _node;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::control_begin
|
||||
// Access: Public
|
||||
// Description: Returns an iterator that can be used to traverse the
|
||||
// entire set of AnimControls currently in effect.
|
||||
// Function: PartBundle::set_control_effect
|
||||
// Access: Published
|
||||
// Description: Sets the amount by which the character is affected by
|
||||
// the indicated AnimControl (and its associated
|
||||
// animation). Normally, this will only be zero or one.
|
||||
// Zero indicates the animation does not affect the
|
||||
// character, and one means it does.
|
||||
//
|
||||
// If the blend_type is not BT_single (see
|
||||
// set_blend_type()), it is possible to have multiple
|
||||
// AnimControls in effect simultaneously. In this case,
|
||||
// the effect is a weight that indicates the relative
|
||||
// importance of each AnimControl to the final
|
||||
// animation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundle::control_iterator PartBundle::
|
||||
control_begin() const {
|
||||
return _blend.begin();
|
||||
void PartBundle::
|
||||
set_control_effect(AnimControl *control, float effect) {
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
do_set_control_effect(control, effect, cdata);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::control_end
|
||||
// Access: Public
|
||||
// Description: Returns an iterator that can be used to traverse the
|
||||
// entire set of AnimControls currently in effect.
|
||||
// Function: PartBundle::get_control_effect
|
||||
// Access: Published
|
||||
// Description: Returns the amount by which the character is affected
|
||||
// by the indicated AnimControl and its associated
|
||||
// animation. See set_control_effect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundle::control_iterator PartBundle::
|
||||
control_end() const {
|
||||
return _blend.end();
|
||||
INLINE float PartBundle::
|
||||
get_control_effect(AnimControl *control) const {
|
||||
CDReader cdata(_cycler);
|
||||
return do_get_control_effect(control, cdata);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::control_size
|
||||
// Access: Public
|
||||
// Description: Returns the number of entries between control_begin()
|
||||
// and control_end(): the number of AnimControls
|
||||
// currently in effect.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PartBundle::control_size_type PartBundle::
|
||||
control_size() const {
|
||||
return _blend.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::get_blend_map
|
||||
// Access: Public
|
||||
// Description: Returns the entire mapping of AnimControls to blend
|
||||
// effect.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const PartBundle::ChannelBlend &PartBundle::
|
||||
get_blend_map() const {
|
||||
return _blend;
|
||||
}
|
||||
|
@ -41,12 +41,10 @@ TypeHandle PartBundle::_type_handle;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PartBundle::
|
||||
PartBundle(const PartBundle ©) :
|
||||
PartGroup(copy),
|
||||
_blend_type(copy._blend_type)
|
||||
PartGroup(copy)
|
||||
{
|
||||
_last_control_set = NULL;
|
||||
_net_blend = 0.0f;
|
||||
_anim_changed = false;
|
||||
CDWriter cdata(_cycler, true);
|
||||
cdata->_blend_type = copy.get_blend_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -58,11 +56,6 @@ PartBundle(const PartBundle ©) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PartBundle::
|
||||
PartBundle(const string &name) : PartGroup(name) {
|
||||
_blend_type = BT_single;
|
||||
|
||||
_last_control_set = NULL;
|
||||
_net_blend = 0.0f;
|
||||
_anim_changed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -99,19 +92,23 @@ make_copy() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
set_blend_type(BlendType bt) {
|
||||
if (_blend_type != bt) {
|
||||
_blend_type = bt;
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
|
||||
if (_blend_type == BT_single && control_size() > 1) {
|
||||
CDReader cdata(_cycler);
|
||||
if (cdata->_blend_type != bt) {
|
||||
CDWriter cdataw(_cycler, cdata);
|
||||
cdataw->_blend_type = bt;
|
||||
|
||||
if (cdataw->_blend_type == BT_single && cdataw->_blend.size() > 1) {
|
||||
// If we just changed to a single blend type, i.e. no blending,
|
||||
// we should eliminate all the AnimControls other than the
|
||||
// most-recently-added one.
|
||||
|
||||
nassertv(_last_control_set != NULL);
|
||||
clear_and_stop_intersecting(_last_control_set);
|
||||
nassertv(cdataw->_last_control_set != NULL);
|
||||
clear_and_stop_intersecting(cdataw->_last_control_set, cdataw);
|
||||
}
|
||||
|
||||
_anim_changed = true;
|
||||
cdataw->_anim_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,84 +129,17 @@ set_blend_type(BlendType bt) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
clear_control_effects() {
|
||||
if (!_blend.empty()) {
|
||||
_blend.clear();
|
||||
_net_blend = 0.0f;
|
||||
_anim_changed = true;
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
if (!cdata->_blend.empty()) {
|
||||
CDWriter cdataw(_cycler, cdata);
|
||||
cdataw->_blend.clear();
|
||||
cdataw->_net_blend = 0.0f;
|
||||
cdataw->_anim_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::set_control_effect
|
||||
// Access: Published
|
||||
// Description: Sets the amount by which the character is affected by
|
||||
// the indicated AnimControl (and its associated
|
||||
// animation). Normally, this will only be zero or one.
|
||||
// Zero indicates the animation does not affect the
|
||||
// character, and one means it does.
|
||||
//
|
||||
// If the blend_type is not BT_single (see
|
||||
// set_blend_type()), it is possible to have multiple
|
||||
// AnimControls in effect simultaneously. In this case,
|
||||
// the effect is a weight that indicates the relative
|
||||
// importance of each AnimControl to the final
|
||||
// animation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
set_control_effect(AnimControl *control, float effect) {
|
||||
nassertv(control->get_part() == this);
|
||||
|
||||
if (effect == 0.0f) {
|
||||
// An effect of zero means to eliminate the control.
|
||||
ChannelBlend::iterator cbi = _blend.find(control);
|
||||
if (cbi != _blend.end()) {
|
||||
_blend.erase(cbi);
|
||||
_anim_changed = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Otherwise we define it.
|
||||
|
||||
// If we currently have BT_single, we only allow one AnimControl
|
||||
// at a time. Stop all of the other AnimControls.
|
||||
if (get_blend_type() == BT_single) {
|
||||
clear_and_stop_intersecting(control);
|
||||
}
|
||||
|
||||
if (get_control_effect(control) != effect) {
|
||||
_blend[control] = effect;
|
||||
_anim_changed = true;
|
||||
}
|
||||
_last_control_set = control;
|
||||
}
|
||||
|
||||
recompute_net_blend();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::get_control_effect
|
||||
// Access: Published
|
||||
// Description: Returns the amount by which the character is affected
|
||||
// by the indicated AnimControl and its associated
|
||||
// animation. See set_control_effect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float PartBundle::
|
||||
get_control_effect(AnimControl *control) {
|
||||
nassertr(control->get_part() == this, 0.0f);
|
||||
|
||||
ChannelBlend::iterator cbi = _blend.find(control);
|
||||
if (cbi == _blend.end()) {
|
||||
// The control is not in effect.
|
||||
return 0.0f;
|
||||
} else {
|
||||
return (*cbi).second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::output
|
||||
// Access: Published, Virtual
|
||||
@ -261,6 +191,8 @@ write(ostream &out, int indent_level) const {
|
||||
PT(AnimControl) PartBundle::
|
||||
bind_anim(AnimBundle *anim, int hierarchy_match_flags,
|
||||
const PartSubset &subset) {
|
||||
nassertr(Thread::get_current_pipeline_stage() == 0, NULL);
|
||||
|
||||
if ((hierarchy_match_flags & HMF_ok_wrong_root_name) == 0) {
|
||||
// Make sure the root names match.
|
||||
if (get_name() != anim->get_name()) {
|
||||
@ -308,15 +240,22 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PartBundle::
|
||||
update() {
|
||||
bool any_changed = do_update(this, NULL, false, _anim_changed);
|
||||
bool anim_changed;
|
||||
{
|
||||
CDReader cdata(_cycler);
|
||||
anim_changed = cdata->_anim_changed;
|
||||
}
|
||||
bool any_changed = do_update(this, NULL, false, anim_changed);
|
||||
|
||||
// Now update all the controls for next time.
|
||||
CDWriter cdata(_cycler, false);
|
||||
ChannelBlend::const_iterator cbi;
|
||||
for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
control->mark_channels();
|
||||
}
|
||||
_anim_changed = false;
|
||||
|
||||
cdata->_anim_changed = false;
|
||||
|
||||
return any_changed;
|
||||
}
|
||||
@ -333,12 +272,14 @@ force_update() {
|
||||
bool any_changed = do_update(this, NULL, true, true);
|
||||
|
||||
// Now update all the controls for next time.
|
||||
CDWriter cdata(_cycler, false);
|
||||
ChannelBlend::const_iterator cbi;
|
||||
for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *control = (*cbi).first;
|
||||
control->mark_channels();
|
||||
}
|
||||
_anim_changed = false;
|
||||
|
||||
cdata->_anim_changed = false;
|
||||
|
||||
return any_changed;
|
||||
}
|
||||
@ -353,31 +294,128 @@ force_update() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
control_activated(AnimControl *control) {
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
nassertv(control->get_part() == this);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
// If (and only if) our blend type is BT_single, which means no
|
||||
// blending, then starting an animation implicitly enables it.
|
||||
if (get_blend_type() == BT_single) {
|
||||
set_control_effect(control, 1.0f);
|
||||
if (cdata->_blend_type == BT_single) {
|
||||
CDWriter cdataw(_cycler, cdata);
|
||||
do_set_control_effect(control, 1.0f, cdataw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::do_set_control_effect
|
||||
// Access: Private
|
||||
// Description: The private implementation of set_control_effect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
do_set_control_effect(AnimControl *control, float effect, CData *cdata) {
|
||||
nassertv(control->get_part() == this);
|
||||
|
||||
if (effect == 0.0f) {
|
||||
// An effect of zero means to eliminate the control.
|
||||
ChannelBlend::iterator cbi = cdata->_blend.find(control);
|
||||
if (cbi != cdata->_blend.end()) {
|
||||
cdata->_blend.erase(cbi);
|
||||
cdata->_anim_changed = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Otherwise we define it.
|
||||
|
||||
// If we currently have BT_single, we only allow one AnimControl
|
||||
// at a time. Stop all of the other AnimControls.
|
||||
if (cdata->_blend_type == BT_single) {
|
||||
clear_and_stop_intersecting(control, cdata);
|
||||
}
|
||||
|
||||
if (do_get_control_effect(control, cdata) != effect) {
|
||||
cdata->_blend[control] = effect;
|
||||
cdata->_anim_changed = true;
|
||||
}
|
||||
cdata->_last_control_set = control;
|
||||
}
|
||||
|
||||
recompute_net_blend(cdata);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::do_get_control_effect
|
||||
// Access: Private
|
||||
// Description: The private implementation of get_control_effect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float PartBundle::
|
||||
do_get_control_effect(AnimControl *control, const CData *cdata) const {
|
||||
nassertr(control->get_part() == this, 0.0f);
|
||||
|
||||
ChannelBlend::const_iterator cbi = cdata->_blend.find(control);
|
||||
if (cbi == cdata->_blend.end()) {
|
||||
// The control is not in effect.
|
||||
return 0.0f;
|
||||
} else {
|
||||
return (*cbi).second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::recompute_net_blend
|
||||
// Access: Protected
|
||||
// Access: Private
|
||||
// Description: Recomputes the total blending amount after a control
|
||||
// effect has been adjusted. This value must be kept
|
||||
// up-to-date so we can normalize the blending amounts.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
recompute_net_blend() {
|
||||
_net_blend = 0.0f;
|
||||
recompute_net_blend(CData *cdata) {
|
||||
cdata->_net_blend = 0.0f;
|
||||
|
||||
ChannelBlend::const_iterator bti;
|
||||
for (bti = _blend.begin(); bti != _blend.end(); ++bti) {
|
||||
_net_blend += (*bti).second;
|
||||
for (bti = cdata->_blend.begin(); bti != cdata->_blend.end(); ++bti) {
|
||||
cdata->_net_blend += (*bti).second;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::clear_and_stop_intersecting
|
||||
// Access: Private
|
||||
// Description: Removes and stops all the currently activated
|
||||
// AnimControls that animate some joints also animated
|
||||
// by the indicated AnimControl. This is a special
|
||||
// internal function that's only called when _blend_type
|
||||
// is BT_single, to automatically stop all the other
|
||||
// currently-executing animations.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
clear_and_stop_intersecting(AnimControl *control, CData *cdata) {
|
||||
double new_net_blend = 0.0f;
|
||||
ChannelBlend new_blend;
|
||||
bool any_changed = false;
|
||||
|
||||
ChannelBlend::iterator cbi;
|
||||
for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
|
||||
AnimControl *ac = (*cbi).first;
|
||||
if (ac == control ||
|
||||
!ac->get_bound_joints().has_bits_in_common(control->get_bound_joints())) {
|
||||
// Save this control--it's either the target control, or it has
|
||||
// no joints in common with the target control.
|
||||
new_blend.insert(new_blend.end(), (*cbi));
|
||||
new_net_blend += (*cbi).second;
|
||||
} else {
|
||||
// Remove and stop this control.
|
||||
ac->stop();
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_changed) {
|
||||
cdata->_net_blend = new_net_blend;
|
||||
cdata->_blend.swap(new_blend);
|
||||
cdata->_anim_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,40 +461,42 @@ register_with_read_factory()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::clear_and_stop_intersecting
|
||||
// Access: Protected
|
||||
// Description: Removes and stops all the currently activated
|
||||
// AnimControls that animate some joints also animated
|
||||
// by the indicated AnimControl. This is a special
|
||||
// internal function that's only called when _blend_type
|
||||
// is BT_single, to automatically stop all the other
|
||||
// currently-executing animations.
|
||||
// Function: PartBundle::CData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PartBundle::
|
||||
clear_and_stop_intersecting(AnimControl *control) {
|
||||
double new_net_blend = 0.0f;
|
||||
ChannelBlend new_blend;
|
||||
bool any_changed = false;
|
||||
|
||||
ChannelBlend::iterator cbi;
|
||||
for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
|
||||
AnimControl *ac = (*cbi).first;
|
||||
if (ac == control ||
|
||||
!ac->get_bound_joints().has_bits_in_common(control->get_bound_joints())) {
|
||||
// Save this control--it's either the target control, or it has
|
||||
// no joints in common with the target control.
|
||||
new_blend.insert(new_blend.end(), (*cbi));
|
||||
new_net_blend += (*cbi).second;
|
||||
} else {
|
||||
// Remove and stop this control.
|
||||
ac->stop();
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_changed) {
|
||||
_net_blend = new_net_blend;
|
||||
_blend.swap(new_blend);
|
||||
_anim_changed = true;
|
||||
}
|
||||
PartBundle::CData::
|
||||
CData() {
|
||||
_blend_type = BT_single;
|
||||
_last_control_set = NULL;
|
||||
_net_blend = 0.0f;
|
||||
_anim_changed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::CData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PartBundle::CData::
|
||||
CData(const PartBundle::CData ©) :
|
||||
_blend_type(copy._blend_type),
|
||||
_last_control_set(copy._last_control_set),
|
||||
_blend(copy._blend),
|
||||
_net_blend(copy._net_blend),
|
||||
_anim_changed(copy._anim_changed)
|
||||
{
|
||||
// Note that this copy constructor is not used by the PartBundle
|
||||
// copy constructor! Any elements that must be copied between
|
||||
// PartBundles should also be explicitly copied there.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PartBundle::CData::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *PartBundle::CData::
|
||||
make_copy() const {
|
||||
return new CData(*this);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "animControl.h"
|
||||
#include "partSubset.h"
|
||||
#include "pointerTo.h"
|
||||
#include "iterator_types.h"
|
||||
|
||||
class AnimBundle;
|
||||
class PartBundleNode;
|
||||
@ -44,9 +43,6 @@ public:
|
||||
// do_update() call to specify the channels that are in effect.
|
||||
typedef pmap<AnimControl *, float> ChannelBlend;
|
||||
|
||||
typedef first_of_pair_iterator<ChannelBlend::const_iterator> control_iterator;
|
||||
typedef ChannelBlend::size_type control_size_type;
|
||||
|
||||
protected:
|
||||
// The copy constructor is protected; use make_copy() or copy_subgraph().
|
||||
PartBundle(const PartBundle ©);
|
||||
@ -105,8 +101,8 @@ PUBLISHED:
|
||||
INLINE PartBundleNode *get_node() const;
|
||||
|
||||
void clear_control_effects();
|
||||
void set_control_effect(AnimControl *control, float effect);
|
||||
float get_control_effect(AnimControl *control);
|
||||
INLINE void set_control_effect(AnimControl *control, float effect);
|
||||
INLINE float get_control_effect(AnimControl *control) const;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
@ -116,15 +112,6 @@ PUBLISHED:
|
||||
const PartSubset &subset = PartSubset());
|
||||
|
||||
public:
|
||||
// The following functions may be used to traverse the set of
|
||||
// controls applied to the PartBundle. Beware! These are not safe
|
||||
// to use outside of PANDA.DLL.
|
||||
INLINE control_iterator control_begin() const;
|
||||
INLINE control_iterator control_end() const;
|
||||
INLINE control_size_type control_size() const;
|
||||
|
||||
INLINE const ChannelBlend &get_blend_map() const;
|
||||
|
||||
// The following functions aren't really part of the public
|
||||
// interface; they're just public so we don't have to declare a
|
||||
// bunch of friends.
|
||||
@ -133,17 +120,37 @@ public:
|
||||
bool force_update();
|
||||
virtual void control_activated(AnimControl *control);
|
||||
|
||||
protected:
|
||||
void recompute_net_blend();
|
||||
void clear_and_stop_intersecting(AnimControl *control);
|
||||
private:
|
||||
class CData;
|
||||
|
||||
void do_set_control_effect(AnimControl *control, float effect, CData *cdata);
|
||||
float do_get_control_effect(AnimControl *control, const CData *cdata) const;
|
||||
void recompute_net_blend(CData *cdata);
|
||||
void clear_and_stop_intersecting(AnimControl *control, CData *cdata);
|
||||
|
||||
BlendType _blend_type;
|
||||
PartBundleNode *_node;
|
||||
|
||||
AnimControl *_last_control_set;
|
||||
ChannelBlend _blend;
|
||||
float _net_blend;
|
||||
bool _anim_changed;
|
||||
// This is the data that must be cycled between pipeline stages.
|
||||
class CData : public CycleData {
|
||||
public:
|
||||
CData();
|
||||
CData(const CData ©);
|
||||
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return PartBundle::get_class_type();
|
||||
}
|
||||
|
||||
BlendType _blend_type;
|
||||
AnimControl *_last_control_set;
|
||||
ChannelBlend _blend;
|
||||
float _net_blend;
|
||||
bool _anim_changed;
|
||||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
@ -170,6 +177,9 @@ private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class PartBundleNode;
|
||||
friend class MovingPartBase;
|
||||
friend class MovingPartMatrix;
|
||||
friend class MovingPartScalar;
|
||||
};
|
||||
|
||||
inline ostream &operator <<(ostream &out, const PartBundle &bundle) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user