mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 23:34:53 +08:00
[ts] Updated to 3.6-beta, changes to updateWorldVertices (now computeWorldVertices) for attachments, two color timeline, point attachment, transform constraint local and relative modes. Meshes don't render yet in WebGL backend. Need to update other backends as well.
This commit is contained in:
parent
6d87c3bddb
commit
fcade28c7a
2715
spine-ts/build/spine-webgl.d.ts
vendored
2715
spine-ts/build/spine-webgl.d.ts
vendored
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
@ -87,7 +87,8 @@ module spine {
|
||||
attachment, color, deform,
|
||||
event, drawOrder,
|
||||
ikConstraint, transformConstraint,
|
||||
pathConstraintPosition, pathConstraintSpacing, pathConstraintMix
|
||||
pathConstraintPosition, pathConstraintSpacing, pathConstraintMix,
|
||||
twoColor
|
||||
}
|
||||
|
||||
export abstract class CurveTimeline implements Timeline {
|
||||
@ -486,6 +487,90 @@ module spine {
|
||||
}
|
||||
}
|
||||
|
||||
export class TwoColorTimeline extends CurveTimeline {
|
||||
static ENTRIES = 8;
|
||||
static PREV_TIME = -8; static PREV_R = -7; static PREV_G = -6; static PREV_B = -5; static PREV_A = -4;
|
||||
static PREV_R2 = -3; static PREV_G2 = -2; static PREV_B2 = -1;
|
||||
static R = 1; static G = 2; static B = 3; static A = 4; static R2 = 5; static G2 = 6; static B2 = 7;
|
||||
|
||||
slotIndex: number;
|
||||
frames: ArrayLike<number>; // time, r, g, b, a, r2, g2, b2, ...
|
||||
|
||||
constructor (frameCount: number) {
|
||||
super(frameCount);
|
||||
this.frames = Utils.newFloatArray(frameCount * TwoColorTimeline.ENTRIES);
|
||||
}
|
||||
|
||||
getPropertyId () {
|
||||
return (TimelineType.color << 24) + this.slotIndex;
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
setFrame (frameIndex: number, time: number, r: number, g: number, b: number, a: number, r2: number, g2: number, b2: number) {
|
||||
frameIndex *= TwoColorTimeline.ENTRIES;
|
||||
this.frames[frameIndex] = time;
|
||||
this.frames[frameIndex + TwoColorTimeline.R] = r;
|
||||
this.frames[frameIndex + TwoColorTimeline.G] = g;
|
||||
this.frames[frameIndex + TwoColorTimeline.B] = b;
|
||||
this.frames[frameIndex + TwoColorTimeline.A] = a;
|
||||
this.frames[frameIndex + TwoColorTimeline.R2] = r2;
|
||||
this.frames[frameIndex + TwoColorTimeline.G2] = g2;
|
||||
this.frames[frameIndex + TwoColorTimeline.B2] = b2;
|
||||
}
|
||||
|
||||
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, setupPose: boolean, mixingOut: boolean) {
|
||||
let slot = skeleton.slots[this.slotIndex];
|
||||
let frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
if (setupPose) {
|
||||
slot.color.setFromColor(slot.data.color);
|
||||
slot.darkColor.setFromColor(slot.data.darkColor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;
|
||||
if (time >= frames[frames.length - TwoColorTimeline.ENTRIES]) { // Time is after last frame.
|
||||
let i = frames.length;
|
||||
r = frames[i + TwoColorTimeline.PREV_R];
|
||||
g = frames[i + TwoColorTimeline.PREV_G];
|
||||
b = frames[i + TwoColorTimeline.PREV_B];
|
||||
a = frames[i + TwoColorTimeline.PREV_A];
|
||||
r2 = frames[i + TwoColorTimeline.PREV_R2];
|
||||
g2 = frames[i + TwoColorTimeline.PREV_G2];
|
||||
b2 = frames[i + TwoColorTimeline.PREV_B2];
|
||||
} else {
|
||||
// Interpolate between the previous frame and the current frame.
|
||||
let frame = Animation.binarySearch(frames, time, TwoColorTimeline.ENTRIES);
|
||||
r = frames[frame + TwoColorTimeline.PREV_R];
|
||||
g = frames[frame + TwoColorTimeline.PREV_G];
|
||||
b = frames[frame + TwoColorTimeline.PREV_B];
|
||||
a = frames[frame + TwoColorTimeline.PREV_A];
|
||||
r2 = frames[frame + TwoColorTimeline.PREV_R2];
|
||||
g2 = frames[frame + TwoColorTimeline.PREV_G2];
|
||||
b2 = frames[frame + TwoColorTimeline.PREV_B2];
|
||||
let frameTime = frames[frame];
|
||||
let percent = this.getCurvePercent(frame / TwoColorTimeline.ENTRIES - 1,
|
||||
1 - (time - frameTime) / (frames[frame + TwoColorTimeline.PREV_TIME] - frameTime));
|
||||
|
||||
r += (frames[frame + TwoColorTimeline.R] - r) * percent;
|
||||
g += (frames[frame + TwoColorTimeline.G] - g) * percent;
|
||||
b += (frames[frame + TwoColorTimeline.B] - b) * percent;
|
||||
a += (frames[frame + TwoColorTimeline.A] - a) * percent;
|
||||
r2 += (frames[frame + TwoColorTimeline.R2] - r2) * percent;
|
||||
g2 += (frames[frame + TwoColorTimeline.G2] - g2) * percent;
|
||||
b2 += (frames[frame + TwoColorTimeline.B2] - b2) * percent;
|
||||
}
|
||||
if (alpha == 1)
|
||||
slot.color.set(r, g, b, a);
|
||||
else {
|
||||
let color = slot.color;
|
||||
if (setupPose) color.setFromColor(slot.data.color);
|
||||
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class AttachmentTimeline implements Timeline {
|
||||
slotIndex: number;
|
||||
frames: ArrayLike<number> // time, ...
|
||||
|
||||
@ -65,5 +65,9 @@ module spine {
|
||||
newPathAttachment (skin: Skin, name: string): PathAttachment {
|
||||
return new PathAttachment(name);
|
||||
}
|
||||
|
||||
newPointAttachment(skin: Skin, name: string): PointAttachment {
|
||||
return new PointAttachment(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,30 +217,6 @@ module spine {
|
||||
return Math.sqrt(this.b * this.b + this.d * this.d);
|
||||
}
|
||||
|
||||
worldToLocalRotationX () {
|
||||
let parent = this.parent;
|
||||
if (parent == null) return this.arotation;
|
||||
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c;
|
||||
return Math.atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.radDeg;
|
||||
}
|
||||
|
||||
worldToLocalRotationY () {
|
||||
let parent = this.parent;
|
||||
if (parent == null) return this.arotation;
|
||||
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d;
|
||||
return Math.atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.radDeg;
|
||||
}
|
||||
|
||||
rotateWorld (degrees: number) {
|
||||
let a = this.a, b = this.b, c = this.c, d = this.d;
|
||||
let cos = MathUtils.cosDeg(degrees), sin = MathUtils.sinDeg(degrees);
|
||||
this.a = cos * a - sin * c;
|
||||
this.b = cos * b - sin * d;
|
||||
this.c = sin * a + cos * c;
|
||||
this.d = sin * b + cos * d;
|
||||
this.appliedValid = false;
|
||||
}
|
||||
|
||||
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
|
||||
* the applied transform after the world transform has been modified directly (eg, by a constraint).
|
||||
* <p>
|
||||
@ -301,5 +277,25 @@ module spine {
|
||||
local.y = x * this.c + y * this.d + this.worldY;
|
||||
return local;
|
||||
}
|
||||
|
||||
worldToLocalRotation (worldRotation: number) {
|
||||
let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation);
|
||||
return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg;
|
||||
}
|
||||
|
||||
localToWorldRotation (localRotation: number) {
|
||||
let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation);
|
||||
return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg;
|
||||
}
|
||||
|
||||
rotateWorld (degrees: number) {
|
||||
let a = this.a, b = this.b, c = this.c, d = this.d;
|
||||
let cos = MathUtils.cosDeg(degrees), sin = MathUtils.sinDeg(degrees);
|
||||
this.a = cos * a - sin * c;
|
||||
this.b = cos * b - sin * d;
|
||||
this.c = sin * a + cos * c;
|
||||
this.d = sin * b + cos * d;
|
||||
this.appliedValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,10 +80,10 @@ module spine {
|
||||
if (scale) lengths = Utils.setArraySize(this.lengths, boneCount);
|
||||
for (let i = 0, n = spacesCount - 1; i < n;) {
|
||||
let bone = bones[i];
|
||||
let length = bone.data.length, x = length * bone.a, y = length * bone.c;
|
||||
length = Math.sqrt(x * x + y * y);
|
||||
let setupLength = bone.data.length, x = setupLength * bone.a, y = setupLength * bone.c;
|
||||
let length = Math.sqrt(x * x + y * y);
|
||||
if (scale) lengths[i] = length;
|
||||
spaces[++i] = lengthSpacing ? Math.max(0, length + spacing) : spacing;
|
||||
spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
|
||||
}
|
||||
} else {
|
||||
for (let i = 1; i < spacesCount; i++)
|
||||
@ -180,14 +180,14 @@ module spine {
|
||||
} else if (p < 0) {
|
||||
if (prevCurve != PathConstraint.BEFORE) {
|
||||
prevCurve = PathConstraint.BEFORE;
|
||||
path.computeWorldVerticesWith(target, 2, 4, world, 0);
|
||||
path.computeWorldVertices(target, 2, 4, world, 0, 2);
|
||||
}
|
||||
this.addBeforePosition(p, world, 0, out, o);
|
||||
continue;
|
||||
} else if (p > pathLength) {
|
||||
if (prevCurve != PathConstraint.AFTER) {
|
||||
prevCurve = PathConstraint.AFTER;
|
||||
path.computeWorldVerticesWith(target, verticesLength - 6, 4, world, 0);
|
||||
path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);
|
||||
}
|
||||
this.addAfterPosition(p - pathLength, world, 0, out, o);
|
||||
continue;
|
||||
@ -208,10 +208,10 @@ module spine {
|
||||
if (curve != prevCurve) {
|
||||
prevCurve = curve;
|
||||
if (closed && curve == curveCount) {
|
||||
path.computeWorldVerticesWith(target, verticesLength - 4, 4, world, 0);
|
||||
path.computeWorldVerticesWith(target, 0, 4, world, 4);
|
||||
path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);
|
||||
path.computeWorldVertices(target, 0, 4, world, 4, 2);
|
||||
} else
|
||||
path.computeWorldVerticesWith(target, curve * 6 + 2, 8, world, 0);
|
||||
path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);
|
||||
}
|
||||
this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
|
||||
tangents || (i > 0 && space == 0));
|
||||
@ -223,15 +223,15 @@ module spine {
|
||||
if (closed) {
|
||||
verticesLength += 2;
|
||||
world = Utils.setArraySize(this.world, verticesLength);
|
||||
path.computeWorldVerticesWith(target, 2, verticesLength - 4, world, 0);
|
||||
path.computeWorldVerticesWith(target, 0, 2, world, verticesLength - 4);
|
||||
path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);
|
||||
path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);
|
||||
world[verticesLength - 2] = world[0];
|
||||
world[verticesLength - 1] = world[1];
|
||||
} else {
|
||||
curveCount--;
|
||||
verticesLength -= 4;
|
||||
world = Utils.setArraySize(this.world, verticesLength);
|
||||
path.computeWorldVerticesWith(target, 2, verticesLength, world, 0);
|
||||
path.computeWorldVertices(target, 2, verticesLength, world, 0, 2);
|
||||
}
|
||||
|
||||
// Curve lengths.
|
||||
|
||||
@ -165,23 +165,23 @@ module spine {
|
||||
if (this.skin != null) this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);
|
||||
if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin)
|
||||
this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone);
|
||||
for (let ii = 0, nn = this.data.skins.length; ii < nn; ii++)
|
||||
this.sortPathConstraintAttachment(this.data.skins[ii], slotIndex, slotBone);
|
||||
for (let i = 0, n = this.data.skins.length; i < n; i++)
|
||||
this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone);
|
||||
|
||||
let attachment = slot.getAttachment();
|
||||
if (attachment instanceof PathAttachment) this.sortPathConstraintAttachmentWith(attachment, slotBone);
|
||||
|
||||
let constrained = constraint.bones;
|
||||
let boneCount = constrained.length;
|
||||
for (let ii = 0; ii < boneCount; ii++)
|
||||
this.sortBone(constrained[ii]);
|
||||
for (let i = 0; i < boneCount; i++)
|
||||
this.sortBone(constrained[i]);
|
||||
|
||||
this._updateCache.push(constraint);
|
||||
|
||||
for (let ii = 0; ii < boneCount; ii++)
|
||||
this.sortReset(constrained[ii].children);
|
||||
for (let ii = 0; ii < boneCount; ii++)
|
||||
constrained[ii].sorted = true;
|
||||
for (let i = 0; i < boneCount; i++)
|
||||
this.sortReset(constrained[i].children);
|
||||
for (let i = 0; i < boneCount; i++)
|
||||
constrained[i].sorted = true;
|
||||
}
|
||||
|
||||
sortTransformConstraint (constraint: TransformConstraint) {
|
||||
@ -189,8 +189,17 @@ module spine {
|
||||
|
||||
let constrained = constraint.bones;
|
||||
let boneCount = constrained.length;
|
||||
for (let ii = 0; ii < boneCount; ii++)
|
||||
this.sortBone(constrained[ii]);
|
||||
if (constraint.data.local) {
|
||||
for (let i = 0; i < boneCount; i++) {
|
||||
let child = constrained[constrained.length - 1];
|
||||
this.sortBone(child.parent);
|
||||
if (!(this._updateCache.indexOf(child) > -1)) this.updateCacheReset.push(child);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < boneCount; i++) {
|
||||
this.sortBone(constrained[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this._updateCache.push(constraint);
|
||||
|
||||
@ -456,23 +465,31 @@ module spine {
|
||||
|
||||
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
||||
* @param offset The distance from the skeleton origin to the bottom left corner of the AABB.
|
||||
* @param size The width and height of the AABB. */
|
||||
getBounds (offset: Vector2, size: Vector2) {
|
||||
* @param size The width and height of the AABB.
|
||||
* @param temp Working memory */
|
||||
getBounds (offset: Vector2, size: Vector2, temp: Array<number>) {
|
||||
if (offset == null) throw new Error("offset cannot be null.");
|
||||
if (size == null) throw new Error("size cannot be null.");
|
||||
let drawOrder = this.drawOrder;
|
||||
let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
|
||||
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
||||
let slot = drawOrder[i];
|
||||
let verticesLength = 0;
|
||||
let vertices: ArrayLike<number> = null;
|
||||
let attachment = slot.getAttachment();
|
||||
if (attachment instanceof RegionAttachment)
|
||||
vertices = (<RegionAttachment>attachment).updateWorldVertices(slot, false);
|
||||
else if (attachment instanceof MeshAttachment) //
|
||||
vertices = (<MeshAttachment>attachment).updateWorldVertices(slot, true);
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
verticesLength = 8;
|
||||
vertices = Utils.setArraySize(temp, verticesLength, 0);
|
||||
(<RegionAttachment>attachment).computeWorldVertices(slot.bone, vertices, 0, 2);
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
let mesh = (<MeshAttachment>attachment);
|
||||
verticesLength = mesh.worldVerticesLength;
|
||||
vertices = Utils.setArraySize(temp, verticesLength, 0);
|
||||
mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
|
||||
}
|
||||
if (vertices != null) {
|
||||
for (let ii = 0, nn = vertices.length; ii < nn; ii += 8) {
|
||||
let x = vertices[ii], y = vertices[ii + 1];
|
||||
for (let i = 0, nn = vertices.length; i < nn; i += 8) {
|
||||
let x = vertices[i], y = vertices[i + 1];
|
||||
minX = Math.min(minX, x);
|
||||
minY = Math.min(minY, y);
|
||||
maxX = Math.max(maxX, x);
|
||||
|
||||
@ -61,11 +61,11 @@ module spine {
|
||||
polygon = Utils.newFloatArray(boundingBox.worldVerticesLength);
|
||||
}
|
||||
polygons.push(polygon);
|
||||
boundingBox.computeWorldVertices(slot, polygon);
|
||||
boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (updateAabb) {
|
||||
if (updateAabb) {
|
||||
this.aabbCompute();
|
||||
} else {
|
||||
this.minX = Number.POSITIVE_INFINITY;
|
||||
|
||||
@ -93,6 +93,9 @@ module spine {
|
||||
let color: string = this.getValue(slotMap, "color", null);
|
||||
if (color != null) data.color.setFromString(color);
|
||||
|
||||
let dark: string = this.getValue(slotMap, "dark", null);
|
||||
if (dark != null) data.darkColor.setFromString(color);
|
||||
|
||||
data.attachmentName = this.getValue(slotMap, "attachment", null);
|
||||
data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
|
||||
skeletonData.slots.push(data);
|
||||
@ -323,6 +326,17 @@ module spine {
|
||||
if (color != null) path.color.setFromString(color);
|
||||
return path;
|
||||
}
|
||||
case "point": {
|
||||
let point = this.attachmentLoader.newPointAttachment(skin, name);
|
||||
if (point == null) return null;
|
||||
point.x = this.getValue(map, "x", 0) * scale;
|
||||
point.y = this.getValue(map, "y", 0) * scale;
|
||||
point.rotation = this.getValue(map, "rotation", 0);
|
||||
|
||||
let color = this.getValue(map, "color", null);
|
||||
if (color != null) point.color.setFromString(color);
|
||||
return point;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -368,7 +382,18 @@ module spine {
|
||||
if (slotIndex == -1) throw new Error("Slot not found: " + slotName);
|
||||
for (let timelineName in slotMap) {
|
||||
let timelineMap = slotMap[timelineName];
|
||||
if (timelineName == "color") {
|
||||
if (timelineName = "attachment") {
|
||||
let timeline = new AttachmentTimeline(timelineMap.length);
|
||||
timeline.slotIndex = slotIndex;
|
||||
|
||||
let frameIndex = 0;
|
||||
for (let i = 0; i < timelineMap.length; i++) {
|
||||
let valueMap = timelineMap[i];
|
||||
timeline.setFrame(frameIndex++, valueMap.time, valueMap.name);
|
||||
}
|
||||
timelines.push(timeline);
|
||||
duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
|
||||
} else if (timelineName == "color") {
|
||||
let timeline = new ColorTimeline(timelineMap.length);
|
||||
timeline.slotIndex = slotIndex;
|
||||
|
||||
@ -384,17 +409,24 @@ module spine {
|
||||
timelines.push(timeline);
|
||||
duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * ColorTimeline.ENTRIES]);
|
||||
|
||||
} else if (timelineName = "attachment") {
|
||||
let timeline = new AttachmentTimeline(timelineMap.length);
|
||||
} else if (timelineName == "twoColor") {
|
||||
let timeline = new TwoColorTimeline(timelineMap.length);
|
||||
timeline.slotIndex = slotIndex;
|
||||
|
||||
let frameIndex = 0;
|
||||
for (let i = 0; i < timelineMap.length; i++) {
|
||||
let valueMap = timelineMap[i];
|
||||
timeline.setFrame(frameIndex++, valueMap.time, valueMap.name);
|
||||
let light = new Color();
|
||||
let dark = new Color();
|
||||
light.setFromString(valueMap.color);
|
||||
dark.setFromString(valueMap.dark);
|
||||
timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
|
||||
this.readCurve(valueMap, timeline, frameIndex);
|
||||
frameIndex++;
|
||||
}
|
||||
timelines.push(timeline);
|
||||
duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
|
||||
duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * TwoColorTimeline.ENTRIES]);
|
||||
|
||||
} else
|
||||
throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
|
||||
}
|
||||
@ -707,7 +739,7 @@ module spine {
|
||||
}
|
||||
|
||||
static transformModeFromString(str: string) {
|
||||
str = str.toLowerCase();
|
||||
str = str.toLowerCase();
|
||||
if (str == "normal") return TransformMode.Normal;
|
||||
if (str == "onlytranslation") return TransformMode.OnlyTranslation;
|
||||
if (str == "norotationorreflection") return TransformMode.NoRotationOrReflection;
|
||||
|
||||
@ -33,6 +33,7 @@ module spine {
|
||||
data: SlotData;
|
||||
bone: Bone;
|
||||
color: Color;
|
||||
darkColor: Color;
|
||||
private attachment: Attachment;
|
||||
private attachmentTime: number;
|
||||
attachmentVertices = new Array<number>();
|
||||
@ -43,6 +44,7 @@ module spine {
|
||||
this.data = data;
|
||||
this.bone = bone;
|
||||
this.color = new Color();
|
||||
this.darkColor = data.darkColor == null ? null : new Color();
|
||||
this.setToSetupPose();
|
||||
}
|
||||
|
||||
@ -71,6 +73,7 @@ module spine {
|
||||
|
||||
setToSetupPose () {
|
||||
this.color.setFromColor(this.data.color);
|
||||
if (this.darkColor != null) this.darkColor.setFromColor(this.data.darkColor);
|
||||
if (this.data.attachmentName == null)
|
||||
this.attachment = null;
|
||||
else {
|
||||
|
||||
@ -34,6 +34,7 @@ module spine {
|
||||
name: string;
|
||||
boneData: BoneData;
|
||||
color = new Color(1, 1, 1, 1);
|
||||
darkColor: Color;
|
||||
attachmentName: string;
|
||||
blendMode: BlendMode;
|
||||
|
||||
|
||||
@ -55,6 +55,21 @@ module spine {
|
||||
}
|
||||
|
||||
update () {
|
||||
if (this.data.local) {
|
||||
if (this.data.relative)
|
||||
this.applyRelativeLocal();
|
||||
else
|
||||
this.applyAbsoluteLocal();
|
||||
|
||||
} else {
|
||||
if (this.data.relative)
|
||||
this.applyRelativeWorld();
|
||||
else
|
||||
this.applyAbsoluteWorld();
|
||||
}
|
||||
}
|
||||
|
||||
applyAbsoluteWorld () {
|
||||
let rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
|
||||
let target = this.target;
|
||||
let ta = target.a, tb = target.b, tc = target.c, td = target.d;
|
||||
@ -123,6 +138,137 @@ module spine {
|
||||
}
|
||||
}
|
||||
|
||||
applyRelativeWorld () {
|
||||
let rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
|
||||
let target = this.target;
|
||||
let ta = target.a, tb = target.b, tc = target.c, td = target.d;
|
||||
let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;
|
||||
let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect;
|
||||
let bones = this.bones;
|
||||
for (let i = 0, n = bones.length; i < n; i++) {
|
||||
let bone = bones[i];
|
||||
let modified = false;
|
||||
|
||||
if (rotateMix != 0) {
|
||||
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
||||
let r = Math.atan2(tc, ta) + offsetRotation;
|
||||
if (r > MathUtils.PI)
|
||||
r -= MathUtils.PI2;
|
||||
else if (r < -MathUtils.PI) r += MathUtils.PI2;
|
||||
r *= rotateMix;
|
||||
let cos = Math.cos(r), sin = Math.sin(r);
|
||||
bone.a = cos * a - sin * c;
|
||||
bone.b = cos * b - sin * d;
|
||||
bone.c = sin * a + cos * c;
|
||||
bone.d = sin * b + cos * d;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (translateMix != 0) {
|
||||
let temp = this.temp;
|
||||
target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));
|
||||
bone.worldX += temp.x * translateMix;
|
||||
bone.worldY += temp.y * translateMix;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (scaleMix > 0) {
|
||||
let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1;
|
||||
bone.a *= s;
|
||||
bone.c *= s;
|
||||
s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1;
|
||||
bone.b *= s;
|
||||
bone.d *= s;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (shearMix > 0) {
|
||||
let r = Math.atan2(td, tb) - Math.atan2(tc, ta);
|
||||
if (r > MathUtils.PI)
|
||||
r -= MathUtils.PI2;
|
||||
else if (r < -MathUtils.PI) r += MathUtils.PI2;
|
||||
let b = bone.b, d = bone.d;
|
||||
r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * shearMix;
|
||||
let s = Math.sqrt(b * b + d * d);
|
||||
bone.b = Math.cos(r) * s;
|
||||
bone.d = Math.sin(r) * s;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified) bone.appliedValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
applyAbsoluteLocal () {
|
||||
let rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
|
||||
let target = this.target;
|
||||
if (!target.appliedValid) target.updateAppliedTransform();
|
||||
let bones = this.bones;
|
||||
for (let i = 0, n = bones.length; i < n; i++) {
|
||||
let bone = bones[i];
|
||||
if (!bone.appliedValid) bone.updateAppliedTransform();
|
||||
|
||||
let rotation = bone.arotation;
|
||||
if (rotateMix != 0) {
|
||||
let r = target.arotation - rotation + this.data.offsetRotation;
|
||||
r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
|
||||
rotation += r * rotateMix;
|
||||
}
|
||||
|
||||
let x = bone.ax, y = bone.ay;
|
||||
if (translateMix != 0) {
|
||||
x += (target.ax - x + this.data.offsetX) * translateMix;
|
||||
y += (target.ay - y + this.data.offsetY) * translateMix;
|
||||
}
|
||||
|
||||
let scaleX = bone.ascaleX, scaleY = bone.ascaleY;
|
||||
if (scaleMix > 0) {
|
||||
if (scaleX > 0.00001) scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX;
|
||||
if (scaleY > 0.00001) scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY;
|
||||
}
|
||||
|
||||
let shearY = bone.ashearY;
|
||||
if (shearMix > 0) {
|
||||
let r = target.ashearY - shearY + this.data.offsetShearY;
|
||||
r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
|
||||
bone.shearY += r * shearMix;
|
||||
}
|
||||
|
||||
bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
||||
}
|
||||
}
|
||||
|
||||
applyRelativeLocal () {
|
||||
let rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
|
||||
let target = this.target;
|
||||
if (!target.appliedValid) target.updateAppliedTransform();
|
||||
let bones = this.bones;
|
||||
for (let i = 0, n = bones.length; i < n; i++) {
|
||||
let bone = bones[i];
|
||||
if (!bone.appliedValid) bone.updateAppliedTransform();
|
||||
|
||||
let rotation = bone.arotation;
|
||||
if (rotateMix != 0) rotation += (target.arotation + this.data.offsetRotation) * rotateMix;
|
||||
|
||||
let x = bone.ax, y = bone.ay;
|
||||
if (translateMix != 0) {
|
||||
x += (target.ax + this.data.offsetX) * translateMix;
|
||||
y += (target.ay + this.data.offsetY) * translateMix;
|
||||
}
|
||||
|
||||
let scaleX = bone.ascaleX, scaleY = bone.ascaleY;
|
||||
if (scaleMix > 0) {
|
||||
if (scaleX > 0.00001) scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1;
|
||||
if (scaleY > 0.00001) scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1;
|
||||
}
|
||||
|
||||
let shearY = bone.ashearY;
|
||||
if (shearMix > 0) shearY += (target.ashearY + this.data.offsetShearY) * shearMix;
|
||||
|
||||
bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
||||
}
|
||||
}
|
||||
|
||||
getOrder () {
|
||||
return this.data.order;
|
||||
}
|
||||
|
||||
@ -36,6 +36,8 @@ module spine {
|
||||
target: BoneData;
|
||||
rotateMix = 0; translateMix = 0; scaleMix = 0; shearMix = 0;
|
||||
offsetRotation = 0; offsetX = 0; offsetY = 0; offsetScaleX = 0; offsetScaleY = 0; offsetShearY = 0;
|
||||
relative = false;
|
||||
local = false;
|
||||
|
||||
constructor (name: string) {
|
||||
if (name == null) throw new Error("name cannot be null.");
|
||||
|
||||
@ -47,17 +47,13 @@ module spine {
|
||||
super(name);
|
||||
}
|
||||
|
||||
computeWorldVertices (slot: Slot, worldVertices: ArrayLike<number>) {
|
||||
this.computeWorldVerticesWith(slot, 0, this.worldVerticesLength, worldVertices, 0);
|
||||
}
|
||||
|
||||
/** Transforms local vertices to world coordinates.
|
||||
* @param start The index of the first local vertex value to transform. Each vertex has 2 values, x and y.
|
||||
* @param count The number of world vertex values to output. Must be <= {@link #getWorldVerticesLength()} - start.
|
||||
* @param worldVertices The output world vertices. Must have a length >= offset + count.
|
||||
* @param offset The worldVertices index to begin writing values. */
|
||||
computeWorldVerticesWith (slot: Slot, start: number, count: number, worldVertices: ArrayLike<number>, offset: number) {
|
||||
count += offset;
|
||||
computeWorldVertices (slot: Slot, start: number, count: number, worldVertices: ArrayLike<number>, offset: number, stride: number) {
|
||||
count = offset + (count >> 1) * stride;
|
||||
let skeleton = slot.bone.skeleton;
|
||||
let deformArray = slot.attachmentVertices;
|
||||
let vertices = this.vertices;
|
||||
@ -68,7 +64,7 @@ module spine {
|
||||
let x = bone.worldX;
|
||||
let y = bone.worldY;
|
||||
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
||||
for (let v = start, w = offset; w < count; v += 2, w += 2) {
|
||||
for (let v = start, w = offset; w < count; v += 2, w += stride) {
|
||||
let vx = vertices[v], vy = vertices[v + 1];
|
||||
worldVertices[w] = vx * a + vy * b + x;
|
||||
worldVertices[w + 1] = vx * c + vy * d + y;
|
||||
@ -83,7 +79,7 @@ module spine {
|
||||
}
|
||||
let skeletonBones = skeleton.bones;
|
||||
if (deformArray.length == 0) {
|
||||
for (let w = offset, b = skip * 3; w < count; w += 2) {
|
||||
for (let w = offset, b = skip * 3; w < count; w += stride) {
|
||||
let wx = 0, wy = 0;
|
||||
let n = bones[v++];
|
||||
n += v;
|
||||
@ -98,7 +94,7 @@ module spine {
|
||||
}
|
||||
} else {
|
||||
let deform = deformArray;
|
||||
for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) {
|
||||
for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {
|
||||
let wx = 0, wy = 0;
|
||||
let n = bones[v++];
|
||||
n += v;
|
||||
|
||||
@ -41,5 +41,8 @@ module spine {
|
||||
|
||||
/** @return May be null to not load an attachment */
|
||||
newPathAttachment(skin: Skin, name: string): PathAttachment;
|
||||
|
||||
/** @return May be null to not load an attachment */
|
||||
newPointAttachment(skin: Skin, name: string): PointAttachment;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,6 @@
|
||||
|
||||
module spine {
|
||||
export enum AttachmentType {
|
||||
Region, BoundingBox, Mesh, LinkedMesh, Path
|
||||
Region, BoundingBox, Mesh, LinkedMesh, Path, Point
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ module spine {
|
||||
export class MeshAttachment extends VertexAttachment {
|
||||
region: TextureRegion;
|
||||
path: string;
|
||||
regionUVs: ArrayLike<number>; worldVertices: ArrayLike<number>;
|
||||
regionUVs: ArrayLike<number>; uvs: ArrayLike<number>;
|
||||
triangles: Array<number>;
|
||||
color = new Color(1, 1, 1, 1);
|
||||
hullLength: number;
|
||||
@ -45,12 +45,6 @@ module spine {
|
||||
}
|
||||
|
||||
updateUVs () {
|
||||
let regionUVs = this.regionUVs;
|
||||
let verticesLength = regionUVs.length;
|
||||
let worldVerticesLength = (verticesLength >> 1) * 8;
|
||||
if (this.worldVertices == null || this.worldVertices.length != worldVerticesLength)
|
||||
this.worldVertices = Utils.newFloatArray(worldVerticesLength);
|
||||
|
||||
let u = 0, v = 0, width = 0, height = 0;
|
||||
if (this.region == null) {
|
||||
u = v = 0;
|
||||
@ -61,92 +55,22 @@ module spine {
|
||||
width = this.region.u2 - u;
|
||||
height = this.region.v2 - v;
|
||||
}
|
||||
let regionUVs = this.regionUVs;
|
||||
if (this.uvs == null || this.uvs.length != regionUVs.length) this.uvs = Utils.newFloatArray(regionUVs.length);
|
||||
let uvs = this.uvs;
|
||||
if (this.region.rotate) {
|
||||
for (let i = 0, w = 6; i < verticesLength; i += 2, w += 8) {
|
||||
this.worldVertices[w] = u + regionUVs[i + 1] * width;
|
||||
this.worldVertices[w + 1] = v + height - regionUVs[i] * height;
|
||||
for (let i = 0, n = uvs.length; i < n; i += 2) {
|
||||
uvs[i] = u + regionUVs[i + 1] * width;
|
||||
uvs[i + 1] = v + height - regionUVs[i] * height;
|
||||
}
|
||||
} else {
|
||||
for (let i = 0, w = 6; i < verticesLength; i += 2, w += 8) {
|
||||
this.worldVertices[w] = u + regionUVs[i] * width;
|
||||
this.worldVertices[w + 1] = v + regionUVs[i + 1] * height;
|
||||
for (let i = 0, n = uvs.length; i < n; i += 2) {
|
||||
uvs[i] = u + regionUVs[i] * width;
|
||||
uvs[i] = v + regionUVs[i + 1] * height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @return The updated world vertices. */
|
||||
updateWorldVertices (slot: Slot, premultipliedAlpha: boolean) {
|
||||
let skeleton = slot.bone.skeleton;
|
||||
let skeletonColor = skeleton.color, slotColor = slot.color, meshColor = this.color;
|
||||
let alpha = skeletonColor.a * slotColor.a * meshColor.a;
|
||||
let multiplier = premultipliedAlpha ? alpha : 1;
|
||||
let color = this.tempColor;
|
||||
color.set(skeletonColor.r * slotColor.r * meshColor.r * multiplier,
|
||||
skeletonColor.g * slotColor.g * meshColor.g * multiplier,
|
||||
skeletonColor.b * slotColor.b * meshColor.b * multiplier,
|
||||
alpha);
|
||||
|
||||
let deformArray = slot.attachmentVertices;
|
||||
let vertices = this.vertices, worldVertices = this.worldVertices;
|
||||
let bones = this.bones;
|
||||
if (bones == null) {
|
||||
let verticesLength = vertices.length;
|
||||
if (deformArray.length > 0) vertices = deformArray;
|
||||
let bone = slot.bone;
|
||||
let x = bone.worldX;
|
||||
let y = bone.worldY;
|
||||
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
||||
for (let v = 0, w = 0; v < verticesLength; v += 2, w += 8) {
|
||||
let vx = vertices[v], vy = vertices[v + 1];
|
||||
worldVertices[w] = vx * a + vy * b + x;
|
||||
worldVertices[w + 1] = vx * c + vy * d + y;
|
||||
worldVertices[w + 2] = color.r;
|
||||
worldVertices[w + 3] = color.g;
|
||||
worldVertices[w + 4] = color.b;
|
||||
worldVertices[w + 5] = color.a;
|
||||
}
|
||||
return worldVertices;
|
||||
}
|
||||
let skeletonBones = skeleton.bones;
|
||||
if (deformArray.length == 0) {
|
||||
for (let w = 0, v = 0, b = 0, n = bones.length; v < n; w += 8) {
|
||||
let wx = 0, wy = 0;
|
||||
let nn = bones[v++] + v;
|
||||
for (; v < nn; v++, b += 3) {
|
||||
let bone = skeletonBones[bones[v]];
|
||||
let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
|
||||
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
||||
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
||||
}
|
||||
worldVertices[w] = wx;
|
||||
worldVertices[w + 1] = wy;
|
||||
worldVertices[w + 2] = color.r;
|
||||
worldVertices[w + 3] = color.g;
|
||||
worldVertices[w + 4] = color.b;
|
||||
worldVertices[w + 5] = color.a;
|
||||
}
|
||||
} else {
|
||||
let deform = deformArray;
|
||||
for (let w = 0, v = 0, b = 0, f = 0, n = bones.length; v < n; w += 8) {
|
||||
let wx = 0, wy = 0;
|
||||
let nn = bones[v++] + v;
|
||||
for (; v < nn; v++, b += 3, f += 2) {
|
||||
let bone = skeletonBones[bones[v]];
|
||||
let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
|
||||
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
||||
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
||||
}
|
||||
worldVertices[w] = wx;
|
||||
worldVertices[w + 1] = wy;
|
||||
worldVertices[w + 2] = color.r;
|
||||
worldVertices[w + 3] = color.g;
|
||||
worldVertices[w + 4] = color.b;
|
||||
worldVertices[w + 5] = color.a;
|
||||
}
|
||||
}
|
||||
return worldVertices;
|
||||
}
|
||||
|
||||
applyDeform (sourceAttachment: VertexAttachment): boolean {
|
||||
return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment);
|
||||
}
|
||||
|
||||
53
spine-ts/core/src/attachments/PointAttachment.ts
Normal file
53
spine-ts/core/src/attachments/PointAttachment.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License v2.5
|
||||
*
|
||||
* Copyright (c) 2013-2016, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable, and
|
||||
* non-transferable license to use, install, execute, and perform the Spine
|
||||
* Runtimes software and derivative works solely for personal or internal
|
||||
* use. Without the written permission of Esoteric Software (see Section 2 of
|
||||
* the Spine Software License Agreement), you may not (a) modify, translate,
|
||||
* adapt, or develop new applications using the Spine Runtimes or otherwise
|
||||
* create derivative works or improvements of the Spine Runtimes or (b) remove,
|
||||
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
|
||||
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
module spine {
|
||||
export class PointAttachment extends VertexAttachment {
|
||||
x: number; y: number; rotation: number;
|
||||
color = new Color(0.38, 0.94, 0, 1);
|
||||
|
||||
constructor (name: string) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
computeWorldPosition (bone: Bone, point: Vector2) {
|
||||
point.x = this.x * bone.a + this.y * bone.b + bone.worldX;
|
||||
point.y = this.x * bone.c + this.y * bone.d + bone.worldY;
|
||||
return point;
|
||||
}
|
||||
|
||||
computeWorldRotation (bone: Bone) {
|
||||
let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation);
|
||||
let x = cos * bone.a + sin * bone.b;
|
||||
let y = cos * bone.c + sin * bone.d;
|
||||
return Math.atan2(y, x) * MathUtils.radDeg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,7 +83,7 @@ module spine {
|
||||
region: TextureRegion;
|
||||
|
||||
offset = Utils.newFloatArray(8);
|
||||
vertices = Utils.newFloatArray(8 * 4);
|
||||
uvs = Utils.newFloatArray(8);
|
||||
|
||||
tempColor = new Color(1, 1, 1, 1);
|
||||
|
||||
@ -91,30 +91,6 @@ module spine {
|
||||
super(name);
|
||||
}
|
||||
|
||||
setRegion (region: TextureRegion) : void {
|
||||
let vertices = this.vertices;
|
||||
if (region.rotate) {
|
||||
vertices[RegionAttachment.U2] = region.u;
|
||||
vertices[RegionAttachment.V2] = region.v2;
|
||||
vertices[RegionAttachment.U3] = region.u;
|
||||
vertices[RegionAttachment.V3] = region.v;
|
||||
vertices[RegionAttachment.U4] = region.u2;
|
||||
vertices[RegionAttachment.V4] = region.v;
|
||||
vertices[RegionAttachment.U1] = region.u2;
|
||||
vertices[RegionAttachment.V1] = region.v2;
|
||||
} else {
|
||||
vertices[RegionAttachment.U1] = region.u;
|
||||
vertices[RegionAttachment.V1] = region.v2;
|
||||
vertices[RegionAttachment.U2] = region.u;
|
||||
vertices[RegionAttachment.V2] = region.v;
|
||||
vertices[RegionAttachment.U3] = region.u2;
|
||||
vertices[RegionAttachment.V3] = region.v;
|
||||
vertices[RegionAttachment.U4] = region.u2;
|
||||
vertices[RegionAttachment.V4] = region.v2;
|
||||
}
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
updateOffset () : void {
|
||||
let regionScaleX = this.width / this.region.originalWidth * this.scaleX;
|
||||
let regionScaleY = this.height / this.region.originalHeight * this.scaleY;
|
||||
@ -144,63 +120,58 @@ module spine {
|
||||
offset[RegionAttachment.OY4] = localYCos + localX2Sin;
|
||||
}
|
||||
|
||||
updateWorldVertices (slot: Slot, premultipliedAlpha: boolean) {
|
||||
let skeleton = slot.bone.skeleton;
|
||||
let skeletonColor = skeleton.color;
|
||||
let slotColor = slot.color;
|
||||
let regionColor = this.color;
|
||||
let alpha = skeletonColor.a * slotColor.a * regionColor.a;
|
||||
let multiplier = premultipliedAlpha ? alpha : 1;
|
||||
let color = this.tempColor;
|
||||
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
|
||||
skeletonColor.g * slotColor.g * regionColor.g * multiplier,
|
||||
skeletonColor.b * slotColor.b * regionColor.b * multiplier,
|
||||
alpha);
|
||||
setRegion (region: TextureRegion) : void {
|
||||
this.region = region;
|
||||
let uvs = this.uvs;
|
||||
if (region.rotate) {
|
||||
uvs[2] = region.u;
|
||||
uvs[3] = region.v2;
|
||||
uvs[4] = region.u;
|
||||
uvs[5] = region.v;
|
||||
uvs[6] = region.u2;
|
||||
uvs[7] = region.v;
|
||||
uvs[0] = region.u2;
|
||||
uvs[1] = region.v2;
|
||||
} else {
|
||||
uvs[0] = region.u;
|
||||
uvs[1] = region.v2;
|
||||
uvs[2] = region.u;
|
||||
uvs[3] = region.v;
|
||||
uvs[4] = region.u2;
|
||||
uvs[5] = region.v;
|
||||
uvs[6] = region.u2;
|
||||
uvs[7] = region.v2;
|
||||
}
|
||||
}
|
||||
|
||||
let vertices = this.vertices;
|
||||
let offset = this.offset;
|
||||
let bone = slot.bone;
|
||||
computeWorldVertices (bone: Bone, worldVertices: ArrayLike<number>, offset: number, stride: number) {
|
||||
let vertexOffset = this.offset;
|
||||
let x = bone.worldX, y = bone.worldY;
|
||||
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
||||
let offsetX = 0, offsetY = 0;
|
||||
|
||||
offsetX = offset[RegionAttachment.OX1];
|
||||
offsetY = offset[RegionAttachment.OY1];
|
||||
vertices[RegionAttachment.X1] = offsetX * a + offsetY * b + x; // br
|
||||
vertices[RegionAttachment.Y1] = offsetX * c + offsetY * d + y;
|
||||
vertices[RegionAttachment.C1R] = color.r;
|
||||
vertices[RegionAttachment.C1G] = color.g;
|
||||
vertices[RegionAttachment.C1B] = color.b;
|
||||
vertices[RegionAttachment.C1A] = color.a;
|
||||
offsetX = vertexOffset[RegionAttachment.OX1];
|
||||
offsetY = vertexOffset[RegionAttachment.OY1];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // br
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = offset[RegionAttachment.OX2];
|
||||
offsetY = offset[RegionAttachment.OY2];
|
||||
vertices[RegionAttachment.X2] = offsetX * a + offsetY * b + x; // bl
|
||||
vertices[RegionAttachment.Y2] = offsetX * c + offsetY * d + y;
|
||||
vertices[RegionAttachment.C2R] = color.r;
|
||||
vertices[RegionAttachment.C2G] = color.g;
|
||||
vertices[RegionAttachment.C2B] = color.b;
|
||||
vertices[RegionAttachment.C2A] = color.a;
|
||||
offsetX = vertexOffset[RegionAttachment.OX2];
|
||||
offsetY = vertexOffset[RegionAttachment.OY2];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // bl
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = offset[RegionAttachment.OX3];
|
||||
offsetY = offset[RegionAttachment.OY3];
|
||||
vertices[RegionAttachment.X3] = offsetX * a + offsetY * b + x; // ul
|
||||
vertices[RegionAttachment.Y3] = offsetX * c + offsetY * d + y;
|
||||
vertices[RegionAttachment.C3R] = color.r;
|
||||
vertices[RegionAttachment.C3G] = color.g;
|
||||
vertices[RegionAttachment.C3B] = color.b;
|
||||
vertices[RegionAttachment.C3A] = color.a;
|
||||
offsetX = vertexOffset[RegionAttachment.OX3];
|
||||
offsetY = vertexOffset[RegionAttachment.OY3];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // ul
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = offset[RegionAttachment.OX4];
|
||||
offsetY = offset[RegionAttachment.OY4];
|
||||
vertices[RegionAttachment.X4] = offsetX * a + offsetY * b + x; // ur
|
||||
vertices[RegionAttachment.Y4] = offsetX * c + offsetY * d + y;
|
||||
vertices[RegionAttachment.C4R] = color.r;
|
||||
vertices[RegionAttachment.C4G] = color.g;
|
||||
vertices[RegionAttachment.C4B] = color.b;
|
||||
vertices[RegionAttachment.C4A] = color.a;
|
||||
|
||||
return vertices;
|
||||
offsetX = vertexOffset[RegionAttachment.OX4];
|
||||
offsetY = vertexOffset[RegionAttachment.OY4];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // ur
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ function loadSkeleton (name, initialAnimation, premultipliedAlpha, skin) {
|
||||
animationStateData = new spine.AnimationStateData(skeleton.data);
|
||||
var animationState = new spine.AnimationState(animationStateData);
|
||||
if (name == "spineboy") {
|
||||
animationStateData.setMix("walk", "jump", 0.4)
|
||||
animationStateData.setMix("walk", "jump", 0.4)
|
||||
animationStateData.setMix("jump", "run", 0.4);
|
||||
animationState.setAnimation(0, "walk", true);
|
||||
var jumpEntry = animationState.addAnimation(0, "jump", false, 3);
|
||||
@ -157,7 +157,7 @@ function calculateBounds(skeleton) {
|
||||
skeleton.updateWorldTransform();
|
||||
var offset = new spine.Vector2();
|
||||
var size = new spine.Vector2();
|
||||
skeleton.getBounds(offset, size);
|
||||
skeleton.getBounds(offset, size, []);
|
||||
return { offset: offset, size: size };
|
||||
}
|
||||
|
||||
|
||||
@ -30,10 +30,12 @@
|
||||
|
||||
module spine.webgl {
|
||||
export class SkeletonRenderer {
|
||||
static VERTEX_SIZE = 2 + 2 + 4;
|
||||
static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
|
||||
|
||||
premultipliedAlpha = false;
|
||||
private gl: WebGLRenderingContext;
|
||||
private tempColor = new Color();
|
||||
|
||||
constructor (gl: WebGLRenderingContext) {
|
||||
this.gl = gl;
|
||||
@ -52,13 +54,13 @@ module spine.webgl {
|
||||
let texture: GLTexture = null;
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
let region = <RegionAttachment>attachment;
|
||||
vertices = region.updateWorldVertices(slot, premultipliedAlpha);
|
||||
vertices = this.computeRegionVertices(slot, region, premultipliedAlpha);
|
||||
triangles = SkeletonRenderer.QUAD_TRIANGLES;
|
||||
texture = <GLTexture>(<TextureAtlasRegion>region.region.renderObject).texture;
|
||||
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
let mesh = <MeshAttachment>attachment;
|
||||
vertices = mesh.updateWorldVertices(slot, premultipliedAlpha);
|
||||
vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha);
|
||||
triangles = mesh.triangles;
|
||||
texture = <GLTexture>(<TextureAtlasRegion>mesh.region.renderObject).texture;
|
||||
} else continue;
|
||||
@ -73,5 +75,85 @@ module spine.webgl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
computeRegionVertices(slot: Slot, region: RegionAttachment, pma: boolean) {
|
||||
let skeleton = slot.bone.skeleton;
|
||||
let skeletonColor = skeleton.color;
|
||||
let slotColor = slot.color;
|
||||
let regionColor = region.color;
|
||||
let alpha = skeletonColor.a * slotColor.a * regionColor.a;
|
||||
let multiplier = pma ? alpha : 1;
|
||||
let color = this.tempColor;
|
||||
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
|
||||
skeletonColor.g * slotColor.g * regionColor.g * multiplier,
|
||||
skeletonColor.b * slotColor.b * regionColor.b * multiplier,
|
||||
alpha);
|
||||
|
||||
let vertices = Utils.newFloatArray(4 * SkeletonRenderer.VERTEX_SIZE);
|
||||
region.computeWorldVertices(slot.bone, vertices, 0, SkeletonRenderer.VERTEX_SIZE);
|
||||
|
||||
let uvs = region.uvs;
|
||||
|
||||
vertices[RegionAttachment.U1] = uvs[0];
|
||||
vertices[RegionAttachment.V1] = uvs[1];
|
||||
vertices[RegionAttachment.C1R] = color.r;
|
||||
vertices[RegionAttachment.C1G] = color.g;
|
||||
vertices[RegionAttachment.C1B] = color.b;
|
||||
vertices[RegionAttachment.C1A] = color.a;
|
||||
|
||||
vertices[RegionAttachment.U2] = uvs[2];
|
||||
vertices[RegionAttachment.V2] = uvs[3];
|
||||
vertices[RegionAttachment.C2R] = color.r;
|
||||
vertices[RegionAttachment.C2G] = color.g;
|
||||
vertices[RegionAttachment.C2B] = color.b;
|
||||
vertices[RegionAttachment.C2A] = color.a;
|
||||
|
||||
vertices[RegionAttachment.U3] = uvs[4];
|
||||
vertices[RegionAttachment.V3] = uvs[5];
|
||||
vertices[RegionAttachment.C3R] = color.r;
|
||||
vertices[RegionAttachment.C3G] = color.g;
|
||||
vertices[RegionAttachment.C3B] = color.b;
|
||||
vertices[RegionAttachment.C3A] = color.a;
|
||||
|
||||
vertices[RegionAttachment.U4] = uvs[6];
|
||||
vertices[RegionAttachment.V4] = uvs[7];
|
||||
vertices[RegionAttachment.C4R] = color.r;
|
||||
vertices[RegionAttachment.C4G] = color.g;
|
||||
vertices[RegionAttachment.C4B] = color.b;
|
||||
vertices[RegionAttachment.C4A] = color.a;
|
||||
|
||||
return vertices;
|
||||
}
|
||||
|
||||
computeMeshVertices(slot: Slot, mesh: MeshAttachment, pma: boolean) {
|
||||
let skeleton = slot.bone.skeleton;
|
||||
let skeletonColor = skeleton.color;
|
||||
let slotColor = slot.color;
|
||||
let regionColor = mesh.color;
|
||||
let alpha = skeletonColor.a * slotColor.a * regionColor.a;
|
||||
let multiplier = pma ? alpha : 1;
|
||||
let color = this.tempColor;
|
||||
color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
|
||||
skeletonColor.g * slotColor.g * regionColor.g * multiplier,
|
||||
skeletonColor.b * slotColor.b * regionColor.b * multiplier,
|
||||
alpha);
|
||||
|
||||
let numVertices = mesh.worldVerticesLength / 2;
|
||||
let vertices = Utils.newFloatArray(numVertices * SkeletonRenderer.VERTEX_SIZE);
|
||||
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE);
|
||||
|
||||
let uvs = mesh.uvs;
|
||||
for (let i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
|
||||
vertices[v++] = uvs[u++];
|
||||
vertices[v++] = uvs[u++];
|
||||
vertices[v++] = color.r;
|
||||
vertices[v++] = color.g;
|
||||
vertices[v++] = color.b;
|
||||
vertices[v++] = color.a;
|
||||
v += 2;
|
||||
}
|
||||
|
||||
return vertices;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user