[ts][webgl][widget] Implemented clipping, updated README.md and CHANGELOG

This commit is contained in:
badlogic 2017-04-12 14:14:34 +02:00
parent 06f32233c0
commit d4266cf89a
27 changed files with 13179 additions and 10466 deletions

View File

@ -120,12 +120,14 @@
* Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees). * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
* Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`. * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
* Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface. * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
* Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
### WebGL backend ### WebGL backend
* Fixed renderer to work with 3.6 changes. * Fixed renderer to work with 3.6 changes.
* Added support for two color tinting. * Added support for two color tinting.
* Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`. * Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`.
* Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled. * Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled.
* Added clipping support
### Canvas backend ### Canvas backend
* Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API. * Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API.
@ -136,5 +138,5 @@
* Fixed renderer to work with 3.6 changes. Two color tinting is not supported. * Fixed renderer to work with 3.6 changes. Two color tinting is not supported.
### Widget backend ### Widget backend
* Fixed renderer to work for 3.6 changes. Supports two color tinting (see webgl backend changes for details). * Fixed renderer to work for 3.6 changes. Supports two color tinting & clipping (see webgl backend changes for details).
* Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details. * Added fields `atlasContent`, `atlasPagesContent`, and `jsonContent` to `WidgetConfiguration` allowing you to directly pass the contents of the `.atlas`, atlas page `.png` files, and the `.json` file without having to do a request. See `README.md` and the example for details.

View File

@ -22,9 +22,9 @@ spine-ts works with data exported from Spine 3.6.xx
spine-ts WebGL & Widget backends supports all Spine features. spine-ts WebGL & Widget backends supports all Spine features.
spine-ts Canvas does not support color tinting and mesh attachments. Only the alpha channel from tint colors is applied. Experimental support for mesh attachments can be enabled by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers. spine-ts Canvas does not support color tinting, mesh attachments and clipping. Only the alpha channel from tint colors is applied. Experimental support for mesh attachments can be enabled by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers.
spine-ts THREE.JS does not support color tinting and blend modes. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings. spine-ts THREE.JS does not support color tinting, blend modes and clipping. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings.
spine-ts does not yet support loading the binary format. spine-ts does not yet support loading the binary format.

View File

@ -454,6 +454,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -477,6 +478,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -495,6 +497,13 @@ declare module spine {
constructor(name: string); constructor(name: string);
} }
} }
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine { declare module spine {
class MeshAttachment extends VertexAttachment { class MeshAttachment extends VertexAttachment {
region: TextureRegion; region: TextureRegion;
@ -678,6 +687,21 @@ declare module spine {
getOrder(): number; getOrder(): number;
} }
} }
declare module spine {
class ConvexDecomposer {
private convexPolygons;
private convexPolygonsIndices;
private indicesArray;
private isConcaveArray;
private triangles;
private polygonPool;
private polygonIndicesPool;
decompose(input: ArrayLike<number>): Array<Array<number>>;
private static isConcave(index, vertexCount, vertices, indices);
private static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y);
private static winding(p1x, p1y, p2x, p2y, p3x, p3y);
}
}
declare module spine { declare module spine {
class Event { class Event {
data: EventData; data: EventData;
@ -873,6 +897,25 @@ declare module spine {
getHeight(): number; getHeight(): number;
} }
} }
declare module spine {
class SkeletonClipping {
private decomposer;
private clippingPolygon;
private clipOutput;
clippedVertices: number[];
clippedTriangles: number[];
private scratch;
private clipAttachment;
private clippingPolygons;
clipStart(slot: Slot, clip: ClippingAttachment): void;
clipEndWithSlot(slot: Slot): void;
clipEnd(): void;
isClipping(): boolean;
clipTriangles(vertices: ArrayLike<number>, verticesLength: number, triangles: ArrayLike<number>, trianglesLength: number, uvs: ArrayLike<number>, light: Color, dark: Color, twoColor: boolean): void;
clip(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array<number>, output: Array<number>): boolean;
static makeClockwise(polygon: ArrayLike<number>): void;
}
}
declare module spine { declare module spine {
class SkeletonData { class SkeletonData {
name: string; name: string;
@ -911,7 +954,7 @@ declare module spine {
private linkedMeshes; private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader); constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(json: string | any): SkeletonData; readSkeletonData(json: string | any): SkeletonData;
readAttachment(map: any, skin: Skin, slotIndex: number, name: string): Attachment; readAttachment(map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment;
readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void; readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void;
readAnimation(map: any, name: string, skeletonData: SkeletonData): void; readAnimation(map: any, name: string, skeletonData: SkeletonData): void;
readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void; readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void;
@ -1089,6 +1132,7 @@ declare module spine {
static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>; static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>;
static newArray<T>(size: number, defaultValue: T): Array<T>; static newArray<T>(size: number, defaultValue: T): Array<T>;
static newFloatArray(size: number): ArrayLike<number>; static newFloatArray(size: number): ArrayLike<number>;
static newShortArray(size: number): ArrayLike<number>;
static toFloatArray(array: Array<number>): number[] | Float32Array; static toFloatArray(array: Array<number>): number[] | Float32Array;
} }
class DebugUtils { class DebugUtils {
@ -1524,6 +1568,7 @@ declare module spine.webgl {
attachmentLineColor: Color; attachmentLineColor: Color;
triangleLineColor: Color; triangleLineColor: Color;
pathColor: Color; pathColor: Color;
clipColor: Color;
aabbColor: Color; aabbColor: Color;
drawBones: boolean; drawBones: boolean;
drawRegionAttachments: boolean; drawRegionAttachments: boolean;
@ -1532,6 +1577,7 @@ declare module spine.webgl {
drawMeshTriangles: boolean; drawMeshTriangles: boolean;
drawPaths: boolean; drawPaths: boolean;
drawSkeletonXY: boolean; drawSkeletonXY: boolean;
drawClipping: boolean;
premultipliedAlpha: boolean; premultipliedAlpha: boolean;
scale: number; scale: number;
boneWidth: number; boneWidth: number;
@ -1557,10 +1603,9 @@ declare module spine.webgl {
private vertexSize; private vertexSize;
private twoColorTint; private twoColorTint;
private renderable; private renderable;
private clipper;
constructor(gl: WebGLRenderingContext, twoColorTint?: boolean); constructor(gl: WebGLRenderingContext, twoColorTint?: boolean);
draw(batcher: PolygonBatcher, skeleton: Skeleton): void; draw(batcher: PolygonBatcher, skeleton: Skeleton): void;
private computeRegionVertices(slot, region, pma, twoColorTint?);
private computeMeshVertices(slot, mesh, pma, twoColorTint?);
} }
} }
declare module spine.webgl { declare module spine.webgl {

View File

@ -2242,6 +2242,9 @@ var spine;
AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) {
return new spine.PointAttachment(name); return new spine.PointAttachment(name);
}; };
AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) {
return new spine.ClippingAttachment(name);
};
return AtlasAttachmentLoader; return AtlasAttachmentLoader;
}()); }());
spine.AtlasAttachmentLoader = AtlasAttachmentLoader; spine.AtlasAttachmentLoader = AtlasAttachmentLoader;
@ -2354,6 +2357,18 @@ var spine;
spine.BoundingBoxAttachment = BoundingBoxAttachment; spine.BoundingBoxAttachment = BoundingBoxAttachment;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ClippingAttachment = (function (_super) {
__extends(ClippingAttachment, _super);
function ClippingAttachment(name) {
_super.call(this, name);
this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1);
}
return ClippingAttachment;
}(spine.VertexAttachment));
spine.ClippingAttachment = ClippingAttachment;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var MeshAttachment = (function (_super) { var MeshAttachment = (function (_super) {
__extends(MeshAttachment, _super); __extends(MeshAttachment, _super);
@ -2897,6 +2912,207 @@ var spine;
var TransformMode = spine.TransformMode; var TransformMode = spine.TransformMode;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ConvexDecomposer = (function () {
function ConvexDecomposer() {
this.convexPolygons = new Array();
this.convexPolygonsIndices = new Array();
this.indicesArray = new Array();
this.isConcaveArray = new Array();
this.triangles = new Array();
this.polygonPool = new spine.Pool(function () {
return new Array();
});
this.polygonIndicesPool = new spine.Pool(function () {
return new Array();
});
}
ConvexDecomposer.prototype.decompose = function (input) {
var vertices = input;
var vertexCount = input.length >> 1;
var indices = this.indicesArray;
indices.length = 0;
for (var i = 0; i < vertexCount; i++)
indices[i] = i;
var isConcave = this.isConcaveArray;
isConcave.length = 0;
for (var i = 0, n = vertexCount; i < n; ++i)
isConcave[i] = ConvexDecomposer.isConcave(i, vertexCount, vertices, indices);
var triangles = this.triangles;
triangles.length = 0;
while (vertexCount > 3) {
var previous = vertexCount - 1, i = 0, next = 1;
while (true) {
outer: if (!isConcave[i]) {
var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
var p1x = vertices[p1], p1y = vertices[p1 + 1];
var p2x = vertices[p2], p2y = vertices[p2 + 1];
var p3x = vertices[p3], p3y = vertices[p3 + 1];
for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
if (!isConcave[ii])
continue;
var v = indices[ii] << 1;
var vx = vertices[v], vy = vertices[v + 1];
if (ConvexDecomposer.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
break outer;
}
}
}
break;
}
if (next == 0) {
do {
if (!isConcave[i])
break;
i--;
} while (i > 0);
break;
}
previous = i;
i = next;
next = (next + 1) % vertexCount;
}
triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
triangles.push(indices[i]);
triangles.push(indices[(i + 1) % vertexCount]);
indices.splice(i, 1);
isConcave.splice(i, 1);
vertexCount--;
var previousIndex = (vertexCount + i - 1) % vertexCount;
var nextIndex = i == vertexCount ? 0 : i;
isConcave[previousIndex] = ConvexDecomposer.isConcave(previousIndex, vertexCount, vertices, indices);
isConcave[nextIndex] = ConvexDecomposer.isConcave(nextIndex, vertexCount, vertices, indices);
}
if (vertexCount == 3) {
triangles.push(indices[2]);
triangles.push(indices[0]);
triangles.push(indices[1]);
}
var convexPolygons = this.convexPolygons;
this.polygonPool.freeAll(convexPolygons);
convexPolygons.length = 0;
var convexPolygonsIndices = this.convexPolygonsIndices;
this.polygonIndicesPool.freeAll(convexPolygonsIndices);
convexPolygonsIndices.length = 0;
var polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
var polygon = this.polygonPool.obtain();
polygon.length = 0;
var fanBaseIndex = -1, lastWinding = 0;
for (var i = 0, n = triangles.length; i < n; i += 3) {
var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
var x1 = vertices[t1], y1 = vertices[t1 + 1];
var x2 = vertices[t2], y2 = vertices[t2 + 1];
var x3 = vertices[t3], y3 = vertices[t3 + 1];
var merged = false;
if (fanBaseIndex == t1) {
var o = polygon.length - 4;
var winding1 = ConvexDecomposer.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
if (winding1 == lastWinding && winding2 == lastWinding) {
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(t3);
merged = true;
}
}
if (!merged) {
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
polygon = this.polygonPool.obtain();
polygon.length = 0;
polygon.push(x1);
polygon.push(y1);
polygon.push(x2);
polygon.push(y2);
polygon.push(x3);
polygon.push(y3);
polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
polygonIndices.push(t1);
polygonIndices.push(t2);
polygonIndices.push(t3);
lastWinding = ConvexDecomposer.winding(x1, y1, x2, y2, x3, y3);
fanBaseIndex = t1;
}
}
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
for (var i = 0, n = convexPolygons.length; i < n; i++) {
polygonIndices = convexPolygonsIndices[i];
if (polygonIndices.length == 0)
continue;
var firstIndex = polygonIndices[0];
var lastIndex = polygonIndices[polygonIndices.length - 1];
polygon = convexPolygons[i];
var o = polygon.length - 4;
var prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
var prevX = polygon[o + 2], prevY = polygon[o + 3];
var firstX = polygon[0], firstY = polygon[1];
var secondX = polygon[2], secondY = polygon[3];
var winding = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
for (var ii = 0; ii < n; ii++) {
if (ii == i)
continue;
var otherIndices = convexPolygonsIndices[ii];
if (otherIndices.length != 3)
continue;
var otherFirstIndex = otherIndices[0];
var otherSecondIndex = otherIndices[1];
var otherLastIndex = otherIndices[2];
var otherPoly = convexPolygons[ii];
var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
continue;
var winding1 = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, firstX, firstY, secondX, secondY);
if (winding1 == winding && winding2 == winding) {
otherPoly.length = 0;
otherIndices.length = 0;
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(otherLastIndex);
prevPrevX = prevX;
prevPrevY = prevY;
prevX = x3;
prevY = y3;
ii = 0;
}
}
}
for (var i = convexPolygons.length - 1; i >= 0; i--) {
polygon = convexPolygons[i];
if (polygon.length == 0) {
convexPolygons.splice(i, 1);
this.polygonPool.free(polygon);
}
}
return convexPolygons;
};
ConvexDecomposer.isConcave = function (index, vertexCount, vertices, indices) {
var previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
var current = indices[index] << 1;
var next = indices[(index + 1) % vertexCount] << 1;
return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]);
};
ConvexDecomposer.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) {
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
};
ConvexDecomposer.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) {
var px = p2x - p1x, py = p2y - p1y;
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
};
return ConvexDecomposer;
}());
spine.ConvexDecomposer = ConvexDecomposer;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var Event = (function () { var Event = (function () {
function Event(time, data) { function Event(time, data) {
@ -4265,6 +4481,285 @@ var spine;
spine.SkeletonBounds = SkeletonBounds; spine.SkeletonBounds = SkeletonBounds;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var SkeletonClipping = (function () {
function SkeletonClipping() {
this.decomposer = new spine.ConvexDecomposer();
this.clippingPolygon = new Array();
this.clipOutput = new Array();
this.clippedVertices = new Array();
this.clippedTriangles = new Array();
this.scratch = new Array();
}
SkeletonClipping.prototype.clipStart = function (slot, clip) {
if (this.clipAttachment != null)
return;
this.clipAttachment = clip;
var n = clip.worldVerticesLength;
var vertices = spine.Utils.setArraySize(this.clippingPolygon, n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.decomposer.decompose(clippingPolygon);
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
polygon.push(polygon[1]);
}
};
SkeletonClipping.prototype.clipEndWithSlot = function (slot) {
if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data)
this.clipEnd();
};
SkeletonClipping.prototype.clipEnd = function () {
if (this.clipAttachment == null)
return;
this.clipAttachment = null;
this.clippingPolygons = null;
this.clippedVertices.length = 0;
this.clippedTriangles.length = 0;
this.clippingPolygon.length = 0;
};
SkeletonClipping.prototype.isClipping = function () {
return this.clipAttachment != null;
};
SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
var clippedTriangles = this.clippedTriangles;
var polygons = this.clippingPolygons;
var polygonsCount = this.clippingPolygons.length;
var vertexSize = twoColor ? 12 : 8;
var index = 0;
clippedVertices.length = 0;
clippedTriangles.length = 0;
outer: for (var i = 0; i < trianglesLength; i += 3) {
var vertexOffset = triangles[i] << 1;
var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 1] << 1;
var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 2] << 1;
var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
for (var p = 0; p < polygonsCount; p++) {
var s = clippedVertices.length;
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
var clipOutputLength = clipOutput.length;
if (clipOutputLength == 0)
continue;
var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
var d = 1 / (d0 * d2 + d1 * (y1 - y3));
var clipOutputCount = clipOutputLength >> 1;
var clipOutputItems = this.clipOutput;
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
for (var ii = 0; ii < clipOutputLength; ii += 2) {
var x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
var c0 = x - x3, c1 = y - y3;
var a = (d0 * c0 + d1 * c1) * d;
var b = (d4 * c0 + d2 * c1) * d;
var c = 1 - a - b;
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
if (twoColor) {
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 8] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
}
s += vertexSize;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (var ii = 1; ii < clipOutputCount; ii++) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + ii);
clippedTrianglesItems[s + 2] = (index + ii + 1);
s += 3;
}
index += clipOutputCount + 1;
}
else {
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
clippedVerticesItems[s] = x1;
clippedVerticesItems[s + 1] = y1;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
if (!twoColor) {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = x2;
clippedVerticesItems[s + 9] = y2;
clippedVerticesItems[s + 10] = light.r;
clippedVerticesItems[s + 11] = light.g;
clippedVerticesItems[s + 12] = light.b;
clippedVerticesItems[s + 13] = light.a;
clippedVerticesItems[s + 14] = u2;
clippedVerticesItems[s + 15] = v2;
clippedVerticesItems[s + 16] = x3;
clippedVerticesItems[s + 17] = y3;
clippedVerticesItems[s + 18] = light.r;
clippedVerticesItems[s + 19] = light.g;
clippedVerticesItems[s + 20] = light.b;
clippedVerticesItems[s + 21] = light.a;
clippedVerticesItems[s + 22] = u3;
clippedVerticesItems[s + 23] = v3;
}
else {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
clippedVerticesItems[s + 12] = x2;
clippedVerticesItems[s + 13] = y2;
clippedVerticesItems[s + 14] = light.r;
clippedVerticesItems[s + 15] = light.g;
clippedVerticesItems[s + 16] = light.b;
clippedVerticesItems[s + 17] = light.a;
clippedVerticesItems[s + 18] = u2;
clippedVerticesItems[s + 19] = v2;
clippedVerticesItems[s + 20] = dark.r;
clippedVerticesItems[s + 21] = dark.g;
clippedVerticesItems[s + 22] = dark.b;
clippedVerticesItems[s + 23] = dark.a;
clippedVerticesItems[s + 24] = x3;
clippedVerticesItems[s + 25] = y3;
clippedVerticesItems[s + 26] = light.r;
clippedVerticesItems[s + 27] = light.g;
clippedVerticesItems[s + 28] = light.b;
clippedVerticesItems[s + 29] = light.a;
clippedVerticesItems[s + 30] = u3;
clippedVerticesItems[s + 31] = v3;
clippedVerticesItems[s + 32] = dark.r;
clippedVerticesItems[s + 33] = dark.g;
clippedVerticesItems[s + 34] = dark.b;
clippedVerticesItems[s + 35] = dark.a;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3);
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + 1);
clippedTrianglesItems[s + 2] = (index + 2);
index += 3;
continue outer;
}
}
}
};
SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) {
var originalOutput = output;
var clipped = false;
var input = null;
if (clippingArea.length % 4 >= 2) {
input = output;
output = this.scratch;
}
else
input = this.scratch;
input.length = 0;
input.push(x1);
input.push(y1);
input.push(x2);
input.push(y2);
input.push(x3);
input.push(y3);
input.push(x1);
input.push(y1);
output.length = 0;
var clippingVertices = clippingArea;
var clippingVerticesLast = clippingArea.length - 4;
for (var i = 0;; i += 2) {
var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
var inputVertices = input;
var inputVerticesLength = input.length - 2, outputStart = output.length;
for (var ii = 0; ii < inputVerticesLength; ii += 2) {
var inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
if (side2) {
output.push(inputX2);
output.push(inputY2);
continue;
}
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
}
else if (side2) {
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
output.push(inputX2);
output.push(inputY2);
}
clipped = true;
}
if (outputStart == output.length) {
originalOutput.length = 0;
return true;
}
output.push(output[0]);
output.push(output[1]);
if (i == clippingVerticesLast)
break;
var temp = output;
output = input;
output.length = 0;
input = temp;
}
if (originalOutput != output) {
originalOutput.length = 0;
for (var i = 0, n = output.length - 2; i < n; i++)
originalOutput[i] = output[i];
}
else
originalOutput.length = originalOutput.length - 2;
return clipped;
};
SkeletonClipping.makeClockwise = function (polygon) {
var vertices = polygon;
var verticeslength = polygon.length;
var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
for (var i = 0, n = verticeslength - 3; i < n; i += 2) {
p1x = vertices[i];
p1y = vertices[i + 1];
p2x = vertices[i + 2];
p2y = vertices[i + 3];
area += p1x * p2y - p2x * p1y;
}
if (area < 0)
return;
for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
var x = vertices[i], y = vertices[i + 1];
var other = lastX - i;
vertices[i] = vertices[other];
vertices[i + 1] = vertices[other + 1];
vertices[other] = x;
vertices[other + 1] = y;
}
};
return SkeletonClipping;
}());
spine.SkeletonClipping = SkeletonClipping;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var SkeletonData = (function () { var SkeletonData = (function () {
function SkeletonData() { function SkeletonData() {
@ -4556,7 +5051,7 @@ var spine;
throw new Error("Slot not found: " + slotName); throw new Error("Slot not found: " + slotName);
var slotMap = skinMap[slotName]; var slotMap = skinMap[slotName];
for (var entryName in slotMap) { for (var entryName in slotMap) {
var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData);
if (attachment != null) if (attachment != null)
skin.addAttachment(slotIndex, entryName, attachment); skin.addAttachment(slotIndex, entryName, attachment);
} }
@ -4596,7 +5091,7 @@ var spine;
} }
return skeletonData; return skeletonData;
}; };
SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) {
var scale = this.scale; var scale = this.scale;
name = this.getValue(map, "name", name); name = this.getValue(map, "name", name);
var type = this.getValue(map, "type", "region"); var type = this.getValue(map, "type", "region");
@ -4683,6 +5178,24 @@ var spine;
point.color.setFromString(color); point.color.setFromString(color);
return point; return point;
} }
case "clipping": {
var clip = this.attachmentLoader.newClippingAttachment(skin, name);
if (clip == null)
return null;
var end = this.getValue(map, "end", null);
if (end != null) {
var slot = skeletonData.findSlot(end);
if (slot == null)
throw new Error("Clipping end slot not found: " + end);
clip.endSlot = slot;
}
var vertexCount = map.vertexCount;
this.readVertices(map, clip, vertexCount << 1);
var color = this.getValue(map, "color", null);
if (color != null)
clip.color.setFromString(color);
return clip;
}
} }
return null; return null;
}; };
@ -5797,6 +6310,17 @@ var spine;
return array; return array;
} }
}; };
Utils.newShortArray = function (size) {
if (Utils.SUPPORTS_TYPED_ARRAYS) {
return new Int16Array(size);
}
else {
var array = new Array(size);
for (var i = 0; i < array.length; i++)
array[i] = 0;
return array;
}
};
Utils.toFloatArray = function (array) { Utils.toFloatArray = function (array) {
return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
}; };
@ -8101,6 +8625,7 @@ var spine;
this.attachmentLineColor = new spine.Color(0, 0, 1, 0.5); this.attachmentLineColor = new spine.Color(0, 0, 1, 0.5);
this.triangleLineColor = new spine.Color(1, 0.64, 0, 0.5); this.triangleLineColor = new spine.Color(1, 0.64, 0, 0.5);
this.pathColor = new spine.Color().setFromString("FF7F00"); this.pathColor = new spine.Color().setFromString("FF7F00");
this.clipColor = new spine.Color(0.8, 0, 0, 2);
this.aabbColor = new spine.Color(0, 1, 0, 0.5); this.aabbColor = new spine.Color(0, 1, 0, 0.5);
this.drawBones = true; this.drawBones = true;
this.drawRegionAttachments = true; this.drawRegionAttachments = true;
@ -8109,6 +8634,7 @@ var spine;
this.drawMeshTriangles = true; this.drawMeshTriangles = true;
this.drawPaths = true; this.drawPaths = true;
this.drawSkeletonXY = false; this.drawSkeletonXY = false;
this.drawClipping = true;
this.premultipliedAlpha = false; this.premultipliedAlpha = false;
this.scale = 1; this.scale = 1;
this.boneWidth = 2; this.boneWidth = 2;
@ -8249,6 +8775,27 @@ var spine;
shapes.circle(true, skeletonX + bone.worldX, skeletonY + bone.worldY, 3 * this.scale, SkeletonDebugRenderer.GREEN, 8); shapes.circle(true, skeletonX + bone.worldX, skeletonY + bone.worldY, 3 * this.scale, SkeletonDebugRenderer.GREEN, 8);
} }
} }
if (this.drawClipping) {
var slots = skeleton.slots;
shapes.setColor(this.clipColor);
for (var i = 0, n = slots.length; i < n; i++) {
var slot = slots[i];
var attachment = slot.getAttachment();
if (!(attachment instanceof spine.ClippingAttachment))
continue;
var clip = attachment;
var nn = clip.worldVerticesLength;
var world = this.temp = spine.Utils.setArraySize(this.temp, nn, 0);
clip.computeWorldVertices(slot, 0, nn, world, 0, 2);
for (var i_5 = 0, n_2 = world.length; i_5 < n_2; i_5 += 2) {
var x = world[i_5];
var y = world[i_5 + 1];
var x2 = world[(i_5 + 2) % world.length];
var y2 = world[(i_5 + 3) % world.length];
shapes.line(x, y, x2, y2);
}
}
}
}; };
SkeletonDebugRenderer.prototype.dispose = function () { SkeletonDebugRenderer.prototype.dispose = function () {
}; };
@ -8264,8 +8811,9 @@ var spine;
var webgl; var webgl;
(function (webgl) { (function (webgl) {
var Renderable = (function () { var Renderable = (function () {
function Renderable(vertices, numFloats) { function Renderable(vertices, numVertices, numFloats) {
this.vertices = vertices; this.vertices = vertices;
this.numVertices = numVertices;
this.numFloats = numFloats; this.numFloats = numFloats;
} }
return Renderable; return Renderable;
@ -8279,7 +8827,8 @@ var spine;
this.tempColor2 = new spine.Color(); this.tempColor2 = new spine.Color();
this.vertexSize = 2 + 2 + 4; this.vertexSize = 2 + 2 + 4;
this.twoColorTint = false; this.twoColorTint = false;
this.renderable = new Renderable(null, 0); this.renderable = new Renderable(null, 0, 0);
this.clipper = new spine.SkeletonClipping();
this.gl = gl; this.gl = gl;
this.twoColorTint = twoColorTint; this.twoColorTint = twoColorTint;
if (twoColorTint) if (twoColorTint)
@ -8287,165 +8836,115 @@ var spine;
this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024); this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024);
} }
SkeletonRenderer.prototype.draw = function (batcher, skeleton) { SkeletonRenderer.prototype.draw = function (batcher, skeleton) {
var clipper = this.clipper;
var premultipliedAlpha = this.premultipliedAlpha; var premultipliedAlpha = this.premultipliedAlpha;
var twoColorTint = this.twoColorTint;
var blendMode = null; var blendMode = null;
var vertices = null; var renderable = this.renderable;
var uvs = null;
var triangles = null; var triangles = null;
var drawOrder = skeleton.drawOrder; var drawOrder = skeleton.drawOrder;
var attachmentColor = null;
var skeletonColor = skeleton.color;
var vertexSize = twoColorTint ? 12 : 8;
for (var i = 0, n = drawOrder.length; i < n; i++) { for (var i = 0, n = drawOrder.length; i < n; i++) {
var clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
var slot = drawOrder[i]; var slot = drawOrder[i];
var attachment = slot.getAttachment(); var attachment = slot.getAttachment();
var texture = null; var texture = null;
if (attachment instanceof spine.RegionAttachment) { if (attachment instanceof spine.RegionAttachment) {
var region = attachment; var region = attachment;
vertices = this.computeRegionVertices(slot, region, premultipliedAlpha, this.twoColorTint); renderable.vertices = this.vertices;
renderable.numVertices = 4;
renderable.numFloats = clippedVertexSize << 2;
region.computeWorldVertices(slot.bone, renderable.vertices, 0, clippedVertexSize);
triangles = SkeletonRenderer.QUAD_TRIANGLES; triangles = SkeletonRenderer.QUAD_TRIANGLES;
uvs = region.uvs;
texture = region.region.renderObject.texture; texture = region.region.renderObject.texture;
attachmentColor = region.color;
} }
else if (attachment instanceof spine.MeshAttachment) { else if (attachment instanceof spine.MeshAttachment) {
var mesh = attachment; var mesh = attachment;
vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha, this.twoColorTint); renderable.vertices = this.vertices;
renderable.numVertices = (mesh.worldVerticesLength >> 1);
renderable.numFloats = renderable.numVertices * clippedVertexSize;
if (renderable.numFloats > renderable.vertices.length) {
renderable.vertices = this.vertices = spine.Utils.newFloatArray(renderable.numFloats);
}
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);
triangles = mesh.triangles; triangles = mesh.triangles;
texture = mesh.region.renderObject.texture; texture = mesh.region.renderObject.texture;
uvs = mesh.uvs;
attachmentColor = mesh.color;
}
else if (attachment instanceof spine.ClippingAttachment) {
var clip = (attachment);
clipper.clipStart(slot, clip);
continue;
} }
else else
continue; continue;
if (texture != null) { if (texture != null) {
var slotColor = slot.color;
var finalColor = this.tempColor;
finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r;
finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g;
finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b;
finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a;
if (premultipliedAlpha) {
finalColor.r *= finalColor.a;
finalColor.g *= finalColor.a;
finalColor.b *= finalColor.a;
}
var darkColor = this.tempColor2;
if (slot.darkColor == null)
darkColor.set(0, 0, 0, 1);
else
darkColor.setFromColor(slot.darkColor);
var slotBlendMode = slot.data.blendMode; var slotBlendMode = slot.data.blendMode;
if (slotBlendMode != blendMode) { if (slotBlendMode != blendMode) {
blendMode = slotBlendMode; blendMode = slotBlendMode;
batcher.setBlendMode(webgl.getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), webgl.getDestGLBlendMode(this.gl, blendMode)); batcher.setBlendMode(webgl.getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), webgl.getDestGLBlendMode(this.gl, blendMode));
} }
var view = vertices.vertices.subarray(0, vertices.numFloats); if (clipper.isClipping()) {
batcher.draw(texture, view, triangles); clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
var clippedVertices = new Float32Array(clipper.clippedVertices);
var clippedTriangles = clipper.clippedTriangles;
batcher.draw(texture, clippedVertices, clippedTriangles);
}
else {
var verts = renderable.vertices;
if (!twoColorTint) {
for (var v = 2, u = 0, n_3 = renderable.numFloats; v < n_3; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
verts[v + 3] = finalColor.a;
verts[v + 4] = uvs[u];
verts[v + 5] = uvs[u + 1];
}
}
else {
for (var v = 2, u = 0, n_4 = renderable.numFloats; v < n_4; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
verts[v + 3] = finalColor.a;
verts[v + 4] = uvs[u];
verts[v + 5] = uvs[u + 1];
verts[v + 6] = darkColor.r;
verts[v + 7] = darkColor.g;
verts[v + 8] = darkColor.b;
verts[v + 9] = darkColor.a;
}
}
var view = renderable.vertices.subarray(0, renderable.numFloats);
batcher.draw(texture, view, triangles);
}
} }
clipper.clipEndWithSlot(slot);
} }
}; clipper.clipEnd();
SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma, twoColorTint) {
if (twoColorTint === void 0) { twoColorTint = false; }
var skeleton = slot.bone.skeleton;
var skeletonColor = skeleton.color;
var slotColor = slot.color;
var regionColor = region.color;
var alpha = skeletonColor.a * slotColor.a * regionColor.a;
var multiplier = pma ? alpha : 1;
var color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
var dark = this.tempColor2;
if (slot.darkColor == null)
dark.set(0, 0, 0, 1);
else
dark.setFromColor(slot.darkColor);
region.computeWorldVertices(slot.bone, this.vertices, 0, this.vertexSize);
var vertices = this.vertices;
var uvs = region.uvs;
var i = 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[0];
vertices[i++] = uvs[1];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i += 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[2];
vertices[i++] = uvs[3];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i += 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[4];
vertices[i++] = uvs[5];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i += 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[6];
vertices[i++] = uvs[7];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
this.renderable.vertices = vertices;
this.renderable.numFloats = 4 * (twoColorTint ? 12 : 8);
return this.renderable;
};
SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma, twoColorTint) {
if (twoColorTint === void 0) { twoColorTint = false; }
var skeleton = slot.bone.skeleton;
var skeletonColor = skeleton.color;
var slotColor = slot.color;
var regionColor = mesh.color;
var alpha = skeletonColor.a * slotColor.a * regionColor.a;
var multiplier = pma ? alpha : 1;
var color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
var dark = this.tempColor2;
if (slot.darkColor == null)
dark.set(0, 0, 0, 1);
else
dark.setFromColor(slot.darkColor);
var numVertices = mesh.worldVerticesLength / 2;
if (this.vertices.length < mesh.worldVerticesLength) {
this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength);
}
var vertices = this.vertices;
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, this.vertexSize);
var uvs = mesh.uvs;
if (!twoColorTint) {
for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
vertices[v++] = color.r;
vertices[v++] = color.g;
vertices[v++] = color.b;
vertices[v++] = color.a;
vertices[v++] = uvs[u++];
vertices[v++] = uvs[u++];
v += 2;
}
}
else {
for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
vertices[v++] = color.r;
vertices[v++] = color.g;
vertices[v++] = color.b;
vertices[v++] = color.a;
vertices[v++] = uvs[u++];
vertices[v++] = uvs[u++];
vertices[v++] = dark.r;
vertices[v++] = dark.g;
vertices[v++] = dark.b;
vertices[v++] = 1;
v += 2;
}
}
this.renderable.vertices = vertices;
this.renderable.numFloats = numVertices * (twoColorTint ? 12 : 8);
return this.renderable;
}; };
SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
return SkeletonRenderer; return SkeletonRenderer;

File diff suppressed because one or more lines are too long

View File

@ -454,6 +454,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -477,6 +478,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -495,6 +497,13 @@ declare module spine {
constructor(name: string); constructor(name: string);
} }
} }
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine { declare module spine {
class MeshAttachment extends VertexAttachment { class MeshAttachment extends VertexAttachment {
region: TextureRegion; region: TextureRegion;
@ -678,6 +687,21 @@ declare module spine {
getOrder(): number; getOrder(): number;
} }
} }
declare module spine {
class ConvexDecomposer {
private convexPolygons;
private convexPolygonsIndices;
private indicesArray;
private isConcaveArray;
private triangles;
private polygonPool;
private polygonIndicesPool;
decompose(input: ArrayLike<number>): Array<Array<number>>;
private static isConcave(index, vertexCount, vertices, indices);
private static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y);
private static winding(p1x, p1y, p2x, p2y, p3x, p3y);
}
}
declare module spine { declare module spine {
class Event { class Event {
data: EventData; data: EventData;
@ -873,6 +897,25 @@ declare module spine {
getHeight(): number; getHeight(): number;
} }
} }
declare module spine {
class SkeletonClipping {
private decomposer;
private clippingPolygon;
private clipOutput;
clippedVertices: number[];
clippedTriangles: number[];
private scratch;
private clipAttachment;
private clippingPolygons;
clipStart(slot: Slot, clip: ClippingAttachment): void;
clipEndWithSlot(slot: Slot): void;
clipEnd(): void;
isClipping(): boolean;
clipTriangles(vertices: ArrayLike<number>, verticesLength: number, triangles: ArrayLike<number>, trianglesLength: number, uvs: ArrayLike<number>, light: Color, dark: Color, twoColor: boolean): void;
clip(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array<number>, output: Array<number>): boolean;
static makeClockwise(polygon: ArrayLike<number>): void;
}
}
declare module spine { declare module spine {
class SkeletonData { class SkeletonData {
name: string; name: string;
@ -911,7 +954,7 @@ declare module spine {
private linkedMeshes; private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader); constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(json: string | any): SkeletonData; readSkeletonData(json: string | any): SkeletonData;
readAttachment(map: any, skin: Skin, slotIndex: number, name: string): Attachment; readAttachment(map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment;
readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void; readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void;
readAnimation(map: any, name: string, skeletonData: SkeletonData): void; readAnimation(map: any, name: string, skeletonData: SkeletonData): void;
readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void; readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void;
@ -1089,6 +1132,7 @@ declare module spine {
static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>; static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>;
static newArray<T>(size: number, defaultValue: T): Array<T>; static newArray<T>(size: number, defaultValue: T): Array<T>;
static newFloatArray(size: number): ArrayLike<number>; static newFloatArray(size: number): ArrayLike<number>;
static newShortArray(size: number): ArrayLike<number>;
static toFloatArray(array: Array<number>): number[] | Float32Array; static toFloatArray(array: Array<number>): number[] | Float32Array;
} }
class DebugUtils { class DebugUtils {

View File

@ -2242,6 +2242,9 @@ var spine;
AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) {
return new spine.PointAttachment(name); return new spine.PointAttachment(name);
}; };
AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) {
return new spine.ClippingAttachment(name);
};
return AtlasAttachmentLoader; return AtlasAttachmentLoader;
}()); }());
spine.AtlasAttachmentLoader = AtlasAttachmentLoader; spine.AtlasAttachmentLoader = AtlasAttachmentLoader;
@ -2354,6 +2357,18 @@ var spine;
spine.BoundingBoxAttachment = BoundingBoxAttachment; spine.BoundingBoxAttachment = BoundingBoxAttachment;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ClippingAttachment = (function (_super) {
__extends(ClippingAttachment, _super);
function ClippingAttachment(name) {
_super.call(this, name);
this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1);
}
return ClippingAttachment;
}(spine.VertexAttachment));
spine.ClippingAttachment = ClippingAttachment;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var MeshAttachment = (function (_super) { var MeshAttachment = (function (_super) {
__extends(MeshAttachment, _super); __extends(MeshAttachment, _super);
@ -2897,6 +2912,207 @@ var spine;
var TransformMode = spine.TransformMode; var TransformMode = spine.TransformMode;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ConvexDecomposer = (function () {
function ConvexDecomposer() {
this.convexPolygons = new Array();
this.convexPolygonsIndices = new Array();
this.indicesArray = new Array();
this.isConcaveArray = new Array();
this.triangles = new Array();
this.polygonPool = new spine.Pool(function () {
return new Array();
});
this.polygonIndicesPool = new spine.Pool(function () {
return new Array();
});
}
ConvexDecomposer.prototype.decompose = function (input) {
var vertices = input;
var vertexCount = input.length >> 1;
var indices = this.indicesArray;
indices.length = 0;
for (var i = 0; i < vertexCount; i++)
indices[i] = i;
var isConcave = this.isConcaveArray;
isConcave.length = 0;
for (var i = 0, n = vertexCount; i < n; ++i)
isConcave[i] = ConvexDecomposer.isConcave(i, vertexCount, vertices, indices);
var triangles = this.triangles;
triangles.length = 0;
while (vertexCount > 3) {
var previous = vertexCount - 1, i = 0, next = 1;
while (true) {
outer: if (!isConcave[i]) {
var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
var p1x = vertices[p1], p1y = vertices[p1 + 1];
var p2x = vertices[p2], p2y = vertices[p2 + 1];
var p3x = vertices[p3], p3y = vertices[p3 + 1];
for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
if (!isConcave[ii])
continue;
var v = indices[ii] << 1;
var vx = vertices[v], vy = vertices[v + 1];
if (ConvexDecomposer.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
break outer;
}
}
}
break;
}
if (next == 0) {
do {
if (!isConcave[i])
break;
i--;
} while (i > 0);
break;
}
previous = i;
i = next;
next = (next + 1) % vertexCount;
}
triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
triangles.push(indices[i]);
triangles.push(indices[(i + 1) % vertexCount]);
indices.splice(i, 1);
isConcave.splice(i, 1);
vertexCount--;
var previousIndex = (vertexCount + i - 1) % vertexCount;
var nextIndex = i == vertexCount ? 0 : i;
isConcave[previousIndex] = ConvexDecomposer.isConcave(previousIndex, vertexCount, vertices, indices);
isConcave[nextIndex] = ConvexDecomposer.isConcave(nextIndex, vertexCount, vertices, indices);
}
if (vertexCount == 3) {
triangles.push(indices[2]);
triangles.push(indices[0]);
triangles.push(indices[1]);
}
var convexPolygons = this.convexPolygons;
this.polygonPool.freeAll(convexPolygons);
convexPolygons.length = 0;
var convexPolygonsIndices = this.convexPolygonsIndices;
this.polygonIndicesPool.freeAll(convexPolygonsIndices);
convexPolygonsIndices.length = 0;
var polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
var polygon = this.polygonPool.obtain();
polygon.length = 0;
var fanBaseIndex = -1, lastWinding = 0;
for (var i = 0, n = triangles.length; i < n; i += 3) {
var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
var x1 = vertices[t1], y1 = vertices[t1 + 1];
var x2 = vertices[t2], y2 = vertices[t2 + 1];
var x3 = vertices[t3], y3 = vertices[t3 + 1];
var merged = false;
if (fanBaseIndex == t1) {
var o = polygon.length - 4;
var winding1 = ConvexDecomposer.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
if (winding1 == lastWinding && winding2 == lastWinding) {
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(t3);
merged = true;
}
}
if (!merged) {
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
polygon = this.polygonPool.obtain();
polygon.length = 0;
polygon.push(x1);
polygon.push(y1);
polygon.push(x2);
polygon.push(y2);
polygon.push(x3);
polygon.push(y3);
polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
polygonIndices.push(t1);
polygonIndices.push(t2);
polygonIndices.push(t3);
lastWinding = ConvexDecomposer.winding(x1, y1, x2, y2, x3, y3);
fanBaseIndex = t1;
}
}
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
for (var i = 0, n = convexPolygons.length; i < n; i++) {
polygonIndices = convexPolygonsIndices[i];
if (polygonIndices.length == 0)
continue;
var firstIndex = polygonIndices[0];
var lastIndex = polygonIndices[polygonIndices.length - 1];
polygon = convexPolygons[i];
var o = polygon.length - 4;
var prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
var prevX = polygon[o + 2], prevY = polygon[o + 3];
var firstX = polygon[0], firstY = polygon[1];
var secondX = polygon[2], secondY = polygon[3];
var winding = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
for (var ii = 0; ii < n; ii++) {
if (ii == i)
continue;
var otherIndices = convexPolygonsIndices[ii];
if (otherIndices.length != 3)
continue;
var otherFirstIndex = otherIndices[0];
var otherSecondIndex = otherIndices[1];
var otherLastIndex = otherIndices[2];
var otherPoly = convexPolygons[ii];
var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
continue;
var winding1 = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, firstX, firstY, secondX, secondY);
if (winding1 == winding && winding2 == winding) {
otherPoly.length = 0;
otherIndices.length = 0;
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(otherLastIndex);
prevPrevX = prevX;
prevPrevY = prevY;
prevX = x3;
prevY = y3;
ii = 0;
}
}
}
for (var i = convexPolygons.length - 1; i >= 0; i--) {
polygon = convexPolygons[i];
if (polygon.length == 0) {
convexPolygons.splice(i, 1);
this.polygonPool.free(polygon);
}
}
return convexPolygons;
};
ConvexDecomposer.isConcave = function (index, vertexCount, vertices, indices) {
var previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
var current = indices[index] << 1;
var next = indices[(index + 1) % vertexCount] << 1;
return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]);
};
ConvexDecomposer.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) {
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
};
ConvexDecomposer.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) {
var px = p2x - p1x, py = p2y - p1y;
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
};
return ConvexDecomposer;
}());
spine.ConvexDecomposer = ConvexDecomposer;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var Event = (function () { var Event = (function () {
function Event(time, data) { function Event(time, data) {
@ -4265,6 +4481,285 @@ var spine;
spine.SkeletonBounds = SkeletonBounds; spine.SkeletonBounds = SkeletonBounds;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var SkeletonClipping = (function () {
function SkeletonClipping() {
this.decomposer = new spine.ConvexDecomposer();
this.clippingPolygon = new Array();
this.clipOutput = new Array();
this.clippedVertices = new Array();
this.clippedTriangles = new Array();
this.scratch = new Array();
}
SkeletonClipping.prototype.clipStart = function (slot, clip) {
if (this.clipAttachment != null)
return;
this.clipAttachment = clip;
var n = clip.worldVerticesLength;
var vertices = spine.Utils.setArraySize(this.clippingPolygon, n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.decomposer.decompose(clippingPolygon);
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
polygon.push(polygon[1]);
}
};
SkeletonClipping.prototype.clipEndWithSlot = function (slot) {
if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data)
this.clipEnd();
};
SkeletonClipping.prototype.clipEnd = function () {
if (this.clipAttachment == null)
return;
this.clipAttachment = null;
this.clippingPolygons = null;
this.clippedVertices.length = 0;
this.clippedTriangles.length = 0;
this.clippingPolygon.length = 0;
};
SkeletonClipping.prototype.isClipping = function () {
return this.clipAttachment != null;
};
SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
var clippedTriangles = this.clippedTriangles;
var polygons = this.clippingPolygons;
var polygonsCount = this.clippingPolygons.length;
var vertexSize = twoColor ? 12 : 8;
var index = 0;
clippedVertices.length = 0;
clippedTriangles.length = 0;
outer: for (var i = 0; i < trianglesLength; i += 3) {
var vertexOffset = triangles[i] << 1;
var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 1] << 1;
var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 2] << 1;
var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
for (var p = 0; p < polygonsCount; p++) {
var s = clippedVertices.length;
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
var clipOutputLength = clipOutput.length;
if (clipOutputLength == 0)
continue;
var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
var d = 1 / (d0 * d2 + d1 * (y1 - y3));
var clipOutputCount = clipOutputLength >> 1;
var clipOutputItems = this.clipOutput;
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
for (var ii = 0; ii < clipOutputLength; ii += 2) {
var x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
var c0 = x - x3, c1 = y - y3;
var a = (d0 * c0 + d1 * c1) * d;
var b = (d4 * c0 + d2 * c1) * d;
var c = 1 - a - b;
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
if (twoColor) {
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 8] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
}
s += vertexSize;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (var ii = 1; ii < clipOutputCount; ii++) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + ii);
clippedTrianglesItems[s + 2] = (index + ii + 1);
s += 3;
}
index += clipOutputCount + 1;
}
else {
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
clippedVerticesItems[s] = x1;
clippedVerticesItems[s + 1] = y1;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
if (!twoColor) {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = x2;
clippedVerticesItems[s + 9] = y2;
clippedVerticesItems[s + 10] = light.r;
clippedVerticesItems[s + 11] = light.g;
clippedVerticesItems[s + 12] = light.b;
clippedVerticesItems[s + 13] = light.a;
clippedVerticesItems[s + 14] = u2;
clippedVerticesItems[s + 15] = v2;
clippedVerticesItems[s + 16] = x3;
clippedVerticesItems[s + 17] = y3;
clippedVerticesItems[s + 18] = light.r;
clippedVerticesItems[s + 19] = light.g;
clippedVerticesItems[s + 20] = light.b;
clippedVerticesItems[s + 21] = light.a;
clippedVerticesItems[s + 22] = u3;
clippedVerticesItems[s + 23] = v3;
}
else {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
clippedVerticesItems[s + 12] = x2;
clippedVerticesItems[s + 13] = y2;
clippedVerticesItems[s + 14] = light.r;
clippedVerticesItems[s + 15] = light.g;
clippedVerticesItems[s + 16] = light.b;
clippedVerticesItems[s + 17] = light.a;
clippedVerticesItems[s + 18] = u2;
clippedVerticesItems[s + 19] = v2;
clippedVerticesItems[s + 20] = dark.r;
clippedVerticesItems[s + 21] = dark.g;
clippedVerticesItems[s + 22] = dark.b;
clippedVerticesItems[s + 23] = dark.a;
clippedVerticesItems[s + 24] = x3;
clippedVerticesItems[s + 25] = y3;
clippedVerticesItems[s + 26] = light.r;
clippedVerticesItems[s + 27] = light.g;
clippedVerticesItems[s + 28] = light.b;
clippedVerticesItems[s + 29] = light.a;
clippedVerticesItems[s + 30] = u3;
clippedVerticesItems[s + 31] = v3;
clippedVerticesItems[s + 32] = dark.r;
clippedVerticesItems[s + 33] = dark.g;
clippedVerticesItems[s + 34] = dark.b;
clippedVerticesItems[s + 35] = dark.a;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3);
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + 1);
clippedTrianglesItems[s + 2] = (index + 2);
index += 3;
continue outer;
}
}
}
};
SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) {
var originalOutput = output;
var clipped = false;
var input = null;
if (clippingArea.length % 4 >= 2) {
input = output;
output = this.scratch;
}
else
input = this.scratch;
input.length = 0;
input.push(x1);
input.push(y1);
input.push(x2);
input.push(y2);
input.push(x3);
input.push(y3);
input.push(x1);
input.push(y1);
output.length = 0;
var clippingVertices = clippingArea;
var clippingVerticesLast = clippingArea.length - 4;
for (var i = 0;; i += 2) {
var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
var inputVertices = input;
var inputVerticesLength = input.length - 2, outputStart = output.length;
for (var ii = 0; ii < inputVerticesLength; ii += 2) {
var inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
if (side2) {
output.push(inputX2);
output.push(inputY2);
continue;
}
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
}
else if (side2) {
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
output.push(inputX2);
output.push(inputY2);
}
clipped = true;
}
if (outputStart == output.length) {
originalOutput.length = 0;
return true;
}
output.push(output[0]);
output.push(output[1]);
if (i == clippingVerticesLast)
break;
var temp = output;
output = input;
output.length = 0;
input = temp;
}
if (originalOutput != output) {
originalOutput.length = 0;
for (var i = 0, n = output.length - 2; i < n; i++)
originalOutput[i] = output[i];
}
else
originalOutput.length = originalOutput.length - 2;
return clipped;
};
SkeletonClipping.makeClockwise = function (polygon) {
var vertices = polygon;
var verticeslength = polygon.length;
var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
for (var i = 0, n = verticeslength - 3; i < n; i += 2) {
p1x = vertices[i];
p1y = vertices[i + 1];
p2x = vertices[i + 2];
p2y = vertices[i + 3];
area += p1x * p2y - p2x * p1y;
}
if (area < 0)
return;
for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
var x = vertices[i], y = vertices[i + 1];
var other = lastX - i;
vertices[i] = vertices[other];
vertices[i + 1] = vertices[other + 1];
vertices[other] = x;
vertices[other + 1] = y;
}
};
return SkeletonClipping;
}());
spine.SkeletonClipping = SkeletonClipping;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var SkeletonData = (function () { var SkeletonData = (function () {
function SkeletonData() { function SkeletonData() {
@ -4556,7 +5051,7 @@ var spine;
throw new Error("Slot not found: " + slotName); throw new Error("Slot not found: " + slotName);
var slotMap = skinMap[slotName]; var slotMap = skinMap[slotName];
for (var entryName in slotMap) { for (var entryName in slotMap) {
var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData);
if (attachment != null) if (attachment != null)
skin.addAttachment(slotIndex, entryName, attachment); skin.addAttachment(slotIndex, entryName, attachment);
} }
@ -4596,7 +5091,7 @@ var spine;
} }
return skeletonData; return skeletonData;
}; };
SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) {
var scale = this.scale; var scale = this.scale;
name = this.getValue(map, "name", name); name = this.getValue(map, "name", name);
var type = this.getValue(map, "type", "region"); var type = this.getValue(map, "type", "region");
@ -4683,6 +5178,24 @@ var spine;
point.color.setFromString(color); point.color.setFromString(color);
return point; return point;
} }
case "clipping": {
var clip = this.attachmentLoader.newClippingAttachment(skin, name);
if (clip == null)
return null;
var end = this.getValue(map, "end", null);
if (end != null) {
var slot = skeletonData.findSlot(end);
if (slot == null)
throw new Error("Clipping end slot not found: " + end);
clip.endSlot = slot;
}
var vertexCount = map.vertexCount;
this.readVertices(map, clip, vertexCount << 1);
var color = this.getValue(map, "color", null);
if (color != null)
clip.color.setFromString(color);
return clip;
}
} }
return null; return null;
}; };
@ -5797,6 +6310,17 @@ var spine;
return array; return array;
} }
}; };
Utils.newShortArray = function (size) {
if (Utils.SUPPORTS_TYPED_ARRAYS) {
return new Int16Array(size);
}
else {
var array = new Array(size);
for (var i = 0; i < array.length; i++)
array[i] = 0;
return array;
}
};
Utils.toFloatArray = function (array) { Utils.toFloatArray = function (array) {
return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
}; };

File diff suppressed because one or more lines are too long

View File

@ -383,6 +383,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -406,6 +407,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -424,6 +426,13 @@ declare module spine {
constructor(name: string); constructor(name: string);
} }
} }
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine { declare module spine {
class MeshAttachment extends VertexAttachment { class MeshAttachment extends VertexAttachment {
region: TextureRegion; region: TextureRegion;
@ -607,6 +616,21 @@ declare module spine {
getOrder(): number; getOrder(): number;
} }
} }
declare module spine {
class ConvexDecomposer {
private convexPolygons;
private convexPolygonsIndices;
private indicesArray;
private isConcaveArray;
private triangles;
private polygonPool;
private polygonIndicesPool;
decompose(input: ArrayLike<number>): Array<Array<number>>;
private static isConcave(index, vertexCount, vertices, indices);
private static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y);
private static winding(p1x, p1y, p2x, p2y, p3x, p3y);
}
}
declare module spine { declare module spine {
class Event { class Event {
data: EventData; data: EventData;
@ -802,6 +826,25 @@ declare module spine {
getHeight(): number; getHeight(): number;
} }
} }
declare module spine {
class SkeletonClipping {
private decomposer;
private clippingPolygon;
private clipOutput;
clippedVertices: number[];
clippedTriangles: number[];
private scratch;
private clipAttachment;
private clippingPolygons;
clipStart(slot: Slot, clip: ClippingAttachment): void;
clipEndWithSlot(slot: Slot): void;
clipEnd(): void;
isClipping(): boolean;
clipTriangles(vertices: ArrayLike<number>, verticesLength: number, triangles: ArrayLike<number>, trianglesLength: number, uvs: ArrayLike<number>, light: Color, dark: Color, twoColor: boolean): void;
clip(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array<number>, output: Array<number>): boolean;
static makeClockwise(polygon: ArrayLike<number>): void;
}
}
declare module spine { declare module spine {
class SkeletonData { class SkeletonData {
name: string; name: string;
@ -840,7 +883,7 @@ declare module spine {
private linkedMeshes; private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader); constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(json: string | any): SkeletonData; readSkeletonData(json: string | any): SkeletonData;
readAttachment(map: any, skin: Skin, slotIndex: number, name: string): Attachment; readAttachment(map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment;
readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void; readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void;
readAnimation(map: any, name: string, skeletonData: SkeletonData): void; readAnimation(map: any, name: string, skeletonData: SkeletonData): void;
readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void; readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void;
@ -1058,6 +1101,7 @@ declare module spine {
static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>; static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>;
static newArray<T>(size: number, defaultValue: T): Array<T>; static newArray<T>(size: number, defaultValue: T): Array<T>;
static newFloatArray(size: number): ArrayLike<number>; static newFloatArray(size: number): ArrayLike<number>;
static newShortArray(size: number): ArrayLike<number>;
static toFloatArray(array: Array<number>): number[] | Float32Array; static toFloatArray(array: Array<number>): number[] | Float32Array;
} }
class DebugUtils { class DebugUtils {

View File

@ -1922,6 +1922,9 @@ var spine;
AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) {
return new spine.PointAttachment(name); return new spine.PointAttachment(name);
}; };
AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) {
return new spine.ClippingAttachment(name);
};
return AtlasAttachmentLoader; return AtlasAttachmentLoader;
}()); }());
spine.AtlasAttachmentLoader = AtlasAttachmentLoader; spine.AtlasAttachmentLoader = AtlasAttachmentLoader;
@ -2034,6 +2037,18 @@ var spine;
spine.BoundingBoxAttachment = BoundingBoxAttachment; spine.BoundingBoxAttachment = BoundingBoxAttachment;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ClippingAttachment = (function (_super) {
__extends(ClippingAttachment, _super);
function ClippingAttachment(name) {
_super.call(this, name);
this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1);
}
return ClippingAttachment;
}(spine.VertexAttachment));
spine.ClippingAttachment = ClippingAttachment;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var MeshAttachment = (function (_super) { var MeshAttachment = (function (_super) {
__extends(MeshAttachment, _super); __extends(MeshAttachment, _super);
@ -2577,6 +2592,207 @@ var spine;
var TransformMode = spine.TransformMode; var TransformMode = spine.TransformMode;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ConvexDecomposer = (function () {
function ConvexDecomposer() {
this.convexPolygons = new Array();
this.convexPolygonsIndices = new Array();
this.indicesArray = new Array();
this.isConcaveArray = new Array();
this.triangles = new Array();
this.polygonPool = new spine.Pool(function () {
return new Array();
});
this.polygonIndicesPool = new spine.Pool(function () {
return new Array();
});
}
ConvexDecomposer.prototype.decompose = function (input) {
var vertices = input;
var vertexCount = input.length >> 1;
var indices = this.indicesArray;
indices.length = 0;
for (var i = 0; i < vertexCount; i++)
indices[i] = i;
var isConcave = this.isConcaveArray;
isConcave.length = 0;
for (var i = 0, n = vertexCount; i < n; ++i)
isConcave[i] = ConvexDecomposer.isConcave(i, vertexCount, vertices, indices);
var triangles = this.triangles;
triangles.length = 0;
while (vertexCount > 3) {
var previous = vertexCount - 1, i = 0, next = 1;
while (true) {
outer: if (!isConcave[i]) {
var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
var p1x = vertices[p1], p1y = vertices[p1 + 1];
var p2x = vertices[p2], p2y = vertices[p2 + 1];
var p3x = vertices[p3], p3y = vertices[p3 + 1];
for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
if (!isConcave[ii])
continue;
var v = indices[ii] << 1;
var vx = vertices[v], vy = vertices[v + 1];
if (ConvexDecomposer.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
break outer;
}
}
}
break;
}
if (next == 0) {
do {
if (!isConcave[i])
break;
i--;
} while (i > 0);
break;
}
previous = i;
i = next;
next = (next + 1) % vertexCount;
}
triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
triangles.push(indices[i]);
triangles.push(indices[(i + 1) % vertexCount]);
indices.splice(i, 1);
isConcave.splice(i, 1);
vertexCount--;
var previousIndex = (vertexCount + i - 1) % vertexCount;
var nextIndex = i == vertexCount ? 0 : i;
isConcave[previousIndex] = ConvexDecomposer.isConcave(previousIndex, vertexCount, vertices, indices);
isConcave[nextIndex] = ConvexDecomposer.isConcave(nextIndex, vertexCount, vertices, indices);
}
if (vertexCount == 3) {
triangles.push(indices[2]);
triangles.push(indices[0]);
triangles.push(indices[1]);
}
var convexPolygons = this.convexPolygons;
this.polygonPool.freeAll(convexPolygons);
convexPolygons.length = 0;
var convexPolygonsIndices = this.convexPolygonsIndices;
this.polygonIndicesPool.freeAll(convexPolygonsIndices);
convexPolygonsIndices.length = 0;
var polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
var polygon = this.polygonPool.obtain();
polygon.length = 0;
var fanBaseIndex = -1, lastWinding = 0;
for (var i = 0, n = triangles.length; i < n; i += 3) {
var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
var x1 = vertices[t1], y1 = vertices[t1 + 1];
var x2 = vertices[t2], y2 = vertices[t2 + 1];
var x3 = vertices[t3], y3 = vertices[t3 + 1];
var merged = false;
if (fanBaseIndex == t1) {
var o = polygon.length - 4;
var winding1 = ConvexDecomposer.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
if (winding1 == lastWinding && winding2 == lastWinding) {
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(t3);
merged = true;
}
}
if (!merged) {
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
polygon = this.polygonPool.obtain();
polygon.length = 0;
polygon.push(x1);
polygon.push(y1);
polygon.push(x2);
polygon.push(y2);
polygon.push(x3);
polygon.push(y3);
polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
polygonIndices.push(t1);
polygonIndices.push(t2);
polygonIndices.push(t3);
lastWinding = ConvexDecomposer.winding(x1, y1, x2, y2, x3, y3);
fanBaseIndex = t1;
}
}
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
for (var i = 0, n = convexPolygons.length; i < n; i++) {
polygonIndices = convexPolygonsIndices[i];
if (polygonIndices.length == 0)
continue;
var firstIndex = polygonIndices[0];
var lastIndex = polygonIndices[polygonIndices.length - 1];
polygon = convexPolygons[i];
var o = polygon.length - 4;
var prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
var prevX = polygon[o + 2], prevY = polygon[o + 3];
var firstX = polygon[0], firstY = polygon[1];
var secondX = polygon[2], secondY = polygon[3];
var winding = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
for (var ii = 0; ii < n; ii++) {
if (ii == i)
continue;
var otherIndices = convexPolygonsIndices[ii];
if (otherIndices.length != 3)
continue;
var otherFirstIndex = otherIndices[0];
var otherSecondIndex = otherIndices[1];
var otherLastIndex = otherIndices[2];
var otherPoly = convexPolygons[ii];
var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
continue;
var winding1 = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, firstX, firstY, secondX, secondY);
if (winding1 == winding && winding2 == winding) {
otherPoly.length = 0;
otherIndices.length = 0;
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(otherLastIndex);
prevPrevX = prevX;
prevPrevY = prevY;
prevX = x3;
prevY = y3;
ii = 0;
}
}
}
for (var i = convexPolygons.length - 1; i >= 0; i--) {
polygon = convexPolygons[i];
if (polygon.length == 0) {
convexPolygons.splice(i, 1);
this.polygonPool.free(polygon);
}
}
return convexPolygons;
};
ConvexDecomposer.isConcave = function (index, vertexCount, vertices, indices) {
var previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
var current = indices[index] << 1;
var next = indices[(index + 1) % vertexCount] << 1;
return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]);
};
ConvexDecomposer.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) {
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
};
ConvexDecomposer.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) {
var px = p2x - p1x, py = p2y - p1y;
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
};
return ConvexDecomposer;
}());
spine.ConvexDecomposer = ConvexDecomposer;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var Event = (function () { var Event = (function () {
function Event(time, data) { function Event(time, data) {
@ -3945,6 +4161,285 @@ var spine;
spine.SkeletonBounds = SkeletonBounds; spine.SkeletonBounds = SkeletonBounds;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var SkeletonClipping = (function () {
function SkeletonClipping() {
this.decomposer = new spine.ConvexDecomposer();
this.clippingPolygon = new Array();
this.clipOutput = new Array();
this.clippedVertices = new Array();
this.clippedTriangles = new Array();
this.scratch = new Array();
}
SkeletonClipping.prototype.clipStart = function (slot, clip) {
if (this.clipAttachment != null)
return;
this.clipAttachment = clip;
var n = clip.worldVerticesLength;
var vertices = spine.Utils.setArraySize(this.clippingPolygon, n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.decomposer.decompose(clippingPolygon);
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
polygon.push(polygon[1]);
}
};
SkeletonClipping.prototype.clipEndWithSlot = function (slot) {
if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data)
this.clipEnd();
};
SkeletonClipping.prototype.clipEnd = function () {
if (this.clipAttachment == null)
return;
this.clipAttachment = null;
this.clippingPolygons = null;
this.clippedVertices.length = 0;
this.clippedTriangles.length = 0;
this.clippingPolygon.length = 0;
};
SkeletonClipping.prototype.isClipping = function () {
return this.clipAttachment != null;
};
SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
var clippedTriangles = this.clippedTriangles;
var polygons = this.clippingPolygons;
var polygonsCount = this.clippingPolygons.length;
var vertexSize = twoColor ? 12 : 8;
var index = 0;
clippedVertices.length = 0;
clippedTriangles.length = 0;
outer: for (var i = 0; i < trianglesLength; i += 3) {
var vertexOffset = triangles[i] << 1;
var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 1] << 1;
var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 2] << 1;
var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
for (var p = 0; p < polygonsCount; p++) {
var s = clippedVertices.length;
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
var clipOutputLength = clipOutput.length;
if (clipOutputLength == 0)
continue;
var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
var d = 1 / (d0 * d2 + d1 * (y1 - y3));
var clipOutputCount = clipOutputLength >> 1;
var clipOutputItems = this.clipOutput;
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
for (var ii = 0; ii < clipOutputLength; ii += 2) {
var x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
var c0 = x - x3, c1 = y - y3;
var a = (d0 * c0 + d1 * c1) * d;
var b = (d4 * c0 + d2 * c1) * d;
var c = 1 - a - b;
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
if (twoColor) {
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 8] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
}
s += vertexSize;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (var ii = 1; ii < clipOutputCount; ii++) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + ii);
clippedTrianglesItems[s + 2] = (index + ii + 1);
s += 3;
}
index += clipOutputCount + 1;
}
else {
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
clippedVerticesItems[s] = x1;
clippedVerticesItems[s + 1] = y1;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
if (!twoColor) {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = x2;
clippedVerticesItems[s + 9] = y2;
clippedVerticesItems[s + 10] = light.r;
clippedVerticesItems[s + 11] = light.g;
clippedVerticesItems[s + 12] = light.b;
clippedVerticesItems[s + 13] = light.a;
clippedVerticesItems[s + 14] = u2;
clippedVerticesItems[s + 15] = v2;
clippedVerticesItems[s + 16] = x3;
clippedVerticesItems[s + 17] = y3;
clippedVerticesItems[s + 18] = light.r;
clippedVerticesItems[s + 19] = light.g;
clippedVerticesItems[s + 20] = light.b;
clippedVerticesItems[s + 21] = light.a;
clippedVerticesItems[s + 22] = u3;
clippedVerticesItems[s + 23] = v3;
}
else {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
clippedVerticesItems[s + 12] = x2;
clippedVerticesItems[s + 13] = y2;
clippedVerticesItems[s + 14] = light.r;
clippedVerticesItems[s + 15] = light.g;
clippedVerticesItems[s + 16] = light.b;
clippedVerticesItems[s + 17] = light.a;
clippedVerticesItems[s + 18] = u2;
clippedVerticesItems[s + 19] = v2;
clippedVerticesItems[s + 20] = dark.r;
clippedVerticesItems[s + 21] = dark.g;
clippedVerticesItems[s + 22] = dark.b;
clippedVerticesItems[s + 23] = dark.a;
clippedVerticesItems[s + 24] = x3;
clippedVerticesItems[s + 25] = y3;
clippedVerticesItems[s + 26] = light.r;
clippedVerticesItems[s + 27] = light.g;
clippedVerticesItems[s + 28] = light.b;
clippedVerticesItems[s + 29] = light.a;
clippedVerticesItems[s + 30] = u3;
clippedVerticesItems[s + 31] = v3;
clippedVerticesItems[s + 32] = dark.r;
clippedVerticesItems[s + 33] = dark.g;
clippedVerticesItems[s + 34] = dark.b;
clippedVerticesItems[s + 35] = dark.a;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3);
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + 1);
clippedTrianglesItems[s + 2] = (index + 2);
index += 3;
continue outer;
}
}
}
};
SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) {
var originalOutput = output;
var clipped = false;
var input = null;
if (clippingArea.length % 4 >= 2) {
input = output;
output = this.scratch;
}
else
input = this.scratch;
input.length = 0;
input.push(x1);
input.push(y1);
input.push(x2);
input.push(y2);
input.push(x3);
input.push(y3);
input.push(x1);
input.push(y1);
output.length = 0;
var clippingVertices = clippingArea;
var clippingVerticesLast = clippingArea.length - 4;
for (var i = 0;; i += 2) {
var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
var inputVertices = input;
var inputVerticesLength = input.length - 2, outputStart = output.length;
for (var ii = 0; ii < inputVerticesLength; ii += 2) {
var inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
if (side2) {
output.push(inputX2);
output.push(inputY2);
continue;
}
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
}
else if (side2) {
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
output.push(inputX2);
output.push(inputY2);
}
clipped = true;
}
if (outputStart == output.length) {
originalOutput.length = 0;
return true;
}
output.push(output[0]);
output.push(output[1]);
if (i == clippingVerticesLast)
break;
var temp = output;
output = input;
output.length = 0;
input = temp;
}
if (originalOutput != output) {
originalOutput.length = 0;
for (var i = 0, n = output.length - 2; i < n; i++)
originalOutput[i] = output[i];
}
else
originalOutput.length = originalOutput.length - 2;
return clipped;
};
SkeletonClipping.makeClockwise = function (polygon) {
var vertices = polygon;
var verticeslength = polygon.length;
var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
for (var i = 0, n = verticeslength - 3; i < n; i += 2) {
p1x = vertices[i];
p1y = vertices[i + 1];
p2x = vertices[i + 2];
p2y = vertices[i + 3];
area += p1x * p2y - p2x * p1y;
}
if (area < 0)
return;
for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
var x = vertices[i], y = vertices[i + 1];
var other = lastX - i;
vertices[i] = vertices[other];
vertices[i + 1] = vertices[other + 1];
vertices[other] = x;
vertices[other + 1] = y;
}
};
return SkeletonClipping;
}());
spine.SkeletonClipping = SkeletonClipping;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var SkeletonData = (function () { var SkeletonData = (function () {
function SkeletonData() { function SkeletonData() {
@ -4236,7 +4731,7 @@ var spine;
throw new Error("Slot not found: " + slotName); throw new Error("Slot not found: " + slotName);
var slotMap = skinMap[slotName]; var slotMap = skinMap[slotName];
for (var entryName in slotMap) { for (var entryName in slotMap) {
var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData);
if (attachment != null) if (attachment != null)
skin.addAttachment(slotIndex, entryName, attachment); skin.addAttachment(slotIndex, entryName, attachment);
} }
@ -4276,7 +4771,7 @@ var spine;
} }
return skeletonData; return skeletonData;
}; };
SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) {
var scale = this.scale; var scale = this.scale;
name = this.getValue(map, "name", name); name = this.getValue(map, "name", name);
var type = this.getValue(map, "type", "region"); var type = this.getValue(map, "type", "region");
@ -4363,6 +4858,24 @@ var spine;
point.color.setFromString(color); point.color.setFromString(color);
return point; return point;
} }
case "clipping": {
var clip = this.attachmentLoader.newClippingAttachment(skin, name);
if (clip == null)
return null;
var end = this.getValue(map, "end", null);
if (end != null) {
var slot = skeletonData.findSlot(end);
if (slot == null)
throw new Error("Clipping end slot not found: " + end);
clip.endSlot = slot;
}
var vertexCount = map.vertexCount;
this.readVertices(map, clip, vertexCount << 1);
var color = this.getValue(map, "color", null);
if (color != null)
clip.color.setFromString(color);
return clip;
}
} }
return null; return null;
}; };
@ -5543,6 +6056,17 @@ var spine;
return array; return array;
} }
}; };
Utils.newShortArray = function (size) {
if (Utils.SUPPORTS_TYPED_ARRAYS) {
return new Int16Array(size);
}
else {
var array = new Array(size);
for (var i = 0; i < array.length; i++)
array[i] = 0;
return array;
}
};
Utils.toFloatArray = function (array) { Utils.toFloatArray = function (array) {
return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
}; };

File diff suppressed because one or more lines are too long

View File

@ -383,6 +383,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -406,6 +407,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -424,6 +426,13 @@ declare module spine {
constructor(name: string); constructor(name: string);
} }
} }
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine { declare module spine {
class MeshAttachment extends VertexAttachment { class MeshAttachment extends VertexAttachment {
region: TextureRegion; region: TextureRegion;
@ -607,6 +616,21 @@ declare module spine {
getOrder(): number; getOrder(): number;
} }
} }
declare module spine {
class ConvexDecomposer {
private convexPolygons;
private convexPolygonsIndices;
private indicesArray;
private isConcaveArray;
private triangles;
private polygonPool;
private polygonIndicesPool;
decompose(input: ArrayLike<number>): Array<Array<number>>;
private static isConcave(index, vertexCount, vertices, indices);
private static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y);
private static winding(p1x, p1y, p2x, p2y, p3x, p3y);
}
}
declare module spine { declare module spine {
class Event { class Event {
data: EventData; data: EventData;
@ -802,6 +826,25 @@ declare module spine {
getHeight(): number; getHeight(): number;
} }
} }
declare module spine {
class SkeletonClipping {
private decomposer;
private clippingPolygon;
private clipOutput;
clippedVertices: number[];
clippedTriangles: number[];
private scratch;
private clipAttachment;
private clippingPolygons;
clipStart(slot: Slot, clip: ClippingAttachment): void;
clipEndWithSlot(slot: Slot): void;
clipEnd(): void;
isClipping(): boolean;
clipTriangles(vertices: ArrayLike<number>, verticesLength: number, triangles: ArrayLike<number>, trianglesLength: number, uvs: ArrayLike<number>, light: Color, dark: Color, twoColor: boolean): void;
clip(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array<number>, output: Array<number>): boolean;
static makeClockwise(polygon: ArrayLike<number>): void;
}
}
declare module spine { declare module spine {
class SkeletonData { class SkeletonData {
name: string; name: string;
@ -840,7 +883,7 @@ declare module spine {
private linkedMeshes; private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader); constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(json: string | any): SkeletonData; readSkeletonData(json: string | any): SkeletonData;
readAttachment(map: any, skin: Skin, slotIndex: number, name: string): Attachment; readAttachment(map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment;
readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void; readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void;
readAnimation(map: any, name: string, skeletonData: SkeletonData): void; readAnimation(map: any, name: string, skeletonData: SkeletonData): void;
readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void; readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void;
@ -1058,6 +1101,7 @@ declare module spine {
static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>; static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>;
static newArray<T>(size: number, defaultValue: T): Array<T>; static newArray<T>(size: number, defaultValue: T): Array<T>;
static newFloatArray(size: number): ArrayLike<number>; static newFloatArray(size: number): ArrayLike<number>;
static newShortArray(size: number): ArrayLike<number>;
static toFloatArray(array: Array<number>): number[] | Float32Array; static toFloatArray(array: Array<number>): number[] | Float32Array;
} }
class DebugUtils { class DebugUtils {

View File

@ -1922,6 +1922,9 @@ var spine;
AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) {
return new spine.PointAttachment(name); return new spine.PointAttachment(name);
}; };
AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) {
return new spine.ClippingAttachment(name);
};
return AtlasAttachmentLoader; return AtlasAttachmentLoader;
}()); }());
spine.AtlasAttachmentLoader = AtlasAttachmentLoader; spine.AtlasAttachmentLoader = AtlasAttachmentLoader;
@ -2034,6 +2037,18 @@ var spine;
spine.BoundingBoxAttachment = BoundingBoxAttachment; spine.BoundingBoxAttachment = BoundingBoxAttachment;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ClippingAttachment = (function (_super) {
__extends(ClippingAttachment, _super);
function ClippingAttachment(name) {
_super.call(this, name);
this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1);
}
return ClippingAttachment;
}(spine.VertexAttachment));
spine.ClippingAttachment = ClippingAttachment;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var MeshAttachment = (function (_super) { var MeshAttachment = (function (_super) {
__extends(MeshAttachment, _super); __extends(MeshAttachment, _super);
@ -2577,6 +2592,207 @@ var spine;
var TransformMode = spine.TransformMode; var TransformMode = spine.TransformMode;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ConvexDecomposer = (function () {
function ConvexDecomposer() {
this.convexPolygons = new Array();
this.convexPolygonsIndices = new Array();
this.indicesArray = new Array();
this.isConcaveArray = new Array();
this.triangles = new Array();
this.polygonPool = new spine.Pool(function () {
return new Array();
});
this.polygonIndicesPool = new spine.Pool(function () {
return new Array();
});
}
ConvexDecomposer.prototype.decompose = function (input) {
var vertices = input;
var vertexCount = input.length >> 1;
var indices = this.indicesArray;
indices.length = 0;
for (var i = 0; i < vertexCount; i++)
indices[i] = i;
var isConcave = this.isConcaveArray;
isConcave.length = 0;
for (var i = 0, n = vertexCount; i < n; ++i)
isConcave[i] = ConvexDecomposer.isConcave(i, vertexCount, vertices, indices);
var triangles = this.triangles;
triangles.length = 0;
while (vertexCount > 3) {
var previous = vertexCount - 1, i = 0, next = 1;
while (true) {
outer: if (!isConcave[i]) {
var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
var p1x = vertices[p1], p1y = vertices[p1 + 1];
var p2x = vertices[p2], p2y = vertices[p2 + 1];
var p3x = vertices[p3], p3y = vertices[p3 + 1];
for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
if (!isConcave[ii])
continue;
var v = indices[ii] << 1;
var vx = vertices[v], vy = vertices[v + 1];
if (ConvexDecomposer.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
break outer;
}
}
}
break;
}
if (next == 0) {
do {
if (!isConcave[i])
break;
i--;
} while (i > 0);
break;
}
previous = i;
i = next;
next = (next + 1) % vertexCount;
}
triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
triangles.push(indices[i]);
triangles.push(indices[(i + 1) % vertexCount]);
indices.splice(i, 1);
isConcave.splice(i, 1);
vertexCount--;
var previousIndex = (vertexCount + i - 1) % vertexCount;
var nextIndex = i == vertexCount ? 0 : i;
isConcave[previousIndex] = ConvexDecomposer.isConcave(previousIndex, vertexCount, vertices, indices);
isConcave[nextIndex] = ConvexDecomposer.isConcave(nextIndex, vertexCount, vertices, indices);
}
if (vertexCount == 3) {
triangles.push(indices[2]);
triangles.push(indices[0]);
triangles.push(indices[1]);
}
var convexPolygons = this.convexPolygons;
this.polygonPool.freeAll(convexPolygons);
convexPolygons.length = 0;
var convexPolygonsIndices = this.convexPolygonsIndices;
this.polygonIndicesPool.freeAll(convexPolygonsIndices);
convexPolygonsIndices.length = 0;
var polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
var polygon = this.polygonPool.obtain();
polygon.length = 0;
var fanBaseIndex = -1, lastWinding = 0;
for (var i = 0, n = triangles.length; i < n; i += 3) {
var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
var x1 = vertices[t1], y1 = vertices[t1 + 1];
var x2 = vertices[t2], y2 = vertices[t2 + 1];
var x3 = vertices[t3], y3 = vertices[t3 + 1];
var merged = false;
if (fanBaseIndex == t1) {
var o = polygon.length - 4;
var winding1 = ConvexDecomposer.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
if (winding1 == lastWinding && winding2 == lastWinding) {
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(t3);
merged = true;
}
}
if (!merged) {
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
polygon = this.polygonPool.obtain();
polygon.length = 0;
polygon.push(x1);
polygon.push(y1);
polygon.push(x2);
polygon.push(y2);
polygon.push(x3);
polygon.push(y3);
polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
polygonIndices.push(t1);
polygonIndices.push(t2);
polygonIndices.push(t3);
lastWinding = ConvexDecomposer.winding(x1, y1, x2, y2, x3, y3);
fanBaseIndex = t1;
}
}
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
for (var i = 0, n = convexPolygons.length; i < n; i++) {
polygonIndices = convexPolygonsIndices[i];
if (polygonIndices.length == 0)
continue;
var firstIndex = polygonIndices[0];
var lastIndex = polygonIndices[polygonIndices.length - 1];
polygon = convexPolygons[i];
var o = polygon.length - 4;
var prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
var prevX = polygon[o + 2], prevY = polygon[o + 3];
var firstX = polygon[0], firstY = polygon[1];
var secondX = polygon[2], secondY = polygon[3];
var winding = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
for (var ii = 0; ii < n; ii++) {
if (ii == i)
continue;
var otherIndices = convexPolygonsIndices[ii];
if (otherIndices.length != 3)
continue;
var otherFirstIndex = otherIndices[0];
var otherSecondIndex = otherIndices[1];
var otherLastIndex = otherIndices[2];
var otherPoly = convexPolygons[ii];
var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
continue;
var winding1 = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, firstX, firstY, secondX, secondY);
if (winding1 == winding && winding2 == winding) {
otherPoly.length = 0;
otherIndices.length = 0;
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(otherLastIndex);
prevPrevX = prevX;
prevPrevY = prevY;
prevX = x3;
prevY = y3;
ii = 0;
}
}
}
for (var i = convexPolygons.length - 1; i >= 0; i--) {
polygon = convexPolygons[i];
if (polygon.length == 0) {
convexPolygons.splice(i, 1);
this.polygonPool.free(polygon);
}
}
return convexPolygons;
};
ConvexDecomposer.isConcave = function (index, vertexCount, vertices, indices) {
var previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
var current = indices[index] << 1;
var next = indices[(index + 1) % vertexCount] << 1;
return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]);
};
ConvexDecomposer.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) {
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
};
ConvexDecomposer.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) {
var px = p2x - p1x, py = p2y - p1y;
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
};
return ConvexDecomposer;
}());
spine.ConvexDecomposer = ConvexDecomposer;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var Event = (function () { var Event = (function () {
function Event(time, data) { function Event(time, data) {
@ -3945,6 +4161,285 @@ var spine;
spine.SkeletonBounds = SkeletonBounds; spine.SkeletonBounds = SkeletonBounds;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var SkeletonClipping = (function () {
function SkeletonClipping() {
this.decomposer = new spine.ConvexDecomposer();
this.clippingPolygon = new Array();
this.clipOutput = new Array();
this.clippedVertices = new Array();
this.clippedTriangles = new Array();
this.scratch = new Array();
}
SkeletonClipping.prototype.clipStart = function (slot, clip) {
if (this.clipAttachment != null)
return;
this.clipAttachment = clip;
var n = clip.worldVerticesLength;
var vertices = spine.Utils.setArraySize(this.clippingPolygon, n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.decomposer.decompose(clippingPolygon);
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
polygon.push(polygon[1]);
}
};
SkeletonClipping.prototype.clipEndWithSlot = function (slot) {
if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data)
this.clipEnd();
};
SkeletonClipping.prototype.clipEnd = function () {
if (this.clipAttachment == null)
return;
this.clipAttachment = null;
this.clippingPolygons = null;
this.clippedVertices.length = 0;
this.clippedTriangles.length = 0;
this.clippingPolygon.length = 0;
};
SkeletonClipping.prototype.isClipping = function () {
return this.clipAttachment != null;
};
SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
var clippedTriangles = this.clippedTriangles;
var polygons = this.clippingPolygons;
var polygonsCount = this.clippingPolygons.length;
var vertexSize = twoColor ? 12 : 8;
var index = 0;
clippedVertices.length = 0;
clippedTriangles.length = 0;
outer: for (var i = 0; i < trianglesLength; i += 3) {
var vertexOffset = triangles[i] << 1;
var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 1] << 1;
var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 2] << 1;
var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
for (var p = 0; p < polygonsCount; p++) {
var s = clippedVertices.length;
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
var clipOutputLength = clipOutput.length;
if (clipOutputLength == 0)
continue;
var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
var d = 1 / (d0 * d2 + d1 * (y1 - y3));
var clipOutputCount = clipOutputLength >> 1;
var clipOutputItems = this.clipOutput;
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
for (var ii = 0; ii < clipOutputLength; ii += 2) {
var x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
var c0 = x - x3, c1 = y - y3;
var a = (d0 * c0 + d1 * c1) * d;
var b = (d4 * c0 + d2 * c1) * d;
var c = 1 - a - b;
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
if (twoColor) {
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 8] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
}
s += vertexSize;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (var ii = 1; ii < clipOutputCount; ii++) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + ii);
clippedTrianglesItems[s + 2] = (index + ii + 1);
s += 3;
}
index += clipOutputCount + 1;
}
else {
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
clippedVerticesItems[s] = x1;
clippedVerticesItems[s + 1] = y1;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
if (!twoColor) {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = x2;
clippedVerticesItems[s + 9] = y2;
clippedVerticesItems[s + 10] = light.r;
clippedVerticesItems[s + 11] = light.g;
clippedVerticesItems[s + 12] = light.b;
clippedVerticesItems[s + 13] = light.a;
clippedVerticesItems[s + 14] = u2;
clippedVerticesItems[s + 15] = v2;
clippedVerticesItems[s + 16] = x3;
clippedVerticesItems[s + 17] = y3;
clippedVerticesItems[s + 18] = light.r;
clippedVerticesItems[s + 19] = light.g;
clippedVerticesItems[s + 20] = light.b;
clippedVerticesItems[s + 21] = light.a;
clippedVerticesItems[s + 22] = u3;
clippedVerticesItems[s + 23] = v3;
}
else {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
clippedVerticesItems[s + 12] = x2;
clippedVerticesItems[s + 13] = y2;
clippedVerticesItems[s + 14] = light.r;
clippedVerticesItems[s + 15] = light.g;
clippedVerticesItems[s + 16] = light.b;
clippedVerticesItems[s + 17] = light.a;
clippedVerticesItems[s + 18] = u2;
clippedVerticesItems[s + 19] = v2;
clippedVerticesItems[s + 20] = dark.r;
clippedVerticesItems[s + 21] = dark.g;
clippedVerticesItems[s + 22] = dark.b;
clippedVerticesItems[s + 23] = dark.a;
clippedVerticesItems[s + 24] = x3;
clippedVerticesItems[s + 25] = y3;
clippedVerticesItems[s + 26] = light.r;
clippedVerticesItems[s + 27] = light.g;
clippedVerticesItems[s + 28] = light.b;
clippedVerticesItems[s + 29] = light.a;
clippedVerticesItems[s + 30] = u3;
clippedVerticesItems[s + 31] = v3;
clippedVerticesItems[s + 32] = dark.r;
clippedVerticesItems[s + 33] = dark.g;
clippedVerticesItems[s + 34] = dark.b;
clippedVerticesItems[s + 35] = dark.a;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3);
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + 1);
clippedTrianglesItems[s + 2] = (index + 2);
index += 3;
continue outer;
}
}
}
};
SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) {
var originalOutput = output;
var clipped = false;
var input = null;
if (clippingArea.length % 4 >= 2) {
input = output;
output = this.scratch;
}
else
input = this.scratch;
input.length = 0;
input.push(x1);
input.push(y1);
input.push(x2);
input.push(y2);
input.push(x3);
input.push(y3);
input.push(x1);
input.push(y1);
output.length = 0;
var clippingVertices = clippingArea;
var clippingVerticesLast = clippingArea.length - 4;
for (var i = 0;; i += 2) {
var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
var inputVertices = input;
var inputVerticesLength = input.length - 2, outputStart = output.length;
for (var ii = 0; ii < inputVerticesLength; ii += 2) {
var inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
if (side2) {
output.push(inputX2);
output.push(inputY2);
continue;
}
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
}
else if (side2) {
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
output.push(inputX2);
output.push(inputY2);
}
clipped = true;
}
if (outputStart == output.length) {
originalOutput.length = 0;
return true;
}
output.push(output[0]);
output.push(output[1]);
if (i == clippingVerticesLast)
break;
var temp = output;
output = input;
output.length = 0;
input = temp;
}
if (originalOutput != output) {
originalOutput.length = 0;
for (var i = 0, n = output.length - 2; i < n; i++)
originalOutput[i] = output[i];
}
else
originalOutput.length = originalOutput.length - 2;
return clipped;
};
SkeletonClipping.makeClockwise = function (polygon) {
var vertices = polygon;
var verticeslength = polygon.length;
var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
for (var i = 0, n = verticeslength - 3; i < n; i += 2) {
p1x = vertices[i];
p1y = vertices[i + 1];
p2x = vertices[i + 2];
p2y = vertices[i + 3];
area += p1x * p2y - p2x * p1y;
}
if (area < 0)
return;
for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
var x = vertices[i], y = vertices[i + 1];
var other = lastX - i;
vertices[i] = vertices[other];
vertices[i + 1] = vertices[other + 1];
vertices[other] = x;
vertices[other + 1] = y;
}
};
return SkeletonClipping;
}());
spine.SkeletonClipping = SkeletonClipping;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var SkeletonData = (function () { var SkeletonData = (function () {
function SkeletonData() { function SkeletonData() {
@ -4236,7 +4731,7 @@ var spine;
throw new Error("Slot not found: " + slotName); throw new Error("Slot not found: " + slotName);
var slotMap = skinMap[slotName]; var slotMap = skinMap[slotName];
for (var entryName in slotMap) { for (var entryName in slotMap) {
var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData);
if (attachment != null) if (attachment != null)
skin.addAttachment(slotIndex, entryName, attachment); skin.addAttachment(slotIndex, entryName, attachment);
} }
@ -4276,7 +4771,7 @@ var spine;
} }
return skeletonData; return skeletonData;
}; };
SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) {
var scale = this.scale; var scale = this.scale;
name = this.getValue(map, "name", name); name = this.getValue(map, "name", name);
var type = this.getValue(map, "type", "region"); var type = this.getValue(map, "type", "region");
@ -4363,6 +4858,24 @@ var spine;
point.color.setFromString(color); point.color.setFromString(color);
return point; return point;
} }
case "clipping": {
var clip = this.attachmentLoader.newClippingAttachment(skin, name);
if (clip == null)
return null;
var end = this.getValue(map, "end", null);
if (end != null) {
var slot = skeletonData.findSlot(end);
if (slot == null)
throw new Error("Clipping end slot not found: " + end);
clip.endSlot = slot;
}
var vertexCount = map.vertexCount;
this.readVertices(map, clip, vertexCount << 1);
var color = this.getValue(map, "color", null);
if (color != null)
clip.color.setFromString(color);
return clip;
}
} }
return null; return null;
}; };
@ -5543,6 +6056,17 @@ var spine;
return array; return array;
} }
}; };
Utils.newShortArray = function (size) {
if (Utils.SUPPORTS_TYPED_ARRAYS) {
return new Int16Array(size);
}
else {
var array = new Array(size);
for (var i = 0; i < array.length; i++)
array[i] = 0;
return array;
}
};
Utils.toFloatArray = function (array) { Utils.toFloatArray = function (array) {
return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
}; };

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -383,6 +383,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -406,6 +407,7 @@ declare module spine {
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment; newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment; newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment; newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
} }
} }
declare module spine { declare module spine {
@ -424,6 +426,13 @@ declare module spine {
constructor(name: string); constructor(name: string);
} }
} }
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine { declare module spine {
class MeshAttachment extends VertexAttachment { class MeshAttachment extends VertexAttachment {
region: TextureRegion; region: TextureRegion;
@ -607,6 +616,21 @@ declare module spine {
getOrder(): number; getOrder(): number;
} }
} }
declare module spine {
class ConvexDecomposer {
private convexPolygons;
private convexPolygonsIndices;
private indicesArray;
private isConcaveArray;
private triangles;
private polygonPool;
private polygonIndicesPool;
decompose(input: ArrayLike<number>): Array<Array<number>>;
private static isConcave(index, vertexCount, vertices, indices);
private static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y);
private static winding(p1x, p1y, p2x, p2y, p3x, p3y);
}
}
declare module spine { declare module spine {
class Event { class Event {
data: EventData; data: EventData;
@ -802,6 +826,25 @@ declare module spine {
getHeight(): number; getHeight(): number;
} }
} }
declare module spine {
class SkeletonClipping {
private decomposer;
private clippingPolygon;
private clipOutput;
clippedVertices: number[];
clippedTriangles: number[];
private scratch;
private clipAttachment;
private clippingPolygons;
clipStart(slot: Slot, clip: ClippingAttachment): void;
clipEndWithSlot(slot: Slot): void;
clipEnd(): void;
isClipping(): boolean;
clipTriangles(vertices: ArrayLike<number>, verticesLength: number, triangles: ArrayLike<number>, trianglesLength: number, uvs: ArrayLike<number>, light: Color, dark: Color, twoColor: boolean): void;
clip(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array<number>, output: Array<number>): boolean;
static makeClockwise(polygon: ArrayLike<number>): void;
}
}
declare module spine { declare module spine {
class SkeletonData { class SkeletonData {
name: string; name: string;
@ -840,7 +883,7 @@ declare module spine {
private linkedMeshes; private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader); constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(json: string | any): SkeletonData; readSkeletonData(json: string | any): SkeletonData;
readAttachment(map: any, skin: Skin, slotIndex: number, name: string): Attachment; readAttachment(map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment;
readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void; readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void;
readAnimation(map: any, name: string, skeletonData: SkeletonData): void; readAnimation(map: any, name: string, skeletonData: SkeletonData): void;
readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void; readCurve(map: any, timeline: CurveTimeline, frameIndex: number): void;
@ -1058,6 +1101,7 @@ declare module spine {
static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>; static ensureArrayCapacity<T>(array: Array<T>, size: number, value?: any): Array<T>;
static newArray<T>(size: number, defaultValue: T): Array<T>; static newArray<T>(size: number, defaultValue: T): Array<T>;
static newFloatArray(size: number): ArrayLike<number>; static newFloatArray(size: number): ArrayLike<number>;
static newShortArray(size: number): ArrayLike<number>;
static toFloatArray(array: Array<number>): number[] | Float32Array; static toFloatArray(array: Array<number>): number[] | Float32Array;
} }
class DebugUtils { class DebugUtils {
@ -1445,6 +1489,7 @@ declare module spine.webgl {
attachmentLineColor: Color; attachmentLineColor: Color;
triangleLineColor: Color; triangleLineColor: Color;
pathColor: Color; pathColor: Color;
clipColor: Color;
aabbColor: Color; aabbColor: Color;
drawBones: boolean; drawBones: boolean;
drawRegionAttachments: boolean; drawRegionAttachments: boolean;
@ -1453,6 +1498,7 @@ declare module spine.webgl {
drawMeshTriangles: boolean; drawMeshTriangles: boolean;
drawPaths: boolean; drawPaths: boolean;
drawSkeletonXY: boolean; drawSkeletonXY: boolean;
drawClipping: boolean;
premultipliedAlpha: boolean; premultipliedAlpha: boolean;
scale: number; scale: number;
boneWidth: number; boneWidth: number;
@ -1478,10 +1524,9 @@ declare module spine.webgl {
private vertexSize; private vertexSize;
private twoColorTint; private twoColorTint;
private renderable; private renderable;
private clipper;
constructor(gl: WebGLRenderingContext, twoColorTint?: boolean); constructor(gl: WebGLRenderingContext, twoColorTint?: boolean);
draw(batcher: PolygonBatcher, skeleton: Skeleton): void; draw(batcher: PolygonBatcher, skeleton: Skeleton): void;
private computeRegionVertices(slot, region, pma, twoColorTint?);
private computeMeshVertices(slot, mesh, pma, twoColorTint?);
} }
} }
declare module spine.webgl { declare module spine.webgl {

View File

@ -1922,6 +1922,9 @@ var spine;
AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) {
return new spine.PointAttachment(name); return new spine.PointAttachment(name);
}; };
AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) {
return new spine.ClippingAttachment(name);
};
return AtlasAttachmentLoader; return AtlasAttachmentLoader;
}()); }());
spine.AtlasAttachmentLoader = AtlasAttachmentLoader; spine.AtlasAttachmentLoader = AtlasAttachmentLoader;
@ -2034,6 +2037,18 @@ var spine;
spine.BoundingBoxAttachment = BoundingBoxAttachment; spine.BoundingBoxAttachment = BoundingBoxAttachment;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ClippingAttachment = (function (_super) {
__extends(ClippingAttachment, _super);
function ClippingAttachment(name) {
_super.call(this, name);
this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1);
}
return ClippingAttachment;
}(spine.VertexAttachment));
spine.ClippingAttachment = ClippingAttachment;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var MeshAttachment = (function (_super) { var MeshAttachment = (function (_super) {
__extends(MeshAttachment, _super); __extends(MeshAttachment, _super);
@ -2577,6 +2592,207 @@ var spine;
var TransformMode = spine.TransformMode; var TransformMode = spine.TransformMode;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var ConvexDecomposer = (function () {
function ConvexDecomposer() {
this.convexPolygons = new Array();
this.convexPolygonsIndices = new Array();
this.indicesArray = new Array();
this.isConcaveArray = new Array();
this.triangles = new Array();
this.polygonPool = new spine.Pool(function () {
return new Array();
});
this.polygonIndicesPool = new spine.Pool(function () {
return new Array();
});
}
ConvexDecomposer.prototype.decompose = function (input) {
var vertices = input;
var vertexCount = input.length >> 1;
var indices = this.indicesArray;
indices.length = 0;
for (var i = 0; i < vertexCount; i++)
indices[i] = i;
var isConcave = this.isConcaveArray;
isConcave.length = 0;
for (var i = 0, n = vertexCount; i < n; ++i)
isConcave[i] = ConvexDecomposer.isConcave(i, vertexCount, vertices, indices);
var triangles = this.triangles;
triangles.length = 0;
while (vertexCount > 3) {
var previous = vertexCount - 1, i = 0, next = 1;
while (true) {
outer: if (!isConcave[i]) {
var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
var p1x = vertices[p1], p1y = vertices[p1 + 1];
var p2x = vertices[p2], p2y = vertices[p2 + 1];
var p3x = vertices[p3], p3y = vertices[p3 + 1];
for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
if (!isConcave[ii])
continue;
var v = indices[ii] << 1;
var vx = vertices[v], vy = vertices[v + 1];
if (ConvexDecomposer.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (ConvexDecomposer.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
break outer;
}
}
}
break;
}
if (next == 0) {
do {
if (!isConcave[i])
break;
i--;
} while (i > 0);
break;
}
previous = i;
i = next;
next = (next + 1) % vertexCount;
}
triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
triangles.push(indices[i]);
triangles.push(indices[(i + 1) % vertexCount]);
indices.splice(i, 1);
isConcave.splice(i, 1);
vertexCount--;
var previousIndex = (vertexCount + i - 1) % vertexCount;
var nextIndex = i == vertexCount ? 0 : i;
isConcave[previousIndex] = ConvexDecomposer.isConcave(previousIndex, vertexCount, vertices, indices);
isConcave[nextIndex] = ConvexDecomposer.isConcave(nextIndex, vertexCount, vertices, indices);
}
if (vertexCount == 3) {
triangles.push(indices[2]);
triangles.push(indices[0]);
triangles.push(indices[1]);
}
var convexPolygons = this.convexPolygons;
this.polygonPool.freeAll(convexPolygons);
convexPolygons.length = 0;
var convexPolygonsIndices = this.convexPolygonsIndices;
this.polygonIndicesPool.freeAll(convexPolygonsIndices);
convexPolygonsIndices.length = 0;
var polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
var polygon = this.polygonPool.obtain();
polygon.length = 0;
var fanBaseIndex = -1, lastWinding = 0;
for (var i = 0, n = triangles.length; i < n; i += 3) {
var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
var x1 = vertices[t1], y1 = vertices[t1 + 1];
var x2 = vertices[t2], y2 = vertices[t2 + 1];
var x3 = vertices[t3], y3 = vertices[t3 + 1];
var merged = false;
if (fanBaseIndex == t1) {
var o = polygon.length - 4;
var winding1 = ConvexDecomposer.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
if (winding1 == lastWinding && winding2 == lastWinding) {
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(t3);
merged = true;
}
}
if (!merged) {
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
polygon = this.polygonPool.obtain();
polygon.length = 0;
polygon.push(x1);
polygon.push(y1);
polygon.push(x2);
polygon.push(y2);
polygon.push(x3);
polygon.push(y3);
polygonIndices = this.polygonIndicesPool.obtain();
polygonIndices.length = 0;
polygonIndices.push(t1);
polygonIndices.push(t2);
polygonIndices.push(t3);
lastWinding = ConvexDecomposer.winding(x1, y1, x2, y2, x3, y3);
fanBaseIndex = t1;
}
}
if (polygon.length > 0) {
convexPolygons.push(polygon);
convexPolygonsIndices.push(polygonIndices);
}
for (var i = 0, n = convexPolygons.length; i < n; i++) {
polygonIndices = convexPolygonsIndices[i];
if (polygonIndices.length == 0)
continue;
var firstIndex = polygonIndices[0];
var lastIndex = polygonIndices[polygonIndices.length - 1];
polygon = convexPolygons[i];
var o = polygon.length - 4;
var prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
var prevX = polygon[o + 2], prevY = polygon[o + 3];
var firstX = polygon[0], firstY = polygon[1];
var secondX = polygon[2], secondY = polygon[3];
var winding = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
for (var ii = 0; ii < n; ii++) {
if (ii == i)
continue;
var otherIndices = convexPolygonsIndices[ii];
if (otherIndices.length != 3)
continue;
var otherFirstIndex = otherIndices[0];
var otherSecondIndex = otherIndices[1];
var otherLastIndex = otherIndices[2];
var otherPoly = convexPolygons[ii];
var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
continue;
var winding1 = ConvexDecomposer.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
var winding2 = ConvexDecomposer.winding(x3, y3, firstX, firstY, secondX, secondY);
if (winding1 == winding && winding2 == winding) {
otherPoly.length = 0;
otherIndices.length = 0;
polygon.push(x3);
polygon.push(y3);
polygonIndices.push(otherLastIndex);
prevPrevX = prevX;
prevPrevY = prevY;
prevX = x3;
prevY = y3;
ii = 0;
}
}
}
for (var i = convexPolygons.length - 1; i >= 0; i--) {
polygon = convexPolygons[i];
if (polygon.length == 0) {
convexPolygons.splice(i, 1);
this.polygonPool.free(polygon);
}
}
return convexPolygons;
};
ConvexDecomposer.isConcave = function (index, vertexCount, vertices, indices) {
var previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
var current = indices[index] << 1;
var next = indices[(index + 1) % vertexCount] << 1;
return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]);
};
ConvexDecomposer.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) {
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
};
ConvexDecomposer.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) {
var px = p2x - p1x, py = p2y - p1y;
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
};
return ConvexDecomposer;
}());
spine.ConvexDecomposer = ConvexDecomposer;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var Event = (function () { var Event = (function () {
function Event(time, data) { function Event(time, data) {
@ -3945,6 +4161,285 @@ var spine;
spine.SkeletonBounds = SkeletonBounds; spine.SkeletonBounds = SkeletonBounds;
})(spine || (spine = {})); })(spine || (spine = {}));
var spine; var spine;
(function (spine) {
var SkeletonClipping = (function () {
function SkeletonClipping() {
this.decomposer = new spine.ConvexDecomposer();
this.clippingPolygon = new Array();
this.clipOutput = new Array();
this.clippedVertices = new Array();
this.clippedTriangles = new Array();
this.scratch = new Array();
}
SkeletonClipping.prototype.clipStart = function (slot, clip) {
if (this.clipAttachment != null)
return;
this.clipAttachment = clip;
var n = clip.worldVerticesLength;
var vertices = spine.Utils.setArraySize(this.clippingPolygon, n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
var clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
var clippingPolygons = this.clippingPolygons = this.decomposer.decompose(clippingPolygon);
for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
var polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
polygon.push(polygon[1]);
}
};
SkeletonClipping.prototype.clipEndWithSlot = function (slot) {
if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data)
this.clipEnd();
};
SkeletonClipping.prototype.clipEnd = function () {
if (this.clipAttachment == null)
return;
this.clipAttachment = null;
this.clippingPolygons = null;
this.clippedVertices.length = 0;
this.clippedTriangles.length = 0;
this.clippingPolygon.length = 0;
};
SkeletonClipping.prototype.isClipping = function () {
return this.clipAttachment != null;
};
SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
var clippedTriangles = this.clippedTriangles;
var polygons = this.clippingPolygons;
var polygonsCount = this.clippingPolygons.length;
var vertexSize = twoColor ? 12 : 8;
var index = 0;
clippedVertices.length = 0;
clippedTriangles.length = 0;
outer: for (var i = 0; i < trianglesLength; i += 3) {
var vertexOffset = triangles[i] << 1;
var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 1] << 1;
var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 2] << 1;
var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
for (var p = 0; p < polygonsCount; p++) {
var s = clippedVertices.length;
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
var clipOutputLength = clipOutput.length;
if (clipOutputLength == 0)
continue;
var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
var d = 1 / (d0 * d2 + d1 * (y1 - y3));
var clipOutputCount = clipOutputLength >> 1;
var clipOutputItems = this.clipOutput;
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
for (var ii = 0; ii < clipOutputLength; ii += 2) {
var x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
var c0 = x - x3, c1 = y - y3;
var a = (d0 * c0 + d1 * c1) * d;
var b = (d4 * c0 + d2 * c1) * d;
var c = 1 - a - b;
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
if (twoColor) {
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 8] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
}
s += vertexSize;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (var ii = 1; ii < clipOutputCount; ii++) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + ii);
clippedTrianglesItems[s + 2] = (index + ii + 1);
s += 3;
}
index += clipOutputCount + 1;
}
else {
var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
clippedVerticesItems[s] = x1;
clippedVerticesItems[s + 1] = y1;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
if (!twoColor) {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = x2;
clippedVerticesItems[s + 9] = y2;
clippedVerticesItems[s + 10] = light.r;
clippedVerticesItems[s + 11] = light.g;
clippedVerticesItems[s + 12] = light.b;
clippedVerticesItems[s + 13] = light.a;
clippedVerticesItems[s + 14] = u2;
clippedVerticesItems[s + 15] = v2;
clippedVerticesItems[s + 16] = x3;
clippedVerticesItems[s + 17] = y3;
clippedVerticesItems[s + 18] = light.r;
clippedVerticesItems[s + 19] = light.g;
clippedVerticesItems[s + 20] = light.b;
clippedVerticesItems[s + 21] = light.a;
clippedVerticesItems[s + 22] = u3;
clippedVerticesItems[s + 23] = v3;
}
else {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
clippedVerticesItems[s + 12] = x2;
clippedVerticesItems[s + 13] = y2;
clippedVerticesItems[s + 14] = light.r;
clippedVerticesItems[s + 15] = light.g;
clippedVerticesItems[s + 16] = light.b;
clippedVerticesItems[s + 17] = light.a;
clippedVerticesItems[s + 18] = u2;
clippedVerticesItems[s + 19] = v2;
clippedVerticesItems[s + 20] = dark.r;
clippedVerticesItems[s + 21] = dark.g;
clippedVerticesItems[s + 22] = dark.b;
clippedVerticesItems[s + 23] = dark.a;
clippedVerticesItems[s + 24] = x3;
clippedVerticesItems[s + 25] = y3;
clippedVerticesItems[s + 26] = light.r;
clippedVerticesItems[s + 27] = light.g;
clippedVerticesItems[s + 28] = light.b;
clippedVerticesItems[s + 29] = light.a;
clippedVerticesItems[s + 30] = u3;
clippedVerticesItems[s + 31] = v3;
clippedVerticesItems[s + 32] = dark.r;
clippedVerticesItems[s + 33] = dark.g;
clippedVerticesItems[s + 34] = dark.b;
clippedVerticesItems[s + 35] = dark.a;
}
s = clippedTriangles.length;
var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3);
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + 1);
clippedTrianglesItems[s + 2] = (index + 2);
index += 3;
continue outer;
}
}
}
};
SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) {
var originalOutput = output;
var clipped = false;
var input = null;
if (clippingArea.length % 4 >= 2) {
input = output;
output = this.scratch;
}
else
input = this.scratch;
input.length = 0;
input.push(x1);
input.push(y1);
input.push(x2);
input.push(y2);
input.push(x3);
input.push(y3);
input.push(x1);
input.push(y1);
output.length = 0;
var clippingVertices = clippingArea;
var clippingVerticesLast = clippingArea.length - 4;
for (var i = 0;; i += 2) {
var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
var inputVertices = input;
var inputVerticesLength = input.length - 2, outputStart = output.length;
for (var ii = 0; ii < inputVerticesLength; ii += 2) {
var inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
if (side2) {
output.push(inputX2);
output.push(inputY2);
continue;
}
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
}
else if (side2) {
var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
output.push(inputX2);
output.push(inputY2);
}
clipped = true;
}
if (outputStart == output.length) {
originalOutput.length = 0;
return true;
}
output.push(output[0]);
output.push(output[1]);
if (i == clippingVerticesLast)
break;
var temp = output;
output = input;
output.length = 0;
input = temp;
}
if (originalOutput != output) {
originalOutput.length = 0;
for (var i = 0, n = output.length - 2; i < n; i++)
originalOutput[i] = output[i];
}
else
originalOutput.length = originalOutput.length - 2;
return clipped;
};
SkeletonClipping.makeClockwise = function (polygon) {
var vertices = polygon;
var verticeslength = polygon.length;
var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
for (var i = 0, n = verticeslength - 3; i < n; i += 2) {
p1x = vertices[i];
p1y = vertices[i + 1];
p2x = vertices[i + 2];
p2y = vertices[i + 3];
area += p1x * p2y - p2x * p1y;
}
if (area < 0)
return;
for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
var x = vertices[i], y = vertices[i + 1];
var other = lastX - i;
vertices[i] = vertices[other];
vertices[i + 1] = vertices[other + 1];
vertices[other] = x;
vertices[other + 1] = y;
}
};
return SkeletonClipping;
}());
spine.SkeletonClipping = SkeletonClipping;
})(spine || (spine = {}));
var spine;
(function (spine) { (function (spine) {
var SkeletonData = (function () { var SkeletonData = (function () {
function SkeletonData() { function SkeletonData() {
@ -4236,7 +4731,7 @@ var spine;
throw new Error("Slot not found: " + slotName); throw new Error("Slot not found: " + slotName);
var slotMap = skinMap[slotName]; var slotMap = skinMap[slotName];
for (var entryName in slotMap) { for (var entryName in slotMap) {
var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData);
if (attachment != null) if (attachment != null)
skin.addAttachment(slotIndex, entryName, attachment); skin.addAttachment(slotIndex, entryName, attachment);
} }
@ -4276,7 +4771,7 @@ var spine;
} }
return skeletonData; return skeletonData;
}; };
SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) {
var scale = this.scale; var scale = this.scale;
name = this.getValue(map, "name", name); name = this.getValue(map, "name", name);
var type = this.getValue(map, "type", "region"); var type = this.getValue(map, "type", "region");
@ -4363,6 +4858,24 @@ var spine;
point.color.setFromString(color); point.color.setFromString(color);
return point; return point;
} }
case "clipping": {
var clip = this.attachmentLoader.newClippingAttachment(skin, name);
if (clip == null)
return null;
var end = this.getValue(map, "end", null);
if (end != null) {
var slot = skeletonData.findSlot(end);
if (slot == null)
throw new Error("Clipping end slot not found: " + end);
clip.endSlot = slot;
}
var vertexCount = map.vertexCount;
this.readVertices(map, clip, vertexCount << 1);
var color = this.getValue(map, "color", null);
if (color != null)
clip.color.setFromString(color);
return clip;
}
} }
return null; return null;
}; };
@ -5543,6 +6056,17 @@ var spine;
return array; return array;
} }
}; };
Utils.newShortArray = function (size) {
if (Utils.SUPPORTS_TYPED_ARRAYS) {
return new Int16Array(size);
}
else {
var array = new Array(size);
for (var i = 0; i < array.length; i++)
array[i] = 0;
return array;
}
};
Utils.toFloatArray = function (array) { Utils.toFloatArray = function (array) {
return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
}; };
@ -7563,6 +8087,7 @@ var spine;
this.attachmentLineColor = new spine.Color(0, 0, 1, 0.5); this.attachmentLineColor = new spine.Color(0, 0, 1, 0.5);
this.triangleLineColor = new spine.Color(1, 0.64, 0, 0.5); this.triangleLineColor = new spine.Color(1, 0.64, 0, 0.5);
this.pathColor = new spine.Color().setFromString("FF7F00"); this.pathColor = new spine.Color().setFromString("FF7F00");
this.clipColor = new spine.Color(0.8, 0, 0, 2);
this.aabbColor = new spine.Color(0, 1, 0, 0.5); this.aabbColor = new spine.Color(0, 1, 0, 0.5);
this.drawBones = true; this.drawBones = true;
this.drawRegionAttachments = true; this.drawRegionAttachments = true;
@ -7571,6 +8096,7 @@ var spine;
this.drawMeshTriangles = true; this.drawMeshTriangles = true;
this.drawPaths = true; this.drawPaths = true;
this.drawSkeletonXY = false; this.drawSkeletonXY = false;
this.drawClipping = true;
this.premultipliedAlpha = false; this.premultipliedAlpha = false;
this.scale = 1; this.scale = 1;
this.boneWidth = 2; this.boneWidth = 2;
@ -7711,6 +8237,27 @@ var spine;
shapes.circle(true, skeletonX + bone.worldX, skeletonY + bone.worldY, 3 * this.scale, SkeletonDebugRenderer.GREEN, 8); shapes.circle(true, skeletonX + bone.worldX, skeletonY + bone.worldY, 3 * this.scale, SkeletonDebugRenderer.GREEN, 8);
} }
} }
if (this.drawClipping) {
var slots = skeleton.slots;
shapes.setColor(this.clipColor);
for (var i = 0, n = slots.length; i < n; i++) {
var slot = slots[i];
var attachment = slot.getAttachment();
if (!(attachment instanceof spine.ClippingAttachment))
continue;
var clip = attachment;
var nn = clip.worldVerticesLength;
var world = this.temp = spine.Utils.setArraySize(this.temp, nn, 0);
clip.computeWorldVertices(slot, 0, nn, world, 0, 2);
for (var i_5 = 0, n_2 = world.length; i_5 < n_2; i_5 += 2) {
var x = world[i_5];
var y = world[i_5 + 1];
var x2 = world[(i_5 + 2) % world.length];
var y2 = world[(i_5 + 3) % world.length];
shapes.line(x, y, x2, y2);
}
}
}
}; };
SkeletonDebugRenderer.prototype.dispose = function () { SkeletonDebugRenderer.prototype.dispose = function () {
}; };
@ -7726,8 +8273,9 @@ var spine;
var webgl; var webgl;
(function (webgl) { (function (webgl) {
var Renderable = (function () { var Renderable = (function () {
function Renderable(vertices, numFloats) { function Renderable(vertices, numVertices, numFloats) {
this.vertices = vertices; this.vertices = vertices;
this.numVertices = numVertices;
this.numFloats = numFloats; this.numFloats = numFloats;
} }
return Renderable; return Renderable;
@ -7741,7 +8289,8 @@ var spine;
this.tempColor2 = new spine.Color(); this.tempColor2 = new spine.Color();
this.vertexSize = 2 + 2 + 4; this.vertexSize = 2 + 2 + 4;
this.twoColorTint = false; this.twoColorTint = false;
this.renderable = new Renderable(null, 0); this.renderable = new Renderable(null, 0, 0);
this.clipper = new spine.SkeletonClipping();
this.gl = gl; this.gl = gl;
this.twoColorTint = twoColorTint; this.twoColorTint = twoColorTint;
if (twoColorTint) if (twoColorTint)
@ -7749,165 +8298,115 @@ var spine;
this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024); this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024);
} }
SkeletonRenderer.prototype.draw = function (batcher, skeleton) { SkeletonRenderer.prototype.draw = function (batcher, skeleton) {
var clipper = this.clipper;
var premultipliedAlpha = this.premultipliedAlpha; var premultipliedAlpha = this.premultipliedAlpha;
var twoColorTint = this.twoColorTint;
var blendMode = null; var blendMode = null;
var vertices = null; var renderable = this.renderable;
var uvs = null;
var triangles = null; var triangles = null;
var drawOrder = skeleton.drawOrder; var drawOrder = skeleton.drawOrder;
var attachmentColor = null;
var skeletonColor = skeleton.color;
var vertexSize = twoColorTint ? 12 : 8;
for (var i = 0, n = drawOrder.length; i < n; i++) { for (var i = 0, n = drawOrder.length; i < n; i++) {
var clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
var slot = drawOrder[i]; var slot = drawOrder[i];
var attachment = slot.getAttachment(); var attachment = slot.getAttachment();
var texture = null; var texture = null;
if (attachment instanceof spine.RegionAttachment) { if (attachment instanceof spine.RegionAttachment) {
var region = attachment; var region = attachment;
vertices = this.computeRegionVertices(slot, region, premultipliedAlpha, this.twoColorTint); renderable.vertices = this.vertices;
renderable.numVertices = 4;
renderable.numFloats = clippedVertexSize << 2;
region.computeWorldVertices(slot.bone, renderable.vertices, 0, clippedVertexSize);
triangles = SkeletonRenderer.QUAD_TRIANGLES; triangles = SkeletonRenderer.QUAD_TRIANGLES;
uvs = region.uvs;
texture = region.region.renderObject.texture; texture = region.region.renderObject.texture;
attachmentColor = region.color;
} }
else if (attachment instanceof spine.MeshAttachment) { else if (attachment instanceof spine.MeshAttachment) {
var mesh = attachment; var mesh = attachment;
vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha, this.twoColorTint); renderable.vertices = this.vertices;
renderable.numVertices = (mesh.worldVerticesLength >> 1);
renderable.numFloats = renderable.numVertices * clippedVertexSize;
if (renderable.numFloats > renderable.vertices.length) {
renderable.vertices = this.vertices = spine.Utils.newFloatArray(renderable.numFloats);
}
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);
triangles = mesh.triangles; triangles = mesh.triangles;
texture = mesh.region.renderObject.texture; texture = mesh.region.renderObject.texture;
uvs = mesh.uvs;
attachmentColor = mesh.color;
}
else if (attachment instanceof spine.ClippingAttachment) {
var clip = (attachment);
clipper.clipStart(slot, clip);
continue;
} }
else else
continue; continue;
if (texture != null) { if (texture != null) {
var slotColor = slot.color;
var finalColor = this.tempColor;
finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r;
finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g;
finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b;
finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a;
if (premultipliedAlpha) {
finalColor.r *= finalColor.a;
finalColor.g *= finalColor.a;
finalColor.b *= finalColor.a;
}
var darkColor = this.tempColor2;
if (slot.darkColor == null)
darkColor.set(0, 0, 0, 1);
else
darkColor.setFromColor(slot.darkColor);
var slotBlendMode = slot.data.blendMode; var slotBlendMode = slot.data.blendMode;
if (slotBlendMode != blendMode) { if (slotBlendMode != blendMode) {
blendMode = slotBlendMode; blendMode = slotBlendMode;
batcher.setBlendMode(webgl.getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), webgl.getDestGLBlendMode(this.gl, blendMode)); batcher.setBlendMode(webgl.getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), webgl.getDestGLBlendMode(this.gl, blendMode));
} }
var view = vertices.vertices.subarray(0, vertices.numFloats); if (clipper.isClipping()) {
batcher.draw(texture, view, triangles); clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
var clippedVertices = new Float32Array(clipper.clippedVertices);
var clippedTriangles = clipper.clippedTriangles;
batcher.draw(texture, clippedVertices, clippedTriangles);
}
else {
var verts = renderable.vertices;
if (!twoColorTint) {
for (var v = 2, u = 0, n_3 = renderable.numFloats; v < n_3; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
verts[v + 3] = finalColor.a;
verts[v + 4] = uvs[u];
verts[v + 5] = uvs[u + 1];
}
}
else {
for (var v = 2, u = 0, n_4 = renderable.numFloats; v < n_4; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
verts[v + 3] = finalColor.a;
verts[v + 4] = uvs[u];
verts[v + 5] = uvs[u + 1];
verts[v + 6] = darkColor.r;
verts[v + 7] = darkColor.g;
verts[v + 8] = darkColor.b;
verts[v + 9] = darkColor.a;
}
}
var view = renderable.vertices.subarray(0, renderable.numFloats);
batcher.draw(texture, view, triangles);
}
} }
clipper.clipEndWithSlot(slot);
} }
}; clipper.clipEnd();
SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma, twoColorTint) {
if (twoColorTint === void 0) { twoColorTint = false; }
var skeleton = slot.bone.skeleton;
var skeletonColor = skeleton.color;
var slotColor = slot.color;
var regionColor = region.color;
var alpha = skeletonColor.a * slotColor.a * regionColor.a;
var multiplier = pma ? alpha : 1;
var color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
var dark = this.tempColor2;
if (slot.darkColor == null)
dark.set(0, 0, 0, 1);
else
dark.setFromColor(slot.darkColor);
region.computeWorldVertices(slot.bone, this.vertices, 0, this.vertexSize);
var vertices = this.vertices;
var uvs = region.uvs;
var i = 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[0];
vertices[i++] = uvs[1];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i += 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[2];
vertices[i++] = uvs[3];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i += 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[4];
vertices[i++] = uvs[5];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i += 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[6];
vertices[i++] = uvs[7];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
this.renderable.vertices = vertices;
this.renderable.numFloats = 4 * (twoColorTint ? 12 : 8);
return this.renderable;
};
SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma, twoColorTint) {
if (twoColorTint === void 0) { twoColorTint = false; }
var skeleton = slot.bone.skeleton;
var skeletonColor = skeleton.color;
var slotColor = slot.color;
var regionColor = mesh.color;
var alpha = skeletonColor.a * slotColor.a * regionColor.a;
var multiplier = pma ? alpha : 1;
var color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
var dark = this.tempColor2;
if (slot.darkColor == null)
dark.set(0, 0, 0, 1);
else
dark.setFromColor(slot.darkColor);
var numVertices = mesh.worldVerticesLength / 2;
if (this.vertices.length < mesh.worldVerticesLength) {
this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength);
}
var vertices = this.vertices;
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, this.vertexSize);
var uvs = mesh.uvs;
if (!twoColorTint) {
for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
vertices[v++] = color.r;
vertices[v++] = color.g;
vertices[v++] = color.b;
vertices[v++] = color.a;
vertices[v++] = uvs[u++];
vertices[v++] = uvs[u++];
v += 2;
}
}
else {
for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
vertices[v++] = color.r;
vertices[v++] = color.g;
vertices[v++] = color.b;
vertices[v++] = color.a;
vertices[v++] = uvs[u++];
vertices[v++] = uvs[u++];
vertices[v++] = dark.r;
vertices[v++] = dark.g;
vertices[v++] = dark.b;
vertices[v++] = 1;
v += 2;
}
}
this.renderable.vertices = vertices;
this.renderable.numFloats = numVertices * (twoColorTint ? 12 : 8);
return this.renderable;
}; };
SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
return SkeletonRenderer; return SkeletonRenderer;

File diff suppressed because one or more lines are too long

View File

@ -33,8 +33,8 @@ module spine {
private decomposer = new ConvexDecomposer(); private decomposer = new ConvexDecomposer();
private clippingPolygon = new Array<number>(); private clippingPolygon = new Array<number>();
private clipOutput = new Array<number>(); private clipOutput = new Array<number>();
private clippedVertices = new Array<number>(); clippedVertices = new Array<number>();
private clippedTriangles = new Array<number>(); clippedTriangles = new Array<number>();
private scratch = new Array<number>(); private scratch = new Array<number>();
private clipAttachment: ClippingAttachment; private clipAttachment: ClippingAttachment;
@ -82,7 +82,7 @@ module spine {
let clippedTriangles = this.clippedTriangles; let clippedTriangles = this.clippedTriangles;
let polygons = this.clippingPolygons; let polygons = this.clippingPolygons;
let polygonsCount = this.clippingPolygons.length; let polygonsCount = this.clippingPolygons.length;
let vertexSize = twoColor ? 6 : 5; let vertexSize = twoColor ? 12 : 8;
let index = 0; let index = 0;
clippedVertices.length = 0; clippedVertices.length = 0;
@ -120,21 +120,19 @@ module spine {
clippedVerticesItems[s + 3] = light.g; clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b; clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a; clippedVerticesItems[s + 5] = light.a;
if (twoColor) {
clippedVerticesItems[s + 6] = dark.r;
clippedVerticesItems[s + 7] = dark.g;
clippedVerticesItems[s + 8] = dark.b;
clippedVerticesItems[s + 9] = dark.a;
s += 10;
} else
s += 6;
let c0 = x - x3, c1 = y - y3; let c0 = x - x3, c1 = y - y3;
let a = (d0 * c0 + d1 * c1) * d; let a = (d0 * c0 + d1 * c1) * d;
let b = (d4 * c0 + d2 * c1) * d; let b = (d4 * c0 + d2 * c1) * d;
let c = 1 - a - b; let c = 1 - a - b;
clippedVerticesItems[s] = u1 * a + u2 * b + u3 * c; clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
clippedVerticesItems[s + 1] = v1 * a + v2 * b + v3 * c; clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
s += 2; if (twoColor) {
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 8] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
}
s += vertexSize;
} }
s = clippedTriangles.length; s = clippedTriangles.length;
@ -178,12 +176,12 @@ module spine {
clippedVerticesItems[s + 22] = u3; clippedVerticesItems[s + 22] = u3;
clippedVerticesItems[s + 23] = v3; clippedVerticesItems[s + 23] = v3;
} else { } else {
clippedVerticesItems[s + 6] = dark.r; clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = dark.g; clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = dark.b; clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.a; clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = u1; clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = v1; clippedVerticesItems[s + 11] = dark.a;
clippedVerticesItems[s + 12] = x2; clippedVerticesItems[s + 12] = x2;
clippedVerticesItems[s + 13] = y2; clippedVerticesItems[s + 13] = y2;
@ -191,12 +189,12 @@ module spine {
clippedVerticesItems[s + 15] = light.g; clippedVerticesItems[s + 15] = light.g;
clippedVerticesItems[s + 16] = light.b; clippedVerticesItems[s + 16] = light.b;
clippedVerticesItems[s + 17] = light.a; clippedVerticesItems[s + 17] = light.a;
clippedVerticesItems[s + 18] = dark.r; clippedVerticesItems[s + 18] = u2;
clippedVerticesItems[s + 19] = dark.g; clippedVerticesItems[s + 19] = v2;
clippedVerticesItems[s + 20] = dark.b; clippedVerticesItems[s + 20] = dark.r;
clippedVerticesItems[s + 21] = dark.a; clippedVerticesItems[s + 21] = dark.g;
clippedVerticesItems[s + 22] = u2; clippedVerticesItems[s + 22] = dark.b;
clippedVerticesItems[s + 23] = v2; clippedVerticesItems[s + 23] = dark.a;
clippedVerticesItems[s + 24] = x3; clippedVerticesItems[s + 24] = x3;
clippedVerticesItems[s + 25] = y3; clippedVerticesItems[s + 25] = y3;
@ -204,12 +202,12 @@ module spine {
clippedVerticesItems[s + 27] = light.g; clippedVerticesItems[s + 27] = light.g;
clippedVerticesItems[s + 28] = light.b; clippedVerticesItems[s + 28] = light.b;
clippedVerticesItems[s + 29] = light.a; clippedVerticesItems[s + 29] = light.a;
clippedVerticesItems[s + 30] = dark.r; clippedVerticesItems[s + 30] = u3;
clippedVerticesItems[s + 31] = dark.g; clippedVerticesItems[s + 31] = v3;
clippedVerticesItems[s + 32] = dark.b; clippedVerticesItems[s + 32] = dark.r;
clippedVerticesItems[s + 33] = dark.a; clippedVerticesItems[s + 33] = dark.g;
clippedVerticesItems[s + 34] = u3; clippedVerticesItems[s + 34] = dark.b;
clippedVerticesItems[s + 35] = v3; clippedVerticesItems[s + 35] = dark.a;
} }
s = clippedTriangles.length; s = clippedTriangles.length;

View File

@ -1,279 +1,251 @@
raptor.png raptor.png
size: 1024,1024 size: 2048,2048
format: RGBA8888 format: RGBA8888
filter: Linear,Linear filter: Linear,Linear
repeat: none repeat: none
back_arm back_arm
rotate: true rotate: false
xy: 140, 191 xy: 1888, 1638
size: 46, 29 size: 91, 57
orig: 46, 29 orig: 91, 57
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back_bracer back_bracer
rotate: true rotate: false
xy: 167, 317 xy: 1888, 1581
size: 39, 28 size: 77, 55
orig: 39, 28 orig: 77, 55
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back_hand back_hand
rotate: false rotate: false
xy: 167, 358 xy: 1954, 1764
size: 36, 34 size: 72, 68
orig: 36, 34 orig: 72, 68
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back_knee back_knee
rotate: false rotate: false
xy: 299, 478 xy: 275, 438
size: 49, 67 size: 97, 134
orig: 49, 67 orig: 97, 134
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back_thigh back_thigh
rotate: true rotate: false
xy: 167, 437 xy: 1778, 1518
size: 39, 24 size: 78, 47
orig: 39, 24 orig: 78, 47
offset: 0, 0
index: -1
eyes_closed
rotate: true
xy: 2, 2
size: 47, 45
orig: 47, 45
offset: 0, 0 offset: 0, 0
index: -1 index: -1
eyes_open eyes_open
rotate: true rotate: false
xy: 49, 2 xy: 275, 347
size: 47, 45 size: 93, 89
orig: 47, 45 orig: 93, 89
offset: 0, 0
index: -1
eyes_surprised
rotate: true
xy: 96, 2
size: 47, 45
orig: 47, 45
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front_arm front_arm
rotate: false rotate: false
xy: 419, 544 xy: 830, 1089
size: 48, 30 size: 96, 60
orig: 48, 30 orig: 96, 60
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front_bracer front_bracer
rotate: false rotate: false
xy: 880, 695 xy: 1888, 1697
size: 41, 29 size: 81, 58
orig: 41, 29 orig: 81, 58
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front_hand front_hand
rotate: true rotate: false
xy: 167, 394 xy: 1870, 1757
size: 41, 38 size: 82, 75
orig: 41, 38 orig: 82, 75
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front_open_hand front_open_hand
rotate: false rotate: false
xy: 880, 726 xy: 192, 15
size: 43, 44 size: 86, 87
orig: 43, 44 orig: 86, 87
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front_thigh front_thigh
rotate: false rotate: false
xy: 360, 545 xy: 714, 1091
size: 57, 29 size: 114, 58
orig: 57, 29 orig: 114, 58
offset: 0, 0 offset: 0, 0
index: -1 index: -1
gun gun
rotate: false rotate: false
xy: 785, 774 xy: 1563, 1543
size: 107, 103 size: 213, 206
orig: 107, 103 orig: 213, 206
offset: 0, 0 offset: 0, 0
index: -1 index: -1
gun_nohand gun_nohand
rotate: false rotate: false
xy: 614, 703 xy: 1223, 1403
size: 105, 102 size: 210, 203
orig: 105, 102 orig: 210, 203
offset: 0, 0 offset: 0, 0
index: -1 index: -1
head head
rotate: false rotate: false
xy: 2, 137 xy: 2, 274
size: 136, 149 size: 271, 298
orig: 136, 149 orig: 271, 298
offset: 0, 0 offset: 0, 0
index: -1 index: -1
lower_leg lower_leg
rotate: true
xy: 780, 699
size: 73, 98
orig: 73, 98
offset: 0, 0
index: -1
mouth_grind
rotate: false rotate: false
xy: 469, 544 xy: 551, 893
size: 47, 30 size: 146, 195
orig: 47, 30 orig: 146, 195
offset: 0, 0
index: -1
mouth_oooo
rotate: true
xy: 894, 772
size: 105, 30
orig: 105, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
mouth_smile mouth_smile
rotate: true rotate: false
xy: 140, 239 xy: 928, 1090
size: 47, 30 size: 93, 59
orig: 47, 30 orig: 93, 59
offset: 0, 0 offset: 0, 0
index: -1 index: -1
neck neck
rotate: true rotate: false
xy: 538, 577 xy: 330, 908
size: 18, 21 size: 36, 41
orig: 18, 21 orig: 36, 41
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_arm_back raptor_arm_back
rotate: false rotate: false
xy: 940, 936 xy: 386, 916
size: 82, 86 size: 163, 172
orig: 82, 86 orig: 163, 172
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_body raptor_body
rotate: false rotate: false
xy: 2, 737 xy: 2, 1467
size: 610, 285 size: 1219, 570
orig: 610, 285 orig: 1219, 570
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_front_arm raptor_front_arm
rotate: true rotate: false
xy: 195, 464 xy: 1870, 1834
size: 81, 102 size: 162, 203
orig: 81, 102 orig: 162, 203
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_front_leg raptor_front_leg
rotate: false rotate: false
xy: 2, 478 xy: 2, 951
size: 191, 257 size: 382, 514
orig: 191, 257 orig: 382, 514
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_hindleg_back raptor_hindleg_back
rotate: false rotate: false
xy: 614, 807 xy: 1223, 1608
size: 169, 215 size: 338, 429
orig: 169, 215 orig: 338, 429
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_horn raptor_horn
rotate: false rotate: false
xy: 360, 655 xy: 714, 1306
size: 182, 80 size: 363, 159
orig: 182, 80 orig: 363, 159
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_horn_back raptor_horn_back
rotate: false rotate: false
xy: 360, 576 xy: 714, 1151
size: 176, 77 size: 351, 153
orig: 176, 77 orig: 351, 153
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_jaw raptor_jaw
rotate: false rotate: false
xy: 785, 879 xy: 1563, 1751
size: 153, 143 size: 305, 286
orig: 153, 143 orig: 305, 286
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_saddle_noshadow raptor_saddle_noshadow
rotate: false rotate: false
xy: 2, 288 xy: 2, 574
size: 163, 188 size: 326, 375
orig: 163, 188 orig: 326, 375
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_saddle_strap_front raptor_saddle_strap_front
rotate: false rotate: false
xy: 721, 710 xy: 1435, 1417
size: 57, 95 size: 114, 189
orig: 57, 95 orig: 114, 189
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_saddle_strap_rear raptor_saddle_strap_rear
rotate: true rotate: false
xy: 940, 880 xy: 1079, 1317
size: 54, 74 size: 108, 148
orig: 54, 74 orig: 108, 148
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_saddle_w_shadow raptor_saddle_w_shadow
rotate: false rotate: false
xy: 195, 547 xy: 386, 1090
size: 163, 188 size: 326, 375
orig: 163, 188 orig: 326, 375
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor_tongue raptor_tongue
rotate: true rotate: false
xy: 544, 649 xy: 1551, 1413
size: 86, 64 size: 171, 128
orig: 86, 64 orig: 171, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
stirrup_back stirrup_back
rotate: true rotate: false
xy: 140, 145 xy: 275, 276
size: 44, 35 size: 87, 69
orig: 44, 35 orig: 87, 69
offset: 0, 0 offset: 0, 0
index: -1 index: -1
stirrup_front stirrup_front
rotate: false rotate: false
xy: 538, 597 xy: 2, 2
size: 45, 50 size: 89, 100
orig: 45, 50 orig: 89, 100
offset: 0, 0 offset: 0, 0
index: -1 index: -1
stirrup_strap stirrup_strap
rotate: false rotate: false
xy: 350, 497 xy: 93, 11
size: 49, 46 size: 97, 91
orig: 49, 46 orig: 97, 91
offset: 0, 0 offset: 0, 0
index: -1 index: -1
torso torso
rotate: true rotate: false
xy: 610, 647 xy: 1778, 1567
size: 54, 91 size: 108, 182
orig: 54, 91 orig: 108, 182
offset: 0, 0 offset: 0, 0
index: -1 index: -1
visor visor
rotate: false rotate: false
xy: 2, 51 xy: 2, 104
size: 131, 84 size: 261, 168
orig: 131, 84 orig: 261, 168
offset: 0, 0 offset: 0, 0
index: -1 index: -1

View File

@ -1,5 +1,5 @@
{ {
"skeleton": { "hash": "WOArBZLexLEX/Tow3AuM8ddszEE", "spine": "3.6.14-beta", "width": 1223.73, "height": 1055.62, "images": "./images/" }, "skeleton": { "hash": "T+jP778edtEIrEMb7QvVNAgiHUo", "spine": "3.6.14-beta", "width": 1223.73, "height": 1056.91, "images": "./images/" },
"bones": [ "bones": [
{ "name": "root" }, { "name": "root" },
{ "name": "hip", "parent": "root", "rotation": 3.16, "x": -136.79, "y": 415.48, "color": "fbff00ff" }, { "name": "hip", "parent": "root", "rotation": 3.16, "x": -136.79, "y": 415.48, "color": "fbff00ff" },
@ -199,6 +199,7 @@
{ "name": "tongue3", "parent": "tongue2", "length": 43.65, "rotation": 12.86, "x": 44.27, "y": -0.21, "color": "fff200ff" } { "name": "tongue3", "parent": "tongue2", "length": 43.65, "rotation": 12.86, "x": 44.27, "y": -0.21, "color": "fff200ff" }
], ],
"slots": [ "slots": [
{ "name": "clip", "bone": "root", "attachment": "clip" },
{ "name": "back_hand", "bone": "back_hand", "attachment": "back_hand" }, { "name": "back_hand", "bone": "back_hand", "attachment": "back_hand" },
{ "name": "back_arm", "bone": "back_arm", "attachment": "back_arm" }, { "name": "back_arm", "bone": "back_arm", "attachment": "back_arm" },
{ "name": "back_bracer", "bone": "back_bracer", "attachment": "back_bracer" }, { "name": "back_bracer", "bone": "back_bracer", "attachment": "back_bracer" },
@ -310,6 +311,15 @@
"back_thigh": { "back_thigh": {
"back_thigh": { "x": 37.85, "y": -4.37, "rotation": 19.25, "width": 78, "height": 47 } "back_thigh": { "x": 37.85, "y": -4.37, "rotation": 19.25, "width": 78, "height": 47 }
}, },
"clip": {
"clip": {
"type": "clipping",
"end": "clip",
"vertexCount": 25,
"vertices": [ -31.42, 352.85, -182.02, 382.27, -214.91, 562.3, -8.92, 647.12, 183.22, 555.37, 254.19, 375.35, 261.12, 153.78, 3.2, 13.57, -270.3, -36.63, -408.78, 48.19, -349.93, 280.14, -228.76, 133.01, -59.12, 94.93, 107.06, 160.71, 202.26, 349.38, 122.64, 487.86, -41.81, 557.1, -142.21, 489.6, -57.39, 422.09, 49.94, 432.47, 133.02, 370.16, 94.94, 271.49, 43.01, 186.67, -138.74, 174.55, -230.49, 273.22 ],
"color": "ce3a3aff"
}
},
"eyes_open": { "eyes_open": {
"eyes_open": { "x": 93.24, "y": -25.45, "rotation": -70.58, "width": 93, "height": 89 } "eyes_open": { "x": 93.24, "y": -25.45, "rotation": -70.58, "width": 93, "height": 89 }
}, },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 495 KiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

@ -13,8 +13,9 @@
<script> <script>
var FILE = "coin"; var FILE = "coin";
var ANIMATION = "rotate";
var NUM_SKELETONS = 1; var NUM_SKELETONS = 1;
var SCALE = 0.6; var SCALE = 0.5;
var canvas, gl, renderer, input, assetManager; var canvas, gl, renderer, input, assetManager;
var skeletons = []; var skeletons = [];
@ -29,6 +30,12 @@ function init() {
gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false }); gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false });
renderer = new spine.webgl.SceneRenderer(canvas, gl); renderer = new spine.webgl.SceneRenderer(canvas, gl);
renderer.skeletonDebugRenderer.drawBones = false;
renderer.skeletonDebugRenderer.drawMeshTriangles = false;
renderer.skeletonDebugRenderer.drawMeshHull = false;
renderer.skeletonDebugRenderer.drawRegionAttachments = false;
renderer.skeletonDebugRenderer.drawBoundingBoxes = false;
assetManager = new spine.webgl.AssetManager(gl, "assets/"); assetManager = new spine.webgl.AssetManager(gl, "assets/");
var textureLoader = function(img) { return new spine.webgl.GLTexture(gl, img); }; var textureLoader = function(img) { return new spine.webgl.GLTexture(gl, img); };
input = new spine.webgl.Input(canvas); input = new spine.webgl.Input(canvas);
@ -62,10 +69,9 @@ function load() {
stateData.defaultMix = mixDuration; stateData.defaultMix = mixDuration;
state.multipleMixing = false; state.multipleMixing = false;
state.setAnimation(0, "rotate", true); state.setAnimation(0, "walk", true);
state.apply(skeleton); skeleton.x = 0;
skeleton.x = Math.random() * 200 - Math.random() * 200; skeleton.y = 0;
skeleton.y = Math.random() * 200 - Math.random() * 200;
skeleton.updateWorldTransform(); skeleton.updateWorldTransform();
skeletons.push({ skeleton: skeleton, state: state }); skeletons.push({ skeleton: skeleton, state: state });
} }
@ -92,7 +98,7 @@ function render() {
updateMean.addValue(Date.now() - start); updateMean.addValue(Date.now() - start);
start = Date.now(); start = Date.now();
gl.clearColor(0, 0, 0, 1); gl.clearColor(0.2, 0.2, 0.2, 1);
gl.clear(gl.COLOR_BUFFER_BIT); gl.clear(gl.COLOR_BUFFER_BIT);
renderer.resize(spine.webgl.ResizeMode.Fit); renderer.resize(spine.webgl.ResizeMode.Fit);
@ -100,6 +106,7 @@ function render() {
for (var i = 0; i < skeletons.length; i++) { for (var i = 0; i < skeletons.length; i++) {
var skeleton = skeletons[i].skeleton; var skeleton = skeletons[i].skeleton;
renderer.drawSkeleton(skeleton); renderer.drawSkeleton(skeleton);
renderer.drawSkeletonDebug(skeleton);
} }
renderer.end(); renderer.end();

View File

@ -35,6 +35,7 @@ module spine.webgl {
attachmentLineColor = new Color(0, 0, 1, 0.5); attachmentLineColor = new Color(0, 0, 1, 0.5);
triangleLineColor = new Color(1, 0.64, 0, 0.5); triangleLineColor = new Color(1, 0.64, 0, 0.5);
pathColor = new Color().setFromString("FF7F00"); pathColor = new Color().setFromString("FF7F00");
clipColor = new Color(0.8, 0, 0, 2);
aabbColor = new Color(0, 1, 0, 0.5); aabbColor = new Color(0, 1, 0, 0.5);
drawBones = true; drawBones = true;
drawRegionAttachments = true; drawRegionAttachments = true;
@ -43,6 +44,7 @@ module spine.webgl {
drawMeshTriangles = true; drawMeshTriangles = true;
drawPaths = true; drawPaths = true;
drawSkeletonXY = false; drawSkeletonXY = false;
drawClipping = true;
premultipliedAlpha = false; premultipliedAlpha = false;
scale = 1; scale = 1;
boneWidth = 2; boneWidth = 2;
@ -192,6 +194,27 @@ module spine.webgl {
shapes.circle(true, skeletonX + bone.worldX, skeletonY + bone.worldY, 3 * this.scale, SkeletonDebugRenderer.GREEN, 8); shapes.circle(true, skeletonX + bone.worldX, skeletonY + bone.worldY, 3 * this.scale, SkeletonDebugRenderer.GREEN, 8);
} }
} }
if (this.drawClipping) {
let slots = skeleton.slots;
shapes.setColor(this.clipColor)
for (let i = 0, n = slots.length; i < n; i++) {
let slot = slots[i];
let attachment = slot.getAttachment();
if (!(attachment instanceof ClippingAttachment)) continue;
let clip = <ClippingAttachment>attachment;
let nn = clip.worldVerticesLength;
let world = this.temp = Utils.setArraySize(this.temp, nn, 0);
clip.computeWorldVertices(slot, 0, nn, world, 0, 2);
for (let i = 0, n = world.length; i < n; i+=2) {
let x = world[i];
let y = world[i + 1];
let x2 = world[(i + 2) % world.length];
let y2 = world[(i + 3) % world.length];
shapes.line(x, y, x2, y2);
}
}
}
} }
dispose () { dispose () {

View File

@ -30,7 +30,7 @@
module spine.webgl { module spine.webgl {
class Renderable { class Renderable {
constructor(public vertices: ArrayLike<number>, public numFloats: number) {} constructor(public vertices: ArrayLike<number>, public numVertices: number, public numFloats: number) {}
}; };
export class SkeletonRenderer { export class SkeletonRenderer {
@ -43,7 +43,8 @@ module spine.webgl {
private vertices:ArrayLike<number>; private vertices:ArrayLike<number>;
private vertexSize = 2 + 2 + 4; private vertexSize = 2 + 2 + 4;
private twoColorTint = false; private twoColorTint = false;
private renderable: Renderable = new Renderable(null, 0); private renderable: Renderable = new Renderable(null, 0, 0);
private clipper: SkeletonClipping = new SkeletonClipping();
constructor (gl: WebGLRenderingContext, twoColorTint: boolean = true) { constructor (gl: WebGLRenderingContext, twoColorTint: boolean = true) {
this.gl = gl; this.gl = gl;
@ -54,177 +55,112 @@ module spine.webgl {
} }
draw (batcher: PolygonBatcher, skeleton: Skeleton) { draw (batcher: PolygonBatcher, skeleton: Skeleton) {
let clipper = this.clipper;
let premultipliedAlpha = this.premultipliedAlpha; let premultipliedAlpha = this.premultipliedAlpha;
let twoColorTint = this.twoColorTint;
let blendMode: BlendMode = null; let blendMode: BlendMode = null;
let vertices: Renderable = null; let renderable: Renderable = this.renderable;
let uvs: ArrayLike<number> = null;
let triangles: Array<number> = null; let triangles: Array<number> = null;
let drawOrder = skeleton.drawOrder; let drawOrder = skeleton.drawOrder;
let attachmentColor: Color = null;
let skeletonColor = skeleton.color;
let vertexSize = twoColorTint ? 12 : 8;
for (let i = 0, n = drawOrder.length; i < n; i++) { for (let i = 0, n = drawOrder.length; i < n; i++) {
let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
let slot = drawOrder[i]; let slot = drawOrder[i];
let attachment = slot.getAttachment(); let attachment = slot.getAttachment();
let texture: GLTexture = null; let texture: GLTexture = null;
if (attachment instanceof RegionAttachment) { if (attachment instanceof RegionAttachment) {
let region = <RegionAttachment>attachment; let region = <RegionAttachment>attachment;
vertices = this.computeRegionVertices(slot, region, premultipliedAlpha, this.twoColorTint); renderable.vertices = this.vertices;
renderable.numVertices = 4;
renderable.numFloats = clippedVertexSize << 2;
region.computeWorldVertices(slot.bone, renderable.vertices, 0, clippedVertexSize);
triangles = SkeletonRenderer.QUAD_TRIANGLES; triangles = SkeletonRenderer.QUAD_TRIANGLES;
uvs = region.uvs;
texture = <GLTexture>(<TextureAtlasRegion>region.region.renderObject).texture; texture = <GLTexture>(<TextureAtlasRegion>region.region.renderObject).texture;
attachmentColor = region.color;
} else if (attachment instanceof MeshAttachment) { } else if (attachment instanceof MeshAttachment) {
let mesh = <MeshAttachment>attachment; let mesh = <MeshAttachment>attachment;
vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha, this.twoColorTint); renderable.vertices = this.vertices;
renderable.numVertices = (mesh.worldVerticesLength >> 1);
renderable.numFloats = renderable.numVertices * clippedVertexSize;
if (renderable.numFloats > renderable.vertices.length) {
renderable.vertices = this.vertices = spine.Utils.newFloatArray(renderable.numFloats);
}
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);
triangles = mesh.triangles; triangles = mesh.triangles;
texture = <GLTexture>(<TextureAtlasRegion>mesh.region.renderObject).texture; texture = <GLTexture>(<TextureAtlasRegion>mesh.region.renderObject).texture;
uvs = mesh.uvs;
attachmentColor = mesh.color;
} else if (attachment instanceof ClippingAttachment) {
let clip = <ClippingAttachment>(attachment);
clipper.clipStart(slot, clip);
continue;
} else continue; } else continue;
if (texture != null) { if (texture != null) {
let slotColor = slot.color;
let finalColor = this.tempColor;
finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r;
finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g;
finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b;
finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a;
if (premultipliedAlpha) {
finalColor.r *= finalColor.a;
finalColor.g *= finalColor.a;
finalColor.b *= finalColor.a;
}
let darkColor = this.tempColor2;
if (slot.darkColor == null) darkColor.set(0, 0, 0, 1);
else darkColor.setFromColor(slot.darkColor);
let slotBlendMode = slot.data.blendMode; let slotBlendMode = slot.data.blendMode;
if (slotBlendMode != blendMode) { if (slotBlendMode != blendMode) {
blendMode = slotBlendMode; blendMode = slotBlendMode;
batcher.setBlendMode(getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this.gl, blendMode)); batcher.setBlendMode(getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this.gl, blendMode));
} }
let view = (vertices.vertices as Float32Array).subarray(0, vertices.numFloats); if (clipper.isClipping()) {
batcher.draw(texture, view, triangles); clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
let clippedVertices = new Float32Array(clipper.clippedVertices);
let clippedTriangles = clipper.clippedTriangles;
batcher.draw(texture, clippedVertices, clippedTriangles);
} else {
let verts = renderable.vertices;
if (!twoColorTint) {
for (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
verts[v + 3] = finalColor.a;
verts[v + 4] = uvs[u];
verts[v + 5] = uvs[u + 1];
}
} else {
for (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) {
verts[v] = finalColor.r;
verts[v + 1] = finalColor.g;
verts[v + 2] = finalColor.b;
verts[v + 3] = finalColor.a;
verts[v + 4] = uvs[u];
verts[v + 5] = uvs[u + 1];
verts[v + 6] = darkColor.r;
verts[v + 7] = darkColor.g;
verts[v + 8] = darkColor.b;
verts[v + 9] = darkColor.a;
}
}
let view = (renderable.vertices as Float32Array).subarray(0, renderable.numFloats);
batcher.draw(texture, view, triangles);
}
} }
clipper.clipEndWithSlot(slot);
} }
} clipper.clipEnd();
private computeRegionVertices(slot: Slot, region: RegionAttachment, pma: boolean, twoColorTint: boolean = false) {
let skeleton = slot.bone.skeleton;
let skeletonColor = skeleton.color;
let slotColor = slot.color;
let regionColor = region.color;
let alpha = skeletonColor.a * slotColor.a * regionColor.a;
let multiplier = pma ? alpha : 1;
let color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
skeletonColor.g * slotColor.g * regionColor.g * multiplier,
skeletonColor.b * slotColor.b * regionColor.b * multiplier,
alpha);
let dark = this.tempColor2;
if (slot.darkColor == null) dark.set(0, 0, 0, 1);
else dark.setFromColor(slot.darkColor);
region.computeWorldVertices(slot.bone, this.vertices, 0, this.vertexSize);
let vertices = this.vertices;
let uvs = region.uvs;
let i = 2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[0];
vertices[i++] = uvs[1];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i+=2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[2];
vertices[i++] = uvs[3];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i+=2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[4];
vertices[i++] = uvs[5];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
i+=2;
vertices[i++] = color.r;
vertices[i++] = color.g;
vertices[i++] = color.b;
vertices[i++] = color.a;
vertices[i++] = uvs[6];
vertices[i++] = uvs[7];
if (twoColorTint) {
vertices[i++] = dark.r;
vertices[i++] = dark.g;
vertices[i++] = dark.b;
vertices[i++] = 1;
}
this.renderable.vertices = vertices;
this.renderable.numFloats = 4 * (twoColorTint ? 12 : 8);
return this.renderable;
}
private computeMeshVertices(slot: Slot, mesh: MeshAttachment, pma: boolean, twoColorTint: boolean = false) {
let skeleton = slot.bone.skeleton;
let skeletonColor = skeleton.color;
let slotColor = slot.color;
let regionColor = mesh.color;
let alpha = skeletonColor.a * slotColor.a * regionColor.a;
let multiplier = pma ? alpha : 1;
let color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
skeletonColor.g * slotColor.g * regionColor.g * multiplier,
skeletonColor.b * slotColor.b * regionColor.b * multiplier,
alpha);
let dark = this.tempColor2;
if (slot.darkColor == null) dark.set(0, 0, 0, 1);
else dark.setFromColor(slot.darkColor);
let numVertices = mesh.worldVerticesLength / 2;
if (this.vertices.length < mesh.worldVerticesLength) {
this.vertices = Utils.newFloatArray(mesh.worldVerticesLength);
}
let vertices = this.vertices;
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, this.vertexSize);
let uvs = mesh.uvs;
if (!twoColorTint) {
for (let i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
vertices[v++] = color.r;
vertices[v++] = color.g;
vertices[v++] = color.b;
vertices[v++] = color.a;
vertices[v++] = uvs[u++];
vertices[v++] = uvs[u++];
v += 2;
}
} else {
for (let i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
vertices[v++] = color.r;
vertices[v++] = color.g;
vertices[v++] = color.b;
vertices[v++] = color.a;
vertices[v++] = uvs[u++];
vertices[v++] = uvs[u++];
vertices[v++] = dark.r;
vertices[v++] = dark.g;
vertices[v++] = dark.b;
vertices[v++] = 1;
v += 2;
}
}
this.renderable.vertices = vertices;
this.renderable.numFloats = numVertices * (twoColorTint ? 12 : 8);
return this.renderable;
} }
} }
} }