no message
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#include "AtlasAttachmentLoaderExtension.h"
|
||||
#include "mesh-type-define.h"
|
||||
//#include "LogUtil.h"
|
||||
using namespace spine;
|
||||
|
||||
static uint16_t quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
AttachmentVertices::AttachmentVertices(int verticesCount, uint16_t *triangles, int trianglesCount, uint32_t textureId) {
|
||||
_triangles = new Triangles();
|
||||
_triangles->verts = new V3F_T2F_C4B[verticesCount];
|
||||
_triangles->vertCount = verticesCount;
|
||||
_triangles->indices = triangles;
|
||||
_triangles->indexCount = trianglesCount;
|
||||
_textureId = textureId;
|
||||
}
|
||||
|
||||
AttachmentVertices::~AttachmentVertices() {
|
||||
delete[] _triangles->verts;
|
||||
delete _triangles;
|
||||
}
|
||||
|
||||
AttachmentVertices *AttachmentVertices::copy() {
|
||||
AttachmentVertices *atv = new AttachmentVertices(_triangles->vertCount, _triangles->indices, _triangles->indexCount, _textureId);
|
||||
return atv;
|
||||
}
|
||||
|
||||
static void deleteAttachmentVertices(void *vertices) {
|
||||
delete static_cast<AttachmentVertices *>(vertices);
|
||||
}
|
||||
|
||||
AtlasAttachmentLoaderExtension::AtlasAttachmentLoaderExtension(Atlas *atlas) : AtlasAttachmentLoader(atlas), _atlasCache(atlas) {
|
||||
}
|
||||
|
||||
AtlasAttachmentLoaderExtension::~AtlasAttachmentLoaderExtension() = default;
|
||||
|
||||
void AtlasAttachmentLoaderExtension::configureAttachment(Attachment *attachment) {
|
||||
if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
|
||||
auto *regionAttachment = static_cast<RegionAttachment *>(attachment);
|
||||
auto &pages = _atlasCache->getPages();
|
||||
auto *region = static_cast<AtlasRegion *>(regionAttachment->getRendererObject());
|
||||
auto *attachmentVertices = new AttachmentVertices(4, quadTriangles, 6, pages.indexOf(region->page));
|
||||
V3F_T2F_C4B *vertices = attachmentVertices->_triangles->verts;
|
||||
for (int i = 0, ii = 0; i < 4; ++i, ii += 2) {
|
||||
vertices[i].texCoord.u = regionAttachment->getUVs()[ii];
|
||||
vertices[i].texCoord.v = regionAttachment->getUVs()[ii + 1];
|
||||
}
|
||||
regionAttachment->setRendererObject(attachmentVertices, deleteAttachmentVertices);
|
||||
} else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
|
||||
auto *meshAttachment = static_cast<MeshAttachment *>(attachment);
|
||||
auto &pages = _atlasCache->getPages();
|
||||
auto *region = static_cast<AtlasRegion *>(meshAttachment->getRendererObject());
|
||||
auto *attachmentVertices = new AttachmentVertices(
|
||||
static_cast<int32_t>(meshAttachment->getWorldVerticesLength() >> 1), meshAttachment->getTriangles().buffer(), static_cast<int32_t>(meshAttachment->getTriangles().size()), pages.indexOf(region->page));
|
||||
V3F_T2F_C4B *vertices = attachmentVertices->_triangles->verts;
|
||||
for (size_t i = 0, ii = 0, nn = meshAttachment->getWorldVerticesLength(); ii < nn; ++i, ii += 2) {
|
||||
vertices[i].texCoord.u = meshAttachment->getUVs()[ii];
|
||||
vertices[i].texCoord.v = meshAttachment->getUVs()[ii + 1];
|
||||
}
|
||||
meshAttachment->setRendererObject(attachmentVertices, deleteAttachmentVertices);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef __SPINE_ATLAS_ATTACHMENT_LOADER_EXT_H
|
||||
#define __SPINE_ATLAS_ATTACHMENT_LOADER_EXT_H
|
||||
|
||||
#include "mesh-type-define.h"
|
||||
#include "spine/spine.h"
|
||||
|
||||
class AttachmentVertices {
|
||||
public:
|
||||
AttachmentVertices(int verticesCount, uint16_t *triangles, int trianglesCount, uint32_t textureId);
|
||||
virtual ~AttachmentVertices();
|
||||
AttachmentVertices *copy();
|
||||
Triangles *_triangles = nullptr;
|
||||
uint32_t _textureId = 0;
|
||||
};
|
||||
|
||||
class AtlasAttachmentLoaderExtension : public spine::AtlasAttachmentLoader {
|
||||
public:
|
||||
AtlasAttachmentLoaderExtension(spine::Atlas *atlas);
|
||||
virtual ~AtlasAttachmentLoaderExtension();
|
||||
virtual void configureAttachment(spine::Attachment *attachment);
|
||||
|
||||
private:
|
||||
spine::Atlas *_atlasCache;
|
||||
};
|
||||
|
||||
#endif
|
||||
31
cocos/editor-support/spine-wasm/CMakeLists.txt
Normal file
31
cocos/editor-support/spine-wasm/CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
|
||||
set(APP_NAME "spine" CACHE STRING "Project Name")
|
||||
project(${APP_NAME}_wasm)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -frtti -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1")
|
||||
|
||||
message("Current directory: ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
#include_directories(../ ../../)
|
||||
include_directories(../ ../../ ../spine-creator-support/)
|
||||
file(GLOB SPINE_CORE_SRC "../spine/*.cpp" ../spine-creator-support/Vector2.cpp)
|
||||
file(GLOB COCOS_ADAPTER_SRC "./*.cpp")
|
||||
|
||||
#file(GLOB SPINE_CORE_SRC ../spine-creator-support/Vector2.cpp)
|
||||
|
||||
add_executable(${APP_NAME} ${SPINE_CORE_SRC} ${COCOS_ADAPTER_SRC} )
|
||||
#add_executable(${APP_NAME} ${COCOS_ADAPTER_SRC})
|
||||
|
||||
set(EMS_LINK_FLAGS "-O3 -s WASM=1 -s INITIAL_MEMORY=33554432 -s ALLOW_MEMORY_GROWTH=1 -s DYNAMIC_EXECUTION=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
|
||||
-flto --no-entry --bind -s USE_ES6_IMPORT_META=0 -s EXPORT_ES6=1 -s MODULARIZE=1 -s EXPORT_NAME='spineWasm' \
|
||||
-s ENVIRONMENT=web -s FILESYSTEM=0 -s NO_EXIT_RUNTIME=1 -s LLD_REPORT_UNDEFINED \
|
||||
-s MIN_SAFARI_VERSION=110000 \
|
||||
--js-library ../library_spine.js")
|
||||
|
||||
|
||||
set_target_properties(${APP_NAME} PROPERTIES CXX_STANDARD 11 LINK_FLAGS ${EMS_LINK_FLAGS})
|
||||
18
cocos/editor-support/spine-wasm/library_spine.js
Normal file
18
cocos/editor-support/spine-wasm/library_spine.js
Normal file
@@ -0,0 +1,18 @@
|
||||
mergeInto(LibraryManager.library, {
|
||||
spineListenerCallBackFromJS: function () {
|
||||
var wasmUtil = Module['SpineWasmUtil'];
|
||||
var listenerID = wasmUtil.getCurrentListenerID();
|
||||
var trackEntry = wasmUtil.getCurrentTrackEntry();
|
||||
var event = wasmUtil.getCurrentEvent();
|
||||
globalThis.TrackEntryListeners.emitListener(listenerID, trackEntry, event);
|
||||
},
|
||||
|
||||
spineTrackListenerCallback: function() {
|
||||
var wasmUtil = Module['SpineWasmUtil'];
|
||||
var listenerID = wasmUtil.getCurrentListenerID();
|
||||
var eventType = wasmUtil.getCurrentEventType();
|
||||
var trackEntry = wasmUtil.getCurrentTrackEntry();
|
||||
var event = wasmUtil.getCurrentEvent();
|
||||
globalThis.TrackEntryListeners.emitTrackEntryListener(listenerID, trackEntry, event, eventType.value);
|
||||
}
|
||||
});
|
||||
73
cocos/editor-support/spine-wasm/mesh-type-define.h
Normal file
73
cocos/editor-support/spine-wasm/mesh-type-define.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef __MESH_TYPE_DEF_H__
|
||||
#define __MESH_TYPE_DEF_H__
|
||||
#include <stdint.h>
|
||||
|
||||
struct Vec3 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct Tex2F {
|
||||
float u;
|
||||
float v;
|
||||
};
|
||||
|
||||
struct Color4B {
|
||||
Color4B(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
|
||||
Color4B() {}
|
||||
Color4B &operator=(const Color4B &right) = default;
|
||||
|
||||
uint8_t r = 0;
|
||||
uint8_t g = 0;
|
||||
uint8_t b = 0;
|
||||
uint8_t a = 0;
|
||||
|
||||
static const Color4B WHITE;
|
||||
};
|
||||
|
||||
struct Color4F {
|
||||
Color4F(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {}
|
||||
Color4F() {}
|
||||
Color4F &operator=(const Color4F &right) = default;
|
||||
|
||||
float r = 0;
|
||||
float g = 0;
|
||||
float b = 0;
|
||||
float a = 0;
|
||||
};
|
||||
|
||||
struct V3F_T2F_C4B {
|
||||
Vec3 vertex;
|
||||
// tex coords (2F)
|
||||
Tex2F texCoord;
|
||||
|
||||
Color4B color;
|
||||
};
|
||||
|
||||
struct V3F_T2F_C4B_C4B { // NOLINT
|
||||
// vertices (3F)
|
||||
Vec3 vertex;
|
||||
|
||||
// tex coords (2F)
|
||||
Tex2F texCoord;
|
||||
|
||||
// colors (4F)
|
||||
Color4B color;
|
||||
|
||||
// colors (4F)
|
||||
Color4B color2;
|
||||
};
|
||||
|
||||
struct Triangles {
|
||||
/**Vertex data pointer.*/
|
||||
V3F_T2F_C4B *verts = nullptr;
|
||||
/**Index data pointer.*/
|
||||
unsigned short *indices = nullptr; // NOLINT
|
||||
/**The number of vertices.*/
|
||||
int vertCount = 0;
|
||||
/**The number of indices.*/
|
||||
int indexCount = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
60
cocos/editor-support/spine-wasm/spine-mesh-data.cpp
Normal file
60
cocos/editor-support/spine-wasm/spine-mesh-data.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "spine-mesh-data.h"
|
||||
#include <memory>
|
||||
|
||||
uint8_t* SpineMeshData::vBuf = nullptr;
|
||||
uint8_t* SpineMeshData::vPtr = nullptr;
|
||||
uint8_t* SpineMeshData::vEnd = nullptr;
|
||||
uint16_t* SpineMeshData::iBuf = nullptr;
|
||||
uint16_t* SpineMeshData::iPtr = nullptr;
|
||||
uint16_t* SpineMeshData::iEnd = nullptr;
|
||||
|
||||
void SpineMeshData::initMeshMemory() {
|
||||
if (vBuf) return;
|
||||
const auto vCount = 65535;
|
||||
const auto byteStride = 7 * sizeof(float);
|
||||
vBuf = new uint8_t[2 * vCount * byteStride];
|
||||
iBuf = new uint16_t[8 * 65535];
|
||||
|
||||
vPtr = vBuf;
|
||||
iPtr = iBuf;
|
||||
}
|
||||
|
||||
void SpineMeshData::releaseMeshMemory() {
|
||||
if (vBuf) {
|
||||
delete[] vBuf;
|
||||
vBuf = nullptr;
|
||||
}
|
||||
if (iBuf) {
|
||||
delete[] iBuf;
|
||||
iBuf = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SpineMeshData::reset() {
|
||||
vPtr = vBuf;
|
||||
iPtr = iBuf;
|
||||
}
|
||||
|
||||
void SpineMeshData::moveVB(uint32_t count) {
|
||||
vPtr += count;
|
||||
}
|
||||
|
||||
void SpineMeshData::moveIB(uint32_t count) {
|
||||
iPtr += count;
|
||||
}
|
||||
|
||||
uint8_t* SpineMeshData::queryVBuffer() {
|
||||
return vPtr;
|
||||
}
|
||||
|
||||
uint16_t* SpineMeshData::queryIBuffer() {
|
||||
return iPtr;
|
||||
}
|
||||
|
||||
uint8_t* SpineMeshData::vb() {
|
||||
return vBuf;
|
||||
}
|
||||
|
||||
uint16_t* SpineMeshData::ib() {
|
||||
return iBuf;
|
||||
}
|
||||
26
cocos/editor-support/spine-wasm/spine-mesh-data.h
Normal file
26
cocos/editor-support/spine-wasm/spine-mesh-data.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __SPINE_MESH_DATA_H__
|
||||
#define __SPINE_MESH_DATA_H__
|
||||
#include <stdint.h>
|
||||
|
||||
class SpineMeshData {
|
||||
public:
|
||||
static void initMeshMemory();
|
||||
static void releaseMeshMemory();
|
||||
static void reset();
|
||||
static void moveVB(uint32_t count);
|
||||
static void moveIB(uint32_t count);
|
||||
static uint8_t *queryVBuffer();
|
||||
static uint16_t *queryIBuffer();
|
||||
static uint8_t *vb();
|
||||
static uint16_t *ib();
|
||||
|
||||
private:
|
||||
static uint8_t *vBuf;
|
||||
static uint16_t *iBuf;
|
||||
static uint8_t *vPtr;
|
||||
static uint16_t *iPtr;
|
||||
static uint8_t *vEnd;
|
||||
static uint16_t *iEnd;
|
||||
};
|
||||
|
||||
#endif
|
||||
61
cocos/editor-support/spine-wasm/spine-model.cpp
Normal file
61
cocos/editor-support/spine-wasm/spine-model.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "spine-model.h"
|
||||
|
||||
SpineModel::SpineModel() {
|
||||
SpineModel::data = new std::vector<uint32_t>(6, 0);
|
||||
}
|
||||
|
||||
SpineModel::~SpineModel() {
|
||||
delete SpineModel::data;
|
||||
SpineModel::data = nullptr;
|
||||
}
|
||||
|
||||
void SpineModel::addSlotMesh(SlotMesh& mesh, bool needMerge) {
|
||||
bool canMerge = false;
|
||||
auto count = data->size();
|
||||
if (needMerge && count > 0) {
|
||||
if (data->at(count - 2) == mesh.blendMode && data->at(count - 1) == mesh.textureID) {
|
||||
canMerge = true;
|
||||
data->at(count-4) += mesh.vCount;
|
||||
data->at(count-3) += mesh.iCount;
|
||||
}
|
||||
}
|
||||
if (!canMerge) {
|
||||
data->resize(count + 6);
|
||||
data->at(count) = (uint32_t)mesh.vBuf;
|
||||
data->at(count + 1) = (uint32_t)mesh.iBuf;
|
||||
data->at(count + 2) = mesh.vCount;
|
||||
data->at(count + 3) = mesh.iCount;
|
||||
data->at(count + 4) = mesh.blendMode;
|
||||
data->at(count + 5) = mesh.textureID;
|
||||
}
|
||||
|
||||
auto indexCount = mesh.iCount;
|
||||
uint16_t* iiPtr = mesh.iBuf;
|
||||
for (uint16_t i = 0; i < indexCount; i++) {
|
||||
iiPtr[i] += vCount;
|
||||
}
|
||||
|
||||
auto vertexCount = mesh.vCount;
|
||||
float* floatPtr = (float*)mesh.vBuf;
|
||||
int floatStride = this->byteStride / 4;
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
floatPtr[floatStride * i + 2] = 0;
|
||||
}
|
||||
vCount += vertexCount;
|
||||
iCount += indexCount;
|
||||
}
|
||||
|
||||
void SpineModel::clearMeshes() {
|
||||
data->resize(0);
|
||||
vCount = 0;
|
||||
iCount = 0;
|
||||
}
|
||||
|
||||
std::vector<uint32_t>* SpineModel::getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
void SpineModel::setBufferPtr(uint8_t* vp, uint16_t* ip) {
|
||||
vPtr = (uint32_t)vp;
|
||||
iPtr = (uint32_t)ip;
|
||||
}
|
||||
47
cocos/editor-support/spine-wasm/spine-model.h
Normal file
47
cocos/editor-support/spine-wasm/spine-model.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef __SPINE_MODEL_H__
|
||||
#define __SPINE_MODEL_H__
|
||||
#include <spine/spine.h>
|
||||
#include <vector>
|
||||
#include "mesh-type-define.h"
|
||||
|
||||
using namespace spine;
|
||||
class SlotMesh {
|
||||
public:
|
||||
SlotMesh() {}
|
||||
SlotMesh(uint8_t* vb, uint16_t* ib, uint32_t vc, uint32_t ic)
|
||||
: vBuf(vb), iBuf(ib), vCount(vc), iCount(ic) {}
|
||||
~SlotMesh() {}
|
||||
void set(uint8_t* vb, uint16_t* ib, uint32_t vc, uint32_t ic)
|
||||
{
|
||||
this->vBuf = vb;
|
||||
this->iBuf = ib;
|
||||
this->vCount = vc;
|
||||
this->iCount = ic;
|
||||
}
|
||||
uint8_t* vBuf;
|
||||
uint16_t* iBuf;
|
||||
uint32_t vCount;
|
||||
uint32_t iCount;
|
||||
uint32_t blendMode;
|
||||
uint32_t textureID;
|
||||
};
|
||||
|
||||
class SpineModel {
|
||||
public:
|
||||
SpineModel();
|
||||
~SpineModel();
|
||||
void addSlotMesh(SlotMesh& mesh, bool needMerge = true);
|
||||
void clearMeshes();
|
||||
void setBufferPtr(uint8_t* vp, uint16_t* ip);
|
||||
std::vector<uint32_t>* data;
|
||||
std::vector<uint32_t>* getData();
|
||||
|
||||
public:
|
||||
uint32_t vCount;
|
||||
uint32_t iCount;
|
||||
uint32_t vPtr;
|
||||
uint32_t iPtr;
|
||||
uint32_t byteStride;
|
||||
};
|
||||
|
||||
#endif
|
||||
582
cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp
Normal file
582
cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp
Normal file
@@ -0,0 +1,582 @@
|
||||
#include "spine-skeleton-instance.h"
|
||||
#include <spine/spine.h>
|
||||
#include <vector>
|
||||
#include "AtlasAttachmentLoaderExtension.h"
|
||||
#include "spine-mesh-data.h"
|
||||
#include "spine-wasm.h"
|
||||
#include "util-function.h"
|
||||
|
||||
SlotMesh globalMesh(nullptr, nullptr, 0, 0);
|
||||
|
||||
extern "C" {
|
||||
extern void spineListenerCallBackFromJS();
|
||||
extern void spineTrackListenerCallback();
|
||||
}
|
||||
using namespace spine;
|
||||
|
||||
static void animationCallback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) {
|
||||
SpineSkeletonInstance *instance = (static_cast<SpineSkeletonInstance *>(state->getRendererObject()));
|
||||
instance->onAnimationStateEvent(entry, type, event);
|
||||
}
|
||||
|
||||
static void trackEntryCallback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) {
|
||||
void* renderObj = state->getRendererObject();
|
||||
if (renderObj) {
|
||||
(static_cast<SpineSkeletonInstance *>(renderObj))->onTrackEntryEvent(entry, type, event);
|
||||
if (type == EventType_Dispose) {
|
||||
if (entry->getRendererObject()) {
|
||||
entry->setRendererObject(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpineSkeletonInstance::SpineSkeletonInstance() {
|
||||
_model = new SpineModel();
|
||||
}
|
||||
|
||||
SpineSkeletonInstance::~SpineSkeletonInstance() {
|
||||
_skeletonData = nullptr;
|
||||
if (_clipper) delete _clipper;
|
||||
if (_animState) delete _animState;
|
||||
if (_animStateData) delete _animStateData;
|
||||
if (_skeleton) delete _skeleton;
|
||||
if (_model) delete _model;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::destroy() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
Skeleton *SpineSkeletonInstance::initSkeleton(SkeletonData *data) {
|
||||
if (_clipper) delete _clipper;
|
||||
if (_animState) delete _animState;
|
||||
if (_animStateData) delete _animStateData;
|
||||
if (_skeleton) delete _skeleton;
|
||||
|
||||
_skeletonData = data;
|
||||
_skeleton = new Skeleton(_skeletonData);
|
||||
_animStateData = new AnimationStateData(_skeletonData);
|
||||
_animState = new AnimationState(_animStateData);
|
||||
_clipper = new SkeletonClipping();
|
||||
_skeleton->setToSetupPose();
|
||||
_skeleton->updateWorldTransform();
|
||||
_animState->setRendererObject(this);
|
||||
_animState->setListener(animationCallback);
|
||||
return _skeleton;
|
||||
}
|
||||
|
||||
TrackEntry *SpineSkeletonInstance::setAnimation(float trackIndex, const std::string &name, bool loop) {
|
||||
if (!_skeleton) return nullptr;
|
||||
spine::Animation *animation = _skeleton->getData()->findAnimation(name.c_str());
|
||||
if (!animation) {
|
||||
_animState->clearTracks();
|
||||
_skeleton->setToSetupPose();
|
||||
return nullptr;
|
||||
}
|
||||
auto *trackEntry = _animState->setAnimation(trackIndex, animation, loop);
|
||||
_animState->apply(*_skeleton);
|
||||
_skeleton->updateWorldTransform();
|
||||
return trackEntry;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setSkin(const std::string &name) {
|
||||
if (!_skeleton) return;
|
||||
_skeleton->setSkin(name.c_str());
|
||||
_skeleton->setSlotsToSetupPose();
|
||||
_animState->apply(*_skeleton);
|
||||
_skeleton->updateWorldTransform();
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::updateAnimation(float dltTime) {
|
||||
if (!_skeleton) return;
|
||||
dltTime *= dtRate;
|
||||
_skeleton->update(dltTime);
|
||||
_animState->update(dltTime);
|
||||
_animState->apply(*_skeleton);
|
||||
}
|
||||
|
||||
SpineModel *SpineSkeletonInstance::updateRenderData() {
|
||||
if (_userData.debugMode) {
|
||||
_debugShapes.clear();
|
||||
}
|
||||
_skeleton->updateWorldTransform();
|
||||
SpineMeshData::reset();
|
||||
_model->clearMeshes();
|
||||
if (_userData.useTint) {
|
||||
_model->byteStride = sizeof(V3F_T2F_C4B_C4B);
|
||||
} else {
|
||||
_model->byteStride = sizeof(V3F_T2F_C4B);
|
||||
}
|
||||
collectMeshData();
|
||||
_model->setBufferPtr(SpineMeshData::vb(), SpineMeshData::ib());
|
||||
return _model;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::collectMeshData() {
|
||||
uint32_t byteStrideOneColor = sizeof(V3F_T2F_C4B);
|
||||
uint32_t byteStrideTwoColor = sizeof(V3F_T2F_C4B_C4B);
|
||||
uint32_t sizeof_float = sizeof(float);
|
||||
uint32_t strideOneColor = byteStrideOneColor / sizeof_float;
|
||||
uint32_t strideTwoColor = byteStrideTwoColor / sizeof_float;
|
||||
uint16_t sizeof_uint16 = sizeof(uint16_t);
|
||||
|
||||
uint32_t byteStrideColor = !_userData.useTint ? byteStrideOneColor : byteStrideTwoColor;
|
||||
uint32_t strideColor = byteStrideColor / sizeof_float;
|
||||
|
||||
Color4F color;
|
||||
auto &slotArray = _skeleton->getDrawOrder();
|
||||
uint32_t slotCount = slotArray.size();
|
||||
DEBUG_SHAPE_TYPE debugShapeType = DEBUG_SHAPE_TYPE::DEBUG_REGION;
|
||||
|
||||
SlotMesh currMesh = globalMesh;
|
||||
if (_effect) {
|
||||
_effect->begin(*_skeleton);
|
||||
}
|
||||
const Color& skeletonColor = _skeleton->getColor();
|
||||
for (uint32_t drawIdx = 0; drawIdx < slotCount; ++drawIdx) {
|
||||
auto slot = slotArray[drawIdx];
|
||||
auto& bone = slot->getBone();
|
||||
if (bone.isActive() == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!slot->getAttachment()) {
|
||||
_clipper->clipEnd(*slot);
|
||||
continue;
|
||||
}
|
||||
color.r = _userData.color.r;
|
||||
color.g = _userData.color.g;
|
||||
color.b = _userData.color.b;
|
||||
color.a = _userData.color.a;
|
||||
spine::Attachment* attachmentSlot = slot->getAttachment();
|
||||
const spine::RTTI& attachmentRTTI = attachmentSlot->getRTTI();
|
||||
if (attachmentRTTI.isExactly(spine::RegionAttachment::rtti)) {
|
||||
debugShapeType = DEBUG_SHAPE_TYPE::DEBUG_REGION;
|
||||
auto *attachment = static_cast<spine::RegionAttachment *>(attachmentSlot);
|
||||
auto *attachmentVertices = reinterpret_cast<AttachmentVertices *>(attachment->getRendererObject());
|
||||
|
||||
auto& triangles = attachmentVertices->_triangles;
|
||||
auto vertCount = triangles->vertCount;
|
||||
auto indexCount = triangles->indexCount;
|
||||
auto ibSize = indexCount * sizeof_uint16;
|
||||
|
||||
auto vbSize = vertCount * byteStrideColor;
|
||||
auto *vertices = SpineMeshData::queryVBuffer();
|
||||
auto *indices = SpineMeshData::queryIBuffer();
|
||||
|
||||
if (!_userData.useTint) {
|
||||
memcpy(static_cast<void *>(vertices), static_cast<void *>(triangles->verts), vbSize);
|
||||
} else {
|
||||
V3F_T2F_C4B_C4B *verts = (V3F_T2F_C4B_C4B *)vertices;
|
||||
for (int ii = 0; ii < vertCount; ii++) {
|
||||
verts[ii].texCoord = triangles->verts[ii].texCoord;
|
||||
}
|
||||
}
|
||||
memcpy(indices, triangles->indices, ibSize);
|
||||
attachment->computeWorldVertices(bone, (float *)vertices, 0, strideColor);
|
||||
currMesh.set((uint8_t *)vertices, indices, vertCount, indexCount);
|
||||
const Color& attachmentColor = attachment->getColor();
|
||||
color.r *= attachmentColor.r;
|
||||
color.g *= attachmentColor.g;
|
||||
color.b *= attachmentColor.b;
|
||||
color.a *= attachmentColor.a;
|
||||
currMesh.textureID = attachmentVertices->_textureId;
|
||||
} else if (attachmentRTTI.isExactly(spine::MeshAttachment::rtti)) {
|
||||
debugShapeType = DEBUG_SHAPE_TYPE::DEBUG_MESH;
|
||||
auto *attachment = static_cast<spine::MeshAttachment *>(attachmentSlot);
|
||||
auto *attachmentVertices = static_cast<AttachmentVertices *>(attachment->getRendererObject());
|
||||
|
||||
auto& triangles = attachmentVertices->_triangles;
|
||||
auto vertCount = triangles->vertCount;
|
||||
auto indexCount = triangles->indexCount;
|
||||
auto ibSize = indexCount * sizeof_uint16;
|
||||
|
||||
auto vbSize = vertCount * byteStrideColor;
|
||||
auto *vertices = SpineMeshData::queryVBuffer();
|
||||
auto *indices = SpineMeshData::queryIBuffer();
|
||||
if (!_userData.useTint) {
|
||||
memcpy(static_cast<void *>(vertices), static_cast<void *>(triangles->verts), vbSize);
|
||||
} else {
|
||||
V3F_T2F_C4B_C4B *verts = (V3F_T2F_C4B_C4B *)vertices;
|
||||
for (int ii = 0; ii < vertCount; ii++) {
|
||||
verts[ii].texCoord = triangles->verts[ii].texCoord;
|
||||
}
|
||||
}
|
||||
memcpy(indices, triangles->indices, ibSize);
|
||||
attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float *)vertices, 0, strideColor);
|
||||
currMesh.set((uint8_t *)vertices, indices, vertCount, indexCount);
|
||||
const Color& attachmentColor = attachment->getColor();
|
||||
color.r *= attachmentColor.r;
|
||||
color.g *= attachmentColor.g;
|
||||
color.b *= attachmentColor.b;
|
||||
color.a *= attachmentColor.a;
|
||||
currMesh.textureID = attachmentVertices->_textureId;
|
||||
} else if (attachmentRTTI.isExactly(spine::ClippingAttachment::rtti)) {
|
||||
auto *clip = static_cast<spine::ClippingAttachment *>(attachmentSlot);
|
||||
_clipper->clipStart(*slot, clip);
|
||||
continue;
|
||||
} else {
|
||||
_clipper->clipEnd(*slot);
|
||||
continue;
|
||||
}
|
||||
const Color& slotColor = slot->getColor();
|
||||
uint32_t uintA = (uint32_t)(255 * skeletonColor.a * slotColor.a * color.a);
|
||||
uint32_t multiplier = _userData.premultipliedAlpha ? uintA : 255;
|
||||
uint32_t uintR = (uint32_t)(skeletonColor.r * slotColor.r * color.r * multiplier);
|
||||
uint32_t uintG = (uint32_t)(skeletonColor.g * slotColor.g * color.g * multiplier);
|
||||
uint32_t uintB = (uint32_t)(skeletonColor.b * slotColor.b * color.b * multiplier);
|
||||
uint32_t light = (uintA << 24) + (uintB << 16) + (uintG << 8) + uintR;
|
||||
|
||||
if (slot->hasDarkColor()) {
|
||||
const Color& slotDarkColor = slot->getDarkColor();
|
||||
uintR = (uint32_t)(skeletonColor.r * slotDarkColor.r * color.r * multiplier);
|
||||
uintG = (uint32_t)(skeletonColor.g * slotDarkColor.g * color.g * multiplier);
|
||||
uintB = (uint32_t)(skeletonColor.b * slotDarkColor.b * color.b * multiplier);
|
||||
} else {
|
||||
uintR = 0;
|
||||
uintG = 0;
|
||||
uintB = 0;
|
||||
}
|
||||
uintA = _userData.premultipliedAlpha ? 255 : 0;
|
||||
uint32_t dark = (uintA << 24) + (uintB << 16) + (uintG << 8) + uintR;
|
||||
|
||||
if (!_userData.useTint) {
|
||||
if (_clipper->isClipping()) {
|
||||
_clipper->clipTriangles(reinterpret_cast<float *>(currMesh.vBuf), currMesh.iBuf, currMesh.iCount, (float *)(&currMesh.vBuf[3 * 4]), strideColor);
|
||||
auto& clippedTriangles = _clipper->getClippedTriangles();
|
||||
if (clippedTriangles.size() == 0) {
|
||||
_clipper->clipEnd(*slot);
|
||||
continue;
|
||||
}
|
||||
auto& clippedVertices = _clipper->getClippedVertices();
|
||||
auto& clippedUVs = _clipper->getClippedUVs();
|
||||
const auto vertCount = static_cast<int>(clippedVertices.size()) >> 1;
|
||||
const auto indexCount = static_cast<int>(clippedTriangles.size());
|
||||
const auto vbSize = vertCount * byteStrideColor;
|
||||
uint8_t *vPtr = SpineMeshData::queryVBuffer();
|
||||
uint16_t *iPtr = SpineMeshData::queryIBuffer();
|
||||
currMesh.set(vPtr, iPtr, vertCount, indexCount);
|
||||
memcpy(iPtr, clippedTriangles.buffer(), sizeof_uint16 * indexCount);
|
||||
float *verts = clippedVertices.buffer();
|
||||
float *uvs = clippedUVs.buffer();
|
||||
|
||||
V3F_T2F_C4B *vertices = (V3F_T2F_C4B *)currMesh.vBuf;
|
||||
if (_effect) {
|
||||
for (int v = 0, vn = vertCount, vv = 0; v < vn; ++v, vv += 2) {
|
||||
vertices[v].vertex.x = verts[vv];
|
||||
vertices[v].vertex.y = verts[vv + 1];
|
||||
vertices[v].texCoord.u = uvs[vv];
|
||||
vertices[v].texCoord.v = uvs[vv + 1];
|
||||
_effect->transform(vertices[v].vertex.x, vertices[v].vertex.y);
|
||||
*((uint32_t *)&vertices[v].color) = light;
|
||||
}
|
||||
} else {
|
||||
for (int v = 0, vn = vertCount, vv = 0; v < vn; ++v, vv += 2) {
|
||||
vertices[v].vertex.x = verts[vv];
|
||||
vertices[v].vertex.y = verts[vv + 1];
|
||||
vertices[v].texCoord.u = uvs[vv];
|
||||
vertices[v].texCoord.v = uvs[vv + 1];
|
||||
*((uint32_t *)&vertices[v].color) = light;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto vertCount = currMesh.vCount;
|
||||
V3F_T2F_C4B *vertex = (V3F_T2F_C4B *)currMesh.vBuf;
|
||||
if (_effect) {
|
||||
for (int v = 0; v < vertCount; ++v) {
|
||||
_effect->transform(vertex[v].vertex.x, vertex[v].vertex.y);
|
||||
*((uint32_t *)&vertex[v].color) = light;
|
||||
}
|
||||
} else {
|
||||
for (int v = 0; v < vertCount; ++v) {
|
||||
*((uint32_t *)&vertex[v].color) = light;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_clipper->isClipping()) {
|
||||
_clipper->clipTriangles(reinterpret_cast<float *>(currMesh.vBuf), currMesh.iBuf, currMesh.iCount, (float *)(&currMesh.vBuf[3 * 4]), strideColor);
|
||||
auto& clippedTriangles = _clipper->getClippedTriangles();
|
||||
if (clippedTriangles.size() == 0) {
|
||||
_clipper->clipEnd(*slot);
|
||||
continue;
|
||||
}
|
||||
auto& clippedVertices = _clipper->getClippedVertices();
|
||||
auto& clippedUVs = _clipper->getClippedUVs();
|
||||
const auto vertCount = static_cast<int>(clippedVertices.size()) >> 1;
|
||||
const auto indexCount = static_cast<int>(clippedTriangles.size());
|
||||
const auto vbSize = vertCount * byteStrideColor;
|
||||
uint8_t *vPtr = SpineMeshData::queryVBuffer();
|
||||
uint16_t *iPtr = SpineMeshData::queryIBuffer();
|
||||
currMesh.set(vPtr, iPtr, vertCount, indexCount);
|
||||
memcpy(iPtr, clippedTriangles.buffer(), sizeof_uint16 * indexCount);
|
||||
float *verts = clippedVertices.buffer();
|
||||
float *uvs = clippedUVs.buffer();
|
||||
|
||||
V3F_T2F_C4B_C4B *vertices = (V3F_T2F_C4B_C4B *)currMesh.vBuf;
|
||||
if (_effect) {
|
||||
for (int v = 0, vn = vertCount, vv = 0; v < vn; ++v, vv += 2) {
|
||||
vertices[v].vertex.x = verts[vv];
|
||||
vertices[v].vertex.y = verts[vv + 1];
|
||||
vertices[v].texCoord.u = uvs[vv];
|
||||
vertices[v].texCoord.v = uvs[vv + 1];
|
||||
_effect->transform(vertices[v].vertex.x, vertices[v].vertex.y);
|
||||
*((uint32_t *)&vertices[v].color) = light;
|
||||
*((uint32_t *)&vertices[v].color2) = dark;
|
||||
}
|
||||
} else {
|
||||
for (int v = 0, vn = vertCount, vv = 0; v < vn; ++v, vv += 2) {
|
||||
vertices[v].vertex.x = verts[vv];
|
||||
vertices[v].vertex.y = verts[vv + 1];
|
||||
vertices[v].texCoord.u = uvs[vv];
|
||||
vertices[v].texCoord.v = uvs[vv + 1];
|
||||
*((uint32_t *)&vertices[v].color) = light;
|
||||
*((uint32_t *)&vertices[v].color2) = dark;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto vertCount = currMesh.vCount;
|
||||
V3F_T2F_C4B_C4B *vertex = (V3F_T2F_C4B_C4B *)currMesh.vBuf;
|
||||
if (_effect) {
|
||||
for (int v = 0; v < vertCount; ++v) {
|
||||
_effect->transform(vertex[v].vertex.x, vertex[v].vertex.y);
|
||||
*((uint32_t *)&vertex[v].color) = light;
|
||||
*((uint32_t *)&vertex[v].color2) = dark;
|
||||
}
|
||||
} else {
|
||||
for (int v = 0; v < vertCount; ++v) {
|
||||
*((uint32_t *)&vertex[v].color) = light;
|
||||
*((uint32_t *)&vertex[v].color2) = dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpineMeshData::moveVB(currMesh.vCount * byteStrideColor);
|
||||
SpineMeshData::moveIB(currMesh.iCount);
|
||||
// record debug shape info
|
||||
if (_userData.debugMode) {
|
||||
SpineDebugShape debugShape;
|
||||
debugShape.type = static_cast<uint32_t>(debugShapeType);
|
||||
debugShape.vOffset = _model->vCount;
|
||||
debugShape.vCount = currMesh.vCount;
|
||||
debugShape.iOffset = _model->iCount;
|
||||
debugShape.iCount = currMesh.iCount;
|
||||
_debugShapes.push_back(debugShape);
|
||||
}
|
||||
|
||||
currMesh.blendMode = static_cast<uint32_t>(slot->getData().getBlendMode());
|
||||
if (_userData.useSlotTexture) {
|
||||
auto iter = slotTextureSet.find(slot);
|
||||
if (iter != slotTextureSet.end()) {
|
||||
currMesh.textureID = iter->second;
|
||||
}
|
||||
}
|
||||
_model->addSlotMesh(currMesh);
|
||||
_clipper->clipEnd(*slot);
|
||||
}
|
||||
|
||||
_clipper->clipEnd();
|
||||
if (_effect) _effect->end();
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setPremultipliedAlpha(bool val) {
|
||||
_userData.premultipliedAlpha = val;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setColor(float r, float g, float b, float a) {
|
||||
_userData.color.r = r;
|
||||
_userData.color.g = g;
|
||||
_userData.color.b = b;
|
||||
_userData.color.a = a;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setJitterEffect(JitterVertexEffect *effect) {
|
||||
_effect = effect;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setSwirlEffect(SwirlVertexEffect *effect) {
|
||||
_effect = effect;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::clearEffect() {
|
||||
_effect = nullptr;
|
||||
}
|
||||
|
||||
AnimationState *SpineSkeletonInstance::getAnimationState() {
|
||||
return _animState;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setMix(const std::string &from, const std::string &to, float duration) {
|
||||
_animStateData->setMix(from.c_str(), to.c_str(), duration);
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setListener(uint32_t listenerID, uint32_t type) {
|
||||
switch (type) {
|
||||
case EventType_Start:
|
||||
_startListenerID = listenerID;
|
||||
break;
|
||||
case EventType_Interrupt:
|
||||
_interruptListenerID = listenerID;
|
||||
break;
|
||||
case EventType_End:
|
||||
_endListenerID = listenerID;
|
||||
break;
|
||||
case EventType_Dispose:
|
||||
_disposeListenerID = listenerID;
|
||||
break;
|
||||
case EventType_Complete:
|
||||
_completeListenerID = listenerID;
|
||||
break;
|
||||
case EventType_Event:
|
||||
_eventListenerID = listenerID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setTrackEntryListener(uint32_t trackId, TrackEntry *entry) {
|
||||
if (!entry->getRendererObject()) {
|
||||
_trackEntryListenerID = trackId;
|
||||
entry->setRendererObject(this);
|
||||
entry->setListener(trackEntryCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setUseTint(bool useTint) {
|
||||
_userData.useTint = useTint;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setDebugMode(bool debug) {
|
||||
_userData.debugMode = debug;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::onTrackEntryEvent(TrackEntry *entry, EventType type, Event *event) {
|
||||
if (!entry->getRendererObject()) return;
|
||||
SpineWasmUtil::s_listenerID = _trackEntryListenerID;
|
||||
SpineWasmUtil::s_currentType = type;
|
||||
SpineWasmUtil::s_currentEntry = entry;
|
||||
SpineWasmUtil::s_currentEvent = event;
|
||||
spineTrackListenerCallback();
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::onAnimationStateEvent(TrackEntry *entry, EventType type, Event *event) {
|
||||
SpineWasmUtil::s_currentType = type;
|
||||
SpineWasmUtil::s_currentEntry = entry;
|
||||
SpineWasmUtil::s_currentEvent = event;
|
||||
switch (type) {
|
||||
case EventType_Start:
|
||||
if (_startListenerID != 0) {
|
||||
SpineWasmUtil::s_listenerID = _startListenerID;
|
||||
spineListenerCallBackFromJS();
|
||||
}
|
||||
break;
|
||||
case EventType_Interrupt:
|
||||
if (_interruptListenerID != 0) {
|
||||
SpineWasmUtil::s_listenerID = _interruptListenerID;
|
||||
spineListenerCallBackFromJS();
|
||||
}
|
||||
break;
|
||||
case EventType_End:
|
||||
if (_endListenerID != 0) {
|
||||
SpineWasmUtil::s_listenerID = _endListenerID;
|
||||
spineListenerCallBackFromJS();
|
||||
}
|
||||
break;
|
||||
case EventType_Dispose:
|
||||
if (_disposeListenerID != 0) {
|
||||
SpineWasmUtil::s_listenerID = _disposeListenerID;
|
||||
spineListenerCallBackFromJS();
|
||||
}
|
||||
break;
|
||||
case EventType_Complete:
|
||||
if (_completeListenerID != 0) {
|
||||
SpineWasmUtil::s_listenerID = _completeListenerID;
|
||||
spineListenerCallBackFromJS();
|
||||
}
|
||||
break;
|
||||
case EventType_Event:
|
||||
if (_eventListenerID != 0) {
|
||||
SpineWasmUtil::s_listenerID = _eventListenerID;
|
||||
spineListenerCallBackFromJS();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SpineDebugShape> &SpineSkeletonInstance::getDebugShapes() {
|
||||
return this->_debugShapes;
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::resizeSlotRegion(const std::string &slotName, uint32_t width, uint32_t height, bool createNew) {
|
||||
if (!_skeleton) return;
|
||||
auto slot = _skeleton->findSlot(slotName.c_str());
|
||||
if (!slot) return;
|
||||
auto attachment = slot->getAttachment();
|
||||
if (!attachment) return;
|
||||
if (createNew) {
|
||||
attachment = attachment->copy();
|
||||
slot->setAttachment(attachment);
|
||||
}
|
||||
if (attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) {
|
||||
auto region = static_cast<RegionAttachment *>(attachment);
|
||||
region->setRegionWidth(width);
|
||||
region->setRegionHeight(height);
|
||||
region->setRegionOriginalWidth(width);
|
||||
region->setRegionOriginalHeight(height);
|
||||
region->setWidth(width);
|
||||
region->setHeight(height);
|
||||
region->setUVs(0, 0, 1.0f, 1.0f, false);
|
||||
region->updateOffset();
|
||||
auto attachmentVertices = static_cast<AttachmentVertices *>(region->getRendererObject());
|
||||
if (createNew) {
|
||||
attachmentVertices = attachmentVertices->copy();
|
||||
region->setRendererObject(attachmentVertices);
|
||||
}
|
||||
V3F_T2F_C4B *vertices = attachmentVertices->_triangles->verts;
|
||||
auto UVs = region->getUVs();
|
||||
for (int i = 0, ii = 0; i < 4; ++i, ii += 2) {
|
||||
vertices[i].texCoord.u = UVs[ii];
|
||||
vertices[i].texCoord.v = UVs[ii + 1];
|
||||
}
|
||||
} else if (attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) {
|
||||
auto mesh = static_cast<MeshAttachment *>(attachment);
|
||||
mesh->setRegionWidth(width);
|
||||
mesh->setRegionHeight(height);
|
||||
mesh->setRegionOriginalWidth(width);
|
||||
mesh->setRegionOriginalHeight(height);
|
||||
mesh->setWidth(width);
|
||||
mesh->setHeight(height);
|
||||
mesh->setRegionU(0);
|
||||
mesh->setRegionV(0);
|
||||
mesh->setRegionU2(1.0f);
|
||||
mesh->setRegionV2(1.0f);
|
||||
mesh->setRegionRotate(true);
|
||||
mesh->setRegionDegrees(0);
|
||||
mesh->updateUVs();
|
||||
auto attachmentVertices = static_cast<AttachmentVertices *>(mesh->getRendererObject());
|
||||
if (createNew) {
|
||||
attachmentVertices = attachmentVertices->copy();
|
||||
mesh->setRendererObject(attachmentVertices);
|
||||
}
|
||||
V3F_T2F_C4B *vertices = attachmentVertices->_triangles->verts;
|
||||
auto UVs = mesh->getUVs();
|
||||
for (size_t i = 0, ii = 0, nn = mesh->getWorldVerticesLength(); ii < nn; ++i, ii += 2) {
|
||||
vertices[i].texCoord.u = UVs[ii];
|
||||
vertices[i].texCoord.v = UVs[ii + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpineSkeletonInstance::setSlotTexture(const std::string &slotName, uint32_t textureID) {
|
||||
if (!_skeleton) return;
|
||||
auto slot = _skeleton->findSlot(slotName.c_str());
|
||||
if (!slot) return;
|
||||
_userData.useSlotTexture = true;
|
||||
auto iter = slotTextureSet.find(slot);
|
||||
if (iter != slotTextureSet.end()) {
|
||||
iter->second = textureID;
|
||||
} else {
|
||||
slotTextureSet[slot] = textureID;
|
||||
}
|
||||
}
|
||||
88
cocos/editor-support/spine-wasm/spine-skeleton-instance.h
Normal file
88
cocos/editor-support/spine-wasm/spine-skeleton-instance.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef _SPINE_SKELETON_INSTANCE_H_
|
||||
#define _SPINE_SKELETON_INSTANCE_H_
|
||||
#include <spine/spine.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "mesh-type-define.h"
|
||||
#include "spine-model.h"
|
||||
using namespace spine;
|
||||
|
||||
|
||||
enum DEBUG_SHAPE_TYPE {
|
||||
DEBUG_REGION = 0,
|
||||
DEBUG_MESH = 1
|
||||
};
|
||||
class SpineDebugShape {
|
||||
public:
|
||||
SpineDebugShape() {}
|
||||
~SpineDebugShape() {}
|
||||
uint32_t type = 0;
|
||||
uint32_t vOffset = 0;
|
||||
uint32_t vCount = 0;
|
||||
uint32_t iOffset = 0;
|
||||
uint32_t iCount = 0;
|
||||
};
|
||||
|
||||
class SpineSkeletonInstance {
|
||||
struct UserData {
|
||||
bool useTint = false;
|
||||
bool premultipliedAlpha = false;
|
||||
bool debugMode = false;
|
||||
bool useSlotTexture = false;
|
||||
Color4F color = Color4F(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
};
|
||||
|
||||
public:
|
||||
SpineSkeletonInstance();
|
||||
~SpineSkeletonInstance();
|
||||
Skeleton *initSkeleton(SkeletonData *data);
|
||||
TrackEntry *setAnimation(float trackIndex, const std::string &name, bool loop);
|
||||
void setSkin(const std::string &name);
|
||||
void updateAnimation(float dltTime);
|
||||
SpineModel *updateRenderData();
|
||||
void setPremultipliedAlpha(bool val);
|
||||
void setUseTint(bool useTint);
|
||||
void setDebugMode(bool debug);
|
||||
void setColor(float r, float g, float b, float a);
|
||||
void setJitterEffect(JitterVertexEffect *effect);
|
||||
void setSwirlEffect(SwirlVertexEffect *effect);
|
||||
void clearEffect();
|
||||
AnimationState *getAnimationState();
|
||||
void setMix(const std::string &from, const std::string &to, float duration);
|
||||
void setListener(uint32_t listenerID, uint32_t type);
|
||||
void setTrackEntryListener(uint32_t trackId, TrackEntry *entry);
|
||||
void onAnimationStateEvent(TrackEntry *entry, EventType type, Event *event);
|
||||
void onTrackEntryEvent(TrackEntry *entry, EventType type, Event *event);
|
||||
std::vector<SpineDebugShape> &getDebugShapes();
|
||||
void resizeSlotRegion(const std::string &slotName, uint32_t width, uint32_t height, bool createNew = false);
|
||||
void setSlotTexture(const std::string &slotName, uint32_t index);
|
||||
void destroy();
|
||||
bool isCache{false};
|
||||
bool enable{true};
|
||||
float dtRate{1.0F};
|
||||
private:
|
||||
void collectMeshData();
|
||||
|
||||
private:
|
||||
Skeleton *_skeleton = nullptr;
|
||||
SkeletonData *_skeletonData = nullptr;
|
||||
AnimationStateData *_animStateData = nullptr;
|
||||
AnimationState *_animState = nullptr;
|
||||
SkeletonClipping *_clipper = nullptr;
|
||||
VertexEffect *_effect = nullptr;
|
||||
SpineModel *_model = nullptr;
|
||||
uint32_t _startListenerID = 0;
|
||||
uint32_t _interruptListenerID = 0;
|
||||
uint32_t _endListenerID = 0;
|
||||
uint32_t _disposeListenerID = 0;
|
||||
uint32_t _completeListenerID = 0;
|
||||
uint32_t _eventListenerID = 0;
|
||||
uint32_t _trackEntryListenerID = 0;
|
||||
UserData _userData;
|
||||
std::vector<SpineDebugShape> _debugShapes{};
|
||||
std::map<Slot *, uint32_t> slotTextureSet{};
|
||||
};
|
||||
|
||||
#endif
|
||||
1628
cocos/editor-support/spine-wasm/spine-type-export.cpp
Normal file
1628
cocos/editor-support/spine-wasm/spine-type-export.cpp
Normal file
File diff suppressed because it is too large
Load Diff
127
cocos/editor-support/spine-wasm/spine-wasm.cpp
Normal file
127
cocos/editor-support/spine-wasm/spine-wasm.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "spine-wasm.h"
|
||||
#include <map>
|
||||
#include "AtlasAttachmentLoaderExtension.h"
|
||||
#include "spine-mesh-data.h"
|
||||
#include "util-function.h"
|
||||
#include "wasmSpineExtension.h"
|
||||
|
||||
std::map<std::string, SkeletonData*> skeletonDataMap{};
|
||||
|
||||
uint32_t SpineWasmUtil::s_listenerID = 0;
|
||||
EventType SpineWasmUtil::s_currentType = EventType_Event;
|
||||
TrackEntry* SpineWasmUtil::s_currentEntry = nullptr;
|
||||
Event* SpineWasmUtil::s_currentEvent = nullptr;
|
||||
uint8_t* SpineWasmUtil::s_mem = nullptr;
|
||||
uint32_t SpineWasmUtil::s_memSize = 0;
|
||||
|
||||
void SpineWasmUtil::spineWasmInit() {
|
||||
LogUtil::Initialize();
|
||||
spine::SpineExtension* tension = new WasmSpineExtension();
|
||||
spine::SpineExtension::setInstance(tension);
|
||||
|
||||
SpineMeshData::initMeshMemory();
|
||||
|
||||
//LogUtil::PrintToJs("spineWasmInit");
|
||||
}
|
||||
|
||||
void SpineWasmUtil::spineWasmDestroy() {
|
||||
auto* extension = spine::SpineExtension::getInstance();
|
||||
delete extension;
|
||||
freeStoreMemory();
|
||||
SpineMeshData::releaseMeshMemory();
|
||||
LogUtil::ReleaseBuffer();
|
||||
}
|
||||
|
||||
SkeletonData* SpineWasmUtil::querySpineSkeletonDataByUUID(const std::string& uuid) {
|
||||
auto iter = skeletonDataMap.find(uuid);
|
||||
if (iter == skeletonDataMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
SkeletonData* ptrVal = iter->second;
|
||||
return ptrVal;
|
||||
}
|
||||
|
||||
SkeletonData* SpineWasmUtil::createSpineSkeletonDataWithJson(const std::string& jsonStr, const std::string& altasStr) {
|
||||
auto* atlas = new Atlas(altasStr.c_str(), altasStr.size(), "", nullptr, false);
|
||||
if (!atlas) {
|
||||
return nullptr;
|
||||
}
|
||||
AttachmentLoader* attachmentLoader = new AtlasAttachmentLoaderExtension(atlas);
|
||||
spine::SkeletonJson json(attachmentLoader);
|
||||
json.setScale(1.0F);
|
||||
SkeletonData* skeletonData = json.readSkeletonData(jsonStr.c_str());
|
||||
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
SkeletonData* SpineWasmUtil::createSpineSkeletonDataWithBinary(uint32_t byteSize, const std::string& altasStr) {
|
||||
auto* atlas = new Atlas(altasStr.c_str(), altasStr.size(), "", nullptr, false);
|
||||
if (!atlas) {
|
||||
return nullptr;
|
||||
}
|
||||
AttachmentLoader* attachmentLoader = new AtlasAttachmentLoaderExtension(atlas);
|
||||
spine::SkeletonBinary binary(attachmentLoader);
|
||||
binary.setScale(1.0F);
|
||||
SkeletonData* skeletonData = binary.readSkeletonData(s_mem, byteSize);
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
void SpineWasmUtil::registerSpineSkeletonDataWithUUID(SkeletonData* data, const std::string& uuid) {
|
||||
auto iter = skeletonDataMap.find(uuid);
|
||||
if (iter == skeletonDataMap.end()) {
|
||||
skeletonDataMap[uuid] = data;
|
||||
}
|
||||
}
|
||||
|
||||
void SpineWasmUtil::destroySpineSkeletonDataWithUUID(const std::string& uuid) {
|
||||
auto iter = skeletonDataMap.find(uuid);
|
||||
if (iter != skeletonDataMap.end()) {
|
||||
auto* data = skeletonDataMap[uuid];
|
||||
delete data;
|
||||
skeletonDataMap.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void SpineWasmUtil::destroySpineSkeleton(Skeleton* skeleton) {
|
||||
if (skeleton) {
|
||||
delete skeleton;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SpineWasmUtil::queryStoreMemory(uint32_t size) {
|
||||
if (s_mem) {
|
||||
if (s_memSize < size) {
|
||||
delete[] s_mem;
|
||||
s_mem = new uint8_t[size];
|
||||
s_memSize = size;
|
||||
}
|
||||
} else {
|
||||
s_mem = new uint8_t[size];
|
||||
s_memSize = size;
|
||||
}
|
||||
return (uint32_t)s_mem;
|
||||
}
|
||||
|
||||
void SpineWasmUtil::freeStoreMemory() {
|
||||
if (s_mem) {
|
||||
delete[] s_mem;
|
||||
s_mem = nullptr;
|
||||
}
|
||||
s_memSize = 0;
|
||||
}
|
||||
|
||||
uint32_t SpineWasmUtil::getCurrentListenerID() {
|
||||
return s_listenerID;
|
||||
}
|
||||
|
||||
EventType SpineWasmUtil::getCurrentEventType() {
|
||||
return s_currentType;
|
||||
}
|
||||
|
||||
TrackEntry* SpineWasmUtil::getCurrentTrackEntry() {
|
||||
return s_currentEntry;
|
||||
}
|
||||
|
||||
Event* SpineWasmUtil::getCurrentEvent() {
|
||||
return s_currentEvent;
|
||||
}
|
||||
37
cocos/editor-support/spine-wasm/spine-wasm.h
Normal file
37
cocos/editor-support/spine-wasm/spine-wasm.h
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
#ifndef _SPINE_WASM_H_
|
||||
#define _SPINE_WASM_H_
|
||||
#include <spine/spine.h>
|
||||
#include <string>
|
||||
#include "spine-skeleton-instance.h"
|
||||
using namespace spine;
|
||||
|
||||
class SpineWasmUtil {
|
||||
public:
|
||||
static void spineWasmInit();
|
||||
static void spineWasmDestroy();
|
||||
static uint32_t queryStoreMemory(uint32_t size);
|
||||
static void freeStoreMemory();
|
||||
|
||||
static SkeletonData* querySpineSkeletonDataByUUID(const std::string& uuid);
|
||||
static SkeletonData* createSpineSkeletonDataWithJson(const std::string& jsonStr, const std::string& altasStr);
|
||||
static SkeletonData* createSpineSkeletonDataWithBinary(uint32_t byteSize, const std::string& altasStr);
|
||||
static void registerSpineSkeletonDataWithUUID(SkeletonData* data, const std::string& uuid);
|
||||
static void destroySpineSkeletonDataWithUUID(const std::string& uuid);
|
||||
static void destroySpineSkeleton(Skeleton* skeleton);
|
||||
|
||||
static uint32_t getCurrentListenerID();
|
||||
static EventType getCurrentEventType();
|
||||
static TrackEntry* getCurrentTrackEntry();
|
||||
static Event* getCurrentEvent();
|
||||
|
||||
static uint32_t s_listenerID;
|
||||
static EventType s_currentType;
|
||||
static TrackEntry* s_currentEntry;
|
||||
static Event* s_currentEvent;
|
||||
|
||||
static uint8_t* s_mem;
|
||||
static uint32_t s_memSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
67
cocos/editor-support/spine-wasm/util-function.cpp
Normal file
67
cocos/editor-support/spine-wasm/util-function.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "util-function.h"
|
||||
#include <stdint.h>
|
||||
// extern "C" {
|
||||
// extern void consoleInfo(char* ptr, uint32_t length);
|
||||
// }
|
||||
static char* logBuffer = nullptr;
|
||||
const int LOG_LENGTH = 1024;
|
||||
|
||||
void LogUtil::Initialize() {
|
||||
//logBuffer = new char[LOG_LENGTH];
|
||||
}
|
||||
|
||||
void LogUtil::PrintToJs(std::string& message) {
|
||||
// int length = message.length();
|
||||
// if (length >= LOG_LENGTH) length = LOG_LENGTH -1;
|
||||
// memcpy(logBuffer, message.c_str(), length);
|
||||
// logBuffer[length] = 0;
|
||||
// consoleInfo(logBuffer, length);
|
||||
}
|
||||
|
||||
void LogUtil::PrintToJs(const char* message) {
|
||||
// std::string strMessage(message);
|
||||
// int length = strMessage.length();
|
||||
// if (length >= LOG_LENGTH) length = LOG_LENGTH - 1;
|
||||
// memcpy(logBuffer, strMessage.c_str(), length);
|
||||
// logBuffer[length] = 0;
|
||||
// consoleInfo(logBuffer, length);
|
||||
}
|
||||
|
||||
void LogUtil::PrintToJs(char* str, int length) {
|
||||
// if (length >= LOG_LENGTH) length = LOG_LENGTH - 1;
|
||||
// memcpy(logBuffer, str, length);
|
||||
// logBuffer[length] = 0;
|
||||
// consoleInfo(logBuffer, length);
|
||||
}
|
||||
|
||||
void LogUtil::PrintIntValue(int value, const char* message) {
|
||||
// std::string strInt = std::to_string(value);
|
||||
// std::string finalStr = std::string(message) + strInt;
|
||||
// LogUtil::PrintToJs(finalStr);
|
||||
}
|
||||
|
||||
void LogUtil::ReleaseBuffer() {
|
||||
//delete[] logBuffer;
|
||||
}
|
||||
|
||||
// const uint32_t MEMORY_SIZE = 8 * 1024 * 1024;
|
||||
// static uint8_t* uint8Ptr = nullptr;
|
||||
|
||||
// uint8_t* StoreMemory::getStoreMemory() {
|
||||
// if (uint8Ptr) return uint8Ptr;
|
||||
|
||||
// uint32_t* uint32Ptr = new uint32_t[MEMORY_SIZE / 4];
|
||||
// uint8Ptr = (uint8_t*)uint32Ptr;
|
||||
// return uint8Ptr;
|
||||
// }
|
||||
|
||||
// void StoreMemory::freeStoreMemory() {
|
||||
// if (uint8Ptr) {
|
||||
// delete[] uint8Ptr;
|
||||
// uint8Ptr = nullptr;
|
||||
// }
|
||||
// }
|
||||
|
||||
// uint32_t StoreMemory::storeMemorySize() {
|
||||
// return MEMORY_SIZE;
|
||||
// }
|
||||
22
cocos/editor-support/spine-wasm/util-function.h
Normal file
22
cocos/editor-support/spine-wasm/util-function.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __UTIL_FUNCTION_H__
|
||||
#define __UTIL_FUNCTION_H__
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
class LogUtil {
|
||||
public:
|
||||
static void Initialize();
|
||||
static void PrintToJs(std::string& message);
|
||||
static void PrintToJs(const char* message);
|
||||
static void PrintToJs(char* str, int length);
|
||||
static void PrintIntValue(int value, const char* message);
|
||||
static void ReleaseBuffer();
|
||||
};
|
||||
|
||||
// class StoreMemory {
|
||||
// public:
|
||||
// static uint8_t* getStoreMemory();
|
||||
// static void freeStoreMemory();
|
||||
// static uint32_t storeMemorySize();
|
||||
// };
|
||||
|
||||
#endif
|
||||
72
cocos/editor-support/spine-wasm/wasmSpineExtension.cpp
Normal file
72
cocos/editor-support/spine-wasm/wasmSpineExtension.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "wasmSpineExtension.h"
|
||||
#include "util-function.h"
|
||||
|
||||
using namespace spine;
|
||||
// extern "C" {
|
||||
// extern uint32_t jsReadFile(char* fileName, uint32_t length);
|
||||
// }
|
||||
|
||||
WasmSpineExtension::WasmSpineExtension() : DefaultSpineExtension() {
|
||||
}
|
||||
|
||||
WasmSpineExtension::~WasmSpineExtension() {
|
||||
}
|
||||
|
||||
char *WasmSpineExtension::_readFile(const String &path, int *length) {
|
||||
// size_t pathSize = path.length();
|
||||
// uint8_t* uint8Ptr = StoreMemory::getStoreMemory();
|
||||
// char* shareBuffer = (char*)uint8Ptr;
|
||||
// memcpy(shareBuffer, path.buffer(), pathSize);
|
||||
// uint32_t resultSize = jsReadFile(shareBuffer, pathSize);
|
||||
// *length = (int)resultSize;
|
||||
// uint8_t *data = new uint8_t[resultSize];
|
||||
// memcpy(data, shareBuffer, resultSize);
|
||||
// return (char*)data;
|
||||
//LogUtil::PrintToJs("Error WasmSpineExtension::_readFile");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *WasmSpineExtension::_alloc(size_t size, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
void *ptr = new uint8_t[size];
|
||||
return (void *)ptr;
|
||||
}
|
||||
|
||||
void *WasmSpineExtension::_calloc(size_t size, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
uint8_t *ptr = new uint8_t[size];
|
||||
if (ptr) memset(ptr, 0, size);
|
||||
return (void *)ptr;
|
||||
}
|
||||
|
||||
void *WasmSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
uint8_t *mem = new uint8_t[size];
|
||||
memcpy(mem, ptr, size);
|
||||
delete[](char *) ptr;
|
||||
ptr = mem;
|
||||
return mem;
|
||||
}
|
||||
|
||||
void WasmSpineExtension::_free(void *mem, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
delete[](char *) mem;
|
||||
}
|
||||
|
||||
SpineExtension *spine::getDefaultExtension() {
|
||||
return new WasmSpineExtension();
|
||||
}
|
||||
23
cocos/editor-support/spine-wasm/wasmSpineExtension.h
Normal file
23
cocos/editor-support/spine-wasm/wasmSpineExtension.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef __WASM_SPINE_EXTENSION_H__
|
||||
#define __WASM_SPINE_EXTENSION_H__
|
||||
#include "spine/spine.h"
|
||||
|
||||
class WasmSpineExtension : public spine::DefaultSpineExtension {
|
||||
public:
|
||||
WasmSpineExtension();
|
||||
|
||||
virtual ~WasmSpineExtension();
|
||||
|
||||
protected:
|
||||
virtual void *_alloc(size_t size, const char *file, int line);
|
||||
|
||||
virtual void *_calloc(size_t size, const char *file, int line);
|
||||
|
||||
virtual void *_realloc(void *ptr, size_t size, const char *file, int line);
|
||||
|
||||
virtual void _free(void *mem, const char *file, int line);
|
||||
|
||||
virtual char *_readFile(const spine::String &path, int *length);
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user