UNPKG

dragonbones-runtime

Version:

the tools to build dragonbones file for diffrent framework

583 lines (539 loc) 25.9 kB
/** * 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 Surface extends Bone { public static toString(): string { return "[class dragonBones.Surface]"; } private _dX: number; private _dY: number; private _k: number; private _kX: number; private _kY: number; /** * For debug draw. * @internal * @private */ public readonly _vertices: Array<number> = []; /** * For timeline state. * @internal * @private */ public readonly _deformVertices: Array<number> = []; /** * x1, y1, x2, y2, x3, y3, x4, y4, d1X, d1Y, d2X, d2Y */ private readonly _hullCache: Array<number> = []; /** * Inside [flag, a, b, c, d, tx, ty], Outside [flag, a, b, c, d, tx, ty] */ private readonly _matrixCahce: Array<number> = []; /** * @inheritDoc */ protected _onClear(): void { super._onClear(); this._dX = 0.0; this._dY = 0.0; this._k = 0.0; this._kX = 0.0; this._kY = 0.0; this._vertices.length = 0; this._deformVertices.length = 0; this._matrixCahce.length = 0; this._hullCache.length = 0; } private _getAffineTransform( x: number, y: number, lX: number, lY: number, aX: number, aY: number, bX: number, bY: number, cX: number, cY: number, transform: Transform, matrix: Matrix, isDown: boolean ): void { const dabX = bX - aX; const dabY = bY - aY; const dacX = cX - aX; const dacY = cY - aY; transform.rotation = Math.atan2(dabY, dabX); transform.skew = Math.atan2(dacY, dacX) - Math.PI * 0.5 - transform.rotation; if (isDown) { transform.rotation += Math.PI; } transform.scaleX = Math.sqrt(dabX * dabX + dabY * dabY) / lX; transform.scaleY = Math.sqrt(dacX * dacX + dacY * dacY) / lY; transform.toMatrix(matrix); transform.x = matrix.tx = aX - (matrix.a * x + matrix.c * y); transform.y = matrix.ty = aY - (matrix.b * x + matrix.d * y); } private _updateVertices(): void { const originalVertices = (this._boneData as SurfaceData).vertices; const vertices = this._vertices; const animationVertices = this._deformVertices; if (this._parent !== null) { if (this._parent._boneData.type === BoneType.Surface) { for (let i = 0, l = originalVertices.length; i < l; i += 2) { const x = originalVertices[i] + animationVertices[i]; const y = originalVertices[i + 1] + animationVertices[i]; const matrix = (this._parent as Surface)._getGlobalTransformMatrix(x, y); // vertices[i] = matrix.a * x + matrix.c * y + matrix.tx; vertices[i + 1] = matrix.b * x + matrix.d * y + matrix.ty; } } else { const parentMatrix = this._parent.globalTransformMatrix; for (let i = 0, l = originalVertices.length; i < l; i += 2) { const x = originalVertices[i] + animationVertices[i]; const y = originalVertices[i + 1] + animationVertices[i + 1]; // vertices[i] = parentMatrix.a * x + parentMatrix.c * y + parentMatrix.tx; vertices[i + 1] = parentMatrix.b * x + parentMatrix.d * y + parentMatrix.ty; } } } else { for (let i = 0, l = originalVertices.length; i < l; i += 2) { vertices[i] = originalVertices[i] + animationVertices[i]; vertices[i + 1] = originalVertices[i + 1] + animationVertices[i + 1]; } } } /** * @private */ protected _updateGlobalTransformMatrix(isCache: boolean): void { // tslint:disable-next-line:no-unused-expression isCache; const segmentXD = (this._boneData as SurfaceData).segmentX * 2; const lastIndex = this._vertices.length - 2; const lA = 200.0; // const raX = this._vertices[0]; const raY = this._vertices[1]; const rbX = this._vertices[segmentXD]; const rbY = this._vertices[segmentXD + 1]; const rcX = this._vertices[lastIndex]; const rcY = this._vertices[lastIndex + 1]; const rdX = this._vertices[lastIndex - segmentXD]; const rdY = this._vertices[lastIndex - segmentXD + 1]; // const dacX = raX + (rcX - raX) * 0.5; const dacY = raY + (rcY - raY) * 0.5; const dbdX = rbX + (rdX - rbX) * 0.5; const dbdY = rbY + (rdY - rbY) * 0.5; const aX = dacX + (dbdX - dacX) * 0.5; const aY = dacY + (dbdY - dacY) * 0.5; const bX = rbX + (rcX - rbX) * 0.5; const bY = rbY + (rcY - rbY) * 0.5; const cX = rdX + (rcX - rdX) * 0.5; const cY = rdY + (rcY - rdY) * 0.5; // this._globalDirty = false; this._getAffineTransform(0.0, 0.0, lA, lA, aX, aY, bX, bY, cX, cY, this.global, this.globalTransformMatrix, false); } public _getGlobalTransformMatrix(x: number, y: number): Matrix { const lB = 1000.0; if (x < -lB || lB < x || y < -lB || lB < y) { return this.globalTransformMatrix; } let isDown = false; const lA = 200.0; const surfaceData = this._boneData as SurfaceData; const segmentX = surfaceData.segmentX; const segmentY = surfaceData.segmentY; const segmentXD = surfaceData.segmentX * 2; const dX = this._dX; const dY = this._dY; const indexX = Math.floor((x + lA) / dX); const indexY = Math.floor((y + lA) / dY); let matrixIndex = 0; let pX = indexX * dX - lA; let pY = indexY * dY - lA; const matrices = this._matrixCahce; const helpMatrix = Surface._helpMatrix; if (x < -lA) { if (y < -lA || y > lA) { return this.globalTransformMatrix; } isDown = y > this._kX * (x + lA) + pY; matrixIndex = ((segmentX * (segmentY + 1) + segmentX * 2 + segmentY + indexY) * 2 + (isDown ? 1 : 0)) * 7; if (this._matrixCahce[matrixIndex] > 0.0) { helpMatrix.copyFromArray(matrices, matrixIndex + 1); } else { const vertexIndex = indexY * (segmentXD + 2); const ddX = this._hullCache[4]; const ddY = this._hullCache[5]; const sX = this._hullCache[2] - (segmentY - indexY) * ddX; const sY = this._hullCache[3] - (segmentY - indexY) * ddY; const vertices = this._vertices; if (isDown) { this._getAffineTransform( -lA, pY + dY, lB - lA, dY, vertices[vertexIndex + segmentXD + 2], vertices[vertexIndex + segmentXD + 3], sX + ddX, sY + ddY, vertices[vertexIndex], vertices[vertexIndex + 1], Surface._helpTransform, helpMatrix, true); } else { this._getAffineTransform( -lB, pY, lB - lA, dY, sX, sY, vertices[vertexIndex], vertices[vertexIndex + 1], sX + ddX, sY + ddY, Surface._helpTransform, helpMatrix, false); } matrices[matrixIndex] = 1.0; matrices[matrixIndex + 1] = helpMatrix.a; matrices[matrixIndex + 2] = helpMatrix.b; matrices[matrixIndex + 3] = helpMatrix.c; matrices[matrixIndex + 4] = helpMatrix.d; matrices[matrixIndex + 5] = helpMatrix.tx; matrices[matrixIndex + 6] = helpMatrix.ty; } } else if (x > lA) { if (y < -lA || y > lA) { return this.globalTransformMatrix; } isDown = y > this._kX * (x - lB) + pY; matrixIndex = ((segmentX * (segmentY + 1) + segmentX + indexY) * 2 + (isDown ? 1 : 0)) * 7; if (this._matrixCahce[matrixIndex] > 0.0) { helpMatrix.copyFromArray(matrices, matrixIndex + 1); } else { const vertexIndex = (indexY + 1) * (segmentXD + 2) - 2; const ddX = this._hullCache[4]; const ddY = this._hullCache[5]; const sX = this._hullCache[0] + indexY * ddX; const sY = this._hullCache[1] + indexY * ddY; const vertices = this._vertices; if (isDown) { this._getAffineTransform( lB, pY + dY, lB - lA, dY, sX + ddX, sY + ddY, vertices[vertexIndex + segmentXD + 2], vertices[vertexIndex + segmentXD + 3], sX, sY, Surface._helpTransform, helpMatrix, true); } else { this._getAffineTransform( lA, pY, lB - lA, dY, vertices[vertexIndex], vertices[vertexIndex + 1], sX, sY, vertices[vertexIndex + segmentXD + 2], vertices[vertexIndex + segmentXD + 3], Surface._helpTransform, helpMatrix, false); } matrices[matrixIndex] = 1.0; matrices[matrixIndex + 1] = helpMatrix.a; matrices[matrixIndex + 2] = helpMatrix.b; matrices[matrixIndex + 3] = helpMatrix.c; matrices[matrixIndex + 4] = helpMatrix.d; matrices[matrixIndex + 5] = helpMatrix.tx; matrices[matrixIndex + 6] = helpMatrix.ty; } } else if (y < -lA) { if (x < -lA || x > lA) { return this.globalTransformMatrix; } isDown = y > this._kY * (x - pX - dX) - lB; matrixIndex = (segmentX * (segmentY + 1) + indexX * 2 + (isDown ? 1 : 0)) * 7; if (this._matrixCahce[matrixIndex] > 0.0) { helpMatrix.copyFromArray(matrices, matrixIndex + 1); } else { const vertexIndex = indexX * 2; const ddX = this._hullCache[10]; const ddY = this._hullCache[11]; const sX = this._hullCache[8] + indexX * ddX; const sY = this._hullCache[9] + indexX * ddY; const vertices = this._vertices; if (isDown) { this._getAffineTransform( pX + dX, -lA, dX, lB - lA, vertices[vertexIndex + 2], vertices[vertexIndex + 3], vertices[vertexIndex], vertices[vertexIndex + 1], sX + ddX, sY + ddY, Surface._helpTransform, helpMatrix, true); } else { this._getAffineTransform( pX, -lB, dX, lB - lA, sX, sY, sX + ddX, sY + ddY, vertices[vertexIndex], vertices[vertexIndex + 1], Surface._helpTransform, helpMatrix, false); } matrices[matrixIndex] = 1.0; matrices[matrixIndex + 1] = helpMatrix.a; matrices[matrixIndex + 2] = helpMatrix.b; matrices[matrixIndex + 3] = helpMatrix.c; matrices[matrixIndex + 4] = helpMatrix.d; matrices[matrixIndex + 5] = helpMatrix.tx; matrices[matrixIndex + 6] = helpMatrix.ty; } } else if (y > lA) { if (x < -lA || x > lA) { return this.globalTransformMatrix; } isDown = y > this._kY * (x - pX - dX) + lA; matrixIndex = ((segmentX * (segmentY + 1) + segmentX + segmentY + indexY) * 2 + (isDown ? 1 : 0)) * 7; if (this._matrixCahce[matrixIndex] > 0.0) { helpMatrix.copyFromArray(matrices, matrixIndex + 1); } else { const vertexIndex = segmentY * (segmentXD + 2) + indexX * 2; const ddX = this._hullCache[10]; const ddY = this._hullCache[11]; const sX = this._hullCache[6] - (segmentX - indexX) * ddX; const sY = this._hullCache[7] - (segmentX - indexX) * ddY; const vertices = this._vertices; if (isDown) { this._getAffineTransform( pX + dX, lB, dX, lB - lA, sX + ddX, sY + ddY, sX, sY, vertices[vertexIndex + 2], vertices[vertexIndex + 3], Surface._helpTransform, helpMatrix, true); } else { this._getAffineTransform( pX, lA, dX, lB - lA, vertices[vertexIndex], vertices[vertexIndex + 1], vertices[vertexIndex + 2], vertices[vertexIndex + 3], sX, sY, Surface._helpTransform, helpMatrix, false); } matrices[matrixIndex] = 1.0; matrices[matrixIndex + 1] = helpMatrix.a; matrices[matrixIndex + 2] = helpMatrix.b; matrices[matrixIndex + 3] = helpMatrix.c; matrices[matrixIndex + 4] = helpMatrix.d; matrices[matrixIndex + 5] = helpMatrix.tx; matrices[matrixIndex + 6] = helpMatrix.ty; } } else { isDown = y > this._k * (x - pX - dX) + pY; matrixIndex = ((segmentX * indexY + indexX) * 2 + (isDown ? 1 : 0)) * 7; if (this._matrixCahce[matrixIndex] > 0.0) { helpMatrix.copyFromArray(matrices, matrixIndex + 1); } else { const vertexIndex = indexX * 2 + indexY * (segmentXD + 2); const vertices = this._vertices; if (isDown) { this._getAffineTransform( pX + dX, pY + dY, dX, dY, vertices[vertexIndex + segmentXD + 4], vertices[vertexIndex + segmentXD + 5], vertices[vertexIndex + segmentXD + 2], vertices[vertexIndex + segmentXD + 3], vertices[vertexIndex + 2], vertices[vertexIndex + 3], Surface._helpTransform, helpMatrix, true); } else { this._getAffineTransform( pX, pY, dX, dY, vertices[vertexIndex], vertices[vertexIndex + 1], vertices[vertexIndex + 2], vertices[vertexIndex + 3], vertices[vertexIndex + segmentXD + 2], vertices[vertexIndex + segmentXD + 3], Surface._helpTransform, helpMatrix, false); } matrices[matrixIndex] = 1.0; matrices[matrixIndex + 1] = helpMatrix.a; matrices[matrixIndex + 2] = helpMatrix.b; matrices[matrixIndex + 3] = helpMatrix.c; matrices[matrixIndex + 4] = helpMatrix.d; matrices[matrixIndex + 5] = helpMatrix.tx; matrices[matrixIndex + 6] = helpMatrix.ty; } } return helpMatrix; } public init(surfaceData: SurfaceData): void { if (this._boneData !== null) { return; } super.init(surfaceData); const segmentX = surfaceData.segmentX; const segmentY = surfaceData.segmentY; const vertexCount = surfaceData.vertices.length; const lB = 1000.0; const lA = 200.0; // this._dX = lA * 2.0 / segmentX; this._dY = lA * 2.0 / segmentY; this._k = -this._dY / this._dX; this._kX = -this._dY / (lB - lA); this._kY = -(lB - lA) / this._dX; this._vertices.length = vertexCount; this._deformVertices.length = vertexCount; this._matrixCahce.length = (segmentX * segmentY + segmentX * 2 + segmentY * 2) * 2 * 7; this._hullCache.length = 10; for (let i = 0; i < vertexCount; ++i) { this._deformVertices[i] = 0.0; } } /** * @internal * @private */ public update(cacheFrameIndex: number): void { this._blendState.dirty = false; if (cacheFrameIndex >= 0 && this._cachedFrameIndices !== null) { const cachedFrameIndex = this._cachedFrameIndices[cacheFrameIndex]; if (cachedFrameIndex >= 0 && this._cachedFrameIndex === cachedFrameIndex) { // Same cache. this._transformDirty = false; } else if (cachedFrameIndex >= 0) { // Has been Cached. this._transformDirty = true; this._cachedFrameIndex = cachedFrameIndex; } else { if (this._hasConstraint) { // Update constraints. for (const constraint of this._armature._constraints) { if (constraint._root === this) { constraint.update(); } } } if ( this._transformDirty || (this._parent !== null && this._parent._childrenTransformDirty) ) { // Dirty. this._transformDirty = true; this._cachedFrameIndex = -1; } else if (this._cachedFrameIndex >= 0) { // Same cache, but not set index yet. this._transformDirty = false; this._cachedFrameIndices[cacheFrameIndex] = this._cachedFrameIndex; } else { // Dirty. this._transformDirty = true; this._cachedFrameIndex = -1; } } } else { if (this._hasConstraint) { // Update constraints. for (const constraint of this._armature._constraints) { if (constraint._root === this) { constraint.update(); } } } if (this._transformDirty || (this._parent !== null && this._parent._childrenTransformDirty)) { // Dirty. cacheFrameIndex = -1; this._transformDirty = true; this._cachedFrameIndex = -1; } } if (this._transformDirty) { this._transformDirty = false; this._childrenTransformDirty = true; // for (let i = 0, l = this._matrixCahce.length; i < l; i += 7) { this._matrixCahce[i] = -1.0; } // this._updateVertices(); // if (this._cachedFrameIndex < 0) { const isCache = cacheFrameIndex >= 0; if (this._localDirty) { this._updateGlobalTransformMatrix(isCache); } if (isCache && this._cachedFrameIndices !== null) { this._cachedFrameIndex = this._cachedFrameIndices[cacheFrameIndex] = this._armature._armatureData.setCacheFrame(this.globalTransformMatrix, this.global); } } else { this._armature._armatureData.getCacheFrame(this.globalTransformMatrix, this.global, this._cachedFrameIndex); } // Update hull vertices. const lB = 1000.0; const lA = 200.0; const ddX = 2 * this.global.x; const ddY = 2 * this.global.y; // const helpPoint = Surface._helpPoint; this.globalTransformMatrix.transformPoint(lB, -lA, helpPoint); this._hullCache[0] = helpPoint.x; this._hullCache[1] = helpPoint.y; this._hullCache[2] = ddX - helpPoint.x; this._hullCache[3] = ddY - helpPoint.y; this.globalTransformMatrix.transformPoint(0.0, this._dY, helpPoint, true); this._hullCache[4] = helpPoint.x; this._hullCache[5] = helpPoint.y; // this.globalTransformMatrix.transformPoint(lA, lB, helpPoint); this._hullCache[6] = helpPoint.x; this._hullCache[7] = helpPoint.y; this._hullCache[8] = ddX - helpPoint.x; this._hullCache[9] = ddY - helpPoint.y; this.globalTransformMatrix.transformPoint(this._dX, 0.0, helpPoint, true); this._hullCache[10] = helpPoint.x; this._hullCache[11] = helpPoint.y; } else if (this._childrenTransformDirty) { this._childrenTransformDirty = false; } this._localDirty = true; } } }