[ts] Updated all core API documentation. See #1506.

This commit is contained in:
badlogic 2019-10-03 16:43:46 +02:00
parent 3c60f58f1f
commit 4410672ce2
51 changed files with 1349 additions and 221 deletions

View File

@ -253,12 +253,12 @@ declare module spine {
static NOT_LAST: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
events: Event[];
listeners: AnimationStateListener2[];
listeners: AnimationStateListener[];
queue: EventQueue;
propertyIDs: IntSet;
animationsChanged: boolean;
timeScale: number;
trackEntryPool: Pool<TrackEntry>;
constructor(data: AnimationStateData);
update(delta: number): void;
@ -284,8 +284,8 @@ declare module spine {
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener2): void;
removeListener(listener: AnimationStateListener2): void;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
clearListeners(): void;
clearListenerNotifications(): void;
}
@ -294,7 +294,7 @@ declare module spine {
next: TrackEntry;
mixingFrom: TrackEntry;
mixingTo: TrackEntry;
listener: AnimationStateListener2;
listener: AnimationStateListener;
trackIndex: number;
loop: boolean;
holdPrevious: boolean;
@ -348,7 +348,7 @@ declare module spine {
complete = 4,
event = 5
}
interface AnimationStateListener2 {
interface AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -356,7 +356,7 @@ declare module spine {
complete(entry: TrackEntry): void;
event(entry: TrackEntry, event: Event): void;
}
abstract class AnimationStateAdapter2 implements AnimationStateListener2 {
abstract class AnimationStateAdapter implements AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -446,10 +446,10 @@ declare module spine {
appliedValid: boolean;
a: number;
b: number;
worldX: number;
c: number;
d: number;
worldY: number;
worldX: number;
sorted: boolean;
active: boolean;
constructor(data: BoneData, skeleton: Skeleton, parent: Bone);
@ -708,8 +708,8 @@ declare module spine {
static CURVE_LINEAR: number;
static CURVE_STEPPED: number;
static CURVE_BEZIER: number;
attachmentLoader: AttachmentLoader;
scale: number;
attachmentLoader: AttachmentLoader;
private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(binary: Uint8Array): SkeletonData;
@ -852,6 +852,7 @@ declare module spine {
private attachmentTime;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
getAttachment(): Attachment;
setAttachment(attachment: Attachment): void;
setAttachmentTime(time: number): void;

View File

@ -1346,12 +1346,12 @@ var spine;
var AnimationState = (function () {
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
this.propertyIDs = new spine.IntSet();
this.animationsChanged = false;
this.timeScale = 1;
this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); });
this.data = data;
}
@ -2097,24 +2097,24 @@ var spine;
EventType[EventType["complete"] = 4] = "complete";
EventType[EventType["event"] = 5] = "event";
})(EventType = spine.EventType || (spine.EventType = {}));
var AnimationStateAdapter2 = (function () {
function AnimationStateAdapter2() {
var AnimationStateAdapter = (function () {
function AnimationStateAdapter() {
}
AnimationStateAdapter2.prototype.start = function (entry) {
AnimationStateAdapter.prototype.start = function (entry) {
};
AnimationStateAdapter2.prototype.interrupt = function (entry) {
AnimationStateAdapter.prototype.interrupt = function (entry) {
};
AnimationStateAdapter2.prototype.end = function (entry) {
AnimationStateAdapter.prototype.end = function (entry) {
};
AnimationStateAdapter2.prototype.dispose = function (entry) {
AnimationStateAdapter.prototype.dispose = function (entry) {
};
AnimationStateAdapter2.prototype.complete = function (entry) {
AnimationStateAdapter.prototype.complete = function (entry) {
};
AnimationStateAdapter2.prototype.event = function (entry, event) {
AnimationStateAdapter.prototype.event = function (entry, event) {
};
return AnimationStateAdapter2;
return AnimationStateAdapter;
}());
spine.AnimationStateAdapter2 = AnimationStateAdapter2;
spine.AnimationStateAdapter = AnimationStateAdapter;
})(spine || (spine = {}));
var spine;
(function (spine) {
@ -2484,10 +2484,10 @@ var spine;
this.appliedValid = false;
this.a = 0;
this.b = 0;
this.worldX = 0;
this.c = 0;
this.d = 0;
this.worldY = 0;
this.worldX = 0;
this.sorted = false;
this.active = false;
if (data == null)
@ -6416,6 +6416,9 @@ var spine;
this.darkColor = data.darkColor == null ? null : new spine.Color();
this.setToSetupPose();
}
Slot.prototype.getSkeleton = function () {
return this.bone.skeleton;
};
Slot.prototype.getAttachment = function () {
return this.attachment;
};

File diff suppressed because one or more lines are too long

View File

@ -253,12 +253,12 @@ declare module spine {
static NOT_LAST: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
events: Event[];
listeners: AnimationStateListener2[];
listeners: AnimationStateListener[];
queue: EventQueue;
propertyIDs: IntSet;
animationsChanged: boolean;
timeScale: number;
trackEntryPool: Pool<TrackEntry>;
constructor(data: AnimationStateData);
update(delta: number): void;
@ -284,8 +284,8 @@ declare module spine {
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener2): void;
removeListener(listener: AnimationStateListener2): void;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
clearListeners(): void;
clearListenerNotifications(): void;
}
@ -294,7 +294,7 @@ declare module spine {
next: TrackEntry;
mixingFrom: TrackEntry;
mixingTo: TrackEntry;
listener: AnimationStateListener2;
listener: AnimationStateListener;
trackIndex: number;
loop: boolean;
holdPrevious: boolean;
@ -348,7 +348,7 @@ declare module spine {
complete = 4,
event = 5
}
interface AnimationStateListener2 {
interface AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -356,7 +356,7 @@ declare module spine {
complete(entry: TrackEntry): void;
event(entry: TrackEntry, event: Event): void;
}
abstract class AnimationStateAdapter2 implements AnimationStateListener2 {
abstract class AnimationStateAdapter implements AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -446,10 +446,10 @@ declare module spine {
appliedValid: boolean;
a: number;
b: number;
worldX: number;
c: number;
d: number;
worldY: number;
worldX: number;
sorted: boolean;
active: boolean;
constructor(data: BoneData, skeleton: Skeleton, parent: Bone);
@ -708,8 +708,8 @@ declare module spine {
static CURVE_LINEAR: number;
static CURVE_STEPPED: number;
static CURVE_BEZIER: number;
attachmentLoader: AttachmentLoader;
scale: number;
attachmentLoader: AttachmentLoader;
private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(binary: Uint8Array): SkeletonData;
@ -852,6 +852,7 @@ declare module spine {
private attachmentTime;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
getAttachment(): Attachment;
setAttachment(attachment: Attachment): void;
setAttachmentTime(time: number): void;

View File

@ -1346,12 +1346,12 @@ var spine;
var AnimationState = (function () {
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
this.propertyIDs = new spine.IntSet();
this.animationsChanged = false;
this.timeScale = 1;
this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); });
this.data = data;
}
@ -2097,24 +2097,24 @@ var spine;
EventType[EventType["complete"] = 4] = "complete";
EventType[EventType["event"] = 5] = "event";
})(EventType = spine.EventType || (spine.EventType = {}));
var AnimationStateAdapter2 = (function () {
function AnimationStateAdapter2() {
var AnimationStateAdapter = (function () {
function AnimationStateAdapter() {
}
AnimationStateAdapter2.prototype.start = function (entry) {
AnimationStateAdapter.prototype.start = function (entry) {
};
AnimationStateAdapter2.prototype.interrupt = function (entry) {
AnimationStateAdapter.prototype.interrupt = function (entry) {
};
AnimationStateAdapter2.prototype.end = function (entry) {
AnimationStateAdapter.prototype.end = function (entry) {
};
AnimationStateAdapter2.prototype.dispose = function (entry) {
AnimationStateAdapter.prototype.dispose = function (entry) {
};
AnimationStateAdapter2.prototype.complete = function (entry) {
AnimationStateAdapter.prototype.complete = function (entry) {
};
AnimationStateAdapter2.prototype.event = function (entry, event) {
AnimationStateAdapter.prototype.event = function (entry, event) {
};
return AnimationStateAdapter2;
return AnimationStateAdapter;
}());
spine.AnimationStateAdapter2 = AnimationStateAdapter2;
spine.AnimationStateAdapter = AnimationStateAdapter;
})(spine || (spine = {}));
var spine;
(function (spine) {
@ -2484,10 +2484,10 @@ var spine;
this.appliedValid = false;
this.a = 0;
this.b = 0;
this.worldX = 0;
this.c = 0;
this.d = 0;
this.worldY = 0;
this.worldX = 0;
this.sorted = false;
this.active = false;
if (data == null)
@ -6416,6 +6416,9 @@ var spine;
this.darkColor = data.darkColor == null ? null : new spine.Color();
this.setToSetupPose();
}
Slot.prototype.getSkeleton = function () {
return this.bone.skeleton;
};
Slot.prototype.getAttachment = function () {
return this.attachment;
};

File diff suppressed because one or more lines are too long

View File

@ -253,12 +253,12 @@ declare module spine {
static NOT_LAST: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
events: Event[];
listeners: AnimationStateListener2[];
listeners: AnimationStateListener[];
queue: EventQueue;
propertyIDs: IntSet;
animationsChanged: boolean;
timeScale: number;
trackEntryPool: Pool<TrackEntry>;
constructor(data: AnimationStateData);
update(delta: number): void;
@ -284,8 +284,8 @@ declare module spine {
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener2): void;
removeListener(listener: AnimationStateListener2): void;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
clearListeners(): void;
clearListenerNotifications(): void;
}
@ -294,7 +294,7 @@ declare module spine {
next: TrackEntry;
mixingFrom: TrackEntry;
mixingTo: TrackEntry;
listener: AnimationStateListener2;
listener: AnimationStateListener;
trackIndex: number;
loop: boolean;
holdPrevious: boolean;
@ -348,7 +348,7 @@ declare module spine {
complete = 4,
event = 5
}
interface AnimationStateListener2 {
interface AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -356,7 +356,7 @@ declare module spine {
complete(entry: TrackEntry): void;
event(entry: TrackEntry, event: Event): void;
}
abstract class AnimationStateAdapter2 implements AnimationStateListener2 {
abstract class AnimationStateAdapter implements AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -446,10 +446,10 @@ declare module spine {
appliedValid: boolean;
a: number;
b: number;
worldX: number;
c: number;
d: number;
worldY: number;
worldX: number;
sorted: boolean;
active: boolean;
constructor(data: BoneData, skeleton: Skeleton, parent: Bone);
@ -708,8 +708,8 @@ declare module spine {
static CURVE_LINEAR: number;
static CURVE_STEPPED: number;
static CURVE_BEZIER: number;
attachmentLoader: AttachmentLoader;
scale: number;
attachmentLoader: AttachmentLoader;
private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(binary: Uint8Array): SkeletonData;
@ -852,6 +852,7 @@ declare module spine {
private attachmentTime;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
getAttachment(): Attachment;
setAttachment(attachment: Attachment): void;
setAttachmentTime(time: number): void;

View File

@ -1346,12 +1346,12 @@ var spine;
var AnimationState = (function () {
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
this.propertyIDs = new spine.IntSet();
this.animationsChanged = false;
this.timeScale = 1;
this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); });
this.data = data;
}
@ -2097,24 +2097,24 @@ var spine;
EventType[EventType["complete"] = 4] = "complete";
EventType[EventType["event"] = 5] = "event";
})(EventType = spine.EventType || (spine.EventType = {}));
var AnimationStateAdapter2 = (function () {
function AnimationStateAdapter2() {
var AnimationStateAdapter = (function () {
function AnimationStateAdapter() {
}
AnimationStateAdapter2.prototype.start = function (entry) {
AnimationStateAdapter.prototype.start = function (entry) {
};
AnimationStateAdapter2.prototype.interrupt = function (entry) {
AnimationStateAdapter.prototype.interrupt = function (entry) {
};
AnimationStateAdapter2.prototype.end = function (entry) {
AnimationStateAdapter.prototype.end = function (entry) {
};
AnimationStateAdapter2.prototype.dispose = function (entry) {
AnimationStateAdapter.prototype.dispose = function (entry) {
};
AnimationStateAdapter2.prototype.complete = function (entry) {
AnimationStateAdapter.prototype.complete = function (entry) {
};
AnimationStateAdapter2.prototype.event = function (entry, event) {
AnimationStateAdapter.prototype.event = function (entry, event) {
};
return AnimationStateAdapter2;
return AnimationStateAdapter;
}());
spine.AnimationStateAdapter2 = AnimationStateAdapter2;
spine.AnimationStateAdapter = AnimationStateAdapter;
})(spine || (spine = {}));
var spine;
(function (spine) {
@ -2484,10 +2484,10 @@ var spine;
this.appliedValid = false;
this.a = 0;
this.b = 0;
this.worldX = 0;
this.c = 0;
this.d = 0;
this.worldY = 0;
this.worldX = 0;
this.sorted = false;
this.active = false;
if (data == null)
@ -6416,6 +6416,9 @@ var spine;
this.darkColor = data.darkColor == null ? null : new spine.Color();
this.setToSetupPose();
}
Slot.prototype.getSkeleton = function () {
return this.bone.skeleton;
};
Slot.prototype.getAttachment = function () {
return this.attachment;
};

File diff suppressed because one or more lines are too long

View File

@ -253,12 +253,12 @@ declare module spine {
static NOT_LAST: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
events: Event[];
listeners: AnimationStateListener2[];
listeners: AnimationStateListener[];
queue: EventQueue;
propertyIDs: IntSet;
animationsChanged: boolean;
timeScale: number;
trackEntryPool: Pool<TrackEntry>;
constructor(data: AnimationStateData);
update(delta: number): void;
@ -284,8 +284,8 @@ declare module spine {
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener2): void;
removeListener(listener: AnimationStateListener2): void;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
clearListeners(): void;
clearListenerNotifications(): void;
}
@ -294,7 +294,7 @@ declare module spine {
next: TrackEntry;
mixingFrom: TrackEntry;
mixingTo: TrackEntry;
listener: AnimationStateListener2;
listener: AnimationStateListener;
trackIndex: number;
loop: boolean;
holdPrevious: boolean;
@ -348,7 +348,7 @@ declare module spine {
complete = 4,
event = 5
}
interface AnimationStateListener2 {
interface AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -356,7 +356,7 @@ declare module spine {
complete(entry: TrackEntry): void;
event(entry: TrackEntry, event: Event): void;
}
abstract class AnimationStateAdapter2 implements AnimationStateListener2 {
abstract class AnimationStateAdapter implements AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -446,10 +446,10 @@ declare module spine {
appliedValid: boolean;
a: number;
b: number;
worldX: number;
c: number;
d: number;
worldY: number;
worldX: number;
sorted: boolean;
active: boolean;
constructor(data: BoneData, skeleton: Skeleton, parent: Bone);
@ -708,8 +708,8 @@ declare module spine {
static CURVE_LINEAR: number;
static CURVE_STEPPED: number;
static CURVE_BEZIER: number;
attachmentLoader: AttachmentLoader;
scale: number;
attachmentLoader: AttachmentLoader;
private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(binary: Uint8Array): SkeletonData;
@ -852,6 +852,7 @@ declare module spine {
private attachmentTime;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
getAttachment(): Attachment;
setAttachment(attachment: Attachment): void;
setAttachmentTime(time: number): void;

View File

@ -1346,12 +1346,12 @@ var spine;
var AnimationState = (function () {
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
this.propertyIDs = new spine.IntSet();
this.animationsChanged = false;
this.timeScale = 1;
this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); });
this.data = data;
}
@ -2097,24 +2097,24 @@ var spine;
EventType[EventType["complete"] = 4] = "complete";
EventType[EventType["event"] = 5] = "event";
})(EventType = spine.EventType || (spine.EventType = {}));
var AnimationStateAdapter2 = (function () {
function AnimationStateAdapter2() {
var AnimationStateAdapter = (function () {
function AnimationStateAdapter() {
}
AnimationStateAdapter2.prototype.start = function (entry) {
AnimationStateAdapter.prototype.start = function (entry) {
};
AnimationStateAdapter2.prototype.interrupt = function (entry) {
AnimationStateAdapter.prototype.interrupt = function (entry) {
};
AnimationStateAdapter2.prototype.end = function (entry) {
AnimationStateAdapter.prototype.end = function (entry) {
};
AnimationStateAdapter2.prototype.dispose = function (entry) {
AnimationStateAdapter.prototype.dispose = function (entry) {
};
AnimationStateAdapter2.prototype.complete = function (entry) {
AnimationStateAdapter.prototype.complete = function (entry) {
};
AnimationStateAdapter2.prototype.event = function (entry, event) {
AnimationStateAdapter.prototype.event = function (entry, event) {
};
return AnimationStateAdapter2;
return AnimationStateAdapter;
}());
spine.AnimationStateAdapter2 = AnimationStateAdapter2;
spine.AnimationStateAdapter = AnimationStateAdapter;
})(spine || (spine = {}));
var spine;
(function (spine) {
@ -2484,10 +2484,10 @@ var spine;
this.appliedValid = false;
this.a = 0;
this.b = 0;
this.worldX = 0;
this.c = 0;
this.d = 0;
this.worldY = 0;
this.worldX = 0;
this.sorted = false;
this.active = false;
if (data == null)
@ -6416,6 +6416,9 @@ var spine;
this.darkColor = data.darkColor == null ? null : new spine.Color();
this.setToSetupPose();
}
Slot.prototype.getSkeleton = function () {
return this.bone.skeleton;
};
Slot.prototype.getAttachment = function () {
return this.attachment;
};

File diff suppressed because one or more lines are too long

View File

@ -253,12 +253,12 @@ declare module spine {
static NOT_LAST: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
events: Event[];
listeners: AnimationStateListener2[];
listeners: AnimationStateListener[];
queue: EventQueue;
propertyIDs: IntSet;
animationsChanged: boolean;
timeScale: number;
trackEntryPool: Pool<TrackEntry>;
constructor(data: AnimationStateData);
update(delta: number): void;
@ -284,8 +284,8 @@ declare module spine {
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener2): void;
removeListener(listener: AnimationStateListener2): void;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
clearListeners(): void;
clearListenerNotifications(): void;
}
@ -294,7 +294,7 @@ declare module spine {
next: TrackEntry;
mixingFrom: TrackEntry;
mixingTo: TrackEntry;
listener: AnimationStateListener2;
listener: AnimationStateListener;
trackIndex: number;
loop: boolean;
holdPrevious: boolean;
@ -348,7 +348,7 @@ declare module spine {
complete = 4,
event = 5
}
interface AnimationStateListener2 {
interface AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -356,7 +356,7 @@ declare module spine {
complete(entry: TrackEntry): void;
event(entry: TrackEntry, event: Event): void;
}
abstract class AnimationStateAdapter2 implements AnimationStateListener2 {
abstract class AnimationStateAdapter implements AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -446,10 +446,10 @@ declare module spine {
appliedValid: boolean;
a: number;
b: number;
worldX: number;
c: number;
d: number;
worldY: number;
worldX: number;
sorted: boolean;
active: boolean;
constructor(data: BoneData, skeleton: Skeleton, parent: Bone);
@ -708,8 +708,8 @@ declare module spine {
static CURVE_LINEAR: number;
static CURVE_STEPPED: number;
static CURVE_BEZIER: number;
attachmentLoader: AttachmentLoader;
scale: number;
attachmentLoader: AttachmentLoader;
private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(binary: Uint8Array): SkeletonData;
@ -852,6 +852,7 @@ declare module spine {
private attachmentTime;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
getAttachment(): Attachment;
setAttachment(attachment: Attachment): void;
setAttachmentTime(time: number): void;

View File

@ -1346,12 +1346,12 @@ var spine;
var AnimationState = (function () {
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
this.propertyIDs = new spine.IntSet();
this.animationsChanged = false;
this.timeScale = 1;
this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); });
this.data = data;
}
@ -2097,24 +2097,24 @@ var spine;
EventType[EventType["complete"] = 4] = "complete";
EventType[EventType["event"] = 5] = "event";
})(EventType = spine.EventType || (spine.EventType = {}));
var AnimationStateAdapter2 = (function () {
function AnimationStateAdapter2() {
var AnimationStateAdapter = (function () {
function AnimationStateAdapter() {
}
AnimationStateAdapter2.prototype.start = function (entry) {
AnimationStateAdapter.prototype.start = function (entry) {
};
AnimationStateAdapter2.prototype.interrupt = function (entry) {
AnimationStateAdapter.prototype.interrupt = function (entry) {
};
AnimationStateAdapter2.prototype.end = function (entry) {
AnimationStateAdapter.prototype.end = function (entry) {
};
AnimationStateAdapter2.prototype.dispose = function (entry) {
AnimationStateAdapter.prototype.dispose = function (entry) {
};
AnimationStateAdapter2.prototype.complete = function (entry) {
AnimationStateAdapter.prototype.complete = function (entry) {
};
AnimationStateAdapter2.prototype.event = function (entry, event) {
AnimationStateAdapter.prototype.event = function (entry, event) {
};
return AnimationStateAdapter2;
return AnimationStateAdapter;
}());
spine.AnimationStateAdapter2 = AnimationStateAdapter2;
spine.AnimationStateAdapter = AnimationStateAdapter;
})(spine || (spine = {}));
var spine;
(function (spine) {
@ -2484,10 +2484,10 @@ var spine;
this.appliedValid = false;
this.a = 0;
this.b = 0;
this.worldX = 0;
this.c = 0;
this.d = 0;
this.worldY = 0;
this.worldX = 0;
this.sorted = false;
this.active = false;
if (data == null)
@ -6416,6 +6416,9 @@ var spine;
this.darkColor = data.darkColor == null ? null : new spine.Color();
this.setToSetupPose();
}
Slot.prototype.getSkeleton = function () {
return this.bone.skeleton;
};
Slot.prototype.getAttachment = function () {
return this.attachment;
};

File diff suppressed because one or more lines are too long

View File

@ -253,12 +253,12 @@ declare module spine {
static NOT_LAST: number;
data: AnimationStateData;
tracks: TrackEntry[];
timeScale: number;
events: Event[];
listeners: AnimationStateListener2[];
listeners: AnimationStateListener[];
queue: EventQueue;
propertyIDs: IntSet;
animationsChanged: boolean;
timeScale: number;
trackEntryPool: Pool<TrackEntry>;
constructor(data: AnimationStateData);
update(delta: number): void;
@ -284,8 +284,8 @@ declare module spine {
computeHold(entry: TrackEntry): void;
computeNotLast(entry: TrackEntry): void;
getCurrent(trackIndex: number): TrackEntry;
addListener(listener: AnimationStateListener2): void;
removeListener(listener: AnimationStateListener2): void;
addListener(listener: AnimationStateListener): void;
removeListener(listener: AnimationStateListener): void;
clearListeners(): void;
clearListenerNotifications(): void;
}
@ -294,7 +294,7 @@ declare module spine {
next: TrackEntry;
mixingFrom: TrackEntry;
mixingTo: TrackEntry;
listener: AnimationStateListener2;
listener: AnimationStateListener;
trackIndex: number;
loop: boolean;
holdPrevious: boolean;
@ -348,7 +348,7 @@ declare module spine {
complete = 4,
event = 5
}
interface AnimationStateListener2 {
interface AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -356,7 +356,7 @@ declare module spine {
complete(entry: TrackEntry): void;
event(entry: TrackEntry, event: Event): void;
}
abstract class AnimationStateAdapter2 implements AnimationStateListener2 {
abstract class AnimationStateAdapter implements AnimationStateListener {
start(entry: TrackEntry): void;
interrupt(entry: TrackEntry): void;
end(entry: TrackEntry): void;
@ -446,10 +446,10 @@ declare module spine {
appliedValid: boolean;
a: number;
b: number;
worldX: number;
c: number;
d: number;
worldY: number;
worldX: number;
sorted: boolean;
active: boolean;
constructor(data: BoneData, skeleton: Skeleton, parent: Bone);
@ -708,8 +708,8 @@ declare module spine {
static CURVE_LINEAR: number;
static CURVE_STEPPED: number;
static CURVE_BEZIER: number;
attachmentLoader: AttachmentLoader;
scale: number;
attachmentLoader: AttachmentLoader;
private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(binary: Uint8Array): SkeletonData;
@ -852,6 +852,7 @@ declare module spine {
private attachmentTime;
deform: number[];
constructor(data: SlotData, bone: Bone);
getSkeleton(): Skeleton;
getAttachment(): Attachment;
setAttachment(attachment: Attachment): void;
setAttachmentTime(time: number): void;

View File

@ -1346,12 +1346,12 @@ var spine;
var AnimationState = (function () {
function AnimationState(data) {
this.tracks = new Array();
this.timeScale = 1;
this.events = new Array();
this.listeners = new Array();
this.queue = new EventQueue(this);
this.propertyIDs = new spine.IntSet();
this.animationsChanged = false;
this.timeScale = 1;
this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); });
this.data = data;
}
@ -2097,24 +2097,24 @@ var spine;
EventType[EventType["complete"] = 4] = "complete";
EventType[EventType["event"] = 5] = "event";
})(EventType = spine.EventType || (spine.EventType = {}));
var AnimationStateAdapter2 = (function () {
function AnimationStateAdapter2() {
var AnimationStateAdapter = (function () {
function AnimationStateAdapter() {
}
AnimationStateAdapter2.prototype.start = function (entry) {
AnimationStateAdapter.prototype.start = function (entry) {
};
AnimationStateAdapter2.prototype.interrupt = function (entry) {
AnimationStateAdapter.prototype.interrupt = function (entry) {
};
AnimationStateAdapter2.prototype.end = function (entry) {
AnimationStateAdapter.prototype.end = function (entry) {
};
AnimationStateAdapter2.prototype.dispose = function (entry) {
AnimationStateAdapter.prototype.dispose = function (entry) {
};
AnimationStateAdapter2.prototype.complete = function (entry) {
AnimationStateAdapter.prototype.complete = function (entry) {
};
AnimationStateAdapter2.prototype.event = function (entry, event) {
AnimationStateAdapter.prototype.event = function (entry, event) {
};
return AnimationStateAdapter2;
return AnimationStateAdapter;
}());
spine.AnimationStateAdapter2 = AnimationStateAdapter2;
spine.AnimationStateAdapter = AnimationStateAdapter;
})(spine || (spine = {}));
var spine;
(function (spine) {
@ -2484,10 +2484,10 @@ var spine;
this.appliedValid = false;
this.a = 0;
this.b = 0;
this.worldX = 0;
this.c = 0;
this.d = 0;
this.worldY = 0;
this.worldX = 0;
this.sorted = false;
this.active = false;
if (data == null)
@ -6416,6 +6416,9 @@ var spine;
this.darkColor = data.darkColor == null ? null : new spine.Color();
this.setToSetupPose();
}
Slot.prototype.getSkeleton = function () {
return this.bone.skeleton;
};
Slot.prototype.getAttachment = function () {
return this.attachment;
};

File diff suppressed because one or more lines are too long

View File

@ -28,10 +28,15 @@
*****************************************************************************/
module spine {
/** A simple container for a list of timelines and a name. */
export class Animation {
/** The animation's name, which is unique across all animations in the skeleton. */
name: string;
timelines: Array<Timeline>;
timelineIds: Array<boolean>;
/** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */
duration: number;
constructor (name: string, timelines: Array<Timeline>, duration: number) {
@ -49,6 +54,11 @@ module spine {
return this.timelineIds[id] == true;
}
/** Applies all the animation's timelines to the specified skeleton.
*
* See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}.
* @param loop If true, the animation repeats after {@link #getDuration()}.
* @param events May be null to ignore fired events. */
apply (skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
if (skeleton == null) throw new Error("skeleton cannot be null.");
@ -62,6 +72,8 @@ module spine {
timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction);
}
/** @param target After the first and before the last value.
* @returns index of first value greater than the target. */
static binarySearch (values: ArrayLike<number>, target: number, step: number = 1) {
let low = 0;
let high = values.length / step - 2;
@ -84,18 +96,63 @@ module spine {
}
}
/** The interface for all timelines. */
export interface Timeline {
/** Applies this timeline to the skeleton.
* @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other
* skeleton components the timeline may change.
* @param lastTime The time this timeline was last applied. Timelines such as {@link EventTimeline}} trigger only at specific
* times rather than every frame. In that case, the timeline triggers everything between `lastTime`
* (exclusive) and `time` (inclusive).
* @param time The time within the animation. Most timelines find the key before and the key after this time so they can
* interpolate between the keys.
* @param events If any events are fired, they are added to this list. Can be null to ignore fired events or if the timeline
* does not fire events.
* @param alpha 0 applies the current or setup value (depending on `blend`). 1 applies the timeline value.
* Between 0 and 1 applies a value between the current or setup value and the timeline value. By adjusting
* `alpha` over time, an animation can be mixed in or out. `alpha` can also be useful to
* apply animations on top of each other (layering).
* @param blend Controls how mixing is applied when `alpha` < 1.
* @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions,
* such as {@link DrawOrderTimeline} or {@link AttachmentTimeline}. */
apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
/** Uniquely encodes both the type of this timeline and the skeleton property that it affects. */
getPropertyId (): number;
}
/** Controls how a timeline value is mixed with the setup pose value or current pose value when a timeline's `alpha`
* < 1.
*
* See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */
export enum MixBlend {
/** Transitions from the setup value to the timeline value (the current value is not used). Before the first key, the setup
* value is set. */
setup,
/** Transitions from the current value to the timeline value. Before the first key, transitions from the current value to
* the setup value. Timelines which perform instant transitions, such as {@link DrawOrderTimeline} or
* {@link AttachmentTimeline}, use the setup value before the first key.
*
* `first` is intended for the first animations applied, not for animations layered on top of those. */
first,
/** Transitions from the current value to the timeline value. No change is made before the first key (the current value is
* kept until the first key).
*
* `replace` is intended for animations layered on top of others, not for the first animations applied. */
replace,
/** Transitions from the current value to the current value plus the timeline value. No change is made before the first key
* (the current value is kept until the first key).
*
* `add` is intended for animations layered on top of others, not for the first animations applied. Properties
* keyed by additive animations must be set manually or by another animation before applying the additive animations, else
* the property values will increase continually. */
add
}
/** Indicates whether a timeline's `alpha` is mixing out over time toward 0 (the setup or current pose value) or
* mixing in toward 1 (the timeline's value).
*
* See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */
export enum MixDirection {
mixIn, mixOut
}
@ -109,6 +166,7 @@ module spine {
twoColor
}
/** The base class for timelines that use interpolation between key frame values. */
export abstract class CurveTimeline implements Timeline {
static LINEAR = 0; static STEPPED = 1; static BEZIER = 2;
static BEZIER_SIZE = 10 * 2 - 1;
@ -122,18 +180,23 @@ module spine {
this.curves = Utils.newFloatArray((frameCount - 1) * CurveTimeline.BEZIER_SIZE);
}
/** The number of key frames for this timeline. */
getFrameCount () {
return this.curves.length / CurveTimeline.BEZIER_SIZE + 1;
}
/** Sets the specified key frame to linear interpolation. */
setLinear (frameIndex: number) {
this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.LINEAR;
}
/** Sets the specified key frame to stepped interpolation. */
setStepped (frameIndex: number) {
this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.STEPPED;
}
/** Returns the interpolation type for the specified key frame.
* @returns Linear is 0, stepped is 1, Bezier is 2. */
getCurveType (frameIndex: number): number {
let index = frameIndex * CurveTimeline.BEZIER_SIZE;
if (index == this.curves.length) return CurveTimeline.LINEAR;
@ -143,9 +206,9 @@ module spine {
return CurveTimeline.BEZIER;
}
/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
* cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
* the difference between the keyframe's values. */
/** Sets the specified key frame to Bezier interpolation. `cx1` and `cx2` are from 0 to 1,
* representing the percent of time between the two key frames. `cy1` and `cy2` are the percent of the
* difference between the key frame's values. */
setCurve (frameIndex: number, cx1: number, cy1: number, cx2: number, cy2: number) {
let tmpx = (-cx1 * 2 + cx2) * 0.03, tmpy = (-cy1 * 2 + cy2) * 0.03;
let dddfx = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006;
@ -169,6 +232,7 @@ module spine {
}
}
/** Returns the interpolated percentage for the specified key frame and linear percentage. */
getCurvePercent (frameIndex: number, percent: number) {
percent = MathUtils.clamp(percent, 0, 1);
let curves = this.curves;
@ -199,12 +263,16 @@ module spine {
abstract apply (skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;
}
/** Changes a bone's local {@link Bone#rotation}. */
export class RotateTimeline extends CurveTimeline {
static ENTRIES = 2;
static PREV_TIME = -2; static PREV_ROTATION = -1;
static ROTATION = 1;
/** The index of the bone in {@link Skeleton#bones} that will be changed. */
boneIndex: number;
/** The time in seconds and rotation in degrees for each key frame. */
frames: ArrayLike<number>; // time, degrees, ...
constructor (frameCount: number) {
@ -278,12 +346,16 @@ module spine {
}
}
/** Changes a bone's local {@link Bone#x} and {@link Bone#y}. */
export class TranslateTimeline extends CurveTimeline {
static ENTRIES = 3;
static PREV_TIME = -3; static PREV_X = -2; static PREV_Y = -1;
static X = 1; static Y = 2;
/** The index of the bone in {@link Skeleton#bones} that will be changed. */
boneIndex: number;
/** The time in seconds, x, and y values for each key frame. */
frames: ArrayLike<number>; // time, x, y, ...
constructor (frameCount: number) {
@ -295,7 +367,7 @@ module spine {
return (TimelineType.translate << 24) + this.boneIndex;
}
/** Sets the time and value of the specified keyframe. */
/** Sets the time in seconds, x, and y values for the specified key frame. */
setFrame (frameIndex: number, time: number, x: number, y: number) {
frameIndex *= TranslateTimeline.ENTRIES;
this.frames[frameIndex] = time;
@ -354,6 +426,7 @@ module spine {
}
}
/** Changes a bone's local {@link Bone#scaleX)} and {@link Bone#scaleY}. */
export class ScaleTimeline extends TranslateTimeline {
constructor (frameCount: number) {
super(frameCount);
@ -454,6 +527,7 @@ module spine {
}
}
/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */
export class ShearTimeline extends TranslateTimeline {
constructor (frameCount: number) {
super(frameCount);
@ -514,12 +588,16 @@ module spine {
}
}
/** Changes a slot's {@link Slot#color}. */
export class ColorTimeline extends CurveTimeline {
static ENTRIES = 5;
static PREV_TIME = -5; static PREV_R = -4; static PREV_G = -3; static PREV_B = -2; static PREV_A = -1;
static R = 1; static G = 2; static B = 3; static A = 4;
/** The index of the slot in {@link Skeleton#slots} that will be changed. */
slotIndex: number;
/** The time in seconds, red, green, blue, and alpha values for each key frame. */
frames: ArrayLike<number>; // time, r, g, b, a, ...
constructor (frameCount: number) {
@ -531,7 +609,7 @@ module spine {
return (TimelineType.color << 24) + this.slotIndex;
}
/** Sets the time and value of the specified keyframe. */
/** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */
setFrame (frameIndex: number, time: number, r: number, g: number, b: number, a: number) {
frameIndex *= ColorTimeline.ENTRIES;
this.frames[frameIndex] = time;
@ -591,13 +669,18 @@ module spine {
}
}
/** Changes a slot's {@link Slot#color} and {@link Slot#darkColor} for two color tinting. */
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;
/** The index of the slot in {@link Skeleton#slots()} that will be changed. The {@link Slot#darkColor()} must not be
* null. */
slotIndex: number;
/** The time in seconds, red, green, blue, and alpha values of the color, red, green, blue of the dark color, for each key frame. */
frames: ArrayLike<number>; // time, r, g, b, a, r2, g2, b2, ...
constructor (frameCount: number) {
@ -609,7 +692,7 @@ module spine {
return (TimelineType.twoColor << 24) + this.slotIndex;
}
/** Sets the time and value of the specified keyframe. */
/** Sets the time in seconds, light, and dark colors for the specified key frame. */
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;
@ -688,9 +771,15 @@ module spine {
}
}
/** Changes a slot's {@link Slot#attachment}. */
export class AttachmentTimeline implements Timeline {
/** The index of the slot in {@link Skeleton#slots} that will be changed. */
slotIndex: number;
/** The time in seconds for each key frame. */
frames: ArrayLike<number> // time, ...
/** The attachment name for each key frame. May contain null values to clear the attachment. */
attachmentNames: Array<string>;
constructor (frameCount: number) {
@ -702,11 +791,12 @@ module spine {
return (TimelineType.attachment << 24) + this.slotIndex;
}
/** The number of key frames for this timeline. */
getFrameCount () {
return this.frames.length;
}
/** Sets the time and value of the specified keyframe. */
/** Sets the time in seconds and the attachment name for the specified key frame. */
setFrame (frameIndex: number, time: number, attachmentName: string) {
this.frames[frameIndex] = time;
this.attachmentNames[frameIndex] = attachmentName;
@ -744,10 +834,18 @@ module spine {
let zeros : ArrayLike<number> = null;
/** Changes a slot's {@link Slot#deform} to deform a {@link VertexAttachment}. */
export class DeformTimeline extends CurveTimeline {
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */
slotIndex: number;
/** The attachment that will be deformed. */
attachment: VertexAttachment;
/** The time in seconds for each key frame. */
frames: ArrayLike<number>; // time, ...
/** The vertices for each key frame. */
frameVertices: Array<ArrayLike<number>>;
constructor (frameCount: number) {
@ -761,7 +859,8 @@ module spine {
return (TimelineType.deform << 27) + + this.attachment.id + this.slotIndex;
}
/** Sets the time of the specified keyframe. */
/** Sets the time in seconds and the vertices for the specified key frame.
* @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */
setFrame (frameIndex: number, time: number, vertices: ArrayLike<number>) {
this.frames[frameIndex] = time;
this.frameVertices[frameIndex] = vertices;
@ -945,8 +1044,12 @@ module spine {
}
}
/** Fires an {@link Event} when specific animation times are reached. */
export class EventTimeline implements Timeline {
/** The time in seconds for each key frame. */
frames: ArrayLike<number>; // time, ...
/** The event for each key frame. */
events: Array<Event>;
constructor (frameCount: number) {
@ -958,17 +1061,18 @@ module spine {
return TimelineType.event << 24;
}
/** The number of key frames for this timeline. */
getFrameCount () {
return this.frames.length;
}
/** Sets the time of the specified keyframe. */
/** Sets the time in seconds and the event for the specified key frame. */
setFrame (frameIndex: number, event: Event) {
this.frames[frameIndex] = event.time;
this.events[frameIndex] = event;
}
/** Fires events for frames > lastTime and <= time. */
/** Fires events for frames > `lastTime` and <= `time`. */
apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection) {
if (firedEvents == null) return;
let frames = this.frames;
@ -997,8 +1101,12 @@ module spine {
}
}
/** Changes a skeleton's {@link Skeleton#drawOrder}. */
export class DrawOrderTimeline implements Timeline {
/** The time in seconds for each key frame. */
frames: ArrayLike<number>; // time, ...
/** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */
drawOrders: Array<Array<number>>;
constructor (frameCount: number) {
@ -1010,12 +1118,14 @@ module spine {
return TimelineType.drawOrder << 24;
}
/** The number of key frames for this timeline. */
getFrameCount () {
return this.frames.length;
}
/** Sets the time of the specified keyframe.
* @param drawOrder May be null to use bind pose draw order. */
/** Sets the time in seconds and the draw order for the specified key frame.
* @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose
* draw order. */
setFrame (frameIndex: number, time: number, drawOrder: Array<number>) {
this.frames[frameIndex] = time;
this.drawOrders[frameIndex] = drawOrder;
@ -1051,12 +1161,17 @@ module spine {
}
}
/** Changes an IK constraint's {@link IkConstraint#mix}, {@link IkConstraint#softness},
* {@link IkConstraint#bendDirection}, {@link IkConstraint#stretch}, and {@link IkConstraint#compress}. */
export class IkConstraintTimeline extends CurveTimeline {
static ENTRIES = 6;
static PREV_TIME = -6; static PREV_MIX = -5; static PREV_SOFTNESS = -4; static PREV_BEND_DIRECTION = -3; static PREV_COMPRESS = -2; static PREV_STRETCH = -1;
static MIX = 1; static SOFTNESS = 2; static BEND_DIRECTION = 3; static COMPRESS = 4; static STRETCH = 5;
/** The index of the IK constraint slot in {@link Skeleton#ikConstraints} that will be changed. */
ikConstraintIndex: number;
/** The time in seconds, mix, softness, bend direction, compress, and stretch for each key frame. */
frames: ArrayLike<number>; // time, mix, softness, bendDirection, compress, stretch, ...
constructor (frameCount: number) {
@ -1068,7 +1183,7 @@ module spine {
return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex;
}
/** Sets the time, mix, softness, and bend direction of the specified keyframe. */
/** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */
setFrame (frameIndex: number, time: number, mix: number, softness: number, bendDirection: number, compress: boolean, stretch: boolean) {
frameIndex *= IkConstraintTimeline.ENTRIES;
this.frames[frameIndex] = time;
@ -1161,12 +1276,17 @@ module spine {
}
}
/** Changes a transform constraint's {@link TransformConstraint#rotateMix}, {@link TransformConstraint#translateMix},
* {@link TransformConstraint#scaleMix}, and {@link TransformConstraint#shearMix}. */
export class TransformConstraintTimeline extends CurveTimeline {
static ENTRIES = 5;
static PREV_TIME = -5; static PREV_ROTATE = -4; static PREV_TRANSLATE = -3; static PREV_SCALE = -2; static PREV_SHEAR = -1;
static ROTATE = 1; static TRANSLATE = 2; static SCALE = 3; static SHEAR = 4;
/** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */
transformConstraintIndex: number;
/** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for each key frame. */
frames: ArrayLike<number>; // time, rotate mix, translate mix, scale mix, shear mix, ...
constructor (frameCount: number) {
@ -1178,7 +1298,7 @@ module spine {
return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex;
}
/** Sets the time and mixes of the specified keyframe. */
/** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */
setFrame (frameIndex: number, time: number, rotateMix: number, translateMix: number, scaleMix: number, shearMix: number) {
frameIndex *= TransformConstraintTimeline.ENTRIES;
this.frames[frameIndex] = time;
@ -1249,13 +1369,16 @@ module spine {
}
}
/** Changes a path constraint's {@link PathConstraint#position}. */
export class PathConstraintPositionTimeline extends CurveTimeline {
static ENTRIES = 2;
static PREV_TIME = -2; static PREV_VALUE = -1;
static VALUE = 1;
/** The index of the path constraint slot in {@link Skeleton#pathConstraints} that will be changed. */
pathConstraintIndex: number;
/** The time in seconds and path constraint position for each key frame. */
frames: ArrayLike<number>; // time, position, ...
constructor (frameCount: number) {
@ -1267,7 +1390,7 @@ module spine {
return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex;
}
/** Sets the time and value of the specified keyframe. */
/** Sets the time in seconds and path constraint position for the specified key frame. */
setFrame (frameIndex: number, time: number, value: number) {
frameIndex *= PathConstraintPositionTimeline.ENTRIES;
this.frames[frameIndex] = time;
@ -1309,6 +1432,7 @@ module spine {
}
}
/** Changes a path constraint's {@link PathConstraint#spacing}. */
export class PathConstraintSpacingTimeline extends PathConstraintPositionTimeline {
constructor (frameCount: number) {
super(frameCount);
@ -1354,13 +1478,17 @@ module spine {
}
}
/** Changes a transform constraint's {@link PathConstraint#rotateMix} and
* {@link TransformConstraint#translateMix}. */
export class PathConstraintMixTimeline extends CurveTimeline {
static ENTRIES = 3;
static PREV_TIME = -3; static PREV_ROTATE = -2; static PREV_TRANSLATE = -1;
static ROTATE = 1; static TRANSLATE = 2;
/** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */
pathConstraintIndex: number;
/** The time in seconds, rotate mix, and translate mix for each key frame. */
frames: ArrayLike<number>; // time, rotate mix, translate mix, ...
constructor (frameCount: number) {
@ -1372,7 +1500,7 @@ module spine {
return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex;
}
/** Sets the time and mixes of the specified keyframe. */
/** The time in seconds, rotate mix, and translate mix for the specified key frame. */
setFrame (frameIndex: number, time: number, rotateMix: number, translateMix: number) {
frameIndex *= PathConstraintMixTimeline.ENTRIES;
this.frames[frameIndex] = time;

View File

@ -28,22 +28,68 @@
*****************************************************************************/
module spine {
/** Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies
* multiple animations on top of each other (layering).
*
* See [Applying Animations](http://esotericsoftware.com/spine-applying-animations/) in the Spine Runtimes Guide. */
export class AnimationState {
static emptyAnimation = new Animation("<empty>", [], 0);
/** 1. A previously applied timeline has set this property.
*
* Result: Mix from the current pose to the timeline pose. */
static SUBSEQUENT = 0;
/** 1. This is the first timeline to set this property.
* 2. The next track entry applied after this one does not have a timeline to set this property.
*
* Result: Mix from the setup pose to the timeline pose. */
static FIRST = 1;
/** 1. This is the first timeline to set this property.
* 2. The next track entry to be applied does have a timeline to set this property.
* 3. The next track entry after that one does not have a timeline to set this property.
*
* Result: Mix from the setup pose to the timeline pose, but do not mix out. This avoids "dipping" when crossfading animations
* that key the same property. A subsequent timeline will set this property using a mix. */
static HOLD = 2;
/** 1. This is the first timeline to set this property.
* 2. The next track entry to be applied does have a timeline to set this property.
* 3. The next track entry after that one does have a timeline to set this property.
* 4. timelineHoldMix stores the first subsequent track entry that does not have a timeline to set this property.
*
* Result: The same as HOLD except the mix percentage from the timelineHoldMix track entry is used. This handles when more than
* 2 track entries in a row have a timeline that sets the same property.
*
* Eg, A -> B -> C -> D where A, B, and C have a timeline setting same property, but D does not. When A is applied, to avoid
* "dipping" A is not mixed out, however D (the first entry that doesn't set the property) mixing in is used to mix out A
* (which affects B and C). Without using D to mix out, A would be applied fully until mixing completes, then snap into
* place. */
static HOLD_MIX = 3;
/** 1. An attachment timeline in a subsequent track entry sets the attachment for the same slot as this attachment
* timeline.
*
* Result: This attachment timeline will not use MixDirection.out, which would otherwise show the setup mode attachment (or
* none if not visible in setup mode). This allows deform timelines to be applied for the subsequent entry to mix from, rather
* than mixing from the setup pose. */
static NOT_LAST = 4;
/** The AnimationStateData to look up mix durations. */
data: AnimationStateData;
/** The list of tracks that currently have animations, which may contain null entries. */
tracks = new Array<TrackEntry>();
/** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower
* or faster. Defaults to 1.
*
* See TrackEntry {@link TrackEntry#timeScale} for affecting a single animation. */
timeScale = 1;
events = new Array<Event>();
listeners = new Array<AnimationStateListener2>();
listeners = new Array<AnimationStateListener>();
queue = new EventQueue(this);
propertyIDs = new IntSet();
animationsChanged = false;
timeScale = 1;
trackEntryPool = new Pool<TrackEntry>(() => new TrackEntry());
@ -51,6 +97,7 @@ module spine {
this.data = data;
}
/** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */
update (delta: number) {
delta *= this.timeScale;
let tracks = this.tracks;
@ -108,6 +155,7 @@ module spine {
this.queue.drain();
}
/** Returns true when all mixing from entries are complete. */
updateMixingFrom (to: TrackEntry, delta: number): boolean {
let from = to.mixingFrom;
if (from == null) return true;
@ -134,6 +182,9 @@ module spine {
return false;
}
/** Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the
* animation state can be applied to multiple skeletons to pose them identically.
* @returns True if any animations were applied. */
apply (skeleton: Skeleton) : boolean {
if (skeleton == null) throw new Error("skeleton cannot be null.");
if (this.animationsChanged) this._animationsChanged();
@ -388,6 +439,10 @@ module spine {
}
}
/** Removes all animations from all tracks, leaving skeletons in their current pose.
*
* It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose,
* rather than leaving them in their current pose. */
clearTracks () {
let oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
@ -398,6 +453,10 @@ module spine {
this.queue.drain();
}
/** Removes all animations from the track, leaving skeletons in their current pose.
*
* It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose,
* rather than leaving them in their current pose. */
clearTrack (trackIndex: number) {
if (trackIndex >= this.tracks.length) return;
let current = this.tracks[trackIndex];
@ -442,12 +501,21 @@ module spine {
this.queue.start(current);
}
/** Sets an animation by name.
*
* {@link #setAnimationWith(}. */
setAnimation (trackIndex: number, animationName: string, loop: boolean) {
let animation = this.data.skeletonData.findAnimation(animationName);
if (animation == null) throw new Error("Animation not found: " + animationName);
return this.setAnimationWith(trackIndex, animation, loop);
}
/** Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never
* applied to a skeleton, it is replaced (not mixed from).
* @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
* duration. In either case {@link TrackEntry#trackEnd} determines when the track is cleared.
* @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept
* after the {@link AnimationStateListener#dispose()} event occurs. */
setAnimationWith (trackIndex: number, animation: Animation, loop: boolean) {
if (animation == null) throw new Error("animation cannot be null.");
let interrupt = true;
@ -470,12 +538,23 @@ module spine {
return entry;
}
/** Queues an animation by name.
*
* See {@link #addAnimationWith()}. */
addAnimation (trackIndex: number, animationName: string, loop: boolean, delay: number) {
let animation = this.data.skeletonData.findAnimation(animationName);
if (animation == null) throw new Error("Animation not found: " + animationName);
return this.addAnimationWith(trackIndex, animation, loop, delay);
}
/** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is
* equivalent to calling {@link #setAnimationWith()}.
* @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry
* minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix
* ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the
* previous entry is looping, its next loop completion is used instead of its duration.
* @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept
* after the {@link AnimationStateListener#dispose()} event occurs. */
addAnimationWith (trackIndex: number, animation: Animation, loop: boolean, delay: number) {
if (animation == null) throw new Error("animation cannot be null.");
@ -509,6 +588,20 @@ module spine {
return entry;
}
/** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's
* {@link TrackEntry#mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out.
*
* Mixing out is done by setting an empty animation with a mix duration using either {@link #setEmptyAnimation()},
* {@link #setEmptyAnimations()}, or {@link #addEmptyAnimation()}. Mixing to an empty animation causes
* the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation
* transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of
* 0 still mixes out over one frame.
*
* Mixing in is done by first setting an empty animation, then adding an animation using
* {@link #addAnimation()} and on the returned track entry, set the
* {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and
* more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the
* setup pose value if no lower tracks key the property to the value keyed in the new animation. */
setEmptyAnimation (trackIndex: number, mixDuration: number) {
let entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation, false);
entry.mixDuration = mixDuration;
@ -516,6 +609,17 @@ module spine {
return entry;
}
/** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
* {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling
* {@link #setEmptyAnimation()}.
*
* See {@link #setEmptyAnimation()}.
* @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry
* minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or
* before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next
* loop completion is used instead of its duration.
* @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
* after the {@link AnimationStateListener#dispose()} event occurs. */
addEmptyAnimation (trackIndex: number, mixDuration: number, delay: number) {
if (delay <= 0) delay -= mixDuration;
let entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation, false, delay);
@ -524,6 +628,8 @@ module spine {
return entry;
}
/** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix
* duration. */
setEmptyAnimations (mixDuration: number) {
let oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
@ -542,6 +648,7 @@ module spine {
return null;
}
/** @param last May be null. */
trackEntry (trackIndex: number, animation: Animation, loop: boolean, last: TrackEntry) {
let entry = this.trackEntryPool.obtain();
entry.trackIndex = trackIndex;
@ -663,42 +770,186 @@ module spine {
}
}
/** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */
getCurrent (trackIndex: number) {
if (trackIndex >= this.tracks.length) return null;
return this.tracks[trackIndex];
}
addListener (listener: AnimationStateListener2) {
/** Adds a listener to receive events for all track entries. */
addListener (listener: AnimationStateListener) {
if (listener == null) throw new Error("listener cannot be null.");
this.listeners.push(listener);
}
/** Removes the listener added with {@link #addListener(AnimationStateListener)}. */
removeListener (listener: AnimationStateListener2) {
/** Removes the listener added with {@link #addListener()}. */
removeListener (listener: AnimationStateListener) {
let index = this.listeners.indexOf(listener);
if (index >= 0) this.listeners.splice(index, 1);
}
/** Removes all listeners added with {@link #addListener()}. */
clearListeners () {
this.listeners.length = 0;
}
/** Discards all listener notifications that have not yet been delivered. This can be useful to call from an
* {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery
* are not wanted because new animations are being set. */
clearListenerNotifications () {
this.queue.clear();
}
}
/** Stores settings and other state for the playback of an animation on an {@link AnimationState} track.
*
* References to a track entry must not be kept after the {@link AnimationStateListener#dispose()} event occurs. */
export class TrackEntry {
/** The animation to apply for this track entry. */
animation: Animation;
next: TrackEntry; mixingFrom: TrackEntry; mixingTo: TrackEntry;
listener: AnimationStateListener2;
/** The animation queued to start after this animation, or null. `next` makes up a linked list. */
next: TrackEntry;
/** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no
* mixing is currently occuring. When mixing from multiple animations, `mixingFrom` makes up a linked list. */
mixingFrom: TrackEntry;
/** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is
* currently occuring. When mixing to multiple animations, `mixingTo` makes up a linked list. */
mixingTo: TrackEntry;
/** The listener for events generated by this track entry, or null.
*
* A track entry returned from {@link AnimationState#setAnimation()} is already the current animation
* for the track, so the track entry listener {@link AnimationStateListener#start()} will not be called. */
listener: AnimationStateListener;
/** The index of the track where this track entry is either current or queued.
*
* See {@link AnimationState#getCurrent()}. */
trackIndex: number;
/** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
* duration. */
loop: boolean;
/** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead
* of being mixed out.
*
* When mixing between animations that key the same property, if a lower track also keys that property then the value will
* briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0%
* while the second animation mixes from 0% to 100%. Setting `holdPrevious` to true applies the first animation
* at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which
* keys the property, only when a higher track also keys the property.
*
* Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the
* previous animation. */
holdPrevious: boolean;
eventThreshold: number; attachmentThreshold: number; drawOrderThreshold: number;
animationStart: number; animationEnd: number; animationLast: number; nextAnimationLast: number;
delay: number; trackTime: number; trackLast: number; nextTrackLast: number; trackEnd: number; timeScale: number;
alpha: number; mixTime: number; mixDuration: number; interruptAlpha: number; totalAlpha: number;
/** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the
* `eventThreshold`, event timelines are applied while this animation is being mixed out. Defaults to 0, so event
* timelines are not applied while this animation is being mixed out. */
eventThreshold: number;
/** When the mix percentage ({@link #mixtime} / {@link #mixDuration}) is less than the
* `attachmentThreshold`, attachment timelines are applied while this animation is being mixed out. Defaults to
* 0, so attachment timelines are not applied while this animation is being mixed out. */
attachmentThreshold: number;
/** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the
* `drawOrderThreshold`, draw order timelines are applied while this animation is being mixed out. Defaults to 0,
* so draw order timelines are not applied while this animation is being mixed out. */
drawOrderThreshold: number;
/** Seconds when this animation starts, both initially and after looping. Defaults to 0.
*
* When changing the `animationStart` time, it often makes sense to set {@link #animationLast} to the same
* value to prevent timeline keys before the start time from triggering. */
animationStart: number;
/** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will
* loop back to {@link #animationStart} at this time. Defaults to the animation {@link Animation#duration}. */
animationEnd: number;
/** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this
* animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) and
* `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation
* is applied. */
animationLast: number;
nextAnimationLast: number;
/** Seconds to postpone playing the animation. When this track entry is the current track entry, `delay`
* postpones incrementing the {@link #trackTime}. When this track entry is queued, `delay` is the time from
* the start of the previous animation to when this track entry will become the current track entry (ie when the previous
* track entry {@link TrackEntry#trackTime} >= this track entry's `delay`).
*
* {@link #timeScale} affects the delay. */
delay: number;
/** Current time in seconds this track entry has been the current track entry. The track time determines
* {@link #animationTime}. The track time can be set to start the animation at a time other than 0, without affecting
* looping. */
trackTime: number;
trackLast: number; nextTrackLast: number;
/** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float
* value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time
* is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the
* properties keyed by the animation are set to the setup pose and the track is cleared.
*
* It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation
* abruptly cease being applied. */
trackEnd: number;
/** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or
* faster. Defaults to 1.
*
* {@link #mixTime} is not affected by track entry time scale, so {@link #mixDuration} may need to be adjusted to
* match the animation speed.
*
* When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the
* {@link #delay} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If
* the time scale is not 1, the delay may need to be adjusted.
*
* See AnimationState {@link AnimationState#timeScale} for affecting all animations. */
timeScale: number;
/** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults
* to 1, which overwrites the skeleton's current pose with this animation.
*
* Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to
* use alpha on track 0 if the skeleton pose is from the last frame render. */
alpha: number;
/** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be
* slightly more than `mixDuration` when the mix is complete. */
mixTime: number;
/** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData
* {@link AnimationStateData#getMix()} based on the animation before this animation (if any).
*
* A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the
* properties it was animating.
*
* The `mixDuration` can be set manually rather than use the value from
* {@link AnimationStateData#getMix()}. In that case, the `mixDuration` can be set for a new
* track entry only before {@link AnimationState#update(float)} is first called.
*
* When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the
* {@link #delay} is set using the mix duration from the {@link AnimationStateData}, not a mix duration set
* afterward. */
mixDuration: number; interruptAlpha: number; totalAlpha: number;
/** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to {@link MixBlend#replace}, which
* replaces the values from the lower tracks with the animation values. {@link MixBlend#add} adds the animation values to
* the values from the lower tracks.
*
* The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is first
* called. */
mixBlend = MixBlend.replace;
timelineMode = new Array<number>();
timelineHoldMix = new Array<TrackEntry>();
@ -715,6 +966,9 @@ module spine {
this.timelinesRotation.length = 0;
}
/** Uses {@link #trackTime} to compute the `animationTime`, which is between {@link #animationStart}
* and {@link #animationEnd}. When the `trackTime` is 0, the `animationTime` is equal to the
* `animationStart` time. */
getAnimationTime () {
if (this.loop) {
let duration = this.animationEnd - this.animationStart;
@ -729,10 +983,20 @@ module spine {
this.nextAnimationLast = animationLast;
}
/** Returns true if at least one loop has been completed.
*
* See {@link AnimationStateListener#complete()}. */
isComplete () {
return this.trackTime >= this.animationEnd - this.animationStart;
}
/** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the
* long way around when using {@link #alpha} and starting animations on other tracks.
*
* Mixing with {@link MixBlend#replace} involves finding a rotation between two others, which has two possible solutions:
* the short way or the long way around. The two rotations likely change over time, so which direction is the short or long
* way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the
* long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */
resetRotationDirections () {
this.timelinesRotation.length = 0;
}
@ -839,7 +1103,12 @@ module spine {
start, interrupt, end, dispose, complete, event
}
export interface AnimationStateListener2 {
/** The interface to implement for receiving TrackEntry events. It is always safe to call AnimationState methods when receiving
* events.
*
* See TrackEntry {@link TrackEntry#listener} and AnimationState
* {@link AnimationState#addListener()}. */
export interface AnimationStateListener {
/** Invoked when this entry has been set as the current entry. */
start (entry: TrackEntry): void;
@ -861,7 +1130,7 @@ module spine {
event (entry: TrackEntry, event: Event): void;
}
export abstract class AnimationStateAdapter2 implements AnimationStateListener2 {
export abstract class AnimationStateAdapter implements AnimationStateListener {
start (entry: TrackEntry) {
}

View File

@ -28,9 +28,15 @@
*****************************************************************************/
module spine {
/** Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed. */
export class AnimationStateData {
/** The SkeletonData to look up animations when they are specified by name. */
skeletonData: SkeletonData;
animationToMixTime: Map<number> = { };
/** The mix duration to use when no mix duration has been defined between two animations. */
defaultMix = 0;
constructor (skeletonData: SkeletonData) {
@ -38,6 +44,9 @@ module spine {
this.skeletonData = skeletonData;
}
/** Sets a mix duration by animation name.
*
* See {@link #setMixWith()}. */
setMix (fromName: string, toName: string, duration: number) {
let from = this.skeletonData.findAnimation(fromName);
if (from == null) throw new Error("Animation not found: " + fromName);
@ -46,6 +55,9 @@ module spine {
this.setMixWith(from, to, duration);
}
/** Sets the mix duration when changing from the specified animation to the other.
*
* See {@link TrackEntry#mixDuration}. */
setMixWith (from: Animation, to: Animation, duration: number) {
if (from == null) throw new Error("from cannot be null.");
if (to == null) throw new Error("to cannot be null.");
@ -53,6 +65,8 @@ module spine {
this.animationToMixTime[key] = duration;
}
/** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if
* no mix duration has been set. */
getMix (from: Animation, to: Animation) {
let key = from.name + "." + to.name;
let value = this.animationToMixTime[key];

View File

@ -28,6 +28,10 @@
*****************************************************************************/
module spine {
/** An {@link AttachmentLoader} that configures attachments using texture regions from an {@link TextureAtlas}.
*
* See [Loading skeleton data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the
* Spine Runtimes Guide. */
export class AtlasAttachmentLoader implements AttachmentLoader {
atlas: TextureAtlas;
@ -35,7 +39,6 @@ module spine {
this.atlas = atlas;
}
/** @return May be null to not load an attachment. */
newRegionAttachment (skin: Skin, name: string, path: string): RegionAttachment {
let region = this.atlas.findRegion(path);
if (region == null) throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")");
@ -45,7 +48,6 @@ module spine {
return attachment;
}
/** @return May be null to not load an attachment. */
newMeshAttachment (skin: Skin, name: string, path: string) : MeshAttachment {
let region = this.atlas.findRegion(path);
if (region == null) throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
@ -55,12 +57,10 @@ module spine {
return attachment;
}
/** @return May be null to not load an attachment. */
newBoundingBoxAttachment (skin: Skin, name: string) : BoundingBoxAttachment {
return new BoundingBoxAttachment(name);
}
/** @return May be null to not load an attachment */
newPathAttachment (skin: Skin, name: string): PathAttachment {
return new PathAttachment(name);
}

View File

@ -28,6 +28,8 @@
*****************************************************************************/
module spine {
/** Determines how images are blended with existing pixels when drawn. */
export enum BlendMode {
Normal,
Additive,

View File

@ -28,17 +28,88 @@
*****************************************************************************/
module spine {
/** Stores a bone's current pose.
*
* A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a
* local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a
* constraint or application code modifies the world transform after it was computed from the local transform. */
export class Bone implements Updatable {
/** The bone's setup pose data. */
data: BoneData;
/** The skeleton this bone belongs to. */
skeleton: Skeleton;
/** The parent bone, or null if this is the root bone. */
parent: Bone;
/** The immediate children of this bone. */
children = new Array<Bone>();
x = 0; y = 0; rotation = 0; scaleX = 0; scaleY = 0; shearX = 0; shearY = 0;
ax = 0; ay = 0; arotation = 0; ascaleX = 0; ascaleY = 0; ashearX = 0; ashearY = 0;
/** The local x translation. */
x = 0;
/** The local y translation. */
y = 0;
/** The local rotation in degrees, counter clockwise. */
rotation = 0;
/** The local scaleX. */
scaleX = 0;
/** The local scaleY. */
scaleY = 0;
/** The local shearX. */
shearX = 0;
/** The local shearY. */
shearY = 0;
/** The applied local x translation. */
ax = 0;
/** The applied local y translation. */
ay = 0;
/** The applied local rotation in degrees, counter clockwise. */
arotation = 0;
/** The applied local scaleX. */
ascaleX = 0;
/** The applied local scaleY. */
ascaleY = 0;
/** The applied local shearX. */
ashearX = 0;
/** The applied local shearY. */
ashearY = 0;
/** If true, the applied transform matches the world transform. If false, the world transform has been modified since it was
* computed and {@link #updateAppliedTransform()} must be called before accessing the applied transform. */
appliedValid = false;
a = 0; b = 0; worldX = 0;
c = 0; d = 0; worldY = 0;
/** Part of the world transform matrix for the X axis. If changed, {@link #appliedValid} should be set to false. */
a = 0;
/** Part of the world transform matrix for the Y axis. If changed, {@link #appliedValid} should be set to false. */
b = 0;
/** Part of the world transform matrix for the X axis. If changed, {@link #appliedValid} should be set to false. */
c = 0;
/** Part of the world transform matrix for the Y axis. If changed, {@link #appliedValid} should be set to false. */
d = 0;
/** The world X position. If changed, {@link #appliedValid} should be set to false. */
worldY = 0;
/** The world Y position. If changed, {@link #appliedValid} should be set to false. */
worldX = 0;
sorted = false;
active = false;
@ -53,6 +124,8 @@ module spine {
this.setToSetupPose();
}
/** Returns false when the bone has not been computed because {@link BoneData#skinRequired} is true and the
* {@link Skeleton#skin active skin} does not {@link Skin#bones contain} this bone. */
isActive () {
return this.active;
}
@ -62,12 +135,17 @@ module spine {
this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);
}
/** Computes the world transform using the parent bone and this bone's local transform. */
/** Computes the world transform using the parent bone and this bone's local transform.
*
* See {@link #updateWorldTransformWith()}. */
updateWorldTransform () {
this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);
}
/** Computes the world transform using the parent bone and the specified local transform. */
/** Computes the world transform using the parent bone and the specified local transform. Child bones are not updated.
*
* See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
* Runtimes Guide. */
updateWorldTransformWith (x: number, y: number, rotation: number, scaleX: number, scaleY: number, shearX: number, shearY: number) {
this.ax = x;
this.ay = y;
@ -176,6 +254,7 @@ module spine {
this.d *= this.skeleton.scaleY;
}
/** Sets this bone's local transform to the setup pose. */
setToSetupPose () {
let data = this.data;
this.x = data.x;
@ -187,26 +266,34 @@ module spine {
this.shearY = data.shearY;
}
/** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */
getWorldRotationX () {
return Math.atan2(this.c, this.a) * MathUtils.radDeg;
}
/** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */
getWorldRotationY () {
return Math.atan2(this.d, this.b) * MathUtils.radDeg;
}
/** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */
getWorldScaleX () {
return Math.sqrt(this.a * this.a + this.c * this.c);
}
/** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */
getWorldScaleY () {
return Math.sqrt(this.b * this.b + this.d * this.d);
}
/** 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>
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
/** Computes the applied transform values from the world transform. This allows the applied transform to be accessed after the
* world transform has been modified (by a constraint, {@link #rotateWorld()}, etc).
*
* If {@link #updateWorldTransform()} has been called for a bone and {@link #appliedValid} is false, then
* {@link #updateAppliedTransform()} must be called before accessing the applied transform.
*
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after
* calling this method is equivalent to the local tranform used to compute the world transform, but may not be identical. */
updateAppliedTransform () {
this.appliedValid = true;
let parent = this.parent;
@ -248,6 +335,7 @@ module spine {
}
}
/** Transforms a point from world coordinates to the bone's local coordinates. */
worldToLocal (world: Vector2) {
let a = this.a, b = this.b, c = this.c, d = this.d;
let invDet = 1 / (a * d - b * c);
@ -257,6 +345,7 @@ module spine {
return world;
}
/** Transforms a point from the bone's local coordinates to world coordinates. */
localToWorld (local: Vector2) {
let x = local.x, y = local.y;
local.x = x * this.a + y * this.b + this.worldX;
@ -264,17 +353,21 @@ module spine {
return local;
}
/** Transforms a world rotation to a local rotation. */
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 + this.rotation - this.shearX;
}
/** Transforms a local rotation to a world rotation. */
localToWorldRotation (localRotation: number) {
localRotation -= this.rotation - this.shearX;
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;
}
/** Rotates the world transform the specified amount and sets {@link #appliedValid} to false.
* {@link #updateWorldTransform()} will need to be called on any child bones, recursively, and any constraints reapplied. */
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);

View File

@ -28,15 +28,52 @@
*****************************************************************************/
module spine {
/** Stores the setup pose for a {@link Bone}. */
export class BoneData {
/** The index of the bone in {@link Skeleton#getBones()}. */
index: number;
/** The name of the bone, which is unique across all bones in the skeleton. */
name: string;
/** @returns May be null. */
parent: BoneData;
/** The bone's length. */
length: number;
x = 0; y = 0; rotation = 0; scaleX = 1; scaleY = 1; shearX = 0; shearY = 0;
/** The local x translation. */
x = 0;
/** The local y translation. */
y = 0;
/** The local rotation. */
rotation = 0;
/** The local scaleX. */
scaleX = 1;
/** The local scaleY. */
scaleY = 1;
/** The local shearX. */
shearX = 0;
/** The local shearX. */
shearY = 0;
/** The transform mode for how parent world transforms affect this bone. */
transformMode = TransformMode.Normal;
/** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#skin} contains this
* bone.
* @see Skin#bones */
skinRequired = false;
/** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually
* rendered at runtime. */
color = new Color();
constructor (index: number, name: string, parent: BoneData) {
@ -48,6 +85,7 @@ module spine {
}
}
/** Determines how a bone inherits world transforms from parent bones. */
export enum TransformMode {
Normal, OnlyTranslation, NoRotationOrReflection, NoScale, NoScaleOrReflection
}

View File

@ -28,6 +28,7 @@
*****************************************************************************/
module spine {
/** The base class for all constraint datas. */
export abstract class ConstraintData {
constructor(public name: string, public order: number, public skinRequired: boolean) { }
}

View File

@ -28,6 +28,12 @@
*****************************************************************************/
module spine {
/** Stores the current pose values for an {@link Event}.
*
* See Timeline {@link Timeline#apply()},
* AnimationStateListener {@link AnimationStateListener#event()}, and
* [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */
export class Event {
data: EventData;
intValue: number;

View File

@ -28,6 +28,9 @@
*****************************************************************************/
module spine {
/** Stores the setup pose values for an {@link Event}.
*
* See [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */
export class EventData {
name: string;
intValue: number;

View File

@ -28,14 +28,35 @@
*****************************************************************************/
module spine {
/** Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of
* the last bone is as close to the target bone as possible.
*
* See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide. */
export class IkConstraint implements Updatable {
/** The IK constraint's setup pose data. */
data: IkConstraintData;
/** The bones that will be modified by this IK constraint. */
bones: Array<Bone>;
/** The bone that is the IK target. */
target: Bone;
/** Controls the bend direction of the IK bones, either 1 or -1. */
bendDirection = 0;
/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */
compress = false;
/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained
* and the parent bone has local nonuniform scale, stretch is not applied. */
stretch = false;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
mix = 1;
/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */
softness = 0;
active = false;
@ -59,6 +80,7 @@ module spine {
return this.active;
}
/** Applies the constraint to the constrained bones. */
apply () {
this.update();
}
@ -76,8 +98,7 @@ module spine {
}
}
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
* coordinate system. */
/** Applies 1 bone IK. The target is specified in the world coordinate system. */
apply1 (bone: Bone, targetX: number, targetY: number, compress: boolean, stretch: boolean, uniform: boolean, alpha: number) {
if (!bone.appliedValid) bone.updateAppliedTransform();
let p = bone.parent;
@ -102,8 +123,7 @@ module spine {
bone.ashearY);
}
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
* target is specified in the world coordinate system.
/** Applies 2 bone IK. The target is specified in the world coordinate system.
* @param child A direct descendant of the parent bone. */
apply2 (parent: Bone, child: Bone, targetX: number, targetY: number, bendDir: number, stretch: boolean, softness: number, alpha: number) {
if (alpha == 0) {

View File

@ -28,14 +28,35 @@
*****************************************************************************/
module spine {
/** Stores the setup pose for an {@link IkConstraint}.
* <p>
* See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide. */
export class IkConstraintData extends ConstraintData {
/** The bones that are constrained by this IK constraint. */
bones = new Array<BoneData>();
/** The bone that is the IK target. */
target: BoneData;
/** Controls the bend direction of the IK bones, either 1 or -1. */
bendDirection = 1;
/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */
compress = false;
/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained
* and the parent bone has local nonuniform scale, stretch is not applied. */
stretch = false;
/** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone
* is scaled on both the X and Y axes. */
uniform = false;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
mix = 1;
/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */
softness = 0;
constructor (name: string) {

View File

@ -28,14 +28,35 @@
*****************************************************************************/
module spine {
/** Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the
* constrained bones so they follow a {@link PathAttachment}.
*
* See [Path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide. */
export class PathConstraint implements Updatable {
static NONE = -1; static BEFORE = -2; static AFTER = -3;
static epsilon = 0.00001;
/** The path constraint's setup pose data. */
data: PathConstraintData;
/** The bones that will be modified by this path constraint. */
bones: Array<Bone>;
/** The slot whose path attachment will be used to constrained the bones. */
target: Slot;
position = 0; spacing = 0; rotateMix = 0; translateMix = 0;
/** The position along the path. */
position = 0;
/** The spacing between bones. */
spacing = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
rotateMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
translateMix = 0;
spaces = new Array<number>(); positions = new Array<number>();
world = new Array<number>(); curves = new Array<number>(); lengths = new Array<number>();
@ -61,6 +82,7 @@ module spine {
return this.active;
}
/** Applies the constraint to the constrained bones. */
apply () {
this.update();
}

View File

@ -28,28 +28,64 @@
*****************************************************************************/
module spine {
/** Stores the setup pose for a {@link PathConstraint}.
*
* See [Path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide. */
export class PathConstraintData extends ConstraintData {
/** The bones that will be modified by this path constraint. */
bones = new Array<BoneData>();
/** The slot whose path attachment will be used to constrained the bones. */
target: SlotData;
/** The mode for positioning the first bone on the path. */
positionMode: PositionMode;
/** The mode for positioning the bones after the first bone on the path. */
spacingMode: SpacingMode;
/** The mode for adjusting the rotation of the bones. */
rotateMode: RotateMode;
/** An offset added to the constrained bone rotation. */
offsetRotation: number;
position: number; spacing: number; rotateMix: number; translateMix: number;
/** The position along the path. */
position: number;
/** The spacing between bones. */
spacing: number;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
rotateMix: number;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
translateMix: number;
constructor (name: string) {
super(name, 0, false);
}
}
/** Controls how the first bone is positioned along the path.
*
* See [Position mode](http://esotericsoftware.com/spine-path-constraints#Position-mode) in the Spine User Guide. */
export enum PositionMode {
Fixed, Percent
}
/** Controls how bones after the first bone are positioned along the path.
*
* [Spacing mode](http://esotericsoftware.com/spine-path-constraints#Spacing-mode) in the Spine User Guide. */
export enum SpacingMode {
Length, Fixed, Percent
}
/** Controls how bones are rotated, translated, and scaled to match the path.
*
* [Rotate mode](http://esotericsoftware.com/spine-path-constraints#Rotate-mod) in the Spine User Guide. */
export enum RotateMode {
Tangent, Chain, ChainScale
}

View File

@ -28,21 +28,60 @@
*****************************************************************************/
module spine {
/** Stores the current pose for a skeleton.
*
* See [Instance objects](http://esotericsoftware.com/spine-runtime-architecture#Instance-objects) in the Spine Runtimes Guide. */
export class Skeleton {
/** The skeleton's setup pose data. */
data: SkeletonData;
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
bones: Array<Bone>;
/** The skeleton's slots. */
slots: Array<Slot>;
/** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */
drawOrder: Array<Slot>;
/** The skeleton's IK constraints. */
ikConstraints: Array<IkConstraint>;
/** The skeleton's transform constraints. */
transformConstraints: Array<TransformConstraint>;
/** The skeleton's path constraints. */
pathConstraints: Array<PathConstraint>;
/** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */
_updateCache = new Array<Updatable>();
updateCacheReset = new Array<Updatable>();
/** The skeleton's current skin. May be null. */
skin: Skin;
/** The color to tint all the skeleton's attachments. */
color: Color;
/** Returns the skeleton's time. This can be used for tracking, such as with Slot {@link Slot#attachmentTime}.
* <p>
* See {@link #update()}. */
time = 0;
scaleX = 1; scaleY = 1;
x = 0; y = 0;
/** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale
* inheritance. */
scaleX = 1;
/** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale
* inheritance. */
scaleY = 1;
/** Sets the skeleton X position, which is added to the root bone worldX position. */
x = 0;
/** Sets the skeleton Y position, which is added to the root bone worldY position. */
y = 0;
constructor (data: SkeletonData) {
if (data == null) throw new Error("data cannot be null.");
@ -94,6 +133,8 @@ module spine {
this.updateCache();
}
/** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones,
* constraints, or weighted path attachments are added or removed. */
updateCache () {
let updateCache = this._updateCache;
updateCache.length = 0;
@ -276,7 +317,10 @@ module spine {
}
}
/** Updates the world transform for each bone and applies constraints. */
/** Updates the world transform for each bone and applies all constraints.
*
* See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
* Runtimes Guide. */
updateWorldTransform () {
let updateCacheReset = this.updateCacheReset;
for (let i = 0, n = updateCacheReset.length; i < n; i++) {
@ -338,6 +382,7 @@ module spine {
}
}
/** Sets the slots and draw order to their setup pose values. */
setSlotsToSetupPose () {
let slots = this.slots;
Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length);
@ -345,13 +390,13 @@ module spine {
slots[i].setToSetupPose();
}
/** @return May return null. */
/** @returns May return null. */
getRootBone () {
if (this.bones.length == 0) return null;
return this.bones[0];
}
/** @return May be null. */
/** @returns May be null. */
findBone (boneName: string) {
if (boneName == null) throw new Error("boneName cannot be null.");
let bones = this.bones;
@ -362,7 +407,7 @@ module spine {
return null;
}
/** @return -1 if the bone was not found. */
/** @returns -1 if the bone was not found. */
findBoneIndex (boneName: string) {
if (boneName == null) throw new Error("boneName cannot be null.");
let bones = this.bones;
@ -371,7 +416,9 @@ module spine {
return -1;
}
/** @return May be null. */
/** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it
* repeatedly.
* @returns May be null. */
findSlot (slotName: string) {
if (slotName == null) throw new Error("slotName cannot be null.");
let slots = this.slots;
@ -382,7 +429,7 @@ module spine {
return null;
}
/** @return -1 if the bone was not found. */
/** @returns -1 if the bone was not found. */
findSlotIndex (slotName: string) {
if (slotName == null) throw new Error("slotName cannot be null.");
let slots = this.slots;
@ -392,16 +439,23 @@ module spine {
}
/** Sets a skin by name.
* @see #setSkin(Skin) */
*
* See {@link #setSkin()}. */
setSkinByName (skinName: string) {
let skin = this.data.findSkin(skinName);
if (skin == null) throw new Error("Skin not found: " + skinName);
this.setSkin(skin);
}
/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}.
/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the
* skin is changed, {@link #updateCache()} is called.
*
* Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no
* old skin, each slot's setup mode attachment is attached from the new skin.
*
* After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
* {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the
* skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.
* @param newSkin May be null. */
setSkin (newSkin: Skin) {
if (newSkin == this.skin) return;
@ -424,12 +478,21 @@ module spine {
this.updateCache();
}
/** @return May be null. */
/** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment
* name.
*
* See {@link #getAttachment()}.
* @returns May be null. */
getAttachmentByName (slotName: string, attachmentName: string): Attachment {
return this.getAttachment(this.data.findSlotIndex(slotName), attachmentName);
}
/** @return May be null. */
/** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and
* attachment name. First the skin is checked and if the attachment was not found, the default skin is checked.
*
* See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide.
* @returns May be null. */
getAttachment (slotIndex: number, attachmentName: string): Attachment {
if (attachmentName == null) throw new Error("attachmentName cannot be null.");
if (this.skin != null) {
@ -440,7 +503,9 @@ module spine {
return null;
}
/** @param attachmentName May be null. */
/** A convenience method to set an attachment by finding the slot with {@link #findSlot()}, finding the attachment with
* {@link #getAttachment()}, then setting the slot's {@link Slot#attachment}.
* @param attachmentName May be null to clear the slot's attachment. */
setAttachment (slotName: string, attachmentName: string) {
if (slotName == null) throw new Error("slotName cannot be null.");
let slots = this.slots;
@ -460,7 +525,10 @@ module spine {
throw new Error("Slot not found: " + slotName);
}
/** @return May be null. */
/** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method
* than to call it repeatedly.
* @return May be null. */
findIkConstraint (constraintName: string) {
if (constraintName == null) throw new Error("constraintName cannot be null.");
let ikConstraints = this.ikConstraints;
@ -471,7 +539,9 @@ module spine {
return null;
}
/** @return May be null. */
/** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of
* this method than to call it repeatedly.
* @return May be null. */
findTransformConstraint (constraintName: string) {
if (constraintName == null) throw new Error("constraintName cannot be null.");
let transformConstraints = this.transformConstraints;
@ -482,7 +552,9 @@ module spine {
return null;
}
/** @return May be null. */
/** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method
* than to call it repeatedly.
* @return May be null. */
findPathConstraint (constraintName: string) {
if (constraintName == null) throw new Error("constraintName cannot be null.");
let pathConstraints = this.pathConstraints;
@ -494,9 +566,9 @@ 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.
* @param temp Working memory */
* @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB.
* @param size An output value, the width and height of the AABB.
* @param temp Working memory to temporarily store attachments' computed world vertices. */
getBounds (offset: Vector2, size: Vector2, temp: Array<number> = new Array<number>(2)) {
if (offset == null) throw new Error("offset cannot be null.");
if (size == null) throw new Error("size cannot be null.");
@ -532,6 +604,7 @@ module spine {
size.set(maxX - minX, maxY - minY);
}
/** Increments the skeleton's {@link #time}. */
update (delta: number) {
this.time += delta;
}

View File

@ -28,6 +28,11 @@
*****************************************************************************/
module spine {
/** Loads skeleton data in the Spine binary format.
*
* See [Spine binary format](http://esotericsoftware.com/spine-binary-format) and
* [JSON and binary data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the Spine
* Runtimes Guide. */
export class SkeletonBinary {
static AttachmentTypeValues = [ 0 /*AttachmentType.Region*/, 1/*AttachmentType.BoundingBox*/, 2/*AttachmentType.Mesh*/, 3/*AttachmentType.LinkedMesh*/, 4/*AttachmentType.Path*/, 5/*AttachmentType.Point*/, 6/*AttachmentType.Clipping*/ ];
static TransformModeValues = [TransformMode.Normal, TransformMode.OnlyTranslation, TransformMode.NoRotationOrReflection, TransformMode.NoScale, TransformMode.NoScaleOrReflection];
@ -53,8 +58,13 @@ module spine {
static CURVE_STEPPED = 1;
static CURVE_BEZIER = 2;
attachmentLoader: AttachmentLoader;
/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at
* runtime than were used in Spine.
*
* See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */
scale = 1;
attachmentLoader: AttachmentLoader;
private linkedMeshes = new Array<LinkedMesh>();
constructor (attachmentLoader: AttachmentLoader) {

View File

@ -28,14 +28,36 @@
*****************************************************************************/
module spine {
/** Collects each visible {@link BoundingBoxAttachment} and computes the world vertices for its polygon. The polygon vertices are
* provided along with convenience methods for doing hit detection. */
export class SkeletonBounds {
minX = 0; minY = 0; maxX = 0; maxY = 0;
/** The left edge of the axis aligned bounding box. */
minX = 0;
/** The bottom edge of the axis aligned bounding box. */
minY = 0;
/** The right edge of the axis aligned bounding box. */
maxX = 0;
/** The top edge of the axis aligned bounding box. */
maxY = 0;
/** The visible bounding boxes. */
boundingBoxes = new Array<BoundingBoxAttachment>();
/** The world vertices for the bounding box polygons. */
polygons = new Array<ArrayLike<number>>();
private polygonPool = new Pool<ArrayLike<number>>(() => {
return Utils.newFloatArray(16);
});
/** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding
* box's polygon.
* @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the
* SkeletonBounds AABB methods will always return true. */
update (skeleton: Skeleton, updateAabb: boolean) {
if (skeleton == null) throw new Error("skeleton cannot be null.");
let boundingBoxes = this.boundingBoxes;
@ -155,7 +177,7 @@ module spine {
}
/** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it
* is usually more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns
* is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns
* true. */
intersectsSegment (x1: number, y1: number, x2: number, y2: number) {
let polygons = this.polygons;
@ -195,10 +217,12 @@ module spine {
return index == -1 ? null : this.polygons[index];
}
/** The width of the axis aligned bounding box. */
getWidth () {
return this.maxX - this.minX;
}
/** The height of the axis aligned bounding box. */
getHeight () {
return this.maxY - this.minY;
}

View File

@ -28,25 +28,74 @@
*****************************************************************************/
module spine {
/** Stores the setup pose and all of the stateless data for a skeleton.
*
* See [Data objects](http://esotericsoftware.com/spine-runtime-architecture#Data-objects) in the Spine Runtimes
* Guide. */
export class SkeletonData {
/** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */
name: string;
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
bones = new Array<BoneData>(); // Ordered parents first.
/** The skeleton's slots. */
slots = new Array<SlotData>(); // Setup pose draw order.
skins = new Array<Skin>();
/** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine.
*
* See {@link Skeleton#getAttachmentByName()}.
* May be null. */
defaultSkin: Skin;
/** The skeleton's events. */
events = new Array<EventData>();
/** The skeleton's animations. */
animations = new Array<Animation>();
/** The skeleton's IK constraints. */
ikConstraints = new Array<IkConstraintData>();
/** The skeleton's transform constraints. */
transformConstraints = new Array<TransformConstraintData>();
/** The skeleton's path constraints. */
pathConstraints = new Array<PathConstraintData>();
x: number; y: number; width: number; height: number;
version: string; hash: string;
/** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */
x: number;
/** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */
y: number;
/** The width of the skeleton's axis aligned bounding box in the setup pose. */
width: number;
/** The height of the skeleton's axis aligned bounding box in the setup pose. */
height: number;
/** The Spine version used to export the skeleton data, or null. */
version: string;
/** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */
hash: string;
// Nonessential
/** The dopesheet FPS in Spine. Available only when nonessential data was exported. */
fps = 0;
/** The path to the images directory as defined in Spine. Available only when nonessential data was exported. May be null. */
imagesPath: string;
/** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */
audioPath: string;
/** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @returns May be null. */
findBone (boneName: string) {
if (boneName == null) throw new Error("boneName cannot be null.");
let bones = this.bones;
@ -65,6 +114,9 @@ module spine {
return -1;
}
/** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @returns May be null. */
findSlot (slotName: string) {
if (slotName == null) throw new Error("slotName cannot be null.");
let slots = this.slots;
@ -83,6 +135,9 @@ module spine {
return -1;
}
/** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @returns May be null. */
findSkin (skinName: string) {
if (skinName == null) throw new Error("skinName cannot be null.");
let skins = this.skins;
@ -93,6 +148,9 @@ module spine {
return null;
}
/** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @returns May be null. */
findEvent (eventDataName: string) {
if (eventDataName == null) throw new Error("eventDataName cannot be null.");
let events = this.events;
@ -103,6 +161,9 @@ module spine {
return null;
}
/** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to
* call it multiple times.
* @returns May be null. */
findAnimation (animationName: string) {
if (animationName == null) throw new Error("animationName cannot be null.");
let animations = this.animations;
@ -113,6 +174,9 @@ module spine {
return null;
}
/** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method
* than to call it multiple times.
* @return May be null. */
findIkConstraint (constraintName: string) {
if (constraintName == null) throw new Error("constraintName cannot be null.");
let ikConstraints = this.ikConstraints;
@ -123,6 +187,9 @@ module spine {
return null;
}
/** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of
* this method than to call it multiple times.
* @return May be null. */
findTransformConstraint (constraintName: string) {
if (constraintName == null) throw new Error("constraintName cannot be null.");
let transformConstraints = this.transformConstraints;
@ -133,6 +200,9 @@ module spine {
return null;
}
/** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method
* than to call it multiple times.
* @return May be null. */
findPathConstraint (constraintName: string) {
if (constraintName == null) throw new Error("constraintName cannot be null.");
let pathConstraints = this.pathConstraints;

View File

@ -28,8 +28,19 @@
*****************************************************************************/
module spine {
/** Loads skeleton data in the Spine JSON format.
*
* See [Spine JSON format](http://esotericsoftware.com/spine-json-format) and
* [JSON and binary data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the Spine
* Runtimes Guide. */
export class SkeletonJson {
attachmentLoader: AttachmentLoader;
/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at
* runtime than were used in Spine.
*
* See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */
scale = 1;
private linkedMeshes = new Array<LinkedMesh>();

View File

@ -28,12 +28,19 @@
*****************************************************************************/
module spine {
/** Stores an entry in the skin consisting of the slot index, name, and attachment **/
export class SkinEntry {
constructor(public slotIndex: number, public name: string, public attachment: Attachment) { }
}
/** Stores attachments by slot index and attachment name.
*
* See SkeletonData {@link SkeletonData#defaultSkin}, Skeleton {@link Skeleton#skin}, and
* [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. */
export class Skin {
/** The skin's name, which is unique across all skins in the skeleton. */
name: string;
attachments = new Array<Map<Attachment>>();
bones = Array<BoneData>();
constraints = new Array<ConstraintData>();
@ -43,6 +50,7 @@ module spine {
this.name = name;
}
/** Adds an attachment to the skin for the specified slot index and name. */
setAttachment (slotIndex: number, name: string, attachment: Attachment) {
if (attachment == null) throw new Error("attachment cannot be null.");
let attachments = this.attachments;
@ -51,6 +59,7 @@ module spine {
attachments[slotIndex][name] = attachment;
}
/** Adds all attachments, bones, and constraints from the specified skin to this skin. */
addSkin (skin: Skin) {
for(let i = 0; i < skin.bones.length; i++) {
let bone = skin.bones[i];
@ -83,6 +92,8 @@ module spine {
}
}
/** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not
* copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */
copySkin (skin: Skin) {
for(let i = 0; i < skin.bones.length; i++) {
let bone = skin.bones[i];
@ -122,17 +133,19 @@ module spine {
}
}
/** @return May be null. */
/** Returns the attachment for the specified slot index and name, or null. */
getAttachment (slotIndex: number, name: string): Attachment {
let dictionary = this.attachments[slotIndex];
return dictionary ? dictionary[name] : null;
}
/** Removes the attachment in the skin for the specified slot index and name, if any. */
removeAttachment (slotIndex: number, name: string) {
let dictionary = this.attachments[slotIndex];
if (dictionary) dictionary[name] = null;
}
/** Returns all attachments in this skin. */
getAttachments (): Array<SkinEntry> {
let entries = new Array<SkinEntry>();
for (var i = 0; i < this.attachments.length; i++) {
@ -147,6 +160,7 @@ module spine {
return entries;
}
/** Returns all attachments in this skin for the specified slot index. */
getAttachmentsForSlot (slotIndex: number, attachments: Array<SkinEntry>) {
let slotAttachments = this.attachments[slotIndex];
if (slotAttachments) {
@ -157,6 +171,7 @@ module spine {
}
}
/** Clears all attachments, bones, and constraints. */
clear () {
this.attachments.length = 0;
this.bones.length = 0;

View File

@ -28,13 +28,33 @@
*****************************************************************************/
module spine {
/** Stores a slot's current pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store
* state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared
* across multiple skeletons. */
export class Slot {
/** The slot's setup pose data. */
data: SlotData;
/** The bone this slot belongs to. */
bone: Bone;
/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two
* color tinting. */
color: Color;
/** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark
* color's alpha is not used. */
darkColor: Color;
private attachment: Attachment;
private attachmentTime: number;
/** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a
* weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions.
*
* See {@link VertexAttachment#computeWorldVertices()} and {@link DeformTimeline}. */
deform = new Array<number>();
constructor (data: SlotData, bone: Bone) {
@ -47,12 +67,17 @@ module spine {
this.setToSetupPose();
}
/** @return May be null. */
/** The skeleton this slot belongs to. */
getSkeleton (): Skeleton {
return this.bone.skeleton;
}
/** The current attachment for the slot, or null if the slot has no attachment. */
getAttachment (): Attachment {
return this.attachment;
}
/** Sets the attachment and if it changed, resets {@link #getAttachmentTime()} and clears {@link #getAttachmentVertices()}.
/** Sets the slot's attachment and, if the attachment changed, resets {@link #attachmentTime} and clears {@link #deform}.
* @param attachment May be null. */
setAttachment (attachment: Attachment) {
if (this.attachment == attachment) return;
@ -65,11 +90,13 @@ module spine {
this.attachmentTime = this.bone.skeleton.time - time;
}
/** Returns the time since the attachment was set. */
/** The time that has elapsed since the last time the attachment was set or cleared. Relies on Skeleton
* {@link Skeleton#time}. */
getAttachmentTime (): number {
return this.bone.skeleton.time - this.attachmentTime;
}
/** Sets this slot to the setup pose. */
setToSetupPose () {
this.color.setFromColor(this.data.color);
if (this.darkColor != null) this.darkColor.setFromColor(this.data.darkColor);

View File

@ -28,13 +28,31 @@
*****************************************************************************/
module spine {
/** Stores the setup pose for a {@link Slot}. */
export class SlotData {
/** The index of the slot in {@link Skeleton#getSlots()}. */
index: number;
/** The name of the slot, which is unique across all slots in the skeleton. */
name: string;
/** The bone this slot belongs to. */
boneData: BoneData;
/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two
* color tinting. */
color = new Color(1, 1, 1, 1);
/** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark
* color's alpha is not used. */
darkColor: Color;
/** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */
attachmentName: string;
/** The blend mode for drawing the slot's attachment. */
blendMode: BlendMode;
constructor (index: number, name: string, boneData: BoneData) {

View File

@ -28,11 +28,34 @@
*****************************************************************************/
module spine {
/** Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained
* bones to match that of the target bone.
*
* See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide. */
export class TransformConstraint implements Updatable {
/** The transform constraint's setup pose data. */
data: TransformConstraintData;
/** The bones that will be modified by this transform constraint. */
bones: Array<Bone>;
/** The target bone whose world transform will be copied to the constrained bones. */
target: Bone;
rotateMix = 0; translateMix = 0; scaleMix = 0; shearMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
rotateMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
translateMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
scaleMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
shearMix = 0;
temp = new Vector2();
active = false;
@ -54,6 +77,7 @@ module spine {
return this.active;
}
/** Applies the constraint to the constrained bones. */
apply () {
this.update();
}

View File

@ -28,11 +28,48 @@
*****************************************************************************/
module spine {
/** Stores the setup pose for a {@link TransformConstraint}.
*
* See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide. */
export class TransformConstraintData extends ConstraintData {
/** The bones that will be modified by this transform constraint. */
bones = new Array<BoneData>();
/** The target bone whose world transform will be copied to the constrained bones. */
target: BoneData;
rotateMix = 0; translateMix = 0; scaleMix = 0; shearMix = 0;
offsetRotation = 0; offsetX = 0; offsetY = 0; offsetScaleX = 0; offsetScaleY = 0; offsetShearY = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
rotateMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
translateMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
scaleMix = 0;
/** A percentage (0-1) that controls the mix between the constrained and unconstrained shears. */
shearMix = 0;
/** An offset added to the constrained bone rotation. */
offsetRotation = 0;
/** An offset added to the constrained bone X translation. */
offsetX = 0;
/** An offset added to the constrained bone Y translation. */
offsetY = 0;
/** An offset added to the constrained bone scaleX. */
offsetScaleX = 0;
/** An offset added to the constrained bone scaleY. */
offsetScaleY = 0;
/** An offset added to the constrained bone shearY. */
offsetShearY = 0;
relative = false;
local = false;

View File

@ -28,9 +28,15 @@
*****************************************************************************/
module spine {
/** The interface for items updated by {@link Skeleton#updateWorldTransform()}. */
export interface Updatable {
update(): void;
/** Returns false when this item has not been updated because a skin is required and the {@link Skeleton#skin active skin}
* does not contain this item.
* @see Skin#getBones()
* @see Skin#getConstraints() */
isActive(): boolean;
}
}

View File

@ -28,6 +28,7 @@
*****************************************************************************/
module spine {
/** The base class for all attachments. */
export abstract class Attachment {
name: string;
@ -39,24 +40,46 @@ module spine {
abstract copy (): Attachment;
}
/** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's
* {@link Slot#deform}. */
export abstract class VertexAttachment extends Attachment {
private static nextID = 0;
/** The unique ID for this attachment. */
id = (VertexAttachment.nextID++ & 65535) << 11;
/** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting
* the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null
* if this attachment has no weights. */
bones: Array<number>;
/** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y`
* entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting
* each vertex. */
vertices: ArrayLike<number>;
/** The maximum number of world vertex values that can be output by
* {@link #computeWorldVertices()} using the `count` parameter. */
worldVerticesLength = 0;
/** Deform keys for the deform attachment are also applied to this attachment. May be null if no deform keys should be applied. */
deformAttachment: VertexAttachment = this;
constructor (name: string) {
super(name);
}
/** 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. */
/** Transforms the attachment's local {@link vertices} to world coordinates. If the slot's {@link Slot#deform} is
* not empty, it is used to deform the vertices.
*
* See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
* Runtimes Guide.
* @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y.
* @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`.
* @param worldVertices The output world vertices. Must have a length >= `offset` + `count` *
* `stride` / 2.
* @param offset The `worldVertices` index to begin writing values.
* @param stride The number of `worldVertices` entries between the value pairs written. */
computeWorldVertices (slot: Slot, start: number, count: number, worldVertices: ArrayLike<number>, offset: number, stride: number) {
count = offset + (count >> 1) * stride;
let skeleton = slot.bone.skeleton;
@ -115,6 +138,7 @@ module spine {
}
}
/** Does not copy id (generated) or name (set on construction). **/
copyTo (attachment: VertexAttachment) {
if (this.bones != null) {
attachment.bones = new Array<number>(this.bones.length);

View File

@ -28,6 +28,11 @@
*****************************************************************************/
module spine {
/** The interface which can be implemented to customize creating and populating attachments.
*
* See [Loading skeleton data](http://esotericsoftware.com/spine-loading-skeleton-data#AttachmentLoader) in the Spine
* Runtimes Guide. */
export interface AttachmentLoader {
/** @return May be null to not load an attachment. */
newRegionAttachment (skin: Skin, name: string, path: string): RegionAttachment;

View File

@ -28,6 +28,12 @@
*****************************************************************************/
module spine {
/** An attachment with vertices that make up a polygon. Can be used for hit detection, creating physics bodies, spawning particle
* effects, and more.
*
* See {@link SkeletonBounds} and [Bounding Boxes](http://esotericsoftware.com/spine-bounding-boxes) in the Spine User
* Guide. */
export class BoundingBoxAttachment extends VertexAttachment {
color = new Color(1, 1, 1, 1);

View File

@ -28,10 +28,15 @@
*****************************************************************************/
module spine {
/** An attachment with vertices that make up a polygon used for clipping the rendering of other attachments. */
export class ClippingAttachment extends VertexAttachment {
/** Clipping is performed between the clipping polygon's slot and the end slot. Returns null if clipping is done until the end of
* the skeleton's rendering. */
endSlot: SlotData;
// Nonessential.
/** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons
* are not usually rendered at runtime. */
color = new Color(0.2275, 0.2275, 0.8078, 1); // ce3a3aff
constructor (name: string) {

View File

@ -28,16 +28,43 @@
*****************************************************************************/
module spine {
/** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not
* supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh.
*
* See [Mesh attachments](http://esotericsoftware.com/spine-meshes) in the Spine User Guide. */
export class MeshAttachment extends VertexAttachment {
region: TextureRegion;
/** The name of the texture region for this attachment. */
path: string;
regionUVs: ArrayLike<number>; uvs: ArrayLike<number>;
/** The UV pair for each vertex, normalized within the texture region. */
regionUVs: ArrayLike<number>;
/** The UV pair for each vertex, normalized within the entire texture.
*
* See {@link #updateUVs}. */
uvs: ArrayLike<number>;
/** Triplets of vertex indices which describe the mesh's triangulation. */
triangles: Array<number>;
/** The color to tint the mesh. */
color = new Color(1, 1, 1, 1);
/** The width of the mesh's image. Available only when nonessential data was exported. */
width: number;
/** The height of the mesh's image. Available only when nonessential data was exported. */
height: number;
/** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */
hullLength: number;
/** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if
* nonessential data was exported. Triangulation is not performed at runtime. */
edges: Array<number>;
private parentMesh: MeshAttachment;
tempColor = new Color(0, 0, 0, 0);
@ -45,6 +72,8 @@ module spine {
super(name);
}
/** Calculates {@link #uvs} using {@link #regionUVs} and the {@link #region}. Must be called after changing the region UVs or
* region. */
updateUVs () {
let regionUVs = this.regionUVs;
if (this.uvs == null || this.uvs.length != regionUVs.length) this.uvs = Utils.newFloatArray(regionUVs.length);
@ -104,6 +133,9 @@ module spine {
}
}
/** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices},
* {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the
* parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */
getParentMesh () {
return this.parentMesh;
}
@ -150,6 +182,7 @@ module spine {
return copy;
}
/** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/
newLinkedMesh (): MeshAttachment {
let copy = new MeshAttachment(this.name);
copy.region = this.region;

View File

@ -28,9 +28,24 @@
*****************************************************************************/
module spine {
/** An attachment whose vertices make up a composite Bezier curve.
*
* See {@link PathConstraint} and [Paths](http://esotericsoftware.com/spine-paths) in the Spine User Guide. */
export class PathAttachment extends VertexAttachment {
/** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */
lengths: Array<number>;
closed = false; constantSpeed = false;
/** If true, the start and end knots are connected. */
closed = false;
/** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer
* calculations are performed but calculating positions along the path is less accurate. */
constantSpeed = false;
/** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually
* rendered at runtime. */
color = new Color(1, 1, 1, 1);
constructor (name: string) {

View File

@ -28,8 +28,16 @@
*****************************************************************************/
module spine {
/** An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be
* used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a
* skin.
*
* See [Point Attachments](http://esotericsoftware.com/spine-point-attachments) in the Spine User Guide. */
export class PointAttachment extends VertexAttachment {
x: number; y: number; rotation: number;
/** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments
* are not usually rendered at runtime. */
color = new Color(0.38, 0.94, 0, 1);
constructor (name: string) {

View File

@ -28,6 +28,10 @@
*****************************************************************************/
module spine {
/** An attachment that displays a textured quadrilateral.
*
* See [Region attachments](http://esotericsoftware.com/spine-regions) in the Spine User Guide. */
export class RegionAttachment extends Attachment {
static OX1 = 0;
static OY1 = 1;
@ -74,14 +78,42 @@ module spine {
static U4 = 30;
static V4 = 31;
x = 0; y = 0; scaleX = 1; scaleY = 1; rotation = 0; width = 0; height = 0;
/** The local x translation. */
x = 0;
/** The local y translation. */
y = 0;
/** The local scaleX. */
scaleX = 1;
/** The local scaleY. */
scaleY = 1;
/** The local rotation. */
rotation = 0;
/** The width of the region attachment in Spine. */
width = 0;
/** The height of the region attachment in Spine. */
height = 0;
/** The color to tint the region attachment. */
color = new Color(1, 1, 1, 1);
/** The name of the texture region for this attachment. */
path: string;
rendererObject: any;
region: TextureRegion;
/** For each of the 4 vertices, a pair of <code>x,y</code> values that is the local position of the vertex.
*
* See {@link #updateOffset()}. */
offset = Utils.newFloatArray(8);
uvs = Utils.newFloatArray(8);
tempColor = new Color(1, 1, 1, 1);
@ -90,6 +122,7 @@ module spine {
super(name);
}
/** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */
updateOffset () : void {
let regionScaleX = this.width / this.region.originalWidth * this.scaleX;
let regionScaleY = this.height / this.region.originalHeight * this.scaleY;
@ -143,6 +176,13 @@ module spine {
}
}
/** Transforms the attachment's four vertices to world coordinates.
*
* See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
* Runtimes Guide.
* @param worldVertices The output world vertices. Must have a length >= `offset` + 8.
* @param offset The `worldVertices` index to begin writing values.
* @param stride The number of `worldVertices` entries between the value pairs written. */
computeWorldVertices (bone: Bone, worldVertices: ArrayLike<number>, offset: number, stride: number) {
let vertexOffset = this.offset;
let x = bone.worldX, y = bone.worldY;