Merge remote-tracking branch 'origin/3.7-beta' into 3.7-beta

This commit is contained in:
Nathan Sweet 2017-10-30 13:58:31 +01:00
commit 070b3c98d8
7 changed files with 10865 additions and 10598 deletions

View File

@ -85,6 +85,7 @@
* Added support for two color tinting. All base materials, e.g. SpineUnlitNormalMaterial, now do proper two color tinting. No material parameters have changed.
* Updated to Unreal Engine 4.16.1. Note that 4.16 has a regression which will make it impossible to compile plain .c files!
* spine-c is now exposed from the plugin shared library on Windows via __declspec.
* Updated to Unreal Engine 4.18
## C#
* **Breaking changes**

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

@ -42,7 +42,7 @@ module spine {
this.duration = duration;
}
apply (skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
if (skeleton == null) throw new Error("skeleton cannot be null.");
if (loop && this.duration != 0) {
@ -52,7 +52,7 @@ module spine {
let timelines = this.timelines;
for (let i = 0, n = timelines.length; i < n; i++)
timelines[i].apply(skeleton, lastTime, time, events, alpha, pose, direction);
timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction);
}
static binarySearch (values: ArrayLike<number>, target: number, step: number = 1) {
@ -78,14 +78,15 @@ module spine {
}
export interface Timeline {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection): void;
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
getPropertyId (): number;
}
export enum MixPose {
export enum MixBlend {
setup,
current,
currentLayered
first,
replace,
add
}
export enum MixDirection {
@ -188,7 +189,7 @@ module spine {
return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
}
abstract apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection): void;
abstract apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
}
export class RotateTimeline extends CurveTimeline {
@ -215,29 +216,33 @@ module spine {
this.frames[frameIndex + RotateTimeline.ROTATION] = degrees;
}
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let bone = skeleton.bones[this.boneIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
bone.rotation = bone.data.rotation;
return;
case MixPose.current:
case MixBlend.first:
let r = bone.data.rotation - bone.rotation;
r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
bone.rotation += r * alpha;
bone.rotation += (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * alpha;
}
return;
}
if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { // Time is after last frame.
if (pose == MixPose.setup)
bone.rotation = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] * alpha;
else {
let r = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation;
var r = frames[frames.length + RotateTimeline.PREV_ROTATION];
switch (blend) {
case MixBlend.setup:
bone.rotation = bone.data.rotation + r * alpha;
break;
case MixBlend.first:
case MixBlend.replace:
r += bone.data.rotation - bone.rotation;
r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; // Wrap within -180 and 180.
case MixBlend.add:
bone.rotation += r * alpha;
}
return;
@ -250,16 +255,17 @@ module spine {
let percent = this.getCurvePercent((frame >> 1) - 1,
1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime));
let r = frames[frame + RotateTimeline.ROTATION] - prevRotation;
r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
r = prevRotation + r * percent;
if (pose == MixPose.setup) {
r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
bone.rotation = bone.data.rotation + r * alpha;
} else {
r = bone.data.rotation + r - bone.rotation;
r -= (16384 - ((16384.499999999996 - r / 360) |0)) * 360;
bone.rotation += r * alpha;
r = frames[frame + RotateTimeline.ROTATION] - prevRotation;
r = prevRotation + (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * percent;
switch (blend) {
case MixBlend.setup:
bone.rotation = bone.data.rotation + (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * alpha;
break;
case MixBlend.first:
case MixBlend.replace:
r += bone.data.rotation - bone.rotation;
case MixBlend.add:
bone.rotation += (r - (16384 - ((16384.499999999996 - r / 360) | 0)) * 360) * alpha;
}
}
}
@ -289,17 +295,17 @@ module spine {
this.frames[frameIndex + TranslateTimeline.Y] = y;
}
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let bone = skeleton.bones[this.boneIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
bone.x = bone.data.x;
bone.y = bone.data.y;
return;
case MixPose.current:
case MixBlend.first:
bone.x += (bone.data.x - bone.x) * alpha;
bone.y += (bone.data.y - bone.y) * alpha;
}
@ -322,12 +328,19 @@ module spine {
x += (frames[frame + TranslateTimeline.X] - x) * percent;
y += (frames[frame + TranslateTimeline.Y] - y) * percent;
}
if (pose == MixPose.setup) {
switch (blend) {
case MixBlend.setup:
bone.x = bone.data.x + x * alpha;
bone.y = bone.data.y + y * alpha;
} else {
break;
case MixBlend.first:
case MixBlend.replace:
bone.x += (bone.data.x + x - bone.x) * alpha;
bone.y += (bone.data.y + y - bone.y) * alpha;
break;
case MixBlend.add:
bone.x += x * alpha;
bone.y += y * alpha;
}
}
}
@ -341,17 +354,17 @@ module spine {
return (TimelineType.scale << 24) + this.boneIndex;
}
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let bone = skeleton.bones[this.boneIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
bone.scaleX = bone.data.scaleX;
bone.scaleY = bone.data.scaleY;
return;
case MixPose.current:
case MixBlend.first:
bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
}
@ -375,27 +388,56 @@ module spine {
y = (y + (frames[frame + ScaleTimeline.Y] - y) * percent) * bone.data.scaleY;
}
if (alpha == 1) {
bone.scaleX = x;
bone.scaleY = y;
if (blend == MixBlend.add) {
bone.scaleX += x - bone.data.scaleX;
bone.scaleY += y - bone.data.scaleY;
} else {
bone.scaleX = x;
bone.scaleY = y;
}
} else {
let bx = 0, by = 0;
if (pose == MixPose.setup) {
bx = bone.data.scaleX;
by = bone.data.scaleY;
} else {
bx = bone.scaleX;
by = bone.scaleY;
}
// Mixing out uses sign of setup or current pose, else use sign of key.
if (direction == MixDirection.out) {
x = Math.abs(x) * MathUtils.signum(bx);
y = Math.abs(y) * MathUtils.signum(by);
switch (blend) {
case MixBlend.setup:
bx = bone.data.scaleX;
by = bone.data.scaleY;
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
break;
case MixBlend.first:
case MixBlend.replace:
bx = bone.scaleX;
by = bone.scaleY;
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
break;
case MixBlend.add:
bx = bone.scaleX;
by = bone.scaleY;
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bone.data.scaleX) * alpha;
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - bone.data.scaleY) * alpha;
}
} else {
bx = Math.abs(bx) * MathUtils.signum(x);
by = Math.abs(by) * MathUtils.signum(y);
switch (blend) {
case MixBlend.setup:
bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);
by = Math.abs(bone.data.scaleY) * MathUtils.signum(y);
bone.scaleX = bx + (x - bx) * alpha;
bone.scaleY = by + (y - by) * alpha;
break;
case MixBlend.first:
case MixBlend.replace:
bone.scaleX += (x - bone.scaleX * MathUtils.signum(x)) * alpha;
bone.scaleY += (y - bone.scaleY * MathUtils.signum(y)) * alpha;
break;
case MixBlend.add:
bx = MathUtils.signum(x);
by = MathUtils.signum(y);
bone.scaleX = Math.abs(bone.scaleX) * bx + (x - Math.abs(bone.data.scaleX) * bx) * alpha;
bone.scaleY = Math.abs(bone.scaleY) * by + (y - Math.abs(bone.data.scaleY) * by) * alpha;
}
}
bone.scaleX = bx + (x - bx) * alpha;
bone.scaleY = by + (y - by) * alpha;
}
}
}
@ -409,17 +451,17 @@ module spine {
return (TimelineType.shear << 24) + this.boneIndex;
}
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let bone = skeleton.bones[this.boneIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
bone.shearX = bone.data.shearX;
bone.shearY = bone.data.shearY;
return;
case MixPose.current:
case MixBlend.first:
bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
}
@ -442,12 +484,19 @@ module spine {
x = x + (frames[frame + ShearTimeline.X] - x) * percent;
y = y + (frames[frame + ShearTimeline.Y] - y) * percent;
}
if (pose == MixPose.setup) {
switch (blend) {
case MixBlend.setup:
bone.shearX = bone.data.shearX + x * alpha;
bone.shearY = bone.data.shearY + y * alpha;
} else {
break;
case MixBlend.first:
case MixBlend.replace:
bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
break;
case MixBlend.add:
bone.shearX += x * alpha;
bone.shearY += y * alpha;
}
}
}
@ -479,15 +528,15 @@ module spine {
this.frames[frameIndex + ColorTimeline.A] = a;
}
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let slot = skeleton.slots[this.slotIndex];
let frames = this.frames;
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
slot.color.setFromColor(slot.data.color);
return;
case MixPose.current:
case MixBlend.first:
let color = slot.color, setup = slot.data.color;
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
(setup.a - color.a) * alpha);
@ -522,7 +571,7 @@ module spine {
slot.color.set(r, g, b, a);
else {
let color = slot.color;
if (pose == MixPose.setup) color.setFromColor(slot.data.color);
if (blend == MixBlend.setup) color.setFromColor(slot.data.color);
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
}
}
@ -559,16 +608,16 @@ module spine {
this.frames[frameIndex + TwoColorTimeline.B2] = b2;
}
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let slot = skeleton.slots[this.slotIndex];
let frames = this.frames;
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
slot.color.setFromColor(slot.data.color);
slot.darkColor.setFromColor(slot.data.darkColor);
return;
case MixPose.current:
case MixBlend.setup:
let light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor;
light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha,
(setupLight.a - light.a) * alpha);
@ -614,7 +663,7 @@ module spine {
slot.darkColor.set(r2, g2, b2, 1);
} else {
let light = slot.color, dark = slot.darkColor;
if (pose == MixPose.setup) {
if (blend == MixBlend.setup) {
light.setFromColor(slot.data.color);
dark.setFromColor(slot.data.darkColor);
}
@ -648,9 +697,9 @@ module spine {
this.attachmentNames[frameIndex] = attachmentName;
}
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let slot = skeleton.slots[this.slotIndex];
if (direction == MixDirection.out && pose == MixPose.setup) {
if (direction == MixDirection.out && blend == MixBlend.setup) {
let attachmentName = slot.data.attachmentName;
slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
return;
@ -658,7 +707,7 @@ module spine {
let frames = this.frames;
if (time < frames[0]) {
if (pose == MixPose.setup) {
if (blend == MixBlend.setup) {
let attachmentName = slot.data.attachmentName;
slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
}
@ -702,25 +751,25 @@ module spine {
this.frameVertices[frameIndex] = vertices;
}
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let slot: Slot = skeleton.slots[this.slotIndex];
let slotAttachment: Attachment = slot.getAttachment();
if (!(slotAttachment instanceof VertexAttachment) || !(<VertexAttachment>slotAttachment).applyDeform(this.attachment)) return;
let verticesArray: Array<number> = slot.attachmentVertices;
if (verticesArray.length == 0) alpha = 1;
if (verticesArray.length == 0) blend = MixBlend.setup;
let frameVertices = this.frameVertices;
let vertexCount = frameVertices[0].length;
let vertexCount = frameVertices[0].length;
let frames = this.frames;
if (time < frames[0]) {
let vertexAttachment = <VertexAttachment>slotAttachment;
switch (pose) {
case MixPose.setup:
verticesArray.length = 0;
switch (blend) {
case MixBlend.setup:
verticesArray.length = 0;
return;
case MixPose.current:
case MixBlend.first:
if (alpha == 1) {
verticesArray.length = 0;
break;
@ -745,24 +794,47 @@ module spine {
if (time >= frames[frames.length - 1]) { // Time is after last frame.
let lastVertices = frameVertices[frames.length - 1];
if (alpha == 1) {
Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount);
} else if (pose == MixPose.setup) {
let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
let setupVertices = vertexAttachment.vertices;
for (let i = 0; i < vertexCount; i++) {
let setup = setupVertices[i];
vertices[i] = setup + (lastVertices[i] - setup) * alpha;
if (blend == MixBlend.add) {
let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
let setupVertices = vertexAttachment.vertices;
for (let i = 0; i < vertexCount; i++) {
vertices[i] += lastVertices[i] - setupVertices[i];
}
} else {
// Weighted deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++)
vertices[i] += lastVertices[i];
}
} else {
// Weighted deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++)
vertices[i] = lastVertices[i] * alpha;
Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount);
}
} else {
for (let i = 0; i < vertexCount; i++)
} else {
switch (blend) {
case MixBlend.setup:
let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
let setupVertices = vertexAttachment.vertices;
for (let i = 0; i < vertexCount; i++) {
let setup = setupVertices[i];
vertices[i] = setup + (lastVertices[i] - setup) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++)
vertices[i] = lastVertices[i] * alpha;
}
break;
case MixBlend.first:
case MixBlend.replace:
for (let i = 0; i < vertexCount; i++)
vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
case MixBlend.add:
for (let i = 0; i < vertexCount; i++)
vertices[i] += lastVertices[i] * alpha;
}
}
return;
}
@ -775,31 +847,71 @@ module spine {
let percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));
if (alpha == 1) {
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] = prev + (nextVertices[i] - prev) * percent;
}
} else if (pose == MixPose.setup) {
let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
let setupVertices = vertexAttachment.vertices;
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i], setup = setupVertices[i];
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
if (blend == MixBlend.add) {
let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
let setupVertices = vertexAttachment.vertices;
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];
}
} else {
// Weighted deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] += prev + (nextVertices[i] - prev) * percent;
}
}
} else {
// Weighted deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
vertices[i] = prev + (nextVertices[i] - prev) * percent;
}
}
} else {
// Vertex positions or deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
switch (blend) {
case MixBlend.setup: {
let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
let setupVertices = vertexAttachment.vertices;
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i], setup = setupVertices[i];
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
}
}
break;
}
case MixBlend.first:
case MixBlend.replace:
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
}
break;
case MixBlend.add:
let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
let setupVertices = vertexAttachment.vertices;
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (let i = 0; i < vertexCount; i++) {
let prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
}
}
}
}
}
@ -829,13 +941,13 @@ module spine {
}
/** Fires events for frames > lastTime and <= time. */
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
if (firedEvents == null) return;
let frames = this.frames;
let frameCount = this.frames.length;
if (lastTime > time) { // Fire events after last time for looped animations.
this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, pose, direction);
this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction);
lastTime = -1;
} else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame.
return;
@ -881,17 +993,17 @@ module spine {
this.drawOrders[frameIndex] = drawOrder;
}
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let drawOrder: Array<Slot> = skeleton.drawOrder;
let slots: Array<Slot> = skeleton.slots;
if (direction == MixDirection.out && pose == MixPose.setup) {
if (direction == MixDirection.out && blend == MixBlend.setup) {
Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
return;
}
let frames = this.frames;
if (time < frames[0]) {
if (pose == MixPose.setup) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
if (blend == MixBlend.setup) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
return;
}
@ -936,16 +1048,16 @@ module spine {
this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection;
}
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let constraint: IkConstraint = skeleton.ikConstraints[this.ikConstraintIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
constraint.mix = constraint.data.mix;
constraint.bendDirection = constraint.data.bendDirection;
return;
case MixPose.current:
case MixBlend.first:
constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
constraint.bendDirection = constraint.data.bendDirection;
}
@ -953,7 +1065,7 @@ module spine {
}
if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { // Time is after last frame.
if (pose == MixPose.setup) {
if (blend == MixBlend.setup) {
constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha;
constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection
: frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION];
@ -971,7 +1083,7 @@ module spine {
let percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1,
1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime));
if (pose == MixPose.setup) {
if (blend == MixBlend.setup) {
constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha;
constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION];
} else {
@ -1008,20 +1120,20 @@ module spine {
this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix;
}
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let constraint: TransformConstraint = skeleton.transformConstraints[this.transformConstraintIndex];
if (time < frames[0]) {
let data = constraint.data;
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
constraint.rotateMix = data.rotateMix;
constraint.translateMix = data.translateMix;
constraint.scaleMix = data.scaleMix;
constraint.shearMix = data.shearMix;
return;
case MixPose.current:
case MixBlend.setup:
constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha;
constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha;
constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha;
@ -1053,7 +1165,7 @@ module spine {
scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent;
shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent;
}
if (pose == MixPose.setup) {
if (blend == MixBlend.setup) {
let data = constraint.data;
constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha;
constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha;
@ -1093,15 +1205,15 @@ module spine {
this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value;
}
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let constraint: PathConstraint = skeleton.pathConstraints[this.pathConstraintIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
constraint.position = constraint.data.position;
return;
case MixPose.current:
case MixBlend.first:
constraint.position += (constraint.data.position - constraint.position) * alpha;
}
return;
@ -1120,7 +1232,7 @@ module spine {
position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent;
}
if (pose == MixPose.setup)
if (blend == MixBlend.setup)
constraint.position = constraint.data.position + (position - constraint.data.position) * alpha;
else
constraint.position += (position - constraint.position) * alpha;
@ -1136,15 +1248,15 @@ module spine {
return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex;
}
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let constraint: PathConstraint = skeleton.pathConstraints[this.pathConstraintIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
constraint.spacing = constraint.data.spacing;
return;
case MixPose.current:
case MixBlend.first:
constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha;
}
return;
@ -1164,7 +1276,7 @@ module spine {
spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent;
}
if (pose == MixPose.setup)
if (blend == MixBlend.setup)
constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha;
else
constraint.spacing += (spacing - constraint.spacing) * alpha;
@ -1197,17 +1309,17 @@ module spine {
this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix;
}
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, pose: MixPose, direction: MixDirection) {
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
let frames = this.frames;
let constraint: PathConstraint = skeleton.pathConstraints[this.pathConstraintIndex];
if (time < frames[0]) {
switch (pose) {
case MixPose.setup:
switch (blend) {
case MixBlend.setup:
constraint.rotateMix = constraint.data.rotateMix;
constraint.translateMix = constraint.data.translateMix;
return;
case MixPose.current:
case MixBlend.first:
constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha;
constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha;
}
@ -1231,7 +1343,7 @@ module spine {
translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent;
}
if (pose == MixPose.setup) {
if (blend == MixBlend.setup) {
constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha;
constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha;
} else {

View File

@ -144,12 +144,12 @@ module spine {
let current = tracks[i];
if (current == null || current.delay > 0) continue;
applied = true;
let currentPose = i == 0 ? MixPose.current : MixPose.currentLayered;
let blend: MixBlend = i == 0 ? MixBlend.first : current.mixBlend;
// Apply mixing from entries first.
let mix = current.alpha;
if (current.mixingFrom != null)
mix *= this.applyMixingFrom(current, skeleton, currentPose);
mix *= this.applyMixingFrom(current, skeleton, blend);
else if (current.trackTime >= current.trackEnd && current.next == null)
mix = 0;
@ -157,9 +157,9 @@ module spine {
let animationLast = current.animationLast, animationTime = current.getAnimationTime();
let timelineCount = current.animation.timelines.length;
let timelines = current.animation.timelines;
if (mix == 1) {
if (mix == 1 || blend == MixBlend.add) {
for (let ii = 0; ii < timelineCount; ii++)
timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, MixPose.setup, MixDirection.in);
timelines[ii].apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection.in);
} else {
let timelineData = current.timelineData;
@ -169,11 +169,11 @@ module spine {
for (let ii = 0; ii < timelineCount; ii++) {
let timeline = timelines[ii];
let pose = timelineData[ii] >= AnimationState.FIRST ? MixPose.setup : currentPose;
let timelineBlend = timelineData[ii] == AnimationState.SUBSEQUENT ? blend : MixBlend.setup;
if (timeline instanceof RotateTimeline) {
this.applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame);
this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
} else
timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.in);
timeline.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, MixDirection.in);
}
}
this.queueEvents(current, animationTime);
@ -186,17 +186,18 @@ module spine {
return applied;
}
applyMixingFrom (to: TrackEntry, skeleton: Skeleton, currentPose: MixPose) {
applyMixingFrom (to: TrackEntry, skeleton: Skeleton, blend: MixBlend) {
let from = to.mixingFrom;
if (from.mixingFrom != null) this.applyMixingFrom(from, skeleton, currentPose);
if (from.mixingFrom != null) this.applyMixingFrom(from, skeleton, blend);
let mix = 0;
if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes.
mix = 1;
currentPose = MixPose.setup;
if (blend == MixBlend.first) blend = MixBlend.setup;
} else {
mix = to.mixTime / to.mixDuration;
if (mix > 1) mix = 1;
if (blend != MixBlend.first) blend = from.mixBlend;
}
let events = mix < from.eventThreshold ? this.events : null;
@ -204,45 +205,50 @@ module spine {
let animationLast = from.animationLast, animationTime = from.getAnimationTime();
let timelineCount = from.animation.timelines.length;
let timelines = from.animation.timelines;
let timelineData = from.timelineData;
let timelineDipMix = from.timelineDipMix;
let alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix);
if (blend == MixBlend.add) {
for (var i = 0; i < timelineCount; i++)
timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.out);
} else {
let timelineData = from.timelineData;
let timelineDipMix = from.timelineDipMix;
let firstFrame = from.timelinesRotation.length == 0;
if (firstFrame) Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null);
let timelinesRotation = from.timelinesRotation;
let firstFrame = from.timelinesRotation.length == 0;
if (firstFrame) Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null);
let timelinesRotation = from.timelinesRotation;
let pose: MixPose;
let alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha = 0;
from.totalAlpha = 0;
for (var i = 0; i < timelineCount; i++) {
let timeline = timelines[i];
switch (timelineData[i]) {
case AnimationState.SUBSEQUENT:
if (!attachments && timeline instanceof AttachmentTimeline) continue;
if (!drawOrder && timeline instanceof DrawOrderTimeline) continue;
pose = currentPose;
alpha = alphaMix;
break;
case AnimationState.FIRST:
pose = MixPose.setup
alpha = alphaMix;
break;
case AnimationState.DIP:
pose = MixPose.setup;
alpha = alphaDip;
break;
default:
pose = MixPose.setup;
alpha = alphaDip;
let dipMix = timelineDipMix[i];
alpha *= Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
break;
}
from.totalAlpha += alpha;
if (timeline instanceof RotateTimeline)
this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame);
else {
timeline.apply(skeleton, animationLast, animationTime, events, alpha, pose, MixDirection.out);
from.totalAlpha = 0;
for (var i = 0; i < timelineCount; i++) {
let timeline = timelines[i];
var timelineBlend: MixBlend;
var alpha = 0;
switch (timelineData[i]) {
case AnimationState.SUBSEQUENT:
if (!attachments && timeline instanceof AttachmentTimeline) continue;
if (!drawOrder && timeline instanceof DrawOrderTimeline) continue;
timelineBlend = blend;
alpha = alphaMix;
break;
case AnimationState.FIRST:
timelineBlend = MixBlend.setup;
alpha = alphaMix;
break;
case AnimationState.DIP:
timelineBlend = MixBlend.setup;
alpha = alphaDip;
break;
default:
timelineBlend = MixBlend.setup;
let dipMix = timelineDipMix[i];
alpha = alphaDip * Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
break;
}
from.totalAlpha += alpha;
if (timeline instanceof RotateTimeline)
this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame);
else {
timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, MixDirection.out);
}
}
}
@ -254,13 +260,13 @@ module spine {
return mix;
}
applyRotateTimeline (timeline: Timeline, skeleton: Skeleton, time: number, alpha: number, pose: MixPose,
applyRotateTimeline (timeline: Timeline, skeleton: Skeleton, time: number, alpha: number, blend: MixBlend,
timelinesRotation: Array<number>, i: number, firstFrame: boolean) {
if (firstFrame) timelinesRotation[i] = 0;
if (alpha == 1) {
timeline.apply(skeleton, 0, time, null, 1, pose, MixDirection.in);
timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.in);
return;
}
@ -268,7 +274,7 @@ module spine {
let frames = rotateTimeline.frames;
let bone = skeleton.bones[rotateTimeline.boneIndex];
if (time < frames[0]) {
if (pose == MixPose.setup) bone.rotation = bone.data.rotation;
if (blend == MixBlend.setup) bone.rotation = bone.data.rotation;
return;
}
@ -290,7 +296,7 @@ module spine {
}
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
let r1 = pose == MixPose.setup ? bone.data.rotation : bone.rotation;
let r1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation;
let total = 0, diff = r2 - r1;
if (diff == 0) {
total = timelinesRotation[i];
@ -544,7 +550,7 @@ module spine {
for (var i = 0, n = this.tracks.length; i < n; i++) {
let entry = this.tracks[i];
if (entry != null) entry.setTimelineData(null, mixingTo, propertyIDs);
if (entry != null && entry.mixBlend != MixBlend.add) entry.setTimelineData(null, mixingTo, propertyIDs);
}
}
@ -583,6 +589,7 @@ module spine {
animationStart: number; animationEnd: number; animationLast: number; nextAnimationLast: number;
delay: number; trackTime: number; trackLast: number; nextTrackLast: number; trackEnd: number; timeScale: number;
alpha: number; mixTime: number; mixDuration: number; interruptAlpha: number; totalAlpha: number;
mixBlend = MixBlend.replace;
timelineData = new Array<number>();
timelineDipMix = new Array<TrackEntry>();
timelinesRotation = new Array<number>();

View File

@ -25,7 +25,11 @@ void FRuntimeMeshComponentDetails::CustomizeDetails( IDetailLayoutBuilder& Detai
const FText ConvertToStaticMeshText = LOCTEXT("ConvertToStaticMesh", "Create StaticMesh");
// Cache set of selected things
#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 18
SelectedObjectsList = DetailBuilder.GetDetailsView().GetSelectedObjects();
#else
SelectedObjectsList = DetailBuilder.GetDetailsView()->GetSelectedObjects();
#endif
RuntimeMeshCategory.AddCustomRow(ConvertToStaticMeshText, false)
.NameContent()