[ts] Ported addition of uniform/compressed IK and rotation fix. See #1163.

This commit is contained in:
badlogic 2018-08-23 15:23:02 +02:00
parent 7df713b13f
commit 18f2ccf480
9 changed files with 10778 additions and 10750 deletions

View File

@ -16,11 +16,11 @@ declare module spine {
setup = 0, setup = 0,
first = 1, first = 1,
replace = 2, replace = 2,
add = 3 add = 3,
} }
enum MixDirection { enum MixDirection {
in = 0, in = 0,
out = 1 out = 1,
} }
enum TimelineType { enum TimelineType {
rotate = 0, rotate = 0,
@ -37,7 +37,7 @@ declare module spine {
pathConstraintPosition = 11, pathConstraintPosition = 11,
pathConstraintSpacing = 12, pathConstraintSpacing = 12,
pathConstraintMix = 13, pathConstraintMix = 13,
twoColor = 14 twoColor = 14,
} }
abstract class CurveTimeline implements Timeline { abstract class CurveTimeline implements Timeline {
static LINEAR: number; static LINEAR: number;
@ -176,15 +176,17 @@ declare module spine {
static PREV_TIME: number; static PREV_TIME: number;
static PREV_MIX: number; static PREV_MIX: number;
static PREV_BEND_DIRECTION: number; static PREV_BEND_DIRECTION: number;
static PREV_COMPRESS: number;
static PREV_STRETCH: number; static PREV_STRETCH: number;
static MIX: number; static MIX: number;
static BEND_DIRECTION: number; static BEND_DIRECTION: number;
static COMPRESS: number;
static STRETCH: number; static STRETCH: number;
ikConstraintIndex: number; ikConstraintIndex: number;
frames: ArrayLike<number>; frames: ArrayLike<number>;
constructor(frameCount: number); constructor(frameCount: number);
getPropertyId(): number; getPropertyId(): number;
setFrame(frameIndex: number, time: number, mix: number, bendDirection: number, stretch: boolean): void; setFrame(frameIndex: number, time: number, mix: number, bendDirection: number, compress: boolean, stretch: boolean): void;
apply(skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void; apply(skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
} }
class TransformConstraintTimeline extends CurveTimeline { class TransformConstraintTimeline extends CurveTimeline {
@ -338,7 +340,7 @@ declare module spine {
end = 2, end = 2,
dispose = 3, dispose = 3,
complete = 4, complete = 4,
event = 5 event = 5,
} }
interface AnimationStateListener2 { interface AnimationStateListener2 {
start(entry: TrackEntry): void; start(entry: TrackEntry): void;
@ -377,8 +379,8 @@ declare module spine {
private toLoad; private toLoad;
private loaded; private loaded;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string); constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
private static downloadText; private static downloadText(url, success, error);
private static downloadBinary; private static downloadBinary(url, success, error);
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void; loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void; loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void; loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
@ -411,7 +413,7 @@ declare module spine {
Normal = 0, Normal = 0,
Additive = 1, Additive = 1,
Multiply = 2, Multiply = 2,
Screen = 3 Screen = 3,
} }
} }
declare module spine { declare module spine {
@ -480,7 +482,7 @@ declare module spine {
OnlyTranslation = 1, OnlyTranslation = 1,
NoRotationOrReflection = 2, NoRotationOrReflection = 2,
NoScale = 3, NoScale = 3,
NoScaleOrReflection = 4 NoScaleOrReflection = 4,
} }
} }
declare module spine { declare module spine {
@ -513,13 +515,14 @@ declare module spine {
bones: Array<Bone>; bones: Array<Bone>;
target: Bone; target: Bone;
bendDirection: number; bendDirection: number;
compress: boolean;
stretch: boolean; stretch: boolean;
mix: number; mix: number;
constructor(data: IkConstraintData, skeleton: Skeleton); constructor(data: IkConstraintData, skeleton: Skeleton);
getOrder(): number; getOrder(): number;
apply(): void; apply(): void;
update(): void; update(): void;
apply1(bone: Bone, targetX: number, targetY: number, stretch: boolean, alpha: number): void; apply1(bone: Bone, targetX: number, targetY: number, compress: boolean, stretch: boolean, uniform: boolean, alpha: number): void;
apply2(parent: Bone, child: Bone, targetX: number, targetY: number, bendDir: number, stretch: boolean, alpha: number): void; apply2(parent: Bone, child: Bone, targetX: number, targetY: number, bendDir: number, stretch: boolean, alpha: number): void;
} }
} }
@ -530,7 +533,9 @@ declare module spine {
bones: BoneData[]; bones: BoneData[];
target: BoneData; target: BoneData;
bendDirection: number; bendDirection: number;
compress: boolean;
stretch: boolean; stretch: boolean;
uniform: boolean;
mix: number; mix: number;
constructor(name: string); constructor(name: string);
} }
@ -582,17 +587,17 @@ declare module spine {
} }
enum PositionMode { enum PositionMode {
Fixed = 0, Fixed = 0,
Percent = 1 Percent = 1,
} }
enum SpacingMode { enum SpacingMode {
Length = 0, Length = 0,
Fixed = 1, Fixed = 1,
Percent = 2 Percent = 2,
} }
enum RotateMode { enum RotateMode {
Tangent = 0, Tangent = 0,
Chain = 1, Chain = 1,
ChainScale = 2 ChainScale = 2,
} }
} }
declare module spine { declare module spine {
@ -603,12 +608,12 @@ declare module spine {
private rawAssets; private rawAssets;
private errors; private errors;
constructor(pathPrefix?: string); constructor(pathPrefix?: string);
private queueAsset; private queueAsset(clientId, textureLoader, path);
loadText(clientId: string, path: string): void; loadText(clientId: string, path: string): void;
loadJson(clientId: string, path: string): void; loadJson(clientId: string, path: string): void;
loadTexture(clientId: string, textureLoader: (image: HTMLImageElement) => any, path: string): void; loadTexture(clientId: string, textureLoader: (image: HTMLImageElement) => any, path: string): void;
get(clientId: string, path: string): any; get(clientId: string, path: string): any;
private updateClientAssets; private updateClientAssets(clientAssets);
isLoadingComplete(clientId: string): boolean; isLoadingComplete(clientId: string): boolean;
dispose(): void; dispose(): void;
hasErrors(): boolean; hasErrors(): boolean;
@ -812,12 +817,12 @@ declare module spine {
MipMapNearestNearest = 9984, MipMapNearestNearest = 9984,
MipMapLinearNearest = 9985, MipMapLinearNearest = 9985,
MipMapNearestLinear = 9986, MipMapNearestLinear = 9986,
MipMapLinearLinear = 9987 MipMapLinearLinear = 9987,
} }
enum TextureWrap { enum TextureWrap {
MirroredRepeat = 33648, MirroredRepeat = 33648,
ClampToEdge = 33071, ClampToEdge = 33071,
Repeat = 10497 Repeat = 10497,
} }
class TextureRegion { class TextureRegion {
renderObject: any; renderObject: any;
@ -844,7 +849,7 @@ declare module spine {
pages: TextureAtlasPage[]; pages: TextureAtlasPage[];
regions: TextureAtlasRegion[]; regions: TextureAtlasRegion[];
constructor(atlasText: string, textureLoader: (path: string) => any); constructor(atlasText: string, textureLoader: (path: string) => any);
private load; private load(atlasText, textureLoader);
findRegion(name: string): TextureAtlasRegion; findRegion(name: string): TextureAtlasRegion;
dispose(): void; dispose(): void;
} }
@ -920,9 +925,9 @@ declare module spine {
private polygonIndicesPool; private polygonIndicesPool;
triangulate(verticesArray: ArrayLike<number>): Array<number>; triangulate(verticesArray: ArrayLike<number>): Array<number>;
decompose(verticesArray: Array<number>, triangles: Array<number>): Array<Array<number>>; decompose(verticesArray: Array<number>, triangles: Array<number>): Array<Array<number>>;
private static isConcave; private static isConcave(index, vertexCount, vertices, indices);
private static positiveArea; private static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y);
private static winding; private static winding(p1x, p1y, p2x, p2y, p3x, p3y);
} }
} }
declare module spine { declare module spine {
@ -1094,7 +1099,7 @@ declare module spine {
Mesh = 2, Mesh = 2,
LinkedMesh = 3, LinkedMesh = 3,
Path = 4, Path = 4,
Point = 5 Point = 5,
} }
} }
declare module spine { declare module spine {
@ -1288,7 +1293,7 @@ declare module spine.webgl {
touchesPool: Pool<Touch>; touchesPool: Pool<Touch>;
private listeners; private listeners;
constructor(element: HTMLElement); constructor(element: HTMLElement);
private setupCallbacks; private setupCallbacks(element);
addListener(listener: InputListener): void; addListener(listener: InputListener): void;
removeListener(listener: InputListener): void; removeListener(listener: InputListener): void;
} }
@ -1397,7 +1402,7 @@ declare module spine.webgl {
drawWithOffset(shader: Shader, primitiveType: number, offset: number, count: number): void; drawWithOffset(shader: Shader, primitiveType: number, offset: number, count: number): void;
bind(shader: Shader): void; bind(shader: Shader): void;
unbind(shader: Shader): void; unbind(shader: Shader): void;
private update; private update();
restore(): void; restore(): void;
dispose(): void; dispose(): void;
} }
@ -1423,7 +1428,7 @@ declare module spine.webgl {
constructor(); constructor();
} }
enum VertexAttributeType { enum VertexAttributeType {
Float = 0 Float = 0,
} }
} }
declare module spine.webgl { declare module spine.webgl {
@ -1442,7 +1447,7 @@ declare module spine.webgl {
begin(shader: Shader): void; begin(shader: Shader): void;
setBlendMode(srcBlend: number, dstBlend: number): void; setBlendMode(srcBlend: number, dstBlend: number): void;
draw(texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>): void; draw(texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>): void;
private flush; private flush();
end(): void; end(): void;
getDrawCalls(): number; getDrawCalls(): number;
dispose(): void; dispose(): void;
@ -1482,13 +1487,13 @@ declare module spine.webgl {
curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void; curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void;
end(): void; end(): void;
resize(resizeMode: ResizeMode): void; resize(resizeMode: ResizeMode): void;
private enableRenderer; private enableRenderer(renderer);
dispose(): void; dispose(): void;
} }
enum ResizeMode { enum ResizeMode {
Stretch = 0, Stretch = 0,
Expand = 1, Expand = 1,
Fit = 2 Fit = 2,
} }
} }
declare module spine.webgl { declare module spine.webgl {
@ -1516,9 +1521,9 @@ declare module spine.webgl {
getVertexShaderSource(): string; getVertexShaderSource(): string;
getFragmentSource(): string; getFragmentSource(): string;
constructor(context: ManagedWebGLRenderingContext | WebGLRenderingContext, vertexShader: string, fragmentShader: string); constructor(context: ManagedWebGLRenderingContext | WebGLRenderingContext, vertexShader: string, fragmentShader: string);
private compile; private compile();
private compileShader; private compileShader(type, source);
private compileProgram; private compileProgram(vs, fs);
restore(): void; restore(): void;
bind(): void; bind(): void;
unbind(): void; unbind(): void;
@ -1565,16 +1570,16 @@ declare module spine.webgl {
polygon(polygonVertices: ArrayLike<number>, offset: number, count: number, color?: Color): void; polygon(polygonVertices: ArrayLike<number>, offset: number, count: number, color?: Color): void;
circle(filled: boolean, x: number, y: number, radius: number, color?: Color, segments?: number): void; circle(filled: boolean, x: number, y: number, radius: number, color?: Color, segments?: number): void;
curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void; curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void;
private vertex; private vertex(x, y, color);
end(): void; end(): void;
private flush; private flush();
private check; private check(shapeType, numVertices);
dispose(): void; dispose(): void;
} }
enum ShapeType { enum ShapeType {
Point = 0, Point = 0,
Line = 1, Line = 1,
Filled = 4 Filled = 4,
} }
} }
declare module spine.webgl { declare module spine.webgl {

View File

@ -1,10 +1,7 @@
var __extends = (this && this.__extends) || (function () { var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) { var extendStatics = Object.setPrototypeOf ||
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) { return function (d, b) {
extendStatics(d, b); extendStatics(d, b);
function __() { this.constructor = d; } function __() { this.constructor = d; }
@ -968,11 +965,12 @@ var spine;
IkConstraintTimeline.prototype.getPropertyId = function () { IkConstraintTimeline.prototype.getPropertyId = function () {
return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex; return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex;
}; };
IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, bendDirection, stretch) { IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, bendDirection, compress, stretch) {
frameIndex *= IkConstraintTimeline.ENTRIES; frameIndex *= IkConstraintTimeline.ENTRIES;
this.frames[frameIndex] = time; this.frames[frameIndex] = time;
this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; this.frames[frameIndex + IkConstraintTimeline.MIX] = mix;
this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection;
this.frames[frameIndex + IkConstraintTimeline.COMPRESS] = compress ? 1 : 0;
this.frames[frameIndex + IkConstraintTimeline.STRETCH] = stretch ? 1 : 0; this.frames[frameIndex + IkConstraintTimeline.STRETCH] = stretch ? 1 : 0;
}; };
IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) { IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
@ -1036,14 +1034,16 @@ var spine;
} }
} }
}; };
IkConstraintTimeline.ENTRIES = 4; IkConstraintTimeline.ENTRIES = 5;
IkConstraintTimeline.PREV_TIME = -4; IkConstraintTimeline.PREV_TIME = -5;
IkConstraintTimeline.PREV_MIX = -3; IkConstraintTimeline.PREV_MIX = -4;
IkConstraintTimeline.PREV_BEND_DIRECTION = -2; IkConstraintTimeline.PREV_BEND_DIRECTION = -3;
IkConstraintTimeline.PREV_COMPRESS = -2;
IkConstraintTimeline.PREV_STRETCH = -1; IkConstraintTimeline.PREV_STRETCH = -1;
IkConstraintTimeline.MIX = 1; IkConstraintTimeline.MIX = 1;
IkConstraintTimeline.BEND_DIRECTION = 2; IkConstraintTimeline.BEND_DIRECTION = 2;
IkConstraintTimeline.STRETCH = 3; IkConstraintTimeline.COMPRESS = 3;
IkConstraintTimeline.STRETCH = 4;
return IkConstraintTimeline; return IkConstraintTimeline;
}(CurveTimeline)); }(CurveTimeline));
spine.IkConstraintTimeline = IkConstraintTimeline; spine.IkConstraintTimeline = IkConstraintTimeline;
@ -1530,11 +1530,11 @@ var spine;
} }
var r1 = blend == spine.MixBlend.setup ? bone.data.rotation : bone.rotation; var r1 = blend == spine.MixBlend.setup ? bone.data.rotation : bone.rotation;
var total = 0, diff = r2 - r1; var total = 0, diff = r2 - r1;
diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360;
if (diff == 0) { if (diff == 0) {
total = timelinesRotation[i]; total = timelinesRotation[i];
} }
else { else {
diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360;
var lastTotal = 0, lastDiff = 0; var lastTotal = 0, lastDiff = 0;
if (firstFrame) { if (firstFrame) {
lastTotal = 0; lastTotal = 0;
@ -2634,6 +2634,7 @@ var spine;
var IkConstraint = (function () { var IkConstraint = (function () {
function IkConstraint(data, skeleton) { function IkConstraint(data, skeleton) {
this.bendDirection = 0; this.bendDirection = 0;
this.compress = false;
this.stretch = false; this.stretch = false;
this.mix = 1; this.mix = 1;
if (data == null) if (data == null)
@ -2643,6 +2644,7 @@ var spine;
this.data = data; this.data = data;
this.mix = data.mix; this.mix = data.mix;
this.bendDirection = data.bendDirection; this.bendDirection = data.bendDirection;
this.compress = data.compress;
this.stretch = data.stretch; this.stretch = data.stretch;
this.bones = new Array(); this.bones = new Array();
for (var i = 0; i < data.bones.length; i++) for (var i = 0; i < data.bones.length; i++)
@ -2660,14 +2662,14 @@ var spine;
var bones = this.bones; var bones = this.bones;
switch (bones.length) { switch (bones.length) {
case 1: case 1:
this.apply1(bones[0], target.worldX, target.worldY, this.stretch, this.mix); this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix);
break; break;
case 2: case 2:
this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.mix); this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.mix);
break; break;
} }
}; };
IkConstraint.prototype.apply1 = function (bone, targetX, targetY, stretch, alpha) { IkConstraint.prototype.apply1 = function (bone, targetX, targetY, compress, stretch, uniform, alpha) {
if (!bone.appliedValid) if (!bone.appliedValid)
bone.updateAppliedTransform(); bone.updateAppliedTransform();
var p = bone.parent; var p = bone.parent;
@ -2681,13 +2683,17 @@ var spine;
rotationIK -= 360; rotationIK -= 360;
else if (rotationIK < -180) else if (rotationIK < -180)
rotationIK += 360; rotationIK += 360;
var sx = bone.ascaleX; var sx = bone.ascaleX, sy = bone.ascaleY;
if (stretch) { if (compress || stretch) {
var b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty); var b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty);
if (dd > b && b > 0.0001) if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) {
sx *= (dd / b - 1) * alpha + 1; var s = (dd / b - 1) * alpha + 1;
sx *= s;
if (uniform)
sy *= s;
} }
bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, bone.ascaleY, bone.ashearX, bone.ashearY); }
bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY);
}; };
IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, stretch, alpha) { IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, stretch, alpha) {
if (alpha == 0) { if (alpha == 0) {
@ -2835,7 +2841,9 @@ var spine;
this.order = 0; this.order = 0;
this.bones = new Array(); this.bones = new Array();
this.bendDirection = 1; this.bendDirection = 1;
this.compress = false;
this.stretch = false; this.stretch = false;
this.uniform = false;
this.mix = 1; this.mix = 1;
this.name = name; this.name = name;
} }
@ -3620,9 +3628,10 @@ var spine;
var ikConstraints = this.ikConstraints; var ikConstraints = this.ikConstraints;
for (var i = 0, n = ikConstraints.length; i < n; i++) { for (var i = 0, n = ikConstraints.length; i < n; i++) {
var constraint = ikConstraints[i]; var constraint = ikConstraints[i];
constraint.bendDirection = constraint.data.bendDirection;
constraint.stretch = constraint.data.stretch;
constraint.mix = constraint.data.mix; constraint.mix = constraint.data.mix;
constraint.bendDirection = constraint.data.bendDirection;
constraint.compress = constraint.data.compress;
constraint.stretch = constraint.data.stretch;
} }
var transformConstraints = this.transformConstraints; var transformConstraints = this.transformConstraints;
for (var i = 0, n = transformConstraints.length; i < n; i++) { for (var i = 0, n = transformConstraints.length; i < n; i++) {
@ -4490,9 +4499,11 @@ var spine;
data.target = skeletonData.findBone(targetName); data.target = skeletonData.findBone(targetName);
if (data.target == null) if (data.target == null)
throw new Error("IK target bone not found: " + targetName); throw new Error("IK target bone not found: " + targetName);
data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1;
data.stretch = this.getValue(constraintMap, "stretch", false);
data.mix = this.getValue(constraintMap, "mix", 1); data.mix = this.getValue(constraintMap, "mix", 1);
data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1;
data.compress = this.getValue(constraintMap, "compress", false);
data.stretch = this.getValue(constraintMap, "stretch", false);
data.uniform = this.getValue(constraintMap, "uniform", false);
skeletonData.ikConstraints.push(data); skeletonData.ikConstraints.push(data);
} }
} }
@ -4862,7 +4873,7 @@ var spine;
var frameIndex = 0; var frameIndex = 0;
for (var i = 0; i < constraintMap.length; i++) { for (var i = 0; i < constraintMap.length; i++) {
var valueMap = constraintMap[i]; var valueMap = constraintMap[i];
timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "bendPositive", true) ? 1 : -1, this.getValue(valueMap, "stretch", false)); timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "bendPositive", true) ? 1 : -1, this.getValue(valueMap, "compress", false), this.getValue(valueMap, "stretch", false));
this.readCurve(valueMap, timeline, frameIndex); this.readCurve(valueMap, timeline, frameIndex);
frameIndex++; frameIndex++;
} }

File diff suppressed because one or more lines are too long

View File

@ -1037,12 +1037,12 @@ module spine {
} }
export class IkConstraintTimeline extends CurveTimeline { export class IkConstraintTimeline extends CurveTimeline {
static ENTRIES = 4; static ENTRIES = 5;
static PREV_TIME = -4; static PREV_MIX = -3; static PREV_BEND_DIRECTION = -2; static PREV_STRETCH = -1; static PREV_TIME = -5; static PREV_MIX = -4; static PREV_BEND_DIRECTION = -3; static PREV_COMPRESS = -2; static PREV_STRETCH = -1;
static MIX = 1; static BEND_DIRECTION = 2; static STRETCH = 3; static MIX = 1; static BEND_DIRECTION = 2; static COMPRESS = 3; static STRETCH = 4;
ikConstraintIndex: number; ikConstraintIndex: number;
frames: ArrayLike<number>; // time, mix, bendDirection, ... frames: ArrayLike<number>; // time, mix, bendDirection, compress, stretch, ...
constructor (frameCount: number) { constructor (frameCount: number) {
super(frameCount); super(frameCount);
@ -1054,11 +1054,12 @@ module spine {
} }
/** Sets the time, mix and bend direction of the specified keyframe. */ /** Sets the time, mix and bend direction of the specified keyframe. */
setFrame (frameIndex: number, time: number, mix: number, bendDirection: number, stretch: boolean) { setFrame (frameIndex: number, time: number, mix: number, bendDirection: number, compress: boolean, stretch: boolean) {
frameIndex *= IkConstraintTimeline.ENTRIES; frameIndex *= IkConstraintTimeline.ENTRIES;
this.frames[frameIndex] = time; this.frames[frameIndex] = time;
this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; this.frames[frameIndex + IkConstraintTimeline.MIX] = mix;
this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection;
this.frames[frameIndex + IkConstraintTimeline.COMPRESS] = compress ? 1 : 0;
this.frames[frameIndex + IkConstraintTimeline.STRETCH] = stretch ? 1 : 0; this.frames[frameIndex + IkConstraintTimeline.STRETCH] = stretch ? 1 : 0;
} }

View File

@ -304,10 +304,10 @@ module spine {
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
let r1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation; let r1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation;
let total = 0, diff = r2 - r1; let total = 0, diff = r2 - r1;
diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360;
if (diff == 0) { if (diff == 0) {
total = timelinesRotation[i]; total = timelinesRotation[i];
} else { } else {
diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360;
let lastTotal = 0, lastDiff = 0; let lastTotal = 0, lastDiff = 0;
if (firstFrame) { if (firstFrame) {
lastTotal = 0; lastTotal = 0;

View File

@ -34,6 +34,7 @@ module spine {
bones: Array<Bone>; bones: Array<Bone>;
target: Bone; target: Bone;
bendDirection = 0; bendDirection = 0;
compress = false;
stretch = false; stretch = false;
mix = 1; mix = 1;
@ -43,6 +44,7 @@ module spine {
this.data = data; this.data = data;
this.mix = data.mix; this.mix = data.mix;
this.bendDirection = data.bendDirection; this.bendDirection = data.bendDirection;
this.compress = data.compress;
this.stretch = data.stretch; this.stretch = data.stretch;
this.bones = new Array<Bone>(); this.bones = new Array<Bone>();
@ -64,7 +66,7 @@ module spine {
let bones = this.bones; let bones = this.bones;
switch (bones.length) { switch (bones.length) {
case 1: case 1:
this.apply1(bones[0], target.worldX, target.worldY, this.stretch, this.mix); this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix);
break; break;
case 2: case 2:
this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.mix); this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.mix);
@ -74,7 +76,7 @@ module spine {
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world /** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
* coordinate system. */ * coordinate system. */
apply1 (bone: Bone, targetX: number, targetY: number, stretch: boolean, alpha: number) { apply1 (bone: Bone, targetX: number, targetY: number, compress: boolean, stretch: boolean, uniform: boolean, alpha: number) {
if (!bone.appliedValid) bone.updateAppliedTransform(); if (!bone.appliedValid) bone.updateAppliedTransform();
let p = bone.parent; let p = bone.parent;
let id = 1 / (p.a * p.d - p.b * p.c); let id = 1 / (p.a * p.d - p.b * p.c);
@ -85,12 +87,16 @@ module spine {
if (rotationIK > 180) if (rotationIK > 180)
rotationIK -= 360; rotationIK -= 360;
else if (rotationIK < -180) rotationIK += 360; else if (rotationIK < -180) rotationIK += 360;
let sx = bone.ascaleX; let sx = bone.ascaleX, sy = bone.ascaleY;
if (stretch) { if (compress || stretch) {
let b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty); let b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty);
if (dd > b && b > 0.0001) sx *= (dd / b - 1) * alpha + 1; if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) {
let s = (dd / b - 1) * alpha + 1;
sx *= s;
if (uniform) sy *= s;
} }
bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, bone.ascaleY, bone.ashearX, }
bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX,
bone.ashearY); bone.ashearY);
} }

View File

@ -35,7 +35,9 @@ module spine {
bones = new Array<BoneData>(); bones = new Array<BoneData>();
target: BoneData; target: BoneData;
bendDirection = 1; bendDirection = 1;
compress = false;
stretch = false; stretch = false;
uniform = false;
mix = 1; mix = 1;
constructor (name: string) { constructor (name: string) {

View File

@ -286,9 +286,10 @@ module spine {
let ikConstraints = this.ikConstraints; let ikConstraints = this.ikConstraints;
for (let i = 0, n = ikConstraints.length; i < n; i++) { for (let i = 0, n = ikConstraints.length; i < n; i++) {
let constraint = ikConstraints[i]; let constraint = ikConstraints[i];
constraint.bendDirection = constraint.data.bendDirection;
constraint.stretch = constraint.data.stretch;
constraint.mix = constraint.data.mix; constraint.mix = constraint.data.mix;
constraint.bendDirection = constraint.data.bendDirection;
constraint.compress = constraint.data.compress;
constraint.stretch = constraint.data.stretch;
} }
let transformConstraints = this.transformConstraints; let transformConstraints = this.transformConstraints;

View File

@ -123,9 +123,11 @@ module spine {
data.target = skeletonData.findBone(targetName); data.target = skeletonData.findBone(targetName);
if (data.target == null) throw new Error("IK target bone not found: " + targetName); if (data.target == null) throw new Error("IK target bone not found: " + targetName);
data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1;
data.stretch = this.getValue(constraintMap, "stretch", false);
data.mix = this.getValue(constraintMap, "mix", 1); data.mix = this.getValue(constraintMap, "mix", 1);
data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1;
data.compress = this.getValue(constraintMap, "compress", false);
data.stretch = this.getValue(constraintMap, "stretch", false);
data.uniform = this.getValue(constraintMap, "uniform", false);
skeletonData.ikConstraints.push(data); skeletonData.ikConstraints.push(data);
} }
@ -521,7 +523,7 @@ module spine {
for (let i = 0; i < constraintMap.length; i++) { for (let i = 0; i < constraintMap.length; i++) {
let valueMap = constraintMap[i]; let valueMap = constraintMap[i];
timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1),
this.getValue(valueMap, "bendPositive", true) ? 1 : -1, this.getValue(valueMap, "stretch", false)); this.getValue(valueMap, "bendPositive", true) ? 1 : -1, this.getValue(valueMap, "compress", false), this.getValue(valueMap, "stretch", false));
this.readCurve(valueMap, timeline, frameIndex); this.readCurve(valueMap, timeline, frameIndex);
frameIndex++; frameIndex++;
} }