[as3] Ported additive blending. See #1029, #1060

This commit is contained in:
badlogic 2018-01-23 15:45:33 +01:00
parent b7e712d3ca
commit 6a556de014
29 changed files with 456 additions and 222 deletions

View File

@ -6,8 +6,32 @@ encoding//src/spine/SkeletonJson.as=UTF-8
encoding//src/spine/Triangulator.as=UTF-8 encoding//src/spine/Triangulator.as=UTF-8
encoding//src/spine/Vertex.as=UTF-8 encoding//src/spine/Vertex.as=UTF-8
encoding//src/spine/VertexEffect.as=UTF-8 encoding//src/spine/VertexEffect.as=UTF-8
encoding//src/spine/animation/Animation.as=UTF-8
encoding//src/spine/animation/AnimationState.as=UTF-8
encoding//src/spine/animation/AnimationStateData.as=UTF-8
encoding//src/spine/animation/AttachmentTimeline.as=UTF-8
encoding//src/spine/animation/ColorTimeline.as=UTF-8
encoding//src/spine/animation/CurveTimeline.as=UTF-8
encoding//src/spine/animation/DeformTimeline.as=UTF-8
encoding//src/spine/animation/DrawOrderTimeline.as=UTF-8
encoding//src/spine/animation/EventQueue.as=UTF-8
encoding//src/spine/animation/EventTimeline.as=UTF-8
encoding//src/spine/animation/EventType.as=UTF-8
encoding//src/spine/animation/IkConstraintTimeline.as=UTF-8
encoding//src/spine/animation/Listeners.as=UTF-8
encoding//src/spine/animation/MixBlend.as=UTF-8
encoding//src/spine/animation/MixDirection.as=UTF-8 encoding//src/spine/animation/MixDirection.as=UTF-8
encoding//src/spine/animation/MixPose.as=UTF-8 encoding//src/spine/animation/PathConstraintMixTimeline.as=UTF-8
encoding//src/spine/animation/PathConstraintPositionTimeline.as=UTF-8
encoding//src/spine/animation/PathConstraintSpacingTimeline.as=UTF-8
encoding//src/spine/animation/RotateTimeline.as=UTF-8
encoding//src/spine/animation/ScaleTimeline.as=UTF-8
encoding//src/spine/animation/ShearTimeline.as=UTF-8
encoding//src/spine/animation/Timeline.as=UTF-8
encoding//src/spine/animation/TimelineType.as=UTF-8
encoding//src/spine/animation/TrackEntry.as=UTF-8
encoding//src/spine/animation/TransformConstraintTimeline.as=UTF-8
encoding//src/spine/animation/TranslateTimeline.as=UTF-8
encoding//src/spine/animation/TwoColorTimeline.as=UTF-8 encoding//src/spine/animation/TwoColorTimeline.as=UTF-8
encoding//src/spine/attachments/ClippingAttachment.as=UTF-8 encoding//src/spine/attachments/ClippingAttachment.as=UTF-8
encoding//src/spine/attachments/PointAttachment.as=UTF-8 encoding//src/spine/attachments/PointAttachment.as=UTF-8

View File

@ -50,7 +50,7 @@ package spine.animation {
} }
/** Poses the skeleton at the specified time for this animation. */ /** Poses the skeleton at the specified time for this animation. */
public function apply(skeleton : Skeleton, lastTime : Number, time : Number, loop : Boolean, events : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { public function apply(skeleton : Skeleton, lastTime : Number, time : Number, loop : Boolean, events : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
if (skeleton == null) throw new ArgumentError("skeleton cannot be null."); if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
if (loop && duration != 0) { if (loop && duration != 0) {
@ -59,7 +59,7 @@ package spine.animation {
} }
for (var i : int = 0, n : int = timelines.length; i < n; i++) for (var i : int = 0, n : int = 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);
} }
public function get name() : String { public function get name() : String {

View File

@ -159,12 +159,12 @@ package spine.animation {
var current : TrackEntry = tracks[i]; var current : TrackEntry = tracks[i];
if (current == null || current.delay > 0) continue; if (current == null || current.delay > 0) continue;
applied = true; applied = true;
var currentPose : MixPose = i == 0 ? MixPose.current : MixPose.currentLayered; var blend : MixBlend = i == 0 ? MixBlend.first : current.mixBlend;
// Apply mixing from entries first. // Apply mixing from entries first.
var mix : Number = current.alpha; var mix : Number = current.alpha;
if (current.mixingFrom != null) if (current.mixingFrom != null)
mix *= applyMixingFrom(current, skeleton, currentPose); mix *= applyMixingFrom(current, skeleton, blend);
else if (current.trackTime >= current.trackEnd && current.next == null) else if (current.trackTime >= current.trackEnd && current.next == null)
mix = 0; mix = 0;
@ -173,9 +173,9 @@ package spine.animation {
var timelineCount : int = current.animation.timelines.length; var timelineCount : int = current.animation.timelines.length;
var timelines : Vector.<Timeline> = current.animation.timelines; var timelines : Vector.<Timeline> = current.animation.timelines;
var ii : int = 0; var ii : int = 0;
if (mix == 1) { if (mix == 1 || blend == MixBlend.add) {
for (ii = 0; ii < timelineCount; ii++) for (ii = 0; ii < timelineCount; ii++)
Timeline(timelines[ii]).apply(skeleton, animationLast, animationTime, events, 1, MixPose.setup, MixDirection.In); Timeline(timelines[ii]).apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection.In);
} else { } else {
var timelineData : Vector.<int> = current.timelineData; var timelineData : Vector.<int> = current.timelineData;
@ -185,11 +185,11 @@ package spine.animation {
for (ii = 0; ii < timelineCount; ii++) { for (ii = 0; ii < timelineCount; ii++) {
var timeline : Timeline = timelines[ii]; var timeline : Timeline = timelines[ii];
var pose : MixPose = timelineData[ii] >= AnimationState.FIRST ? MixPose.setup : currentPose; var timelineBlend : MixBlend = timelineData[ii] == AnimationState.SUBSEQUENT ? blend : MixBlend.setup;
if (timeline is RotateTimeline) { if (timeline is RotateTimeline) {
applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
} else } else
timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.In); timeline.apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, MixDirection.In);
} }
} }
queueEvents(current, animationTime); queueEvents(current, animationTime);
@ -202,17 +202,18 @@ package spine.animation {
return applied; return applied;
} }
private function applyMixingFrom(to : TrackEntry, skeleton : Skeleton, currentPose : MixPose) : Number { private function applyMixingFrom(to : TrackEntry, skeleton : Skeleton, blend : MixBlend) : Number {
var from : TrackEntry = to.mixingFrom; var from : TrackEntry = to.mixingFrom;
if (from.mixingFrom != null) applyMixingFrom(from, skeleton, currentPose); if (from.mixingFrom != null) applyMixingFrom(from, skeleton, blend);
var mix : Number = 0; var mix : Number = 0;
if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes.
mix = 1; mix = 1;
currentPose = MixPose.setup; if (blend == MixBlend.first) blend = MixBlend.setup;
} else { } else {
mix = to.mixTime / to.mixDuration; mix = to.mixTime / to.mixDuration;
if (mix > 1) mix = 1; if (mix > 1) mix = 1;
if (blend != MixBlend.first) blend = from.mixBlend;
} }
var events : Vector.<Event> = mix < from.eventThreshold ? this.events : null; var events : Vector.<Event> = mix < from.eventThreshold ? this.events : null;
@ -220,49 +221,54 @@ package spine.animation {
var animationLast : Number = from.animationLast, animationTime : Number = from.getAnimationTime(); var animationLast : Number = from.animationLast, animationTime : Number = from.getAnimationTime();
var timelineCount : int = from.animation.timelines.length; var timelineCount : int = from.animation.timelines.length;
var timelines : Vector.<Timeline> = from.animation.timelines; var timelines : Vector.<Timeline> = from.animation.timelines;
var timelineData : Vector.<int> = from.timelineData;
var timelineDipMix : Vector.<TrackEntry> = from.timelineDipMix;
var firstFrame : Boolean = from.timelinesRotation.length == 0;
if (firstFrame) from.timelinesRotation.length = timelineCount << 1;
var timelinesRotation : Vector.<Number> = from.timelinesRotation;
var pose : MixPose;
var alphaDip : Number = from.alpha * to.interruptAlpha; var alphaDip : Number = from.alpha * to.interruptAlpha;
var alphaMix : Number = alphaDip * (1 - mix); var alphaMix : Number = alphaDip * (1 - mix);
var alpha : Number = 0; var i : int = 0;
from.totalAlpha = 0; if (blend == MixBlend.add) {
for (var i : int = 0; i < timelineCount; i++) { for (i = 0; i < timelineCount; i++)
var timeline : Timeline = timelines[i]; timelines[i].apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.Out);
switch (timelineData[i]) { } else {
case SUBSEQUENT: var timelineData : Vector.<int> = from.timelineData;
if (!attachments && timeline is AttachmentTimeline) continue; var timelineDipMix : Vector.<TrackEntry> = from.timelineDipMix;
if (!drawOrder && timeline is DrawOrderTimeline) continue;
pose = currentPose; var firstFrame : Boolean = from.timelinesRotation.length == 0;
alpha = alphaMix; if (firstFrame) from.timelinesRotation.length = timelineCount << 1;
break; var timelinesRotation : Vector.<Number> = from.timelinesRotation;
case FIRST:
pose = MixPose.setup; from.totalAlpha = 0;
alpha = alphaMix; for (i = 0; i < timelineCount; i++) {
break; var timeline : Timeline = timelines[i];
case DIP: var timelineBlend: MixBlend;
pose = MixPose.setup; var alpha : Number = 0;
alpha = alphaDip; switch (timelineData[i]) {
break; case SUBSEQUENT:
default: if (!attachments && timeline is AttachmentTimeline) continue;
pose = MixPose.setup; if (!drawOrder && timeline is DrawOrderTimeline) continue;
alpha = alphaDip; timelineBlend = blend;
var dipMix : TrackEntry = timelineDipMix[i]; alpha = alphaMix;
alpha *= Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration); break;
break; case FIRST:
} timelineBlend = MixBlend.setup;
from.totalAlpha += alpha; alpha = alphaMix;
if (timeline is RotateTimeline) break;
applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); case DIP:
else { timelineBlend = MixBlend.setup;
timeline.apply(skeleton, animationLast, animationTime, events, alpha, pose, MixDirection.Out); alpha = alphaDip;
} break;
} default:
timelineBlend = MixBlend.setup;
var dipMix : TrackEntry = timelineDipMix[i];
alpha = alphaDip * Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
break;
}
from.totalAlpha += alpha;
if (timeline is RotateTimeline)
applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame);
else {
timeline.apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, MixDirection.Out);
}
}
}
if (to.mixDuration > 0) queueEvents(from, animationTime); if (to.mixDuration > 0) queueEvents(from, animationTime);
this.events.length = 0; this.events.length = 0;
@ -272,11 +278,11 @@ package spine.animation {
return mix; return mix;
} }
private function applyRotateTimeline(timeline : Timeline, skeleton : Skeleton, time : Number, alpha : Number, pose : MixPose, timelinesRotation : Vector.<Number>, i : int, firstFrame : Boolean) : void { private function applyRotateTimeline(timeline : Timeline, skeleton : Skeleton, time : Number, alpha : Number, blend : MixBlend, timelinesRotation : Vector.<Number>, i : int, firstFrame : Boolean) : void {
if (firstFrame) timelinesRotation[i] = 0; if (firstFrame) timelinesRotation[i] = 0;
if (alpha == 1) { if (alpha == 1) {
timeline.apply(skeleton, 0, time, null, 1, pose, MixDirection.In); timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.In);
return; return;
} }
@ -284,7 +290,7 @@ package spine.animation {
var frames : Vector.<Number> = rotateTimeline.frames; var frames : Vector.<Number> = rotateTimeline.frames;
var bone : Bone = skeleton.bones[rotateTimeline.boneIndex]; var bone : Bone = skeleton.bones[rotateTimeline.boneIndex];
if (time < frames[0]) { if (time < frames[0]) {
if (pose == MixPose.setup) bone.rotation = bone.data.rotation; if (blend == MixBlend.setup) bone.rotation = bone.data.rotation;
return; return;
} }
@ -305,7 +311,7 @@ package spine.animation {
} }
// 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.
var r1 : Number = pose == MixPose.setup ? bone.data.rotation : bone.rotation; var r1 : Number = blend == MixBlend.setup ? bone.data.rotation : bone.rotation;
var total : Number, diff : Number = r2 - r1; var total : Number, diff : Number = r2 - r1;
if (diff == 0) { if (diff == 0) {
total = timelinesRotation[i]; total = timelinesRotation[i];
@ -559,7 +565,8 @@ package spine.animation {
var mixingTo : Vector.<TrackEntry> = this.mixingTo; var mixingTo : Vector.<TrackEntry> = this.mixingTo;
for (var i : int = 0, n : int = tracks.length; i < n; i++) { for (var i : int = 0, n : int = tracks.length; i < n; i++) {
var entry : TrackEntry = tracks[i]; var entry : TrackEntry = tracks[i];
if (entry != null) entry.setTimelineData(null, mixingTo, propertyIDs); if (entry != null && (i == 0 || entry.mixBlend != MixBlend.add))
entry.setTimelineData(null, mixingTo, propertyIDs);
} }
} }

View File

@ -57,17 +57,17 @@ package spine.animation {
attachmentNames[frameIndex] = attachmentName; attachmentNames[frameIndex] = attachmentName;
} }
public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var attachmentName : String; var attachmentName : String;
var slot : Slot = skeleton.slots[slotIndex]; var slot : Slot = skeleton.slots[slotIndex];
if (direction == MixDirection.Out && pose == MixPose.setup) { if (direction == MixDirection.Out && blend == MixBlend.setup) {
attachmentName = slot.data.attachmentName; attachmentName = slot.data.attachmentName;
slot.attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName); slot.attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName);
return; return;
} }
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
if (time < frames[0]) { if (time < frames[0]) {
if (pose == MixPose.setup) { if (blend == MixBlend.setup || blend == MixBlend.first) {
attachmentName = slot.data.attachmentName; attachmentName = slot.data.attachmentName;
slot.attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName); slot.attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName);
} }

View File

@ -60,16 +60,16 @@ package spine.animation {
frames[int(frameIndex + A)] = a; frames[int(frameIndex + A)] = a;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
var slot : Slot = skeleton.slots[slotIndex]; var slot : Slot = skeleton.slots[slotIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
slot.color.setFromColor(slot.data.color); slot.color.setFromColor(slot.data.color);
return; return;
case MixPose.current: case MixBlend.first:
var color : Color = slot.color, setup : Color = slot.data.color; var color : Color = slot.color, setup : Color = slot.data.color;
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
(setup.a - color.a) * alpha); (setup.a - color.a) * alpha);
@ -102,7 +102,7 @@ package spine.animation {
if (alpha == 1) { if (alpha == 1) {
slot.color.setFrom(r, g, b, a); slot.color.setFrom(r, g, b, a);
} else { } else {
if (pose == MixPose.setup) { if (blend == MixBlend.setup) {
slot.color.setFromColor(slot.data.color); slot.color.setFromColor(slot.data.color);
} }
slot.color.r += (r - slot.color.r) * alpha; slot.color.r += (r - slot.color.r) * alpha;

View File

@ -45,7 +45,7 @@ package spine.animation {
curves = new Vector.<Number>((frameCount - 1) * BEZIER_SIZE, true); curves = new Vector.<Number>((frameCount - 1) * BEZIER_SIZE, true);
} }
public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
} }
public function getPropertyId() : int { public function getPropertyId() : int {

View File

@ -57,7 +57,7 @@ package spine.animation {
frameVertices[frameIndex] = vertices; frameVertices[frameIndex] = vertices;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var vertexAttachment : VertexAttachment; var vertexAttachment : VertexAttachment;
var setupVertices : Vector.<Number>; var setupVertices : Vector.<Number>;
var slot : Slot = skeleton.slots[slotIndex]; var slot : Slot = skeleton.slots[slotIndex];
@ -65,7 +65,7 @@ package spine.animation {
if (!(slotAttachment is VertexAttachment) || !(VertexAttachment(slotAttachment)).applyDeform(attachment)) return; if (!(slotAttachment is VertexAttachment) || !(VertexAttachment(slotAttachment)).applyDeform(attachment)) return;
var verticesArray : Vector.<Number> = slot.attachmentVertices; var verticesArray : Vector.<Number> = slot.attachmentVertices;
if (verticesArray.length == 0) alpha = 1; if (verticesArray.length == 0) blend = MixBlend.setup;
var frameVertices : Vector.<Vector.<Number>> = this.frameVertices; var frameVertices : Vector.<Vector.<Number>> = this.frameVertices;
var vertexCount : int = frameVertices[0].length; var vertexCount : int = frameVertices[0].length;
@ -75,11 +75,11 @@ package spine.animation {
var i : int; var i : int;
if (time < frames[0]) { if (time < frames[0]) {
vertexAttachment = VertexAttachment(slotAttachment); vertexAttachment = VertexAttachment(slotAttachment);
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
verticesArray.length = 0; verticesArray.length = 0;
return; return;
case MixPose.current: case MixBlend.first:
if (alpha == 1) { if (alpha == 1) {
verticesArray.length = 0; verticesArray.length = 0;
return; return;
@ -108,27 +108,54 @@ package spine.animation {
if (time >= frames[frames.length - 1]) { // Time is after last frame. if (time >= frames[frames.length - 1]) { // Time is after last frame.
var lastVertices : Vector.<Number> = frameVertices[frames.length - 1]; var lastVertices : Vector.<Number> = frameVertices[frames.length - 1];
if (alpha == 1) { if (alpha == 1) {
// Vertex positions or deform offsets, no alpha. if (blend == MixBlend.add) {
for (i = 0, n = vertexCount; i < n; i++) vertexAttachment = VertexAttachment(slotAttachment);
vertices[i] = lastVertices[i]; if (vertexAttachment.bones == null) {
} else if (pose == MixPose.setup) { setupVertices = vertexAttachment.vertices;
vertexAttachment = VertexAttachment(slotAttachment); for (i = 0; i < vertexCount; i++) {
if (vertexAttachment.bones == null) { vertices[i] += lastVertices[i] - setupVertices[i];
// Unweighted vertex positions, with alpha. }
setupVertices = vertexAttachment.vertices; } else {
for (i = 0; i < vertexCount; i++) { for (i = 0; i < vertexCount; i++)
setup = setupVertices[i]; vertices[i] += lastVertices[i];
vertices[i] = setup + (lastVertices[i] - setup) * alpha;
} }
} else { } else {
// Weighted deform offsets, with alpha. for (i = 0, n = vertexCount; i < n; i++)
for (i = 0; i < vertexCount; i++) vertices[i] = lastVertices[i];
vertices[i] = lastVertices[i] * alpha;
} }
} else { } else {
// Vertex positions or deform offsets, with alpha. switch (blend) {
for (i = 0; i < vertexCount; i++) case MixBlend.setup:
vertices[i] += (lastVertices[i] - vertices[i]) * alpha; vertexAttachment = VertexAttachment(slotAttachment);
if (vertexAttachment.bones == null) {
// Unweighted vertex positions, with alpha.
setupVertices = vertexAttachment.vertices;
for (i = 0; i < vertexCount; i++) {
setup = setupVertices[i];
vertices[i] = setup + (lastVertices[i] - setup) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (i = 0; i < vertexCount; i++)
vertices[i] = lastVertices[i] * alpha;
}
break;
case MixBlend.first:
case MixBlend.replace:
for (i = 0; i < vertexCount; i++)
vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
case MixBlend.add:
vertexAttachment = VertexAttachment(slotAttachment);
if (vertexAttachment.bones == null) {
setupVertices = vertexAttachment.vertices;
for (i = 0; i < vertexCount; i++) {
vertices[i] += (lastVertices[i] - setupVertices[i]) * alpha;
}
} else {
for (i = 0; i < vertexCount; i++)
vertices[i] += lastVertices[i] * alpha;
}
}
} }
return; return;
} }
@ -141,34 +168,67 @@ package spine.animation {
var percent : Number = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); var percent : Number = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));
if (alpha == 1) { if (alpha == 1) {
// Vertex positions or deform offsets, no alpha. if (blend == MixBlend.add) {
for (i = 0; i < vertexCount; i++) { vertexAttachment = VertexAttachment(slotAttachment);
prev = prevVertices[i]; if (vertexAttachment.bones == null) {
vertices[i] = prev + (nextVertices[i] - prev) * percent; setupVertices = vertexAttachment.vertices;
} for (i = 0; i < vertexCount; i++) {
} else if (pose == MixPose.setup) { prev = prevVertices[i];
vertexAttachment = VertexAttachment(slotAttachment); vertices[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];
if (vertexAttachment.bones == null) { }
// Unweighted vertex positions, with alpha. } else {
setupVertices = vertexAttachment.vertices; for (i = 0; i < vertexCount; i++) {
for (i = 0; i < vertexCount; i++) { prev = prevVertices[i];
prev = prevVertices[i]; vertices[i] += prev + (nextVertices[i] - prev) * percent;
setup = setupVertices[i]; }
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
} }
} else { } else {
// Weighted deform offsets, with alpha. for (i = 0; i < vertexCount; i++) {
for (i = 0; i < vertexCount; i++) {
prev = prevVertices[i]; prev = prevVertices[i];
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; vertices[i] = prev + (nextVertices[i] - prev) * percent;
} }
} }
} else { } else {
// Vertex positions or deform offsets, with alpha. switch (blend) {
for (i = 0; i < vertexCount; i++) { case MixBlend.setup:
prev = prevVertices[i]; vertexAttachment = VertexAttachment(slotAttachment);
vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; if (vertexAttachment.bones == null) {
} // Unweighted vertex positions, with alpha.
setupVertices = vertexAttachment.vertices;
for (i = 0; i < vertexCount; i++) {
prev = prevVertices[i], setup = setupVertices[i];
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (i = 0; i < vertexCount; i++) {
prev = prevVertices[i];
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
}
}
break;
case MixBlend.first:
case MixBlend.replace:
for (i = 0; i < vertexCount; i++) {
prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
}
break;
case MixBlend.add:
vertexAttachment = VertexAttachment(slotAttachment);
if (vertexAttachment.bones == null) {
setupVertices = vertexAttachment.vertices;
for (i = 0; i < vertexCount; i++) {
prev = prevVertices[i], setup = setupVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
}
} else {
for (i = 0; i < vertexCount; i++) {
prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
}
}
}
} }
} }
} }

View File

@ -56,8 +56,8 @@ package spine.animation {
drawOrders[frameIndex] = drawOrder; drawOrders[frameIndex] = drawOrder;
} }
public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
if (direction == MixDirection.Out && pose == MixPose.setup) { if (direction == MixDirection.Out && blend == MixBlend.setup) {
for (var ii : int = 0, n : int = skeleton.slots.length; ii < n; ii++) for (var ii : int = 0, n : int = skeleton.slots.length; ii < n; ii++)
skeleton.drawOrder[ii] = skeleton.slots[ii]; skeleton.drawOrder[ii] = skeleton.slots[ii];
return; return;
@ -68,7 +68,7 @@ package spine.animation {
var slot : Slot; var slot : Slot;
var i : int = 0; var i : int = 0;
if (time < frames[0]) { if (time < frames[0]) {
if (pose == MixPose.setup) { if (blend == MixBlend.setup || blend == MixBlend.first) {
for each (slot in slots) for each (slot in slots)
drawOrder[i++] = slot; drawOrder[i++] = slot;
} }

View File

@ -56,11 +56,11 @@ package spine.animation {
} }
/** Fires events for frames > lastTime and <= time. */ /** Fires events for frames > lastTime and <= time. */
public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
if (!firedEvents) return; if (!firedEvents) return;
if (lastTime > time) { // Fire events after last time for looped animations. if (lastTime > time) { // Fire events after last time for looped animations.
apply(skeleton, lastTime, int.MAX_VALUE, firedEvents, alpha, pose, direction); apply(skeleton, lastTime, int.MAX_VALUE, firedEvents, alpha, blend, direction);
lastTime = -1; lastTime = -1;
} else if (lastTime >= frames[int(frameCount - 1)]) // Last time is after last frame. } else if (lastTime >= frames[int(frameCount - 1)]) // Last time is after last frame.
return; return;

View File

@ -57,15 +57,15 @@ package spine.animation {
frames[int(frameIndex + BEND_DIRECTION)] = bendDirection; frames[int(frameIndex + BEND_DIRECTION)] = bendDirection;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var constraint : IkConstraint = skeleton.ikConstraints[ikConstraintIndex]; var constraint : IkConstraint = skeleton.ikConstraints[ikConstraintIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
constraint.mix = constraint.data.mix; constraint.mix = constraint.data.mix;
constraint.bendDirection = constraint.data.bendDirection; constraint.bendDirection = constraint.data.bendDirection;
return; return;
case MixPose.current: case MixBlend.first:
constraint.mix += (constraint.data.mix - constraint.mix) * alpha; constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
constraint.bendDirection = constraint.data.bendDirection; constraint.bendDirection = constraint.data.bendDirection;
} }
@ -73,7 +73,7 @@ package spine.animation {
} }
if (time >= frames[int(frames.length - ENTRIES)]) { // Time is after last frame. if (time >= frames[int(frames.length - ENTRIES)]) { // Time is after last frame.
if (pose == MixPose.setup) { if (blend == MixBlend.setup) {
constraint.mix = constraint.data.mix + (frames[frames.length + PREV_MIX] - constraint.data.mix) * alpha; constraint.mix = constraint.data.mix + (frames[frames.length + PREV_MIX] - constraint.data.mix) * alpha;
constraint.bendDirection = direction == MixDirection.Out ? constraint.data.bendDirection : int(frames[frames.length + PREV_BEND_DIRECTION]); constraint.bendDirection = direction == MixDirection.Out ? constraint.data.bendDirection : int(frames[frames.length + PREV_BEND_DIRECTION]);
} else { } else {
@ -89,7 +89,7 @@ package spine.animation {
var frameTime : Number = frames[frame]; var frameTime : Number = frames[frame];
var percent : Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); var percent : Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
if (pose == MixPose.setup) { if (blend == MixBlend.setup) {
constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha; constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha;
constraint.bendDirection = direction == MixDirection.Out ? constraint.data.bendDirection : int(frames[frame + PREV_BEND_DIRECTION]); constraint.bendDirection = direction == MixDirection.Out ? constraint.data.bendDirection : int(frames[frame + PREV_BEND_DIRECTION]);
} else { } else {

View File

@ -29,15 +29,16 @@
*****************************************************************************/ *****************************************************************************/
package spine.animation { package spine.animation {
public class MixPose { public class MixBlend {
public var ordinal : int; public var ordinal : int;
public function MixPose(order : int) { public function MixBlend(order : int) {
this.ordinal = order; this.ordinal = order;
} }
public static const setup : MixPose = new MixPose(0); public static const setup : MixBlend = new MixBlend(0);
public static const current : MixPose = new MixPose(1); public static const first : MixBlend = new MixBlend(1);
public static const currentLayered : MixPose = new MixPose(2); public static const replace : MixBlend = new MixBlend(2);
public static const add : MixBlend = new MixBlend(3);
} }
} }

View File

@ -57,15 +57,15 @@ package spine.animation {
frames[frameIndex + TRANSLATE] = translateMix; frames[frameIndex + TRANSLATE] = translateMix;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var constraint : PathConstraint = skeleton.pathConstraints[pathConstraintIndex]; var constraint : PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
constraint.rotateMix = constraint.data.rotateMix; constraint.rotateMix = constraint.data.rotateMix;
constraint.translateMix = constraint.data.translateMix; constraint.translateMix = constraint.data.translateMix;
return; return;
case MixPose.current: case MixBlend.first:
constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha;
constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha;
} }
@ -88,7 +88,7 @@ package spine.animation {
translate += (frames[frame + TRANSLATE] - translate) * percent; translate += (frames[frame + TRANSLATE] - translate) * percent;
} }
if (pose == MixPose.setup) { if (blend == MixBlend.setup) {
constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha;
constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha;
} else { } else {

View File

@ -56,14 +56,14 @@ package spine.animation {
frames[frameIndex + VALUE] = value; frames[frameIndex + VALUE] = value;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var constraint : PathConstraint = skeleton.pathConstraints[pathConstraintIndex]; var constraint : PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
constraint.position = constraint.data.position; constraint.position = constraint.data.position;
return; return;
case MixPose.current: case MixBlend.first:
constraint.position += (constraint.data.position - constraint.position) * alpha; constraint.position += (constraint.data.position - constraint.position) * alpha;
} }
return; return;
@ -81,7 +81,7 @@ package spine.animation {
position += (frames[frame + VALUE] - position) * percent; position += (frames[frame + VALUE] - position) * percent;
} }
if (pose == MixPose.setup) if (blend == MixBlend.setup)
constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; constraint.position = constraint.data.position + (position - constraint.data.position) * alpha;
else else
constraint.position += (position - constraint.position) * alpha; constraint.position += (position - constraint.position) * alpha;

View File

@ -42,14 +42,14 @@ package spine.animation {
return (TimelineType.pathConstraintSpacing.ordinal << 24) + pathConstraintIndex; return (TimelineType.pathConstraintSpacing.ordinal << 24) + pathConstraintIndex;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var constraint : PathConstraint = skeleton.pathConstraints[pathConstraintIndex]; var constraint : PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
constraint.spacing = constraint.data.spacing; constraint.spacing = constraint.data.spacing;
return; return;
case MixPose.current: case MixBlend.first:
constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha;
} }
return; return;
@ -68,7 +68,7 @@ package spine.animation {
spacing += (frames[frame + VALUE] - spacing) * percent; spacing += (frames[frame + VALUE] - spacing) * percent;
} }
if (pose == MixPose.setup) if (blend == MixBlend.setup)
constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha;
else else
constraint.spacing += (spacing - constraint.spacing) * alpha; constraint.spacing += (spacing - constraint.spacing) * alpha;

View File

@ -56,32 +56,36 @@ package spine.animation {
frames[int(frameIndex + ROTATION)] = degrees; frames[int(frameIndex + ROTATION)] = degrees;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
var bone : Bone = skeleton.bones[boneIndex]; var bone : Bone = skeleton.bones[boneIndex];
var r : Number; var r : Number;
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
bone.rotation = bone.data.rotation; bone.rotation = bone.data.rotation;
return; return;
case MixPose.current: case MixBlend.first:
r = bone.data.rotation - bone.rotation; r = bone.data.rotation - bone.rotation;
r -= (16384 - int((16384.499999999996 - r / 360))) * 360; bone.rotation += (r - (16384 - int((16384.499999999996 - r / 360))) * 360) * alpha;
bone.rotation += r * alpha;
} }
return; return;
} }
if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame. if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
if (pose == MixPose.setup) r = frames[frames.length + PREV_ROTATION];
bone.rotation = bone.data.rotation + frames[frames.length + PREV_ROTATION] * alpha; switch (blend) {
else { case MixBlend.setup:
r = bone.data.rotation + frames[frames.length + PREV_ROTATION] - bone.rotation; bone.rotation = bone.data.rotation + r * alpha;
r -= (16384 - int((16384.499999999996 - r / 360))) * 360; // Wrap within -180 and 180. break;
bone.rotation += r * alpha; case MixBlend.first:
} case MixBlend.replace:
r += bone.data.rotation - bone.rotation;
r -= (16384 - int((16384.499999999996 - r / 360))) * 360; // Wrap within -180 and 180.
case MixBlend.add:
bone.rotation += r * alpha;
}
return; return;
} }
@ -92,15 +96,16 @@ package spine.animation {
var percent : Number = getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); var percent : Number = getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
r = frames[frame + ROTATION] - prevRotation; r = frames[frame + ROTATION] - prevRotation;
r -= (16384 - int((16384.499999999996 - r / 360))) * 360; r = prevRotation + (r - (16384 - int((16384.499999999996 - r / 360))) * 360) * percent;
r = prevRotation + r * percent; switch (blend) {
if (pose == MixPose.setup) { case MixBlend.setup:
r -= (16384 - int((16384.499999999996 - r / 360))) * 360; bone.rotation = bone.data.rotation + (r - (16384 - int((16384.499999999996 - r / 360))) * 360) * alpha;
bone.rotation = bone.data.rotation + r * alpha; break;
} else { case MixBlend.first:
r = bone.data.rotation + r - bone.rotation; case MixBlend.replace:
r -= (16384 - int((16384.499999999996 - r / 360))) * 360; r += bone.data.rotation - bone.rotation;
bone.rotation += r * alpha; case MixBlend.add:
bone.rotation += (r - (16384 - int((16384.499999999996 - r / 360))) * 360) * alpha;
} }
} }
} }

View File

@ -43,17 +43,17 @@ package spine.animation {
return (TimelineType.scale.ordinal << 24) + boneIndex; return (TimelineType.scale.ordinal << 24) + boneIndex;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
var bone : Bone = skeleton.bones[boneIndex]; var bone : Bone = skeleton.bones[boneIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
bone.scaleX = bone.data.scaleX; bone.scaleX = bone.data.scaleX;
bone.scaleY = bone.data.scaleY; bone.scaleY = bone.data.scaleY;
return; return;
case MixPose.current: case MixBlend.first:
bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
} }
@ -76,27 +76,58 @@ package spine.animation {
y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY; y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY;
} }
if (alpha == 1) { if (alpha == 1) {
bone.scaleX = x; if (blend == MixBlend.add) {
bone.scaleY = y; bone.scaleX += x - bone.data.scaleX;
bone.scaleY += y - bone.data.scaleY;
} else {
bone.scaleX = x;
bone.scaleY = y;
}
} else { } else {
var bx : Number, by : Number; var bx : Number, by : Number;
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) { if (direction == MixDirection.Out) {
x = Math.abs(x) * MathUtils.signum(bx); switch (blend) {
y = Math.abs(y) * MathUtils.signum(by); 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 { } else {
bx = Math.abs(bx) * MathUtils.signum(x); switch (blend) {
by = Math.abs(by) * MathUtils.signum(y); 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:
bx = Math.abs(bone.scaleX) * MathUtils.signum(x);
by = Math.abs(bone.scaleY) * MathUtils.signum(y);
bone.scaleX = bx + (x - bx) * alpha;
bone.scaleY = by + (y - by) * 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;
} }
} }
} }

View File

@ -42,17 +42,17 @@ package spine.animation {
return (TimelineType.shear.ordinal << 24) + boneIndex; return (TimelineType.shear.ordinal << 24) + boneIndex;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
var bone : Bone = skeleton.bones[boneIndex]; var bone : Bone = skeleton.bones[boneIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
bone.shearX = bone.data.shearX; bone.shearX = bone.data.shearX;
bone.shearY = bone.data.shearY; bone.shearY = bone.data.shearY;
return; return;
case MixPose.current: case MixBlend.first:
bone.shearX += (bone.data.shearX - bone.shearX) * alpha; bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
bone.shearY += (bone.data.shearY - bone.shearY) * alpha; bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
} }
@ -74,12 +74,19 @@ package spine.animation {
x = x + (frames[frame + X] - x) * percent; x = x + (frames[frame + X] - x) * percent;
y = y + (frames[frame + Y] - y) * percent; y = y + (frames[frame + Y] - y) * percent;
} }
if (pose == MixPose.setup) { switch (blend) {
bone.shearX = bone.data.shearX + x * alpha; case MixBlend.setup:
bone.shearY = bone.data.shearY + y * alpha; bone.shearX = bone.data.shearX + x * alpha;
} else { bone.shearY = bone.data.shearY + y * alpha;
bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; break;
bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; 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;
} }
} }
} }

View File

@ -34,7 +34,7 @@ package spine.animation {
public interface Timeline { public interface Timeline {
/** Sets the value(s) for the specified time. */ /** Sets the value(s) for the specified time. */
function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void; function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void;
function getPropertyId() : int; function getPropertyId() : int;
} }

View File

@ -47,6 +47,7 @@ package spine.animation {
public var animationStart : Number, animationEnd : Number, animationLast : Number, nextAnimationLast : Number; public var animationStart : Number, animationEnd : Number, animationLast : Number, nextAnimationLast : Number;
public var delay : Number, trackTime : Number, trackLast : Number, nextTrackLast : Number, trackEnd : Number, timeScale : Number; public var delay : Number, trackTime : Number, trackLast : Number, nextTrackLast : Number, trackEnd : Number, timeScale : Number;
public var alpha : Number, mixTime : Number, mixDuration : Number, interruptAlpha : Number, totalAlpha : Number = 0; public var alpha : Number, mixTime : Number, mixDuration : Number, interruptAlpha : Number, totalAlpha : Number = 0;
public var mixBlend: MixBlend = MixBlend.replace;
public var timelineData : Vector.<int> = new Vector.<int>(); public var timelineData : Vector.<int> = new Vector.<int>();
public var timelineDipMix : Vector.<TrackEntry> = new Vector.<TrackEntry>(); public var timelineDipMix : Vector.<TrackEntry> = new Vector.<TrackEntry>();
public var timelinesRotation : Vector.<Number> = new Vector.<Number>(); public var timelinesRotation : Vector.<Number> = new Vector.<Number>();

View File

@ -60,21 +60,21 @@ package spine.animation {
frames[frameIndex + SHEAR] = shearMix; frames[frameIndex + SHEAR] = shearMix;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
var constraint : TransformConstraint = skeleton.transformConstraints[transformConstraintIndex]; var constraint : TransformConstraint = skeleton.transformConstraints[transformConstraintIndex];
var data : TransformConstraintData; var data : TransformConstraintData;
if (time < frames[0]) { if (time < frames[0]) {
data = constraint.data; data = constraint.data;
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
constraint.rotateMix = data.rotateMix; constraint.rotateMix = data.rotateMix;
constraint.translateMix = data.translateMix; constraint.translateMix = data.translateMix;
constraint.scaleMix = data.scaleMix; constraint.scaleMix = data.scaleMix;
constraint.shearMix = data.shearMix; constraint.shearMix = data.shearMix;
return; return;
case MixPose.current: case MixBlend.first:
constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha;
constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha;
constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha;
@ -105,7 +105,7 @@ package spine.animation {
scale += (frames[frame + SCALE] - scale) * percent; scale += (frames[frame + SCALE] - scale) * percent;
shear += (frames[frame + SHEAR] - shear) * percent; shear += (frames[frame + SHEAR] - shear) * percent;
} }
if (pose == MixPose.setup) { if (blend == MixBlend.setup) {
data = constraint.data; data = constraint.data;
constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha;
constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha;

View File

@ -57,17 +57,17 @@ package spine.animation {
frames[int(frameIndex + Y)] = y; frames[int(frameIndex + Y)] = y;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
var bone : Bone = skeleton.bones[boneIndex]; var bone : Bone = skeleton.bones[boneIndex];
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
bone.x = bone.data.x; bone.x = bone.data.x;
bone.y = bone.data.y; bone.y = bone.data.y;
return; return;
case MixPose.current: case MixBlend.first:
bone.x += (bone.data.x - bone.x) * alpha; bone.x += (bone.data.x - bone.x) * alpha;
bone.y += (bone.data.y - bone.y) * alpha; bone.y += (bone.data.y - bone.y) * alpha;
} }
@ -89,12 +89,19 @@ package spine.animation {
x += (frames[frame + X] - x) * percent; x += (frames[frame + X] - x) * percent;
y += (frames[frame + Y] - y) * percent; y += (frames[frame + Y] - y) * percent;
} }
if (pose == MixPose.setup) { switch (blend) {
bone.x = bone.data.x + x * alpha; case MixBlend.setup:
bone.y = bone.data.y + y * alpha; bone.x = bone.data.x + x * alpha;
} else { bone.y = bone.data.y + y * alpha;
bone.x += (bone.data.x + x - bone.x) * alpha; break;
bone.y += (bone.data.y + y - bone.y) * alpha; 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;
} }
} }
} }

View File

@ -64,18 +64,18 @@ package spine.animation {
this.frames[frameIndex + TwoColorTimeline.B2] = b2; this.frames[frameIndex + TwoColorTimeline.B2] = b2;
} }
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void { override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, blend : MixBlend, direction : MixDirection) : void {
var frames : Vector.<Number> = this.frames; var frames : Vector.<Number> = this.frames;
var slot : Slot = skeleton.slots[slotIndex]; var slot : Slot = skeleton.slots[slotIndex];
var light : Color, dark : Color; var light : Color, dark : Color;
if (time < frames[0]) { if (time < frames[0]) {
switch (pose) { switch (blend) {
case MixPose.setup: case MixBlend.setup:
slot.color.setFromColor(slot.data.color); slot.color.setFromColor(slot.data.color);
slot.darkColor.setFromColor(slot.data.darkColor); slot.darkColor.setFromColor(slot.data.darkColor);
return; return;
case MixPose.current: case MixBlend.first:
light = slot.color; light = slot.color;
dark = slot.darkColor; dark = slot.darkColor;
var setupLight : Color = slot.data.color, setupDark : Color = slot.data.darkColor; var setupLight : Color = slot.data.color, setupDark : Color = slot.data.darkColor;
@ -123,7 +123,7 @@ package spine.animation {
} else { } else {
light = slot.color; light = slot.color;
dark = slot.darkColor; dark = slot.darkColor;
if (pose == MixPose.setup) { if (blend == MixBlend.setup) {
light.setFromColor(slot.data.color); light.setFromColor(slot.data.color);
dark.setFromColor(slot.data.darkColor); dark.setFromColor(slot.data.darkColor);
} }

View File

@ -489,8 +489,10 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
break; break;
case SP_MIX_BLEND_FIRST: case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE: case SP_MIX_BLEND_REPLACE:
bone->scaleX += (x - bone->scaleX * SIGNUM(x)) * alpha; bx = ABS(bone->scaleX) * SIGNUM(x);
bone->scaleY += (y - bone->scaleY * SIGNUM(y)) * alpha; by = ABS(bone->scaleY) * SIGNUM(y);
bone->scaleX = bx + (x - bx) * alpha;
bone->scaleY = by + (y - by) * alpha;
break; break;
case SP_MIX_BLEND_ADD: case SP_MIX_BLEND_ADD:
bx = SIGNUM(x); bx = SIGNUM(x);

View File

@ -38,7 +38,7 @@ package spine.examples {
private var _starling : Starling; private var _starling : Starling;
public function Main() { public function Main() {
_starling = new Starling(SpineboyExample, stage); _starling = new Starling(OwlExample, stage);
_starling.enableErrorChecking = true; _starling.enableErrorChecking = true;
_starling.showStats = true; _starling.showStats = true;
_starling.skipUnchangedFrames = false; _starling.skipUnchangedFrames = false;

View File

@ -0,0 +1,88 @@
package spine.examples {
import spine.animation.MixBlend;
import spine.animation.TrackEntry;
import starling.display.DisplayObjectContainer;
import starling.events.Touch;
import starling.events.TouchPhase;
import starling.core.Starling;
import starling.events.TouchEvent;
import starling.display.Sprite;
import spine.SkeletonData;
import spine.SkeletonJson;
import spine.attachments.AtlasAttachmentLoader;
import spine.starling.StarlingTextureLoader;
import spine.atlas.Atlas;
import spine.attachments.AttachmentLoader;
import spine.starling.SkeletonAnimation;
public class OwlExample extends Sprite {
[Embed(source = "/owl-pro.json", mimeType = "application/octet-stream")]
static public const OwlJson : Class;
[Embed(source = "/owl.atlas", mimeType = "application/octet-stream")]
static public const OwlAtlas : Class;
[Embed(source = "/owl.png")]
static public const OwlAtlasTexture : Class;
private var skeleton : SkeletonAnimation;
private var left: TrackEntry;
private var right: TrackEntry;
private var up: TrackEntry;
private var down: TrackEntry;
public function OwlExample() {
var attachmentLoader : AttachmentLoader;
var spineAtlas : Atlas = new Atlas(new OwlAtlas(), new StarlingTextureLoader(new OwlAtlasTexture()));
attachmentLoader = new AtlasAttachmentLoader(spineAtlas);
var json : SkeletonJson = new SkeletonJson(attachmentLoader);
json.scale = 0.5;
var skeletonData : SkeletonData = json.readSkeletonData(new OwlJson());
this.x = 400;
this.y = 400;
skeleton = new SkeletonAnimation(skeletonData);
skeleton.state.setAnimationByName(0, "idle", true);
skeleton.state.setAnimationByName(1, "blink", true);
left = skeleton.state.setAnimationByName(2, "left", true);
right = skeleton.state.setAnimationByName(3, "right", true);
up = skeleton.state.setAnimationByName(4, "up", true);
down = skeleton.state.setAnimationByName(5, "down", true);
left.alpha = right.alpha = up.alpha = down.alpha = 0;
left.mixBlend = right.mixBlend = up.mixBlend = down.mixBlend = MixBlend.add;
skeleton.state.timeScale = 0.5;
skeleton.state.update(0.25);
skeleton.state.apply(skeleton.skeleton);
skeleton.skeleton.updateWorldTransform();
addChild(skeleton);
Starling.juggler.add(skeleton);
addEventListener(TouchEvent.TOUCH, onTouch);
}
private function onTouch(event : TouchEvent) : void {
var touch : Touch = event.getTouch(this);
if (touch && touch.phase == TouchPhase.ENDED) {
var parent : DisplayObjectContainer = this.parent;
this.removeFromParent(true);
parent.addChild(new SpineboyExample());
}
if (touch && touch.phase == TouchPhase.HOVER) {
var x : Number = touch.globalX / 800.0;
left.alpha = (Math.max(x, 0.5) - 0.5) * 2;
right.alpha = (0.5 - Math.min(x, 0.5)) * 2;
var y : Number = touch.globalY / 600.0;
down.alpha = (Math.max(y, 0.5) - 0.5) * 2;
up.alpha = (0.5 - Math.min(y, 0.5)) * 2;
}
}
}
}

View File

@ -554,7 +554,8 @@ module spine {
for (var i = 0, n = this.tracks.length; i < n; i++) { for (var i = 0, n = this.tracks.length; i < n; i++) {
let entry = this.tracks[i]; let entry = this.tracks[i];
if (entry != null && (i == 0 || entry.mixBlend != MixBlend.add)) entry.setTimelineData(null, mixingTo, propertyIDs); if (entry != null && (i == 0 || entry.mixBlend != MixBlend.add))
entry.setTimelineData(null, mixingTo, propertyIDs);
} }
} }