axmol/extensions/DragonBones/animation/TimelineState.cpp

1045 lines
36 KiB
C++

#include "TimelineState.h"
#include "WorldClock.h"
#include "Animation.h"
#include "../model/DragonBonesData.h"
#include "../model/UserData.h"
#include "../model/ArmatureData.h"
#include "../model/ConstraintData.h"
#include "../model/DisplayData.h"
#include "../model/AnimationData.h"
#include "../event/EventObject.h"
#include "../event/IEventDispatcher.h"
#include "../armature/Armature.h"
#include "../armature/Bone.h"
#include "../armature/Slot.h"
#include "../armature/Constraint.h"
#include "../armature/DeformVertices.h"
#include "AnimationState.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];
_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