mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-10 00:58:43 +08:00
Merge branch '4.1-beta' into 4.1-beta-physics
This commit is contained in:
commit
7138baa615
@ -49,6 +49,9 @@
|
||||
* **Breaking changes**
|
||||
|
||||
* **Additions**
|
||||
* `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported).
|
||||
* `SpineAtlasAsset.CreateRuntimeInstance` methods now provide an optional `newCustomTextureLoader` parameter (defaults to `null`) which can be set to e.g. `(a) => new YourCustomTextureLoader(a)` to use your own `TextureLoader` subclass instead of `MaterialsTextureLoader`.
|
||||
* Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`.
|
||||
|
||||
* **Changes of default values**
|
||||
|
||||
@ -246,6 +249,8 @@
|
||||
* Prefabs containing `SkeletonRenderer`, `SkeletonAnimation` and `SkeletonMecanim` now provide a proper Editor preview, including the preview thumbnail.
|
||||
* `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`) now provide a property `Advanced - Fix Prefab Override MeshFilter`, which when enabled fixes the prefab always being marked as changed. It sets the MeshFilter's hide flags to `DontSaveInEditor`. Unfortunately this comes at the cost of references to the `MeshFilter` by other components being lost, therefore this parameter defaults to `false` to keep the safe existing behaviour.
|
||||
* `BoundingBoxFollower` and `BoundingBoxFollowerGraphic` now provide previously missing `usedByEffector` and `usedByComposite` parameters to be set at all generated colliders.
|
||||
* `BoneFollower` and `BoneFollowerGraphic` now provide an additional `Follow Parent World Scale` parameter to allow following simple scale of parent bones (rotated/skewed scale can't be supported).
|
||||
* Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`.
|
||||
|
||||
* **Changes of default values**
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
|
||||
#include <spine/dll.h>
|
||||
#include <spine/Array.h>
|
||||
#include "TextureRegion.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -96,13 +97,10 @@ _SP_ARRAY_DECLARE_TYPE(spKeyValueArray, spKeyValue)
|
||||
/**/
|
||||
typedef struct spAtlasRegion spAtlasRegion;
|
||||
struct spAtlasRegion {
|
||||
spTextureRegion super;
|
||||
const char *name;
|
||||
int x, y, width, height;
|
||||
float u, v, u2, v2;
|
||||
int offsetX, offsetY;
|
||||
int originalWidth, originalHeight;
|
||||
int x, y;
|
||||
int index;
|
||||
int degrees;
|
||||
int *splits;
|
||||
int *pads;
|
||||
spKeyValueArray *keyValues;
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <spine/dll.h>
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/Sequence.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -51,7 +52,7 @@ SP_API void spAttachmentLoader_dispose(spAttachmentLoader *self);
|
||||
* called, an error occurred. */
|
||||
SP_API spAttachment *
|
||||
spAttachmentLoader_createAttachment(spAttachmentLoader *self, spSkin *skin, spAttachmentType type, const char *name,
|
||||
const char *path);
|
||||
const char *path, spSequence *sequence);
|
||||
/* Called after the attachment has been fully configured. */
|
||||
SP_API void spAttachmentLoader_configureAttachment(spAttachmentLoader *self, spAttachment *attachment);
|
||||
/* Called just before the attachment is disposed. This can release allocations made in spAttachmentLoader_configureAttachment. */
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include <spine/VertexAttachment.h>
|
||||
#include <spine/Atlas.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/Sequence.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -45,11 +46,8 @@ struct spMeshAttachment {
|
||||
spVertexAttachment super;
|
||||
|
||||
void *rendererObject;
|
||||
int regionOffsetX, regionOffsetY; /* Pixels stripped from the bottom left, unrotated. */
|
||||
int regionWidth, regionHeight; /* Unrotated, stripped pixel size. */
|
||||
int regionOriginalWidth, regionOriginalHeight; /* Unrotated, unstripped pixel size. */
|
||||
float regionU, regionV, regionU2, regionV2;
|
||||
int regionDegrees;
|
||||
spTextureRegion *region;
|
||||
spSequence *sequence;
|
||||
|
||||
const char *path;
|
||||
|
||||
@ -73,7 +71,7 @@ struct spMeshAttachment {
|
||||
|
||||
SP_API spMeshAttachment *spMeshAttachment_create(const char *name);
|
||||
|
||||
SP_API void spMeshAttachment_updateUVs(spMeshAttachment *self);
|
||||
SP_API void spMeshAttachment_updateRegion(spMeshAttachment *self);
|
||||
|
||||
SP_API void spMeshAttachment_setParentMesh(spMeshAttachment *self, spMeshAttachment *parentMesh);
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/Atlas.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/Sequence.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -46,9 +47,8 @@ typedef struct spRegionAttachment {
|
||||
spColor color;
|
||||
|
||||
void *rendererObject;
|
||||
int regionOffsetX, regionOffsetY; /* Pixels stripped from the bottom left, unrotated. */
|
||||
int regionWidth, regionHeight; /* Unrotated, stripped pixel size. */
|
||||
int regionOriginalWidth, regionOriginalHeight; /* Unrotated, unstripped pixel size. */
|
||||
spTextureRegion *region;
|
||||
spSequence *sequence;
|
||||
|
||||
float offset[8];
|
||||
float uvs[8];
|
||||
@ -56,11 +56,9 @@ typedef struct spRegionAttachment {
|
||||
|
||||
SP_API spRegionAttachment *spRegionAttachment_create(const char *name);
|
||||
|
||||
SP_API void spRegionAttachment_setUVs(spRegionAttachment *self, float u, float v, float u2, float v2, float degrees);
|
||||
SP_API void spRegionAttachment_updateRegion(spRegionAttachment *self);
|
||||
|
||||
SP_API void spRegionAttachment_updateOffset(spRegionAttachment *self);
|
||||
|
||||
SP_API void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spBone *bone, float *vertices, int offset,
|
||||
SP_API void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spSlot *slot, float *vertices, int offset,
|
||||
int stride);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
75
spine-c/spine-c/include/spine/Sequence.h
Normal file
75
spine-c/spine-c/include/spine/Sequence.h
Normal file
@ -0,0 +1,75 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef SPINE_SEQUENCE_H
|
||||
#define SPINE_SEQUENCE_H
|
||||
|
||||
#include <spine/dll.h>
|
||||
#include <spine/TextureRegion.h>
|
||||
#include <spine/Atlas.h>
|
||||
#include "Attachment.h"
|
||||
#include "Slot.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
_SP_ARRAY_DECLARE_TYPE(spTextureRegionArray, spTextureRegion*)
|
||||
|
||||
typedef struct spSequence {
|
||||
int id;
|
||||
int start;
|
||||
int digits;
|
||||
int setupIndex;
|
||||
spTextureRegionArray *regions;
|
||||
} spSequence;
|
||||
|
||||
SP_API spSequence *spSequence_create(int start, int digits, int setupIndex, int numRegions);
|
||||
|
||||
SP_API void spSequence_dispose(spSequence *self);
|
||||
|
||||
SP_API spSequence *spSequence_copy(spSequence *self);
|
||||
|
||||
SP_API void spSequence_apply(spSequence *self, spSlot *slot, spAttachment *attachment);
|
||||
|
||||
SP_API void spSequence_getPath(const char* basePath, int index, char *path);
|
||||
|
||||
#define SP_SEQUENCE_MODE_HOLD 0
|
||||
#define SP_SEQUENCE_MODE_ONCE 1
|
||||
#define SP_SEQUENCE_MODE_LOOP 2
|
||||
#define SP_SEQUENCE_MODE_PINGPONG 3
|
||||
#define SP_SEQUENCE_MODE_ONCEREVERSE 4
|
||||
#define SP_SEQUENCE_MODE_LOOPREVERSE 5
|
||||
#define SP_SEQUENCE_MODE_PINGPONGREVERSE 6
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -64,7 +64,6 @@ typedef struct spSkeleton {
|
||||
|
||||
spSkin *const skin;
|
||||
spColor color;
|
||||
float time;
|
||||
float scaleX, scaleY;
|
||||
float x, y;
|
||||
} spSkeleton;
|
||||
@ -120,8 +119,6 @@ SP_API spTransformConstraint *spSkeleton_findTransformConstraint(const spSkeleto
|
||||
/* Returns 0 if the path constraint was not found. */
|
||||
SP_API spPathConstraint *spSkeleton_findPathConstraint(const spSkeleton *self, const char *constraintName);
|
||||
|
||||
SP_API void spSkeleton_update(spSkeleton *self, float deltaTime);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -50,6 +50,8 @@ typedef struct spSlot {
|
||||
int deformCapacity;
|
||||
int deformCount;
|
||||
float *deform;
|
||||
|
||||
int sequenceIndex;
|
||||
} spSlot;
|
||||
|
||||
SP_API spSlot *spSlot_create(spSlotData *data, spBone *bone);
|
||||
@ -59,10 +61,6 @@ SP_API void spSlot_dispose(spSlot *self);
|
||||
/* @param attachment May be 0 to clear the attachment for the slot. */
|
||||
SP_API void spSlot_setAttachment(spSlot *self, spAttachment *attachment);
|
||||
|
||||
SP_API void spSlot_setAttachmentTime(spSlot *self, float time);
|
||||
|
||||
SP_API float spSlot_getAttachmentTime(const spSlot *self);
|
||||
|
||||
SP_API void spSlot_setToSetupPose(spSlot *self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
50
spine-c/spine-c/include/spine/TextureRegion.h
Normal file
50
spine-c/spine-c/include/spine/TextureRegion.h
Normal file
@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef SPINE_TEXTURE_REGION_H
|
||||
#define SPINE_TEXTURE_REGION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct spTextureRegion {
|
||||
void *rendererObject;
|
||||
float u, v, u2, v2;
|
||||
int degrees;
|
||||
float offsetX, offsetY;
|
||||
int width, height;
|
||||
int originalWidth, originalHeight;
|
||||
} spTextureRegion;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -50,7 +50,7 @@ struct spVertexAttachment {
|
||||
|
||||
int worldVerticesLength;
|
||||
|
||||
spVertexAttachment *deformAttachment;
|
||||
spAttachment *timelineAttachment;
|
||||
|
||||
int id;
|
||||
};
|
||||
|
||||
@ -246,7 +246,7 @@ void _spAttachmentLoader_init(spAttachmentLoader *self,
|
||||
void (*dispose)(spAttachmentLoader *self),
|
||||
spAttachment *(*createAttachment)(spAttachmentLoader *self, spSkin *skin,
|
||||
spAttachmentType type, const char *name,
|
||||
const char *path),
|
||||
const char *path, spSequence *sequence),
|
||||
void (*configureAttachment)(spAttachmentLoader *self, spAttachment *),
|
||||
void (*disposeAttachment)(spAttachmentLoader *self, spAttachment *)
|
||||
);
|
||||
|
||||
@ -1775,7 +1775,7 @@ void _spDeformTimeline_apply(
|
||||
case SP_ATTACHMENT_MESH:
|
||||
case SP_ATTACHMENT_PATH: {
|
||||
spVertexAttachment *vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment);
|
||||
if (vertexAttachment->deformAttachment != SUB_CAST(spVertexAttachment, self->attachment)) return;
|
||||
if (vertexAttachment->timelineAttachment != self->attachment) return;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@ -356,29 +356,29 @@ spAtlas *spAtlas_create(const char *begin, int length, const char *dir, void *re
|
||||
region->x = ss_toInt(&entry[1]);
|
||||
region->y = ss_toInt(&entry[2]);
|
||||
} else if (ss_equals(&entry[0], "size")) {
|
||||
region->width = ss_toInt(&entry[1]);
|
||||
region->height = ss_toInt(&entry[2]);
|
||||
region->super.width = ss_toInt(&entry[1]);
|
||||
region->super.height = ss_toInt(&entry[2]);
|
||||
} else if (ss_equals(&entry[0], "bounds")) {
|
||||
region->x = ss_toInt(&entry[1]);
|
||||
region->y = ss_toInt(&entry[2]);
|
||||
region->width = ss_toInt(&entry[3]);
|
||||
region->height = ss_toInt(&entry[4]);
|
||||
region->super.width = ss_toInt(&entry[3]);
|
||||
region->super.height = ss_toInt(&entry[4]);
|
||||
} else if (ss_equals(&entry[0], "offset")) {
|
||||
region->offsetX = ss_toInt(&entry[1]);
|
||||
region->offsetY = ss_toInt(&entry[2]);
|
||||
region->super.offsetX = ss_toInt(&entry[1]);
|
||||
region->super.offsetY = ss_toInt(&entry[2]);
|
||||
} else if (ss_equals(&entry[0], "orig")) {
|
||||
region->originalWidth = ss_toInt(&entry[1]);
|
||||
region->originalHeight = ss_toInt(&entry[2]);
|
||||
region->super.originalWidth = ss_toInt(&entry[1]);
|
||||
region->super.originalHeight = ss_toInt(&entry[2]);
|
||||
} else if (ss_equals(&entry[0], "offsets")) {
|
||||
region->offsetX = ss_toInt(&entry[1]);
|
||||
region->offsetY = ss_toInt(&entry[2]);
|
||||
region->originalWidth = ss_toInt(&entry[3]);
|
||||
region->originalHeight = ss_toInt(&entry[4]);
|
||||
region->super.offsetX = ss_toInt(&entry[1]);
|
||||
region->super.offsetY = ss_toInt(&entry[2]);
|
||||
region->super.originalWidth = ss_toInt(&entry[3]);
|
||||
region->super.originalHeight = ss_toInt(&entry[4]);
|
||||
} else if (ss_equals(&entry[0], "rotate")) {
|
||||
if (ss_equals(&entry[1], "true")) {
|
||||
region->degrees = 90;
|
||||
region->super.degrees = 90;
|
||||
} else if (!ss_equals(&entry[1], "false")) {
|
||||
region->degrees = ss_toInt(&entry[1]);
|
||||
region->super.degrees = ss_toInt(&entry[1]);
|
||||
}
|
||||
} else if (ss_equals(&entry[0], "index")) {
|
||||
region->index = ss_toInt(&entry[1]);
|
||||
@ -392,19 +392,19 @@ spAtlas *spAtlas_create(const char *begin, int length, const char *dir, void *re
|
||||
spKeyValueArray_add(region->keyValues, keyValue);
|
||||
}
|
||||
}
|
||||
if (region->originalWidth == 0 && region->originalHeight == 0) {
|
||||
region->originalWidth = region->width;
|
||||
region->originalHeight = region->height;
|
||||
if (region->super.originalWidth == 0 && region->super.originalHeight == 0) {
|
||||
region->super.originalWidth = region->super.width;
|
||||
region->super.originalHeight = region->super.height;
|
||||
}
|
||||
|
||||
region->u = (float) region->x / page->width;
|
||||
region->v = (float) region->y / page->height;
|
||||
if (region->degrees == 90) {
|
||||
region->u2 = (float) (region->x + region->height) / page->width;
|
||||
region->v2 = (float) (region->y + region->width) / page->height;
|
||||
region->super.u = (float) region->x / page->width;
|
||||
region->super.v = (float) region->y / page->height;
|
||||
if (region->super.degrees == 90) {
|
||||
region->super.u2 = (float) (region->x + region->super.height) / page->width;
|
||||
region->super.v2 = (float) (region->y + region->super.width) / page->height;
|
||||
} else {
|
||||
region->u2 = (float) (region->x + region->width) / page->width;
|
||||
region->v2 = (float) (region->y + region->height) / page->height;
|
||||
region->super.u2 = (float) (region->x + region->super.width) / page->width;
|
||||
region->super.v2 = (float) (region->y + region->super.height) / page->height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,50 +29,68 @@
|
||||
|
||||
#include <spine/AtlasAttachmentLoader.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/Sequence.h>
|
||||
|
||||
static int /*bool*/ loadSequence(spAtlas *atlas, const char *basePath, spSequence *sequence) {
|
||||
spTextureRegionArray *regions = sequence->regions;
|
||||
char *path = CALLOC(char, strlen(basePath) + sequence->digits + 1);
|
||||
int i ;
|
||||
for (i = 0; i < regions->size; i++) {
|
||||
spSequence_getPath(basePath, i, path);
|
||||
regions->items[i] = SUPER(spAtlas_findRegion(atlas, path));
|
||||
if (!regions->items[i]) {
|
||||
FREE(path);
|
||||
return 0;
|
||||
}
|
||||
regions->items[i]->rendererObject = regions->items[i];
|
||||
}
|
||||
FREE(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
spAttachment *_spAtlasAttachmentLoader_createAttachment(spAttachmentLoader *loader, spSkin *skin, spAttachmentType type,
|
||||
const char *name, const char *path) {
|
||||
const char *name, const char *path, spSequence *sequence) {
|
||||
spAtlasAttachmentLoader *self = SUB_CAST(spAtlasAttachmentLoader, loader);
|
||||
switch (type) {
|
||||
case SP_ATTACHMENT_REGION: {
|
||||
spRegionAttachment *attachment;
|
||||
spAtlasRegion *region = spAtlas_findRegion(self->atlas, path);
|
||||
if (!region) {
|
||||
_spAttachmentLoader_setError(loader, "Region not found: ", path);
|
||||
return 0;
|
||||
spRegionAttachment *attachment = spRegionAttachment_create(name);
|
||||
if (sequence) {
|
||||
if (!loadSequence(self->atlas, path, sequence)) {
|
||||
spAttachment_dispose(SUPER(attachment));
|
||||
_spAttachmentLoader_setError(loader, "Couldn't load sequence for region attachment: ", path);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
spAtlasRegion *region = spAtlas_findRegion(self->atlas, path);
|
||||
if (!region) {
|
||||
spAttachment_dispose(SUPER(attachment));
|
||||
_spAttachmentLoader_setError(loader, "Region not found: ", path);
|
||||
return 0;
|
||||
}
|
||||
attachment->rendererObject = region;
|
||||
attachment->region = SUPER(region);
|
||||
}
|
||||
attachment = spRegionAttachment_create(name);
|
||||
attachment->rendererObject = region;
|
||||
spRegionAttachment_setUVs(attachment, region->u, region->v, region->u2, region->v2, region->degrees);
|
||||
attachment->regionOffsetX = region->offsetX;
|
||||
attachment->regionOffsetY = region->offsetY;
|
||||
attachment->regionWidth = region->width;
|
||||
attachment->regionHeight = region->height;
|
||||
attachment->regionOriginalWidth = region->originalWidth;
|
||||
attachment->regionOriginalHeight = region->originalHeight;
|
||||
return SUPER(attachment);
|
||||
}
|
||||
case SP_ATTACHMENT_MESH:
|
||||
case SP_ATTACHMENT_LINKED_MESH: {
|
||||
spMeshAttachment *attachment;
|
||||
spAtlasRegion *region = spAtlas_findRegion(self->atlas, path);
|
||||
if (!region) {
|
||||
_spAttachmentLoader_setError(loader, "Region not found: ", path);
|
||||
return 0;
|
||||
spMeshAttachment *attachment = spMeshAttachment_create(name);
|
||||
|
||||
if (sequence) {
|
||||
if (!loadSequence(self->atlas, path, sequence)) {
|
||||
spAttachment_dispose(SUPER(SUPER(attachment)));
|
||||
_spAttachmentLoader_setError(loader, "Couldn't load sequence for mesh attachment: ", path);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
spAtlasRegion *region = spAtlas_findRegion(self->atlas, path);
|
||||
if (!region) {
|
||||
_spAttachmentLoader_setError(loader, "Region not found: ", path);
|
||||
return 0;
|
||||
}
|
||||
attachment->rendererObject = region;
|
||||
attachment->region = SUPER(region);
|
||||
}
|
||||
attachment = spMeshAttachment_create(name);
|
||||
attachment->rendererObject = region;
|
||||
attachment->regionU = region->u;
|
||||
attachment->regionV = region->v;
|
||||
attachment->regionU2 = region->u2;
|
||||
attachment->regionV2 = region->v2;
|
||||
attachment->regionDegrees = region->degrees;
|
||||
attachment->regionOffsetX = region->offsetX;
|
||||
attachment->regionOffsetY = region->offsetY;
|
||||
attachment->regionWidth = region->width;
|
||||
attachment->regionHeight = region->height;
|
||||
attachment->regionOriginalWidth = region->originalWidth;
|
||||
attachment->regionOriginalHeight = region->originalHeight;
|
||||
return SUPER(SUPER(attachment));
|
||||
}
|
||||
case SP_ATTACHMENT_BOUNDING_BOX:
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
typedef struct _spAttachmentLoaderVtable {
|
||||
spAttachment *(*createAttachment)(spAttachmentLoader *self, spSkin *skin, spAttachmentType type, const char *name,
|
||||
const char *path);
|
||||
const char *path, spSequence *sequence);
|
||||
|
||||
void (*configureAttachment)(spAttachmentLoader *self, spAttachment *);
|
||||
|
||||
@ -46,7 +46,7 @@ void _spAttachmentLoader_init(spAttachmentLoader *self,
|
||||
void (*dispose)(spAttachmentLoader *self),
|
||||
spAttachment *(*createAttachment)(spAttachmentLoader *self, spSkin *skin,
|
||||
spAttachmentType type, const char *name,
|
||||
const char *path),
|
||||
const char *path, spSequence *sequence),
|
||||
void (*configureAttachment)(spAttachmentLoader *self, spAttachment *),
|
||||
void (*disposeAttachment)(spAttachmentLoader *self, spAttachment *)) {
|
||||
CONST_CAST(_spAttachmentLoaderVtable *, self->vtable) = NEW(_spAttachmentLoaderVtable);
|
||||
@ -69,12 +69,12 @@ void spAttachmentLoader_dispose(spAttachmentLoader *self) {
|
||||
|
||||
spAttachment *
|
||||
spAttachmentLoader_createAttachment(spAttachmentLoader *self, spSkin *skin, spAttachmentType type, const char *name,
|
||||
const char *path) {
|
||||
const char *path, spSequence *sequence) {
|
||||
FREE(self->error1);
|
||||
FREE(self->error2);
|
||||
self->error1 = 0;
|
||||
self->error2 = 0;
|
||||
return VTABLE(spAttachmentLoader, self)->createAttachment(self, skin, type, name, path);
|
||||
return VTABLE(spAttachmentLoader, self)->createAttachment(self, skin, type, name, path, sequence);
|
||||
}
|
||||
|
||||
void spAttachmentLoader_configureAttachment(spAttachmentLoader *self, spAttachment *attachment) {
|
||||
|
||||
@ -42,6 +42,7 @@ void _spMeshAttachment_dispose(spAttachment *attachment) {
|
||||
FREE(self->edges);
|
||||
} else
|
||||
_spAttachment_deinit(attachment);
|
||||
if (self->sequence) FREE(self->sequence);
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
@ -52,17 +53,8 @@ spAttachment *_spMeshAttachment_copy(spAttachment *attachment) {
|
||||
return SUPER(SUPER(spMeshAttachment_newLinkedMesh(self)));
|
||||
copy = spMeshAttachment_create(attachment->name);
|
||||
copy->rendererObject = self->rendererObject;
|
||||
copy->regionU = self->regionU;
|
||||
copy->regionV = self->regionV;
|
||||
copy->regionU2 = self->regionU2;
|
||||
copy->regionV2 = self->regionV2;
|
||||
copy->regionDegrees = self->regionDegrees;
|
||||
copy->regionOffsetX = self->regionOffsetX;
|
||||
copy->regionOffsetY = self->regionOffsetY;
|
||||
copy->regionWidth = self->regionWidth;
|
||||
copy->regionHeight = self->regionHeight;
|
||||
copy->regionOriginalWidth = self->regionOriginalWidth;
|
||||
copy->regionOriginalHeight = self->regionOriginalHeight;
|
||||
copy->region = self->region;
|
||||
copy->sequence = self->sequence != NULL ? spSequence_copy(self->sequence) : NULL;
|
||||
MALLOC_STR(copy->path, self->path);
|
||||
spColor_setFromColor(©->color, &self->color);
|
||||
|
||||
@ -90,22 +82,12 @@ spMeshAttachment *spMeshAttachment_newLinkedMesh(spMeshAttachment *self) {
|
||||
spMeshAttachment *copy = spMeshAttachment_create(self->super.super.name);
|
||||
|
||||
copy->rendererObject = self->rendererObject;
|
||||
copy->regionU = self->regionU;
|
||||
copy->regionV = self->regionV;
|
||||
copy->regionU2 = self->regionU2;
|
||||
copy->regionV2 = self->regionV2;
|
||||
copy->regionDegrees = self->regionDegrees;
|
||||
copy->regionOffsetX = self->regionOffsetX;
|
||||
copy->regionOffsetY = self->regionOffsetY;
|
||||
copy->regionWidth = self->regionWidth;
|
||||
copy->regionHeight = self->regionHeight;
|
||||
copy->regionOriginalWidth = self->regionOriginalWidth;
|
||||
copy->regionOriginalHeight = self->regionOriginalHeight;
|
||||
copy->region = self->region;
|
||||
MALLOC_STR(copy->path, self->path);
|
||||
spColor_setFromColor(©->color, &self->color);
|
||||
copy->super.deformAttachment = self->super.deformAttachment;
|
||||
copy->super.timelineAttachment = self->super.timelineAttachment;
|
||||
spMeshAttachment_setParentMesh(copy, self->parentMesh ? self->parentMesh : self);
|
||||
spMeshAttachment_updateUVs(copy);
|
||||
if (copy->region) spMeshAttachment_updateRegion(copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
@ -117,7 +99,7 @@ spMeshAttachment *spMeshAttachment_create(const char *name) {
|
||||
return self;
|
||||
}
|
||||
|
||||
void spMeshAttachment_updateUVs(spMeshAttachment *self) {
|
||||
void spMeshAttachment_updateRegion(spMeshAttachment *self) {
|
||||
int i, n;
|
||||
float *uvs;
|
||||
float u, v, width, height;
|
||||
@ -125,17 +107,17 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
|
||||
FREE(self->uvs);
|
||||
uvs = self->uvs = MALLOC(float, verticesLength);
|
||||
n = verticesLength;
|
||||
u = self->regionU;
|
||||
v = self->regionV;
|
||||
u = self->region->u;
|
||||
v = self->region->v;
|
||||
|
||||
switch (self->regionDegrees) {
|
||||
switch (self->region->degrees) {
|
||||
case 90: {
|
||||
float textureWidth = self->regionHeight / (self->regionU2 - self->regionU);
|
||||
float textureHeight = self->regionWidth / (self->regionV2 - self->regionV);
|
||||
u -= (self->regionOriginalHeight - self->regionOffsetY - self->regionHeight) / textureWidth;
|
||||
v -= (self->regionOriginalWidth - self->regionOffsetX - self->regionWidth) / textureHeight;
|
||||
width = self->regionOriginalHeight / textureWidth;
|
||||
height = self->regionOriginalWidth / textureHeight;
|
||||
float textureWidth = self->region->height / (self->region->u2 - self->region->u);
|
||||
float textureHeight = self->region->width / (self->region->v2 - self->region->v);
|
||||
u -= (self->region->originalHeight - self->region->offsetY - self->region->height) / textureWidth;
|
||||
v -= (self->region->originalWidth - self->region->offsetX - self->region->width) / textureHeight;
|
||||
width = self->region->originalHeight / textureWidth;
|
||||
height = self->region->originalWidth / textureHeight;
|
||||
for (i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + self->regionUVs[i + 1] * width;
|
||||
uvs[i + 1] = v + (1 - self->regionUVs[i]) * height;
|
||||
@ -143,12 +125,12 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
|
||||
return;
|
||||
}
|
||||
case 180: {
|
||||
float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
|
||||
float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
|
||||
u -= (self->regionOriginalWidth - self->regionOffsetX - self->regionWidth) / textureWidth;
|
||||
v -= self->regionOffsetY / textureHeight;
|
||||
width = self->regionOriginalWidth / textureWidth;
|
||||
height = self->regionOriginalHeight / textureHeight;
|
||||
float textureWidth = self->region->width / (self->region->u2 - self->region->u);
|
||||
float textureHeight = self->region->height / (self->region->v2 - self->region->v);
|
||||
u -= (self->region->originalWidth - self->region->offsetX - self->region->width) / textureWidth;
|
||||
v -= self->region->offsetY / textureHeight;
|
||||
width = self->region->originalWidth / textureWidth;
|
||||
height = self->region->originalHeight / textureHeight;
|
||||
for (i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + (1 - self->regionUVs[i]) * width;
|
||||
uvs[i + 1] = v + (1 - self->regionUVs[i + 1]) * height;
|
||||
@ -156,12 +138,12 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
|
||||
return;
|
||||
}
|
||||
case 270: {
|
||||
float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
|
||||
float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
|
||||
u -= self->regionOffsetY / textureWidth;
|
||||
v -= self->regionOffsetX / textureHeight;
|
||||
width = self->regionOriginalHeight / textureWidth;
|
||||
height = self->regionOriginalWidth / textureHeight;
|
||||
float textureHeight = self->region->height / (self->region->v2 - self->region->v);
|
||||
float textureWidth = self->region->width / (self->region->u2 - self->region->u);
|
||||
u -= self->region->offsetY / textureWidth;
|
||||
v -= self->region->offsetX / textureHeight;
|
||||
width = self->region->originalHeight / textureWidth;
|
||||
height = self->region->originalWidth / textureHeight;
|
||||
for (i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + (1 - self->regionUVs[i + 1]) * width;
|
||||
uvs[i + 1] = v + self->regionUVs[i] * height;
|
||||
@ -169,12 +151,12 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
|
||||
float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
|
||||
u -= self->regionOffsetX / textureWidth;
|
||||
v -= (self->regionOriginalHeight - self->regionOffsetY - self->regionHeight) / textureHeight;
|
||||
width = self->regionOriginalWidth / textureWidth;
|
||||
height = self->regionOriginalHeight / textureHeight;
|
||||
float textureWidth = self->region->width / (self->region->u2 - self->region->u);
|
||||
float textureHeight = self->region->height / (self->region->v2 - self->region->v);
|
||||
u -= self->region->offsetX / textureWidth;
|
||||
v -= (self->region->originalHeight - self->region->offsetY - self->region->height) / textureHeight;
|
||||
width = self->region->originalWidth / textureWidth;
|
||||
height = self->region->originalHeight / textureHeight;
|
||||
for (i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + self->regionUVs[i] * width;
|
||||
uvs[i + 1] = v + self->regionUVs[i + 1] * height;
|
||||
|
||||
@ -51,12 +51,7 @@ void _spRegionAttachment_dispose(spAttachment *attachment) {
|
||||
spAttachment *_spRegionAttachment_copy(spAttachment *attachment) {
|
||||
spRegionAttachment *self = SUB_CAST(spRegionAttachment, attachment);
|
||||
spRegionAttachment *copy = spRegionAttachment_create(attachment->name);
|
||||
copy->regionWidth = self->regionWidth;
|
||||
copy->regionHeight = self->regionHeight;
|
||||
copy->regionOffsetX = self->regionOffsetX;
|
||||
copy->regionOffsetY = self->regionOffsetY;
|
||||
copy->regionOriginalWidth = self->regionOriginalWidth;
|
||||
copy->regionOriginalHeight = self->regionOriginalHeight;
|
||||
copy->region = self->region;
|
||||
copy->rendererObject = self->rendererObject;
|
||||
MALLOC_STR(copy->path, self->path);
|
||||
copy->x = self->x;
|
||||
@ -69,6 +64,7 @@ spAttachment *_spRegionAttachment_copy(spAttachment *attachment) {
|
||||
memcpy(copy->uvs, self->uvs, sizeof(float) * 8);
|
||||
memcpy(copy->offset, self->offset, sizeof(float) * 8);
|
||||
spColor_setFromColor(©->color, &self->color);
|
||||
copy->sequence = self->sequence ? spSequence_copy(self->sequence) : NULL;
|
||||
return SUPER(copy);
|
||||
}
|
||||
|
||||
@ -81,35 +77,13 @@ spRegionAttachment *spRegionAttachment_create(const char *name) {
|
||||
return self;
|
||||
}
|
||||
|
||||
void spRegionAttachment_setUVs(spRegionAttachment *self, float u, float v, float u2, float v2, float degrees) {
|
||||
if (degrees == 90) {
|
||||
self->uvs[URX] = u;
|
||||
self->uvs[URY] = v2;
|
||||
self->uvs[BRX] = u;
|
||||
self->uvs[BRY] = v;
|
||||
self->uvs[BLX] = u2;
|
||||
self->uvs[BLY] = v;
|
||||
self->uvs[ULX] = u2;
|
||||
self->uvs[ULY] = v2;
|
||||
} else {
|
||||
self->uvs[ULX] = u;
|
||||
self->uvs[ULY] = v2;
|
||||
self->uvs[URX] = u;
|
||||
self->uvs[URY] = v;
|
||||
self->uvs[BRX] = u2;
|
||||
self->uvs[BRY] = v;
|
||||
self->uvs[BLX] = u2;
|
||||
self->uvs[BLY] = v2;
|
||||
}
|
||||
}
|
||||
|
||||
void spRegionAttachment_updateOffset(spRegionAttachment *self) {
|
||||
float regionScaleX = self->width / self->regionOriginalWidth * self->scaleX;
|
||||
float regionScaleY = self->height / self->regionOriginalHeight * self->scaleY;
|
||||
float localX = -self->width / 2 * self->scaleX + self->regionOffsetX * regionScaleX;
|
||||
float localY = -self->height / 2 * self->scaleY + self->regionOffsetY * regionScaleY;
|
||||
float localX2 = localX + self->regionWidth * regionScaleX;
|
||||
float localY2 = localY + self->regionHeight * regionScaleY;
|
||||
void spRegionAttachment_updateRegion(spRegionAttachment *self) {
|
||||
float regionScaleX = self->width / self->region->originalWidth * self->scaleX;
|
||||
float regionScaleY = self->height / self->region->originalHeight * self->scaleY;
|
||||
float localX = -self->width / 2 * self->scaleX + self->region->offsetX * regionScaleX;
|
||||
float localY = -self->height / 2 * self->scaleY + self->region->offsetY * regionScaleY;
|
||||
float localX2 = localX + self->region->width * regionScaleX;
|
||||
float localY2 = localY + self->region->height * regionScaleY;
|
||||
float radians = self->rotation * DEG_RAD;
|
||||
float cosine = COS(radians), sine = SIN(radians);
|
||||
float localXCos = localX * cosine + self->x;
|
||||
@ -128,14 +102,37 @@ void spRegionAttachment_updateOffset(spRegionAttachment *self) {
|
||||
self->offset[URY] = localY2Cos + localX2Sin;
|
||||
self->offset[BRX] = localX2Cos - localYSin;
|
||||
self->offset[BRY] = localYCos + localX2Sin;
|
||||
|
||||
if (self->region->degrees == 90) {
|
||||
self->uvs[URX] = self->region->u;
|
||||
self->uvs[URY] = self->region->v2;
|
||||
self->uvs[BRX] = self->region->u;
|
||||
self->uvs[BRY] = self->region->v;
|
||||
self->uvs[BLX] = self->region->u2;
|
||||
self->uvs[BLY] = self->region->v;
|
||||
self->uvs[ULX] = self->region->u2;
|
||||
self->uvs[ULY] = self->region->v2;
|
||||
} else {
|
||||
self->uvs[ULX] = self->region->u;
|
||||
self->uvs[ULY] = self->region->v2;
|
||||
self->uvs[URX] = self->region->u;
|
||||
self->uvs[URY] = self->region->v;
|
||||
self->uvs[BRX] = self->region->u2;
|
||||
self->uvs[BRY] = self->region->v;
|
||||
self->uvs[BLX] = self->region->u2;
|
||||
self->uvs[BLY] = self->region->v2;
|
||||
}
|
||||
}
|
||||
|
||||
void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spBone *bone, float *vertices, int offset,
|
||||
void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spSlot *slot, float *vertices, int offset,
|
||||
int stride) {
|
||||
const float *offsets = self->offset;
|
||||
spBone *bone = slot->bone;
|
||||
float x = bone->worldX, y = bone->worldY;
|
||||
float offsetX, offsetY;
|
||||
|
||||
if (self->sequence) spSequence_apply(self->sequence, slot, SUPER(self));
|
||||
|
||||
offsetX = offsets[BRX];
|
||||
offsetY = offsets[BRY];
|
||||
vertices[offset] = offsetX * bone->a + offsetY * bone->b + x; /* br */
|
||||
|
||||
92
spine-c/spine-c/src/spine/Sequence.c
Normal file
92
spine-c/spine-c/src/spine/Sequence.c
Normal file
@ -0,0 +1,92 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <spine/Sequence.h>
|
||||
#include <spine/extension.h>
|
||||
|
||||
_SP_ARRAY_IMPLEMENT_TYPE(spTextureRegionArray, spTextureRegion*)
|
||||
|
||||
static int nextSequenceId = 0;
|
||||
|
||||
spSequence *spSequence_create(int start, int digits, int setupIndex, int numRegions) {
|
||||
spSequence *self = NEW(spSequence);
|
||||
self->id = nextSequenceId++;
|
||||
self->start = start;
|
||||
self->digits = digits;
|
||||
self->setupIndex = setupIndex;
|
||||
self->regions = spTextureRegionArray_create(numRegions);
|
||||
spTextureRegionArray_setSize(self->regions, numRegions);
|
||||
return self;
|
||||
}
|
||||
|
||||
void spSequence_dispose(spSequence *self) {
|
||||
FREE(self->regions);
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
spSequence *spSequence_copy(spSequence *self) {
|
||||
int i = 0;
|
||||
spSequence *copy = spSequence_create(self->start, self->digits, self->setupIndex, self->regions->size);
|
||||
for (; i < self->regions->size; i++)
|
||||
copy->regions->items[i] = self->regions->items[i];
|
||||
copy->start = self->start;
|
||||
copy->digits = self->digits;
|
||||
copy->setupIndex = self->setupIndex;
|
||||
return copy;
|
||||
}
|
||||
|
||||
void spSequence_apply(spSequence *self, spSlot *slot, spAttachment *attachment) {
|
||||
int index = slot->sequenceIndex;
|
||||
spTextureRegion *region = NULL;
|
||||
if (index == -1) index = self->setupIndex;
|
||||
if (index >= (int) self->regions->size) index = self->regions->size - 1;
|
||||
region = self->regions->items[index];
|
||||
|
||||
if (attachment->type == SP_ATTACHMENT_REGION) {
|
||||
spRegionAttachment *regionAttachment = (spRegionAttachment*)attachment;
|
||||
if (regionAttachment->region != region) {
|
||||
regionAttachment->rendererObject = region;
|
||||
regionAttachment->region = region;
|
||||
spRegionAttachment_updateRegion(regionAttachment);
|
||||
}
|
||||
}
|
||||
|
||||
if (attachment->type == SP_ATTACHMENT_MESH) {
|
||||
spMeshAttachment *meshAttachment = (spMeshAttachment*)attachment;
|
||||
if (meshAttachment->region != region) {
|
||||
meshAttachment->rendererObject = region;
|
||||
meshAttachment->region = region;
|
||||
spMeshAttachment_updateRegion(meshAttachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spSequence_getPath(const char* basePath, int index, char* path) {
|
||||
fix me
|
||||
}
|
||||
@ -629,7 +629,3 @@ spPathConstraint *spSkeleton_findPathConstraint(const spSkeleton *self, const ch
|
||||
if (strcmp(self->pathConstraints[i]->data->name, constraintName) == 0) return self->pathConstraints[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spSkeleton_update(spSkeleton *self, float deltaTime) {
|
||||
self->time += deltaTime;
|
||||
}
|
||||
|
||||
@ -991,13 +991,13 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
|
||||
region->width = readFloat(input) * self->scale;
|
||||
region->height = readFloat(input) * self->scale;
|
||||
readColor(input, ®ion->color.r, ®ion->color.g, ®ion->color.b, ®ion->color.a);
|
||||
spRegionAttachment_updateOffset(region);
|
||||
spRegionAttachment_updateRegion(region);
|
||||
spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
|
||||
return attachment;
|
||||
}
|
||||
case SP_ATTACHMENT_BOUNDING_BOX: {
|
||||
int vertexCount = readVarint(input, 1);
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0);
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0, NULL);
|
||||
_readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount);
|
||||
if (nonessential) {
|
||||
spBoundingBoxAttachment *bbox = SUB_CAST(spBoundingBoxAttachment, attachment);
|
||||
@ -1025,7 +1025,7 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
|
||||
mesh->regionUVs = _readFloatArray(input, vertexCount << 1, 1);
|
||||
mesh->triangles = (unsigned short *) _readShortArray(input, &mesh->trianglesCount);
|
||||
_readVertices(self, input, SUPER(mesh), vertexCount);
|
||||
spMeshAttachment_updateUVs(mesh);
|
||||
spMeshAttachment_updateRegion(mesh);
|
||||
mesh->hullLength = readVarint(input, 1) << 1;
|
||||
if (nonessential) {
|
||||
mesh->edges = (int *) _readShortArray(input, &mesh->edgesCount);
|
||||
@ -1067,7 +1067,7 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
|
||||
return attachment;
|
||||
}
|
||||
case SP_ATTACHMENT_PATH: {
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0);
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0, NULL);
|
||||
spPathAttachment *path = SUB_CAST(spPathAttachment, attachment);
|
||||
int vertexCount = 0;
|
||||
path->closed = readBoolean(input);
|
||||
@ -1086,7 +1086,7 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
|
||||
return attachment;
|
||||
}
|
||||
case SP_ATTACHMENT_POINT: {
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0);
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0, NULL);
|
||||
spPointAttachment *point = SUB_CAST(spPointAttachment, attachment);
|
||||
point->rotation = readFloat(input);
|
||||
point->x = readFloat(input) * self->scale;
|
||||
@ -1101,7 +1101,7 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
|
||||
case SP_ATTACHMENT_CLIPPING: {
|
||||
int endSlotIndex = readVarint(input, 1);
|
||||
int vertexCount = readVarint(input, 1);
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0);
|
||||
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0, NULL);
|
||||
spClippingAttachment *clip = SUB_CAST(spClippingAttachment, attachment);
|
||||
_readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount);
|
||||
if (nonessential) {
|
||||
@ -1418,11 +1418,10 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
|
||||
_spSkeletonBinary_setError(self, "Parent mesh not found: ", linkedMesh->parent);
|
||||
return NULL;
|
||||
}
|
||||
linkedMesh->mesh->super.deformAttachment = linkedMesh->inheritDeform ? SUB_CAST(spVertexAttachment, parent)
|
||||
: SUB_CAST(spVertexAttachment,
|
||||
linkedMesh->mesh);
|
||||
linkedMesh->mesh->super.timelineAttachment = linkedMesh->inheritDeform ? parent
|
||||
: SUPER(SUPER(linkedMesh->mesh));
|
||||
spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent));
|
||||
spMeshAttachment_updateUVs(linkedMesh->mesh);
|
||||
spMeshAttachment_updateRegion(linkedMesh->mesh);
|
||||
spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh)));
|
||||
}
|
||||
|
||||
|
||||
@ -1352,7 +1352,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
||||
toColor(color, 3));
|
||||
}
|
||||
|
||||
spRegionAttachment_updateOffset(region);
|
||||
spRegionAttachment_updateRegion(region);
|
||||
|
||||
spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
|
||||
break;
|
||||
@ -1392,7 +1392,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
||||
|
||||
_readVertices(self, attachmentMap, SUPER(mesh), verticesLength);
|
||||
|
||||
spMeshAttachment_updateUVs(mesh);
|
||||
spMeshAttachment_updateRegion(mesh);
|
||||
|
||||
mesh->hullLength = Json_getInt(attachmentMap, "hull", 0);
|
||||
|
||||
@ -1514,11 +1514,10 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
||||
_spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent);
|
||||
return NULL;
|
||||
}
|
||||
linkedMesh->mesh->super.deformAttachment = linkedMesh->inheritDeform ? SUB_CAST(spVertexAttachment, parent)
|
||||
: SUB_CAST(spVertexAttachment,
|
||||
linkedMesh->mesh);
|
||||
linkedMesh->mesh->super.timelineAttachment = linkedMesh->inheritDeform ? parent
|
||||
: SUPER(SUPER(linkedMesh->mesh));
|
||||
spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent));
|
||||
spMeshAttachment_updateUVs(linkedMesh->mesh);
|
||||
spMeshAttachment_updateRegion(linkedMesh->mesh);
|
||||
spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh)));
|
||||
}
|
||||
|
||||
|
||||
@ -30,13 +30,8 @@
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/extension.h>
|
||||
|
||||
typedef struct {
|
||||
spSlot super;
|
||||
float attachmentTime;
|
||||
} _spSlot;
|
||||
|
||||
spSlot *spSlot_create(spSlotData *data, spBone *bone) {
|
||||
spSlot *self = SUPER(NEW(_spSlot));
|
||||
spSlot *self = NEW(spSlot);
|
||||
CONST_CAST(spSlotData *, self->data) = data;
|
||||
CONST_CAST(spBone *, self->bone) = bone;
|
||||
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
|
||||
@ -68,20 +63,12 @@ void spSlot_setAttachment(spSlot *self, spAttachment *attachment) {
|
||||
if (attachment == self->attachment) return;
|
||||
|
||||
if (!isVertexAttachment(attachment) ||
|
||||
!isVertexAttachment(self->attachment) || (SUB_CAST(spVertexAttachment, attachment)->deformAttachment != SUB_CAST(spVertexAttachment, self->attachment)->deformAttachment)) {
|
||||
!isVertexAttachment(self->attachment) || (SUB_CAST(spVertexAttachment, attachment)->timelineAttachment != SUB_CAST(spVertexAttachment, self->attachment)->timelineAttachment)) {
|
||||
self->deformCount = 0;
|
||||
}
|
||||
|
||||
CONST_CAST(spAttachment *, self->attachment) = attachment;
|
||||
SUB_CAST(_spSlot, self)->attachmentTime = self->bone->skeleton->time;
|
||||
}
|
||||
|
||||
void spSlot_setAttachmentTime(spSlot *self, float time) {
|
||||
SUB_CAST(_spSlot, self)->attachmentTime = self->bone->skeleton->time - time;
|
||||
}
|
||||
|
||||
float spSlot_getAttachmentTime(const spSlot *self) {
|
||||
return self->bone->skeleton->time - SUB_CAST(_spSlot, self)->attachmentTime;
|
||||
self->sequenceIndex = -1;
|
||||
}
|
||||
|
||||
void spSlot_setToSetupPose(spSlot *self) {
|
||||
|
||||
@ -35,7 +35,7 @@ static int nextID = 0;
|
||||
|
||||
void _spVertexAttachment_init(spVertexAttachment *attachment) {
|
||||
attachment->id = nextID++;
|
||||
attachment->deformAttachment = attachment;
|
||||
attachment->timelineAttachment = SUPER(attachment);
|
||||
}
|
||||
|
||||
void _spVertexAttachment_deinit(spVertexAttachment *attachment) {
|
||||
@ -52,6 +52,11 @@ void spVertexAttachment_computeWorldVertices(spVertexAttachment *self, spSlot *s
|
||||
float *vertices;
|
||||
int *bones;
|
||||
|
||||
if (self->super.type == SP_ATTACHMENT_MESH || self->super.type == SP_ATTACHMENT_LINKED_MESH) {
|
||||
spMeshAttachment *mesh = SUB_CAST(spMeshAttachment, self);
|
||||
if (mesh->sequence) spSequence_apply(mesh->sequence, slot, SUPER(self));
|
||||
}
|
||||
|
||||
count = offset + (count >> 1) * stride;
|
||||
skeleton = slot->bone->skeleton;
|
||||
deformLength = slot->deformCount;
|
||||
|
||||
@ -249,7 +249,6 @@ namespace spine {
|
||||
|
||||
void SkeletonRenderer::update(float deltaTime) {
|
||||
Node::update(deltaTime);
|
||||
if (_ownsSkeleton) _skeleton->update(deltaTime * _timeScale);
|
||||
}
|
||||
|
||||
void SkeletonRenderer::draw(Renderer *renderer, const Mat4 &transform, uint32_t transformFlags) {
|
||||
@ -657,7 +656,7 @@ namespace spine {
|
||||
|
||||
RegionAttachment *attachment = (RegionAttachment *) slot->getAttachment();
|
||||
float worldVertices[8];
|
||||
attachment->computeWorldVertices(slot->getBone(), worldVertices, 0, 2);
|
||||
attachment->computeWorldVertices(*slot, worldVertices, 0, 2);
|
||||
const Vec2 points[4] =
|
||||
{
|
||||
{worldVertices[0], worldVertices[1]},
|
||||
@ -958,7 +957,7 @@ namespace spine {
|
||||
if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
|
||||
RegionAttachment *const regionAttachment = static_cast<RegionAttachment *>(attachment);
|
||||
assert(dstPtr + 8 <= dstEnd);
|
||||
regionAttachment->computeWorldVertices(slot.getBone(), dstPtr, 0, 2);
|
||||
regionAttachment->computeWorldVertices(slot, dstPtr, 0, 2);
|
||||
dstPtr += 8;
|
||||
} else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
|
||||
MeshAttachment *const mesh = static_cast<MeshAttachment *>(attachment);
|
||||
|
||||
@ -116,16 +116,15 @@ namespace spine {
|
||||
|
||||
void setDuration(float inValue);
|
||||
|
||||
/// @param target After the first and before the last entry.
|
||||
static int search(Vector<float> &values, float target);
|
||||
|
||||
static int search(Vector<float> &values, float target, int step);
|
||||
private:
|
||||
Vector<Timeline *> _timelines;
|
||||
HashMap<PropertyId, bool> _timelineIds;
|
||||
float _duration;
|
||||
String _name;
|
||||
|
||||
/// @param target After the first and before the last entry.
|
||||
static int search(Vector<float> &values, float target);
|
||||
|
||||
static int search(Vector<float> &values, float target, int step);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -43,14 +43,14 @@ namespace spine {
|
||||
|
||||
public:
|
||||
LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent,
|
||||
bool inheritDeform);
|
||||
bool inheritTimeline);
|
||||
|
||||
private:
|
||||
MeshAttachment *_mesh;
|
||||
String _skin;
|
||||
size_t _slotIndex;
|
||||
String _parent;
|
||||
bool _inheritDeform;
|
||||
bool _inheritTimeline;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,8 @@ namespace spine {
|
||||
Property_TransformConstraint = 1 << 15,
|
||||
Property_PathConstraintPosition = 1 << 16,
|
||||
Property_PathConstraintSpacing = 1 << 17,
|
||||
Property_PathConstraintMix = 1 << 18
|
||||
Property_PathConstraintMix = 1 << 18,
|
||||
Property_Sequence = 1 << 19
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -60,8 +60,6 @@ namespace spine {
|
||||
|
||||
void updateRegion();
|
||||
|
||||
void setUVs(float u, float v, float u2, float v2, float degrees);
|
||||
|
||||
/// Transforms the attachment's four vertices to world coordinates.
|
||||
/// @param bone The parent bone.
|
||||
/// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8.
|
||||
|
||||
@ -39,12 +39,14 @@ namespace spine {
|
||||
|
||||
class Attachment;
|
||||
|
||||
class SkeletonBinary;
|
||||
class SkeletonJson;
|
||||
|
||||
class SP_API Sequence : public SpineObject {
|
||||
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
public:
|
||||
explicit Sequence();
|
||||
|
||||
Sequence(int id, const Vector<TextureRegion *> ®ions, int start, int digits, int setupIndex);
|
||||
Sequence(int count);
|
||||
|
||||
~Sequence();
|
||||
|
||||
|
||||
77
spine-cpp/spine-cpp/include/spine/SequenceTimeline.h
Normal file
77
spine-cpp/spine-cpp/include/spine/SequenceTimeline.h
Normal file
@ -0,0 +1,77 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef Spine_SequenceTimeline_h
|
||||
#define Spine_SequenceTimeline_h
|
||||
|
||||
#ifdef SPINE_UE4
|
||||
#include "SpinePluginPrivatePCH.h"
|
||||
#endif
|
||||
|
||||
#include <spine/Timeline.h>
|
||||
#include <spine/Sequence.h>
|
||||
|
||||
namespace spine {
|
||||
class Attachment;
|
||||
|
||||
class SP_API SequenceTimeline : public Timeline {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
friend class SkeletonJson;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit SequenceTimeline(size_t frameCount, int slotIndex, spine::Attachment *attachment);
|
||||
|
||||
virtual ~SequenceTimeline();
|
||||
|
||||
virtual void
|
||||
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
|
||||
MixDirection direction);
|
||||
|
||||
void setFrame(int frame, float time, SequenceMode mode, int index, float delay);
|
||||
|
||||
int getSlotIndex() { return _slotIndex; };
|
||||
|
||||
void setSlotIndex(int inValue) { _slotIndex = inValue; }
|
||||
|
||||
Attachment *getAttachment() { return _attachment; }
|
||||
|
||||
protected:
|
||||
int _slotIndex;
|
||||
Attachment *_attachment;
|
||||
|
||||
static const int ENTRIES = 3;
|
||||
static const int MODE = 1;
|
||||
static const int DELAY = 2;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* Spine_SequenceTimeline_h */
|
||||
@ -61,6 +61,8 @@ namespace spine {
|
||||
|
||||
class CurveTimeline2;
|
||||
|
||||
class Sequence;
|
||||
|
||||
class SP_API SkeletonBinary : public SpineObject {
|
||||
public:
|
||||
static const int BONE_ROTATE = 0;
|
||||
@ -81,6 +83,9 @@ namespace spine {
|
||||
static const int SLOT_RGB2 = 4;
|
||||
static const int SLOT_ALPHA = 5;
|
||||
|
||||
static const int ATTACHMENT_DEFORM = 0;
|
||||
static const int ATTACHMENT_SEQUENCE = 1;
|
||||
|
||||
static const int PATH_POSITION = 0;
|
||||
static const int PATH_SPACING = 1;
|
||||
static const int PATH_MIX = 2;
|
||||
@ -137,10 +142,12 @@ namespace spine {
|
||||
|
||||
Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential);
|
||||
|
||||
Sequence *readSequence(DataInput *input);
|
||||
|
||||
Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
|
||||
SkeletonData *skeletonData, bool nonessential);
|
||||
|
||||
void readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount);
|
||||
void readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount);
|
||||
|
||||
void readFloatArray(DataInput *input, int n, float scale, Vector<float> &array);
|
||||
|
||||
|
||||
@ -59,6 +59,8 @@ namespace spine {
|
||||
|
||||
class String;
|
||||
|
||||
class Sequence;
|
||||
|
||||
class SP_API SkeletonJson : public SpineObject {
|
||||
public:
|
||||
explicit SkeletonJson(Atlas *atlas);
|
||||
@ -82,6 +84,8 @@ namespace spine {
|
||||
const bool _ownsLoader;
|
||||
String _error;
|
||||
|
||||
static Sequence *readSequence(Json *sequence);
|
||||
|
||||
static void
|
||||
setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1,
|
||||
float cy1,
|
||||
|
||||
@ -48,7 +48,7 @@ namespace spine {
|
||||
AtlasAttachmentLoader::AtlasAttachmentLoader(Atlas *atlas) : AttachmentLoader(), _atlas(atlas) {
|
||||
}
|
||||
|
||||
bool loadSequence (Atlas *atlas, const String &basePath, Sequence *sequence) {
|
||||
bool loadSequence(Atlas *atlas, const String &basePath, Sequence *sequence) {
|
||||
Vector<TextureRegion *> ®ions = sequence->getRegions();
|
||||
for (int i = 0, n = regions.size(); i < n; i++) {
|
||||
String path = sequence->getPath(basePath, i);
|
||||
@ -61,7 +61,7 @@ namespace spine {
|
||||
|
||||
RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) {
|
||||
SP_UNUSED(skin);
|
||||
RegionAttachment *attachment = new(__FILE__, __LINE__) RegionAttachment(name);
|
||||
RegionAttachment *attachment = new (__FILE__, __LINE__) RegionAttachment(name);
|
||||
if (sequence) {
|
||||
if (!loadSequence(_atlas, path, sequence)) return NULL;
|
||||
} else {
|
||||
|
||||
@ -38,9 +38,9 @@
|
||||
using namespace spine;
|
||||
|
||||
LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent,
|
||||
bool inheritDeform) : _mesh(mesh),
|
||||
_skin(skin),
|
||||
_slotIndex(slotIndex),
|
||||
_parent(parent),
|
||||
_inheritDeform(inheritDeform) {
|
||||
bool inheritTimeline) : _mesh(mesh),
|
||||
_skin(skin),
|
||||
_slotIndex(slotIndex),
|
||||
_parent(parent),
|
||||
_inheritTimeline(inheritTimeline) {
|
||||
}
|
||||
|
||||
@ -144,6 +144,22 @@ void MeshAttachment::setPath(const String &inValue) {
|
||||
_path = inValue;
|
||||
}
|
||||
|
||||
TextureRegion *MeshAttachment::getRegion() {
|
||||
return _region;
|
||||
}
|
||||
|
||||
void MeshAttachment::setRegion(TextureRegion *region) {
|
||||
_region = region;
|
||||
}
|
||||
|
||||
Sequence *MeshAttachment::getSequence() {
|
||||
return _sequence;
|
||||
}
|
||||
|
||||
void MeshAttachment::setSequence(Sequence *sequence) {
|
||||
_sequence = sequence;
|
||||
}
|
||||
|
||||
MeshAttachment *MeshAttachment::getParentMesh() {
|
||||
return _parentMesh;
|
||||
}
|
||||
|
||||
@ -35,22 +35,21 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Sequence::Sequence() : _id(Sequence::getNextID()),
|
||||
_regions(),
|
||||
_start(0),
|
||||
_digits(0),
|
||||
_setupIndex(0) {
|
||||
|
||||
Sequence::Sequence(int count) : _id(Sequence::getNextID()),
|
||||
_regions(),
|
||||
_start(0),
|
||||
_digits(0),
|
||||
_setupIndex(0) {
|
||||
_regions.setSize(count, NULL);
|
||||
}
|
||||
|
||||
Sequence::~Sequence() {
|
||||
|
||||
}
|
||||
|
||||
Sequence *Sequence::copy() {
|
||||
Sequence *copy = new (__FILE__, __LINE__) Sequence();
|
||||
Sequence *copy = new (__FILE__, __LINE__) Sequence(_regions.size());
|
||||
for (size_t i = 0; i < _regions.size(); i++) {
|
||||
copy->_regions.add(_regions[i]);
|
||||
copy->_regions[i] = _regions[i];
|
||||
}
|
||||
copy->_start = _start;
|
||||
copy->_digits = _digits;
|
||||
@ -61,12 +60,13 @@ Sequence *Sequence::copy() {
|
||||
void Sequence::apply(Slot *slot, Attachment *attachment) {
|
||||
int index = slot->getSequenceIndex();
|
||||
if (index == -1) index = _setupIndex;
|
||||
if (index >= (int)_regions.size()) index = _regions.size() - 1;
|
||||
if (index >= (int) _regions.size()) index = _regions.size() - 1;
|
||||
TextureRegion *region = _regions[index];
|
||||
|
||||
if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
|
||||
RegionAttachment *regionAttachment = static_cast<RegionAttachment *>(attachment);
|
||||
if (regionAttachment->getRegion() != region) {
|
||||
regionAttachment->setRendererObject(region);
|
||||
regionAttachment->setRegion(region);
|
||||
regionAttachment->updateRegion();
|
||||
}
|
||||
@ -75,6 +75,7 @@ void Sequence::apply(Slot *slot, Attachment *attachment) {
|
||||
if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
|
||||
MeshAttachment *meshAttachment = static_cast<MeshAttachment *>(attachment);
|
||||
if (meshAttachment->getRegion() != region) {
|
||||
meshAttachment->setRendererObject(region);
|
||||
meshAttachment->setRegion(region);
|
||||
meshAttachment->updateRegion();
|
||||
}
|
||||
|
||||
129
spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp
Normal file
129
spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef SPINE_UE4
|
||||
#include "SpinePluginPrivatePCH.h"
|
||||
#endif
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/SequenceTimeline.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/Animation.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(SequenceTimeline, Timeline)
|
||||
|
||||
SequenceTimeline::SequenceTimeline(size_t frameCount, int slotIndex, Attachment *attachment) : Timeline(frameCount, ENTRIES), _slotIndex(slotIndex), _attachment(attachment) {
|
||||
int sequenceId = 0;
|
||||
if (attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) attachment)->getSequence()->getId();
|
||||
if (attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequenceId = ((MeshAttachment *) attachment)->getSequence()->getId();
|
||||
PropertyId ids[] = {((PropertyId) Property_Sequence << 32) | ((slotIndex << 16 | sequenceId) & 0xffffffff)};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
SequenceTimeline::~SequenceTimeline() {
|
||||
}
|
||||
|
||||
void SequenceTimeline::setFrame(int frame, float time, SequenceMode mode, int index, float delay) {
|
||||
Vector<float> &frames = this->_frames;
|
||||
frame *= ENTRIES;
|
||||
frames[frame] = time;
|
||||
frames[frame + MODE] = mode | (index << 4);
|
||||
frames[frame + DELAY] = delay;
|
||||
}
|
||||
|
||||
void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents,
|
||||
float alpha, MixBlend blend, MixDirection direction) {
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(pEvents);
|
||||
SP_UNUSED(direction);
|
||||
|
||||
Slot *slot = skeleton.getSlots()[_slotIndex];
|
||||
if (!slot->getBone().isActive()) return;
|
||||
Attachment *slotAttachment = slot->getAttachment();
|
||||
if (slotAttachment != _attachment) {
|
||||
if (!slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti) || ((VertexAttachment *) slotAttachment)->getTimelineAttachment() != _attachment) return;
|
||||
}
|
||||
|
||||
Vector<float> &frames = this->_frames;
|
||||
if (time < frames[0]) {// Time is before first frame.
|
||||
if (blend == MixBlend_Setup || blend == MixBlend_First) slot->setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = Animation::search(frames, time, ENTRIES);
|
||||
float before = frames[i];
|
||||
int modeAndIndex = (int) frames[i + MODE];
|
||||
float delay = frames[i + DELAY];
|
||||
|
||||
Sequence *sequence = NULL;
|
||||
if (_attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequence = ((RegionAttachment *) _attachment)->getSequence();
|
||||
if (_attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = ((MeshAttachment *) _attachment)->getSequence();
|
||||
int index = modeAndIndex >> 4, count = sequence->getRegions().size();
|
||||
int mode = modeAndIndex & 0xf;
|
||||
if (mode != SequenceMode::hold) {
|
||||
index += (int) (((time - before) / delay + 0.00001));
|
||||
switch (mode) {
|
||||
case SequenceMode::once:
|
||||
index = MathUtil::min(count - 1, index);
|
||||
break;
|
||||
case SequenceMode::loop:
|
||||
index %= count;
|
||||
break;
|
||||
case SequenceMode::pingpong: {
|
||||
int n = (count << 1) - 2;
|
||||
index %= n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
case SequenceMode::onceReverse:
|
||||
index = MathUtil::max(count - 1 - index, 0);
|
||||
break;
|
||||
case SequenceMode::loopReverse:
|
||||
index = count - 1 - (index % count);
|
||||
break;
|
||||
case SequenceMode::pingpongReverse: {
|
||||
int n = (count << 1) - 2;
|
||||
index = (index + count - 1) % n;
|
||||
if (index >= count) index = n - index;
|
||||
}
|
||||
}
|
||||
}
|
||||
slot->setSequenceIndex(index);
|
||||
}
|
||||
@ -72,6 +72,7 @@
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/TransformConstraintTimeline.h>
|
||||
#include <spine/TranslateTimeline.h>
|
||||
#include "spine/SequenceTimeline.h"
|
||||
|
||||
using namespace spine;
|
||||
|
||||
@ -298,10 +299,10 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
setError("Parent mesh not found: ", linkedMesh->_parent.buffer());
|
||||
return NULL;
|
||||
}
|
||||
linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritDeform ? static_cast<VertexAttachment *>(parent)
|
||||
: linkedMesh->_mesh;
|
||||
linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast<VertexAttachment *>(parent)
|
||||
: linkedMesh->_mesh;
|
||||
linkedMesh->_mesh->setParentMesh(static_cast<MeshAttachment *>(parent));
|
||||
linkedMesh->_mesh->updateRegion();
|
||||
if (linkedMesh->_mesh->_region) linkedMesh->_mesh->updateRegion();
|
||||
_attachmentLoader->configureAttachment(linkedMesh->_mesh);
|
||||
}
|
||||
ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes);
|
||||
@ -478,6 +479,15 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData
|
||||
return skin;
|
||||
}
|
||||
|
||||
Sequence *SkeletonBinary::readSequence(DataInput *input) {
|
||||
if (!readBoolean(input)) return NULL;
|
||||
Sequence *sequence = new (__FILE__, __LINE__) Sequence(readVarint(input, true));
|
||||
sequence->_start = readVarint(input, true);
|
||||
sequence->_digits = readVarint(input, true);
|
||||
sequence->_setupIndex = readVarint(input, true);
|
||||
return sequence;
|
||||
}
|
||||
|
||||
Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
|
||||
SkeletonData *skeletonData, bool nonessential) {
|
||||
String name(readStringRef(input, skeletonData));
|
||||
@ -488,21 +498,32 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
case AttachmentType_Region: {
|
||||
String path(readStringRef(input, skeletonData));
|
||||
if (path.isEmpty()) path = name;
|
||||
RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path));
|
||||
float rotation = readFloat(input);
|
||||
float x = readFloat(input) * _scale;
|
||||
float y = readFloat(input) * _scale;
|
||||
float scaleX = readFloat(input);
|
||||
float scaleY = readFloat(input);
|
||||
float width = readFloat(input) * _scale;
|
||||
float height = readFloat(input) * _scale;
|
||||
Color color;
|
||||
readColor(input, color);
|
||||
Sequence *sequence = readSequence(input);
|
||||
RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path), sequence);
|
||||
if (!region) {
|
||||
setError("Error reading attachment: ", name.buffer());
|
||||
return nullptr;
|
||||
}
|
||||
region->_path = path;
|
||||
region->_rotation = readFloat(input);
|
||||
region->_x = readFloat(input) * _scale;
|
||||
region->_y = readFloat(input) * _scale;
|
||||
region->_scaleX = readFloat(input);
|
||||
region->_scaleY = readFloat(input);
|
||||
region->_width = readFloat(input) * _scale;
|
||||
region->_height = readFloat(input) * _scale;
|
||||
readColor(input, region->getColor());
|
||||
region->updateRegion();
|
||||
region->_rotation = rotation;
|
||||
region->_x = x;
|
||||
region->_y = y;
|
||||
region->_scaleX = scaleX;
|
||||
region->_scaleY = scaleY;
|
||||
region->_width = width;
|
||||
region->_height = height;
|
||||
region->getColor().set(color);
|
||||
region->_sequence = sequence;
|
||||
if (sequence == NULL) region->updateRegion();
|
||||
_attachmentLoader->configureAttachment(region);
|
||||
return region;
|
||||
}
|
||||
@ -513,7 +534,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
setError("Error reading attachment: ", name.buffer());
|
||||
return nullptr;
|
||||
}
|
||||
readVertices(input, static_cast<VertexAttachment *>(box), vertexCount);
|
||||
readVertices(input, box->getVertices(), box->getBones(), vertexCount);
|
||||
box->setWorldVerticesLength(vertexCount << 1);
|
||||
if (nonessential) {
|
||||
readColor(input, box->getColor());
|
||||
}
|
||||
@ -521,31 +543,52 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
return box;
|
||||
}
|
||||
case AttachmentType_Mesh: {
|
||||
Color color;
|
||||
int vertexCount;
|
||||
MeshAttachment *mesh;
|
||||
Vector<float> uvs;
|
||||
Vector<unsigned short> triangles;
|
||||
Vector<float> vertices;
|
||||
Vector<size_t> bones;
|
||||
int hullLength;
|
||||
Sequence *sequence;
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
Vector<unsigned short> edges;
|
||||
|
||||
String path(readStringRef(input, skeletonData));
|
||||
if (path.isEmpty()) path = name;
|
||||
readColor(input, color);
|
||||
vertexCount = readVarint(input, true);
|
||||
readFloatArray(input, vertexCount << 1, 1, uvs);
|
||||
readShortArray(input, triangles);
|
||||
readVertices(input, vertices, bones, vertexCount);
|
||||
hullLength = readVarint(input, true) << 1;
|
||||
sequence = readSequence(input);
|
||||
if (nonessential) {
|
||||
readShortArray(input, edges);
|
||||
width = readFloat(input) * _scale;
|
||||
height = readFloat(input) * _scale;
|
||||
}
|
||||
|
||||
mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
|
||||
MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence);
|
||||
if (!mesh) {
|
||||
setError("Error reading attachment: ", name.buffer());
|
||||
return nullptr;
|
||||
}
|
||||
mesh->_path = path;
|
||||
readColor(input, mesh->getColor());
|
||||
vertexCount = readVarint(input, true);
|
||||
readFloatArray(input, vertexCount << 1, 1, mesh->getRegionUVs());
|
||||
readShortArray(input, mesh->getTriangles());
|
||||
readVertices(input, static_cast<VertexAttachment *>(mesh), vertexCount);
|
||||
mesh->updateRegion();
|
||||
mesh->_hullLength = readVarint(input, true) << 1;
|
||||
mesh->_color.set(color);
|
||||
mesh->_bones.addAll(bones);
|
||||
mesh->_vertices.addAll(vertices);
|
||||
mesh->setWorldVerticesLength(vertexCount << 1);
|
||||
mesh->_triangles.addAll(triangles);
|
||||
mesh->_regionUVs.addAll(uvs);
|
||||
if (sequence == NULL) mesh->updateRegion();
|
||||
mesh->_hullLength = hullLength;
|
||||
mesh->_sequence = sequence;
|
||||
if (nonessential) {
|
||||
readShortArray(input, mesh->getEdges());
|
||||
mesh->_width = readFloat(input) * _scale;
|
||||
mesh->_height = readFloat(input) * _scale;
|
||||
} else {
|
||||
mesh->_width = 0;
|
||||
mesh->_height = 0;
|
||||
mesh->_edges.addAll(edges);
|
||||
mesh->_width = width;
|
||||
mesh->_height = height;
|
||||
}
|
||||
_attachmentLoader->configureAttachment(mesh);
|
||||
return mesh;
|
||||
@ -554,23 +597,33 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
String path(readStringRef(input, skeletonData));
|
||||
if (path.isEmpty()) path = name;
|
||||
|
||||
MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
|
||||
Color color;
|
||||
float width, height;
|
||||
readColor(input, color);
|
||||
String skinName(readStringRef(input, skeletonData));
|
||||
String parent(readStringRef(input, skeletonData));
|
||||
bool inheritTimelines = readBoolean(input);
|
||||
Sequence *sequence = readSequence(input);
|
||||
if (nonessential) {
|
||||
width = readFloat(input) * _scale;
|
||||
height = readFloat(input) * _scale;
|
||||
}
|
||||
|
||||
MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence);
|
||||
if (!mesh) {
|
||||
setError("Error reading attachment: ", name.buffer());
|
||||
return nullptr;
|
||||
}
|
||||
mesh->_path = path;
|
||||
readColor(input, mesh->getColor());
|
||||
String skinName(readStringRef(input, skeletonData));
|
||||
String parent(readStringRef(input, skeletonData));
|
||||
bool inheritDeform = readBoolean(input);
|
||||
mesh->_color.set(color);
|
||||
mesh->_sequence = sequence;
|
||||
if (nonessential) {
|
||||
mesh->_width = readFloat(input) * _scale;
|
||||
mesh->_height = readFloat(input) * _scale;
|
||||
mesh->_width = width;
|
||||
mesh->_height = height;
|
||||
}
|
||||
|
||||
LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex,
|
||||
String(parent), inheritDeform);
|
||||
String(parent), inheritTimelines);
|
||||
_linkedMeshes.add(linkedMesh);
|
||||
return mesh;
|
||||
}
|
||||
@ -583,7 +636,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
path->_closed = readBoolean(input);
|
||||
path->_constantSpeed = readBoolean(input);
|
||||
int vertexCount = readVarint(input, true);
|
||||
readVertices(input, static_cast<VertexAttachment *>(path), vertexCount);
|
||||
readVertices(input, path->getVertices(), path->getBones(), vertexCount);
|
||||
path->setWorldVerticesLength(vertexCount << 1);
|
||||
int lengthsLength = vertexCount / 3;
|
||||
path->_lengths.setSize(lengthsLength, 0);
|
||||
for (int i = 0; i < lengthsLength; ++i) {
|
||||
@ -619,7 +673,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
setError("Error reading attachment: ", name.buffer());
|
||||
return nullptr;
|
||||
}
|
||||
readVertices(input, static_cast<VertexAttachment *>(clip), vertexCount);
|
||||
readVertices(input, clip->getVertices(), clip->getBones(), vertexCount);
|
||||
clip->setWorldVerticesLength(vertexCount << 1);
|
||||
clip->_endSlot = skeletonData->_slots[endSlotIndex];
|
||||
if (nonessential) {
|
||||
readColor(input, clip->getColor());
|
||||
@ -631,18 +686,15 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) {
|
||||
void SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount) {
|
||||
float scale = _scale;
|
||||
int verticesLength = vertexCount << 1;
|
||||
attachment->setWorldVerticesLength(vertexCount << 1);
|
||||
|
||||
if (!readBoolean(input)) {
|
||||
readFloatArray(input, verticesLength, scale, attachment->getVertices());
|
||||
readFloatArray(input, verticesLength, scale, vertices);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<float> &vertices = attachment->getVertices();
|
||||
Vector<size_t> &bones = attachment->getBones();
|
||||
vertices.ensureCapacity(verticesLength * 3 * 3);
|
||||
bones.ensureCapacity(verticesLength * 3);
|
||||
|
||||
@ -1176,69 +1228,84 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
||||
for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) {
|
||||
const char *attachmentName = readStringRef(input, skeletonData);
|
||||
Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName));
|
||||
|
||||
if (!baseAttachment) {
|
||||
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
||||
setError("Attachment not found: ", attachmentName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment);
|
||||
|
||||
bool weighted = attachment->_bones.size() > 0;
|
||||
Vector<float> &vertices = attachment->_vertices;
|
||||
int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
|
||||
|
||||
unsigned int timelineType = readByte(input);
|
||||
int frameCount = readVarint(input, true);
|
||||
int frameLast = frameCount - 1;
|
||||
int bezierCount = readVarint(input, true);
|
||||
DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex,
|
||||
attachment);
|
||||
|
||||
float time = readFloat(input);
|
||||
for (int frame = 0, bezier = 0;; ++frame) {
|
||||
Vector<float> deform;
|
||||
size_t end = (size_t) readVarint(input, true);
|
||||
if (end == 0) {
|
||||
if (weighted) {
|
||||
deform.setSize(deformLength, 0);
|
||||
for (int iiii = 0; iiii < deformLength; ++iiii)
|
||||
deform[iiii] = 0;
|
||||
} else {
|
||||
deform.clearAndAddAll(vertices);
|
||||
}
|
||||
} else {
|
||||
deform.setSize(deformLength, 0);
|
||||
size_t start = (size_t) readVarint(input, true);
|
||||
end += start;
|
||||
if (scale == 1) {
|
||||
for (size_t v = start; v < end; ++v)
|
||||
deform[v] = readFloat(input);
|
||||
} else {
|
||||
for (size_t v = start; v < end; ++v)
|
||||
deform[v] = readFloat(input) * scale;
|
||||
switch (timelineType) {
|
||||
case ATTACHMENT_DEFORM: {
|
||||
bool weighted = attachment->_bones.size() > 0;
|
||||
Vector<float> &vertices = attachment->_vertices;
|
||||
int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
|
||||
|
||||
int bezierCount = readVarint(input, true);
|
||||
DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex,
|
||||
attachment);
|
||||
|
||||
float time = readFloat(input);
|
||||
for (int frame = 0, bezier = 0;; ++frame) {
|
||||
Vector<float> deform;
|
||||
size_t end = (size_t) readVarint(input, true);
|
||||
if (end == 0) {
|
||||
if (weighted) {
|
||||
deform.setSize(deformLength, 0);
|
||||
for (int iiii = 0; iiii < deformLength; ++iiii)
|
||||
deform[iiii] = 0;
|
||||
} else {
|
||||
deform.clearAndAddAll(vertices);
|
||||
}
|
||||
} else {
|
||||
deform.setSize(deformLength, 0);
|
||||
size_t start = (size_t) readVarint(input, true);
|
||||
end += start;
|
||||
if (scale == 1) {
|
||||
for (size_t v = start; v < end; ++v)
|
||||
deform[v] = readFloat(input);
|
||||
} else {
|
||||
for (size_t v = start; v < end; ++v)
|
||||
deform[v] = readFloat(input) * scale;
|
||||
}
|
||||
|
||||
if (!weighted) {
|
||||
for (size_t v = 0, vn = deform.size(); v < vn; ++v)
|
||||
deform[v] += vertices[v];
|
||||
}
|
||||
}
|
||||
|
||||
timeline->setFrame(frame, time, deform);
|
||||
if (frame == frameLast) break;
|
||||
float time2 = readFloat(input);
|
||||
switch (readSByte(input)) {
|
||||
case CURVE_STEPPED:
|
||||
timeline->setStepped(frame);
|
||||
break;
|
||||
case CURVE_BEZIER:
|
||||
setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
|
||||
}
|
||||
time = time2;
|
||||
}
|
||||
|
||||
if (!weighted) {
|
||||
for (size_t v = 0, vn = deform.size(); v < vn; ++v)
|
||||
deform[v] += vertices[v];
|
||||
}
|
||||
timelines.add(timeline);
|
||||
break;
|
||||
}
|
||||
|
||||
timeline->setFrame(frame, time, deform);
|
||||
if (frame == frameLast) break;
|
||||
float time2 = readFloat(input);
|
||||
switch (readSByte(input)) {
|
||||
case CURVE_STEPPED:
|
||||
timeline->setStepped(frame);
|
||||
break;
|
||||
case CURVE_BEZIER:
|
||||
setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
|
||||
case ATTACHMENT_SEQUENCE: {
|
||||
SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, attachment);
|
||||
for (int frame = 0; frame < frameCount; frame++) {
|
||||
float time = readFloat(input);
|
||||
int modeAndIndex = readInt(input);
|
||||
float delay = readFloat(input);
|
||||
timeline->setFrame(frame, time, (spine::SequenceMode)(modeAndIndex & 0xf), modeAndIndex >> 4, delay);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
break;
|
||||
}
|
||||
time = time2;
|
||||
}
|
||||
|
||||
timelines.add(timeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,6 +72,7 @@
|
||||
#include <spine/TransformConstraintTimeline.h>
|
||||
#include <spine/TranslateTimeline.h>
|
||||
#include <spine/Vertices.h>
|
||||
#include "spine/SequenceTimeline.h"
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
|
||||
#define strdup _strdup
|
||||
@ -548,7 +549,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
|
||||
switch (type) {
|
||||
case AttachmentType_Region: {
|
||||
attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath);
|
||||
Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence"));
|
||||
attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath, sequence);
|
||||
if (!attachment) {
|
||||
delete skeletonData;
|
||||
setError(root, "Error reading attachment: ", skinAttachmentName);
|
||||
@ -565,17 +567,19 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
region->_rotation = Json::getFloat(attachmentMap, "rotation", 0);
|
||||
region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale;
|
||||
region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale;
|
||||
region->_sequence = sequence;
|
||||
|
||||
color = Json::getString(attachmentMap, "color", 0);
|
||||
if (color) toColor(region->getColor(), color, true);
|
||||
|
||||
region->updateRegion();
|
||||
if (region->_region != NULL) region->updateRegion();
|
||||
_attachmentLoader->configureAttachment(region);
|
||||
break;
|
||||
}
|
||||
case AttachmentType_Mesh:
|
||||
case AttachmentType_Linkedmesh: {
|
||||
attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath);
|
||||
Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence"));
|
||||
attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath, sequence);
|
||||
|
||||
if (!attachment) {
|
||||
delete skeletonData;
|
||||
@ -591,6 +595,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
|
||||
mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale;
|
||||
mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale;
|
||||
mesh->_sequence = sequence;
|
||||
|
||||
entry = Json::getItem(attachmentMap, "parent");
|
||||
if (!entry) {
|
||||
@ -610,7 +615,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
|
||||
readVertices(attachmentMap, mesh, verticesLength);
|
||||
|
||||
mesh->updateRegion();
|
||||
if (mesh->_region != NULL) mesh->updateRegion();
|
||||
|
||||
mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0);
|
||||
|
||||
@ -623,14 +628,14 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
}
|
||||
_attachmentLoader->configureAttachment(mesh);
|
||||
} else {
|
||||
bool inheritDeform = Json::getInt(attachmentMap, "deform", 1) ? true : false;
|
||||
bool inheritTimelines = Json::getInt(attachmentMap, "timelines", 1) ? true : false;
|
||||
LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh,
|
||||
String(Json::getString(
|
||||
attachmentMap,
|
||||
"skin", 0)),
|
||||
slot->getIndex(),
|
||||
String(entry->_valueString),
|
||||
inheritDeform);
|
||||
inheritTimelines);
|
||||
_linkedMeshes.add(linkedMesh);
|
||||
}
|
||||
break;
|
||||
@ -722,10 +727,10 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
setError(root, "Parent mesh not found: ", linkedMesh->_parent.buffer());
|
||||
return NULL;
|
||||
}
|
||||
linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritDeform ? static_cast<VertexAttachment *>(parent)
|
||||
: linkedMesh->_mesh;
|
||||
linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast<VertexAttachment *>(parent)
|
||||
: linkedMesh->_mesh;
|
||||
linkedMesh->_mesh->setParentMesh(static_cast<MeshAttachment *>(parent));
|
||||
linkedMesh->_mesh->updateRegion();
|
||||
if (linkedMesh->_mesh->_region != NULL) linkedMesh->_mesh->updateRegion();
|
||||
_attachmentLoader->configureAttachment(linkedMesh->_mesh);
|
||||
}
|
||||
ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes);
|
||||
@ -777,6 +782,15 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
Sequence *SkeletonJson::readSequence(Json *item) {
|
||||
if (item == NULL) return NULL;
|
||||
Sequence *sequence = new Sequence(Json::getInt(item, "count", 0));
|
||||
sequence->_start = Json::getInt(item, "start", 1);
|
||||
sequence->_digits = Json::getInt(item, "digits", 0);
|
||||
sequence->_setupIndex = Json::getInt(item, "setupIndex", 0);
|
||||
return sequence;
|
||||
}
|
||||
|
||||
void SkeletonJson::setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1,
|
||||
float cy1,
|
||||
float cx2, float cy2, float time2, float value2) {
|
||||
@ -865,10 +879,10 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
Json *ik = Json::getItem(root, "ik");
|
||||
Json *transform = Json::getItem(root, "transform");
|
||||
Json *paths = Json::getItem(root, "path");
|
||||
Json *deform = Json::getItem(root, "deform");
|
||||
Json *attachments = Json::getItem(root, "attachments");
|
||||
Json *drawOrder = Json::getItem(root, "drawOrder");
|
||||
Json *events = Json::getItem(root, "events");
|
||||
Json *boneMap, *slotMap, *constraintMap, *keyMap, *nextMap, *curve;
|
||||
Json *boneMap, *slotMap, *keyMap, *nextMap, *curve;
|
||||
int frame, bezier;
|
||||
Color color, color2, newColor, newColor2;
|
||||
|
||||
@ -883,7 +897,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frames, slotIndex);
|
||||
for (keyMap = timelineMap->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) {
|
||||
timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0),
|
||||
Json::getItem(keyMap, "name")->_valueString);
|
||||
Json::getItem(keyMap, "name") ? Json::getItem(keyMap, "name")->_valueString : NULL);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
|
||||
@ -1079,7 +1093,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
}
|
||||
|
||||
/** IK constraint timelines. */
|
||||
for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
|
||||
for (Json *constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
|
||||
keyMap = constraintMap->_child;
|
||||
if (keyMap == NULL) continue;
|
||||
|
||||
@ -1122,7 +1136,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
}
|
||||
|
||||
/** Transform constraint timelines. */
|
||||
for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
|
||||
for (Json *constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
|
||||
keyMap = constraintMap->_child;
|
||||
if (keyMap == NULL) continue;
|
||||
|
||||
@ -1178,7 +1192,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
}
|
||||
|
||||
/** Path constraint timelines. */
|
||||
for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
|
||||
for (Json *constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
|
||||
PathConstraintData *constraint = skeletonData->findPathConstraint(constraintMap->_name);
|
||||
if (!constraint) {
|
||||
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
||||
@ -1239,77 +1253,99 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Deform timelines. */
|
||||
for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) {
|
||||
Skin *skin = skeletonData->findSkin(constraintMap->_name);
|
||||
for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) {
|
||||
/** Attachment timelines. */
|
||||
for (Json *attachmenstMap = attachments ? attachments->_child : NULL; attachmenstMap; attachmenstMap = attachmenstMap->_next) {
|
||||
Skin *skin = skeletonData->findSkin(attachmenstMap->_name);
|
||||
for (slotMap = attachmenstMap->_child; slotMap; slotMap = slotMap->_next) {
|
||||
int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines);
|
||||
if (slotIndex == -1) return NULL;
|
||||
|
||||
for (Json *timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) {
|
||||
keyMap = timelineMap->_child;
|
||||
if (keyMap == NULL) continue;
|
||||
|
||||
Attachment *baseAttachment = skin->getAttachment(slotIndex, timelineMap->_name);
|
||||
if (!baseAttachment) {
|
||||
for (Json *attachmentMap = slotMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) {
|
||||
Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name);
|
||||
if (!attachment) {
|
||||
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
||||
setError(NULL, "Attachment not found: ", timelineMap->_name);
|
||||
setError(NULL, "Attachment not found: ", attachmentMap->_name);
|
||||
return NULL;
|
||||
}
|
||||
VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment);
|
||||
|
||||
bool weighted = attachment->_bones.size() != 0;
|
||||
Vector<float> &verts = attachment->_vertices;
|
||||
int deformLength = weighted ? verts.size() / 3 * 2 : verts.size();
|
||||
for (Json *timelineMap = attachmentMap->_child; timelineMap; timelineMap = timelineMap->_next) {
|
||||
keyMap = timelineMap->_child;
|
||||
if (keyMap == NULL) continue;
|
||||
int frames = timelineMap->_size;
|
||||
String timelineName = timelineMap->_name;
|
||||
if (timelineName == "deform") {
|
||||
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(attachment);
|
||||
bool weighted = vertexAttachment->_bones.size() != 0;
|
||||
Vector<float> &verts = vertexAttachment->_vertices;
|
||||
int deformLength = weighted ? verts.size() / 3 * 2 : verts.size();
|
||||
|
||||
DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(timelineMap->_size,
|
||||
timelineMap->_size, slotIndex,
|
||||
attachment);
|
||||
float time = Json::getFloat(keyMap, "time", 0);
|
||||
for (frame = 0, bezier = 0;; frame++) {
|
||||
Json *vertices = Json::getItem(keyMap, "vertices");
|
||||
Vector<float> deformed;
|
||||
if (!vertices) {
|
||||
if (weighted) {
|
||||
deformed.setSize(deformLength, 0);
|
||||
} else {
|
||||
deformed.clearAndAddAll(attachment->_vertices);
|
||||
}
|
||||
} else {
|
||||
int v, start = Json::getInt(keyMap, "offset", 0);
|
||||
Json *vertex;
|
||||
deformed.setSize(deformLength, 0);
|
||||
if (_scale == 1) {
|
||||
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) {
|
||||
deformed[v] = vertex->_valueFloat;
|
||||
DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frames,
|
||||
frames, slotIndex, vertexAttachment);
|
||||
float time = Json::getFloat(keyMap, "time", 0);
|
||||
for (frame = 0, bezier = 0;; frame++) {
|
||||
Json *vertices = Json::getItem(keyMap, "vertices");
|
||||
Vector<float> deformed;
|
||||
if (!vertices) {
|
||||
if (weighted) {
|
||||
deformed.setSize(deformLength, 0);
|
||||
} else {
|
||||
deformed.clearAndAddAll(vertexAttachment->_vertices);
|
||||
}
|
||||
} else {
|
||||
deformed.setSize(deformLength, 0);
|
||||
int v, start = Json::getInt(keyMap, "offset", 0);
|
||||
Json *vertex;
|
||||
if (_scale == 1) {
|
||||
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) {
|
||||
deformed[v] = vertex->_valueFloat;
|
||||
}
|
||||
} else {
|
||||
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) {
|
||||
deformed[v] = vertex->_valueFloat * _scale;
|
||||
}
|
||||
}
|
||||
if (!weighted) {
|
||||
Vector<float> &verticesAttachment = vertexAttachment->_vertices;
|
||||
for (v = 0; v < deformLength; ++v) {
|
||||
deformed[v] += verticesAttachment[v];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) {
|
||||
deformed[v] = vertex->_valueFloat * _scale;
|
||||
timeline->setFrame(frame, time, deformed);
|
||||
nextMap = keyMap->_next;
|
||||
if (!nextMap) {
|
||||
// timeline.shrink(); // BOZO
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!weighted) {
|
||||
Vector<float> &verticesAttachment = attachment->_vertices;
|
||||
for (v = 0; v < deformLength; ++v) {
|
||||
deformed[v] += verticesAttachment[v];
|
||||
float time2 = Json::getFloat(nextMap, "time", 0);
|
||||
curve = Json::getItem(keyMap, "curve");
|
||||
if (curve) {
|
||||
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
|
||||
}
|
||||
time = time2;
|
||||
keyMap = nextMap;
|
||||
}
|
||||
timelines.add(timeline);
|
||||
} else if (timelineName == "sequence") {
|
||||
SequenceTimeline *timeline = new SequenceTimeline(frames, slotIndex, attachment);
|
||||
float lastDelay = 0;
|
||||
for (frame = 0; keyMap != NULL; keyMap = keyMap->_next, frame++) {
|
||||
float delay = Json::getFloat(keyMap, "delay", lastDelay);
|
||||
float time = Json::getFloat(keyMap, "time", 0);
|
||||
String modeString = Json::getString(keyMap, "mode", "hold");
|
||||
int index = Json::getInt(keyMap, "index", 0);
|
||||
SequenceMode mode = SequenceMode::hold;
|
||||
if (modeString == "once") mode = SequenceMode::once;
|
||||
if (modeString == "loop") mode = SequenceMode::loop;
|
||||
if (modeString == "pingpong") mode = SequenceMode::pingpong;
|
||||
if (modeString == "onceReverse") mode = SequenceMode::onceReverse;
|
||||
if (modeString == "loopReverse") mode = SequenceMode::loopReverse;
|
||||
if (modeString == "pingpongReverse") mode = SequenceMode::pingpongReverse;
|
||||
timeline->setFrame(frame, time, mode, index, delay);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
}
|
||||
timeline->setFrame(frame, time, deformed);
|
||||
nextMap = keyMap->_next;
|
||||
if (!nextMap) {
|
||||
// timeline.shrink(); // BOZO
|
||||
break;
|
||||
}
|
||||
float time2 = Json::getFloat(nextMap, "time", 0);
|
||||
curve = Json::getItem(keyMap, "curve");
|
||||
if (curve) {
|
||||
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
|
||||
}
|
||||
time = time2;
|
||||
keyMap = nextMap;
|
||||
}
|
||||
timelines.add(timeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,8 +103,8 @@ void Slot::setAttachment(Attachment *inValue) {
|
||||
!_attachment ||
|
||||
!inValue->getRTTI().instanceOf(VertexAttachment::rtti) ||
|
||||
!_attachment->getRTTI().instanceOf(VertexAttachment::rtti) ||
|
||||
static_cast<VertexAttachment *>(inValue)->getTimelineAttachment() !=
|
||||
static_cast<VertexAttachment *>(_attachment)->getTimelineAttachment()) {
|
||||
static_cast<VertexAttachment *>(inValue)->getTimelineAttachment() !=
|
||||
static_cast<VertexAttachment *>(_attachment)->getTimelineAttachment()) {
|
||||
_deform.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -150,7 +150,7 @@ void VertexAttachment::setWorldVerticesLength(size_t inValue) {
|
||||
_worldVerticesLength = inValue;
|
||||
}
|
||||
|
||||
Attachment * VertexAttachment::getTimelineAttachment() {
|
||||
Attachment *VertexAttachment::getTimelineAttachment() {
|
||||
return _timelineAttachment;
|
||||
}
|
||||
|
||||
|
||||
@ -2665,17 +2665,24 @@ namespace Spine {
|
||||
case SequenceMode.Loop:
|
||||
index %= count;
|
||||
break;
|
||||
case SequenceMode.Pingpong:
|
||||
case SequenceMode.Pingpong: {
|
||||
int n = (count << 1) - 2;
|
||||
index %= n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
case SequenceMode.OnceReverse:
|
||||
index = Math.Max(count - 1 - index, 0);
|
||||
break;
|
||||
case SequenceMode.LoopReverse:
|
||||
index = count - 1 - (index % count);
|
||||
break;
|
||||
case SequenceMode.PingpongReverse: {
|
||||
int n = (count << 1) - 2;
|
||||
index = (index + count - 1) % n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
} // end case
|
||||
}
|
||||
}
|
||||
slot.SequenceIndex = index;
|
||||
|
||||
@ -2494,16 +2494,22 @@ public class Animation {
|
||||
case loop:
|
||||
index %= count;
|
||||
break;
|
||||
case pingpong:
|
||||
case pingpong: {
|
||||
int n = (count << 1) - 2;
|
||||
index %= n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
case onceReverse:
|
||||
index = Math.max(count - 1 - index, 0);
|
||||
break;
|
||||
case loopReverse:
|
||||
index = count - 1 - (index % count);
|
||||
break;
|
||||
case pingpongReverse:
|
||||
int n = (count << 1) - 2;
|
||||
index = (index + count - 1) % n;
|
||||
if (index >= count) index = n - index;
|
||||
}
|
||||
}
|
||||
slot.setSequenceIndex(index);
|
||||
|
||||
@ -1351,6 +1351,9 @@ public class AnimationState {
|
||||
/** The interface to implement for receiving TrackEntry events. It is always safe to call AnimationState methods when receiving
|
||||
* events.
|
||||
* <p>
|
||||
* TrackEntry events are collected during {@link AnimationState#update(float)} and {@link AnimationState#apply(Skeleton)} and
|
||||
* fired only after those methods are finished.
|
||||
* <p>
|
||||
* See TrackEntry {@link TrackEntry#setListener(AnimationStateListener)} and AnimationState
|
||||
* {@link AnimationState#addListener(AnimationStateListener)}. */
|
||||
static public interface AnimationStateListener {
|
||||
|
||||
@ -645,13 +645,13 @@ int main() {
|
||||
SpineExtension::setInstance(&dbgExtension);
|
||||
|
||||
testcase(dragon, "data/dragon-ess.json", "data/dragon-ess.skel", "data/dragon-pma.atlas", 0.6f);
|
||||
testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f);
|
||||
testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
|
||||
testcase(ikDemo, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
|
||||
testcase(mixAndMatch, "data/mix-and-match-pro.json", "data/mix-and-match-pro.skel", "data/mix-and-match-pma.atlas", 0.5f);
|
||||
testcase(coin, "data/coin-pro.json", "data/coin-pro.skel", "data/coin-pma.atlas", 0.5f);
|
||||
testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
|
||||
testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
|
||||
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
|
||||
testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f);
|
||||
testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 0.2f);
|
||||
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
|
||||
testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f);
|
||||
|
||||
@ -77,7 +77,6 @@ namespace spine {
|
||||
}
|
||||
|
||||
void SkeletonDrawable::update(float deltaTime) {
|
||||
skeleton->update(deltaTime);
|
||||
state->update(deltaTime * timeScale);
|
||||
state->apply(*skeleton);
|
||||
skeleton->updateWorldTransform();
|
||||
@ -123,7 +122,7 @@ namespace spine {
|
||||
}
|
||||
|
||||
worldVertices.setSize(8, 0);
|
||||
regionAttachment->computeWorldVertices(slot.getBone(), worldVertices, 0, 2);
|
||||
regionAttachment->computeWorldVertices(slot, worldVertices, 0, 2);
|
||||
verticesCount = 4;
|
||||
uvs = ®ionAttachment->getUVs();
|
||||
indices = &quadIndices;
|
||||
@ -142,7 +141,7 @@ namespace spine {
|
||||
|
||||
worldVertices.setSize(mesh->getWorldVerticesLength(), 0);
|
||||
texture = (Texture *) ((AtlasRegion *) mesh->getRendererObject())->page->getRendererObject();
|
||||
mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices, 0, 2);
|
||||
mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices.buffer(), 0, 2);
|
||||
verticesCount = mesh->getWorldVerticesLength() >> 1;
|
||||
uvs = &mesh->getUVs();
|
||||
indices = &mesh->getTriangles();
|
||||
|
||||
@ -7,7 +7,7 @@ up into multiple modules:
|
||||
1. `spine-webgl/`, a self-contained WebGL backend, built on the core classes.
|
||||
1. `spine-canvas/`, a self-contained Canvas backend, built on the core classes.
|
||||
1. `spine-threejs/`, a self-contained THREE.JS backend, built on the core classes.
|
||||
1. `spine-player/`, a self-contained player to easily display Spine animations on your website, built on core the classes and WebGL backend.
|
||||
1. `spine-player/`, a self-contained player to easily display Spine animations on your website, built on the core classes and WebGL backend.
|
||||
|
||||
In most cases, the `spine-player` module is best suited for your needs. Please refer to the [Spine Web Player documentation](https://esotericsoftware.com/spine-player) for more information.
|
||||
|
||||
@ -104,6 +104,7 @@ spine-ts is developed with TypeScript, we thus recommend the following developme
|
||||
3. Open a terminal and execute
|
||||
```
|
||||
git clone https://github.com/esotericsoftware/spine-runtimes
|
||||
cd spine-runtimes/spine-ts
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
182
spine-ts/package-lock.json
generated
182
spine-ts/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-ts",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@esotericsoftware/spine-ts",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"workspaces": [
|
||||
"spine-core",
|
||||
@ -519,9 +519,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.3.0.tgz",
|
||||
"integrity": "sha512-k4k1jQGHHKsfbqzkUszVf29qECBrkvBKkcPJEUDTyVR7tZd1G/JOfnst4g1sYbFvJ4UjHZisj1aWQR8yLKpGPw==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.4.0.tgz",
|
||||
"integrity": "sha512-HZ3D0RTQMH3oS4gvtYj1P+NBc6PzE2McEra6yEFcQKrUQ9HvtTGU4Dbne083F034p+LRb7kWU0tPRNvSGs1UCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
@ -603,9 +603,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.25.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
|
||||
"integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w==",
|
||||
"version": "2.27.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.27.0.tgz",
|
||||
"integrity": "sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
@ -1100,16 +1100,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
|
||||
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.1.1",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -1125,9 +1125,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/http-parser-js": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz",
|
||||
"integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==",
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
|
||||
"integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
@ -1468,21 +1468,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.50.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz",
|
||||
"integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==",
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
|
||||
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.33",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz",
|
||||
"integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==",
|
||||
"version": "2.1.34",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
|
||||
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.50.0"
|
||||
"mime-db": "1.51.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -7101,9 +7101,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"version": "0.17.2",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
|
||||
"integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
@ -7113,9 +7113,9 @@
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"http-errors": "1.8.1",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
@ -7134,9 +7134,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/serve-index": {
|
||||
@ -7209,9 +7209,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/snapdragon": {
|
||||
@ -7667,9 +7667,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
@ -7691,9 +7691,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
|
||||
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
|
||||
"integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@ -7949,41 +7949,41 @@
|
||||
},
|
||||
"spine-canvas": {
|
||||
"name": "@esotericsoftware/spine-canvas",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.1.3"
|
||||
"@esotericsoftware/spine-core": "^4.1.5"
|
||||
}
|
||||
},
|
||||
"spine-core": {
|
||||
"name": "@esotericsoftware/spine-core",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"license": "LicenseRef-LICENSE"
|
||||
},
|
||||
"spine-player": {
|
||||
"name": "@esotericsoftware/spine-player",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-webgl": "^4.1.3"
|
||||
"@esotericsoftware/spine-webgl": "^4.1.5"
|
||||
}
|
||||
},
|
||||
"spine-threejs": {
|
||||
"name": "@esotericsoftware/spine-threejs",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.1.3",
|
||||
"@esotericsoftware/spine-core": "^4.1.5",
|
||||
"@types/three": "^0.133.1",
|
||||
"three": "^0.133.1"
|
||||
}
|
||||
},
|
||||
"spine-webgl": {
|
||||
"name": "@esotericsoftware/spine-webgl",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.1.4"
|
||||
"@esotericsoftware/spine-core": "^4.1.5"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -7991,7 +7991,7 @@
|
||||
"@esotericsoftware/spine-canvas": {
|
||||
"version": "file:spine-canvas",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-core": "^4.1.3"
|
||||
"@esotericsoftware/spine-core": "^4.1.5"
|
||||
}
|
||||
},
|
||||
"@esotericsoftware/spine-core": {
|
||||
@ -8000,13 +8000,13 @@
|
||||
"@esotericsoftware/spine-player": {
|
||||
"version": "file:spine-player",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-webgl": "^4.1.3"
|
||||
"@esotericsoftware/spine-webgl": "^4.1.5"
|
||||
}
|
||||
},
|
||||
"@esotericsoftware/spine-threejs": {
|
||||
"version": "file:spine-threejs",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-core": "^4.1.3",
|
||||
"@esotericsoftware/spine-core": "^4.1.5",
|
||||
"@types/three": "^0.133.1",
|
||||
"three": "^0.133.1"
|
||||
}
|
||||
@ -8014,7 +8014,7 @@
|
||||
"@esotericsoftware/spine-webgl": {
|
||||
"version": "file:spine-webgl",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-core": "^4.1.4"
|
||||
"@esotericsoftware/spine-core": "^4.1.5"
|
||||
}
|
||||
},
|
||||
"@types/offscreencanvas": {
|
||||
@ -8401,9 +8401,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"concurrently": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.3.0.tgz",
|
||||
"integrity": "sha512-k4k1jQGHHKsfbqzkUszVf29qECBrkvBKkcPJEUDTyVR7tZd1G/JOfnst4g1sYbFvJ4UjHZisj1aWQR8yLKpGPw==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.4.0.tgz",
|
||||
"integrity": "sha512-HZ3D0RTQMH3oS4gvtYj1P+NBc6PzE2McEra6yEFcQKrUQ9HvtTGU4Dbne083F034p+LRb7kWU0tPRNvSGs1UCQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
@ -8466,9 +8466,9 @@
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.25.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
|
||||
"integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w==",
|
||||
"version": "2.27.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.27.0.tgz",
|
||||
"integrity": "sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
@ -8861,16 +8861,16 @@
|
||||
}
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
|
||||
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.1.1",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
@ -8882,9 +8882,9 @@
|
||||
}
|
||||
},
|
||||
"http-parser-js": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz",
|
||||
"integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==",
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
|
||||
"integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
@ -9152,18 +9152,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.50.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz",
|
||||
"integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==",
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
|
||||
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.33",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz",
|
||||
"integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==",
|
||||
"version": "2.1.34",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
|
||||
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.50.0"
|
||||
"mime-db": "1.51.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
@ -13563,9 +13563,9 @@
|
||||
}
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"version": "0.17.2",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
|
||||
"integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
@ -13575,9 +13575,9 @@
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"http-errors": "1.8.1",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
@ -13590,9 +13590,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@ -13657,9 +13657,9 @@
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
|
||||
"dev": true
|
||||
},
|
||||
"snapdragon": {
|
||||
@ -14041,9 +14041,9 @@
|
||||
}
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
|
||||
"dev": true
|
||||
},
|
||||
"tree-kill": {
|
||||
@ -14059,9 +14059,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
|
||||
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
|
||||
"integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-ts",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"files": [
|
||||
"README.md"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-canvas",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -30,6 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.1.3"
|
||||
"@esotericsoftware/spine-core": "^4.1.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-core",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -42,8 +42,8 @@ import { SequenceMode, SequenceModeValues } from "./attachments/Sequence";
|
||||
export class Animation {
|
||||
/** The animation's name, which is unique across all animations in the skeleton. */
|
||||
name: string;
|
||||
timelines: Array<Timeline>;
|
||||
timelineIds: StringSet;
|
||||
timelines: Array<Timeline> = null;
|
||||
timelineIds: StringSet = null;
|
||||
|
||||
/** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */
|
||||
duration: number;
|
||||
@ -155,8 +155,8 @@ const Property = {
|
||||
|
||||
/** The interface for all timelines. */
|
||||
export abstract class Timeline {
|
||||
propertyIds: string[];
|
||||
frames: NumberArrayLike;
|
||||
propertyIds: string[] = null;
|
||||
frames: NumberArrayLike = null;
|
||||
|
||||
constructor (frameCount: number, propertyIds: string[]) {
|
||||
this.propertyIds = propertyIds;
|
||||
@ -208,7 +208,7 @@ export interface SlotTimeline {
|
||||
|
||||
/** The base class for timelines that use interpolation between key frame values. */
|
||||
export abstract class CurveTimeline extends Timeline {
|
||||
protected curves: NumberArrayLike; // type, x, y, ...
|
||||
protected curves: NumberArrayLike = null; // type, x, y, ...
|
||||
|
||||
constructor (frameCount: number, bezierCount: number, propertyIds: string[]) {
|
||||
super(frameCount, propertyIds);
|
||||
@ -1430,10 +1430,10 @@ export class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
||||
slotIndex = 0;
|
||||
|
||||
/** The attachment that will be deformed. */
|
||||
attachment: VertexAttachment;
|
||||
attachment: VertexAttachment = null;
|
||||
|
||||
/** The vertices for each key frame. */
|
||||
vertices: Array<NumberArrayLike>;
|
||||
vertices: Array<NumberArrayLike> = null;
|
||||
|
||||
constructor (frameCount: number, bezierCount: number, slotIndex: number, attachment: VertexAttachment) {
|
||||
super(frameCount, bezierCount, [
|
||||
@ -1685,7 +1685,7 @@ export class EventTimeline extends Timeline {
|
||||
static propertyIds = ["" + Property.event];
|
||||
|
||||
/** The event for each key frame. */
|
||||
events: Array<Event>;
|
||||
events: Array<Event> = null;
|
||||
|
||||
constructor (frameCount: number) {
|
||||
super(frameCount, EventTimeline.propertyIds);
|
||||
@ -1738,7 +1738,7 @@ export class DrawOrderTimeline extends Timeline {
|
||||
static propertyIds = ["" + Property.drawOrder];
|
||||
|
||||
/** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */
|
||||
drawOrders: Array<Array<number>>;
|
||||
drawOrders: Array<Array<number>> = null;
|
||||
|
||||
constructor (frameCount: number) {
|
||||
super(frameCount, DrawOrderTimeline.propertyIds);
|
||||
@ -1784,7 +1784,7 @@ export class DrawOrderTimeline extends Timeline {
|
||||
* {@link IkConstraint#bendDirection}, {@link IkConstraint#stretch}, and {@link IkConstraint#compress}. */
|
||||
export class IkConstraintTimeline extends CurveTimeline {
|
||||
/** The index of the IK constraint slot in {@link Skeleton#ikConstraints} that will be changed. */
|
||||
ikConstraintIndex: number;
|
||||
ikConstraintIndex: number = 0;
|
||||
|
||||
constructor (frameCount: number, bezierCount: number, ikConstraintIndex: number) {
|
||||
super(frameCount, bezierCount, [
|
||||
@ -1882,7 +1882,7 @@ export class IkConstraintTimeline extends CurveTimeline {
|
||||
* {@link TransformConstraint#scaleMix}, and {@link TransformConstraint#shearMix}. */
|
||||
export class TransformConstraintTimeline extends CurveTimeline {
|
||||
/** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */
|
||||
transformConstraintIndex: number;
|
||||
transformConstraintIndex: number = 0;
|
||||
|
||||
constructor (frameCount: number, bezierCount: number, transformConstraintIndex: number) {
|
||||
super(frameCount, bezierCount, [
|
||||
@ -1995,7 +1995,7 @@ export class TransformConstraintTimeline extends CurveTimeline {
|
||||
/** Changes a path constraint's {@link PathConstraint#position}. */
|
||||
export class PathConstraintPositionTimeline extends CurveTimeline1 {
|
||||
/** The index of the path constraint slot in {@link Skeleton#pathConstraints} that will be changed. */
|
||||
pathConstraintIndex: number;
|
||||
pathConstraintIndex: number = 0;
|
||||
|
||||
constructor (frameCount: number, bezierCount: number, pathConstraintIndex: number) {
|
||||
super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex);
|
||||
@ -2218,16 +2218,23 @@ export class SequenceTimeline extends Timeline implements SlotTimeline {
|
||||
case SequenceMode.loop:
|
||||
index %= count;
|
||||
break;
|
||||
case SequenceMode.pingpong:
|
||||
case SequenceMode.pingpong: {
|
||||
let n = (count << 1) - 2;
|
||||
index %= n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
case SequenceMode.onceReverse:
|
||||
index = Math.max(count - 1 - index, 0);
|
||||
break;
|
||||
case SequenceMode.loopReverse:
|
||||
index = count - 1 - (index % count);
|
||||
break;
|
||||
case SequenceMode.pingpongReverse: {
|
||||
let n = (count << 1) - 2;
|
||||
index = (index + count - 1) % n;
|
||||
if (index >= count) index = n - index;
|
||||
}
|
||||
}
|
||||
}
|
||||
slot.sequenceIndex = index;
|
||||
|
||||
@ -46,7 +46,7 @@ export class AnimationState {
|
||||
}
|
||||
|
||||
/** The AnimationStateData to look up mix durations. */
|
||||
data: AnimationStateData;
|
||||
data: AnimationStateData = null;
|
||||
|
||||
/** The list of tracks that currently have animations, which may contain null entries. */
|
||||
tracks = new Array<TrackEntry>();
|
||||
@ -645,6 +645,7 @@ export class AnimationState {
|
||||
/** @param last May be null. */
|
||||
trackEntry (trackIndex: number, animation: Animation, loop: boolean, last: TrackEntry) {
|
||||
let entry = this.trackEntryPool.obtain();
|
||||
entry.reset();
|
||||
entry.trackIndex = trackIndex;
|
||||
entry.animation = animation;
|
||||
entry.loop = loop;
|
||||
@ -777,35 +778,35 @@ export class AnimationState {
|
||||
* 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;
|
||||
animation: Animation = null;
|
||||
|
||||
previous: TrackEntry;
|
||||
previous: TrackEntry = null;
|
||||
|
||||
/** The animation queued to start after this animation, or null. `next` makes up a linked list. */
|
||||
next: TrackEntry;
|
||||
next: TrackEntry = null;
|
||||
|
||||
/** 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;
|
||||
mixingFrom: TrackEntry = null;
|
||||
|
||||
/** 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;
|
||||
mixingTo: TrackEntry = null;
|
||||
|
||||
/** 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;
|
||||
listener: AnimationStateListener = null;
|
||||
|
||||
/** The index of the track where this track entry is either current or queued.
|
||||
*
|
||||
* See {@link AnimationState#getCurrent()}. */
|
||||
trackIndex: number;
|
||||
trackIndex: number = 0;
|
||||
|
||||
/** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
|
||||
* duration. */
|
||||
loop: boolean;
|
||||
loop: boolean = false;
|
||||
|
||||
/** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead
|
||||
* of being mixed out.
|
||||
@ -818,43 +819,43 @@ export class TrackEntry {
|
||||
*
|
||||
* Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the
|
||||
* previous animation. */
|
||||
holdPrevious: boolean;
|
||||
holdPrevious: boolean = false;
|
||||
|
||||
reverse: boolean;
|
||||
reverse: boolean = false;
|
||||
|
||||
/** 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;
|
||||
eventThreshold: number = 0;
|
||||
|
||||
/** 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;
|
||||
attachmentThreshold: number = 0;
|
||||
|
||||
/** 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;
|
||||
drawOrderThreshold: number = 0;
|
||||
|
||||
/** 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;
|
||||
animationStart: number = 0;
|
||||
|
||||
/** 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;
|
||||
animationEnd: number = 0;
|
||||
|
||||
|
||||
/** 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;
|
||||
animationLast: number = 0;
|
||||
|
||||
nextAnimationLast: number;
|
||||
nextAnimationLast: number = 0;
|
||||
|
||||
/** 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
|
||||
@ -862,14 +863,14 @@ export class TrackEntry {
|
||||
* track entry {@link TrackEntry#trackTime} >= this track entry's `delay`).
|
||||
*
|
||||
* {@link #timeScale} affects the delay. */
|
||||
delay: number;
|
||||
delay: number = 0;
|
||||
|
||||
/** 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;
|
||||
trackTime: number = 0;
|
||||
|
||||
trackLast: number; nextTrackLast: number;
|
||||
trackLast: number = 0; nextTrackLast: number = 0;
|
||||
|
||||
/** 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
|
||||
@ -878,7 +879,7 @@ export class TrackEntry {
|
||||
*
|
||||
* It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation
|
||||
* abruptly cease being applied. */
|
||||
trackEnd: number;
|
||||
trackEnd: number = 0;
|
||||
|
||||
/** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or
|
||||
* faster. Defaults to 1.
|
||||
@ -891,18 +892,18 @@ export class TrackEntry {
|
||||
* the time scale is not 1, the delay may need to be adjusted.
|
||||
*
|
||||
* See AnimationState {@link AnimationState#timeScale} for affecting all animations. */
|
||||
timeScale: number;
|
||||
timeScale: number = 0;
|
||||
|
||||
/** 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;
|
||||
alpha: number = 0;
|
||||
|
||||
/** 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;
|
||||
mixTime: number = 0;
|
||||
|
||||
/** 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).
|
||||
@ -917,7 +918,7 @@ export class TrackEntry {
|
||||
* 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;
|
||||
mixDuration: number = 0; interruptAlpha: number = 0; totalAlpha: number = 0;
|
||||
|
||||
/** 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
|
||||
@ -990,7 +991,7 @@ export class TrackEntry {
|
||||
export class EventQueue {
|
||||
objects: Array<any> = [];
|
||||
drainDisabled = false;
|
||||
animState: AnimationState;
|
||||
animState: AnimationState = null;
|
||||
|
||||
constructor (animState: AnimationState) {
|
||||
this.animState = animState;
|
||||
|
||||
@ -35,7 +35,7 @@ import { StringMap } from "./Utils";
|
||||
/** 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;
|
||||
skeletonData: SkeletonData = null;
|
||||
|
||||
animationToMixTime: StringMap<number> = {};
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ import { TextureAtlas } from "./TextureAtlas";
|
||||
import { Disposable, StringMap } from "./Utils";
|
||||
|
||||
export class AssetManagerBase implements Disposable {
|
||||
private pathPrefix: string;
|
||||
private pathPrefix: string = null;
|
||||
private textureLoader: (image: HTMLImageElement | ImageBitmap) => Texture;
|
||||
private downloader: Downloader;
|
||||
private assets: StringMap<any> = {};
|
||||
|
||||
@ -43,7 +43,7 @@ import { Sequence } from "./attachments/Sequence"
|
||||
* 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;
|
||||
atlas: TextureAtlas = null;
|
||||
|
||||
constructor (atlas: TextureAtlas) {
|
||||
this.atlas = atlas;
|
||||
|
||||
@ -39,13 +39,13 @@ import { MathUtils, Vector2 } from "./Utils";
|
||||
* 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;
|
||||
data: BoneData = null;
|
||||
|
||||
/** The skeleton this bone belongs to. */
|
||||
skeleton: Skeleton;
|
||||
skeleton: Skeleton = null;
|
||||
|
||||
/** The parent bone, or null if this is the root bone. */
|
||||
parent: Bone;
|
||||
parent: Bone = null;
|
||||
|
||||
/** The immediate children of this bone. */
|
||||
children = new Array<Bone>();
|
||||
|
||||
@ -32,16 +32,16 @@ import { Color } from "./Utils";
|
||||
/** Stores the setup pose for a {@link Bone}. */
|
||||
export class BoneData {
|
||||
/** The index of the bone in {@link Skeleton#getBones()}. */
|
||||
index: number;
|
||||
index: number = 0;
|
||||
|
||||
/** The name of the bone, which is unique across all bones in the skeleton. */
|
||||
name: string;
|
||||
name: string = null;
|
||||
|
||||
/** @returns May be null. */
|
||||
parent: BoneData;
|
||||
parent: BoneData = null;
|
||||
|
||||
/** The bone's length. */
|
||||
length: number;
|
||||
length: number = 0;
|
||||
|
||||
/** The local x translation. */
|
||||
x = 0;
|
||||
|
||||
@ -35,13 +35,13 @@ import { EventData } from "./EventData";
|
||||
* AnimationStateListener {@link AnimationStateListener#event()}, and
|
||||
* [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */
|
||||
export class Event {
|
||||
data: EventData;
|
||||
intValue: number;
|
||||
floatValue: number;
|
||||
stringValue: string;
|
||||
time: number;
|
||||
volume: number;
|
||||
balance: number;
|
||||
data: EventData = null;
|
||||
intValue: number = 0;
|
||||
floatValue: number = 0;
|
||||
stringValue: string = null;
|
||||
time: number = 0;
|
||||
volume: number = 0;
|
||||
balance: number = 0;
|
||||
|
||||
constructor (time: number, data: EventData) {
|
||||
if (!data) throw new Error("data cannot be null.");
|
||||
|
||||
@ -31,13 +31,13 @@
|
||||
*
|
||||
* See [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */
|
||||
export class EventData {
|
||||
name: string;
|
||||
intValue: number;
|
||||
floatValue: number;
|
||||
stringValue: string;
|
||||
audioPath: string;
|
||||
volume: number;
|
||||
balance: number;
|
||||
name: string = null;
|
||||
intValue: number = 0;
|
||||
floatValue: number = 0;
|
||||
stringValue: string = null;
|
||||
audioPath: string = null;
|
||||
volume: number = 0;
|
||||
balance: number = 0;
|
||||
|
||||
constructor (name: string) {
|
||||
this.name = name;
|
||||
|
||||
@ -40,13 +40,13 @@ import { MathUtils } from "./Utils";
|
||||
* 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;
|
||||
data: IkConstraintData = null;
|
||||
|
||||
/** The bones that will be modified by this IK constraint. */
|
||||
bones: Array<Bone>;
|
||||
bones: Array<Bone> = null;
|
||||
|
||||
/** The bone that is the IK target. */
|
||||
target: Bone;
|
||||
target: Bone = null;
|
||||
|
||||
/** Controls the bend direction of the IK bones, either 1 or -1. */
|
||||
bendDirection = 0;
|
||||
|
||||
@ -39,7 +39,7 @@ export class IkConstraintData extends ConstraintData {
|
||||
bones = new Array<BoneData>();
|
||||
|
||||
/** The bone that is the IK target. */
|
||||
target: BoneData;
|
||||
target: BoneData = null;
|
||||
|
||||
/** Controls the bend direction of the IK bones, either 1 or -1. */
|
||||
bendDirection = 1;
|
||||
|
||||
@ -45,13 +45,13 @@ export class PathConstraint implements Updatable {
|
||||
static epsilon = 0.00001;
|
||||
|
||||
/** The path constraint's setup pose data. */
|
||||
data: PathConstraintData;
|
||||
data: PathConstraintData = null;
|
||||
|
||||
/** The bones that will be modified by this path constraint. */
|
||||
bones: Array<Bone>;
|
||||
bones: Array<Bone> = null;
|
||||
|
||||
/** The slot whose path attachment will be used to constrained the bones. */
|
||||
target: Slot;
|
||||
target: Slot = null;
|
||||
|
||||
/** The position along the path. */
|
||||
position = 0;
|
||||
|
||||
@ -41,25 +41,25 @@ export class PathConstraintData extends ConstraintData {
|
||||
bones = new Array<BoneData>();
|
||||
|
||||
/** The slot whose path attachment will be used to constrained the bones. */
|
||||
target: SlotData;
|
||||
target: SlotData = null;
|
||||
|
||||
/** The mode for positioning the first bone on the path. */
|
||||
positionMode: PositionMode;
|
||||
positionMode: PositionMode = null;
|
||||
|
||||
/** The mode for positioning the bones after the first bone on the path. */
|
||||
spacingMode: SpacingMode;
|
||||
spacingMode: SpacingMode = null;
|
||||
|
||||
/** The mode for adjusting the rotation of the bones. */
|
||||
rotateMode: RotateMode;
|
||||
rotateMode: RotateMode = null;
|
||||
|
||||
/** An offset added to the constrained bone rotation. */
|
||||
offsetRotation: number;
|
||||
offsetRotation: number = 0;
|
||||
|
||||
/** The position along the path. */
|
||||
position: number;
|
||||
position: number = 0;
|
||||
|
||||
/** The spacing between bones. */
|
||||
spacing: number;
|
||||
spacing: number = 0;
|
||||
|
||||
mixRotate = 0;
|
||||
mixX = 0;
|
||||
|
||||
@ -46,34 +46,34 @@ import { Color, Utils, MathUtils, Vector2, NumberArrayLike } from "./Utils";
|
||||
* 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;
|
||||
data: SkeletonData = null;
|
||||
|
||||
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
|
||||
bones: Array<Bone>;
|
||||
bones: Array<Bone> = null;
|
||||
|
||||
/** The skeleton's slots. */
|
||||
slots: Array<Slot>;
|
||||
slots: Array<Slot> = null;
|
||||
|
||||
/** 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>;
|
||||
drawOrder: Array<Slot> = null;
|
||||
|
||||
/** The skeleton's IK constraints. */
|
||||
ikConstraints: Array<IkConstraint>;
|
||||
ikConstraints: Array<IkConstraint> = null;
|
||||
|
||||
/** The skeleton's transform constraints. */
|
||||
transformConstraints: Array<TransformConstraint>;
|
||||
transformConstraints: Array<TransformConstraint> = null;
|
||||
|
||||
/** The skeleton's path constraints. */
|
||||
pathConstraints: Array<PathConstraint>;
|
||||
pathConstraints: Array<PathConstraint> = null;
|
||||
|
||||
/** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */
|
||||
_updateCache = new Array<Updatable>();
|
||||
|
||||
/** The skeleton's current skin. May be null. */
|
||||
skin: Skin;
|
||||
skin: Skin = null;
|
||||
|
||||
/** The color to tint all the skeleton's attachments. */
|
||||
color: Color;
|
||||
color: Color = null;
|
||||
|
||||
/** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale
|
||||
* inheritance. */
|
||||
|
||||
@ -56,7 +56,7 @@ export class SkeletonBinary {
|
||||
* See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */
|
||||
scale = 1;
|
||||
|
||||
attachmentLoader: AttachmentLoader;
|
||||
attachmentLoader: AttachmentLoader = null;
|
||||
private linkedMeshes = new Array<LinkedMesh>();
|
||||
|
||||
constructor (attachmentLoader: AttachmentLoader) {
|
||||
|
||||
@ -43,7 +43,7 @@ import { TransformConstraintData } from "./TransformConstraintData";
|
||||
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;
|
||||
name: string = null;
|
||||
|
||||
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
|
||||
bones = new Array<BoneData>(); // Ordered parents first.
|
||||
@ -56,7 +56,7 @@ export class SkeletonData {
|
||||
*
|
||||
* See {@link Skeleton#getAttachmentByName()}.
|
||||
* May be null. */
|
||||
defaultSkin: Skin;
|
||||
defaultSkin: Skin = null;
|
||||
|
||||
/** The skeleton's events. */
|
||||
events = new Array<EventData>();
|
||||
@ -74,32 +74,32 @@ export class SkeletonData {
|
||||
pathConstraints = new Array<PathConstraintData>();
|
||||
|
||||
/** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */
|
||||
x: number;
|
||||
x: number = 0;
|
||||
|
||||
/** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */
|
||||
y: number;
|
||||
y: number = 0;
|
||||
|
||||
/** The width of the skeleton's axis aligned bounding box in the setup pose. */
|
||||
width: number;
|
||||
width: number = 0;
|
||||
|
||||
/** The height of the skeleton's axis aligned bounding box in the setup pose. */
|
||||
height: number;
|
||||
height: number = 0;
|
||||
|
||||
/** The Spine version used to export the skeleton data, or null. */
|
||||
version: string;
|
||||
version: string = null;
|
||||
|
||||
/** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */
|
||||
hash: string;
|
||||
hash: string = null;
|
||||
|
||||
// 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;
|
||||
imagesPath: string = null;
|
||||
|
||||
/** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */
|
||||
audioPath: string;
|
||||
audioPath: string = null;
|
||||
|
||||
/** 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.
|
||||
|
||||
@ -51,7 +51,7 @@ import { HasTextureRegion } from "./attachments/HasTextureRegion";
|
||||
* [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;
|
||||
attachmentLoader: AttachmentLoader = null;
|
||||
|
||||
/** 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.
|
||||
|
||||
@ -36,7 +36,7 @@ import { StringMap } from "./Utils";
|
||||
|
||||
/** 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) { }
|
||||
constructor (public slotIndex: number = 0, public name: string = null, public attachment: Attachment = null) { }
|
||||
}
|
||||
|
||||
/** Stores attachments by slot index and attachment name.
|
||||
@ -45,7 +45,7 @@ export class SkinEntry {
|
||||
* [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;
|
||||
name: string = null;
|
||||
|
||||
attachments = new Array<StringMap<Attachment>>();
|
||||
bones = Array<BoneData>();
|
||||
|
||||
@ -38,22 +38,22 @@ import { Color } from "./Utils";
|
||||
* across multiple skeletons. */
|
||||
export class Slot {
|
||||
/** The slot's setup pose data. */
|
||||
data: SlotData;
|
||||
data: SlotData = null;
|
||||
|
||||
/** The bone this slot belongs to. */
|
||||
bone: Bone;
|
||||
bone: Bone = null;
|
||||
|
||||
/** 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;
|
||||
color: Color = null;
|
||||
|
||||
/** 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;
|
||||
darkColor: Color = null;
|
||||
|
||||
attachment: Attachment;
|
||||
attachment: Attachment = null;
|
||||
|
||||
attachmentState: number;
|
||||
attachmentState: number = 0;
|
||||
|
||||
/** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the
|
||||
* {@link Sequence#getSetupIndex()}. */
|
||||
|
||||
@ -33,13 +33,13 @@ import { Color } from "./Utils";
|
||||
/** Stores the setup pose for a {@link Slot}. */
|
||||
export class SlotData {
|
||||
/** The index of the slot in {@link Skeleton#getSlots()}. */
|
||||
index: number;
|
||||
index: number = 0;
|
||||
|
||||
/** The name of the slot, which is unique across all slots in the skeleton. */
|
||||
name: string;
|
||||
name: string = null;
|
||||
|
||||
/** The bone this slot belongs to. */
|
||||
boneData: BoneData;
|
||||
boneData: BoneData = null;
|
||||
|
||||
/** 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. */
|
||||
@ -47,13 +47,13 @@ export class SlotData {
|
||||
|
||||
/** 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;
|
||||
darkColor: Color = null;
|
||||
|
||||
/** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */
|
||||
attachmentName: string;
|
||||
attachmentName: string = null;
|
||||
|
||||
/** The blend mode for drawing the slot's attachment. */
|
||||
blendMode: BlendMode;
|
||||
blendMode: BlendMode = null;
|
||||
|
||||
constructor (index: number, name: string, boneData: BoneData) {
|
||||
if (index < 0) throw new Error("index must be >= 0.");
|
||||
|
||||
@ -198,7 +198,7 @@ export class TextureAtlas implements Disposable {
|
||||
}
|
||||
|
||||
class TextureAtlasReader {
|
||||
lines: Array<string>;
|
||||
lines: Array<string> = null;
|
||||
index: number = 0;
|
||||
|
||||
constructor (text: string) {
|
||||
@ -233,15 +233,15 @@ class TextureAtlasReader {
|
||||
}
|
||||
|
||||
export class TextureAtlasPage {
|
||||
name: string;
|
||||
name: string = null;
|
||||
minFilter: TextureFilter = TextureFilter.Nearest;
|
||||
magFilter: TextureFilter = TextureFilter.Nearest;
|
||||
uWrap: TextureWrap = TextureWrap.ClampToEdge;
|
||||
vWrap: TextureWrap = TextureWrap.ClampToEdge;
|
||||
texture: Texture;
|
||||
width: number;
|
||||
height: number;
|
||||
pma: boolean;
|
||||
texture: Texture = null;
|
||||
width: number = 0;
|
||||
height: number = 0;
|
||||
pma: boolean = false;
|
||||
|
||||
setTexture (texture: Texture) {
|
||||
this.texture = texture;
|
||||
@ -251,16 +251,16 @@ export class TextureAtlasPage {
|
||||
}
|
||||
|
||||
export class TextureAtlasRegion extends TextureRegion {
|
||||
page: TextureAtlasPage;
|
||||
name: string;
|
||||
x: number;
|
||||
y: number;
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
originalWidth: number;
|
||||
originalHeight: number;
|
||||
index: number;
|
||||
degrees: number;
|
||||
names: string[];
|
||||
values: number[][];
|
||||
page: TextureAtlasPage = null;
|
||||
name: string = null;
|
||||
x: number = 0;
|
||||
y: number = 0;
|
||||
offsetX: number = 0;
|
||||
offsetY: number = 0;
|
||||
originalWidth: number = 0;
|
||||
originalHeight: number = 0;
|
||||
index: number = 0;
|
||||
degrees: number = 0;
|
||||
names: string[] = null;
|
||||
values: number[][] = null;
|
||||
}
|
||||
|
||||
@ -41,13 +41,13 @@ import { Vector2, MathUtils } from "./Utils";
|
||||
export class TransformConstraint implements Updatable {
|
||||
|
||||
/** The transform constraint's setup pose data. */
|
||||
data: TransformConstraintData;
|
||||
data: TransformConstraintData = null;
|
||||
|
||||
/** The bones that will be modified by this transform constraint. */
|
||||
bones: Array<Bone>;
|
||||
bones: Array<Bone> = null;
|
||||
|
||||
/** The target bone whose world transform will be copied to the constrained bones. */
|
||||
target: Bone;
|
||||
target: Bone = null;
|
||||
|
||||
mixRotate = 0; mixX = 0; mixY = 0; mixScaleX = 0; mixScaleY = 0; mixShearY = 0;
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ export class TransformConstraintData extends ConstraintData {
|
||||
bones = new Array<BoneData>();
|
||||
|
||||
/** The target bone whose world transform will be copied to the constrained bones. */
|
||||
target: BoneData;
|
||||
target: BoneData = null;
|
||||
|
||||
mixRotate = 0;
|
||||
mixX = 0;
|
||||
|
||||
@ -53,12 +53,12 @@ export abstract class VertexAttachment extends Attachment {
|
||||
/** 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>;
|
||||
bones: Array<number> = null;
|
||||
|
||||
/** 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: NumberArrayLike;
|
||||
vertices: NumberArrayLike = null;
|
||||
|
||||
/** The maximum number of world vertex values that can be output by
|
||||
* {@link #computeWorldVertices()} using the `count` parameter. */
|
||||
|
||||
@ -35,7 +35,7 @@ import { VertexAttachment, Attachment } from "./Attachment";
|
||||
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;
|
||||
endSlot: SlotData = null;
|
||||
|
||||
// Nonessential.
|
||||
/** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons
|
||||
|
||||
@ -40,41 +40,41 @@ import { Slot } from "../Slot";
|
||||
*
|
||||
* See [Mesh attachments](http://esotericsoftware.com/spine-meshes) in the Spine User Guide. */
|
||||
export class MeshAttachment extends VertexAttachment implements HasTextureRegion {
|
||||
region: TextureRegion;
|
||||
region: TextureRegion = null;
|
||||
|
||||
/** The name of the texture region for this attachment. */
|
||||
path: string;
|
||||
path: string = null;
|
||||
|
||||
/** The UV pair for each vertex, normalized within the texture region. */
|
||||
regionUVs: NumberArrayLike;
|
||||
regionUVs: NumberArrayLike = null;
|
||||
|
||||
/** The UV pair for each vertex, normalized within the entire texture.
|
||||
*
|
||||
* See {@link #updateUVs}. */
|
||||
uvs: NumberArrayLike;
|
||||
uvs: NumberArrayLike = null;
|
||||
|
||||
/** Triplets of vertex indices which describe the mesh's triangulation. */
|
||||
triangles: Array<number>;
|
||||
triangles: Array<number> = null;
|
||||
|
||||
/** 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;
|
||||
width: number = 0;
|
||||
|
||||
/** The height of the mesh's image. Available only when nonessential data was exported. */
|
||||
height: number;
|
||||
height: number = 0;
|
||||
|
||||
/** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */
|
||||
hullLength: number;
|
||||
hullLength: number = 0;
|
||||
|
||||
/** 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>;
|
||||
edges: Array<number> = null;
|
||||
|
||||
private parentMesh: MeshAttachment;
|
||||
private parentMesh: MeshAttachment = null;
|
||||
|
||||
sequence: Sequence;
|
||||
sequence: Sequence = null;
|
||||
|
||||
tempColor = new Color(0, 0, 0, 0);
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ import { VertexAttachment, Attachment } from "./Attachment";
|
||||
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>;
|
||||
lengths: Array<number> = null;
|
||||
|
||||
/** If true, the start and end knots are connected. */
|
||||
closed = false;
|
||||
|
||||
@ -37,7 +37,9 @@ import { VertexAttachment, Attachment } from "./Attachment";
|
||||
*
|
||||
* 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;
|
||||
x: number = 0;
|
||||
y: number = 0;
|
||||
rotation: number = 0;
|
||||
|
||||
/** 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. */
|
||||
|
||||
@ -64,11 +64,11 @@ export class RegionAttachment extends Attachment implements HasTextureRegion {
|
||||
color = new Color(1, 1, 1, 1);
|
||||
|
||||
/** The name of the texture region for this attachment. */
|
||||
path: string;
|
||||
path: string = null;
|
||||
|
||||
private rendererObject: any;
|
||||
region: TextureRegion;
|
||||
sequence: Sequence;
|
||||
private rendererObject: any = null;
|
||||
region: TextureRegion = null;
|
||||
sequence: Sequence = null;
|
||||
|
||||
/** For each of the 4 vertices, a pair of <code>x,y</code> values that is the local position of the vertex.
|
||||
*
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-player",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -30,6 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-webgl": "^4.1.3"
|
||||
"@esotericsoftware/spine-webgl": "^4.1.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-threejs",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -32,6 +32,6 @@
|
||||
"dependencies": {
|
||||
"@types/three": "^0.133.1",
|
||||
"three": "^0.133.1",
|
||||
"@esotericsoftware/spine-core": "^4.1.3"
|
||||
"@esotericsoftware/spine-core": "^4.1.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-webgl",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.5",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -30,6 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.1.4"
|
||||
"@esotericsoftware/spine-core": "^4.1.5"
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,8 @@
|
||||
],
|
||||
"declaration": true,
|
||||
"composite": true,
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "node"
|
||||
/*"strictNullChecks": true,
|
||||
"strictPropertyInitialization": true*/
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -45,12 +45,17 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
static int brushNameId = 0;
|
||||
|
||||
// Workaround for https://github.com/EsotericSoftware/spine-runtimes/issues/1458
|
||||
// See issue comments for more information.
|
||||
struct SpineSlateMaterialBrush : public FSlateBrush {
|
||||
SpineSlateMaterialBrush(class UMaterialInterface &InMaterial, const FVector2D &InImageSize)
|
||||
: FSlateBrush(ESlateBrushDrawType::Image, FName(TEXT("None")), FMargin(0), ESlateBrushTileType::NoTile, ESlateBrushImageType::FullColor, InImageSize, FLinearColor::White, &InMaterial) {
|
||||
ResourceName = FName(*InMaterial.GetFullName());
|
||||
// Workaround for https://github.com/EsotericSoftware/spine-runtimes/issues/2006
|
||||
FString brushName = TEXT("spineslatebrush");
|
||||
brushName.AppendInt(brushNameId++);
|
||||
ResourceName = FName(brushName);
|
||||
}
|
||||
};
|
||||
|
||||
@ -269,7 +274,7 @@ void SSpineWidget::UpdateMesh(int32 LayerId, FSlateWindowElementList &OutDrawEle
|
||||
RegionAttachment *regionAttachment = (RegionAttachment *) attachment;
|
||||
attachmentColor.set(regionAttachment->getColor());
|
||||
attachmentAtlasRegion = (AtlasRegion *) regionAttachment->getRendererObject();
|
||||
regionAttachment->computeWorldVertices(slot->getBone(), *attachmentVertices, 0, 2);
|
||||
regionAttachment->computeWorldVertices(*slot, *attachmentVertices, 0, 2);
|
||||
attachmentIndices = quadIndices;
|
||||
attachmentUvs = regionAttachment->getUVs().buffer();
|
||||
numVertices = 4;
|
||||
@ -278,7 +283,7 @@ void SSpineWidget::UpdateMesh(int32 LayerId, FSlateWindowElementList &OutDrawEle
|
||||
MeshAttachment *mesh = (MeshAttachment *) attachment;
|
||||
attachmentColor.set(mesh->getColor());
|
||||
attachmentAtlasRegion = (AtlasRegion *) mesh->getRendererObject();
|
||||
mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), *attachmentVertices, 0, 2);
|
||||
mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), attachmentVertices->buffer(), 0, 2);
|
||||
attachmentIndices = mesh->getTriangles().buffer();
|
||||
attachmentUvs = mesh->getUVs().buffer();
|
||||
numVertices = mesh->getWorldVerticesLength() >> 1;
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
using namespace spine;
|
||||
|
||||
#define SPINE_MAJOR_VERSION 4
|
||||
#define SPINE_MINOR_VERSION 0
|
||||
#define SPINE_MINOR_VERSION 1
|
||||
|
||||
FName USpineSkeletonDataAsset::GetSkeletonDataFileName() const {
|
||||
#if WITH_EDITORONLY_DATA
|
||||
@ -100,11 +100,11 @@ void USpineSkeletonDataAsset::BeginDestroy() {
|
||||
|
||||
class SP_API NullAttachmentLoader : public AttachmentLoader {
|
||||
public:
|
||||
virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path) {
|
||||
virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) {
|
||||
return new (__FILE__, __LINE__) RegionAttachment(name);
|
||||
}
|
||||
|
||||
virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path) {
|
||||
virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) {
|
||||
return new (__FILE__, __LINE__) MeshAttachment(name);
|
||||
}
|
||||
|
||||
|
||||
@ -226,7 +226,7 @@ void USpineSkeletonRendererComponent::UpdateMesh(Skeleton *Skeleton) {
|
||||
|
||||
attachmentColor.set(regionAttachment->getColor());
|
||||
attachmentAtlasRegion = (AtlasRegion *) regionAttachment->getRendererObject();
|
||||
regionAttachment->computeWorldVertices(slot->getBone(), *attachmentVertices, 0, 2);
|
||||
regionAttachment->computeWorldVertices(*slot, *attachmentVertices, 0, 2);
|
||||
attachmentIndices = quadIndices;
|
||||
attachmentUvs = regionAttachment->getUVs().buffer();
|
||||
numVertices = 4;
|
||||
@ -242,7 +242,7 @@ void USpineSkeletonRendererComponent::UpdateMesh(Skeleton *Skeleton) {
|
||||
|
||||
attachmentColor.set(mesh->getColor());
|
||||
attachmentAtlasRegion = (AtlasRegion *) mesh->getRendererObject();
|
||||
mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), *attachmentVertices, 0, 2);
|
||||
mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), attachmentVertices->buffer(), 0, 2);
|
||||
attachmentIndices = mesh->getTriangles().buffer();
|
||||
attachmentUvs = mesh->getUVs().buffer();
|
||||
numVertices = mesh->getWorldVerticesLength() >> 1;
|
||||
|
||||
@ -26,6 +26,7 @@ spine-ue4 does not support multiply and screen blending. spine-ue4 does not supp
|
||||
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it as a zip via the download button above.
|
||||
3. Copy the `Plugins` folder from this directory to your new project's root directory.
|
||||
4. Copy the folder `spine-runtimes/spine-cpp/spine-cpp` to your project's `Plugins/SpinePlugin/Source/SpinePlugin/Public/` folder.
|
||||
5. Add `SpinePlugin` to `PublicDependencyModuleNames` in your project's `Build.cs` file.
|
||||
5. Open the Unreal Project in the Unreal Editor
|
||||
|
||||
See the [Spine Runtimes documentation](http://esotericsoftware.com/spine-documentation#runtimesTitle) on how to use the APIs or check out the Spine UE4 example.
|
||||
|
||||
@ -49,7 +49,7 @@ TextureImporter:
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
|
||||
@ -84,7 +84,7 @@ TextureImporter:
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
|
||||
@ -49,7 +49,7 @@ TextureImporter:
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
|
||||
@ -76,7 +76,7 @@ TextureImporter:
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
|
||||
@ -49,7 +49,7 @@ TextureImporter:
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
|
||||
@ -40,7 +40,7 @@ namespace Spine.Unity.Editor {
|
||||
public class BoneFollowerGraphicInspector : Editor {
|
||||
|
||||
SerializedProperty boneName, skeletonGraphic, followXYPosition, followZPosition, followBoneRotation,
|
||||
followLocalScale, followSkeletonFlip, maintainedAxisOrientation;
|
||||
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
|
||||
BoneFollowerGraphic targetBoneFollower;
|
||||
bool needsReset;
|
||||
|
||||
@ -77,6 +77,7 @@ namespace Spine.Unity.Editor {
|
||||
followXYPosition = serializedObject.FindProperty("followXYPosition");
|
||||
followZPosition = serializedObject.FindProperty("followZPosition");
|
||||
followLocalScale = serializedObject.FindProperty("followLocalScale");
|
||||
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
|
||||
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
|
||||
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
|
||||
|
||||
@ -172,6 +173,7 @@ namespace Spine.Unity.Editor {
|
||||
EditorGUILayout.PropertyField(followXYPosition);
|
||||
EditorGUILayout.PropertyField(followZPosition);
|
||||
EditorGUILayout.PropertyField(followLocalScale);
|
||||
EditorGUILayout.PropertyField(followParentWorldScale);
|
||||
EditorGUILayout.PropertyField(followSkeletonFlip);
|
||||
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
|
||||
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
|
||||
|
||||
@ -38,7 +38,7 @@ namespace Spine.Unity.Editor {
|
||||
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
|
||||
public class BoneFollowerInspector : Editor {
|
||||
SerializedProperty boneName, skeletonRenderer, followXYPosition, followZPosition, followBoneRotation,
|
||||
followLocalScale, followSkeletonFlip, maintainedAxisOrientation;
|
||||
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
|
||||
BoneFollower targetBoneFollower;
|
||||
bool needsReset;
|
||||
|
||||
@ -86,6 +86,7 @@ namespace Spine.Unity.Editor {
|
||||
followXYPosition = serializedObject.FindProperty("followXYPosition");
|
||||
followZPosition = serializedObject.FindProperty("followZPosition");
|
||||
followLocalScale = serializedObject.FindProperty("followLocalScale");
|
||||
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
|
||||
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
|
||||
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
|
||||
|
||||
@ -178,6 +179,7 @@ namespace Spine.Unity.Editor {
|
||||
EditorGUILayout.PropertyField(followXYPosition);
|
||||
EditorGUILayout.PropertyField(followZPosition);
|
||||
EditorGUILayout.PropertyField(followLocalScale);
|
||||
EditorGUILayout.PropertyField(followParentWorldScale);
|
||||
EditorGUILayout.PropertyField(followSkeletonFlip);
|
||||
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
|
||||
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
|
||||
|
||||
@ -45,8 +45,6 @@
|
||||
#define HAS_ON_POSTPROCESS_PREFAB
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
@ -131,7 +129,7 @@ namespace Spine.Unity.Editor {
|
||||
SingleSubmeshLabel = new GUIContent("Use Single Submesh", "Simplifies submesh generation by assuming you are only using one Material and need only one submesh. This is will disable multiple materials, render separation, and custom slot materials.");
|
||||
UpdateWhenInvisibleLabel = new GUIContent("Update When Invisible", "Update mode used when the MeshRenderer becomes invisible. Update mode is automatically reset to UpdateMode.FullUpdate when the mesh becomes visible again.");
|
||||
FixDrawOrderLabel = new GUIContent("Fix Draw Order", "Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. \"A B A\"). If true, GPU instancing will be disabled at all materials and MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes by e.g. the LWRP renderer, leading to incorrect draw order (e.g. \"A1 B A2\" changed to \"A1A2 B\"). You can disable this parameter when everything is drawn correctly to save the additional performance cost. Note: the GPU instancing setting will remain disabled at affected material assets after exiting play mode, you have to enable it manually if you accidentally enabled this parameter.");
|
||||
FixPrefabOverrideViaMeshFilterLabel = new GUIContent("Fix Prefab Overr. MeshFilter", "Fixes the prefab always being marked as changed (sets the MeshFilter's hide flags to DontSaveInEditor), but at the cost of references to the MeshFilter by other components being lost.");
|
||||
FixPrefabOverrideViaMeshFilterLabel = new GUIContent("Fix Prefab Overr. MeshFilter", "Fixes the prefab always being marked as changed (sets the MeshFilter's hide flags to DontSaveInEditor), but at the cost of references to the MeshFilter by other components being lost. For global settings see Edit - Preferences - Spine.");
|
||||
MaskInteractionLabel = new GUIContent("Mask Interaction", "SkeletonRenderer's interaction with a Sprite Mask.");
|
||||
MaskMaterialsHeadingLabel = new GUIContent("Mask Interaction Materials", "Materials used for different interaction with sprite masks.");
|
||||
MaskMaterialsNoneLabel = new GUIContent("Normal Materials", "Normal materials used when Mask Interaction is set to None.");
|
||||
@ -397,11 +395,11 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
bool ignoredParam = true;
|
||||
MaskMaterialsEditingField(ref setMaskNoneMaterialsQueued, ref ignoredParam, maskMaterialsNone, MaskMaterialsNoneLabel,
|
||||
differentMaskModesSelected, allowDelete : false, isActiveMaterial : activeMaskInteractionValue == (int)SpriteMaskInteraction.None);
|
||||
differentMaskModesSelected, allowDelete: false, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.None);
|
||||
MaskMaterialsEditingField(ref setInsideMaskMaterialsQueued, ref deleteInsideMaskMaterialsQueued, maskMaterialsInside, MaskMaterialsInsideLabel,
|
||||
differentMaskModesSelected, allowDelete: true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleInsideMask);
|
||||
MaskMaterialsEditingField(ref setOutsideMaskMaterialsQueued, ref deleteOutsideMaskMaterialsQueued, maskMaterialsOutside, MaskMaterialsOutsideLabel,
|
||||
differentMaskModesSelected, allowDelete : true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleOutsideMask);
|
||||
differentMaskModesSelected, allowDelete: true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleOutsideMask);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -630,14 +628,13 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
|
||||
#if BUILT_IN_SPRITE_MASK_COMPONENT
|
||||
static void EditorSetMaskMaterials(SkeletonRenderer component, SpriteMaskInteraction maskType)
|
||||
{
|
||||
static void EditorSetMaskMaterials (SkeletonRenderer component, SpriteMaskInteraction maskType) {
|
||||
if (component == null) return;
|
||||
if (!SpineEditorUtilities.SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return;
|
||||
SpineMaskUtilities.EditorInitMaskMaterials(component, component.maskMaterials, maskType);
|
||||
}
|
||||
|
||||
static void EditorDeleteMaskMaterials(SkeletonRenderer component, SpriteMaskInteraction maskType) {
|
||||
static void EditorDeleteMaskMaterials (SkeletonRenderer component, SpriteMaskInteraction maskType) {
|
||||
if (component == null) return;
|
||||
if (!SpineEditorUtilities.SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return;
|
||||
SpineMaskUtilities.EditorDeleteMaskMaterials(component.maskMaterials, maskType);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user