void GfxBody::setAnimationMask (const std::string &name, float v) { if (dead) THROW_DEAD(className); Ogre::AnimationState *state = getAnimState(name); state->setWeight(v); state->setEnabled(v > 0.0f); }
/**更新动画*/ void Enemy::updateAnimation(float time) { m_AniFade-=time; m_AniFade=std::max(m_AniFade,0.0f); if (m_pEntity) { Ogre::AnimationStateSet* animStateSet = m_pEntity->getAllAnimationStates(); // 更新自身动画 if (animStateSet) { Ogre::ConstEnabledAnimationStateIterator animStateItor = animStateSet->getEnabledAnimationStateIterator(); while (animStateItor.hasMoreElements()) { Ogre::AnimationState* animState = animStateItor.getNext(); animState->addTime(time); // 当前动画逐渐递增权重 if (animState== m_pAniSate) { if (animState->getWeight() < 1.0f) { animState->setWeight(1.0f - m_AniFade); } } // 其余动画逐渐递减权重,直到关闭动画 else { if (Ogre::Math::RealEqual(animState->getWeight(), 0.0f)) { animState->setWeight(1.0f); animState->setEnabled(false); } else { animState->setWeight(m_AniFade); } } } } } }
bool CAnimatedEntity::setAnimation(const std::string &anim, bool loop, int rewind, float fadeTime) { if(!_entity->getAllAnimationStates()->hasAnimationState(anim)) return false; //comprobamos si la animación ya estaba ejecutandose auto runningAnim = _runningAnimations.find(anim); if(runningAnim != _runningAnimations.end()) { if(runningAnim->second.state == FADE_OUT) { runningAnim->second.state = FADE_IN; //comprobamos que la animación no estaba justo para //ser sacada if(!_deletedAnims.empty()) { auto delAnim = _deletedAnims.begin(); auto delEnd = _deletedAnims.end(); for(; delAnim!=delEnd; delAnim++) { if ((*delAnim) == runningAnim->second.animation->getAnimationName()) { _deletedAnims.erase(delAnim); runningAnim->second.animation->setEnabled(true); break; } } } } runningAnim->second.direction = rewind; return true; } //cogemos la animacion y la preparamos para ejecutarla Ogre::AnimationState* animstate = _entity->getAnimationState(anim); animstate->setEnabled(true); animstate->setLoop(loop); animstate->setWeight(0); //seteamos la animación nueva para que haga fade-in, teniendo //en cuenta el tiempo de fade que se le ha pasado Animation animation; animation.animation = animstate; animation.state = FADE_IN; animation.fadeTime = fadeTime; animation.direction = rewind; //metemos la animacion en la lista de animaciones ejecutandose TAnim newAnim (anim,animation); _runningAnimations.insert(newAnim); return true; } // setAnimation
CharacterAnimation::CharacterAnimation(Ogre::Entity* ent) { Ogre::AnimationStateSet * anims = ent->getAllAnimationStates(); Ogre::AnimationStateIterator it = anims->getAnimationStateIterator(); while(it.hasMoreElements()) { Ogre::AnimationState * as = it.getNext(); as->setWeight(0); Animations.insert(std::make_pair(as->getAnimationName(), AnimState(as, 0, 5, 5, 1))); } ent->getSkeleton()->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE); }
void EC_OgreAnimationController::Update(f64 frametime) { Ogre::Entity* entity = GetEntity(); if (!entity) return; std::vector<std::string> erase_list; // Loop through all animations & update them as necessary for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; switch(i->second.phase_) { case PHASE_FADEIN: // If period is infinitely fast, skip to full weight & PLAY status if (i->second.fade_period_ == 0.0f) { i->second.weight_ = 1.0f; i->second.phase_ = PHASE_PLAY; } else { i->second.weight_ += (1.0f / i->second.fade_period_) * frametime; if (i->second.weight_ >= 1.0f) { i->second.weight_ = 1.0f; i->second.phase_ = PHASE_PLAY; } } break; case PHASE_PLAY: if (i->second.auto_stop_ || i->second.num_repeats_ != 1) { if ((i->second.speed_factor_ >= 0.f && animstate->getTimePosition() >= animstate->getLength()) || (i->second.speed_factor_ < 0.f && animstate->getTimePosition() <= 0.f)) { if (i->second.num_repeats_ != 1) { if (i->second.num_repeats_ > 1) i->second.num_repeats_--; Ogre::Real rewindpos = i->second.speed_factor_ >= 0.f ? (animstate->getTimePosition() - animstate->getLength()) : animstate->getLength(); animstate->setTimePosition(rewindpos); } else { i->second.phase_ = PHASE_FADEOUT; } } } break; case PHASE_FADEOUT: // If period is infinitely fast, skip to disabled status immediately if (i->second.fade_period_ == 0.0f) { i->second.weight_ = 0.0f; i->second.phase_ = PHASE_STOP; } else { i->second.weight_ -= (1.0f / i->second.fade_period_) * frametime; if (i->second.weight_ <= 0.0f) { i->second.weight_ = 0.0f; i->second.phase_ = PHASE_STOP; } } break; } // Set weight & step the animation forward if (i->second.phase_ != PHASE_STOP) { Ogre::Real advance = i->second.speed_factor_ * frametime; Ogre::Real new_weight = i->second.weight_ * i->second.weight_factor_; if (new_weight != animstate->getWeight()) animstate->setWeight((Ogre::Real)i->second.weight_ * i->second.weight_factor_); if (advance != 0.0f) animstate->addTime((Ogre::Real)(i->second.speed_factor_ * frametime)); if (!animstate->getEnabled()) animstate->setEnabled(true); } else { // If stopped, disable & remove this animation from list animstate->setEnabled(false); erase_list.push_back(i->first); } } for (uint i = 0; i < erase_list.size(); ++i) { animations_.erase(erase_list[i]); } // High-priority/low-priority blending code if (entity->hasSkeleton()) { Ogre::SkeletonInstance* skel = entity->getSkeleton(); if (!skel) return; if (highpriority_mask_.size() != skel->getNumBones()) highpriority_mask_.resize(skel->getNumBones()); if (lowpriority_mask_.size() != skel->getNumBones()) lowpriority_mask_.resize(skel->getNumBones()); for (uint i = 0; i < skel->getNumBones(); ++i) { highpriority_mask_[i] = 1.0; lowpriority_mask_[i] = 1.0; } // Loop through all high priority animations & update the lowpriority-blendmask based on their active tracks for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; // Create blend mask if animstate doesn't have it yet if (!animstate->hasBlendMask()) animstate->createBlendMask(skel->getNumBones()); if ((i->second.high_priority_) && (i->second.weight_ > 0.0)) { // High-priority animations get the full weight blend mask animstate->_setBlendMaskData(&highpriority_mask_[0]); if (!skel->hasAnimation(animstate->getAnimationName())) continue; Ogre::Animation* anim = skel->getAnimation(animstate->getAnimationName()); Ogre::Animation::NodeTrackIterator it = anim->getNodeTrackIterator(); while (it.hasMoreElements()) { Ogre::NodeAnimationTrack* track = it.getNext(); unsigned id = track->getHandle(); // For each active track, reduce corresponding bone weight in lowpriority-blendmask // by this animation's weight if (id < lowpriority_mask_.size()) { lowpriority_mask_[id] -= i->second.weight_; if (lowpriority_mask_[id] < 0.0) lowpriority_mask_[id] = 0.0; } } } } // Now set the calculated blendmask on low-priority animations for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; if (i->second.high_priority_ == false) animstate->_setBlendMaskData(&lowpriority_mask_[0]); } } }