axmol/extensions/DragonBones/animation/BaseTimelineState.cpp

345 lines
11 KiB
C++
Raw Normal View History

2021-12-24 21:11:44 +08:00
#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()
{
2021-12-25 10:04:45 +08:00
playState = -1;
currentPlayTimes = -1;
2021-12-25 10:04:45 +08:00
currentTime = -1.0f;
2021-12-25 10:04:45 +08:00
_tweenState = TweenState::None;
_frameRate = 0;
_frameValueOffset = 0;
2021-12-25 10:04:45 +08:00
_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)
{
2021-12-25 10:04:45 +08:00
const auto prevState = playState;
const auto prevPlayTimes = currentPlayTimes;
2021-12-25 10:04:45 +08:00
const auto prevTime = currentTime;
2021-12-25 10:04:45 +08:00
if (_actionTimeline != nullptr && _frameCount <= 1) // No frame or only one frame.
{
2021-12-25 10:04:45 +08:00
playState = _actionTimeline->playState >= 0 ? 1 : -1;
currentPlayTimes = 1;
2021-12-25 10:04:45 +08:00
currentTime = _actionTimeline->currentTime;
}
2021-12-25 10:04:45 +08:00
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;
2021-12-25 10:04:45 +08:00
if (_timeOffset != 0.0f)
{
passedTime += _timeOffset * _animationData->duration;
}
2021-12-25 10:04:45 +08:00
if (playTimes > 0 && (passedTime >= totalTime || passedTime <= -totalTime))
{
2021-12-25 10:04:45 +08:00
if (playState <= 0 && _animationState->_playheadState == 3)
{
playState = 1;
}
currentPlayTimes = playTimes;
2021-12-25 10:04:45 +08:00
if (passedTime < 0.0f)
{
currentTime = 0.0f;
}
2021-12-25 10:04:45 +08:00
else
{
2021-12-25 10:04:45 +08:00
currentTime = _duration + 0.000001f; // Precision problem
}
}
2021-12-25 10:04:45 +08:00
else
{
if (playState != 0 && _animationState->_playheadState == 3)
{
playState = 0;
}
if (passedTime < 0.0f)
{
2021-12-25 10:04:45 +08:00
passedTime = -passedTime;
currentPlayTimes = (int)(passedTime / _duration);
2021-12-25 10:04:45 +08:00
currentTime = _duration - fmod(passedTime, _duration);
}
2021-12-25 10:04:45 +08:00
else
{
currentPlayTimes = (int)(passedTime / _duration);
2021-12-25 10:04:45 +08:00
currentTime = fmod(passedTime, _duration);
}
}
currentTime += _position;
}
2021-12-25 10:04:45 +08:00
else // Multi frames.
{
2021-12-25 10:04:45 +08:00
playState = _actionTimeline->playState;
currentPlayTimes = _actionTimeline->currentPlayTimes;
2021-12-25 10:04:45 +08:00
currentTime = _actionTimeline->currentTime;
}
2021-12-25 10:04:45 +08:00
if (currentPlayTimes == prevPlayTimes && currentTime == prevTime)
{
return false;
}
// Clear frame flag when timeline start or loopComplete.
2021-12-25 10:04:45 +08:00
if ((prevState < 0 && playState != prevState) || (playState <= 0 && currentPlayTimes != prevPlayTimes))
{
_frameIndex = -1;
}
return true;
}
void TimelineState::init(Armature* armature, AnimationState* animationState, TimelineData* timelineData)
{
2021-12-25 10:04:45 +08:00
_armature = armature;
_animationState = animationState;
2021-12-25 10:04:45 +08:00
_timelineData = timelineData;
_actionTimeline = _animationState->_actionTimeline;
2021-12-25 10:04:45 +08:00
if (this == _actionTimeline)
{
2021-12-25 10:04:45 +08:00
_actionTimeline = nullptr; //
}
_animationData = _animationState->_animationData;
2021-12-25 10:04:45 +08:00
_frameRate = _animationData->parent->frameRate;
_frameRateR = 1.0f / _frameRate;
_position = _animationState->_position;
_duration = _animationState->_duration;
_dragonBonesData = _animationData->parent->parent;
2021-12-25 10:04:45 +08:00
if (_timelineData != nullptr)
{
2021-12-25 10:04:45 +08:00
_frameIntArray = _dragonBonesData->frameIntArray;
_frameFloatArray = _dragonBonesData->frameFloatArray;
2021-12-25 10:04:45 +08:00
_frameArray = _dragonBonesData->frameArray;
_timelineArray = _dragonBonesData->timelineArray;
_frameIndices = &(_dragonBonesData->frameIndices);
2021-12-25 10:04:45 +08:00
_frameCount = _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineKeyFrameCount];
_frameValueOffset = _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameValueOffset];
2021-12-25 10:04:45 +08:00
_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))
{
2021-12-25 10:04:45 +08:00
if (_frameCount > 1)
{
const auto timelineFrameIndex = (unsigned)(currentTime * _frameRate);
2021-12-25 10:04:45 +08:00
const auto frameIndex = (*_frameIndices)[_timelineData->frameIndicesOffset + timelineFrameIndex];
if ((unsigned)_frameIndex != frameIndex)
{
_frameIndex = frameIndex;
2021-12-25 10:04:45 +08:00
_frameOffset =
_animationData->frameOffset +
_timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + _frameIndex];
_onArriveAtFrame();
}
}
2021-12-25 10:04:45 +08:00
else if (_frameIndex < 0)
{
_frameIndex = 0;
2021-12-25 10:04:45 +08:00
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();
2021-12-25 10:04:45 +08:00
_tweenType = TweenType::None;
_curveCount = 0;
_framePosition = 0.0f;
_frameDurationR = 0.0f;
2021-12-25 10:04:45 +08:00
_tweenProgress = 0.0f;
_tweenEasing = 0.0f;
}
void TweenTimelineState::_onArriveAtFrame()
{
2021-12-25 10:04:45 +08:00
if (_frameCount > 1 && ((unsigned)_frameIndex != _frameCount - 1 || _animationState->playTimes == 0 ||
_animationState->getCurrentPlayTimes() < _animationState->playTimes - 1))
{
2021-12-25 10:04:45 +08:00
_tweenType = (TweenType)
_frameArray[_frameOffset + (unsigned)BinaryOffset::FrameTweenType]; // TODO recode ture tween type.
_tweenState = _tweenType == TweenType::None ? TweenState::Once : TweenState::Always;
2021-12-25 10:04:45 +08:00
if (_tweenType == TweenType::Curve)
{
_curveCount = _frameArray[_frameOffset + (unsigned)BinaryOffset::FrameTweenEasingOrCurveSampleCount];
}
2021-12-25 10:04:45 +08:00
else if (_tweenType != TweenType::None && _tweenType != TweenType::Line)
{
2021-12-25 10:04:45 +08:00
_tweenEasing =
_frameArray[_frameOffset + (unsigned)BinaryOffset::FrameTweenEasingOrCurveSampleCount] * 0.01;
}
_framePosition = _frameArray[_frameOffset] * _frameRateR;
if ((unsigned)_frameIndex == _frameCount - 1)
{
_frameDurationR = 1.0f / (_animationData->duration - _framePosition);
}
2021-12-25 10:04:45 +08:00
else
{
2021-12-25 10:04:45 +08:00
const auto nextFrameOffset =
_animationData->frameOffset +
_timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + _frameIndex + 1];
const auto frameDuration = _frameArray[nextFrameOffset] * _frameRateR - _framePosition;
2021-12-25 10:04:45 +08:00
if (frameDuration > 0.0f) // Fixed animation data bug.
{
_frameDurationR = 1.0f / frameDuration;
}
2021-12-25 10:04:45 +08:00
else
{
_frameDurationR = 0.0f;
}
}
}
2021-12-25 10:04:45 +08:00
else
{
_tweenState = TweenState::Once;
}
}
void TweenTimelineState::_onUpdateFrame()
{
2021-12-25 10:04:45 +08:00
if (_tweenState == TweenState::Always)
{
_tweenProgress = (currentTime - _framePosition) * _frameDurationR;
if (_tweenType == TweenType::Curve)
{
2021-12-25 10:04:45 +08:00
_tweenProgress = TweenTimelineState::_getEasingCurveValue(
_tweenProgress, _frameArray, _curveCount, _frameOffset + (unsigned)BinaryOffset::FrameCurveSamples);
}
else if (_tweenType != TweenType::Line)
{
_tweenProgress = TweenTimelineState::_getEasingValue(_tweenType, _tweenProgress, _tweenEasing);
}
}
2021-12-25 10:04:45 +08:00
else
{
_tweenProgress = 0.0f;
}
}
void BoneTimelineState::_onClear()
{
TweenTimelineState::_onClear();
2021-12-25 10:04:45 +08:00
bone = nullptr;
bonePose = nullptr;
}
void BoneTimelineState::blend(int state)
{
const auto blendWeight = bone->_blendState.blendWeight;
2021-12-25 10:04:45 +08:00
auto& animationPose = bone->animationPose;
const auto& result = bonePose->result;
2021-12-25 10:04:45 +08:00
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;
}
2021-12-25 10:04:45 +08:00
else if (blendWeight != 1.0f)
{
2021-12-25 10:04:45 +08:00
animationPose.x = result.x * blendWeight;
animationPose.y = result.y * blendWeight;
animationPose.rotation = result.rotation * blendWeight;
2021-12-25 10:04:45 +08:00
animationPose.skew = result.skew * blendWeight;
animationPose.scaleX = (result.scaleX - 1.0f) * blendWeight + 1.0f;
animationPose.scaleY = (result.scaleY - 1.0f) * blendWeight + 1.0f;
}
2021-12-25 10:04:45 +08:00
else
{
2021-12-25 10:04:45 +08:00
animationPose.x = result.x;
animationPose.y = result.y;
animationPose.rotation = result.rotation;
2021-12-25 10:04:45 +08:00
animationPose.skew = result.skew;
animationPose.scaleX = result.scaleX;
animationPose.scaleY = result.scaleY;
}
if (_animationState->_fadeState != 0 || _animationState->_subFadeState != 0)
{
bone->_transformDirty = true;
}
}
2021-12-25 10:04:45 +08:00
void SlotTimelineState::_onClear()
{
TweenTimelineState::_onClear();
slot = nullptr;
}
void ConstraintTimelineState::_onClear()
{
TweenTimelineState::_onClear();
constraint = nullptr;
}
DRAGONBONES_NAMESPACE_END