dragonbones-runtime
Version:
the tools to build dragonbones file for diffrent framework
1,096 lines (945 loc) • 54.3 kB
text/typescript
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2017 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.
*/
namespace dragonBones {
/**
* @internal
* @private
*/
export class ActionTimelineState extends TimelineState {
public static toString(): string {
return "[class dragonBones.ActionTimelineState]";
}
private _onCrossFrame(frameIndex: number): void {
const eventDispatcher = this._armature.eventDispatcher;
if (this._animationState.actionEnabled) {
const frameOffset = this._animationData.frameOffset + this._timelineArray[(this._timelineData as TimelineData).offset + BinaryOffset.TimelineFrameOffset + frameIndex];
const actionCount = this._frameArray[frameOffset + 1];
const actions = this._animationData.parent.actions; // May be the animaton data not belong to this armature data.
for (let i = 0; i < actionCount; ++i) {
const actionIndex = this._frameArray[frameOffset + 2 + i];
const action = actions[actionIndex];
if (action.type === ActionType.Play) {
if (action.slot !== null) {
const slot = this._armature.getSlot(action.slot.name);
if (slot !== null) {
const childArmature = slot.childArmature;
if (childArmature !== null) {
childArmature._bufferAction(action, true);
}
}
}
else if (action.bone !== null) {
for (const slot of this._armature.getSlots()) {
const childArmature = slot.childArmature;
if (childArmature !== null && slot.parent._boneData === action.bone) {
childArmature._bufferAction(action, true);
}
}
}
else {
this._armature._bufferAction(action, true);
}
}
else {
const eventType = action.type === ActionType.Frame ? EventObject.FRAME_EVENT : EventObject.SOUND_EVENT;
if (action.type === ActionType.Sound || eventDispatcher.hasDBEventListener(eventType)) {
const eventObject = BaseObject.borrowObject(EventObject);
// eventObject.time = this._frameArray[frameOffset] * this._frameRateR; // Precision problem
eventObject.time = this._frameArray[frameOffset] / this._frameRate;
eventObject.type = eventType;
eventObject.name = action.name;
eventObject.data = action.data;
eventObject.armature = this._armature;
eventObject.animationState = this._animationState;
if (action.bone !== null) {
eventObject.bone = this._armature.getBone(action.bone.name);
}
if (action.slot !== null) {
eventObject.slot = this._armature.getSlot(action.slot.name);
}
this._armature._dragonBones.bufferEvent(eventObject);
}
}
}
}
}
protected _onArriveAtFrame(): void { }
protected _onUpdateFrame(): void { }
public update(passedTime: number): void {
const prevState = this.playState;
let prevPlayTimes = this.currentPlayTimes;
let prevTime = this.currentTime;
if (this._setCurrentTime(passedTime)) {
const eventDispatcher = this._armature.eventDispatcher;
if (prevState < 0) {
if (this.playState !== prevState) {
if (this._animationState.displayControl && this._animationState.resetToPose) { // Reset zorder to pose.
this._armature._sortZOrder(null, 0);
}
prevPlayTimes = this.currentPlayTimes;
if (eventDispatcher.hasDBEventListener(EventObject.START)) {
const eventObject = BaseObject.borrowObject(EventObject);
eventObject.type = EventObject.START;
eventObject.armature = this._armature;
eventObject.animationState = this._animationState;
this._armature._dragonBones.bufferEvent(eventObject);
}
}
else {
return;
}
}
const isReverse = this._animationState.timeScale < 0.0;
let loopCompleteEvent: EventObject | null = null;
let completeEvent: EventObject | null = null;
if (this.currentPlayTimes !== prevPlayTimes) {
if (eventDispatcher.hasDBEventListener(EventObject.LOOP_COMPLETE)) {
loopCompleteEvent = BaseObject.borrowObject(EventObject);
loopCompleteEvent.type = EventObject.LOOP_COMPLETE;
loopCompleteEvent.armature = this._armature;
loopCompleteEvent.animationState = this._animationState;
}
if (this.playState > 0) {
if (eventDispatcher.hasDBEventListener(EventObject.COMPLETE)) {
completeEvent = BaseObject.borrowObject(EventObject);
completeEvent.type = EventObject.COMPLETE;
completeEvent.armature = this._armature;
completeEvent.animationState = this._animationState;
}
}
}
if (this._frameCount > 1) {
const timelineData = this._timelineData as TimelineData;
const timelineFrameIndex = Math.floor(this.currentTime * this._frameRate); // uint
const frameIndex = this._frameIndices[timelineData.frameIndicesOffset + timelineFrameIndex];
if (this._frameIndex !== frameIndex) { // Arrive at frame.
let crossedFrameIndex = this._frameIndex;
this._frameIndex = frameIndex;
if (this._timelineArray !== null) {
this._frameOffset = this._animationData.frameOffset + this._timelineArray[timelineData.offset + BinaryOffset.TimelineFrameOffset + this._frameIndex];
if (isReverse) {
if (crossedFrameIndex < 0) {
const prevFrameIndex = Math.floor(prevTime * this._frameRate);
crossedFrameIndex = this._frameIndices[timelineData.frameIndicesOffset + prevFrameIndex];
if (this.currentPlayTimes === prevPlayTimes) { // Start.
if (crossedFrameIndex === frameIndex) { // Uncrossed.
crossedFrameIndex = -1;
}
}
}
while (crossedFrameIndex >= 0) {
const frameOffset = this._animationData.frameOffset + this._timelineArray[timelineData.offset + BinaryOffset.TimelineFrameOffset + crossedFrameIndex];
// const framePosition = this._frameArray[frameOffset] * this._frameRateR; // Precision problem
const framePosition = this._frameArray[frameOffset] / this._frameRate;
if (
this._position <= framePosition &&
framePosition <= this._position + this._duration
) { // Support interval play.
this._onCrossFrame(crossedFrameIndex);
}
if (loopCompleteEvent !== null && crossedFrameIndex === 0) { // Add loop complete event after first frame.
this._armature._dragonBones.bufferEvent(loopCompleteEvent);
loopCompleteEvent = null;
}
if (crossedFrameIndex > 0) {
crossedFrameIndex--;
}
else {
crossedFrameIndex = this._frameCount - 1;
}
if (crossedFrameIndex === frameIndex) {
break;
}
}
}
else {
if (crossedFrameIndex < 0) {
const prevFrameIndex = Math.floor(prevTime * this._frameRate);
crossedFrameIndex = this._frameIndices[timelineData.frameIndicesOffset + prevFrameIndex];
const frameOffset = this._animationData.frameOffset + this._timelineArray[timelineData.offset + BinaryOffset.TimelineFrameOffset + crossedFrameIndex];
// const framePosition = this._frameArray[frameOffset] * this._frameRateR; // Precision problem
const framePosition = this._frameArray[frameOffset] / this._frameRate;
if (this.currentPlayTimes === prevPlayTimes) { // Start.
if (prevTime <= framePosition) { // Crossed.
if (crossedFrameIndex > 0) {
crossedFrameIndex--;
}
else {
crossedFrameIndex = this._frameCount - 1;
}
}
else if (crossedFrameIndex === frameIndex) { // Uncrossed.
crossedFrameIndex = -1;
}
}
}
while (crossedFrameIndex >= 0) {
if (crossedFrameIndex < this._frameCount - 1) {
crossedFrameIndex++;
}
else {
crossedFrameIndex = 0;
}
const frameOffset = this._animationData.frameOffset + this._timelineArray[timelineData.offset + BinaryOffset.TimelineFrameOffset + crossedFrameIndex];
// const framePosition = this._frameArray[frameOffset] * this._frameRateR; // Precision problem
const framePosition = this._frameArray[frameOffset] / this._frameRate;
if (
this._position <= framePosition &&
framePosition <= this._position + this._duration
) { // Support interval play.
this._onCrossFrame(crossedFrameIndex);
}
if (loopCompleteEvent !== null && crossedFrameIndex === 0) { // Add loop complete event before first frame.
this._armature._dragonBones.bufferEvent(loopCompleteEvent);
loopCompleteEvent = null;
}
if (crossedFrameIndex === frameIndex) {
break;
}
}
}
}
}
}
else if (this._frameIndex < 0) {
this._frameIndex = 0;
if (this._timelineData !== null) {
this._frameOffset = this._animationData.frameOffset + this._timelineArray[this._timelineData.offset + BinaryOffset.TimelineFrameOffset];
// Arrive at frame.
const framePosition = this._frameArray[this._frameOffset] / this._frameRate;
if (this.currentPlayTimes === prevPlayTimes) { // Start.
if (prevTime <= framePosition) {
this._onCrossFrame(this._frameIndex);
}
}
else if (this._position <= framePosition) { // Loop complete.
if (!isReverse && loopCompleteEvent !== null) { // Add loop complete event before first frame.
this._armature._dragonBones.bufferEvent(loopCompleteEvent);
loopCompleteEvent = null;
}
this._onCrossFrame(this._frameIndex);
}
}
}
if (loopCompleteEvent !== null) {
this._armature._dragonBones.bufferEvent(loopCompleteEvent);
}
if (completeEvent !== null) {
this._armature._dragonBones.bufferEvent(completeEvent);
}
}
}
public setCurrentTime(value: number): void {
this._setCurrentTime(value);
this._frameIndex = -1;
}
}
/**
* @internal
* @private
*/
export class ZOrderTimelineState extends TimelineState {
public static toString(): string {
return "[class dragonBones.ZOrderTimelineState]";
}
protected _onArriveAtFrame(): void {
if (this.playState >= 0) {
const count = this._frameArray[this._frameOffset + 1];
if (count > 0) {
this._armature._sortZOrder(this._frameArray, this._frameOffset + 2);
}
else {
this._armature._sortZOrder(null, 0);
}
}
}
protected _onUpdateFrame(): void { }
}
/**
* @internal
* @private
*/
export class BoneAllTimelineState extends BoneTimelineState {
public static toString(): string {
return "[class dragonBones.BoneAllTimelineState]";
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
if (this._timelineData !== null) {
let valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset + this._frameIndex * 6; // ...(timeline value offset)|xxxxxx|xxxxxx|(Value offset)xxxxx|(Next offset)xxxxx|xxxxxx|xxxxxx|...
const scale = this._armature._armatureData.scale;
const frameFloatArray = this._frameFloatArray;
const current = this.bonePose.current;
const delta = this.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 (this._tweenState === TweenState.Always) {
if (this._frameIndex === this._frameCount - 1) {
valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset; // + 0 * 6
}
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.0;
delta.y = 0.0;
delta.rotation = 0.0;
delta.skew = 0.0;
delta.scaleX = 0.0;
delta.scaleY = 0.0;
}
}
else { // Pose.
const current = this.bonePose.current;
const delta = this.bonePose.delta;
current.x = 0.0;
current.y = 0.0;
current.rotation = 0.0;
current.skew = 0.0;
current.scaleX = 1.0;
current.scaleY = 1.0;
delta.x = 0.0;
delta.y = 0.0;
delta.rotation = 0.0;
delta.skew = 0.0;
delta.scaleX = 0.0;
delta.scaleY = 0.0;
}
}
protected _onUpdateFrame(): void {
super._onUpdateFrame();
const current = this.bonePose.current;
const delta = this.bonePose.delta;
const result = this.bonePose.result;
this.bone._transformDirty = true;
if (this._tweenState !== TweenState.Always) {
this._tweenState = TweenState.None;
}
result.x = current.x + delta.x * this._tweenProgress;
result.y = current.y + delta.y * this._tweenProgress;
result.rotation = current.rotation + delta.rotation * this._tweenProgress;
result.skew = current.skew + delta.skew * this._tweenProgress;
result.scaleX = current.scaleX + delta.scaleX * this._tweenProgress;
result.scaleY = current.scaleY + delta.scaleY * this._tweenProgress;
}
public fadeOut(): void {
const result = this.bonePose.result;
result.rotation = Transform.normalizeRadian(result.rotation);
result.skew = Transform.normalizeRadian(result.skew);
}
}
/**
* @internal
* @private
*/
export class BoneTranslateTimelineState extends BoneTimelineState {
public static toString(): string {
return "[class dragonBones.BoneTranslateTimelineState]";
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
if (this._timelineData !== null) {
let valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset + this._frameIndex * 2;
const scale = this._armature._armatureData.scale;
const frameFloatArray = this._frameFloatArray;
const current = this.bonePose.current;
const delta = this.bonePose.delta;
current.x = frameFloatArray[valueOffset++] * scale;
current.y = frameFloatArray[valueOffset++] * scale;
if (this._tweenState === TweenState.Always) {
if (this._frameIndex === this._frameCount - 1) {
valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset; // + 0 * 2
}
delta.x = frameFloatArray[valueOffset++] * scale - current.x;
delta.y = frameFloatArray[valueOffset++] * scale - current.y;
}
else {
delta.x = 0.0;
delta.y = 0.0;
}
}
else { // Pose.
const current = this.bonePose.current;
const delta = this.bonePose.delta;
current.x = 0.0;
current.y = 0.0;
delta.x = 0.0;
delta.y = 0.0;
}
}
protected _onUpdateFrame(): void {
super._onUpdateFrame();
const current = this.bonePose.current;
const delta = this.bonePose.delta;
const result = this.bonePose.result;
this.bone._transformDirty = true;
if (this._tweenState !== TweenState.Always) {
this._tweenState = TweenState.None;
}
result.x = (current.x + delta.x * this._tweenProgress);
result.y = (current.y + delta.y * this._tweenProgress);
}
}
/**
* @internal
* @private
*/
export class BoneRotateTimelineState extends BoneTimelineState {
public static toString(): string {
return "[class dragonBones.BoneRotateTimelineState]";
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
if (this._timelineData !== null) {
let valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset + this._frameIndex * 2;
const frameFloatArray = this._frameFloatArray;
const current = this.bonePose.current;
const delta = this.bonePose.delta;
current.rotation = frameFloatArray[valueOffset++];
current.skew = frameFloatArray[valueOffset++];
if (this._tweenState === TweenState.Always) {
if (this._frameIndex === this._frameCount - 1) {
valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset; // + 0 * 2
}
delta.rotation = frameFloatArray[valueOffset++] - current.rotation;
delta.skew = frameFloatArray[valueOffset++] - current.skew;
}
else {
delta.rotation = 0.0;
delta.skew = 0.0;
}
}
else { // Pose.
const current = this.bonePose.current;
const delta = this.bonePose.delta;
current.rotation = 0.0;
current.skew = 0.0;
delta.rotation = 0.0;
delta.skew = 0.0;
}
}
protected _onUpdateFrame(): void {
super._onUpdateFrame();
const current = this.bonePose.current;
const delta = this.bonePose.delta;
const result = this.bonePose.result;
this.bone._transformDirty = true;
if (this._tweenState !== TweenState.Always) {
this._tweenState = TweenState.None;
}
result.rotation = current.rotation + delta.rotation * this._tweenProgress;
result.skew = current.skew + delta.skew * this._tweenProgress;
}
public fadeOut(): void {
const result = this.bonePose.result;
result.rotation = Transform.normalizeRadian(result.rotation);
result.skew = Transform.normalizeRadian(result.skew);
}
}
/**
* @internal
* @private
*/
export class BoneScaleTimelineState extends BoneTimelineState {
public static toString(): string {
return "[class dragonBones.BoneScaleTimelineState]";
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
if (this._timelineData !== null) {
let valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset + this._frameIndex * 2;
const frameFloatArray = this._frameFloatArray;
const current = this.bonePose.current;
const delta = this.bonePose.delta;
current.scaleX = frameFloatArray[valueOffset++];
current.scaleY = frameFloatArray[valueOffset++];
if (this._tweenState === TweenState.Always) {
if (this._frameIndex === this._frameCount - 1) {
valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset; // + 0 * 2
}
delta.scaleX = frameFloatArray[valueOffset++] - current.scaleX;
delta.scaleY = frameFloatArray[valueOffset++] - current.scaleY;
}
else {
delta.scaleX = 0.0;
delta.scaleY = 0.0;
}
}
else { // Pose.
const current = this.bonePose.current;
const delta = this.bonePose.delta;
current.scaleX = 1.0;
current.scaleY = 1.0;
delta.scaleX = 0.0;
delta.scaleY = 0.0;
}
}
protected _onUpdateFrame(): void {
super._onUpdateFrame();
const current = this.bonePose.current;
const delta = this.bonePose.delta;
const result = this.bonePose.result;
this.bone._transformDirty = true;
if (this._tweenState !== TweenState.Always) {
this._tweenState = TweenState.None;
}
result.scaleX = current.scaleX + delta.scaleX * this._tweenProgress;
result.scaleY = current.scaleY + delta.scaleY * this._tweenProgress;
}
}
/**
* @internal
* @private
*/
export class SurfaceTimelineState extends TweenTimelineState {
public static toString(): string {
return "[class dragonBones.SurfaceTimelineState]";
}
public surface: Surface;
private _frameFloatOffset: number;
private _valueCount: number;
private _deformCount: number;
private _valueOffset: number;
private readonly _current: Array<number> = [];
private readonly _delta: Array<number> = [];
private readonly _result: Array<number> = [];
protected _onClear(): void {
super._onClear();
this.surface = null as any;
this._frameFloatOffset = 0;
this._valueCount = 0;
this._deformCount = 0;
this._valueOffset = 0;
this._current.length = 0;
this._delta.length = 0;
this._result.length = 0;
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
if (this._timelineData !== null) {
const valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset + this._frameIndex * this._valueCount;
const scale = this._armature._armatureData.scale;
const frameFloatArray = this._frameFloatArray;
if (this._tweenState === TweenState.Always) {
let nextValueOffset = valueOffset + this._valueCount;
if (this._frameIndex === this._frameCount - 1) {
nextValueOffset = this._animationData.frameFloatOffset + this._frameValueOffset;
}
for (let i = 0; i < this._valueCount; ++i) {
this._delta[i] = frameFloatArray[nextValueOffset + i] * scale - (this._current[i] = frameFloatArray[valueOffset + i] * scale);
}
}
else {
for (let i = 0; i < this._valueCount; ++i) {
this._current[i] = frameFloatArray[valueOffset + i] * scale;
}
}
}
else {
for (let i = 0; i < this._valueCount; ++i) {
this._current[i] = 0.0;
}
}
}
protected _onUpdateFrame(): void {
super._onUpdateFrame();
this.surface._transformDirty = true;
if (this._tweenState !== TweenState.Always) {
this._tweenState = TweenState.None;
}
for (let i = 0; i < this._valueCount; ++i) {
this._result[i] = this._current[i] + this._delta[i] * this._tweenProgress;
}
}
public init(armature: Armature, animationState: AnimationState, timelineData: TimelineData | null): void {
super.init(armature, animationState, timelineData);
if (this._timelineData !== null) {
const frameIntOffset = this._animationData.frameIntOffset + this._timelineArray[this._timelineData.offset + BinaryOffset.TimelineFrameValueCount];
this._deformCount = this._frameIntArray[frameIntOffset + BinaryOffset.DeformCount];
this._valueCount = this._frameIntArray[frameIntOffset + BinaryOffset.DeformValueCount];
this._valueOffset = this._frameIntArray[frameIntOffset + BinaryOffset.DeformValueOffset];
this._frameFloatOffset = this._frameIntArray[frameIntOffset + BinaryOffset.DeformFloatOffset] + this._animationData.frameFloatOffset;
}
else {
this._deformCount = this.surface._deformVertices.length;
this._valueCount = this._deformCount;
this._valueOffset = 0;
this._frameFloatOffset = 0;
}
this._current.length = this._valueCount;
this._delta.length = this._valueCount;
this._result.length = this._valueCount;
for (let i = 0; i < this._valueCount; ++i) {
this._delta[i] = 0.0;
}
}
public blend(state: number): void {
const blendWeight = this.surface._blendState.blendWeight;
const result = this.surface._deformVertices;
for (let i = 0; i < this._deformCount; ++i) {
let value = 0.0;
if (i < this._valueOffset) {
value = this._frameFloatArray[this._frameFloatOffset + i];
}
else if (i < this._valueOffset + this._valueCount) {
value = this._result[i - this._valueOffset];
}
else {
value = this._frameFloatArray[this._frameFloatOffset + i - this._valueCount];
}
if (state === 2) {
result[i] += value * blendWeight;
}
else if (blendWeight !== 1.0) {
result[i] = value * blendWeight;
}
else {
result[i] = value;
}
}
if (this._animationState._fadeState !== 0 || this._animationState._subFadeState !== 0) {
this.surface._transformDirty = true;
}
}
}
/**
* @internal
* @private
*/
export class SlotDislayTimelineState extends SlotTimelineState {
public static toString(): string {
return "[class dragonBones.SlotDislayTimelineState]";
}
protected _onArriveAtFrame(): void {
if (this.playState >= 0) {
const displayIndex = this._timelineData !== null ? this._frameArray[this._frameOffset + 1] : this.slot._slotData.displayIndex;
if (this.slot.displayIndex !== displayIndex) {
this.slot._setDisplayIndex(displayIndex, true);
}
}
}
}
/**
* @internal
* @private
*/
export class SlotColorTimelineState extends SlotTimelineState {
public static toString(): string {
return "[class dragonBones.SlotColorTimelineState]";
}
private _dirty: boolean;
private readonly _current: Array<number> = [0, 0, 0, 0, 0, 0, 0, 0];
private readonly _delta: Array<number> = [0, 0, 0, 0, 0, 0, 0, 0];
private readonly _result: Array<number> = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
protected _onClear(): void {
super._onClear();
this._dirty = false;
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
if (this._timelineData !== null) {
const intArray = this._dragonBonesData.intArray;
const frameIntArray = this._frameIntArray;
const valueOffset = this._animationData.frameIntOffset + this._frameValueOffset + this._frameIndex * 1; // ...(timeline value offset)|x|x|(Value offset)|(Next offset)|x|x|...
let colorOffset = frameIntArray[valueOffset];
if (colorOffset < 0) {
colorOffset += 65536; // Fixed out of bouds bug.
}
this._current[0] = intArray[colorOffset++];
this._current[1] = intArray[colorOffset++];
this._current[2] = intArray[colorOffset++];
this._current[3] = intArray[colorOffset++];
this._current[4] = intArray[colorOffset++];
this._current[5] = intArray[colorOffset++];
this._current[6] = intArray[colorOffset++];
this._current[7] = intArray[colorOffset++];
if (this._tweenState === TweenState.Always) {
if (this._frameIndex === this._frameCount - 1) {
colorOffset = frameIntArray[this._animationData.frameIntOffset + this._frameValueOffset];
}
else {
colorOffset = frameIntArray[valueOffset + 1 * 1];
}
if (colorOffset < 0) {
colorOffset += 65536; // Fixed out of bouds bug.
}
this._delta[0] = intArray[colorOffset++] - this._current[0];
this._delta[1] = intArray[colorOffset++] - this._current[1];
this._delta[2] = intArray[colorOffset++] - this._current[2];
this._delta[3] = intArray[colorOffset++] - this._current[3];
this._delta[4] = intArray[colorOffset++] - this._current[4];
this._delta[5] = intArray[colorOffset++] - this._current[5];
this._delta[6] = intArray[colorOffset++] - this._current[6];
this._delta[7] = intArray[colorOffset++] - this._current[7];
}
}
else { // Pose.
const color = this.slot._slotData.color;
this._current[0] = color.alphaMultiplier * 100.0;
this._current[1] = color.redMultiplier * 100.0;
this._current[2] = color.greenMultiplier * 100.0;
this._current[3] = color.blueMultiplier * 100.0;
this._current[4] = color.alphaOffset;
this._current[5] = color.redOffset;
this._current[6] = color.greenOffset;
this._current[7] = color.blueOffset;
}
}
protected _onUpdateFrame(): void {
super._onUpdateFrame();
this._dirty = true;
if (this._tweenState !== TweenState.Always) {
this._tweenState = TweenState.None;
}
this._result[0] = (this._current[0] + this._delta[0] * this._tweenProgress) * 0.01;
this._result[1] = (this._current[1] + this._delta[1] * this._tweenProgress) * 0.01;
this._result[2] = (this._current[2] + this._delta[2] * this._tweenProgress) * 0.01;
this._result[3] = (this._current[3] + this._delta[3] * this._tweenProgress) * 0.01;
this._result[4] = this._current[4] + this._delta[4] * this._tweenProgress;
this._result[5] = this._current[5] + this._delta[5] * this._tweenProgress;
this._result[6] = this._current[6] + this._delta[6] * this._tweenProgress;
this._result[7] = this._current[7] + this._delta[7] * this._tweenProgress;
}
public fadeOut(): void {
this._tweenState = TweenState.None;
this._dirty = false;
}
public update(passedTime: number): void {
super.update(passedTime);
// Fade animation.
if (this._tweenState !== TweenState.None || this._dirty) {
const result = this.slot._colorTransform;
if (this._animationState._fadeState !== 0 || this._animationState._subFadeState !== 0) {
if (
result.alphaMultiplier !== this._result[0] ||
result.redMultiplier !== this._result[1] ||
result.greenMultiplier !== this._result[2] ||
result.blueMultiplier !== this._result[3] ||
result.alphaOffset !== this._result[4] ||
result.redOffset !== this._result[5] ||
result.greenOffset !== this._result[6] ||
result.blueOffset !== this._result[7]
) {
const fadeProgress = Math.pow(this._animationState._fadeProgress, 4);
result.alphaMultiplier += (this._result[0] - result.alphaMultiplier) * fadeProgress;
result.redMultiplier += (this._result[1] - result.redMultiplier) * fadeProgress;
result.greenMultiplier += (this._result[2] - result.greenMultiplier) * fadeProgress;
result.blueMultiplier += (this._result[3] - result.blueMultiplier) * fadeProgress;
result.alphaOffset += (this._result[4] - result.alphaOffset) * fadeProgress;
result.redOffset += (this._result[5] - result.redOffset) * fadeProgress;
result.greenOffset += (this._result[6] - result.greenOffset) * fadeProgress;
result.blueOffset += (this._result[7] - result.blueOffset) * fadeProgress;
this.slot._colorDirty = true;
}
}
else if (this._dirty) {
this._dirty = false;
if (
result.alphaMultiplier !== this._result[0] ||
result.redMultiplier !== this._result[1] ||
result.greenMultiplier !== this._result[2] ||
result.blueMultiplier !== this._result[3] ||
result.alphaOffset !== this._result[4] ||
result.redOffset !== this._result[5] ||
result.greenOffset !== this._result[6] ||
result.blueOffset !== this._result[7]
) {
result.alphaMultiplier = this._result[0];
result.redMultiplier = this._result[1];
result.greenMultiplier = this._result[2];
result.blueMultiplier = this._result[3];
result.alphaOffset = this._result[4];
result.redOffset = this._result[5];
result.greenOffset = this._result[6];
result.blueOffset = this._result[7];
this.slot._colorDirty = true;
}
}
}
}
}
/**
* @internal
* @private
*/
export class SlotFFDTimelineState extends SlotTimelineState {
public static toString(): string {
return "[class dragonBones.SlotFFDTimelineState]";
}
public meshOffset: number;
private _dirty: boolean;
private _frameFloatOffset: number;
private _valueCount: number;
private _deformCount: number;
private _valueOffset: number;
private readonly _current: Array<number> = [];
private readonly _delta: Array<number> = [];
private readonly _result: Array<number> = [];
protected _onClear(): void {
super._onClear();
this.meshOffset = 0;
this._dirty = false;
this._frameFloatOffset = 0;
this._valueCount = 0;
this._deformCount = 0;
this._valueOffset = 0;
this._current.length = 0;
this._delta.length = 0;
this._result.length = 0;
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
if (this._timelineData !== null) {
const valueOffset = this._animationData.frameFloatOffset + this._frameValueOffset + this._frameIndex * this._valueCount;
const scale = this._armature._armatureData.scale;
const frameFloatArray = this._frameFloatArray;
if (this._tweenState === TweenState.Always) {
let nextValueOffset = valueOffset + this._valueCount;
if (this._frameIndex === this._frameCount - 1) {
nextValueOffset = this._animationData.frameFloatOffset + this._frameValueOffset;
}
for (let i = 0; i < this._valueCount; ++i) {
this._delta[i] = frameFloatArray[nextValueOffset + i] * scale - (this._current[i] = frameFloatArray[valueOffset + i] * scale);
}
}
else {
for (let i = 0; i < this._valueCount; ++i) {
this._current[i] = frameFloatArray[valueOffset + i] * scale;
}
}
}
else {
for (let i = 0; i < this._valueCount; ++i) {
this._current[i] = 0.0;
}
}
}
protected _onUpdateFrame(): void {
super._onUpdateFrame();
this._dirty = true;
if (this._tweenState !== TweenState.Always) {
this._tweenState = TweenState.None;
}
for (let i = 0; i < this._valueCount; ++i) {
this._result[i] = this._current[i] + this._delta[i] * this._tweenProgress;
}
}
public init(armature: Armature, animationState: AnimationState, timelineData: TimelineData | null): void {
super.init(armature, animationState, timelineData);
if (this._timelineData !== null) {
const frameIntOffset = this._animationData.frameIntOffset + this._timelineArray[this._timelineData.offset + BinaryOffset.TimelineFrameValueCount];
this.meshOffset = this._frameIntArray[frameIntOffset + BinaryOffset.DeformMeshOffset];
if (this.meshOffset < 0) {
this.meshOffset += 65536; // Fixed out of bouds bug.
}
this._deformCount = this._frameIntArray[frameIntOffset + BinaryOffset.DeformCount];
this._valueCount = this._frameIntArray[frameIntOffset + BinaryOffset.DeformValueCount];
this._valueOffset = this._frameIntArray[frameIntOffset + BinaryOffset.DeformValueOffset];
this._frameFloatOffset = this._frameIntArray[frameIntOffset + BinaryOffset.DeformFloatOffset] + this._animationData.frameFloatOffset;
}
else {
this._deformCount = this.slot._deformVertices.length;
this._valueCount = this._deformCount;
this._valueOffset = 0;
this._frameFloatOffset = 0;
}
this._current.length = this._valueCount;
this._delta.length = this._valueCount;
this._result.length = this._valueCount;
for (let i = 0; i < this._valueCount; ++i) {
this._delta[i] = 0.0;
}
}
public fadeOut(): void {
this._tweenState = TweenState.None;
this._dirty = false;
}
public update(passedTime: number): void {
if (this.slot._meshData === null || this.slot._meshData.offset !== this.meshOffset) {
return;
}
super.update(passedTime);
// Fade animation.
if (this._tweenState !== TweenState.None || this._dirty) {
const result = this.slot._deformVertices;
if (this._animationState._fadeState !== 0 || this._animationState._subFadeState !== 0) {
const fadeProgress = Math.pow(this._animationState._fadeProgress, 2);
for (let i = 0; i < this._deformCount; ++i) {
if (i < this._valueOffset) {
result[i] += (this._frameFloatArray[this._frameFloatOffset + i] - result[i]) * fadeProgress;
}
else if (i < this._valueOffset + this._valueCount) {
result[i] += (this._result[i - this._valueOffset] - result[i]) * fadeProgress;
}
else {
result[i] += (this._frameFloatArray[this._frameFloatOffset + i - this._valueCount] - result[i]) * fadeProgress;
}
}
this.slot._meshDirty = true;
}
else if (this._dirty) {
this._dirty = false;
for (let i = 0; i < this._deformCount; ++i) {
if (i < this._valueOffset) {
result[i] = this._frameFloatArray[this._frameFloatOffset + i];
}
else if (i < this._valueOffset + this._valueCount) {
result[i] = this._result[i - this._valueOffset];
}
else {
result[i] = this._frameFloatArray[this._frameFloatOffset + i - this._valueCount];
}
}
this.slot._meshDirty = true;
}
}
}
}
/**
* @internal
* @private
*/
export class IKConstraintTimelineState extends ConstraintTimelineState {
public static toString(): string {
return "[class dragonBones.IKConstraintTimelineState]";
}
private _current: number;
private _delta: number;
protected _onClear(): void {
super._onClear();
this._current = 0.0;
this._delta = 0.0;
}
protected _onArriveAtFrame(): void {
super._onArriveAtFrame();
const ikConstraint = this.constraint as IKConstraint;
if (this._timelineData !== null) {
let valueOffset = this._animationData.frameIntOffset + this._frameValueOffset + this._frameIndex * 2;