You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

852 lines
33 KiB

#include "TimelineState.h"
#include "../armature/Armature.h"
#include "../armature/Bone.h"
#include "../armature/Constraint.h"
#include "../armature/DeformVertices.h"
#include "../armature/Slot.h"
#include "../event/EventObject.h"
#include "../event/IEventDispatcher.h"
#include "../model/AnimationData.h"
#include "../model/ArmatureData.h"
#include "../model/ConstraintData.h"
#include "../model/DisplayData.h"
#include "../model/DragonBonesData.h"
#include "../model/UserData.h"
#include "Animation.h"
#include "AnimationState.h"
#include "WorldClock.h"
DRAGONBONES_NAMESPACE_BEGIN
void ActionTimelineState::_onCrossFrame(unsigned frameIndex) const {
const auto eventDispatcher = _armature->getProxy();
if (_animationState->actionEnabled) {
const auto frameOffset = _animationData->frameOffset + _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + frameIndex];
const unsigned actionCount = _frameArray[frameOffset + 1];
const auto& actions = _animationData->parent->actions; // May be the animaton data not belong to this armature data.
for (std::size_t i = 0; i < actionCount; ++i) {
const auto actionIndex = _frameArray[frameOffset + 2 + i];
const auto action = actions[actionIndex];
if (action->type == ActionType::Play) {
const auto eventObject = BaseObject::borrowObject<EventObject>();
// eventObject->time = _frameArray[frameOffset] * _frameRateR; // Precision problem
eventObject->time = _frameArray[frameOffset] / _frameRate;
eventObject->animationState = _animationState;
EventObject::actionDataToInstance(action, eventObject, _armature);
_armature->_bufferAction(eventObject, true);
} else {
const auto eventType = action->type == ActionType::Frame ? EventObject::FRAME_EVENT : EventObject::SOUND_EVENT;
if (action->type == ActionType::Sound || eventDispatcher->hasDBEventListener(eventType)) {
const auto eventObject = BaseObject::borrowObject<EventObject>();
// eventObject->time = _frameArray[frameOffset] * _frameRateR; // Precision problem
eventObject->time = _frameArray[frameOffset] / _frameRate;
eventObject->animationState = _animationState;
EventObject::actionDataToInstance(action, eventObject, _armature);
_armature->_dragonBones->bufferEvent(eventObject);
}
}
}
}
}
void ActionTimelineState::update(float passedTime) {
const auto prevState = playState;
auto prevPlayTimes = currentPlayTimes;
auto prevTime = currentTime;
if (_setCurrentTime(passedTime)) {
const auto eventDispatcher = _armature->getProxy();
if (prevState < 0) {
if (playState != prevState) {
if (_animationState->displayControl && _animationState->resetToPose) // Reset zorder to pose.
{
_armature->_sortZOrder(nullptr, 0);
}
prevPlayTimes = currentPlayTimes;
if (eventDispatcher->hasDBEventListener(EventObject::START)) {
const auto eventObject = BaseObject::borrowObject<EventObject>();
eventObject->type = EventObject::START;
eventObject->armature = _armature;
eventObject->animationState = _animationState;
_armature->_dragonBones->bufferEvent(eventObject);
}
} else {
return;
}
}
const auto isReverse = _animationState->timeScale < 0.0f;
EventObject* loopCompleteEvent = nullptr;
EventObject* completeEvent = nullptr;
if (currentPlayTimes != prevPlayTimes) {
if (eventDispatcher->hasDBEventListener(EventObject::LOOP_COMPLETE)) {
loopCompleteEvent = BaseObject::borrowObject<EventObject>();
loopCompleteEvent->type = EventObject::LOOP_COMPLETE;
loopCompleteEvent->armature = _armature;
loopCompleteEvent->animationState = _animationState;
}
if (playState > 0) {
if (eventDispatcher->hasDBEventListener(EventObject::COMPLETE)) {
completeEvent = BaseObject::borrowObject<EventObject>();
completeEvent->type = EventObject::COMPLETE;
completeEvent->armature = _armature;
completeEvent->animationState = _animationState;
}
}
}
if (_frameCount > 1) {
const auto timelineData = _timelineData;
const auto timelineFrameIndex = (unsigned)(currentTime * _frameRate); // uint
const auto frameIndex = (*_frameIndices)[timelineData->frameIndicesOffset + timelineFrameIndex];
if ((unsigned)_frameIndex != frameIndex) // Arrive at frame.
{
auto crossedFrameIndex = _frameIndex;
_frameIndex = frameIndex;
if (_timelineArray != nullptr) {
_frameOffset = _animationData->frameOffset + _timelineArray[timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + _frameIndex];
if (isReverse) {
if (crossedFrameIndex < 0) {
const auto prevFrameIndex = (unsigned)(prevTime * _frameRate);
crossedFrameIndex = (*_frameIndices)[timelineData->frameIndicesOffset + prevFrameIndex];
if (currentPlayTimes == prevPlayTimes) // Start.
{
if ((unsigned)crossedFrameIndex == frameIndex) // Uncrossed.
{
crossedFrameIndex = -1;
}
}
}
while (crossedFrameIndex >= 0) {
const auto frameOffset = _animationData->frameOffset + _timelineArray[timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + crossedFrameIndex];
const auto framePosition = (float)_frameArray[frameOffset] / _frameRate;
if (
_position <= framePosition &&
framePosition <= _position + _duration) // Support interval play.
{
_onCrossFrame(crossedFrameIndex);
}
if (loopCompleteEvent != nullptr && crossedFrameIndex == 0) // Add loop complete event after first frame.
{
_armature->_dragonBones->bufferEvent(loopCompleteEvent);
loopCompleteEvent = nullptr;
}
if (crossedFrameIndex > 0) {
crossedFrameIndex--;
} else {
crossedFrameIndex = _frameCount - 1;
}
if ((unsigned)crossedFrameIndex == frameIndex) {
break;
}
}
} else {
if (crossedFrameIndex < 0) {
const auto prevFrameIndex = (unsigned)(prevTime * _frameRate);
crossedFrameIndex = (*_frameIndices)[timelineData->frameIndicesOffset + prevFrameIndex];
const auto frameOffset = _animationData->frameOffset + _timelineArray[timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + crossedFrameIndex];
const auto framePosition = (float)_frameArray[frameOffset] / _frameRate;
if (currentPlayTimes == prevPlayTimes) // Start.
{
if (prevTime <= framePosition) // Crossed.
{
if (crossedFrameIndex > 0) {
crossedFrameIndex--;
} else {
crossedFrameIndex = _frameCount - 1;
}
} else if ((unsigned)crossedFrameIndex == frameIndex) // Uncrossed.
{
crossedFrameIndex = -1;
}
}
}
while (crossedFrameIndex >= 0) {
if ((unsigned)crossedFrameIndex < _frameCount - 1) {
crossedFrameIndex++;
} else {
crossedFrameIndex = 0;
}
const auto frameOffset = _animationData->frameOffset + _timelineArray[timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset + crossedFrameIndex];
const auto framePosition = (float)_frameArray[frameOffset] / _frameRate;
if (
_position <= framePosition &&
framePosition <= _position + _duration) // Support interval play.
{
_onCrossFrame(crossedFrameIndex);
}
if (loopCompleteEvent != nullptr && crossedFrameIndex == 0) // Add loop complete event before first frame.
{
_armature->_dragonBones->bufferEvent(loopCompleteEvent);
loopCompleteEvent = nullptr;
}
if ((unsigned)crossedFrameIndex == frameIndex) {
break;
}
}
}
}
}
} else if (_frameIndex < 0) {
_frameIndex = 0;
if (_timelineData != nullptr) {
_frameOffset = _animationData->frameOffset + _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameOffset];
// Arrive at frame.
const auto framePosition = (float)_frameArray[_frameOffset] / _frameRate;
if (currentPlayTimes == prevPlayTimes) // Start.
{
if (prevTime <= framePosition) {
_onCrossFrame(_frameIndex);
}
} else if (_position <= framePosition) // Loop complete.
{
if (!isReverse && loopCompleteEvent != nullptr) // Add loop complete event before first frame.
{
_armature->_dragonBones->bufferEvent(loopCompleteEvent);
loopCompleteEvent = nullptr;
}
_onCrossFrame(_frameIndex);
}
}
}
if (loopCompleteEvent != nullptr) {
_armature->_dragonBones->bufferEvent(loopCompleteEvent);
}
if (completeEvent != nullptr) {
_armature->_dragonBones->bufferEvent(completeEvent);
}
}
}
void ActionTimelineState::setCurrentTime(float value) {
_setCurrentTime(value);
_frameIndex = -1;
}
void ZOrderTimelineState::_onArriveAtFrame() {
if (playState >= 0) {
const auto count = _frameArray[_frameOffset + 1];
if (count > 0) {
_armature->_sortZOrder(_frameArray, _frameOffset + 2);
} else {
_armature->_sortZOrder(nullptr, 0);
}
}
}
void BoneAllTimelineState::_onArriveAtFrame() {
BoneTimelineState::_onArriveAtFrame();
if (_timelineData != nullptr) {
auto valueOffset = _animationData->frameFloatOffset + _frameValueOffset + _frameIndex * 6; // ...(timeline value offset)|xxxxxx|xxxxxx|(Value offset)xxxxx|(Next offset)xxxxx|xxxxxx|xxxxxx|...
const auto scale = _armature->_armatureData->scale;
const auto frameFloatArray = _frameFloatArray;
auto& current = bonePose->current;
auto& delta = bonePose->delta;
//
current.x = frameFloatArray[valueOffset++] * scale;
current.y = frameFloatArray[valueOffset++] * scale;
current.rotation = frameFloatArray[valueOffset++];
current.skew = frameFloatArray[valueOffset++];
current.scaleX = frameFloatArray[valueOffset++];
current.scaleY = frameFloatArray[valueOffset++];
if (_tweenState == TweenState::Always) {
if ((unsigned)_frameIndex == _frameCount - 1) {
valueOffset = _animationData->frameFloatOffset + _frameValueOffset;
}
delta.x = frameFloatArray[valueOffset++] * scale - current.x;
delta.y = frameFloatArray[valueOffset++] * scale - current.y;
delta.rotation = frameFloatArray[valueOffset++] - current.rotation;
delta.skew = frameFloatArray[valueOffset++] - current.skew;
delta.scaleX = frameFloatArray[valueOffset++] - current.scaleX;
delta.scaleY = frameFloatArray[valueOffset++] - current.scaleY;
} else {
delta.x = 0.0f;
delta.y = 0.0f;
delta.rotation = 0.0f;
delta.skew = 0.0f;
delta.scaleX = 0.0f;
delta.scaleY = 0.0f;
}
} else {
auto& current = bonePose->current;
auto& delta = bonePose->delta;
current.x = 0.0f;
current.y = 0.0f;
current.rotation = 0.0f;
current.skew = 0.0f;
current.scaleX = 1.0f;
current.scaleY = 1.0f;
delta.x = 0.0f;
delta.y = 0.0f;
delta.rotation = 0.0f;
delta.skew = 0.0f;
delta.scaleX = 0.0f;
delta.scaleY = 0.0f;
}
}
void BoneAllTimelineState::_onUpdateFrame() {
BoneTimelineState::_onUpdateFrame();
auto& current = bonePose->current;
auto& delta = bonePose->delta;
auto& result = bonePose->result;
bone->_transformDirty = true;
if (_tweenState != TweenState::Always) {
_tweenState = TweenState::None;
}
result.x = current.x + delta.x * _tweenProgress;
result.y = current.y + delta.y * _tweenProgress;
result.rotation = current.rotation + delta.rotation * _tweenProgress;
result.skew = current.skew + delta.skew * _tweenProgress;
result.scaleX = current.scaleX + delta.scaleX * _tweenProgress;
result.scaleY = current.scaleY + delta.scaleY * _tweenProgress;
}
void BoneAllTimelineState::fadeOut() {
auto& result = bonePose->result;
result.rotation = Transform::normalizeRadian(result.rotation);
result.skew = Transform::normalizeRadian(result.skew);
}
void BoneTranslateTimelineState::_onArriveAtFrame() {
BoneTimelineState::_onArriveAtFrame();
if (_timelineData != nullptr) {
auto valueOffset = _animationData->frameFloatOffset + _frameValueOffset + _frameIndex * 2;
const auto scale = _armature->_armatureData->scale;
const auto frameFloatArray = _frameFloatArray;
auto& current = bonePose->current;
auto& delta = bonePose->delta;
current.x = frameFloatArray[valueOffset++] * scale;
current.y = frameFloatArray[valueOffset++] * scale;
if (_tweenState == TweenState::Always) {
if ((unsigned)_frameIndex == _frameCount - 1) {
valueOffset = _animationData->frameFloatOffset + _frameValueOffset; // + 0 * 2
}
delta.x = frameFloatArray[valueOffset++] * scale - current.x;
delta.y = frameFloatArray[valueOffset++] * scale - current.y;
} else {
delta.x = 0.0f;
delta.y = 0.0f;
}
} else {
auto& current = bonePose->current;
auto& delta = bonePose->delta;
current.x = 0.0f;
current.y = 0.0f;
delta.x = 0.0f;
delta.y = 0.0f;
}
}
void BoneTranslateTimelineState::_onUpdateFrame() {
BoneTimelineState::_onUpdateFrame();
auto& current = bonePose->current;
auto& delta = bonePose->delta;
auto& result = bonePose->result;
bone->_transformDirty = true;
if (_tweenState != TweenState::Always) {
_tweenState = TweenState::None;
}
result.x = current.x + delta.x * _tweenProgress;
result.y = current.y + delta.y * _tweenProgress;
}
void BoneRotateTimelineState::_onArriveAtFrame() {
BoneTimelineState::_onArriveAtFrame();
if (_timelineData != nullptr) {
auto valueOffset = _animationData->frameFloatOffset + _frameValueOffset + _frameIndex * 2;
const auto frameFloatArray = _frameFloatArray;
auto& current = bonePose->current;
auto& delta = bonePose->delta;
current.rotation = frameFloatArray[valueOffset++];
current.skew = frameFloatArray[valueOffset++];
if (_tweenState == TweenState::Always) {
if ((unsigned)_frameIndex == _frameCount - 1) {
valueOffset = _animationData->frameFloatOffset + _frameValueOffset; // + 0 * 2
delta.rotation = Transform::normalizeRadian(frameFloatArray[valueOffset++] - current.rotation);
} else {
delta.rotation = frameFloatArray[valueOffset++] - current.rotation;
}
delta.skew = frameFloatArray[valueOffset++] - current.skew;
} else {
delta.rotation = 0.0f;
delta.skew = 0.0f;
}
} else {
auto& current = bonePose->current;
auto& delta = bonePose->delta;
current.rotation = 0.0f;
current.skew = 0.0f;
delta.rotation = 0.0f;
delta.skew = 0.0f;
}
}
void BoneRotateTimelineState::_onUpdateFrame() {
BoneTimelineState::_onUpdateFrame();
auto& current = bonePose->current;
auto& delta = bonePose->delta;
auto& result = bonePose->result;
bone->_transformDirty = true;
if (_tweenState != TweenState::Always) {
_tweenState = TweenState::None;
}
result.rotation = current.rotation + delta.rotation * _tweenProgress;
result.skew = current.skew + delta.skew * _tweenProgress;
}
void BoneRotateTimelineState::fadeOut() {
auto& result = bonePose->result;
result.rotation = Transform::normalizeRadian(result.rotation);
result.skew = Transform::normalizeRadian(result.skew);
}
void BoneScaleTimelineState::_onArriveAtFrame() {
BoneTimelineState::_onArriveAtFrame();
if (_timelineData != nullptr) {
auto valueOffset = _animationData->frameFloatOffset + _frameValueOffset + _frameIndex * 2;
const auto frameFloatArray = _frameFloatArray;
auto& current = bonePose->current;
auto& delta = bonePose->delta;
current.scaleX = frameFloatArray[valueOffset++];
current.scaleY = frameFloatArray[valueOffset++];
if (_tweenState == TweenState::Always) {
if ((unsigned)_frameIndex == _frameCount - 1) {
valueOffset = _animationData->frameFloatOffset + _frameValueOffset; // + 0 * 2
}
delta.scaleX = frameFloatArray[valueOffset++] - current.scaleX;
delta.scaleY = frameFloatArray[valueOffset++] - current.scaleY;
} else {
delta.scaleX = 0.0f;
delta.scaleY = 0.0f;
}
} else {
auto& current = bonePose->current;
auto& delta = bonePose->delta;
current.scaleX = 1.0f;
current.scaleY = 1.0f;
delta.scaleX = 0.0f;
delta.scaleY = 0.0f;
}
}
void BoneScaleTimelineState::_onUpdateFrame() {
BoneTimelineState::_onUpdateFrame();
auto& current = bonePose->current;
auto& delta = bonePose->delta;
auto& result = bonePose->result;
bone->_transformDirty = true;
if (_tweenState != TweenState::Always) {
_tweenState = TweenState::None;
}
result.scaleX = current.scaleX + delta.scaleX * _tweenProgress;
result.scaleY = current.scaleY + delta.scaleY * _tweenProgress;
}
void SlotDislayTimelineState::_onArriveAtFrame() {
if (playState >= 0) {
const auto displayIndex = _timelineData != nullptr ? _frameArray[_frameOffset + 1] : slot->_slotData->displayIndex;
if (slot->getDisplayIndex() != displayIndex) {
slot->_setDisplayIndex(displayIndex, true);
}
}
}
void SlotColorTimelineState::_onClear() {
SlotTimelineState::_onClear();
_dirty = false;
}
void SlotColorTimelineState::_onArriveAtFrame() {
SlotTimelineState::_onArriveAtFrame();
if (_timelineData != nullptr) {
const auto intArray = _dragonBonesData->intArray;
const auto frameIntArray = _frameIntArray;
const auto valueOffset = _animationData->frameIntOffset + _frameValueOffset + _frameIndex * 1; // ...(timeline value offset)|x|x|(Value offset)|(Next offset)|x|x|...
int colorOffset = frameIntArray[valueOffset];
if (colorOffset < 0) {
colorOffset += 65536; // Fixed out of bouds bug.
}
_current[0] = intArray[colorOffset++];
_current[1] = intArray[colorOffset++];
_current[2] = intArray[colorOffset++];
_current[3] = intArray[colorOffset++];
_current[4] = intArray[colorOffset++];
_current[5] = intArray[colorOffset++];
_current[6] = intArray[colorOffset++];
_current[7] = intArray[colorOffset++];
if (_tweenState == TweenState::Always) {
if ((unsigned)_frameIndex == _frameCount - 1) {
colorOffset = frameIntArray[_animationData->frameIntOffset + _frameValueOffset];
} else {
colorOffset = frameIntArray[valueOffset + 1 * 1];
}
if (colorOffset < 0) {
colorOffset += 65536; // Fixed out of bouds bug.
}
_delta[0] = intArray[colorOffset++] - _current[0];
_delta[1] = intArray[colorOffset++] - _current[1];
_delta[2] = intArray[colorOffset++] - _current[2];
_delta[3] = intArray[colorOffset++] - _current[3];
_delta[4] = intArray[colorOffset++] - _current[4];
_delta[5] = intArray[colorOffset++] - _current[5];
_delta[6] = intArray[colorOffset++] - _current[6];
_delta[7] = intArray[colorOffset++] - _current[7];
}
} else {
const auto color = slot->_slotData->color;
_current[0] = color->alphaMultiplier * 100.0f;
_current[1] = color->redMultiplier * 100.0f;
_current[2] = color->greenMultiplier * 100.0f;
_current[3] = color->blueMultiplier * 100.0f;
_current[4] = color->alphaOffset;
_current[5] = color->redOffset;
_current[6] = color->greenOffset;
_current[7] = color->blueOffset;
}
}
void SlotColorTimelineState::_onUpdateFrame() {
SlotTimelineState::_onUpdateFrame();
_dirty = true;
if (_tweenState != TweenState::Always) {
_tweenState = TweenState::None;
}
_result[0] = (_current[0] + _delta[0] * _tweenProgress) * 0.01f;
_result[1] = (_current[1] + _delta[1] * _tweenProgress) * 0.01f;
_result[2] = (_current[2] + _delta[2] * _tweenProgress) * 0.01f;
_result[3] = (_current[3] + _delta[3] * _tweenProgress) * 0.01f;
_result[4] = _current[4] + _delta[4] * _tweenProgress;
_result[5] = _current[5] + _delta[5] * _tweenProgress;
_result[6] = _current[6] + _delta[6] * _tweenProgress;
_result[7] = _current[7] + _delta[7] * _tweenProgress;
}
void SlotColorTimelineState::fadeOut() {
_tweenState = TweenState::None;
_dirty = false;
}
void SlotColorTimelineState::update(float passedTime) {
SlotTimelineState::update(passedTime);
// Fade animation.
if (_tweenState != TweenState::None || _dirty) {
auto& result = slot->_colorTransform;
if (_animationState->_fadeState != 0 || _animationState->_subFadeState != 0) {
if (
result.alphaMultiplier != _result[0] ||
result.redMultiplier != _result[1] ||
result.greenMultiplier != _result[2] ||
result.blueMultiplier != _result[3] ||
result.alphaOffset != _result[4] ||
result.redOffset != _result[5] ||
result.greenOffset != _result[6] ||
result.blueOffset != _result[7]) {
const auto fadeProgress = pow(_animationState->_fadeProgress, 2);
result.alphaMultiplier += (_result[0] - result.alphaMultiplier) * fadeProgress;
result.redMultiplier += (_result[1] - result.redMultiplier) * fadeProgress;
result.greenMultiplier += (_result[2] - result.greenMultiplier) * fadeProgress;
result.blueMultiplier += (_result[3] - result.blueMultiplier) * fadeProgress;
result.alphaOffset += (_result[4] - result.alphaOffset) * fadeProgress;
result.redOffset += (_result[5] - result.redOffset) * fadeProgress;
result.greenOffset += (_result[6] - result.greenOffset) * fadeProgress;
result.blueOffset += (_result[7] - result.blueOffset) * fadeProgress;
slot->_colorDirty = true;
}
} else if (_dirty) {
_dirty = false;
if (
result.alphaMultiplier != _result[0] ||
result.redMultiplier != _result[1] ||
result.greenMultiplier != _result[2] ||
result.blueMultiplier != _result[3] ||
result.alphaOffset != _result[4] ||
result.redOffset != _result[5] ||
result.greenOffset != _result[6] ||
result.blueOffset != _result[7]) {
result.alphaMultiplier = _result[0];
result.redMultiplier = _result[1];
result.greenMultiplier = _result[2];
result.blueMultiplier = _result[3];
result.alphaOffset = _result[4];
result.redOffset = _result[5];
result.greenOffset = _result[6];
result.blueOffset = _result[7];
slot->_colorDirty = true;
}
}
}
}
void DeformTimelineState::_onClear() {
SlotTimelineState::_onClear();
vertexOffset = 0;
_dirty = false;
_frameFloatOffset = 0;
_deformCount = 0;
_valueCount = 0;
_valueOffset = 0;
_current.clear();
_delta.clear();
_result.clear();
}
void DeformTimelineState::_onArriveAtFrame() {
SlotTimelineState::_onArriveAtFrame();
if (_timelineData != nullptr) {
const auto valueOffset = _animationData->frameFloatOffset + _frameValueOffset + _frameIndex * _valueCount;
const auto scale = _armature->_armatureData->scale;
const auto frameFloatArray = _frameFloatArray;
if (_tweenState == TweenState::Always) {
auto nextValueOffset = valueOffset + _valueCount;
if ((unsigned)_frameIndex == _frameCount - 1) {
nextValueOffset = _animationData->frameFloatOffset + _frameValueOffset;
}
for (std::size_t i = 0; i < _valueCount; ++i) {
_delta[i] = frameFloatArray[nextValueOffset + i] * scale - (_current[i] = frameFloatArray[valueOffset + i] * scale);
}
} else {
for (std::size_t i = 0; i < _valueCount; ++i) {
_current[i] = frameFloatArray[valueOffset + i] * scale;
}
}
} else {
for (std::size_t i = 0; i < _valueCount; ++i) {
_current[i] = 0.0f;
}
}
}
void DeformTimelineState::_onUpdateFrame() {
SlotTimelineState::_onUpdateFrame();
_dirty = true;
if (_tweenState != TweenState::Always) {
_tweenState = TweenState::None;
}
for (std::size_t i = 0; i < _valueCount; ++i) {
_result[i] = _current[i] + _delta[i] * _tweenProgress;
}
}
void DeformTimelineState::init(Armature* armature, AnimationState* animationState, TimelineData* timelineData) {
SlotTimelineState::init(armature, animationState, timelineData);
if (_timelineData != nullptr) {
const auto frameIntOffset = _animationData->frameIntOffset + _timelineArray[_timelineData->offset + (unsigned)BinaryOffset::TimelineFrameValueCount];
vertexOffset = _frameIntArray[frameIntOffset + (unsigned)BinaryOffset::DeformVertexOffset];
if (vertexOffset < 0) {
vertexOffset += 65536; // Fixed out of bouds bug.
}
_deformCount = _frameIntArray[frameIntOffset + (unsigned)BinaryOffset::DeformCount];
_valueCount = _frameIntArray[frameIntOffset + (unsigned)BinaryOffset::DeformValueCount];
_valueOffset = _frameIntArray[frameIntOffset + (unsigned)BinaryOffset::DeformValueOffset];
_frameFloatOffset = _frameIntArray[frameIntOffset + (unsigned)BinaryOffset::DeformFloatOffset] + _animationData->frameFloatOffset;
} else {
const auto deformVertices = slot->_deformVertices;
_deformCount = deformVertices != nullptr ? deformVertices->vertices.size() : 0;
_valueCount = _deformCount;
_valueOffset = 0;
_frameFloatOffset = 0;
}
_current.resize(_valueCount);
_delta.resize(_valueCount, 0.0f);
_result.resize(_valueCount);
}
void DeformTimelineState::fadeOut() {
_tweenState = TweenState::None;
_dirty = false;
}
void DeformTimelineState::update(float passedTime) {
const auto deformVertices = slot->_deformVertices;
if (deformVertices == nullptr || deformVertices->verticesData == nullptr || deformVertices->verticesData->offset != vertexOffset) {
return;
} else if (_timelineData != nullptr && _dragonBonesData != deformVertices->verticesData->data) {
return;
}
SlotTimelineState::update(passedTime);
// Fade animation.
if (_tweenState != TweenState::None || _dirty) {
auto& result = deformVertices->vertices;
if (_animationState->_fadeState != 0 || _animationState->_subFadeState != 0) {
const auto fadeProgress = pow(_animationState->_fadeProgress, 2);
if (_timelineData != nullptr) {
for (std::size_t i = 0; i < _deformCount; ++i) {
if (i < _valueOffset) {
result[i] += (_frameFloatArray[_frameFloatOffset + i] - result[i]) * fadeProgress;
} else if (i < _valueOffset + _valueCount) {
result[i] += (_result[i - _valueOffset] - result[i]) * fadeProgress;
} else {
result[i] += (_frameFloatArray[_frameFloatOffset + i - _valueCount] - result[i]) * fadeProgress;
}
}
} else {
_deformCount = result.size();
for (std::size_t i = 0; i < _deformCount; ++i) {
result[i] += (0.0f - result[i]) * fadeProgress;
}
}
deformVertices->verticesDirty = true;
} else if (_dirty) {
_dirty = false;
if (_timelineData != nullptr) {
for (std::size_t i = 0; i < _deformCount; ++i) {
if (i < _valueOffset) {
result[i] = _frameFloatArray[_frameFloatOffset + i];
} else if (i < _valueOffset + _valueCount) {
result[i] = _result[i - _valueOffset];
} else {
result[i] = _frameFloatArray[_frameFloatOffset + i - _valueCount];
}
}
} else {
_deformCount = result.size();
for (std::size_t i = 0; i < _deformCount; ++i) {
result[i] = 0.0f;
}
}
deformVertices->verticesDirty = true;
}
}
}
void IKConstraintTimelineState::_onClear() {
ConstraintTimelineState::_onClear();
_current = 0.0f;
_delta = 0.0f;
}
void IKConstraintTimelineState::_onArriveAtFrame() {
ConstraintTimelineState::_onArriveAtFrame();
const auto ikConstraint = static_cast<IKConstraint*>(constraint);
if (_timelineData != nullptr) {
auto valueOffset = _animationData->frameIntOffset + _frameValueOffset + _frameIndex * 2;
const auto frameIntArray = _frameIntArray;
const auto bendPositive = frameIntArray[valueOffset++] != 0;
_current = frameIntArray[valueOffset++] * 0.01f;
if (_tweenState == TweenState::Always) {
if ((unsigned)_frameIndex == _frameCount - 1) {
valueOffset = _animationData->frameIntOffset + _frameValueOffset; // + 0 * 2
}
_delta = frameIntArray[valueOffset + 1] * 0.01f - _current;
} else {
_delta = 0.0f;
}
ikConstraint->_bendPositive = bendPositive;
} else {
const auto ikConstraintData = static_cast<IKConstraintData*>(ikConstraint->_constraintData);
_current = ikConstraintData->weight;
_delta = 0.0f;
ikConstraint->_bendPositive = ikConstraintData->bendPositive;
}
ikConstraint->invalidUpdate();
}
void IKConstraintTimelineState::_onUpdateFrame() {
ConstraintTimelineState::_onUpdateFrame();
if (_tweenState != TweenState::Always) {
_tweenState = TweenState::None;
}
const auto ikConstraint = static_cast<IKConstraint*>(constraint);
ikConstraint->_weight = _current + _delta * _tweenProgress;
ikConstraint->invalidUpdate();
}
DRAGONBONES_NAMESPACE_END