mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-22 10:16:01 +08:00
[haxe] Initial port complete. WIP.
This commit is contained in:
parent
9d8c32b496
commit
fafb585882
@ -1,20 +1,24 @@
|
|||||||
package spine;
|
package spine;
|
||||||
|
|
||||||
class SequenceMode {
|
import openfl.Vector;
|
||||||
public static var hold(default, never):RotateMode = new SequenceMode("hold");
|
|
||||||
public static var once(default, never):RotateMode = new SequenceMode("once");
|
|
||||||
public static var loop(default, never):RotateMode = new SequenceMode("loop");
|
|
||||||
public static var pingpong(default, never):RotateMode = new SequenceMode("pingpong");
|
|
||||||
public static var onceReverse(default, never):RotateMode = new SequenceMode("onceReverse");
|
|
||||||
public static var loopReverse(default, never):RotateMode = new SequenceMode("loopReverse");
|
|
||||||
public static var pingpongReverse(default, never):RotateMode = new SequenceMode("pingpongReverse");
|
|
||||||
|
|
||||||
public static var values(default, never):Vector<SequenceMode> = Vector.ofArray([tangent, chain, chainScale]);
|
class SequenceMode {
|
||||||
|
public static var hold(default, never):SequenceMode = new SequenceMode("hold", 0);
|
||||||
|
public static var once(default, never):SequenceMode = new SequenceMode("once", 1);
|
||||||
|
public static var loop(default, never):SequenceMode = new SequenceMode("loop", 2);
|
||||||
|
public static var pingpong(default, never):SequenceMode = new SequenceMode("pingpong", 3);
|
||||||
|
public static var onceReverse(default, never):SequenceMode = new SequenceMode("onceReverse", 4);
|
||||||
|
public static var loopReverse(default, never):SequenceMode = new SequenceMode("loopReverse", 5);
|
||||||
|
public static var pingpongReverse(default, never):SequenceMode = new SequenceMode("pingpongReverse", 6);
|
||||||
|
|
||||||
|
public static var values(default, never):Vector<SequenceMode> = Vector.ofArray([hold, once, loop, pingpong, onceReverse, loopReverse, pingpongReverse]);
|
||||||
|
|
||||||
public var name(default, null):String;
|
public var name(default, null):String;
|
||||||
|
public var value:Int;
|
||||||
|
|
||||||
public function new(name:String) {
|
public function new(name:String, value:Int) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fromName(name:String):SequenceMode {
|
public static function fromName(name:String):SequenceMode {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package spine;
|
package spine;
|
||||||
|
|
||||||
|
import spine.animation.SequenceTimeline;
|
||||||
import openfl.errors.ArgumentError;
|
import openfl.errors.ArgumentError;
|
||||||
import openfl.errors.Error;
|
import openfl.errors.Error;
|
||||||
import openfl.utils.ByteArray;
|
import openfl.utils.ByteArray;
|
||||||
@ -69,6 +70,9 @@ class SkeletonBinary {
|
|||||||
private static inline var SLOT_RGB2:Int = 4;
|
private static inline var SLOT_RGB2:Int = 4;
|
||||||
private static inline var SLOT_ALPHA:Int = 5;
|
private static inline var SLOT_ALPHA:Int = 5;
|
||||||
|
|
||||||
|
private static inline var ATTACHMENT_DEFORM = 0;
|
||||||
|
private static inline var ATTACHMENT_SEQUENCE = 1;
|
||||||
|
|
||||||
private static inline var PATH_POSITION:Int = 0;
|
private static inline var PATH_POSITION:Int = 0;
|
||||||
private static inline var PATH_SPACING:Int = 1;
|
private static inline var PATH_SPACING:Int = 1;
|
||||||
private static inline var PATH_MIX:Int = 2;
|
private static inline var PATH_MIX:Int = 2;
|
||||||
@ -253,13 +257,14 @@ class SkeletonBinary {
|
|||||||
for (linkedMesh in linkedMeshes) {
|
for (linkedMesh in linkedMeshes) {
|
||||||
var skin:Skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
var skin:Skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
||||||
if (skin == null)
|
if (skin == null)
|
||||||
throw new Error("Skin not found: " + linkedMesh.skin);
|
throw new SpineException("Skin not found: " + linkedMesh.skin);
|
||||||
var parent:Attachment = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
var parent:Attachment = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
throw new Error("Parent mesh not found: " + linkedMesh.parent);
|
throw new SpineException("Parent mesh not found: " + linkedMesh.parent);
|
||||||
linkedMesh.mesh.deformAttachment = linkedMesh.inheritDeform ? cast(parent, VertexAttachment) : linkedMesh.mesh;
|
linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? cast(parent, VertexAttachment) : linkedMesh.mesh;
|
||||||
linkedMesh.mesh.parentMesh = cast(parent, MeshAttachment);
|
linkedMesh.mesh.parentMesh = cast(parent, MeshAttachment);
|
||||||
linkedMesh.mesh.updateUVs();
|
if (linkedMesh.mesh.region != null)
|
||||||
|
linkedMesh.mesh.updateRegion();
|
||||||
}
|
}
|
||||||
linkedMeshes.length = 0;
|
linkedMeshes.length = 0;
|
||||||
|
|
||||||
@ -327,6 +332,16 @@ class SkeletonBinary {
|
|||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function readSequence(input:BinaryInput):Sequence {
|
||||||
|
if (!input.readBoolean())
|
||||||
|
return null;
|
||||||
|
var sequence = new Sequence(input.readInt(true));
|
||||||
|
sequence.start = input.readInt(true);
|
||||||
|
sequence.digits = input.readInt(true);
|
||||||
|
sequence.setupIndex = input.readInt(true);
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
private function readAttachment(input:BinaryInput, skeletonData:SkeletonData, skin:Skin, slotIndex:Int, attachmentName:String,
|
private function readAttachment(input:BinaryInput, skeletonData:SkeletonData, skin:Skin, slotIndex:Int, attachmentName:String,
|
||||||
nonessential:Bool):Attachment {
|
nonessential:Bool):Attachment {
|
||||||
var vertexCount:Int;
|
var vertexCount:Int;
|
||||||
@ -357,10 +372,11 @@ class SkeletonBinary {
|
|||||||
width = input.readFloat();
|
width = input.readFloat();
|
||||||
height = input.readFloat();
|
height = input.readFloat();
|
||||||
color = input.readInt32();
|
color = input.readInt32();
|
||||||
|
var sequence = readSequence(input);
|
||||||
|
|
||||||
if (path == null)
|
if (path == null)
|
||||||
path = name;
|
path = name;
|
||||||
var region:RegionAttachment = attachmentLoader.newRegionAttachment(skin, name, path);
|
var region:RegionAttachment = attachmentLoader.newRegionAttachment(skin, name, path, sequence);
|
||||||
if (region == null)
|
if (region == null)
|
||||||
return null;
|
return null;
|
||||||
region.path = path;
|
region.path = path;
|
||||||
@ -372,7 +388,9 @@ class SkeletonBinary {
|
|||||||
region.width = width * scale;
|
region.width = width * scale;
|
||||||
region.height = height * scale;
|
region.height = height * scale;
|
||||||
region.color.setFromRgba8888(color);
|
region.color.setFromRgba8888(color);
|
||||||
region.updateOffset();
|
region.sequence = sequence;
|
||||||
|
if (sequence == null)
|
||||||
|
region.updateRegion();
|
||||||
return region;
|
return region;
|
||||||
case AttachmentType.boundingbox:
|
case AttachmentType.boundingbox:
|
||||||
vertexCount = input.readInt(true);
|
vertexCount = input.readInt(true);
|
||||||
@ -397,6 +415,7 @@ class SkeletonBinary {
|
|||||||
var triangles:Vector<Int> = readShortArray(input);
|
var triangles:Vector<Int> = readShortArray(input);
|
||||||
vertices = readVertices(input, vertexCount);
|
vertices = readVertices(input, vertexCount);
|
||||||
var hullLength:Int = input.readInt(true);
|
var hullLength:Int = input.readInt(true);
|
||||||
|
var sequence = readSequence(input);
|
||||||
var edges:Vector<Int> = null;
|
var edges:Vector<Int> = null;
|
||||||
if (nonessential) {
|
if (nonessential) {
|
||||||
edges = readShortArray(input);
|
edges = readShortArray(input);
|
||||||
@ -406,7 +425,7 @@ class SkeletonBinary {
|
|||||||
|
|
||||||
if (path == null)
|
if (path == null)
|
||||||
path = name;
|
path = name;
|
||||||
mesh = attachmentLoader.newMeshAttachment(skin, name, path);
|
mesh = attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
||||||
if (mesh == null)
|
if (mesh == null)
|
||||||
return null;
|
return null;
|
||||||
mesh.path = path;
|
mesh.path = path;
|
||||||
@ -417,8 +436,10 @@ class SkeletonBinary {
|
|||||||
mesh.worldVerticesLength = vertexCount << 1;
|
mesh.worldVerticesLength = vertexCount << 1;
|
||||||
mesh.triangles = triangles;
|
mesh.triangles = triangles;
|
||||||
mesh.regionUVs = uvs;
|
mesh.regionUVs = uvs;
|
||||||
mesh.updateUVs();
|
if (sequence == null)
|
||||||
|
mesh.updateRegion();
|
||||||
mesh.hullLength = hullLength << 1;
|
mesh.hullLength = hullLength << 1;
|
||||||
|
mesh.sequence = sequence;
|
||||||
if (nonessential) {
|
if (nonessential) {
|
||||||
mesh.edges = edges;
|
mesh.edges = edges;
|
||||||
mesh.width = width * scale;
|
mesh.width = width * scale;
|
||||||
@ -430,7 +451,8 @@ class SkeletonBinary {
|
|||||||
color = input.readInt32();
|
color = input.readInt32();
|
||||||
var skinName:String = input.readStringRef();
|
var skinName:String = input.readStringRef();
|
||||||
var parent:String = input.readStringRef();
|
var parent:String = input.readStringRef();
|
||||||
var inheritDeform:Bool = input.readBoolean();
|
var inheritTimelines:Bool = input.readBoolean();
|
||||||
|
var sequence = readSequence(input);
|
||||||
if (nonessential) {
|
if (nonessential) {
|
||||||
width = input.readFloat();
|
width = input.readFloat();
|
||||||
height = input.readFloat();
|
height = input.readFloat();
|
||||||
@ -438,16 +460,17 @@ class SkeletonBinary {
|
|||||||
|
|
||||||
if (path == null)
|
if (path == null)
|
||||||
path = name;
|
path = name;
|
||||||
mesh = attachmentLoader.newMeshAttachment(skin, name, path);
|
mesh = attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
||||||
if (mesh == null)
|
if (mesh == null)
|
||||||
return null;
|
return null;
|
||||||
mesh.path = path;
|
mesh.path = path;
|
||||||
mesh.color.setFromRgba8888(color);
|
mesh.color.setFromRgba8888(color);
|
||||||
|
mesh.sequence = sequence;
|
||||||
if (nonessential) {
|
if (nonessential) {
|
||||||
mesh.width = width * scale;
|
mesh.width = width * scale;
|
||||||
mesh.height = height * scale;
|
mesh.height = height * scale;
|
||||||
}
|
}
|
||||||
this.linkedMeshes.push(new LinkedMeshBinary(mesh, skinName, slotIndex, parent, inheritDeform));
|
this.linkedMeshes.push(new LinkedMeshBinary(mesh, skinName, slotIndex, parent, inheritTimelines));
|
||||||
return mesh;
|
return mesh;
|
||||||
case AttachmentType.path:
|
case AttachmentType.path:
|
||||||
var closed:Bool = input.readBoolean();
|
var closed:Bool = input.readBoolean();
|
||||||
@ -985,64 +1008,78 @@ class SkeletonBinary {
|
|||||||
var attachmentName:String = input.readStringRef();
|
var attachmentName:String = input.readStringRef();
|
||||||
var attachment:VertexAttachment = cast(skin.getAttachment(slotIndex, attachmentName), VertexAttachment);
|
var attachment:VertexAttachment = cast(skin.getAttachment(slotIndex, attachmentName), VertexAttachment);
|
||||||
if (attachment == null)
|
if (attachment == null)
|
||||||
throw new Error("Vertex attachment not found: " + attachmentName);
|
throw new SpineException("Vertex attachment not found: " + attachmentName);
|
||||||
var weighted:Bool = attachment.bones != null;
|
var timelineType = input.readByte();
|
||||||
var vertices:Vector<Float> = attachment.vertices;
|
|
||||||
var deformLength:Int = weighted ? Std.int(vertices.length / 3 * 2) : vertices.length;
|
|
||||||
|
|
||||||
frameCount = input.readInt(true);
|
frameCount = input.readInt(true);
|
||||||
frameLast = frameCount - 1;
|
frameLast = frameCount - 1;
|
||||||
bezierCount = input.readInt(true);
|
|
||||||
var deformTimeline:DeformTimeline = new DeformTimeline(frameCount, bezierCount, slotIndex, attachment);
|
|
||||||
|
|
||||||
time = input.readFloat();
|
switch (timelineType) {
|
||||||
frame = 0;
|
case ATTACHMENT_DEFORM:
|
||||||
bezier = 0;
|
var weighted:Bool = attachment.bones != null;
|
||||||
while (true) {
|
var vertices:Vector<Float> = attachment.vertices;
|
||||||
var deform:Vector<Float>;
|
var deformLength:Int = weighted ? Std.int(vertices.length / 3 * 2) : vertices.length;
|
||||||
var end:Int = input.readInt(true);
|
|
||||||
if (end == 0) {
|
|
||||||
if (weighted) {
|
|
||||||
deform = new Vector<Float>(deformLength, true);
|
|
||||||
} else {
|
|
||||||
deform = vertices;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var v:Int, vn:Int;
|
|
||||||
deform = new Vector<Float>(deformLength, true);
|
|
||||||
var start:Int = input.readInt(true);
|
|
||||||
end += start;
|
|
||||||
if (scale == 1) {
|
|
||||||
for (v in start...end) {
|
|
||||||
deform[v] = input.readFloat();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (v in start...end) {
|
|
||||||
deform[v] = input.readFloat() * scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!weighted) {
|
|
||||||
for (v in 0...deform.length) {
|
|
||||||
deform[v] += vertices[v];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deformTimeline.setFrame(frame, time, deform);
|
bezierCount = input.readInt(true);
|
||||||
if (frame == frameLast)
|
var deformTimeline:DeformTimeline = new DeformTimeline(frameCount, bezierCount, slotIndex, attachment);
|
||||||
|
|
||||||
|
time = input.readFloat();
|
||||||
|
frame = 0;
|
||||||
|
bezier = 0;
|
||||||
|
while (true) {
|
||||||
|
var deform:Vector<Float>;
|
||||||
|
var end:Int = input.readInt(true);
|
||||||
|
if (end == 0) {
|
||||||
|
if (weighted) {
|
||||||
|
deform = new Vector<Float>(deformLength, true);
|
||||||
|
} else {
|
||||||
|
deform = vertices;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var v:Int, vn:Int;
|
||||||
|
deform = new Vector<Float>(deformLength, true);
|
||||||
|
var start:Int = input.readInt(true);
|
||||||
|
end += start;
|
||||||
|
if (scale == 1) {
|
||||||
|
for (v in start...end) {
|
||||||
|
deform[v] = input.readFloat();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (v in start...end) {
|
||||||
|
deform[v] = input.readFloat() * scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!weighted) {
|
||||||
|
for (v in 0...deform.length) {
|
||||||
|
deform[v] += vertices[v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deformTimeline.setFrame(frame, time, deform);
|
||||||
|
if (frame == frameLast)
|
||||||
|
break;
|
||||||
|
time2 = input.readFloat();
|
||||||
|
switch (input.readByte()) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
deformTimeline.setStepped(frame);
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
SkeletonBinary.setBezier(input, deformTimeline, bezier++, frame, 0, time, time2, 0, 1, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
|
||||||
|
frame++;
|
||||||
|
}
|
||||||
|
timelines.push(deformTimeline);
|
||||||
|
case ATTACHMENT_SEQUENCE:
|
||||||
|
var timeline = new SequenceTimeline(frameCount, slotIndex, cast(attachment, HasTextureRegion));
|
||||||
|
for (frame in 0...frameCount) {
|
||||||
|
var time = input.readFloat();
|
||||||
|
var modeAndIndex = input.readInt32();
|
||||||
|
timeline.setFrame(frame, time, SequenceMode.values[modeAndIndex & 0xf], modeAndIndex >> 4, input.readFloat());
|
||||||
|
}
|
||||||
|
timelines.push(timeline);
|
||||||
break;
|
break;
|
||||||
time2 = input.readFloat();
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case CURVE_STEPPED:
|
|
||||||
deformTimeline.setStepped(frame);
|
|
||||||
case CURVE_BEZIER:
|
|
||||||
SkeletonBinary.setBezier(input, deformTimeline, bezier++, frame, 0, time, time2, 0, 1, 1);
|
|
||||||
}
|
|
||||||
time = time2;
|
|
||||||
|
|
||||||
frame++;
|
|
||||||
}
|
}
|
||||||
timelines.push(deformTimeline);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1193,13 +1230,13 @@ class LinkedMeshBinary {
|
|||||||
public var skin(default, null):String;
|
public var skin(default, null):String;
|
||||||
public var slotIndex(default, null):Int;
|
public var slotIndex(default, null):Int;
|
||||||
public var mesh(default, null):MeshAttachment;
|
public var mesh(default, null):MeshAttachment;
|
||||||
public var inheritDeform(default, null):Bool;
|
public var inheritTimeline(default, null):Bool;
|
||||||
|
|
||||||
public function new(mesh:MeshAttachment, skin:String, slotIndex:Int, parent:String, inheritDeform:Bool) {
|
public function new(mesh:MeshAttachment, skin:String, slotIndex:Int, parent:String, inheritTimeline:Bool) {
|
||||||
this.mesh = mesh;
|
this.mesh = mesh;
|
||||||
this.skin = skin;
|
this.skin = skin;
|
||||||
this.slotIndex = slotIndex;
|
this.slotIndex = slotIndex;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.inheritDeform = inheritDeform;
|
this.inheritTimeline = inheritTimeline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package spine;
|
package spine;
|
||||||
|
|
||||||
|
import spine.animation.SequenceTimeline;
|
||||||
import haxe.Json;
|
import haxe.Json;
|
||||||
import openfl.errors.ArgumentError;
|
import openfl.errors.ArgumentError;
|
||||||
import openfl.errors.Error;
|
import openfl.errors.Error;
|
||||||
@ -97,7 +98,7 @@ class SkeletonJson {
|
|||||||
if (parentName != null) {
|
if (parentName != null) {
|
||||||
parent = skeletonData.findBone(parentName);
|
parent = skeletonData.findBone(parentName);
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
throw new Error("Parent bone not found: " + parentName);
|
throw new SpineException("Parent bone not found: " + parentName);
|
||||||
}
|
}
|
||||||
boneData = new BoneData(skeletonData.bones.length, Reflect.getProperty(boneMap, "name"), parent);
|
boneData = new BoneData(skeletonData.bones.length, Reflect.getProperty(boneMap, "name"), parent);
|
||||||
boneData.length = getFloat(Reflect.getProperty(boneMap, "length")) * scale;
|
boneData.length = getFloat(Reflect.getProperty(boneMap, "length")) * scale;
|
||||||
@ -126,7 +127,7 @@ class SkeletonJson {
|
|||||||
var boneName:String = Reflect.getProperty(slotMap, "bone");
|
var boneName:String = Reflect.getProperty(slotMap, "bone");
|
||||||
boneData = skeletonData.findBone(boneName);
|
boneData = skeletonData.findBone(boneName);
|
||||||
if (boneData == null)
|
if (boneData == null)
|
||||||
throw new Error("Slot bone not found: " + boneName);
|
throw new SpineException("Slot bone not found: " + boneName);
|
||||||
var slotData:SlotData = new SlotData(skeletonData.slots.length, slotName, boneData);
|
var slotData:SlotData = new SlotData(skeletonData.slots.length, slotName, boneData);
|
||||||
|
|
||||||
var color:String = Reflect.getProperty(slotMap, "color");
|
var color:String = Reflect.getProperty(slotMap, "color");
|
||||||
@ -155,22 +156,22 @@ class SkeletonJson {
|
|||||||
for (boneName in cast(Reflect.getProperty(constraintMap, "bones"), Array<Dynamic>)) {
|
for (boneName in cast(Reflect.getProperty(constraintMap, "bones"), Array<Dynamic>)) {
|
||||||
var bone:BoneData = skeletonData.findBone(boneName);
|
var bone:BoneData = skeletonData.findBone(boneName);
|
||||||
if (bone == null)
|
if (bone == null)
|
||||||
throw new Error("IK constraint bone not found: " + boneName);
|
throw new SpineException("IK constraint bone not found: " + boneName);
|
||||||
ikData.bones.push(bone);
|
ikData.bones.push(bone);
|
||||||
}
|
}
|
||||||
|
|
||||||
ikData.target = skeletonData.findBone(Reflect.getProperty(constraintMap, "target"));
|
ikData.target = skeletonData.findBone(Reflect.getProperty(constraintMap, "target"));
|
||||||
if (ikData.target == null)
|
if (ikData.target == null)
|
||||||
throw new Error("Target bone not found: " + Reflect.getProperty(constraintMap, "target"));
|
throw new SpineException("Target bone not found: " + Reflect.getProperty(constraintMap, "target"));
|
||||||
|
|
||||||
|
ikData.mix = getFloat(Reflect.getProperty(constraintMap, "mix"), 1);
|
||||||
|
ikData.softness = getFloat(Reflect.getProperty(constraintMap, "softness"), 0) * scale;
|
||||||
ikData.bendDirection = (!Reflect.hasField(constraintMap, "bendPositive")
|
ikData.bendDirection = (!Reflect.hasField(constraintMap, "bendPositive")
|
||||||
|| cast(Reflect.getProperty(constraintMap, "bendPositive"), Bool)) ? 1 : -1;
|
|| cast(Reflect.getProperty(constraintMap, "bendPositive"), Bool)) ? 1 : -1;
|
||||||
ikData.compress = (Reflect.hasField(constraintMap, "compress")
|
ikData.compress = (Reflect.hasField(constraintMap, "compress")
|
||||||
&& cast(Reflect.getProperty(constraintMap, "compress"), Bool));
|
&& cast(Reflect.getProperty(constraintMap, "compress"), Bool));
|
||||||
ikData.stretch = (Reflect.hasField(constraintMap, "stretch") && cast(Reflect.getProperty(constraintMap, "stretch"), Bool));
|
ikData.stretch = (Reflect.hasField(constraintMap, "stretch") && cast(Reflect.getProperty(constraintMap, "stretch"), Bool));
|
||||||
ikData.uniform = (Reflect.hasField(constraintMap, "uniform") && cast(Reflect.getProperty(constraintMap, "uniform"), Bool));
|
ikData.uniform = (Reflect.hasField(constraintMap, "uniform") && cast(Reflect.getProperty(constraintMap, "uniform"), Bool));
|
||||||
ikData.softness = getFloat(Reflect.getProperty(constraintMap, "softness")) * scale;
|
|
||||||
ikData.mix = getFloat(Reflect.getProperty(constraintMap, "mix"), 1);
|
|
||||||
|
|
||||||
skeletonData.ikConstraints.push(ikData);
|
skeletonData.ikConstraints.push(ikData);
|
||||||
}
|
}
|
||||||
@ -186,13 +187,13 @@ class SkeletonJson {
|
|||||||
for (boneName in cast(Reflect.getProperty(constraintMap, "bones"), Array<Dynamic>)) {
|
for (boneName in cast(Reflect.getProperty(constraintMap, "bones"), Array<Dynamic>)) {
|
||||||
var bone = skeletonData.findBone(boneName);
|
var bone = skeletonData.findBone(boneName);
|
||||||
if (bone == null)
|
if (bone == null)
|
||||||
throw new Error("Transform constraint bone not found: " + boneName);
|
throw new SpineException("Transform constraint bone not found: " + boneName);
|
||||||
transformData.bones.push(bone);
|
transformData.bones.push(bone);
|
||||||
}
|
}
|
||||||
|
|
||||||
transformData.target = skeletonData.findBone(Reflect.getProperty(constraintMap, "target"));
|
transformData.target = skeletonData.findBone(Reflect.getProperty(constraintMap, "target"));
|
||||||
if (transformData.target == null)
|
if (transformData.target == null)
|
||||||
throw new Error("Target bone not found: " + Reflect.getProperty(constraintMap, "target"));
|
throw new SpineException("Target bone not found: " + Reflect.getProperty(constraintMap, "target"));
|
||||||
|
|
||||||
transformData.local = Reflect.hasField(constraintMap, "local") ? cast(Reflect.getProperty(constraintMap, "local"), Bool) : false;
|
transformData.local = Reflect.hasField(constraintMap, "local") ? cast(Reflect.getProperty(constraintMap, "local"), Bool) : false;
|
||||||
transformData.relative = Reflect.hasField(constraintMap, "relative") ? cast(Reflect.getProperty(constraintMap, "relative"), Bool) : false;
|
transformData.relative = Reflect.hasField(constraintMap, "relative") ? cast(Reflect.getProperty(constraintMap, "relative"), Bool) : false;
|
||||||
@ -225,13 +226,13 @@ class SkeletonJson {
|
|||||||
for (boneName in cast(Reflect.getProperty(constraintMap, "bones"), Array<Dynamic>)) {
|
for (boneName in cast(Reflect.getProperty(constraintMap, "bones"), Array<Dynamic>)) {
|
||||||
var bone = skeletonData.findBone(boneName);
|
var bone = skeletonData.findBone(boneName);
|
||||||
if (bone == null)
|
if (bone == null)
|
||||||
throw new Error("Path constraint bone not found: " + boneName);
|
throw new SpineException("Path constraint bone not found: " + boneName);
|
||||||
pathData.bones.push(bone);
|
pathData.bones.push(bone);
|
||||||
}
|
}
|
||||||
|
|
||||||
pathData.target = skeletonData.findSlot(Reflect.getProperty(constraintMap, "target"));
|
pathData.target = skeletonData.findSlot(Reflect.getProperty(constraintMap, "target"));
|
||||||
if (pathData.target == null)
|
if (pathData.target == null)
|
||||||
throw new Error("Path target slot not found: " + Reflect.getProperty(constraintMap, "target"));
|
throw new SpineException("Path target slot not found: " + Reflect.getProperty(constraintMap, "target"));
|
||||||
|
|
||||||
pathData.positionMode = Reflect.hasField(constraintMap,
|
pathData.positionMode = Reflect.hasField(constraintMap,
|
||||||
"positionMode") ? PositionMode.fromName(Reflect.getProperty(constraintMap, "positionMode")) : PositionMode.percent;
|
"positionMode") ? PositionMode.fromName(Reflect.getProperty(constraintMap, "positionMode")) : PositionMode.percent;
|
||||||
@ -264,7 +265,7 @@ class SkeletonJson {
|
|||||||
for (ii in 0...bones.length) {
|
for (ii in 0...bones.length) {
|
||||||
var boneData:BoneData = skeletonData.findBone(bones[ii]);
|
var boneData:BoneData = skeletonData.findBone(bones[ii]);
|
||||||
if (boneData == null)
|
if (boneData == null)
|
||||||
throw new Error("Skin bone not found: " + bones[ii]);
|
throw new SpineException("Skin bone not found: " + bones[ii]);
|
||||||
skin.bones.push(boneData);
|
skin.bones.push(boneData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,7 +275,7 @@ class SkeletonJson {
|
|||||||
for (ii in 0...ik.length) {
|
for (ii in 0...ik.length) {
|
||||||
var constraint:ConstraintData = skeletonData.findIkConstraint(ik[ii]);
|
var constraint:ConstraintData = skeletonData.findIkConstraint(ik[ii]);
|
||||||
if (constraint == null)
|
if (constraint == null)
|
||||||
throw new Error("Skin IK constraint not found: " + ik[ii]);
|
throw new SpineException("Skin IK constraint not found: " + ik[ii]);
|
||||||
skin.constraints.push(constraint);
|
skin.constraints.push(constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,7 +285,7 @@ class SkeletonJson {
|
|||||||
for (ii in 0...transform.length) {
|
for (ii in 0...transform.length) {
|
||||||
var constraint:ConstraintData = skeletonData.findTransformConstraint(transform[ii]);
|
var constraint:ConstraintData = skeletonData.findTransformConstraint(transform[ii]);
|
||||||
if (constraint == null)
|
if (constraint == null)
|
||||||
throw new Error("Skin transform constraint not found: " + transform[ii]);
|
throw new SpineException("Skin transform constraint not found: " + transform[ii]);
|
||||||
skin.constraints.push(constraint);
|
skin.constraints.push(constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,7 +295,7 @@ class SkeletonJson {
|
|||||||
for (ii in 0...path.length) {
|
for (ii in 0...path.length) {
|
||||||
var constraint:ConstraintData = skeletonData.findPathConstraint(path[ii]);
|
var constraint:ConstraintData = skeletonData.findPathConstraint(path[ii]);
|
||||||
if (constraint == null)
|
if (constraint == null)
|
||||||
throw new Error("Skin path constraint not found: " + path[ii]);
|
throw new SpineException("Skin path constraint not found: " + path[ii]);
|
||||||
skin.constraints.push(constraint);
|
skin.constraints.push(constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,13 +326,14 @@ class SkeletonJson {
|
|||||||
for (linkedMesh in linkedMeshes) {
|
for (linkedMesh in linkedMeshes) {
|
||||||
var parentSkin:Skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
var parentSkin:Skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
||||||
if (parentSkin == null)
|
if (parentSkin == null)
|
||||||
throw new Error("Skin not found: " + linkedMesh.skin);
|
throw new SpineException("Skin not found: " + linkedMesh.skin);
|
||||||
var parentMesh:Attachment = parentSkin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
var parentMesh:Attachment = parentSkin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
||||||
if (parentMesh == null)
|
if (parentMesh == null)
|
||||||
throw new Error("Parent mesh not found: " + linkedMesh.parent);
|
throw new SpineException("Parent mesh not found: " + linkedMesh.parent);
|
||||||
linkedMesh.mesh.deformAttachment = linkedMesh.inheritDeform ? cast(parentMesh, VertexAttachment) : linkedMesh.mesh;
|
linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? cast(parentMesh, VertexAttachment) : linkedMesh.mesh;
|
||||||
linkedMesh.mesh.parentMesh = cast(parentMesh, MeshAttachment);
|
linkedMesh.mesh.parentMesh = cast(parentMesh, MeshAttachment);
|
||||||
linkedMesh.mesh.updateUVs();
|
if (linkedMesh.mesh.region != null)
|
||||||
|
linkedMesh.mesh.updateRegion();
|
||||||
}
|
}
|
||||||
linkedMeshes.length = 0;
|
linkedMeshes.length = 0;
|
||||||
|
|
||||||
@ -359,6 +361,16 @@ class SkeletonJson {
|
|||||||
return skeletonData;
|
return skeletonData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function readSequence(map:Object) {
|
||||||
|
if (map == null)
|
||||||
|
return null;
|
||||||
|
var sequence = new Sequence(getInt(map["count"], 0));
|
||||||
|
sequence.start = getInt(map["start"], 1);
|
||||||
|
sequence.digits = getInt(map["digits"], 0);
|
||||||
|
sequence.setupIndex = getInt(map["setup"], 0);
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
private function readAttachment(map:Object, skin:Skin, slotIndex:Int, name:String, skeletonData:SkeletonData):Attachment {
|
private function readAttachment(map:Object, skin:Skin, slotIndex:Int, name:String, skeletonData:SkeletonData):Attachment {
|
||||||
if (map["name"] != null)
|
if (map["name"] != null)
|
||||||
name = map["name"];
|
name = map["name"];
|
||||||
@ -366,10 +378,12 @@ class SkeletonJson {
|
|||||||
var color:String;
|
var color:String;
|
||||||
switch (AttachmentType.fromName(Reflect.hasField(map, "type") ? Reflect.getProperty(map, "type") : "region")) {
|
switch (AttachmentType.fromName(Reflect.hasField(map, "type") ? Reflect.getProperty(map, "type") : "region")) {
|
||||||
case AttachmentType.region:
|
case AttachmentType.region:
|
||||||
var region:RegionAttachment = attachmentLoader.newRegionAttachment(skin, name, map["path"] != null ? map["path"] : name);
|
var path = getString(map, "path", name);
|
||||||
|
var sequence = readSequence(map["sequence"]);
|
||||||
|
var region:RegionAttachment = attachmentLoader.newRegionAttachment(skin, name, path, sequence);
|
||||||
if (region == null)
|
if (region == null)
|
||||||
return null;
|
return null;
|
||||||
region.path = map["path"] != null ? map["path"] : name;
|
region.path = path;
|
||||||
region.x = getFloat(map["x"]) * scale;
|
region.x = getFloat(map["x"]) * scale;
|
||||||
region.y = getFloat(map["y"]) * scale;
|
region.y = getFloat(map["y"]) * scale;
|
||||||
region.scaleX = getFloat(map["scaleX"], 1);
|
region.scaleX = getFloat(map["scaleX"], 1);
|
||||||
@ -377,36 +391,48 @@ class SkeletonJson {
|
|||||||
region.rotation = getFloat(map["rotation"]);
|
region.rotation = getFloat(map["rotation"]);
|
||||||
region.width = getFloat(map["width"]) * scale;
|
region.width = getFloat(map["width"]) * scale;
|
||||||
region.height = getFloat(map["height"]) * scale;
|
region.height = getFloat(map["height"]) * scale;
|
||||||
|
region.sequence = sequence;
|
||||||
|
|
||||||
color = Reflect.getProperty(map, "color");
|
color = Reflect.getProperty(map, "color");
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
region.color.setFromString(color);
|
region.color.setFromString(color);
|
||||||
}
|
}
|
||||||
region.updateOffset();
|
if (region.region != null)
|
||||||
|
region.updateRegion();
|
||||||
return region;
|
return region;
|
||||||
case AttachmentType.mesh, AttachmentType.linkedmesh:
|
case AttachmentType.mesh, AttachmentType.linkedmesh:
|
||||||
var mesh:MeshAttachment = attachmentLoader.newMeshAttachment(skin, name, map["path"] != null ? map["path"] : name);
|
var path = getString(map, "path", name);
|
||||||
|
var sequence = readSequence(map["sequence"]);
|
||||||
|
var mesh:MeshAttachment = attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
||||||
if (mesh == null)
|
if (mesh == null)
|
||||||
return null;
|
return null;
|
||||||
mesh.path = map["path"] != null ? map["path"] : name;
|
mesh.path = path;
|
||||||
|
|
||||||
color = Reflect.getProperty(map, "color");
|
color = Reflect.getProperty(map, "color");
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
mesh.color.setFromString(color);
|
mesh.color.setFromString(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.width = getFloat(map["width"]) * scale;
|
mesh.width = getFloat(map["width"]) * scale;
|
||||||
mesh.height = getFloat(map["height"]) * scale;
|
mesh.height = getFloat(map["height"]) * scale;
|
||||||
|
mesh.sequence = sequence;
|
||||||
|
|
||||||
if (map["parent"] != null) {
|
if (map["parent"] != null) {
|
||||||
var inheritDeform:Bool = map.hasOwnProperty("deform") ? cast(map["deform"], Bool) : true;
|
var inheritTimelines:Bool = map.hasOwnProperty("timelines") ? cast(map["timelines"], Bool) : true;
|
||||||
linkedMeshes.push(new LinkedMesh(mesh, map["skin"], slotIndex, map["parent"], inheritDeform));
|
linkedMeshes.push(new LinkedMesh(mesh, map["skin"], slotIndex, map["parent"], inheritTimelines));
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
var uvs:Vector<Float> = getFloatArray(map, "uvs");
|
var uvs:Vector<Float> = getFloatArray(map, "uvs");
|
||||||
readVertices(map, mesh, uvs.length);
|
readVertices(map, mesh, uvs.length);
|
||||||
mesh.triangles = getIntArray(map, "triangles");
|
mesh.triangles = getIntArray(map, "triangles");
|
||||||
mesh.regionUVs = uvs;
|
mesh.regionUVs = uvs;
|
||||||
mesh.updateUVs();
|
if (mesh.region != null)
|
||||||
mesh.hullLength = (getInt(map["hull"])) * 2;
|
mesh.updateRegion();
|
||||||
|
|
||||||
if (map["edges"] != null)
|
if (map["edges"] != null)
|
||||||
mesh.edges = getIntArray(map, "edges");
|
mesh.edges = getIntArray(map, "edges");
|
||||||
|
mesh.hullLength = (getInt(map["hull"])) * 2;
|
||||||
return mesh;
|
return mesh;
|
||||||
case AttachmentType.boundingbox:
|
case AttachmentType.boundingbox:
|
||||||
var box:BoundingBoxAttachment = attachmentLoader.newBoundingBoxAttachment(skin, name);
|
var box:BoundingBoxAttachment = attachmentLoader.newBoundingBoxAttachment(skin, name);
|
||||||
@ -448,7 +474,7 @@ class SkeletonJson {
|
|||||||
if (end != null) {
|
if (end != null) {
|
||||||
var slot:SlotData = skeletonData.findSlot(end);
|
var slot:SlotData = skeletonData.findSlot(end);
|
||||||
if (slot == null)
|
if (slot == null)
|
||||||
throw new Error("Clipping end slot not found: " + end);
|
throw new SpineException("Clipping end slot not found: " + end);
|
||||||
clip.endSlot = slot;
|
clip.endSlot = slot;
|
||||||
}
|
}
|
||||||
var vertexCount:Int = Std.parseInt(map["vertexCount"]);
|
var vertexCount:Int = Std.parseInt(map["vertexCount"]);
|
||||||
@ -524,7 +550,7 @@ class SkeletonJson {
|
|||||||
var attachmentTimeline:AttachmentTimeline = new AttachmentTimeline(timelineMap.length, slotIndex);
|
var attachmentTimeline:AttachmentTimeline = new AttachmentTimeline(timelineMap.length, slotIndex);
|
||||||
for (frame in 0...timelineMap.length) {
|
for (frame in 0...timelineMap.length) {
|
||||||
keyMap = timelineMap[frame];
|
keyMap = timelineMap[frame];
|
||||||
attachmentTimeline.setFrame(frame, getFloat(Reflect.getProperty(keyMap, "time")), keyMap.name);
|
attachmentTimeline.setFrame(frame, getFloat(Reflect.getProperty(keyMap, "time")), getString(keyMap, "name", null));
|
||||||
}
|
}
|
||||||
timelines.push(attachmentTimeline);
|
timelines.push(attachmentTimeline);
|
||||||
} else if (timelineName == "rgba") {
|
} else if (timelineName == "rgba") {
|
||||||
@ -672,7 +698,7 @@ class SkeletonJson {
|
|||||||
|
|
||||||
timelines.push(rgb2Timeline);
|
timelines.push(rgb2Timeline);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
|
throw new SpineException("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -682,7 +708,7 @@ class SkeletonJson {
|
|||||||
for (boneName in bones) {
|
for (boneName in bones) {
|
||||||
var boneIndex:Int = skeletonData.findBoneIndex(boneName);
|
var boneIndex:Int = skeletonData.findBoneIndex(boneName);
|
||||||
if (boneIndex == -1)
|
if (boneIndex == -1)
|
||||||
throw new Error("Bone not found: " + boneName);
|
throw new SpineException("Bone not found: " + boneName);
|
||||||
var boneMap:Object = bones[boneName];
|
var boneMap:Object = bones[boneName];
|
||||||
for (timelineName in boneMap) {
|
for (timelineName in boneMap) {
|
||||||
timelineMap = boneMap[timelineName];
|
timelineMap = boneMap[timelineName];
|
||||||
@ -719,7 +745,7 @@ class SkeletonJson {
|
|||||||
var shearYTimeline:ShearYTimeline = new ShearYTimeline(timelineMap.length, timelineMap.length, boneIndex);
|
var shearYTimeline:ShearYTimeline = new ShearYTimeline(timelineMap.length, timelineMap.length, boneIndex);
|
||||||
timelines.push(readTimeline(timelineMap, shearYTimeline, 0, 1));
|
timelines.push(readTimeline(timelineMap, shearYTimeline, 0, 1));
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
throw new SpineException("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,7 +865,7 @@ class SkeletonJson {
|
|||||||
for (pathName in paths) {
|
for (pathName in paths) {
|
||||||
var index:Int = skeletonData.findPathConstraintIndex(pathName);
|
var index:Int = skeletonData.findPathConstraintIndex(pathName);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
throw new Error("Path constraint not found: " + pathName);
|
throw new SpineException("Path constraint not found: " + pathName);
|
||||||
var pathData:PathConstraintData = skeletonData.pathConstraints[index];
|
var pathData:PathConstraintData = skeletonData.pathConstraints[index];
|
||||||
|
|
||||||
var pathMap:Object = paths[pathName];
|
var pathMap:Object = paths[pathName];
|
||||||
@ -896,78 +922,99 @@ class SkeletonJson {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deform timelines.
|
// Attachment timelines.
|
||||||
var deforms:Object = Reflect.getProperty(map, "deform");
|
var attachments:Object = Reflect.getProperty(map, "attachments");
|
||||||
for (deformName in deforms) {
|
for (attachmentsName in attachments) {
|
||||||
var deformMap:Object = deforms[deformName];
|
var attachmentsMap:Object = attachments[attachmentsName];
|
||||||
var skin:Skin = skeletonData.findSkin(deformName);
|
var skin:Skin = skeletonData.findSkin(attachmentsName);
|
||||||
if (skin == null)
|
if (skin == null)
|
||||||
throw new Error("Skin not found: " + deformName);
|
throw new SpineException("Skin not found: " + attachmentsName);
|
||||||
|
|
||||||
for (slotName in deformMap) {
|
for (slotMapName in attachmentsMap) {
|
||||||
slotMap = deformMap[slotName];
|
slotMap = attachmentsMap[slotMapName];
|
||||||
slotIndex = skeletonData.findSlot(slotName).index;
|
slotIndex = skeletonData.findSlot(slotName).index;
|
||||||
if (slotIndex == -1)
|
if (slotIndex == -1)
|
||||||
throw new Error("Slot not found: " + slotName);
|
throw new SpineException("Slot not found: " + slotName);
|
||||||
for (timelineName in slotMap) {
|
for (attachmentMapName in slotMap) {
|
||||||
timelineMap = slotMap[timelineName];
|
var attachmentMap = slotMap[attachmentMapName];
|
||||||
keyMap = timelineMap[0];
|
var attachment:VertexAttachment = cast(skin.getAttachment(slotIndex, attachmentMapName), VertexAttachment);
|
||||||
if (keyMap == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var attachment:VertexAttachment = cast(skin.getAttachment(slotIndex, timelineName), VertexAttachment);
|
|
||||||
if (attachment == null)
|
if (attachment == null)
|
||||||
throw new Error("Deform attachment not found: " + timelineName);
|
throw new SpineException("Timeline attachment not found: " + timelineName);
|
||||||
var weighted:Bool = attachment.bones != null;
|
|
||||||
var vertices:Vector<Float> = attachment.vertices;
|
|
||||||
var deformLength:Int = weighted ? Std.int(vertices.length / 3 * 2) : vertices.length;
|
|
||||||
|
|
||||||
var deformTimeline:DeformTimeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment);
|
for (timelineMapName in attachmentMap) {
|
||||||
time = getFloat(Reflect.getProperty(keyMap, "time"));
|
var timelineMap = attachmentMap[timelineMapName];
|
||||||
frame = 0;
|
var keyMap = timelineMap[0];
|
||||||
bezier = 0;
|
if (keyMap == null)
|
||||||
while (true) {
|
continue;
|
||||||
var deform:Vector<Float>;
|
|
||||||
var verticesValue:Vector<Float> = Reflect.getProperty(keyMap, "vertices");
|
if (timelineMapName == "deform") {
|
||||||
if (verticesValue == null) {
|
var weighted:Bool = attachment.bones != null;
|
||||||
deform = weighted ? new Vector<Float>(deformLength, true) : vertices;
|
var vertices:Vector<Float> = attachment.vertices;
|
||||||
} else {
|
var deformLength:Int = weighted ? Std.int(vertices.length / 3 * 2) : vertices.length;
|
||||||
deform = new Vector<Float>(deformLength, true);
|
|
||||||
var start:Int = getInt(Reflect.getProperty(keyMap, "offset"));
|
var deformTimeline:DeformTimeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment);
|
||||||
var temp:Vector<Float> = getFloatArray(keyMap, "vertices");
|
time = getFloat(Reflect.getProperty(keyMap, "time"));
|
||||||
for (i in 0...temp.length) {
|
frame = 0;
|
||||||
deform[start + i] = temp[i];
|
bezier = 0;
|
||||||
}
|
while (true) {
|
||||||
if (scale != 1) {
|
var deform:Vector<Float>;
|
||||||
for (i in start...start + temp.length) {
|
var verticesValue:Vector<Float> = Reflect.getProperty(keyMap, "vertices");
|
||||||
deform[i] *= scale;
|
if (verticesValue == null) {
|
||||||
|
deform = weighted ? new Vector<Float>(deformLength, true) : vertices;
|
||||||
|
} else {
|
||||||
|
deform = new Vector<Float>(deformLength, true);
|
||||||
|
var start:Int = getInt(Reflect.getProperty(keyMap, "offset"));
|
||||||
|
var temp:Vector<Float> = getFloatArray(keyMap, "vertices");
|
||||||
|
for (i in 0...temp.length) {
|
||||||
|
deform[start + i] = temp[i];
|
||||||
|
}
|
||||||
|
if (scale != 1) {
|
||||||
|
for (i in start...start + temp.length) {
|
||||||
|
deform[i] *= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!weighted) {
|
||||||
|
for (i in 0...deformLength) {
|
||||||
|
deform[i] += vertices[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!weighted) {
|
deformTimeline.setFrame(frame, time, deform);
|
||||||
for (i in 0...deformLength) {
|
nextMap = timelineMap[frame + 1];
|
||||||
deform[i] += vertices[i];
|
if (nextMap == null) {
|
||||||
|
deformTimeline.shrink(bezier);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
time2 = getFloat(Reflect.getProperty(nextMap, "time"));
|
||||||
|
curve = keyMap.curve;
|
||||||
|
if (curve != null) {
|
||||||
|
bezier = readCurve(curve, deformTimeline, bezier, frame, 0, time, time2, 0, 1, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
keyMap = nextMap;
|
||||||
|
|
||||||
|
frame++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
deformTimeline.setFrame(frame, time, deform);
|
timelines.push(deformTimeline);
|
||||||
nextMap = timelineMap[frame + 1];
|
} else if (timelineMapName == "sequence") {
|
||||||
if (nextMap == null) {
|
var timeline = new SequenceTimeline(timelineMap.length, slotIndex, cast(attachment, HasTextureRegion));
|
||||||
deformTimeline.shrink(bezier);
|
var lastDelay:Float = 0;
|
||||||
break;
|
var frame:Int = 0;
|
||||||
|
while (frame < timelineMap.length) {
|
||||||
|
var delay = getFloat(keyMap["delay"], lastDelay);
|
||||||
|
var time = getFloat(keyMap["time"], 0);
|
||||||
|
var mode = SequenceMode.fromName(getString(keyMap, "mode", "hold"));
|
||||||
|
var index = getInt(keyMap["index"], 0);
|
||||||
|
timeline.setFrame(frame, time, mode, index, delay);
|
||||||
|
lastDelay = delay;
|
||||||
|
keyMap = timelineMap[frame + 1];
|
||||||
|
frame++;
|
||||||
|
}
|
||||||
|
timelines.push(timeline);
|
||||||
}
|
}
|
||||||
time2 = getFloat(Reflect.getProperty(nextMap, "time"));
|
|
||||||
curve = keyMap.curve;
|
|
||||||
if (curve != null) {
|
|
||||||
bezier = readCurve(curve, deformTimeline, bezier, frame, 0, time, time2, 0, 1, 1);
|
|
||||||
}
|
|
||||||
time = time2;
|
|
||||||
keyMap = nextMap;
|
|
||||||
|
|
||||||
frame++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
timelines.push(deformTimeline);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -993,7 +1040,7 @@ class SkeletonJson {
|
|||||||
for (offsetMap in offsets) {
|
for (offsetMap in offsets) {
|
||||||
slotIndex = skeletonData.findSlot(Reflect.getProperty(offsetMap, "slot")).index;
|
slotIndex = skeletonData.findSlot(Reflect.getProperty(offsetMap, "slot")).index;
|
||||||
if (slotIndex == -1)
|
if (slotIndex == -1)
|
||||||
throw new Error("Slot not found: " + Reflect.getProperty(offsetMap, "slot"));
|
throw new SpineException("Slot not found: " + Reflect.getProperty(offsetMap, "slot"));
|
||||||
// Collect unchanged items.
|
// Collect unchanged items.
|
||||||
while (originalIndex != slotIndex) {
|
while (originalIndex != slotIndex) {
|
||||||
unchanged[unchangedIndex++] = originalIndex++;
|
unchanged[unchangedIndex++] = originalIndex++;
|
||||||
@ -1028,7 +1075,7 @@ class SkeletonJson {
|
|||||||
for (eventMap in eventsMap) {
|
for (eventMap in eventsMap) {
|
||||||
var eventData:EventData = skeletonData.findEvent(Reflect.getProperty(eventMap, "name"));
|
var eventData:EventData = skeletonData.findEvent(Reflect.getProperty(eventMap, "name"));
|
||||||
if (eventData == null)
|
if (eventData == null)
|
||||||
throw new Error("Event not found: " + Reflect.getProperty(eventMap, "name"));
|
throw new SpineException("Event not found: " + Reflect.getProperty(eventMap, "name"));
|
||||||
var event:Event = new Event(getFloat(Reflect.getProperty(eventMap, "time")), eventData);
|
var event:Event = new Event(getFloat(Reflect.getProperty(eventMap, "time")), eventData);
|
||||||
event.intValue = Reflect.hasField(eventMap, "int") ? getInt(Reflect.getProperty(eventMap, "int")) : eventData.intValue;
|
event.intValue = Reflect.hasField(eventMap, "int") ? getInt(Reflect.getProperty(eventMap, "int")) : eventData.intValue;
|
||||||
event.floatValue = Reflect.hasField(eventMap, "float") ? getFloat(Reflect.getProperty(eventMap, "float")) : eventData.floatValue;
|
event.floatValue = Reflect.hasField(eventMap, "float") ? getFloat(Reflect.getProperty(eventMap, "float")) : eventData.floatValue;
|
||||||
@ -1128,6 +1175,18 @@ class SkeletonJson {
|
|||||||
return bezier + 1;
|
return bezier + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static private function getValue(map:Object, name:String, defaultValue:Dynamic):Dynamic {
|
||||||
|
if (map.hasOwnProperty(name))
|
||||||
|
return map[name];
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static private function getString(value:Object, name:String, defaultValue:String):String {
|
||||||
|
if (Std.isOfType(value[name], String))
|
||||||
|
return cast(value[name], String);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
static private function getFloat(value:Object, defaultValue:Float = 0):Float {
|
static private function getFloat(value:Object, defaultValue:Float = 0):Float {
|
||||||
if (Std.isOfType(value, Float))
|
if (Std.isOfType(value, Float))
|
||||||
return cast(value, Float);
|
return cast(value, Float);
|
||||||
@ -1146,12 +1205,12 @@ class SkeletonJson {
|
|||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private function getInt(value:Object):Int {
|
static private function getInt(value:Object, defaultValue:Int = 0):Int {
|
||||||
if (Std.isOfType(value, Int))
|
if (Std.isOfType(value, Int))
|
||||||
return cast(value, Int);
|
return cast(value, Int);
|
||||||
var intValue:Null<Int> = Std.parseInt(value);
|
var intValue:Null<Int> = Std.parseInt(value);
|
||||||
if (intValue == null)
|
if (intValue == null)
|
||||||
intValue = 0;
|
intValue = defaultValue;
|
||||||
return intValue;
|
return intValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,13 +1229,13 @@ class LinkedMesh {
|
|||||||
public var skin(default, null):String;
|
public var skin(default, null):String;
|
||||||
public var slotIndex(default, null):Int;
|
public var slotIndex(default, null):Int;
|
||||||
public var mesh(default, null):MeshAttachment;
|
public var mesh(default, null):MeshAttachment;
|
||||||
public var inheritDeform(default, null):Bool;
|
public var inheritTimeline(default, null):Bool;
|
||||||
|
|
||||||
public function new(mesh:MeshAttachment, skin:String, slotIndex:Int, parent:String, inheritDeform:Bool) {
|
public function new(mesh:MeshAttachment, skin:String, slotIndex:Int, parent:String, inheritTimeline:Bool) {
|
||||||
this.mesh = mesh;
|
this.mesh = mesh;
|
||||||
this.skin = skin;
|
this.skin = skin;
|
||||||
this.slotIndex = slotIndex;
|
this.slotIndex = slotIndex;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.inheritDeform = inheritDeform;
|
this.inheritTimeline = inheritTimeline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,8 @@ class Skin {
|
|||||||
if (attachment.attachment == null)
|
if (attachment.attachment == null)
|
||||||
continue;
|
continue;
|
||||||
if (Std.isOfType(attachment.attachment, MeshAttachment)) {
|
if (Std.isOfType(attachment.attachment, MeshAttachment)) {
|
||||||
attachment.attachment = new MeshAttachment(attachment.attachment.name).newLinkedMesh();
|
var mesh = cast(attachment.attachment, MeshAttachment);
|
||||||
|
attachment.attachment = new MeshAttachment(mesh.name, mesh.path).newLinkedMesh();
|
||||||
setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
||||||
} else {
|
} else {
|
||||||
attachment.attachment = attachment.attachment.copy();
|
attachment.attachment = attachment.attachment.copy();
|
||||||
|
|||||||
7
spine-haxe/spine-haxe/spine/SpineException.hx
Normal file
7
spine-haxe/spine-haxe/spine/SpineException.hx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package spine;
|
||||||
|
|
||||||
|
class SpineException extends haxe.Exception {
|
||||||
|
public function new(message:String) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,18 +15,23 @@ class Animation {
|
|||||||
|
|
||||||
public function new(name:String, timelines:Vector<Timeline>, duration:Float) {
|
public function new(name:String, timelines:Vector<Timeline>, duration:Float) {
|
||||||
if (name == null)
|
if (name == null)
|
||||||
throw new ArgumentError("name cannot be null.");
|
throw new SpineException("name cannot be null.");
|
||||||
if (timelines == null)
|
|
||||||
throw new ArgumentError("timelines cannot be null.");
|
|
||||||
_name = name;
|
_name = name;
|
||||||
|
setTimelines(timelines);
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTimelines(timelines:Vector<Timeline>) {
|
||||||
|
if (timelines == null)
|
||||||
|
throw new SpineException("timelines cannot be null.");
|
||||||
_timelines = timelines;
|
_timelines = timelines;
|
||||||
|
_timelineIds = new Dictionary<String, Bool>();
|
||||||
for (timeline in timelines) {
|
for (timeline in timelines) {
|
||||||
var ids:Vector<String> = timeline.propertyIds;
|
var ids:Vector<String> = timeline.propertyIds;
|
||||||
for (id in ids) {
|
for (id in ids) {
|
||||||
_timelineIds[id] = true;
|
_timelineIds[id] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.duration = duration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasTimeline(ids:Vector<String>):Bool {
|
public function hasTimeline(ids:Vector<String>):Bool {
|
||||||
|
|||||||
@ -181,14 +181,22 @@ class AnimationState {
|
|||||||
} else {
|
} else {
|
||||||
var timelineMode:Vector<Int> = current.timelineMode;
|
var timelineMode:Vector<Int> = current.timelineMode;
|
||||||
|
|
||||||
var firstFrame:Bool = current.timelinesRotation.length == 0;
|
var shortestRotation = current.shortestRotation;
|
||||||
|
var firstFrame:Bool = !shortestRotation && current.timelinesRotation.length != timelineCount << 1;
|
||||||
if (firstFrame)
|
if (firstFrame)
|
||||||
current.timelinesRotation.length = timelineCount << 1;
|
current.timelinesRotation.length = timelineCount << 1;
|
||||||
|
|
||||||
for (ii in 0...timelineCount) {
|
for (ii in 0...timelineCount) {
|
||||||
var timeline:Timeline = timelines[ii];
|
var timeline:Timeline = timelines[ii];
|
||||||
var timelineBlend:MixBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup;
|
var timelineBlend:MixBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup;
|
||||||
timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, MixDirection.mixIn);
|
if (!shortestRotation && Std.isOfType(timeline, RotateTimeline)) {
|
||||||
|
this.applyRotateTimeline(cast(timeline, RotateTimeline), skeleton, applyTime, mix, timelineBlend, current.timelinesRotation, ii << 1,
|
||||||
|
firstFrame);
|
||||||
|
} else if (Std.isOfType(timeline, AttachmentTimeline)) {
|
||||||
|
this.applyAttachmentTimeline(cast(timeline, AttachmentTimeline), skeleton, applyTime, blend, true);
|
||||||
|
} else {
|
||||||
|
timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, MixDirection.mixIn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queueEvents(current, animationTime);
|
queueEvents(current, animationTime);
|
||||||
@ -255,8 +263,9 @@ class AnimationState {
|
|||||||
} else {
|
} else {
|
||||||
var timelineMode:Vector<Int> = from.timelineMode;
|
var timelineMode:Vector<Int> = from.timelineMode;
|
||||||
var timelineHoldMix:Vector<TrackEntry> = from.timelineHoldMix;
|
var timelineHoldMix:Vector<TrackEntry> = from.timelineHoldMix;
|
||||||
|
var shortestRotation = from.shortestRotation;
|
||||||
|
|
||||||
var firstFrame:Bool = from.timelinesRotation.length != timelineCount << 1;
|
var firstFrame:Bool = !shortestRotation && from.timelinesRotation.length != timelineCount << 1;
|
||||||
if (firstFrame)
|
if (firstFrame)
|
||||||
from.timelinesRotation.length = timelineCount << 1;
|
from.timelinesRotation.length = timelineCount << 1;
|
||||||
var timelinesRotation:Vector<Float> = from.timelinesRotation;
|
var timelinesRotation:Vector<Float> = from.timelinesRotation;
|
||||||
@ -290,9 +299,15 @@ class AnimationState {
|
|||||||
|
|
||||||
from.totalAlpha += alpha;
|
from.totalAlpha += alpha;
|
||||||
|
|
||||||
if (drawOrder && Std.isOfType(timeline, DrawOrderTimeline) && timelineBlend == MixBlend.setup)
|
if (!shortestRotation && Std.isOfType(timeline, RotateTimeline)) {
|
||||||
direction = MixDirection.mixIn;
|
applyRotateTimeline(cast(timeline, RotateTimeline), skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame);
|
||||||
timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, direction);
|
} else if (Std.isOfType(timeline, AttachmentTimeline)) {
|
||||||
|
applyAttachmentTimeline(cast(timeline, AttachmentTimeline), skeleton, applyTime, timelineBlend, attachments);
|
||||||
|
} else {
|
||||||
|
if (drawOrder && Std.isOfType(timeline, DrawOrderTimeline) && timelineBlend == MixBlend.setup)
|
||||||
|
direction = MixDirection.mixIn;
|
||||||
|
timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,6 +320,83 @@ class AnimationState {
|
|||||||
return mix;
|
return mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function applyAttachmentTimeline(timeline:AttachmentTimeline, skeleton:Skeleton, time:Float, blend:MixBlend, attachments:Bool) {
|
||||||
|
var slot = skeleton.slots[timeline.slotIndex];
|
||||||
|
if (!slot.bone.active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (time < timeline.frames[0]) { // Time is before first frame.
|
||||||
|
if (blend == MixBlend.setup || blend == MixBlend.first)
|
||||||
|
this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
|
||||||
|
} else
|
||||||
|
this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments);
|
||||||
|
|
||||||
|
// If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.
|
||||||
|
if (slot.attachmentState <= this.unkeyedState)
|
||||||
|
slot.attachmentState = this.unkeyedState + SETUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyRotateTimeline(timeline:RotateTimeline, skeleton:Skeleton, time:Float, alpha:Float, blend:MixBlend, timelinesRotation:Vector<Float>,
|
||||||
|
i:Int, firstFrame:Bool) {
|
||||||
|
if (firstFrame)
|
||||||
|
timelinesRotation[i] = 0;
|
||||||
|
|
||||||
|
if (alpha == 1) {
|
||||||
|
timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.mixIn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bone = skeleton.bones[timeline.boneIndex];
|
||||||
|
if (!bone.active)
|
||||||
|
return;
|
||||||
|
var frames = timeline.frames;
|
||||||
|
var r1:Float = 0, r2:Float = 0;
|
||||||
|
if (time < frames[0]) {
|
||||||
|
switch (blend) {
|
||||||
|
case MixBlend.setup:
|
||||||
|
bone.rotation = bone.data.rotation;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
case MixBlend.first:
|
||||||
|
r1 = bone.rotation;
|
||||||
|
r2 = bone.data.rotation;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation;
|
||||||
|
r2 = bone.data.rotation + timeline.getCurveValue(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
|
||||||
|
var total:Float = 0, diff:Float = r2 - r1;
|
||||||
|
diff -= (16384.0 - Std.int((16384.499999999996 - diff / 360.0))) * 360.0;
|
||||||
|
if (diff == 0) {
|
||||||
|
total = timelinesRotation[i];
|
||||||
|
} else {
|
||||||
|
var lastTotal:Float = 0, lastDiff:Float = 0;
|
||||||
|
if (firstFrame) {
|
||||||
|
lastTotal = 0;
|
||||||
|
lastDiff = diff;
|
||||||
|
} else {
|
||||||
|
lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops.
|
||||||
|
lastDiff = timelinesRotation[i + 1]; // Difference between bones.
|
||||||
|
}
|
||||||
|
var current = diff > 0, dir = lastTotal >= 0;
|
||||||
|
// Detect cross at 0 (not 180).
|
||||||
|
if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) {
|
||||||
|
// A cross after a 360 rotation is a loop.
|
||||||
|
if (Math.abs(lastTotal) > 180)
|
||||||
|
lastTotal += 360 * MathUtils.signum(lastTotal);
|
||||||
|
dir = current;
|
||||||
|
}
|
||||||
|
total = diff + lastTotal - lastTotal % 360; // Store loops as part of lastTotal.
|
||||||
|
if (dir != current)
|
||||||
|
total += 360 * MathUtils.signum(lastTotal);
|
||||||
|
timelinesRotation[i] = total;
|
||||||
|
}
|
||||||
|
timelinesRotation[i + 1] = diff;
|
||||||
|
bone.rotation = r1 + total * alpha;
|
||||||
|
}
|
||||||
|
|
||||||
private function setAttachment(skeleton:Skeleton, slot:Slot, attachmentName:String, attachments:Bool):Void {
|
private function setAttachment(skeleton:Skeleton, slot:Slot, attachmentName:String, attachments:Bool):Void {
|
||||||
slot.attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slot.data.index, attachmentName);
|
slot.attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slot.data.index, attachmentName);
|
||||||
if (attachments)
|
if (attachments)
|
||||||
@ -519,6 +611,9 @@ class AnimationState {
|
|||||||
entry.loop = loop;
|
entry.loop = loop;
|
||||||
entry.holdPrevious = false;
|
entry.holdPrevious = false;
|
||||||
|
|
||||||
|
entry.reverse = false;
|
||||||
|
entry.shortestRotation = false;
|
||||||
|
|
||||||
entry.eventThreshold = 0;
|
entry.eventThreshold = 0;
|
||||||
entry.attachmentThreshold = 0;
|
entry.attachmentThreshold = 0;
|
||||||
entry.drawOrderThreshold = 0;
|
entry.drawOrderThreshold = 0;
|
||||||
@ -536,9 +631,10 @@ class AnimationState {
|
|||||||
entry.timeScale = 1;
|
entry.timeScale = 1;
|
||||||
|
|
||||||
entry.alpha = 1;
|
entry.alpha = 1;
|
||||||
entry.interruptAlpha = 1;
|
|
||||||
entry.mixTime = 0;
|
entry.mixTime = 0;
|
||||||
entry.mixDuration = last == null ? 0 : data.getMix(last.animation, animation);
|
entry.mixDuration = last == null ? 0 : data.getMix(last.animation, animation);
|
||||||
|
entry.interruptAlpha = 1;
|
||||||
|
entry.totalAlpha = 0;
|
||||||
entry.mixBlend = MixBlend.replace;
|
entry.mixBlend = MixBlend.replace;
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,10 +106,10 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
if (!slot.bone.active)
|
if (!slot.bone.active)
|
||||||
return;
|
return;
|
||||||
var slotAttachment:Attachment = slot.attachment;
|
var slotAttachment:Attachment = slot.attachment;
|
||||||
|
if (slotAttachment == null)
|
||||||
if (!Std.isOfType(slotAttachment, VertexAttachment) || cast(slotAttachment, VertexAttachment).deformAttachment != attachment)
|
return;
|
||||||
|
if (!Std.isOfType(slotAttachment, VertexAttachment) || cast(slotAttachment, VertexAttachment).timelineAttachment != attachment)
|
||||||
return;
|
return;
|
||||||
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
|
||||||
|
|
||||||
var deform:Vector<Float> = slot.deform;
|
var deform:Vector<Float> = slot.deform;
|
||||||
if (deform.length == 0)
|
if (deform.length == 0)
|
||||||
@ -128,6 +128,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deform.length = vertexCount;
|
deform.length = vertexCount;
|
||||||
|
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
||||||
if (vertexAttachment.bones == null) {
|
if (vertexAttachment.bones == null) {
|
||||||
// Unweighted vertex positions.
|
// Unweighted vertex positions.
|
||||||
setupVertices = vertexAttachment.vertices;
|
setupVertices = vertexAttachment.vertices;
|
||||||
@ -152,6 +153,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
var lastVertices:Vector<Float> = vertices[frames.length - 1];
|
var lastVertices:Vector<Float> = vertices[frames.length - 1];
|
||||||
if (alpha == 1) {
|
if (alpha == 1) {
|
||||||
if (blend == MixBlend.add) {
|
if (blend == MixBlend.add) {
|
||||||
|
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
||||||
if (vertexAttachment.bones == null) {
|
if (vertexAttachment.bones == null) {
|
||||||
// Unweighted vertex positions, with alpha.
|
// Unweighted vertex positions, with alpha.
|
||||||
setupVertices = vertexAttachment.vertices;
|
setupVertices = vertexAttachment.vertices;
|
||||||
@ -172,6 +174,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
} else {
|
} else {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case MixBlend.setup:
|
case MixBlend.setup:
|
||||||
|
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
||||||
if (vertexAttachment.bones == null) {
|
if (vertexAttachment.bones == null) {
|
||||||
// Unweighted vertex positions, with alpha.
|
// Unweighted vertex positions, with alpha.
|
||||||
setupVertices = vertexAttachment.vertices;
|
setupVertices = vertexAttachment.vertices;
|
||||||
@ -190,6 +193,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
deform[i] += (lastVertices[i] - deform[i]) * alpha;
|
deform[i] += (lastVertices[i] - deform[i]) * alpha;
|
||||||
}
|
}
|
||||||
case MixBlend.add:
|
case MixBlend.add:
|
||||||
|
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
||||||
if (vertexAttachment.bones == null) {
|
if (vertexAttachment.bones == null) {
|
||||||
// Unweighted vertex positions, with alpha.
|
// Unweighted vertex positions, with alpha.
|
||||||
setupVertices = vertexAttachment.vertices;
|
setupVertices = vertexAttachment.vertices;
|
||||||
@ -215,6 +219,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
|
|
||||||
if (alpha == 1) {
|
if (alpha == 1) {
|
||||||
if (blend == MixBlend.add) {
|
if (blend == MixBlend.add) {
|
||||||
|
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
||||||
if (vertexAttachment.bones == null) {
|
if (vertexAttachment.bones == null) {
|
||||||
// Unweighted vertex positions, with alpha.
|
// Unweighted vertex positions, with alpha.
|
||||||
setupVertices = vertexAttachment.vertices;
|
setupVertices = vertexAttachment.vertices;
|
||||||
@ -238,6 +243,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
} else {
|
} else {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case MixBlend.setup:
|
case MixBlend.setup:
|
||||||
|
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
||||||
if (vertexAttachment.bones == null) {
|
if (vertexAttachment.bones == null) {
|
||||||
// Unweighted vertex positions, with alpha.
|
// Unweighted vertex positions, with alpha.
|
||||||
setupVertices = vertexAttachment.vertices;
|
setupVertices = vertexAttachment.vertices;
|
||||||
@ -259,6 +265,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
|||||||
deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;
|
deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;
|
||||||
}
|
}
|
||||||
case MixBlend.add:
|
case MixBlend.add:
|
||||||
|
var vertexAttachment:VertexAttachment = cast(slotAttachment, VertexAttachment);
|
||||||
if (vertexAttachment.bones == null) {
|
if (vertexAttachment.bones == null) {
|
||||||
// Unweighted vertex positions, with alpha.
|
// Unweighted vertex positions, with alpha.
|
||||||
setupVertices = vertexAttachment.vertices;
|
setupVertices = vertexAttachment.vertices;
|
||||||
|
|||||||
@ -26,5 +26,7 @@ class Property {
|
|||||||
public static inline var pathConstraintSpacing:Int = 17;
|
public static inline var pathConstraintSpacing:Int = 17;
|
||||||
public static inline var pathConstraintMix:Int = 18;
|
public static inline var pathConstraintMix:Int = 18;
|
||||||
|
|
||||||
|
public static inline var sequence:Int = 19;
|
||||||
|
|
||||||
public function new() {}
|
public function new() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import spine.Event;
|
|||||||
import spine.Skeleton;
|
import spine.Skeleton;
|
||||||
|
|
||||||
class RotateTimeline extends CurveTimeline1 implements BoneTimeline {
|
class RotateTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||||
private var boneIndex:Int = 0;
|
public var boneIndex:Int = 0;
|
||||||
|
|
||||||
public function new(frameCount:Int, bezierCount:Int, boneIndex:Int) {
|
public function new(frameCount:Int, bezierCount:Int, boneIndex:Int) {
|
||||||
super(frameCount, bezierCount, Vector.ofArray([Property.rotate + "|" + boneIndex]));
|
super(frameCount, bezierCount, Vector.ofArray([Property.rotate + "|" + boneIndex]));
|
||||||
|
|||||||
98
spine-haxe/spine-haxe/spine/animation/SequenceTimeline.hx
Normal file
98
spine-haxe/spine-haxe/spine/animation/SequenceTimeline.hx
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package spine.animation;
|
||||||
|
|
||||||
|
import openfl.Vector;
|
||||||
|
import spine.attachments.VertexAttachment;
|
||||||
|
import spine.attachments.Attachment;
|
||||||
|
|
||||||
|
class SequenceTimeline extends Timeline implements SlotTimeline {
|
||||||
|
static var ENTRIES = 3;
|
||||||
|
static var MODE = 1;
|
||||||
|
static var DELAY = 2;
|
||||||
|
|
||||||
|
var slotIndex:Int;
|
||||||
|
var attachment:HasTextureRegion;
|
||||||
|
|
||||||
|
public function new(frameCount:Int, slotIndex:Int, attachment:HasTextureRegion) {
|
||||||
|
super(frameCount, Vector.ofArray([
|
||||||
|
Std.string(Property.sequence) + "|" + Std.string(slotIndex) + "|" + Std.string(attachment.sequence.id)
|
||||||
|
]));
|
||||||
|
this.slotIndex = slotIndex;
|
||||||
|
this.attachment = attachment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override function getFrameEntries():Int {
|
||||||
|
return SequenceTimeline.ENTRIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSlotIndex():Int {
|
||||||
|
return this.slotIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAttachment():Attachment {
|
||||||
|
return cast(attachment, Attachment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the time, mode, index, and frame time for the specified frame.
|
||||||
|
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||||
|
* @param time Seconds between frames. */
|
||||||
|
public function setFrame(frame:Int, time:Float, mode:SequenceMode, index:Int, delay:Float) {
|
||||||
|
frame *= SequenceTimeline.ENTRIES;
|
||||||
|
frames[frame] = time;
|
||||||
|
frames[frame + SequenceTimeline.MODE] = mode.value | (index << 4);
|
||||||
|
frames[frame + SequenceTimeline.DELAY] = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Vector<Event>, alpha:Float, blend:MixBlend,
|
||||||
|
direction:MixDirection):Void {
|
||||||
|
var slot = skeleton.slots[this.slotIndex];
|
||||||
|
if (!slot.bone.active)
|
||||||
|
return;
|
||||||
|
var slotAttachment = slot.attachment;
|
||||||
|
var attachment = cast(this.attachment, Attachment);
|
||||||
|
if (slotAttachment != attachment) {
|
||||||
|
if (!Std.isOfType(slotAttachment, VertexAttachment) || cast(slotAttachment, VertexAttachment).timelineAttachment != attachment)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time < frames[0]) { // Time is before first frame.
|
||||||
|
if (blend == MixBlend.setup || blend == MixBlend.first)
|
||||||
|
slot.sequenceIndex = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = Timeline.search(frames, time, SequenceTimeline.ENTRIES);
|
||||||
|
var before = frames[i];
|
||||||
|
var modeAndIndex = Std.int(frames[i + SequenceTimeline.MODE]);
|
||||||
|
var delay = frames[i + SequenceTimeline.DELAY];
|
||||||
|
|
||||||
|
if (this.attachment.sequence == null)
|
||||||
|
return;
|
||||||
|
var index = modeAndIndex >> 4,
|
||||||
|
count = this.attachment.sequence.regions.length;
|
||||||
|
var mode = SequenceMode.values[modeAndIndex & 0xf];
|
||||||
|
if (mode != SequenceMode.hold) {
|
||||||
|
index += Std.int(((time - before) / delay + 0.00001));
|
||||||
|
switch (mode) {
|
||||||
|
case SequenceMode.once:
|
||||||
|
index = Std.int(Math.min(count - 1, index));
|
||||||
|
case SequenceMode.loop:
|
||||||
|
index %= count;
|
||||||
|
case SequenceMode.pingpong:
|
||||||
|
var n = (count << 1) - 2;
|
||||||
|
index = n == 0 ? 0 : index % n;
|
||||||
|
if (index >= count)
|
||||||
|
index = n - index;
|
||||||
|
case SequenceMode.onceReverse:
|
||||||
|
index = Std.int(Math.max(count - 1 - index, 0));
|
||||||
|
case SequenceMode.loopReverse:
|
||||||
|
index = count - 1 - (index % count);
|
||||||
|
case SequenceMode.pingpongReverse:
|
||||||
|
var n = (count << 1) - 2;
|
||||||
|
index = n == 0 ? 0 : (index + count - 1) % n;
|
||||||
|
if (index >= count)
|
||||||
|
index = n - index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slot.sequenceIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,7 +26,7 @@ class Timeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Vector<Event>, alpha:Float, blend:MixBlend, direction:MixDirection):Void {
|
public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Vector<Event>, alpha:Float, blend:MixBlend, direction:MixDirection):Void {
|
||||||
trace("Timeline implementations must override apply()");
|
throw new SpineException("Timeline implementations must override apply()");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function search1(frames:Vector<Float>, time:Float):Int {
|
public static function search1(frames:Vector<Float>, time:Float):Int {
|
||||||
|
|||||||
@ -42,6 +42,7 @@ class TrackEntry implements Poolable {
|
|||||||
public var timelineMode:Vector<Int> = new Vector<Int>();
|
public var timelineMode:Vector<Int> = new Vector<Int>();
|
||||||
public var timelineHoldMix:Vector<TrackEntry> = new Vector<TrackEntry>();
|
public var timelineHoldMix:Vector<TrackEntry> = new Vector<TrackEntry>();
|
||||||
public var timelinesRotation:Vector<Float> = new Vector<Float>();
|
public var timelinesRotation:Vector<Float> = new Vector<Float>();
|
||||||
|
public var shortestRotation = false;
|
||||||
|
|
||||||
public function new() {}
|
public function new() {}
|
||||||
|
|
||||||
|
|||||||
@ -20,49 +20,34 @@ class AtlasAttachmentLoader implements AttachmentLoader {
|
|||||||
var path = sequence.getPath(basePath, i);
|
var path = sequence.getPath(basePath, i);
|
||||||
var region = this.atlas.findRegion(path);
|
var region = this.atlas.findRegion(path);
|
||||||
if (region == null)
|
if (region == null)
|
||||||
trace("Region not found in atlas: " + path + " (sequence: " + name + ")");
|
throw new SpineException("Region not found in atlas: " + path + " (sequence: " + name + ")");
|
||||||
regions[i] = region;
|
regions[i] = region;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newRegionAttachment(skin:Skin, name:String, path:String):RegionAttachment {
|
public function newRegionAttachment(skin:Skin, name:String, path:String, sequence:Sequence):RegionAttachment {
|
||||||
var region = atlas.findRegion(path);
|
var attachment = new RegionAttachment(name, path);
|
||||||
if (region == null) {
|
if (sequence != null) {
|
||||||
trace("Region not found in atlas: " + path + " (region attachment: " + name + ")");
|
this.loadSequence(name, path, sequence);
|
||||||
return null;
|
} else {
|
||||||
|
var region = this.atlas.findRegion(path);
|
||||||
|
if (region == null)
|
||||||
|
throw new SpineException("Region not found in atlas: " + path + " (region attachment: " + name + ")");
|
||||||
|
attachment.region = region;
|
||||||
}
|
}
|
||||||
var attachment:RegionAttachment = new RegionAttachment(name);
|
|
||||||
attachment.rendererObject = region;
|
|
||||||
attachment.setUVs(region.u, region.v, region.u2, region.v2, region.degrees);
|
|
||||||
attachment.regionOffsetX = region.offsetX;
|
|
||||||
attachment.regionOffsetY = region.offsetY;
|
|
||||||
attachment.regionWidth = region.width;
|
|
||||||
attachment.regionHeight = region.height;
|
|
||||||
attachment.regionOriginalWidth = region.originalWidth;
|
|
||||||
attachment.regionOriginalHeight = region.originalHeight;
|
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newMeshAttachment(skin:Skin, name:String, path:String):MeshAttachment {
|
public function newMeshAttachment(skin:Skin, name:String, path:String, sequence:Sequence):MeshAttachment {
|
||||||
var region = atlas.findRegion(path);
|
var attachment = new MeshAttachment(name, path);
|
||||||
if (region == null) {
|
if (sequence != null) {
|
||||||
trace("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
|
this.loadSequence(name, path, sequence);
|
||||||
return null;
|
} else {
|
||||||
|
var region = atlas.findRegion(path);
|
||||||
|
if (region == null)
|
||||||
|
throw new SpineException("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
|
||||||
|
attachment.region = region;
|
||||||
}
|
}
|
||||||
|
|
||||||
var attachment:MeshAttachment = new MeshAttachment(name);
|
|
||||||
attachment.rendererObject = region;
|
|
||||||
attachment.regionU = region.u;
|
|
||||||
attachment.regionV = region.v;
|
|
||||||
attachment.regionU2 = region.u2;
|
|
||||||
attachment.regionV2 = region.v2;
|
|
||||||
attachment.regionDegrees = region.degrees;
|
|
||||||
attachment.regionOffsetX = region.offsetX;
|
|
||||||
attachment.regionOffsetY = region.offsetY;
|
|
||||||
attachment.regionWidth = region.width;
|
|
||||||
attachment.regionHeight = region.height;
|
|
||||||
attachment.regionOriginalWidth = region.originalWidth;
|
|
||||||
attachment.regionOriginalHeight = region.originalHeight;
|
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,14 +66,4 @@ class AtlasAttachmentLoader implements AttachmentLoader {
|
|||||||
public function newClippingAttachment(skin:Skin, name:String):ClippingAttachment {
|
public function newClippingAttachment(skin:Skin, name:String):ClippingAttachment {
|
||||||
return new ClippingAttachment(name);
|
return new ClippingAttachment(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function nextPOT(value:Int):Int {
|
|
||||||
value--;
|
|
||||||
value |= value >> 1;
|
|
||||||
value |= value >> 2;
|
|
||||||
value |= value >> 4;
|
|
||||||
value |= value >> 8;
|
|
||||||
value |= value >> 16;
|
|
||||||
return value + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class MeshAttachment extends VertexAttachment implements HasTextureRegion {
|
|||||||
|
|
||||||
public function updateRegion():Void {
|
public function updateRegion():Void {
|
||||||
if (region == null) {
|
if (region == null) {
|
||||||
trace("Region not set.");
|
throw new SpineException("Region not set.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var regionUVs = this.regionUVs;
|
var regionUVs = this.regionUVs;
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class RegionAttachment extends Attachment implements HasTextureRegion {
|
|||||||
|
|
||||||
public function updateRegion():Void {
|
public function updateRegion():Void {
|
||||||
if (region == null) {
|
if (region == null) {
|
||||||
trace("Region not set.");
|
throw new SpineException("Region not set.");
|
||||||
uvs[0] = 0;
|
uvs[0] = 0;
|
||||||
uvs[1] = 0;
|
uvs[1] = 0;
|
||||||
uvs[2] = 0;
|
uvs[2] = 0;
|
||||||
|
|||||||
@ -18,7 +18,6 @@ class SkeletonAnimation extends SkeletonSprite implements IAnimatable {
|
|||||||
|
|
||||||
public function advanceTime(time:Float):Void {
|
public function advanceTime(time:Float):Void {
|
||||||
var stage = Starling.current.stage;
|
var stage = Starling.current.stage;
|
||||||
skeleton.update(time);
|
|
||||||
state.update(time);
|
state.update(time);
|
||||||
state.apply(skeleton);
|
state.apply(skeleton);
|
||||||
skeleton.updateWorldTransform();
|
skeleton.updateWorldTransform();
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class SkeletonSprite extends DisplayObject {
|
|||||||
verticesCount = verticesLength >> 1;
|
verticesCount = verticesLength >> 1;
|
||||||
if (worldVertices.length < verticesLength)
|
if (worldVertices.length < verticesLength)
|
||||||
worldVertices.length = verticesLength;
|
worldVertices.length = verticesLength;
|
||||||
region.computeWorldVertices(slot.bone, worldVertices, 0, 2);
|
region.computeWorldVertices(slot, worldVertices, 0, 2);
|
||||||
|
|
||||||
mesh = null;
|
mesh = null;
|
||||||
if (Std.isOfType(region.rendererObject, SkeletonMesh)) {
|
if (Std.isOfType(region.rendererObject, SkeletonMesh)) {
|
||||||
@ -220,7 +220,7 @@ class SkeletonSprite extends DisplayObject {
|
|||||||
if (Std.isOfType(attachment, RegionAttachment)) {
|
if (Std.isOfType(attachment, RegionAttachment)) {
|
||||||
var region:RegionAttachment = cast(slot.attachment, RegionAttachment);
|
var region:RegionAttachment = cast(slot.attachment, RegionAttachment);
|
||||||
verticesLength = 8;
|
verticesLength = 8;
|
||||||
region.computeWorldVertices(slot.bone, worldVertices, 0, 2);
|
region.computeWorldVertices(slot, worldVertices, 0, 2);
|
||||||
} else if (Std.isOfType(attachment, MeshAttachment)) {
|
} else if (Std.isOfType(attachment, MeshAttachment)) {
|
||||||
var mesh:MeshAttachment = cast(attachment, MeshAttachment);
|
var mesh:MeshAttachment = cast(attachment, MeshAttachment);
|
||||||
verticesLength = mesh.worldVerticesLength;
|
verticesLength = mesh.worldVerticesLength;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user