mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 19:55:23 +00:00
初始化
This commit is contained in:
@@ -0,0 +1,602 @@
|
||||
#include "Animation.h"
|
||||
#include "../model/DisplayData.h"
|
||||
#include "../model/AnimationConfig.h"
|
||||
#include "../model/AnimationData.h"
|
||||
#include "../armature/Armature.h"
|
||||
#include "../armature/Bone.h"
|
||||
#include "../armature/Slot.h"
|
||||
#include "AnimationState.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
|
||||
void Animation::_onClear()
|
||||
{
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
animationState->returnToPool();
|
||||
}
|
||||
|
||||
if (_animationConfig != nullptr)
|
||||
{
|
||||
_animationConfig->returnToPool();
|
||||
}
|
||||
|
||||
timeScale = 1.0f;
|
||||
|
||||
_animationDirty = false;
|
||||
_inheritTimeScale = 1.0f;
|
||||
_animations.clear();
|
||||
_animationNames.clear();
|
||||
_animationStates.clear();
|
||||
_armature = nullptr;
|
||||
_animationConfig = nullptr;
|
||||
_lastAnimationState = nullptr;
|
||||
}
|
||||
|
||||
void Animation::_fadeOut(AnimationConfig* animationConfig)
|
||||
{
|
||||
switch (animationConfig->fadeOutMode)
|
||||
{
|
||||
case AnimationFadeOutMode::SameLayer:
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
if (animationState->layer == (unsigned)animationConfig->layer)
|
||||
{
|
||||
animationState->fadeOut(animationConfig->fadeOutTime, animationConfig->pauseFadeOut);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AnimationFadeOutMode::SameGroup:
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
if (animationState->group == animationConfig->group)
|
||||
{
|
||||
animationState->fadeOut(animationConfig->fadeOutTime, animationConfig->pauseFadeOut);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AnimationFadeOutMode::SameLayerAndGroup:
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
if (animationState->layer == (unsigned)animationConfig->layer && animationState->group == animationConfig->group)
|
||||
{
|
||||
animationState->fadeOut(animationConfig->fadeOutTime, animationConfig->pauseFadeOut);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AnimationFadeOutMode::All:
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
animationState->fadeOut(animationConfig->fadeOutTime, animationConfig->pauseFadeOut);
|
||||
}
|
||||
break;
|
||||
|
||||
case AnimationFadeOutMode::None:
|
||||
case AnimationFadeOutMode::Single:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::init(Armature* armature)
|
||||
{
|
||||
if (_armature != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
_armature = armature;
|
||||
_animationConfig = BaseObject::borrowObject<AnimationConfig>();
|
||||
}
|
||||
|
||||
void Animation::advanceTime(float passedTime)
|
||||
{
|
||||
if (passedTime < 0.0f)
|
||||
{
|
||||
passedTime = -passedTime;
|
||||
}
|
||||
|
||||
if (_armature->inheritAnimation && _armature->_parent != nullptr) // Inherit parent animation timeScale.
|
||||
{
|
||||
_inheritTimeScale = _armature->_parent->_armature->getAnimation()->_inheritTimeScale * timeScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
_inheritTimeScale = timeScale;
|
||||
}
|
||||
|
||||
if (_inheritTimeScale != 1.0f)
|
||||
{
|
||||
passedTime *= _inheritTimeScale;
|
||||
}
|
||||
|
||||
const auto animationStateCount = _animationStates.size();
|
||||
if (animationStateCount == 1)
|
||||
{
|
||||
const auto animationState = _animationStates[0];
|
||||
if (animationState->_fadeState > 0 && animationState->_subFadeState > 0)
|
||||
{
|
||||
_armature->_dragonBones->bufferObject(animationState);
|
||||
_animationStates.clear();
|
||||
_lastAnimationState = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto animationData = animationState->_animationData;
|
||||
const auto cacheFrameRate = animationData->cacheFrameRate;
|
||||
if (_animationDirty && cacheFrameRate > 0.0f) // Update cachedFrameIndices.
|
||||
{
|
||||
_animationDirty = false;
|
||||
|
||||
for (const auto bone : _armature->getBones())
|
||||
{
|
||||
bone->_cachedFrameIndices = animationData->getBoneCachedFrameIndices(bone->getName());
|
||||
}
|
||||
|
||||
for (const auto slot : _armature->getSlots())
|
||||
{
|
||||
const auto rawDisplayDatas = slot->getRawDisplayDatas();
|
||||
if (rawDisplayDatas != nullptr && !(*rawDisplayDatas).empty())
|
||||
{
|
||||
const auto rawDsplayData = (*rawDisplayDatas)[0];
|
||||
if (rawDsplayData != nullptr)
|
||||
{
|
||||
if (rawDsplayData->parent == _armature->getArmatureData()->defaultSkin)
|
||||
{
|
||||
slot->_cachedFrameIndices = animationData->getSlotCachedFrameIndices(slot->getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slot->_cachedFrameIndices = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
animationState->advanceTime(passedTime, cacheFrameRate);
|
||||
}
|
||||
}
|
||||
else if (animationStateCount > 1)
|
||||
{
|
||||
for (std::size_t i = 0, r = 0; i < animationStateCount; ++i)
|
||||
{
|
||||
const auto animationState = _animationStates[i];
|
||||
if (animationState->_fadeState > 0 && animationState->_subFadeState > 0)
|
||||
{
|
||||
r++;
|
||||
_armature->_dragonBones->bufferObject(animationState);
|
||||
_animationDirty = true;
|
||||
if (_lastAnimationState == animationState)
|
||||
{
|
||||
_lastAnimationState = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r > 0)
|
||||
{
|
||||
_animationStates[i - r] = animationState;
|
||||
}
|
||||
|
||||
animationState->advanceTime(passedTime, 0.0f);
|
||||
}
|
||||
|
||||
if (i == animationStateCount - 1 && r > 0)
|
||||
{
|
||||
_animationStates.resize(animationStateCount - r);
|
||||
if (_lastAnimationState == nullptr && !_animationStates.empty())
|
||||
{
|
||||
_lastAnimationState = _animationStates[_animationStates.size() - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_armature->_cacheFrameIndex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_armature->_cacheFrameIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::reset()
|
||||
{
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
animationState->returnToPool();
|
||||
}
|
||||
|
||||
_animationDirty = false;
|
||||
_animationConfig->clear();
|
||||
_animationStates.clear();
|
||||
_lastAnimationState = nullptr;
|
||||
}
|
||||
|
||||
void Animation::stop(const std::string& animationName)
|
||||
{
|
||||
if (!animationName.empty())
|
||||
{
|
||||
const auto animationState = getState(animationName);
|
||||
if (animationState != nullptr)
|
||||
{
|
||||
animationState->stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto animationState : _animationStates) {
|
||||
animationState->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnimationState* Animation::playConfig(AnimationConfig* animationConfig)
|
||||
{
|
||||
const auto& animationName = animationConfig->animation;
|
||||
if (_animations.find(animationName) == _animations.end())
|
||||
{
|
||||
DRAGONBONES_ASSERT(
|
||||
false,
|
||||
"Non-existent animation.\n" +
|
||||
" DragonBones name: " + this->_armature->getArmatureData().parent->name +
|
||||
" Armature name: " + this->_armature->name +
|
||||
" Animation name: " + animationName
|
||||
);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto animationData = _animations[animationName];
|
||||
|
||||
if (animationConfig->fadeOutMode == AnimationFadeOutMode::Single)
|
||||
{
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
if (animationState->_animationData == animationData)
|
||||
{
|
||||
return animationState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (animationConfig->fadeInTime < 0.0f)
|
||||
{
|
||||
if (_animationStates.empty())
|
||||
{
|
||||
animationConfig->fadeInTime = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
animationConfig->fadeInTime = animationData->fadeInTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (animationConfig->fadeOutTime < 0.0f)
|
||||
{
|
||||
animationConfig->fadeOutTime = animationConfig->fadeInTime;
|
||||
}
|
||||
|
||||
if (animationConfig->timeScale <= -100.0f)
|
||||
{
|
||||
animationConfig->timeScale = 1.0f / animationData->scale;
|
||||
}
|
||||
|
||||
if (animationData->frameCount > 1)
|
||||
{
|
||||
if (animationConfig->position < 0.0f)
|
||||
{
|
||||
animationConfig->position = fmod(animationConfig->position, animationData->duration);
|
||||
animationConfig->position = animationData->duration - animationConfig->position;
|
||||
}
|
||||
else if (animationConfig->position == animationData->duration)
|
||||
{
|
||||
animationConfig->position -= 0.000001f; // Play a little time before end.
|
||||
}
|
||||
else if (animationConfig->position > animationData->duration)
|
||||
{
|
||||
animationConfig->position = fmod(animationConfig->position, animationData->duration);
|
||||
}
|
||||
|
||||
if (animationConfig->duration > 0.0f && animationConfig->position + animationConfig->duration > animationData->duration)
|
||||
{
|
||||
animationConfig->duration = animationData->duration - animationConfig->position;
|
||||
}
|
||||
|
||||
if (animationConfig->playTimes < 0)
|
||||
{
|
||||
animationConfig->playTimes = animationData->playTimes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
animationConfig->playTimes = 1;
|
||||
animationConfig->position = 0.0f;
|
||||
if (animationConfig->duration > 0.0f)
|
||||
{
|
||||
animationConfig->duration = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (animationConfig->duration == 0.0f)
|
||||
{
|
||||
animationConfig->duration = -1.0f;
|
||||
}
|
||||
|
||||
_fadeOut(animationConfig);
|
||||
|
||||
const auto animationState = BaseObject::borrowObject<AnimationState>();
|
||||
animationState->init(_armature, animationData, animationConfig);
|
||||
_animationDirty = true;
|
||||
_armature->_cacheFrameIndex = -1;
|
||||
|
||||
if (!_animationStates.empty())
|
||||
{
|
||||
auto added = false;
|
||||
for (std::size_t i = 0, l = _animationStates.size(); i < l; ++i)
|
||||
{
|
||||
if (animationState->layer > _animationStates[i]->layer)
|
||||
{
|
||||
added = true;
|
||||
auto parentInerator = std::find(_animationStates.begin(), _animationStates.end(), _animationStates[i]);
|
||||
_animationStates.insert(parentInerator, animationState);
|
||||
break;
|
||||
}
|
||||
else if (i != l - 1 && animationState->layer > _animationStates[i + 1]->layer)
|
||||
{
|
||||
added = true;
|
||||
auto parentInerator = std::find(_animationStates.begin(), _animationStates.end(), _animationStates[i]);
|
||||
_animationStates.insert(parentInerator + 1, animationState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added)
|
||||
{
|
||||
_animationStates.push_back(animationState);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_animationStates.push_back(animationState);
|
||||
}
|
||||
|
||||
// Child armature play same name animation.
|
||||
for (const auto slot : _armature->getSlots())
|
||||
{
|
||||
const auto childArmature = slot->getChildArmature();
|
||||
if (
|
||||
childArmature != nullptr && childArmature->inheritAnimation &&
|
||||
childArmature->getAnimation()->hasAnimation(animationName) &&
|
||||
childArmature->getAnimation()->getState(animationName) == nullptr
|
||||
)
|
||||
{
|
||||
childArmature->getAnimation()->fadeIn(animationName); //
|
||||
}
|
||||
}
|
||||
|
||||
if (animationConfig->fadeInTime <= 0.0f) // Blend animation state, update armature.
|
||||
{
|
||||
_armature->advanceTime(0.0f);
|
||||
}
|
||||
|
||||
_lastAnimationState = animationState;
|
||||
|
||||
return animationState;
|
||||
}
|
||||
|
||||
AnimationState* Animation::play(const std::string& animationName, int playTimes)
|
||||
{
|
||||
_animationConfig->clear();
|
||||
_animationConfig->resetToPose = true;
|
||||
_animationConfig->playTimes = playTimes;
|
||||
_animationConfig->fadeInTime = 0.0f;
|
||||
_animationConfig->animation = animationName;
|
||||
|
||||
if (!animationName.empty())
|
||||
{
|
||||
playConfig(_animationConfig);
|
||||
}
|
||||
else if (_lastAnimationState == nullptr)
|
||||
{
|
||||
const auto defaultAnimation = _armature->_armatureData->defaultAnimation;
|
||||
if (defaultAnimation != nullptr)
|
||||
{
|
||||
_animationConfig->animation = defaultAnimation->name;
|
||||
playConfig(_animationConfig);
|
||||
}
|
||||
}
|
||||
else if (!_lastAnimationState->isPlaying() && !_lastAnimationState->isCompleted())
|
||||
{
|
||||
_lastAnimationState->play();
|
||||
}
|
||||
else
|
||||
{
|
||||
_animationConfig->animation = _lastAnimationState->name;
|
||||
playConfig(_animationConfig);
|
||||
}
|
||||
|
||||
return _lastAnimationState;
|
||||
}
|
||||
#ifdef EGRET_WASM
|
||||
AnimationState* Animation::fadeIn(
|
||||
const std::string& animationName, float fadeInTime, int playTimes,
|
||||
int layer, const std::string& group, int fadeOutMode /*AnimationFadeOutMode*/
|
||||
#else
|
||||
AnimationState* Animation::fadeIn(
|
||||
const std::string& animationName, float fadeInTime, int playTimes,
|
||||
int layer, const std::string& group, AnimationFadeOutMode fadeOutMode
|
||||
#endif // EGRET_WASM
|
||||
)
|
||||
{
|
||||
_animationConfig->clear();
|
||||
_animationConfig->fadeOutMode = (AnimationFadeOutMode)fadeOutMode;
|
||||
_animationConfig->playTimes = playTimes;
|
||||
_animationConfig->layer = layer;
|
||||
_animationConfig->fadeInTime = fadeInTime;
|
||||
_animationConfig->animation = animationName;
|
||||
_animationConfig->group = group;
|
||||
|
||||
return playConfig(_animationConfig);
|
||||
}
|
||||
|
||||
AnimationState* Animation::gotoAndPlayByTime(const std::string& animationName, float time, int playTimes)
|
||||
{
|
||||
_animationConfig->clear();
|
||||
_animationConfig->resetToPose = true;
|
||||
_animationConfig->playTimes = playTimes;
|
||||
_animationConfig->position = time;
|
||||
_animationConfig->fadeInTime = 0.0f;
|
||||
_animationConfig->animation = animationName;
|
||||
|
||||
return playConfig(_animationConfig);
|
||||
}
|
||||
|
||||
AnimationState* Animation::gotoAndPlayByFrame(const std::string& animationName, unsigned frame, int playTimes)
|
||||
{
|
||||
_animationConfig->clear();
|
||||
_animationConfig->resetToPose = true;
|
||||
_animationConfig->playTimes = playTimes;
|
||||
_animationConfig->fadeInTime = 0.0f;
|
||||
_animationConfig->animation = animationName;
|
||||
|
||||
const auto animationData = mapFind(_animations, animationName);
|
||||
if (animationData != nullptr)
|
||||
{
|
||||
_animationConfig->position = animationData->duration * frame / animationData->frameCount;
|
||||
}
|
||||
|
||||
return playConfig(_animationConfig);
|
||||
}
|
||||
|
||||
AnimationState* Animation::gotoAndPlayByProgress(const std::string& animationName, float progress, int playTimes)
|
||||
{
|
||||
_animationConfig->clear();
|
||||
_animationConfig->resetToPose = true;
|
||||
_animationConfig->playTimes = playTimes;
|
||||
_animationConfig->fadeInTime = 0.0f;
|
||||
_animationConfig->animation = animationName;
|
||||
|
||||
const auto animationData = mapFind(_animations, animationName);
|
||||
if (animationData != nullptr) {
|
||||
_animationConfig->position = animationData->duration * (progress > 0.0f ? progress : 0.0f);
|
||||
}
|
||||
|
||||
return playConfig(_animationConfig);
|
||||
}
|
||||
|
||||
AnimationState* Animation::gotoAndStopByTime(const std::string& animationName, float time)
|
||||
{
|
||||
const auto animationState = gotoAndPlayByTime(animationName, time, 1);
|
||||
if (animationState != nullptr)
|
||||
{
|
||||
animationState->stop();
|
||||
}
|
||||
|
||||
return animationState;
|
||||
}
|
||||
|
||||
AnimationState* Animation::gotoAndStopByFrame(const std::string& animationName, unsigned frame)
|
||||
{
|
||||
const auto animationState = gotoAndPlayByFrame(animationName, frame, 1);
|
||||
if (animationState != nullptr)
|
||||
{
|
||||
animationState->stop();
|
||||
}
|
||||
|
||||
return animationState;
|
||||
}
|
||||
|
||||
AnimationState* Animation::gotoAndStopByProgress(const std::string& animationName, float progress)
|
||||
{
|
||||
const auto animationState = gotoAndPlayByProgress(animationName, progress, 1);
|
||||
if (animationState != nullptr)
|
||||
{
|
||||
animationState->stop();
|
||||
}
|
||||
|
||||
return animationState;
|
||||
}
|
||||
|
||||
AnimationState* Animation::getState(const std::string& animationName) const
|
||||
{
|
||||
int i = _animationStates.size();
|
||||
while (i--)
|
||||
{
|
||||
const auto animationState = _animationStates[i];
|
||||
if (animationState->name == animationName)
|
||||
{
|
||||
return animationState;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Animation::hasAnimation(const std::string& animationName) const
|
||||
{
|
||||
return _animations.find(animationName) != _animations.end();
|
||||
}
|
||||
|
||||
bool Animation::isPlaying() const
|
||||
{
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
if (animationState->isPlaying())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Animation::isCompleted() const
|
||||
{
|
||||
for (const auto animationState : _animationStates)
|
||||
{
|
||||
if (!animationState->isCompleted())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !_animationStates.empty();
|
||||
}
|
||||
|
||||
const std::string& Animation::getLastAnimationName() const
|
||||
{
|
||||
if (_lastAnimationState != nullptr)
|
||||
{
|
||||
return _lastAnimationState->name;
|
||||
}
|
||||
|
||||
static const std::string DEFAULT_NAME = "";
|
||||
return DEFAULT_NAME;
|
||||
}
|
||||
|
||||
void Animation::setAnimations(const std::map<std::string, AnimationData*>& value)
|
||||
{
|
||||
if (_animations == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_animationNames.clear();
|
||||
_animations.clear();
|
||||
|
||||
for (const auto& pair : value)
|
||||
{
|
||||
_animationNames.push_back(pair.first);
|
||||
_animations[pair.first] = pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationConfig* Animation::getAnimationConfig() const
|
||||
{
|
||||
_animationConfig->clear();
|
||||
return _animationConfig;
|
||||
}
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
478
cocos2d-x/cocos/editor-support/dragonbones/animation/Animation.h
Normal file
478
cocos2d-x/cocos/editor-support/dragonbones/animation/Animation.h
Normal file
@@ -0,0 +1,478 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2012-2018 DragonBones team and other contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DRAGONBONES_ANIMATION_H
|
||||
#define DRAGONBONES_ANIMATION_H
|
||||
|
||||
#include "../core/BaseObject.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
/**
|
||||
* - The animation player is used to play the animation data and manage the animation states.
|
||||
* @see dragonBones.AnimationData
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 动画播放器用来播放动画数据和管理动画状态。
|
||||
* @see dragonBones.AnimationData
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
class Animation final : public BaseObject
|
||||
{
|
||||
BIND_CLASS_TYPE_B(Animation);
|
||||
|
||||
public:
|
||||
/**
|
||||
* - The play speed of all animations. [0: Stop, (0~1): Slow, 1: Normal, (1~N): Fast]
|
||||
* @default 1.0
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 所有动画的播放速度。 [0: 停止播放, (0~1): 慢速播放, 1: 正常播放, (1~N): 快速播放]
|
||||
* @default 1.0
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
float timeScale;
|
||||
|
||||
private:
|
||||
bool _animationDirty;
|
||||
float _inheritTimeScale;
|
||||
std::vector<std::string> _animationNames;
|
||||
std::vector<AnimationState*> _animationStates;
|
||||
std::map<std::string, AnimationData*> _animations;
|
||||
Armature* _armature;
|
||||
AnimationConfig* _animationConfig;
|
||||
AnimationState* _lastAnimationState;
|
||||
|
||||
public:
|
||||
Animation() :
|
||||
_animationConfig(nullptr)
|
||||
{
|
||||
_onClear();
|
||||
}
|
||||
~Animation()
|
||||
{
|
||||
_onClear();
|
||||
}
|
||||
|
||||
private:
|
||||
void _fadeOut(AnimationConfig* animationConfig);
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void init(Armature* armature);
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void advanceTime(float passedTime);
|
||||
/**
|
||||
* - Clear all animations states.
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 清除所有的动画状态。
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
void reset();
|
||||
/**
|
||||
* - Pause a specific animation state.
|
||||
* @param animationName - The name of animation state. (If not set, it will pause all animations)
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 暂停指定动画状态的播放。
|
||||
* @param animationName - 动画状态名称。 (如果未设置,则暂停所有动画)
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void stop(const std::string& animationName);
|
||||
/**
|
||||
* - Play animation with a specific animation config.
|
||||
* The API is still in the experimental phase and may encounter bugs or stability or compatibility issues when used.
|
||||
* @param animationConfig - The animation config.
|
||||
* @returns The playing animation state.
|
||||
* @see dragonBones.AnimationConfig
|
||||
* @beta
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 通过指定的动画配置来播放动画。
|
||||
* 该 API 仍在实验阶段,使用时可能遭遇 bug 或稳定性或兼容性问题。
|
||||
* @param animationConfig - 动画配置。
|
||||
* @returns 播放的动画状态。
|
||||
* @see dragonBones.AnimationConfig
|
||||
* @beta
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* playConfig(AnimationConfig* animationConfig);
|
||||
/**
|
||||
* - Play a specific animation.
|
||||
* @param animationName - The name of animation data. (If not set, The default animation will be played, or resume the animation playing from pause status, or replay the last playing animation)
|
||||
* @param playTimes - Playing repeat times. [-1: Use default value of the animation data, 0: No end loop playing, [1~N]: Repeat N times] (default: -1)
|
||||
* @returns The playing animation state.
|
||||
* @example
|
||||
* TypeScript style, for reference only.
|
||||
* <pre>
|
||||
* armature.animation.play("walk");
|
||||
* </pre>
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 播放指定动画。
|
||||
* @param animationName - 动画数据名称。 (如果未设置,则播放默认动画,或将暂停状态切换为播放状态,或重新播放之前播放的动画)
|
||||
* @param playTimes - 循环播放次数。 [-1: 使用动画数据默认值, 0: 无限循环播放, [1~N]: 循环播放 N 次] (默认: -1)
|
||||
* @returns 播放的动画状态。
|
||||
* @example
|
||||
* TypeScript 风格,仅供参考。
|
||||
* <pre>
|
||||
* armature.animation.play("walk");
|
||||
* </pre>
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* play(const std::string& animationName = "", int playTimes = -1);
|
||||
/**
|
||||
* - Fade in a specific animation.
|
||||
* @param animationName - The name of animation data.
|
||||
* @param fadeInTime - The fade in time. [-1: Use the default value of animation data, [0~N]: The fade in time (In seconds)] (Default: -1)
|
||||
* @param playTimes - playing repeat times. [-1: Use the default value of animation data, 0: No end loop playing, [1~N]: Repeat N times] (Default: -1)
|
||||
* @param layer - The blending layer, the animation states in high level layer will get the blending weights with high priority, when the total blending weights are more than 1.0, there will be no more weights can be allocated to the other animation states. (Default: 0)
|
||||
* @param group - The blending group name, it is typically used to specify the substitution of multiple animation states blending. (Default: null)
|
||||
* @param fadeOutMode - The fade out mode, which is typically used to specify alternate mode of multiple animation states blending. (Default: AnimationFadeOutMode.SameLayerAndGroup)
|
||||
* @returns The playing animation state.
|
||||
* @example
|
||||
* TypeScript style, for reference only.
|
||||
* <pre>
|
||||
* armature.animation.fadeIn("walk", 0.3, 0, 0, "normalGroup").resetToPose = false;
|
||||
* armature.animation.fadeIn("attack", 0.3, 1, 0, "attackGroup").resetToPose = false;
|
||||
* </pre>
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 淡入播放指定的动画。
|
||||
* @param animationName - 动画数据名称。
|
||||
* @param fadeInTime - 淡入时间。 [-1: 使用动画数据默认值, [0~N]: 淡入时间 (以秒为单位)] (默认: -1)
|
||||
* @param playTimes - 播放次数。 [-1: 使用动画数据默认值, 0: 无限循环播放, [1~N]: 循环播放 N 次] (默认: -1)
|
||||
* @param layer - 混合图层,图层高的动画状态会优先获取混合权重,当混合权重分配总和超过 1.0 时,剩余的动画状态将不能再获得权重分配。 (默认: 0)
|
||||
* @param group - 混合组名称,该属性通常用来指定多个动画状态混合时的相互替换关系。 (默认: null)
|
||||
* @param fadeOutMode - 淡出模式,该属性通常用来指定多个动画状态混合时的相互替换模式。 (默认: AnimationFadeOutMode.SameLayerAndGroup)
|
||||
* @returns 播放的动画状态。
|
||||
* @example
|
||||
* TypeScript 风格,仅供参考。
|
||||
* <pre>
|
||||
* armature.animation.fadeIn("walk", 0.3, 0, 0, "normalGroup").resetToPose = false;
|
||||
* armature.animation.fadeIn("attack", 0.3, 1, 0, "attackGroup").resetToPose = false;
|
||||
* </pre>
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* fadeIn(
|
||||
const std::string& animationName, float fadeInTime = -1.f, int playTimes = -1,
|
||||
int layer = 0, const std::string& group = "", AnimationFadeOutMode fadeOutMode = AnimationFadeOutMode::SameLayerAndGroup
|
||||
);
|
||||
/**
|
||||
* - Play a specific animation from the specific time.
|
||||
* @param animationName - The name of animation data.
|
||||
* @param time - The start time point of playing. (In seconds)
|
||||
* @param playTimes - Playing repeat times. [-1: Use the default value of animation data, 0: No end loop playing, [1~N]: Repeat N times] (Default: -1)
|
||||
* @returns The played animation state.
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 从指定时间开始播放指定的动画。
|
||||
* @param animationName - 动画数据名称。
|
||||
* @param time - 播放开始的时间。 (以秒为单位)
|
||||
* @param playTimes - 循环播放次数。 [-1: 使用动画数据默认值, 0: 无限循环播放, [1~N]: 循环播放 N 次] (默认: -1)
|
||||
* @returns 播放的动画状态。
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* gotoAndPlayByTime(const std::string& animationName, float time = 0.f, int playTimes = -1);
|
||||
/**
|
||||
* - Play a specific animation from the specific frame.
|
||||
* @param animationName - The name of animation data.
|
||||
* @param frame - The start frame of playing.
|
||||
* @param playTimes - Playing repeat times. [-1: Use the default value of animation data, 0: No end loop playing, [1~N]: Repeat N times] (Default: -1)
|
||||
* @returns The played animation state.
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 从指定帧开始播放指定的动画。
|
||||
* @param animationName - 动画数据名称。
|
||||
* @param frame - 播放开始的帧数。
|
||||
* @param playTimes - 播放次数。 [-1: 使用动画数据默认值, 0: 无限循环播放, [1~N]: 循环播放 N 次] (默认: -1)
|
||||
* @returns 播放的动画状态。
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* gotoAndPlayByFrame(const std::string& animationName, unsigned frame = 0, int playTimes = -1);
|
||||
/**
|
||||
* - Play a specific animation from the specific progress.
|
||||
* @param animationName - The name of animation data.
|
||||
* @param progress - The start progress value of playing.
|
||||
* @param playTimes - Playing repeat times. [-1: Use the default value of animation data, 0: No end loop playing, [1~N]: Repeat N times] (Default: -1)
|
||||
* @returns The played animation state.
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 从指定进度开始播放指定的动画。
|
||||
* @param animationName - 动画数据名称。
|
||||
* @param progress - 开始播放的进度。
|
||||
* @param playTimes - 播放次数。 [-1: 使用动画数据默认值, 0: 无限循环播放, [1~N]: 循环播放 N 次] (默认: -1)
|
||||
* @returns 播放的动画状态。
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* gotoAndPlayByProgress(const std::string& animationName, float progress = 0.f, int playTimes = -1);
|
||||
/**
|
||||
* - Stop a specific animation at the specific time.
|
||||
* @param animationName - The name of animation data.
|
||||
* @param time - The stop time. (In seconds)
|
||||
* @returns The played animation state.
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 在指定时间停止指定动画播放
|
||||
* @param animationName - 动画数据名称。
|
||||
* @param time - 停止的时间。 (以秒为单位)
|
||||
* @returns 播放的动画状态。
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* gotoAndStopByTime(const std::string& animationName, float time = 0.f);
|
||||
/**
|
||||
* - Stop a specific animation at the specific frame.
|
||||
* @param animationName - The name of animation data.
|
||||
* @param frame - The stop frame.
|
||||
* @returns The played animation state.
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 在指定帧停止指定动画的播放
|
||||
* @param animationName - 动画数据名称。
|
||||
* @param frame - 停止的帧数。
|
||||
* @returns 播放的动画状态。
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* gotoAndStopByFrame(const std::string& animationName, unsigned frame = 0);
|
||||
/**
|
||||
* - Stop a specific animation at the specific progress.
|
||||
* @param animationName - The name of animation data.
|
||||
* @param progress - The stop progress value.
|
||||
* @returns The played animation state.
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 在指定的进度停止指定的动画播放。
|
||||
* @param animationName - 动画数据名称。
|
||||
* @param progress - 停止进度。
|
||||
* @returns 播放的动画状态。
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* gotoAndStopByProgress(const std::string& animationName, float progress = 0.f);
|
||||
/**
|
||||
* - Get a specific animation state.
|
||||
* @param animationName - The name of animation state.
|
||||
* @example
|
||||
* TypeScript style, for reference only.
|
||||
* <pre>
|
||||
* armature.animation.play("walk");
|
||||
* let walkState = armature.animation.getState("walk");
|
||||
* walkState.timeScale = 0.5;
|
||||
* </pre>
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 获取指定的动画状态
|
||||
* @param animationName - 动画状态名称。
|
||||
* @example
|
||||
* TypeScript 风格,仅供参考。
|
||||
* <pre>
|
||||
* armature.animation.play("walk");
|
||||
* let walkState = armature.animation.getState("walk");
|
||||
* walkState.timeScale = 0.5;
|
||||
* </pre>
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationState* getState(const std::string& animationName) const;
|
||||
/**
|
||||
* - Check whether a specific animation data is included.
|
||||
* @param animationName - The name of animation data.
|
||||
* @see dragonBones.AnimationData
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 检查是否包含指定的动画数据
|
||||
* @param animationName - 动画数据名称。
|
||||
* @see dragonBones.AnimationData
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool hasAnimation(const std::string& animationName) const;
|
||||
/**
|
||||
* - Get all the animation states.
|
||||
* @version DragonBones 5.1
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 获取所有的动画状态
|
||||
* @version DragonBones 5.1
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline const std::vector<AnimationState*>& getStates() const
|
||||
{
|
||||
return _animationStates;
|
||||
}
|
||||
/**
|
||||
* - Check whether there is an animation state is playing
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 检查是否有动画状态正在播放
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool isPlaying() const;
|
||||
/**
|
||||
* - Check whether all the animation states' playing were finished.
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 检查是否所有的动画状态均已播放完毕。
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool isCompleted() const;
|
||||
/**
|
||||
* - The name of the last playing animation state.
|
||||
* @see #lastAnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 上一个播放的动画状态名称
|
||||
* @see #lastAnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
const std::string& getLastAnimationName() const;
|
||||
/**
|
||||
* - The name of all animation data
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 所有动画数据的名称
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline const std::vector<std::string>& getAnimationNames() const
|
||||
{
|
||||
return _animationNames;
|
||||
}
|
||||
/**
|
||||
* - All animation data.
|
||||
* @version DragonBones 4.5
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 所有的动画数据。
|
||||
* @version DragonBones 4.5
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline const std::map<std::string, AnimationData*>& getAnimations() const
|
||||
{
|
||||
return _animations;
|
||||
}
|
||||
void setAnimations(const std::map<std::string, AnimationData*>& value);
|
||||
/**
|
||||
* - An AnimationConfig instance that can be used quickly.
|
||||
* @see dragonBones.AnimationConfig
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 一个可以快速使用的动画配置实例。
|
||||
* @see dragonBones.AnimationConfig
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
AnimationConfig* getAnimationConfig() const;
|
||||
/**
|
||||
* - The last playing animation state
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 上一个播放的动画状态
|
||||
* @see dragonBones.AnimationState
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline AnimationState* getLastAnimationState() const
|
||||
{
|
||||
return _lastAnimationState;
|
||||
}
|
||||
};
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
||||
#endif // DRAGONBONES_ANIMATION_H
|
@@ -0,0 +1,952 @@
|
||||
#include "AnimationState.h"
|
||||
#include "WorldClock.h"
|
||||
#include "../model/DisplayData.h"
|
||||
#include "../model/AnimationConfig.h"
|
||||
#include "../model/AnimationData.h"
|
||||
#include "../armature/Armature.h"
|
||||
#include "../armature/Bone.h"
|
||||
#include "../armature/Slot.h"
|
||||
#include "../armature/Constraint.h"
|
||||
#include "../event/EventObject.h"
|
||||
#include "../event/IEventDispatcher.h"
|
||||
#include "TimelineState.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
|
||||
void AnimationState::_onClear()
|
||||
{
|
||||
for (const auto timeline : _boneTimelines)
|
||||
{
|
||||
timeline->returnToPool();
|
||||
}
|
||||
|
||||
for (const auto timeline : _slotTimelines)
|
||||
{
|
||||
timeline->returnToPool();
|
||||
}
|
||||
|
||||
for (const auto timeline : _constraintTimelines)
|
||||
{
|
||||
timeline->returnToPool();
|
||||
}
|
||||
|
||||
for (const auto& pair : _bonePoses)
|
||||
{
|
||||
pair.second->returnToPool();
|
||||
}
|
||||
|
||||
if (_actionTimeline != nullptr) {
|
||||
_actionTimeline->returnToPool();
|
||||
}
|
||||
|
||||
if (_zOrderTimeline != nullptr) {
|
||||
_zOrderTimeline->returnToPool();
|
||||
}
|
||||
|
||||
actionEnabled = false;
|
||||
additiveBlending = false;
|
||||
displayControl = false;
|
||||
resetToPose = false;
|
||||
playTimes = 1;
|
||||
layer = 0;
|
||||
timeScale = 1.0f;
|
||||
weight = 1.0f;
|
||||
autoFadeOutTime = 0.0f;
|
||||
fadeTotalTime = 0.0f;
|
||||
name = "";
|
||||
group = "";
|
||||
|
||||
_timelineDirty = 2;
|
||||
_playheadState = 0;
|
||||
_fadeState = -1;
|
||||
_subFadeState = -1;
|
||||
_position = 0.0f;
|
||||
_duration = 0.0f;
|
||||
_fadeTime = 0.0f;
|
||||
_time = 0.0f;
|
||||
_fadeProgress = 0.0f;
|
||||
_weightResult = 0.0f;
|
||||
_boneMask.clear();
|
||||
_boneTimelines.clear();
|
||||
_slotTimelines.clear();
|
||||
_constraintTimelines.clear();
|
||||
_poseTimelines.clear();
|
||||
_bonePoses.clear();
|
||||
_animationData = nullptr;
|
||||
_armature = nullptr;
|
||||
_actionTimeline = nullptr;
|
||||
_zOrderTimeline = nullptr;
|
||||
}
|
||||
|
||||
void AnimationState::_updateTimelines()
|
||||
{
|
||||
{ // Update constraint timelines.
|
||||
std::map<std::string, std::vector<ConstraintTimelineState*>> constraintTimelines;
|
||||
for (const auto timeline : _constraintTimelines) // Create constraint timelines map.
|
||||
{
|
||||
constraintTimelines[timeline->constraint->getName()].push_back(timeline);
|
||||
}
|
||||
|
||||
for (const auto constraint : _armature->_constraints)
|
||||
{
|
||||
const auto& timelineName = constraint->getName();
|
||||
const auto timelineDatas = _animationData->getConstraintTimelines(timelineName);
|
||||
const auto iterator = constraintTimelines.find(timelineName);
|
||||
|
||||
if (iterator != constraintTimelines.end()) // Remove constraint timeline from map.
|
||||
{
|
||||
constraintTimelines.erase(iterator);
|
||||
}
|
||||
else // Create new constraint timeline.
|
||||
{
|
||||
if (timelineDatas != nullptr)
|
||||
{
|
||||
for (const auto timelineData : *timelineDatas)
|
||||
{
|
||||
switch (timelineData->type)
|
||||
{
|
||||
case TimelineType::IKConstraint:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<IKConstraintTimelineState>();
|
||||
timeline->constraint = constraint;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_constraintTimelines.push_back(timeline);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resetToPose) // Pose timeline.
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<IKConstraintTimelineState>();
|
||||
timeline->constraint = constraint;
|
||||
timeline->init(_armature, this, nullptr);
|
||||
_constraintTimelines.push_back(timeline);
|
||||
_poseTimelines.push_back(std::make_pair(timeline, BaseTimelineType::Constraint));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationState::_updateBoneAndSlotTimelines()
|
||||
{
|
||||
{ // Update bone timelines.
|
||||
std::map<std::string, std::vector<BoneTimelineState*>> boneTimelines;
|
||||
for (const auto timeline : _boneTimelines) // Create bone timelines map.
|
||||
{
|
||||
boneTimelines[timeline->bone->getName()].push_back(timeline);
|
||||
}
|
||||
|
||||
for (const auto bone : _armature->getBones())
|
||||
{
|
||||
const auto& timelineName = bone->getName();
|
||||
if (!containsBoneMask(timelineName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto timelineDatas = _animationData->getBoneTimelines(timelineName);
|
||||
const auto iterator = boneTimelines.find(timelineName);
|
||||
|
||||
if (iterator != boneTimelines.end()) // Remove bone timeline from map.
|
||||
{
|
||||
boneTimelines.erase(iterator);
|
||||
}
|
||||
else // Create new bone timeline.
|
||||
{
|
||||
const auto bonePose = _bonePoses.find(timelineName) != _bonePoses.end() ? _bonePoses[timelineName] : (_bonePoses[timelineName] = BaseObject::borrowObject<BonePose>());
|
||||
|
||||
if (timelineDatas != nullptr)
|
||||
{
|
||||
for (const auto timelineData : *timelineDatas)
|
||||
{
|
||||
switch (timelineData->type)
|
||||
{
|
||||
case TimelineType::BoneAll:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<BoneAllTimelineState>();
|
||||
timeline->bone = bone;
|
||||
timeline->bonePose = bonePose;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_boneTimelines.push_back(timeline);
|
||||
break;
|
||||
}
|
||||
|
||||
case TimelineType::BoneTranslate:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<BoneTranslateTimelineState>();
|
||||
timeline->bone = bone;
|
||||
timeline->bonePose = bonePose;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_boneTimelines.push_back(timeline);
|
||||
break;
|
||||
}
|
||||
|
||||
case TimelineType::BoneRotate:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<BoneRotateTimelineState>();
|
||||
timeline->bone = bone;
|
||||
timeline->bonePose = bonePose;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_boneTimelines.push_back(timeline);
|
||||
break;
|
||||
}
|
||||
|
||||
case TimelineType::BoneScale:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<BoneScaleTimelineState>();
|
||||
timeline->bone = bone;
|
||||
timeline->bonePose = bonePose;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_boneTimelines.push_back(timeline);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resetToPose) // Pose timeline.
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<BoneAllTimelineState>();
|
||||
timeline->bone = bone;
|
||||
timeline->bonePose = bonePose;
|
||||
timeline->init(_armature, this, nullptr);
|
||||
_boneTimelines.push_back(timeline);
|
||||
_poseTimelines.push_back(std::make_pair(timeline, BaseTimelineType::Bone));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& pair : boneTimelines) // Remove bone timelines.
|
||||
{
|
||||
for (const auto timeline : pair.second)
|
||||
{
|
||||
_boneTimelines.erase(std::find(_boneTimelines.begin(), _boneTimelines.end(), timeline));
|
||||
timeline->returnToPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // Update slot timelines.
|
||||
std::map<std::string, std::vector<SlotTimelineState*>> slotTimelines;
|
||||
std::vector<unsigned> ffdFlags;
|
||||
for (const auto timeline : _slotTimelines) // Create slot timelines map.
|
||||
{
|
||||
slotTimelines[timeline->slot->getName()].push_back(timeline);
|
||||
}
|
||||
|
||||
for (const auto slot : _armature->getSlots())
|
||||
{
|
||||
const auto& boneName = slot->getParent()->getName();
|
||||
if (!containsBoneMask(boneName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& timelineName = slot->getName();
|
||||
const auto timelineDatas = _animationData->getSlotTimelines(timelineName);
|
||||
const auto iterator = slotTimelines.find(timelineName);
|
||||
|
||||
if (iterator != slotTimelines.end()) // Remove slot timeline from map.
|
||||
{
|
||||
slotTimelines.erase(iterator);
|
||||
}
|
||||
else // Create new slot timeline.
|
||||
{
|
||||
auto displayIndexFlag = false;
|
||||
auto colorFlag = false;
|
||||
ffdFlags.clear();
|
||||
|
||||
if (timelineDatas != nullptr)
|
||||
{
|
||||
for (const auto timelineData : *timelineDatas)
|
||||
{
|
||||
switch (timelineData->type)
|
||||
{
|
||||
case TimelineType::SlotDisplay:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<SlotDislayTimelineState>();
|
||||
timeline->slot = slot;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_slotTimelines.push_back(timeline);
|
||||
displayIndexFlag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case TimelineType::SlotColor:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<SlotColorTimelineState>();
|
||||
timeline->slot = slot;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_slotTimelines.push_back(timeline);
|
||||
colorFlag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case TimelineType::SlotDeform:
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<DeformTimelineState>();
|
||||
timeline->slot = slot;
|
||||
timeline->init(_armature, this, timelineData);
|
||||
_slotTimelines.push_back(timeline);
|
||||
ffdFlags.push_back(timeline->vertexOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resetToPose) // Pose timeline.
|
||||
{
|
||||
if (!displayIndexFlag)
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<SlotDislayTimelineState>();
|
||||
timeline->slot = slot;
|
||||
timeline->init(_armature, this, nullptr);
|
||||
_slotTimelines.push_back(timeline);
|
||||
_poseTimelines.push_back(std::make_pair(timeline, BaseTimelineType::Slot));
|
||||
}
|
||||
|
||||
if (!colorFlag)
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<SlotColorTimelineState>();
|
||||
timeline->slot = slot;
|
||||
timeline->init(_armature, this, nullptr);
|
||||
_slotTimelines.push_back(timeline);
|
||||
_poseTimelines.push_back(std::make_pair(timeline, BaseTimelineType::Slot));
|
||||
}
|
||||
|
||||
if (slot->getRawDisplayDatas() != nullptr)
|
||||
{
|
||||
for (const auto displayData : *(slot->getRawDisplayDatas()))
|
||||
{
|
||||
if (displayData != nullptr && displayData->type == DisplayType::Mesh)
|
||||
{
|
||||
const auto meshOffset = static_cast<MeshDisplayData*>(displayData)->vertices.offset;
|
||||
if (std::find(ffdFlags.cbegin(), ffdFlags.cend(), meshOffset) == ffdFlags.cend())
|
||||
{
|
||||
const auto timeline = BaseObject::borrowObject<DeformTimelineState>();
|
||||
timeline->vertexOffset = meshOffset;
|
||||
timeline->slot = slot;
|
||||
timeline->init(_armature, this, nullptr);
|
||||
_slotTimelines.push_back(timeline);
|
||||
_poseTimelines.push_back(std::make_pair(timeline, BaseTimelineType::Slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& pair : slotTimelines) // Remove slot timelines.
|
||||
{
|
||||
for (const auto timeline : pair.second)
|
||||
{
|
||||
_slotTimelines.erase(std::find(_slotTimelines.begin(), _slotTimelines.end(), timeline));
|
||||
timeline->returnToPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationState::_advanceFadeTime(float passedTime)
|
||||
{
|
||||
const auto isFadeOut = _fadeState > 0;
|
||||
|
||||
if (_subFadeState < 0)
|
||||
{
|
||||
_subFadeState = 0;
|
||||
|
||||
const auto eventType = isFadeOut ? EventObject::FADE_OUT : EventObject::FADE_IN;
|
||||
if (_armature->getProxy()->hasDBEventListener(eventType))
|
||||
{
|
||||
const auto eventObject = BaseObject::borrowObject<EventObject>();
|
||||
eventObject->type = eventType;
|
||||
eventObject->armature = _armature;
|
||||
eventObject->animationState = this;
|
||||
_armature->_dragonBones->bufferEvent(eventObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (passedTime < 0.0f)
|
||||
{
|
||||
passedTime = -passedTime;
|
||||
}
|
||||
|
||||
_fadeTime += passedTime;
|
||||
|
||||
if (_fadeTime >= fadeTotalTime)
|
||||
{
|
||||
_subFadeState = 1;
|
||||
_fadeProgress = isFadeOut ? 0.0f : 1.0f;
|
||||
}
|
||||
else if (_fadeTime > 0.0f)
|
||||
{
|
||||
_fadeProgress = isFadeOut ? (1.0f - _fadeTime / fadeTotalTime) : (_fadeTime / fadeTotalTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fadeProgress = isFadeOut ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
if (_subFadeState > 0)
|
||||
{
|
||||
if (!isFadeOut)
|
||||
{
|
||||
_playheadState |= 1; // x1
|
||||
_fadeState = 0;
|
||||
}
|
||||
|
||||
const auto eventType = isFadeOut ? EventObject::FADE_OUT_COMPLETE : EventObject::FADE_IN_COMPLETE;
|
||||
if (_armature->getProxy()->hasDBEventListener(eventType))
|
||||
{
|
||||
const auto eventObject = BaseObject::borrowObject<EventObject>();
|
||||
eventObject->type = eventType;
|
||||
eventObject->armature = _armature;
|
||||
eventObject->animationState = this;
|
||||
_armature->_dragonBones->bufferEvent(eventObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationState::init(Armature* parmature, AnimationData* panimationData, AnimationConfig* animationConfig)
|
||||
{
|
||||
if (_armature != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
_armature = parmature;
|
||||
_animationData = panimationData;
|
||||
//
|
||||
resetToPose = animationConfig->resetToPose;
|
||||
additiveBlending = animationConfig->additiveBlending;
|
||||
displayControl = animationConfig->displayControl;
|
||||
actionEnabled = animationConfig->actionEnabled;
|
||||
layer = animationConfig->layer;
|
||||
playTimes = animationConfig->playTimes;
|
||||
timeScale = animationConfig->timeScale;
|
||||
fadeTotalTime = animationConfig->fadeInTime;
|
||||
autoFadeOutTime = animationConfig->autoFadeOutTime;
|
||||
weight = animationConfig->weight;
|
||||
name = !animationConfig->name.empty() ? animationConfig->name : animationConfig->animation;
|
||||
group = animationConfig->group;
|
||||
|
||||
if (animationConfig->pauseFadeIn)
|
||||
{
|
||||
_playheadState = 2; // 10
|
||||
}
|
||||
else
|
||||
{
|
||||
_playheadState = 3; // 11
|
||||
}
|
||||
|
||||
if (animationConfig->duration < 0.0f)
|
||||
{
|
||||
_position = 0.0f;
|
||||
_duration = _animationData->duration;
|
||||
|
||||
if (animationConfig->position != 0.0f)
|
||||
{
|
||||
if (timeScale >= 0.0f)
|
||||
{
|
||||
_time = animationConfig->position;
|
||||
}
|
||||
else
|
||||
{
|
||||
_time = animationConfig->position - _duration;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_time = 0.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_position = animationConfig->position;
|
||||
_duration = animationConfig->duration;
|
||||
_time = 0.0f;
|
||||
}
|
||||
|
||||
if (timeScale < 0.0f && _time == 0.0f)
|
||||
{
|
||||
_time = -0.000001f; // Can not cross last frame event.
|
||||
}
|
||||
|
||||
if (fadeTotalTime <= 0.0f)
|
||||
{
|
||||
_fadeProgress = 0.999999f;
|
||||
}
|
||||
|
||||
if (!animationConfig->boneMask.empty())
|
||||
{
|
||||
_boneMask.resize(animationConfig->boneMask.size());
|
||||
for (std::size_t i = 0, l = _boneMask.size(); i < l; ++i) {
|
||||
_boneMask[i] = animationConfig->boneMask[i];
|
||||
}
|
||||
}
|
||||
|
||||
_actionTimeline = BaseObject::borrowObject<ActionTimelineState>();
|
||||
_actionTimeline->init(_armature, this, _animationData->actionTimeline); //
|
||||
_actionTimeline->currentTime = _time;
|
||||
if (_actionTimeline->currentTime < 0.0f)
|
||||
{
|
||||
_actionTimeline->currentTime = _duration - _actionTimeline->currentTime;
|
||||
}
|
||||
|
||||
if (_animationData->zOrderTimeline != nullptr)
|
||||
{
|
||||
_zOrderTimeline = BaseObject::borrowObject<ZOrderTimelineState>();
|
||||
_zOrderTimeline->init(_armature, this, _animationData->zOrderTimeline);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationState::advanceTime(float passedTime, float cacheFrameRate)
|
||||
{
|
||||
// Update fade time.
|
||||
if (_fadeState != 0 || _subFadeState != 0)
|
||||
{
|
||||
_advanceFadeTime(passedTime);
|
||||
}
|
||||
|
||||
// Update time.
|
||||
if (_playheadState == 3) // 11
|
||||
{
|
||||
if (timeScale != 1.0f)
|
||||
{
|
||||
passedTime *= timeScale;
|
||||
}
|
||||
|
||||
_time += passedTime;
|
||||
}
|
||||
|
||||
if (_timelineDirty != 0)
|
||||
{
|
||||
if (_timelineDirty == 2)
|
||||
{
|
||||
_updateTimelines();
|
||||
}
|
||||
|
||||
_timelineDirty = 0;
|
||||
_updateBoneAndSlotTimelines();
|
||||
}
|
||||
|
||||
if (weight == 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto isCacheEnabled = _fadeState == 0 && cacheFrameRate > 0.0f;
|
||||
auto isUpdateTimeline = true;
|
||||
auto isUpdateBoneTimeline = true;
|
||||
auto time = _time;
|
||||
_weightResult = weight * _fadeProgress;
|
||||
|
||||
if (_actionTimeline->playState <= 0)
|
||||
{
|
||||
_actionTimeline->update(time); // Update main timeline.
|
||||
}
|
||||
|
||||
if (isCacheEnabled) // Cache time internval.
|
||||
{
|
||||
const auto internval = cacheFrameRate * 2.0f;
|
||||
_actionTimeline->currentTime = (unsigned)(_actionTimeline->currentTime * internval) / internval;
|
||||
}
|
||||
|
||||
if (_zOrderTimeline != nullptr && _zOrderTimeline->playState <= 0) // Update zOrder timeline.
|
||||
{
|
||||
_zOrderTimeline->update(time);
|
||||
}
|
||||
|
||||
if (isCacheEnabled) // Update cache.
|
||||
{
|
||||
const auto cacheFrameIndex = (unsigned)(_actionTimeline->currentTime * cacheFrameRate); // uint
|
||||
if ((unsigned)_armature->_cacheFrameIndex == cacheFrameIndex) // Same cache.
|
||||
{
|
||||
isUpdateTimeline = false;
|
||||
isUpdateBoneTimeline = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_armature->_cacheFrameIndex = cacheFrameIndex;
|
||||
if (_animationData->cachedFrames[cacheFrameIndex]) // Cached.
|
||||
{
|
||||
isUpdateBoneTimeline = false;
|
||||
}
|
||||
else // Cache.
|
||||
{
|
||||
_animationData->cachedFrames[cacheFrameIndex] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isUpdateTimeline)
|
||||
{
|
||||
if (isUpdateBoneTimeline) // Update bone timelines.
|
||||
{
|
||||
for (std::size_t i = 0, l = _boneTimelines.size(); i < l; ++i)
|
||||
{
|
||||
const auto timeline = _boneTimelines[i];
|
||||
|
||||
if (timeline->playState <= 0)
|
||||
{
|
||||
timeline->update(time);
|
||||
}
|
||||
|
||||
if (i == l - 1 || timeline->bone != _boneTimelines[i + 1]->bone)
|
||||
{
|
||||
const auto state = timeline->bone->_blendState.update(_weightResult, layer);
|
||||
if (state != 0)
|
||||
{
|
||||
timeline->blend(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayControl)
|
||||
{
|
||||
for (std::size_t i = 0, l = _slotTimelines.size(); i < l; ++i)
|
||||
{
|
||||
const auto timeline = _slotTimelines[i];
|
||||
const auto& displayController = timeline->slot->displayController;
|
||||
|
||||
if (
|
||||
displayController.empty() ||
|
||||
displayController == name ||
|
||||
displayController == group
|
||||
)
|
||||
{
|
||||
if (timeline->playState <= 0)
|
||||
{
|
||||
timeline->update(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0, l = _constraintTimelines.size(); i < l; ++i)
|
||||
{
|
||||
const auto timeline = _constraintTimelines[i];
|
||||
if (timeline->playState <= 0)
|
||||
{
|
||||
timeline->update(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_fadeState == 0)
|
||||
{
|
||||
if (_subFadeState > 0)
|
||||
{
|
||||
_subFadeState = 0;
|
||||
|
||||
if (!_poseTimelines.empty())
|
||||
{
|
||||
for (const auto& pair : _poseTimelines)
|
||||
{
|
||||
const auto timeline = pair.first;
|
||||
if (pair.second == BaseTimelineType::Bone)
|
||||
{
|
||||
_boneTimelines.erase(std::find(_boneTimelines.begin(), _boneTimelines.end(), timeline));
|
||||
}
|
||||
else if (pair.second == BaseTimelineType::Slot)
|
||||
{
|
||||
_slotTimelines.erase(std::find(_slotTimelines.begin(), _slotTimelines.end(), timeline));
|
||||
}
|
||||
else if (pair.second == BaseTimelineType::Constraint)
|
||||
{
|
||||
_constraintTimelines.erase(std::find(_constraintTimelines.begin(), _constraintTimelines.end(), timeline));
|
||||
}
|
||||
|
||||
timeline->returnToPool();
|
||||
}
|
||||
|
||||
_poseTimelines.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (_actionTimeline->playState > 0)
|
||||
{
|
||||
if (autoFadeOutTime >= 0.0f) // Auto fade out.
|
||||
{
|
||||
fadeOut(autoFadeOutTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationState::play()
|
||||
{
|
||||
_playheadState = 3; // 11
|
||||
}
|
||||
|
||||
void AnimationState::stop()
|
||||
{
|
||||
_playheadState &= 1; // 0x
|
||||
}
|
||||
|
||||
void AnimationState::fadeOut(float fadeOutTime, bool pausePlayhead)
|
||||
{
|
||||
if (fadeOutTime < 0.0f)
|
||||
{
|
||||
fadeOutTime = 0.0f;
|
||||
}
|
||||
|
||||
if (pausePlayhead)
|
||||
{
|
||||
_playheadState &= 2; // x0
|
||||
}
|
||||
|
||||
if (_fadeState > 0)
|
||||
{
|
||||
if (fadeOutTime > fadeTotalTime - _fadeTime) // If the animation is already in fade out, the new fade out will be ignored.
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_fadeState = 1;
|
||||
_subFadeState = -1;
|
||||
|
||||
if (fadeOutTime <= 0.0f || _fadeProgress <= 0.0f)
|
||||
{
|
||||
_fadeProgress = 0.000001f; // Modify fade progress to different value.
|
||||
}
|
||||
|
||||
for (const auto timeline : _boneTimelines)
|
||||
{
|
||||
timeline->fadeOut();
|
||||
}
|
||||
|
||||
for (const auto timeline : _slotTimelines)
|
||||
{
|
||||
timeline->fadeOut();
|
||||
}
|
||||
}
|
||||
|
||||
displayControl = false; //
|
||||
fadeTotalTime = _fadeProgress > 0.000001f ? fadeOutTime / _fadeProgress : 0.0f;
|
||||
_fadeTime = fadeTotalTime * (1.0f - _fadeProgress);
|
||||
}
|
||||
|
||||
bool AnimationState::containsBoneMask(const std::string& boneName) const
|
||||
{
|
||||
return _boneMask.empty() || std::find(_boneMask.cbegin(), _boneMask.cend(), boneName) != _boneMask.cend();
|
||||
}
|
||||
|
||||
void AnimationState::addBoneMask(const std::string& boneName, bool recursive)
|
||||
{
|
||||
const auto currentBone = _armature->getBone(boneName);
|
||||
if (currentBone == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::find(_boneMask.cbegin(), _boneMask.cend(), boneName) == _boneMask.cend())
|
||||
{
|
||||
_boneMask.push_back(boneName);
|
||||
}
|
||||
|
||||
if (recursive) // Add recursive mixing.
|
||||
{
|
||||
for (const auto bone : _armature->getBones())
|
||||
{
|
||||
if (std::find(_boneMask.cbegin(), _boneMask.cend(), bone->getName()) == _boneMask.cend() && currentBone->contains(bone))
|
||||
{
|
||||
_boneMask.push_back(bone->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_timelineDirty = 1;
|
||||
}
|
||||
|
||||
void AnimationState::removeBoneMask(const std::string& boneName, bool recursive)
|
||||
{
|
||||
{
|
||||
auto iterator = std::find(_boneMask.begin(), _boneMask.end(), boneName);
|
||||
if (iterator != _boneMask.cend()) // Remove mixing.
|
||||
{
|
||||
_boneMask.erase(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
const auto currentBone = _armature->getBone(boneName);
|
||||
if (currentBone != nullptr)
|
||||
{
|
||||
const auto& bones = _armature->getBones();
|
||||
if (!_boneMask.empty()) // Remove recursive mixing.
|
||||
{
|
||||
for (const auto bone : bones)
|
||||
{
|
||||
auto iterator = std::find(_boneMask.begin(), _boneMask.end(), bone->getName());
|
||||
if (iterator != _boneMask.end() && currentBone->contains(bone))
|
||||
{
|
||||
_boneMask.erase(iterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Add unrecursive mixing.
|
||||
{
|
||||
for (const auto bone : bones)
|
||||
{
|
||||
if (bone == currentBone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!currentBone->contains(bone))
|
||||
{
|
||||
_boneMask.push_back(bone->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_timelineDirty = 1;
|
||||
}
|
||||
|
||||
void AnimationState::removeAllBoneMask()
|
||||
{
|
||||
_boneMask.clear();
|
||||
_timelineDirty = 1;
|
||||
}
|
||||
|
||||
bool AnimationState::isPlaying() const
|
||||
{
|
||||
return (_playheadState & 2) != 0 && _actionTimeline->playState <= 0;
|
||||
}
|
||||
|
||||
bool AnimationState::isCompleted() const
|
||||
{
|
||||
return _actionTimeline->playState > 0;
|
||||
}
|
||||
|
||||
unsigned AnimationState::getCurrentPlayTimes() const
|
||||
{
|
||||
return _actionTimeline->currentPlayTimes;
|
||||
}
|
||||
|
||||
float AnimationState::getCurrentTime() const
|
||||
{
|
||||
return _actionTimeline->currentTime;
|
||||
}
|
||||
|
||||
void AnimationState::setCurrentTime(float value)
|
||||
{
|
||||
const auto currentPlayTimes = _actionTimeline->currentPlayTimes - (_actionTimeline->playState > 0 ? 1 : 0);
|
||||
if (value < 0.0f || _duration < value)
|
||||
{
|
||||
value = fmod(value, _duration) + currentPlayTimes * _duration;
|
||||
if (value < 0.0f)
|
||||
{
|
||||
value += _duration;
|
||||
}
|
||||
}
|
||||
|
||||
if (playTimes > 0 && (unsigned)currentPlayTimes == playTimes - 1 && value == _duration)
|
||||
{
|
||||
value = _duration - 0.000001f;
|
||||
}
|
||||
|
||||
if (_time == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_time = value;
|
||||
_actionTimeline->setCurrentTime(_time);
|
||||
|
||||
if (_zOrderTimeline != nullptr)
|
||||
{
|
||||
_zOrderTimeline->playState = -1;
|
||||
}
|
||||
|
||||
for (const auto timeline : _boneTimelines)
|
||||
{
|
||||
timeline->playState = -1;
|
||||
}
|
||||
|
||||
for (const auto timeline : _slotTimelines)
|
||||
{
|
||||
timeline->playState = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void BonePose::_onClear()
|
||||
{
|
||||
current.identity();
|
||||
delta.identity();
|
||||
result.identity();
|
||||
}
|
||||
|
||||
int BlendState::update(float weight, int p_layer)
|
||||
{
|
||||
if (dirty)
|
||||
{
|
||||
if (leftWeight > 0.0f)
|
||||
{
|
||||
if (layer != p_layer)
|
||||
{
|
||||
if (layerWeight >= leftWeight)
|
||||
{
|
||||
leftWeight = 0.0f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
layer = p_layer;
|
||||
leftWeight -= layerWeight;
|
||||
layerWeight = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
weight *= leftWeight;
|
||||
layerWeight += weight;
|
||||
blendWeight = weight;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
layer = p_layer;
|
||||
layerWeight = weight;
|
||||
leftWeight = 1.0f;
|
||||
blendWeight = weight;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BlendState::clear()
|
||||
{
|
||||
dirty = false;
|
||||
layer = 0;
|
||||
leftWeight = 0.0f;
|
||||
layerWeight = 0.0f;
|
||||
blendWeight = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
||||
|
@@ -0,0 +1,534 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2012-2018 DragonBones team and other contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DRAGONBONES_ANIMATION_STATE_H
|
||||
#define DRAGONBONES_ANIMATION_STATE_H
|
||||
|
||||
#include "../core/BaseObject.h"
|
||||
#include "../geom/Transform.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
/**
|
||||
* - The animation state is generated when the animation data is played.
|
||||
* @see dragonBones.Animation
|
||||
* @see dragonBones.AnimationData
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 动画状态由播放动画数据时产生。
|
||||
* @see dragonBones.Animation
|
||||
* @see dragonBones.AnimationData
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
class AnimationState : public BaseObject
|
||||
{
|
||||
BIND_CLASS_TYPE_B(AnimationState);
|
||||
|
||||
private:
|
||||
enum class BaseTimelineType {
|
||||
Bone,
|
||||
Slot,
|
||||
Constraint
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
bool actionEnabled;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
bool additiveBlending;
|
||||
/**
|
||||
* - Whether the animation state has control over the display object properties of the slots.
|
||||
* Sometimes blend a animation state does not want it to control the display object properties of the slots,
|
||||
* especially if other animation state are controlling the display object properties of the slots.
|
||||
* @default true
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 动画状态是否对插槽的显示对象属性有控制权。
|
||||
* 有时混合一个动画状态并不希望其控制插槽的显示对象属性,
|
||||
* 尤其是其他动画状态正在控制这些插槽的显示对象属性时。
|
||||
* @default true
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool displayControl;
|
||||
/**
|
||||
* - Whether to reset the objects without animation to the armature pose when the animation state is start to play.
|
||||
* This property should usually be set to false when blend multiple animation states.
|
||||
* @default true
|
||||
* @version DragonBones 5.1
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 开始播放动画状态时是否将没有动画的对象重置为骨架初始值。
|
||||
* 通常在混合多个动画状态时应该将该属性设置为 false。
|
||||
* @default true
|
||||
* @version DragonBones 5.1
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool resetToPose;
|
||||
/**
|
||||
* - The play times. [0: Loop play, [1~N]: Play N times]
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 播放次数。 [0: 无限循环播放, [1~N]: 循环播放 N 次]
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
unsigned playTimes;
|
||||
/**
|
||||
* - The blend layer.
|
||||
* High layer animation state will get the blend weight first.
|
||||
* When the blend weight is assigned more than 1, the remaining animation states will no longer get the weight assigned.
|
||||
* @readonly
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 混合图层。
|
||||
* 图层高的动画状态会优先获取混合权重。
|
||||
* 当混合权重分配超过 1 时,剩余的动画状态将不再获得权重分配。
|
||||
* @readonly
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
unsigned layer;
|
||||
/**
|
||||
* - The play speed.
|
||||
* The value is an overlay relationship with {@link dragonBones.Animation#timeScale}.
|
||||
* [(-N~0): Reverse play, 0: Stop play, (0~1): Slow play, 1: Normal play, (1~N): Fast play]
|
||||
* @default 1.0
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 播放速度。
|
||||
* 该值与 {@link dragonBones.Animation#timeScale} 是叠加关系。
|
||||
* [(-N~0): 倒转播放, 0: 停止播放, (0~1): 慢速播放, 1: 正常播放, (1~N): 快速播放]
|
||||
* @default 1.0
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
float timeScale;
|
||||
/**
|
||||
* - The blend weight.
|
||||
* @default 1.0
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 混合权重。
|
||||
* @default 1.0
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
float weight;
|
||||
/**
|
||||
* - The auto fade out time when the animation state play completed.
|
||||
* [-1: Do not fade out automatically, [0~N]: The fade out time] (In seconds)
|
||||
* @default -1.0
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 动画状态播放完成后的自动淡出时间。
|
||||
* [-1: 不自动淡出, [0~N]: 淡出时间] (以秒为单位)
|
||||
* @default -1.0
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
float autoFadeOutTime;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
float fadeTotalTime;
|
||||
/**
|
||||
* - The name of the animation state. (Can be different from the name of the animation data)
|
||||
* @readonly
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 动画状态名称。 (可以不同于动画数据)
|
||||
* @readonly
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
std::string name;
|
||||
/**
|
||||
* - The blend group name of the animation state.
|
||||
* This property is typically used to specify the substitution of multiple animation states blend.
|
||||
* @readonly
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 混合组名称。
|
||||
* 该属性通常用来指定多个动画状态混合时的相互替换关系。
|
||||
* @readonly
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
std::string group;
|
||||
|
||||
public:
|
||||
/**
|
||||
* - xx: Play Enabled, Fade Play Enabled
|
||||
* @internal
|
||||
*/
|
||||
int _playheadState;
|
||||
/**
|
||||
* -1: Fade in, 0: Fade complete, 1: Fade out;
|
||||
* @internal
|
||||
*/
|
||||
int _fadeState;
|
||||
/**
|
||||
* -1: Fade start, 0: Fading, 1: Fade complete;
|
||||
* @internal
|
||||
*/
|
||||
int _subFadeState;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
float _position;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
float _duration;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
float _fadeProgress;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
float _weightResult;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
AnimationData* _animationData;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
ActionTimelineState* _actionTimeline;
|
||||
|
||||
private:
|
||||
unsigned _timelineDirty;
|
||||
float _fadeTime;
|
||||
float _time;
|
||||
std::vector<std::string> _boneMask;
|
||||
std::vector<BoneTimelineState*> _boneTimelines;
|
||||
std::vector<SlotTimelineState*> _slotTimelines;
|
||||
std::vector<ConstraintTimelineState*> _constraintTimelines;
|
||||
std::vector<std::pair<TimelineState*, BaseTimelineType>> _poseTimelines;
|
||||
std::map<std::string, BonePose*> _bonePoses;
|
||||
Armature* _armature;
|
||||
ZOrderTimelineState* _zOrderTimeline;
|
||||
|
||||
public:
|
||||
AnimationState() :
|
||||
_actionTimeline(nullptr),
|
||||
_zOrderTimeline(nullptr)
|
||||
{
|
||||
_onClear();
|
||||
}
|
||||
virtual ~AnimationState()
|
||||
{
|
||||
_onClear();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
|
||||
private:
|
||||
void _updateTimelines();
|
||||
void _updateBoneAndSlotTimelines();
|
||||
void _advanceFadeTime(float passedTime);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void init(Armature* armature, AnimationData* animationData, AnimationConfig* animationConfig);
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void advanceTime(float passedTime, float cacheFrameRate);
|
||||
/**
|
||||
* - Continue play.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 继续播放。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void play();
|
||||
/**
|
||||
* - Stop play.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 暂停播放。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void stop();
|
||||
/**
|
||||
* - Fade out the animation state.
|
||||
* @param fadeOutTime - The fade out time. (In seconds)
|
||||
* @param pausePlayhead - Whether to pause the animation playing when fade out.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 淡出动画状态。
|
||||
* @param fadeOutTime - 淡出时间。 (以秒为单位)
|
||||
* @param pausePlayhead - 淡出时是否暂停播放。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void fadeOut(float fadeOutTime, bool pausePlayhead = true);
|
||||
/**
|
||||
* - Check if a specific bone mask is included.
|
||||
* @param boneName - The bone name.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 检查是否包含特定骨骼遮罩。
|
||||
* @param boneName - 骨骼名称。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool containsBoneMask(const std::string& boneName) const;
|
||||
/**
|
||||
* - Add a specific bone mask.
|
||||
* @param boneName - The bone name.
|
||||
* @param recursive - Whether or not to add a mask to the bone's sub-bone.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 添加特定的骨骼遮罩。
|
||||
* @param boneName - 骨骼名称。
|
||||
* @param recursive - 是否为该骨骼的子骨骼添加遮罩。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void addBoneMask(const std::string& boneName, bool recursive = true);
|
||||
/**
|
||||
* - Remove the mask of a specific bone.
|
||||
* @param boneName - The bone name.
|
||||
* @param recursive - Whether to remove the bone's sub-bone mask.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 删除特定骨骼的遮罩。
|
||||
* @param boneName - 骨骼名称。
|
||||
* @param recursive - 是否删除该骨骼的子骨骼遮罩。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void removeBoneMask(const std::string& boneName, bool recursive = true);
|
||||
/**
|
||||
* - Remove all bone masks.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 删除所有骨骼遮罩。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void removeAllBoneMask();
|
||||
/**
|
||||
* - Whether the animation state is fading in.
|
||||
* @version DragonBones 5.1
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 是否正在淡入。
|
||||
* @version DragonBones 5.1
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline bool isFadeIn() const
|
||||
{
|
||||
return _fadeState < 0;
|
||||
}
|
||||
/**
|
||||
* - Whether the animation state is fading out.
|
||||
* @version DragonBones 5.1
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 是否正在淡出。
|
||||
* @version DragonBones 5.1
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline bool isFadeOut() const
|
||||
{
|
||||
return _fadeState > 0;
|
||||
}
|
||||
/**
|
||||
* - Whether the animation state is fade completed.
|
||||
* @version DragonBones 5.1
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 是否淡入或淡出完毕。
|
||||
* @version DragonBones 5.1
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline bool isFadeComplete() const
|
||||
{
|
||||
return _fadeState == 0;
|
||||
}
|
||||
/**
|
||||
* - Whether the animation state is playing.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 是否正在播放。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool isPlaying() const;
|
||||
/**
|
||||
* - Whether the animation state is play completed.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 是否播放完毕。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool isCompleted() const;
|
||||
/**
|
||||
* - The times has been played.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 已经循环播放的次数。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
unsigned getCurrentPlayTimes() const;
|
||||
/**
|
||||
* - The total time. (In seconds)
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 总播放时间。 (以秒为单位)
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline float getTotalTime() const
|
||||
{
|
||||
return _duration;
|
||||
}
|
||||
/**
|
||||
* - The time is currently playing. (In seconds)
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 当前播放的时间。 (以秒为单位)
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
float getCurrentTime() const;
|
||||
void setCurrentTime(float value);
|
||||
inline const std::string& getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* - The animation data.
|
||||
* @see dragonBones.AnimationData
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 动画数据。
|
||||
* @see dragonBones.AnimationData
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
inline const AnimationData* getAnimationData() const
|
||||
{
|
||||
return _animationData;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BonePose : public BaseObject
|
||||
{
|
||||
BIND_CLASS_TYPE_A(BonePose);
|
||||
|
||||
public:
|
||||
Transform current;
|
||||
Transform delta;
|
||||
Transform result;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BlendState
|
||||
{
|
||||
public:
|
||||
bool dirty;
|
||||
int layer;
|
||||
float leftWeight;
|
||||
float layerWeight;
|
||||
float blendWeight;
|
||||
|
||||
/**
|
||||
* -1: First blending, 0: No blending, 1: Blending.
|
||||
*/
|
||||
int update(float weight, int p_layer);
|
||||
void clear();
|
||||
};
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
||||
#endif // DRAGONBONES_ANIMATION_STATE_H
|
@@ -0,0 +1,344 @@
|
||||
#include "BaseTimelineState.h"
|
||||
#include "../model/DragonBonesData.h"
|
||||
#include "../model/ArmatureData.h"
|
||||
#include "../model/AnimationData.h"
|
||||
#include "../armature/Armature.h"
|
||||
#include "../armature/Bone.h"
|
||||
#include "../armature/Slot.h"
|
||||
#include "AnimationState.h"
|
||||
#include "TimelineState.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
|
||||
void TimelineState::_onClear()
|
||||
{
|
||||
playState = -1;
|
||||
currentPlayTimes = -1;
|
||||
currentTime = -1.0f;
|
||||
|
||||
_tweenState = TweenState::None;
|
||||
_frameRate = 0;
|
||||
_frameValueOffset = 0;
|
||||
_frameCount = 0;
|
||||
_frameOffset = 0;
|
||||
_frameIndex = -1;
|
||||
_frameRateR = 0.0f;
|
||||
_position = 0.0f;
|
||||
_duration = 0.0f;
|
||||
_timeScale = 1.0f;
|
||||
_timeOffset = 0.0f;
|
||||
_dragonBonesData = nullptr;
|
||||
_animationData = nullptr;
|
||||
_timelineData = nullptr;
|
||||
_armature = nullptr;
|
||||
_animationState = nullptr;
|
||||
_actionTimeline = nullptr;
|
||||
_frameArray = nullptr;
|
||||
_frameIntArray = nullptr;
|
||||
_frameFloatArray = nullptr;
|
||||
_timelineArray = nullptr;
|
||||
_frameIndices = nullptr;
|
||||
}
|
||||
|
||||
bool TimelineState::_setCurrentTime(float passedTime)
|
||||
{
|
||||
const auto prevState = playState;
|
||||
const auto prevPlayTimes = currentPlayTimes;
|
||||
const auto prevTime = currentTime;
|
||||
|
||||
if (_actionTimeline != nullptr && _frameCount <= 1) // No frame or only one frame.
|
||||
{
|
||||
playState = _actionTimeline->playState >= 0 ? 1 : -1;
|
||||
currentPlayTimes = 1;
|
||||
currentTime = _actionTimeline->currentTime;
|
||||
}
|
||||
else if (_actionTimeline == nullptr || _timeScale != 1.0f || _timeOffset != 0.0f) // Action timeline or has scale and offset.
|
||||
{
|
||||
const auto playTimes = _animationState->playTimes;
|
||||
const auto totalTime = playTimes * _duration;
|
||||
|
||||
passedTime *= _timeScale;
|
||||
if (_timeOffset != 0.0f)
|
||||
{
|
||||
passedTime += _timeOffset * _animationData->duration;
|
||||
}
|
||||
|
||||
if (playTimes > 0 && (passedTime >= totalTime || passedTime <= -totalTime))
|
||||
{
|
||||
if (playState <= 0 && _animationState->_playheadState == 3)
|
||||
{
|
||||
playState = 1;
|
||||
}
|
||||
|
||||
currentPlayTimes = playTimes;
|
||||
if (passedTime < 0.0f)
|
||||
{
|
||||
currentTime = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentTime = _duration + 0.000001f; // Precision problem
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (playState != 0 && _animationState->_playheadState == 3)
|
||||
{
|
||||
playState = 0;
|
||||
}
|
||||
|
||||
if (passedTime < 0.0f)
|
||||
{
|
||||
passedTime = -passedTime;
|
||||
currentPlayTimes = (int)(passedTime / _duration);
|
||||
currentTime = _duration - fmod(passedTime, _duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPlayTimes = (int)(passedTime / _duration);
|
||||
currentTime = fmod(passedTime, _duration);
|
||||
}
|
||||
}
|
||||
|
||||
currentTime += _position;
|
||||
}
|
||||
else // Multi frames.
|
||||
{
|
||||
playState = _actionTimeline->playState;
|
||||
currentPlayTimes = _actionTimeline->currentPlayTimes;
|
||||
currentTime = _actionTimeline->currentTime;
|
||||
}
|
||||
|
||||
if (currentPlayTimes == prevPlayTimes && currentTime == prevTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear frame flag when timeline start or loopComplete.
|
||||
if (
|
||||
(prevState < 0 && playState != prevState) ||
|
||||
(playState <= 0 && currentPlayTimes != prevPlayTimes)
|
||||
)
|
||||
{
|
||||
_frameIndex = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimelineState::init(Armature* armature, AnimationState* animationState, TimelineData* timelineData)
|
||||
{
|
||||
_armature = armature;
|
||||
_animationState = animationState;
|
||||
_timelineData = timelineData;
|
||||
_actionTimeline = _animationState->_actionTimeline;
|
||||
|
||||
if (this == _actionTimeline)
|
||||
{
|
||||
_actionTimeline = nullptr; //
|
||||
}
|
||||
|
||||
_animationData = _animationState->_animationData;
|
||||
|
||||
_frameRate = _animationData->parent->frameRate;
|
||||
_frameRateR = 1.0f / _frameRate;
|
||||
_position = _animationState->_position;
|
||||
_duration = _animationState->_duration;
|
||||
_dragonBonesData = _animationData->parent->parent;
|
||||
|
||||
if (_timelineData != nullptr)
|
||||
{
|
||||
_frameIntArray = _dragonBonesData->frameIntArray;
|
||||
_frameFloatArray = _dragonBonesData->frameFloatArray;
|
||||
_frameArray = _dragonBonesData->frameArray;
|
||||
_timelineArray = _dragonBonesData->timelineArray;
|
||||
_frameIndices = &(_dragonBonesData->frameIndices);
|
||||
|
||||
_frameCount = _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineKeyFrameCount];
|
||||
_frameValueOffset = _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameValueOffset];
|
||||
_timeScale = 100.0f / _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineScale];
|
||||
_timeOffset = _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineOffset] * 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineState::update(float passedTime)
|
||||
{
|
||||
if (_setCurrentTime(passedTime))
|
||||
{
|
||||
if (_frameCount > 1)
|
||||
{
|
||||
const auto timelineFrameIndex = (unsigned)(currentTime * _frameRate);
|
||||
const auto frameIndex = (*_frameIndices)[_timelineData->frameIndicesOffset + timelineFrameIndex];
|
||||
if ((unsigned)_frameIndex != frameIndex)
|
||||
{
|
||||
_frameIndex = frameIndex;
|
||||
_frameOffset = _animationData->frameOffset + _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + _frameIndex];
|
||||
|
||||
_onArriveAtFrame();
|
||||
}
|
||||
}
|
||||
else if (_frameIndex < 0)
|
||||
{
|
||||
_frameIndex = 0;
|
||||
if (_timelineData != nullptr) // May be pose timeline.
|
||||
{
|
||||
_frameOffset = _animationData->frameOffset + _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset];
|
||||
}
|
||||
|
||||
_onArriveAtFrame();
|
||||
}
|
||||
|
||||
if (_tweenState != TweenState::None)
|
||||
{
|
||||
_onUpdateFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TweenTimelineState::_onClear()
|
||||
{
|
||||
TimelineState::_onClear();
|
||||
|
||||
_tweenType = TweenType::None;
|
||||
_curveCount = 0;
|
||||
_framePosition = 0.0f;
|
||||
_frameDurationR = 0.0f;
|
||||
_tweenProgress = 0.0f;
|
||||
_tweenEasing = 0.0f;
|
||||
}
|
||||
|
||||
void TweenTimelineState::_onArriveAtFrame()
|
||||
{
|
||||
if (
|
||||
_frameCount > 1 &&
|
||||
(
|
||||
(unsigned)_frameIndex != _frameCount - 1 ||
|
||||
_animationState->playTimes == 0 ||
|
||||
_animationState->getCurrentPlayTimes() < _animationState->playTimes - 1
|
||||
)
|
||||
)
|
||||
{
|
||||
_tweenType = (TweenType)_frameArray[_frameOffset + (unsigned)BinaryOffset::FrameTweenType]; // TODO recode ture tween type.
|
||||
_tweenState = _tweenType == TweenType::None ? TweenState::Once : TweenState::Always;
|
||||
|
||||
if (_tweenType == TweenType::Curve)
|
||||
{
|
||||
_curveCount = _frameArray[_frameOffset + (unsigned)BinaryOffset::FrameTweenEasingOrCurveSampleCount];
|
||||
}
|
||||
else if (_tweenType != TweenType::None && _tweenType != TweenType::Line)
|
||||
{
|
||||
_tweenEasing = _frameArray[_frameOffset + (unsigned)BinaryOffset::FrameTweenEasingOrCurveSampleCount] * 0.01;
|
||||
}
|
||||
|
||||
_framePosition = _frameArray[_frameOffset] * _frameRateR;
|
||||
|
||||
if ((unsigned)_frameIndex == _frameCount - 1)
|
||||
{
|
||||
_frameDurationR = 1.0f / (_animationData->duration - _framePosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto nextFrameOffset = _animationData->frameOffset + _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + _frameIndex + 1];
|
||||
const auto frameDuration = _frameArray[nextFrameOffset] * _frameRateR - _framePosition;
|
||||
|
||||
if (frameDuration > 0.0f) // Fixed animation data bug.
|
||||
{
|
||||
_frameDurationR = 1.0f / frameDuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
_frameDurationR = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_tweenState = TweenState::Once;
|
||||
}
|
||||
}
|
||||
|
||||
void TweenTimelineState::_onUpdateFrame()
|
||||
{
|
||||
if (_tweenState == TweenState::Always)
|
||||
{
|
||||
_tweenProgress = (currentTime - _framePosition) * _frameDurationR;
|
||||
|
||||
if (_tweenType == TweenType::Curve)
|
||||
{
|
||||
_tweenProgress = TweenTimelineState::_getEasingCurveValue(_tweenProgress, _frameArray, _curveCount, _frameOffset + (unsigned)BinaryOffset::FrameCurveSamples);
|
||||
}
|
||||
else if (_tweenType != TweenType::Line)
|
||||
{
|
||||
_tweenProgress = TweenTimelineState::_getEasingValue(_tweenType, _tweenProgress, _tweenEasing);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_tweenProgress = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void BoneTimelineState::_onClear()
|
||||
{
|
||||
TweenTimelineState::_onClear();
|
||||
|
||||
bone = nullptr;
|
||||
bonePose = nullptr;
|
||||
}
|
||||
|
||||
void BoneTimelineState::blend(int state)
|
||||
{
|
||||
const auto blendWeight = bone->_blendState.blendWeight;
|
||||
auto& animationPose = bone->animationPose;
|
||||
const auto& result = bonePose->result;
|
||||
|
||||
if (state == 2)
|
||||
{
|
||||
animationPose.x += result.x * blendWeight;
|
||||
animationPose.y += result.y * blendWeight;
|
||||
animationPose.rotation += result.rotation * blendWeight;
|
||||
animationPose.skew += result.skew * blendWeight;
|
||||
animationPose.scaleX += (result.scaleX - 1.0f) * blendWeight;
|
||||
animationPose.scaleY += (result.scaleY - 1.0f) * blendWeight;
|
||||
}
|
||||
else if (blendWeight != 1.0f)
|
||||
{
|
||||
animationPose.x = result.x * blendWeight;
|
||||
animationPose.y = result.y * blendWeight;
|
||||
animationPose.rotation = result.rotation * blendWeight;
|
||||
animationPose.skew = result.skew * blendWeight;
|
||||
animationPose.scaleX = (result.scaleX - 1.0f) * blendWeight + 1.0f;
|
||||
animationPose.scaleY = (result.scaleY - 1.0f) * blendWeight + 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
animationPose.x = result.x;
|
||||
animationPose.y = result.y;
|
||||
animationPose.rotation = result.rotation;
|
||||
animationPose.skew = result.skew;
|
||||
animationPose.scaleX = result.scaleX;
|
||||
animationPose.scaleY = result.scaleY;
|
||||
}
|
||||
|
||||
if (_animationState->_fadeState != 0 || _animationState->_subFadeState != 0)
|
||||
{
|
||||
bone->_transformDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SlotTimelineState::_onClear()
|
||||
{
|
||||
TweenTimelineState::_onClear();
|
||||
|
||||
slot = nullptr;
|
||||
}
|
||||
|
||||
void ConstraintTimelineState::_onClear()
|
||||
{
|
||||
TweenTimelineState::_onClear();
|
||||
|
||||
constraint = nullptr;
|
||||
}
|
||||
DRAGONBONES_NAMESPACE_END
|
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2012-2018 DragonBones team and other contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DRAGONBONES_BASE_TIMELINE_STATE_H
|
||||
#define DRAGONBONES_BASE_TIMELINE_STATE_H
|
||||
|
||||
#include "../geom/Transform.h"
|
||||
#include "../core/BaseObject.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class TimelineState : public BaseObject
|
||||
{
|
||||
ABSTRACT_CLASS(TimelineState)
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
enum class TweenState
|
||||
{
|
||||
None = 0,
|
||||
Once = 1,
|
||||
Always = 2
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* -1: start, 0: play, 1: complete;
|
||||
*/
|
||||
int playState;
|
||||
int currentPlayTimes;
|
||||
float currentTime;
|
||||
|
||||
protected:
|
||||
TweenState _tweenState;
|
||||
unsigned _frameRate;
|
||||
unsigned _frameValueOffset;
|
||||
unsigned _frameCount;
|
||||
unsigned _frameOffset;
|
||||
int _frameIndex;
|
||||
float _frameRateR;
|
||||
float _position;
|
||||
float _duration;
|
||||
float _timeScale;
|
||||
float _timeOffset;
|
||||
DragonBonesData* _dragonBonesData;
|
||||
AnimationData* _animationData;
|
||||
TimelineData* _timelineData;
|
||||
Armature* _armature;
|
||||
AnimationState* _animationState;
|
||||
TimelineState* _actionTimeline;
|
||||
const int16_t* _frameArray;
|
||||
const int16_t* _frameIntArray;
|
||||
const float* _frameFloatArray;
|
||||
const uint16_t* _timelineArray;
|
||||
const std::vector<unsigned>* _frameIndices;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
virtual void _onArriveAtFrame() = 0;
|
||||
virtual void _onUpdateFrame() = 0;
|
||||
bool _setCurrentTime(float passedTime);
|
||||
|
||||
public:
|
||||
virtual void init(Armature* armature, AnimationState* animationState, TimelineData* timelineData);
|
||||
virtual void fadeOut() {}
|
||||
virtual void update(float passedTime);
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class TweenTimelineState : public TimelineState
|
||||
{
|
||||
ABSTRACT_CLASS(TweenTimelineState)
|
||||
|
||||
private:
|
||||
inline static float _getEasingValue(TweenType tweenType, float progress, float easing)
|
||||
{
|
||||
auto value = progress;
|
||||
switch (tweenType)
|
||||
{
|
||||
case TweenType::QuadIn:
|
||||
value = std::pow(progress, 2.0f);
|
||||
break;
|
||||
|
||||
case TweenType::QuadOut:
|
||||
value = 1.0f - std::pow(1.0f - progress, 2.0f);
|
||||
break;
|
||||
|
||||
case TweenType::QuadInOut:
|
||||
value = 0.5f * (1.0f - std::cos(progress * Transform::PI));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (value - progress) * easing + progress;
|
||||
}
|
||||
|
||||
inline static float _getEasingCurveValue(float progress, const int16_t* samples, unsigned count, unsigned offset)
|
||||
{
|
||||
if (progress <= 0.0f)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
else if (progress >= 1.0f)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
const auto segmentCount = count + 1; // + 2 - 1
|
||||
const auto valueIndex = (unsigned)(progress * segmentCount);
|
||||
const auto fromValue = valueIndex == 0 ? 0.0f : samples[offset + valueIndex - 1];
|
||||
const auto toValue = (valueIndex == segmentCount - 1) ? 10000.0f : samples[offset + valueIndex];
|
||||
|
||||
return (fromValue + (toValue - fromValue) * (progress * segmentCount - valueIndex)) * 0.0001f;
|
||||
}
|
||||
|
||||
protected:
|
||||
TweenType _tweenType;
|
||||
unsigned _curveCount;
|
||||
float _framePosition;
|
||||
float _frameDurationR;
|
||||
float _tweenProgress;
|
||||
float _tweenEasing;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BoneTimelineState : public TweenTimelineState
|
||||
{
|
||||
ABSTRACT_CLASS(BoneTimelineState)
|
||||
|
||||
public:
|
||||
Bone* bone;
|
||||
BonePose* bonePose;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
|
||||
public:
|
||||
void blend(int state);
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class SlotTimelineState : public TweenTimelineState
|
||||
{
|
||||
ABSTRACT_CLASS(SlotTimelineState)
|
||||
|
||||
public:
|
||||
Slot* slot;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ConstraintTimelineState : public TweenTimelineState
|
||||
{
|
||||
ABSTRACT_CLASS(ConstraintTimelineState)
|
||||
|
||||
public:
|
||||
Constraint* constraint;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
};
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
||||
#endif // DRAGONBONES_BASE_TIMELINE_STATE_H
|
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2012-2018 DragonBones team and other contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DRAGONBONES_ANIMATEBLE_H
|
||||
#define DRAGONBONES_ANIMATEBLE_H
|
||||
|
||||
#include "../core/DragonBones.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
/**
|
||||
* - Play animation interface. (Both Armature and Wordclock implement the interface)
|
||||
* Any instance that implements the interface can be added to the Worldclock instance and advance time by Worldclock instance uniformly.
|
||||
* @see dragonBones.WorldClock
|
||||
* @see dragonBones.Armature
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 播放动画接口。 (Armature 和 WordClock 都实现了该接口)
|
||||
* 任何实现了此接口的实例都可以添加到 WorldClock 实例中,由 WorldClock 实例统一更新时间。
|
||||
* @see dragonBones.WorldClock
|
||||
* @see dragonBones.Armature
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
class IAnimatable
|
||||
{
|
||||
ABSTRACT_CLASS(IAnimatable)
|
||||
|
||||
public:
|
||||
/**
|
||||
* - Advance time.
|
||||
* @param passedTime - Passed time. (In seconds)
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 更新时间。
|
||||
* @param passedTime - 前进的时间。 (以秒为单位)
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
virtual void advanceTime(float passedTime) = 0;
|
||||
|
||||
/**
|
||||
* - Render.
|
||||
* @version Cocos creator 2.3
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 渲染。
|
||||
* @version Cocos creator 2.3
|
||||
* @language zh_CN
|
||||
*/
|
||||
virtual void render() = 0;
|
||||
/**
|
||||
* - The Wordclock instance to which the current belongs.
|
||||
* @example
|
||||
* TypeScript style, for reference only.
|
||||
* <pre>
|
||||
* armature.clock = factory.clock; // Add armature to clock.
|
||||
* armature.clock = null; // Remove armature from clock.
|
||||
* </pre>
|
||||
* @version DragonBones 5.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 当前所属的 WordClock 实例。
|
||||
* @example
|
||||
* TypeScript 风格,仅供参考。
|
||||
* <pre>
|
||||
* armature.clock = factory.clock; // 将骨架添加到时钟。
|
||||
* armature.clock = null; // 将骨架从时钟移除。
|
||||
* </pre>
|
||||
* @version DragonBones 5.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
virtual WorldClock* getClock() const = 0;
|
||||
virtual void setClock(WorldClock* value) = 0;
|
||||
|
||||
/**
|
||||
* - Gets render order.
|
||||
* @version Cocos creator 2.3
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 获得渲染顺序。
|
||||
* @version Cocos creator 2.3
|
||||
* @language zh_CN
|
||||
*/
|
||||
virtual uint32_t getRenderOrder() const { return 0; }
|
||||
};
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
||||
#endif // DRAGONBONES_ANIMATEBLE_H
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2012-2018 DragonBones team and other contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DRAGONBONES_TIMELINE_STATE_H
|
||||
#define DRAGONBONES_TIMELINE_STATE_H
|
||||
|
||||
#include "BaseTimelineState.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ActionTimelineState : public TimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(ActionTimelineState);
|
||||
|
||||
void _onCrossFrame(unsigned frameIndex) const;
|
||||
|
||||
protected:
|
||||
virtual void _onArriveAtFrame() override {}
|
||||
virtual void _onUpdateFrame() override {}
|
||||
|
||||
public:
|
||||
void update(float passedTime) override;
|
||||
void setCurrentTime(float value);
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ZOrderTimelineState : public TimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(ZOrderTimelineState);
|
||||
|
||||
protected:
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override {}
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BoneAllTimelineState : public BoneTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(BoneAllTimelineState);
|
||||
|
||||
protected:
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override;
|
||||
|
||||
public:
|
||||
virtual void fadeOut() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BoneTranslateTimelineState : public BoneTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(BoneTranslateTimelineState);
|
||||
|
||||
protected:
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BoneRotateTimelineState : public BoneTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(BoneRotateTimelineState);
|
||||
|
||||
protected:
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override;
|
||||
|
||||
public:
|
||||
virtual void fadeOut() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BoneScaleTimelineState : public BoneTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(BoneScaleTimelineState);
|
||||
|
||||
protected:
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class SlotDislayTimelineState : public SlotTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(SlotDislayTimelineState);
|
||||
|
||||
protected:
|
||||
virtual void _onArriveAtFrame() override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class SlotColorTimelineState : public SlotTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_B(SlotColorTimelineState);
|
||||
|
||||
private:
|
||||
bool _dirty;
|
||||
int* _current;
|
||||
int* _delta;
|
||||
float* _result;
|
||||
|
||||
public:
|
||||
SlotColorTimelineState() :
|
||||
_current(new int[8]{ 0 }),
|
||||
_delta(new int[8]{ 0 }),
|
||||
_result(new float[8]{ 0.0f })
|
||||
{
|
||||
_onClear();
|
||||
}
|
||||
~SlotColorTimelineState()
|
||||
{
|
||||
_onClear();
|
||||
|
||||
delete _current;
|
||||
delete _delta;
|
||||
delete _result;
|
||||
}
|
||||
|
||||
protected:
|
||||
void _onClear() override;
|
||||
void _onArriveAtFrame() override;
|
||||
void _onUpdateFrame() override;
|
||||
|
||||
public:
|
||||
void fadeOut() override;
|
||||
void update(float passedTime) override;
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class DeformTimelineState : public SlotTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(DeformTimelineState);
|
||||
|
||||
public:
|
||||
unsigned vertexOffset;
|
||||
|
||||
private:
|
||||
bool _dirty;
|
||||
unsigned _frameFloatOffset;
|
||||
unsigned _deformCount;
|
||||
unsigned _valueCount;
|
||||
unsigned _valueOffset;
|
||||
std::vector<float> _current;
|
||||
std::vector<float> _delta;
|
||||
std::vector<float> _result;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override;
|
||||
|
||||
public:
|
||||
virtual void init(Armature* armature, AnimationState* animationState, TimelineData* timelineData) override;
|
||||
virtual void fadeOut() override;
|
||||
virtual void update(float passedTime) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class IKConstraintTimelineState : public ConstraintTimelineState
|
||||
{
|
||||
BIND_CLASS_TYPE_A(IKConstraintTimelineState);
|
||||
|
||||
private:
|
||||
float _current;
|
||||
float _delta;
|
||||
|
||||
protected:
|
||||
virtual void _onClear() override;
|
||||
virtual void _onArriveAtFrame() override;
|
||||
virtual void _onUpdateFrame() override;
|
||||
};
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
||||
#endif // DRAGONBONES_TIMELINE_STATE_H
|
@@ -0,0 +1,179 @@
|
||||
#include "WorldClock.h"
|
||||
#include <algorithm>
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
|
||||
WorldClock WorldClock::clock;
|
||||
|
||||
void WorldClock::advanceTime(float passedTime)
|
||||
{
|
||||
if (passedTime < 0.0f || passedTime != passedTime)
|
||||
{
|
||||
passedTime = 0.0f;
|
||||
}
|
||||
|
||||
const auto currentTime = 0.0f;
|
||||
|
||||
if (passedTime < 0.0f)
|
||||
{
|
||||
passedTime = currentTime - _systemTime;
|
||||
}
|
||||
|
||||
_systemTime = currentTime;
|
||||
|
||||
if (timeScale != 1.0f)
|
||||
{
|
||||
passedTime *= timeScale;
|
||||
}
|
||||
|
||||
if (passedTime == 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (passedTime < 0.0f)
|
||||
{
|
||||
time -= passedTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
time += passedTime;
|
||||
}
|
||||
|
||||
std::size_t i = 0, r = 0, l = _animatebles.size();
|
||||
for (; i < l; ++i)
|
||||
{
|
||||
const auto animatable = _animatebles[i];
|
||||
if (animatable != nullptr)
|
||||
{
|
||||
if (r > 0)
|
||||
{
|
||||
_animatebles[i - r] = animatable;
|
||||
_animatebles[i] = nullptr;
|
||||
}
|
||||
|
||||
animatable->advanceTime(passedTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
if (r > 0)
|
||||
{
|
||||
l = _animatebles.size();
|
||||
for (; i < l; ++i)
|
||||
{
|
||||
const auto animateble = _animatebles[i];
|
||||
if (animateble != nullptr)
|
||||
{
|
||||
_animatebles[i - r] = animateble;
|
||||
}
|
||||
else
|
||||
{
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
_animatebles.resize(l - r);
|
||||
}
|
||||
}
|
||||
|
||||
bool WorldClock::contains(const IAnimatable* value) const
|
||||
{
|
||||
if (value == this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ancestor = value;
|
||||
while (ancestor != this && ancestor != nullptr)
|
||||
{
|
||||
ancestor = ancestor->getClock();
|
||||
}
|
||||
|
||||
return ancestor == this;
|
||||
}
|
||||
|
||||
void WorldClock::add(IAnimatable* value)
|
||||
{
|
||||
if (std::find(_animatebles.begin(), _animatebles.end(), value) == _animatebles.end())
|
||||
{
|
||||
_animatebles.push_back(value);
|
||||
value->setClock(this);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldClock::remove(IAnimatable* value)
|
||||
{
|
||||
const auto iterator = std::find(_animatebles.begin(), _animatebles.end(), value);
|
||||
if (iterator != _animatebles.end())
|
||||
{
|
||||
*iterator = nullptr;
|
||||
value->setClock(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldClock::render()
|
||||
{
|
||||
auto isOrderDirty = false;
|
||||
uint32_t maxRenderOrder = 0;
|
||||
for (const auto animatable : _animatebles)
|
||||
{
|
||||
if (animatable != nullptr)
|
||||
{
|
||||
animatable->render();
|
||||
auto renderOrder = animatable->getRenderOrder();
|
||||
if (maxRenderOrder > renderOrder)
|
||||
{
|
||||
isOrderDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxRenderOrder = renderOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isOrderDirty)
|
||||
{
|
||||
std::sort(_animatebles.begin(), _animatebles.end(), [](IAnimatable* it1, IAnimatable* it2)
|
||||
{
|
||||
if (!it1 || !it2) return false;
|
||||
return it1->getRenderOrder() < it2->getRenderOrder();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void WorldClock::clear()
|
||||
{
|
||||
for (const auto animatable : _animatebles)
|
||||
{
|
||||
if (animatable != nullptr)
|
||||
{
|
||||
animatable->setClock(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldClock::setClock(WorldClock* value)
|
||||
{
|
||||
if (_clock == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_clock != nullptr)
|
||||
{
|
||||
_clock->remove(this);
|
||||
}
|
||||
|
||||
_clock = value;
|
||||
|
||||
if (_clock != nullptr)
|
||||
{
|
||||
_clock->add(this);
|
||||
}
|
||||
}
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2012-2018 DragonBones team and other contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DRAGONBONES_WORLD_CLOCK_H
|
||||
#define DRAGONBONES_WORLD_CLOCK_H
|
||||
|
||||
#include "../core/DragonBones.h"
|
||||
#include "IAnimatable.h"
|
||||
|
||||
DRAGONBONES_NAMESPACE_BEGIN
|
||||
/**
|
||||
* - Worldclock provides clock support for animations, advance time for each IAnimatable object added to the instance.
|
||||
* @see dragonBones.IAnimateble
|
||||
* @see dragonBones.Armature
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - WorldClock 对动画提供时钟支持,为每个加入到该实例的 IAnimatable 对象更新时间。
|
||||
* @see dragonBones.IAnimateble
|
||||
* @see dragonBones.Armature
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
class WorldClock : public IAnimatable
|
||||
{
|
||||
DRAGONBONES_DISALLOW_COPY_AND_ASSIGN(WorldClock)
|
||||
|
||||
public:
|
||||
/**
|
||||
* - Deprecated, please refer to {@link dragonBones.BaseFactory#clock}.
|
||||
* @deprecated
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 已废弃,请参考 {@link dragonBones.BaseFactory#clock}。
|
||||
* @deprecated
|
||||
* @language zh_CN
|
||||
*/
|
||||
static WorldClock clock;
|
||||
|
||||
public:
|
||||
/**
|
||||
* - Current time. (In seconds)
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 当前的时间。 (以秒为单位)
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
float time;
|
||||
/**
|
||||
* - The play speed, used to control animation speed-shift play.
|
||||
* [0: Stop play, (0~1): Slow play, 1: Normal play, (1~N): Fast play]
|
||||
* @default 1.0
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 播放速度,用于控制动画变速播放。
|
||||
* [0: 停止播放, (0~1): 慢速播放, 1: 正常播放, (1~N): 快速播放]
|
||||
* @default 1.0
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
float timeScale;
|
||||
|
||||
private:
|
||||
float _systemTime;
|
||||
std::vector<IAnimatable*> _animatebles;
|
||||
WorldClock* _clock;
|
||||
|
||||
public:
|
||||
/**
|
||||
* - Creating a Worldclock instance. Typically, you do not need to create Worldclock instance.
|
||||
* When multiple Worldclock instances are running at different speeds, can achieving some specific animation effects, such as bullet time.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 创建一个 WorldClock 实例。通常并不需要创建 WorldClock 实例。
|
||||
* 当多个 WorldClock 实例使用不同的速度运行时,可以实现一些特殊的动画效果,比如子弹时间等。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
WorldClock(float timeValue = 0.0f) :
|
||||
time(timeValue),
|
||||
timeScale(1.0f),
|
||||
_systemTime(0.0f),
|
||||
_animatebles(),
|
||||
_clock(nullptr)
|
||||
{
|
||||
_systemTime = 0.0f;
|
||||
}
|
||||
virtual ~WorldClock()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
/**
|
||||
* - Advance time for all IAnimatable instances.
|
||||
* @param passedTime - Passed time. [-1: Automatically calculates the time difference between the current frame and the previous frame, [0~N): Passed time] (In seconds)
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 为所有的 IAnimatable 实例更新时间。
|
||||
* @param passedTime - 前进的时间。 [-1: 自动计算当前帧与上一帧的时间差, [0~N): 前进的时间] (以秒为单位)
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
virtual void advanceTime(float passedTime) override;
|
||||
/**
|
||||
* - render all IAnimatable instances.
|
||||
* @version Cocos creator 2.3
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 渲染所有的 IAnimatable 实例。
|
||||
* @version Cocos creator 2.3
|
||||
* @language zh_CN
|
||||
*/
|
||||
virtual void render() override;
|
||||
|
||||
/**
|
||||
* - Check whether contains a specific instance of IAnimatable.
|
||||
* @param value - The IAnimatable instance.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 检查是否包含特定的 IAnimatable 实例。
|
||||
* @param value - IAnimatable 实例。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
bool contains(const IAnimatable* value) const;
|
||||
/**
|
||||
* - Add IAnimatable instance.
|
||||
* @param value - The IAnimatable instance.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 添加 IAnimatable 实例。
|
||||
* @param value - IAnimatable 实例。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void add(IAnimatable* value);
|
||||
/**
|
||||
* - Removes a specified IAnimatable instance.
|
||||
* @param value - The IAnimatable instance.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 移除特定的 IAnimatable 实例。
|
||||
* @param value - IAnimatable 实例。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void remove(IAnimatable* value);
|
||||
/**
|
||||
* - Clear all IAnimatable instances.
|
||||
* @version DragonBones 3.0
|
||||
* @language en_US
|
||||
*/
|
||||
/**
|
||||
* - 清除所有的 IAnimatable 实例。
|
||||
* @version DragonBones 3.0
|
||||
* @language zh_CN
|
||||
*/
|
||||
void clear();
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
inline virtual WorldClock* getClock() const override
|
||||
{
|
||||
return _clock;
|
||||
}
|
||||
virtual void setClock(WorldClock* value) override;
|
||||
|
||||
public: // For WebAssembly.
|
||||
static WorldClock* getStaticClock() { return &clock; }
|
||||
};
|
||||
|
||||
DRAGONBONES_NAMESPACE_END
|
||||
#endif // DRAGONBONES_WORLD_CLOCK_H
|
Reference in New Issue
Block a user