[cocos2d-x] Spine 组件所有特性原生平台适配

This commit is contained in:
SmallMain
2022-07-05 11:05:41 +08:00
parent f4599764fe
commit 3b1584ee1c
25 changed files with 1801 additions and 312 deletions

View File

@@ -38,11 +38,10 @@ MeshBuffer::MeshBuffer(int vertexFormat)
}
MeshBuffer::MeshBuffer(int vertexFormat, size_t indexSize, size_t vertexSize)
: _vertexFormat(vertexFormat)
, _ib(indexSize)
, _vb(vertexSize * vertexFormat * sizeof(float))
{
_vb.setMaxSize(MAX_VERTEX_BUFFER_SIZE * _vertexFormat * sizeof(float));
: _vertexFormat(vertexFormat),
_ib(indexSize),
_vb(vertexSize * (vertexFormat == 7 ? 6 : (vertexFormat == 8 ? 7 : vertexFormat)) * sizeof(float)) {
_vb.setMaxSize(MAX_VERTEX_BUFFER_SIZE * (vertexFormat == 7 ? 6 : (vertexFormat == 8 ? 7 : vertexFormat)) * sizeof(float));
_ib.setMaxSize(INIT_INDEX_BUFFER_SIZE);
_vb.setFullCallback([this]
{
@@ -66,6 +65,12 @@ MeshBuffer::MeshBuffer(int vertexFormat, size_t indexSize, size_t vertexSize)
case VF_XYUVCC:
glVB->init(DeviceGraphics::getInstance(), VertexFormat::XY_UV_Two_Color, Usage::DYNAMIC, nullptr, 0, (uint32_t)_vb.getCapacity() / VertexFormat::XY_UV_Two_Color->getBytes());
break;
case VF_XYUVCT:
glVB->init(DeviceGraphics::getInstance(), VertexFormat::XY_UV_Color_TexId, Usage::DYNAMIC, nullptr, 0, (uint32_t)_vb.getCapacity() / VertexFormat::XY_UV_Color_TexId->getBytes());
break;
case VF_XYUVCCT:
glVB->init(DeviceGraphics::getInstance(), VertexFormat::XY_UV_Two_Color_TexId, Usage::DYNAMIC, nullptr, 0, (uint32_t)_vb.getCapacity() / VertexFormat::XY_UV_Two_Color_TexId->getBytes());
break;
default:
CCASSERT(false, "MeshBuffer constructor unknow vertex format");
break;
@@ -126,6 +131,12 @@ void MeshBuffer::next()
case VF_XYUVCC:
glVB->init(DeviceGraphics::getInstance(), VertexFormat::XY_UV_Two_Color, Usage::DYNAMIC, nullptr, 0, (uint32_t)_vb.getCapacity() / VertexFormat::XY_UV_Two_Color->getBytes());
break;
case VF_XYUVCT:
glVB->init(DeviceGraphics::getInstance(), VertexFormat::XY_UV_Color_TexId, Usage::DYNAMIC, nullptr, 0, (uint32_t)_vb.getCapacity() / VertexFormat::XY_UV_Color_TexId->getBytes());
break;
case VF_XYUVCCT:
glVB->init(DeviceGraphics::getInstance(), VertexFormat::XY_UV_Two_Color_TexId, Usage::DYNAMIC, nullptr, 0, (uint32_t)_vb.getCapacity() / VertexFormat::XY_UV_Two_Color_TexId->getBytes());
break;
default:
CCASSERT(false, "MeshBuffer constructor unknow vertex format");
break;

View File

@@ -46,3 +46,6 @@
#define VF_XYUVC 5
#define VF_XYUVCC 6
#define VF_XYUVCT 7
#define VF_XYUVCCT 8

View File

@@ -72,6 +72,45 @@ struct V2F_T2F_C4B_C4B
cocos2d::Color4B color2; // 4 bytes
};
/**
* Vertex Format with x y u v color texId.
*/
struct V2F_T2F_C4B_T1F
{
// vertices (2F)
cocos2d::Vec2 vertex; // 8 bytes
// tex coords (2F)
Tex2F texCoord; // 8 bytes
// colors (4B)
cocos2d::Color4B color; // 4 bytes
// tex id (1F)
GLfloat texId; // 4 bytes
};
/**
* Vertex Format with x y u v color1 color2 texId.
*/
struct V2F_T2F_C4B_C4B_T1F
{
// vertices (2F)
cocos2d::Vec2 vertex; // 8 bytes
// tex coords (2F)
Tex2F texCoord; // 8 bytes
// colors (4B)
cocos2d::Color4B color; // 4 bytes
// colors (4B)
cocos2d::Color4B color2; // 4 bytes
// tex id (1F)
GLfloat texId; // 4 bytes
};
struct Triangles
{
/**Vertex data pointer.*/
@@ -96,6 +135,30 @@ struct TwoColorTriangles
int indexCount = 0;
};
struct TrianglesTexId
{
/**Vertex data pointer.*/
V2F_T2F_C4B_T1F* verts = nullptr;
/**Index data pointer.*/
unsigned short* indices = nullptr;
/**The number of vertices.*/
int vertCount = 0;
/**The number of indices.*/
int indexCount = 0;
};
struct TwoColorTrianglesTexId
{
/**Vertex data pointer.*/
V2F_T2F_C4B_C4B_T1F* verts = nullptr;
/**Index data pointer.*/
unsigned short* indices = nullptr;
/**The number of vertices.*/
int vertCount = 0;
/**The number of indices.*/
int indexCount = 0;
};
///////////////////////////////////////////////////////////////////////
// adapt to editor texture,this is a texture delegate,not real texture
///////////////////////////////////////////////////////////////////////

View File

@@ -52,7 +52,31 @@ namespace spine {
private:
cocos2d::middleware::Texture2D* _texture = nullptr;
};
struct TextureMultiData {
TextureMultiData(float textureId, int vertexFloatCount,
int indexOffset,
cocos2d::renderer::Texture* texture)
: textureId(textureId),
vertexFloatCount(vertexFloatCount),
indexOffset(indexOffset),
texture(texture){};
int vertexFloatCount = 0;
int indexOffset = 0;
float textureId = -1;
cocos2d::renderer::Texture* texture = nullptr;
};
struct SegmentMultiData {
public:
int indexCount = 0;
int vertexFloatCount = 0;
int blendMode = 0;
bool inEffect = false;
std::vector<TextureMultiData> textureDatas;
};
struct BoneData {
cocos2d::Mat4 globalTransformMatrix;
};

View File

@@ -35,12 +35,17 @@
#include "renderer/scene/assembler/CustomAssembler.hpp"
#include "renderer/gfx/Texture.h"
#include "spine-creator-support/AttachUtil.h"
#include <climits>
USING_NS_CC;
USING_NS_MW;
using namespace cocos2d::renderer;
static const std::string techStage = "opaque";
static const std::string textureKey = "texture";
static const std::vector<std::string> textureKeys = {
"texture", "texture2", "texture3", "texture4",
"texture5", "texture6", "texture7", "texture8",
};
namespace spine {
@@ -138,9 +143,77 @@ namespace spine {
}
_curFrameIndex = frameIdx;
}
void SkeletonCacheAnimation::render(float dt) {
std::vector<spine::SkeletonCache::SegmentMultiData>
SkeletonCacheAnimation::toMultiSegments(
const std::vector<spine::SkeletonCache::SegmentData*>& segments){
std::vector<spine::SkeletonCache::SegmentMultiData> multiSegments;
if (segments.size() <= 0) return multiSegments;
auto end = segments.end();
auto cur = segments.begin();
multiSegments.emplace_back();
auto* tmp = &multiSegments.back();
auto getTextureId = [&]() -> float {
auto glID = (*cur)->getTexture()->getNativeTexture()->getHandle();
auto result = _effectTextures.find(glID);
if (result == _effectTextures.end()) {
for (size_t i = 0; i < textureKeys.size(); i++) {
auto prop = _effect->getProperty(textureKeys[i]);
if (prop->getTexture()->getHandle() == glID) {
_effectTextures.insert(std::make_pair(glID, i));
return i;
}
}
_effectTextures.insert(std::make_pair(glID, -1));
return -1;
} else {
return result->second;
}
};
tmp->blendMode = (*cur)->blendMode;
tmp->indexCount = (*cur)->indexCount;
tmp->vertexFloatCount = (*cur)->vertexFloatCount;
float curTextureId = getTextureId();
tmp->textureDatas.emplace_back(curTextureId, (*cur)->vertexFloatCount, 0, (*cur)->getTexture()->getNativeTexture());
tmp->inEffect = curTextureId != -1;
cur++;
while (cur != end)
{
float curTextureId = getTextureId();
float tmpTextureId = tmp->textureDatas[0].textureId;
if ((*cur)->blendMode != tmp->blendMode ||
(tmpTextureId != -1 && curTextureId == -1) ||
tmpTextureId == -1) {
multiSegments.emplace_back();
tmp = &multiSegments.back();
tmp->blendMode = (*cur)->blendMode;
tmp->indexCount = (*cur)->indexCount;
tmp->vertexFloatCount = (*cur)->vertexFloatCount;
tmp->textureDatas.emplace_back(curTextureId, (*cur)->vertexFloatCount, 0, (*cur)->getTexture()->getNativeTexture());
tmp->inEffect = curTextureId != -1;
} else {
tmp->textureDatas.emplace_back(curTextureId, (*cur)->vertexFloatCount, tmp->indexCount, (*cur)->getTexture()->getNativeTexture());
tmp->indexCount += (*cur)->indexCount;
tmp->vertexFloatCount += (*cur)->vertexFloatCount;
}
cur++;
}
return multiSegments;
}
void SkeletonCacheAnimation::render(float dt) {
if (_useMulti) {
renderMulti(dt);
return;
}
if (!_nodeProxy || !_effect) {
return;
}
@@ -377,6 +450,289 @@ namespace spine {
_attachUtil->syncAttachedNode(_nodeProxy, frameData);
}
}
void SkeletonCacheAnimation::renderMulti(float dt) {
if (!_nodeProxy || !_effect) {
return;
}
CustomAssembler* assembler = (CustomAssembler*)_nodeProxy->getAssembler();
if (assembler == nullptr) {
return;
}
assembler->reset();
assembler->setUseModel(!_batch);
if (!_animationData) return;
SkeletonCache::FrameData* frameData = _animationData->getFrameData(_curFrameIndex);
if (!frameData) return;
auto& tmpSegments = frameData->getSegments();
auto& colors = frameData->getColors();
if (tmpSegments.size() == 0 || colors.size() == 0) return;
auto mgr = MiddlewareManager::getInstance();
if (!mgr->isRendering) return;
_nodeColor.a = _nodeProxy->getRealOpacity() / (float)255;
auto vertexFormat = _useTint ? VF_XYUVCCT : VF_XYUVCT;
middleware::MeshBuffer* mb = mgr->getMeshBuffer(vertexFormat);
middleware::IOBuffer& vb = mb->getVB();
middleware::IOBuffer& ib = mb->getIB();
const auto& srcVB = frameData->vb;
const auto& srcIB = frameData->ib;
// vertex size int bytes with one color
int vbs1 = sizeof(V2F_T2F_C4B_T1F);
// vertex size in floats with one color
int vs1 = vbs1 / sizeof(float);
// vertex size int bytes with two color
int vbs2 = sizeof(V2F_T2F_C4B_C4B_T1F);
// vertex size in floats with two color
int vs2 = vbs2 / sizeof(float);
int vbs3 = sizeof(V2F_T2F_C4B);
int vs3 = vbs3 / sizeof(float);
int vbs4 = sizeof(V2F_T2F_C4B_C4B);
int vs4 = vbs4 / sizeof(float);
int vs = _useTint ? vs2 : vs1;
int vbs = _useTint ? vbs2 : vbs1;
const cocos2d::Mat4& nodeWorldMat = _nodeProxy->getWorldMatrix();
int colorOffset = 0;
SkeletonCache::ColorData* nowColor = colors[colorOffset++];
auto maxVFOffset = nowColor->vertexFloatOffset;
Color4B finalColor;
Color4B darkColor;
float tempR = 0.0f, tempG = 0.0f, tempB = 0.0f, tempA = 0.0f;
float multiplier = 1.0f;
int srcVertexBytesOffset = 0;
int srcVertexBytes = 0;
int vertexBytes = 0;
int vertexFloats = 0;
int tintBytes = 0;
int srcIndexBytesOffset = 0;
int indexBytes = 0;
GLuint textureHandle = 0;
double effectHash = 0;
int blendMode = 0;
int dstVertexOffset = 0;
float* dstVertexBuffer = nullptr;
unsigned int* dstColorBuffer = nullptr;
unsigned short* dstIndexBuffer = nullptr;
bool needColor = false;
BlendFactor curBlendSrc = BlendFactor::ONE;
BlendFactor curBlendDst = BlendFactor::ZERO;
if (abs(_nodeColor.r - 1.0f) > 0.0001f ||
abs(_nodeColor.g - 1.0f) > 0.0001f ||
abs(_nodeColor.b - 1.0f) > 0.0001f ||
abs(_nodeColor.a - 1.0f) > 0.0001f ||
_premultipliedAlpha) {
needColor = true;
}
auto handleColor = [&](SkeletonCache::ColorData* colorData){
tempA = colorData->finalColor.a * _nodeColor.a;
multiplier = _premultipliedAlpha ? tempA / 255 : 1;
tempR = _nodeColor.r * multiplier;
tempG = _nodeColor.g * multiplier;
tempB = _nodeColor.b * multiplier;
finalColor.a = (GLubyte)tempA;
finalColor.r = (GLubyte)(colorData->finalColor.r * tempR);
finalColor.g = (GLubyte)(colorData->finalColor.g * tempG);
finalColor.b = (GLubyte)(colorData->finalColor.b * tempB);
darkColor.r = (GLubyte)(colorData->darkColor.r * tempR);
darkColor.g = (GLubyte)(colorData->darkColor.g * tempG);
darkColor.b = (GLubyte)(colorData->darkColor.b * tempB);
darkColor.a = _premultipliedAlpha ? 255 : 0;
};
handleColor(nowColor);
// 重新生成多纹理使用的 segments
auto segments = toMultiSegments(tmpSegments);
for (std::size_t segIndex = 0, segLen = segments.size(); segIndex < segLen; segIndex++) {
auto segment = &segments[segIndex];
srcVertexBytes = segment->vertexFloatCount * sizeof(float);
if (!_useTint) {
vertexBytes = srcVertexBytes;
vertexFloats = segment->vertexFloatCount;
} else {
tintBytes = segment->vertexFloatCount / vs4 * sizeof(float);
vertexBytes = srcVertexBytes + tintBytes;
vertexFloats = vertexBytes / sizeof(float);
}
// fill vertex buffer
vb.checkSpace(vertexBytes, true);
dstVertexOffset = (int)vb.getCurPos() / vbs;
dstVertexBuffer = (float*)vb.getCurBuffer();
dstColorBuffer = (unsigned int*)vb.getCurBuffer();
char* srcBuffer = (char*)srcVB.getBuffer() + srcVertexBytesOffset;
auto curTextureData = segment->textureDatas.begin();
auto curTextureDataVfc = (*curTextureData).vertexFloatCount * sizeof(float);
if (!_useTint) {
int t = 0;
for (std::size_t srcBufferIdx = 0; srcBufferIdx < srcVertexBytes; srcBufferIdx += vbs4) {
if (curTextureDataVfc <= srcBufferIdx) {
curTextureData++;
curTextureDataVfc += (*curTextureData).vertexFloatCount * sizeof(float);
}
vb.writeBytes(srcBuffer + srcBufferIdx, vbs3);
vb.writeFloat32((*curTextureData).textureId);
}
} else {
for (std::size_t srcBufferIdx = 0; srcBufferIdx < srcVertexBytes; srcBufferIdx += vbs4) {
if (curTextureDataVfc <= srcBufferIdx) {
curTextureData++;
curTextureDataVfc += (*curTextureData).vertexFloatCount * sizeof(float);
}
vb.writeBytes(srcBuffer + srcBufferIdx, vbs4);
vb.writeFloat32((*curTextureData).textureId);
}
}
// batch handle
if (_batch) {
cocos2d::Vec3* point = nullptr;
float tempZ = 0.0f;
for (auto posIndex = 0; posIndex < vertexFloats; posIndex += vs)
{
point = (cocos2d::Vec3*)(dstVertexBuffer + posIndex);
tempZ = point->z;
point->z = 0;
nodeWorldMat.transformPoint(point);
point->z = tempZ;
}
}
// handle vertex color
if (needColor) {
int srcVertexFloatOffset = srcVertexBytesOffset / sizeof(float);
if (_useTint) {
for (auto colorIndex = 0; colorIndex < vertexFloats; colorIndex += vs, srcVertexFloatOffset += vs4)
{
if (srcVertexFloatOffset >= maxVFOffset) {
nowColor = colors[colorOffset++];
handleColor(nowColor);
maxVFOffset = nowColor->vertexFloatOffset;
}
memcpy(dstColorBuffer + colorIndex + 4, &finalColor, sizeof(finalColor));
memcpy(dstColorBuffer + colorIndex + 5, &darkColor, sizeof(darkColor));
}
} else {
for (auto colorIndex = 0; colorIndex < vertexFloats; colorIndex += vs, srcVertexFloatOffset += vs4)
{
if (srcVertexFloatOffset >= maxVFOffset) {
nowColor = colors[colorOffset++];
handleColor(nowColor);
maxVFOffset = nowColor->vertexFloatOffset;
}
memcpy(dstColorBuffer + colorIndex + 4, &finalColor, sizeof(finalColor));
}
}
}
// move src vertex buffer offset
srcVertexBytesOffset += srcVertexBytes;
// fill index buffer
indexBytes = segment->indexCount * sizeof(unsigned short);
ib.checkSpace(indexBytes, true);
assembler->updateIARange(segIndex, (int)ib.getCurPos() / sizeof(unsigned short), segment->indexCount);
dstIndexBuffer = (unsigned short*)ib.getCurBuffer();
ib.writeBytes((char*)srcIB.getBuffer() + srcIndexBytesOffset, indexBytes);
curTextureData = ++segment->textureDatas.begin();
curTextureDataVfc = 0;
auto leftTextureData = segment->textureDatas.begin();
auto curTextureDataIo = curTextureData == segment->textureDatas.end() ? INT_MAX : (*curTextureData).indexOffset;
for (auto indexPos = 0; indexPos < segment->indexCount; indexPos++) {
if (curTextureDataIo <= indexPos) {
curTextureDataVfc += (*leftTextureData).vertexFloatCount / vs4;
leftTextureData = curTextureData;
curTextureData++;
curTextureDataIo = curTextureData == segment->textureDatas.end() ? INT_MAX : (*curTextureData).indexOffset;
}
dstIndexBuffer[indexPos] += dstVertexOffset + curTextureDataVfc;
}
srcIndexBytesOffset += indexBytes;
// set assembler glvb and glib
assembler->updateIABuffer(segIndex, mb->getGLVB(), mb->getGLIB());
// handle material
blendMode = segment->blendMode;
effectHash =
segment->inEffect
? ((blendMode << 16) + ((int)_useTint << 24) +
((int)_batch << 25) + ((int)_effect->getHash() << 26))
: (segment->textureDatas[0].texture->getHandle() + (blendMode << 16) + ((int)_useTint << 24) +
((int)_batch << 25) + ((int)_effect->getHash() << 26));
EffectVariant* renderEffect = assembler->getEffect(segIndex);
bool needUpdate = false;
if (renderEffect) {
double renderHash = renderEffect->getHash();
if (abs(renderHash - effectHash) >= 0.01) {
needUpdate = true;
}
}
else {
auto effect = new cocos2d::renderer::EffectVariant();
effect->autorelease();
effect->copy(_effect);
assembler->updateEffect(segIndex, effect);
renderEffect = effect;
needUpdate = true;
}
if (needUpdate) {
if (!segment->inEffect) {
renderEffect->setProperty(textureKey, segment->textureDatas[0].texture);
}
switch (blendMode) {
case BlendMode_Additive:
curBlendSrc = _premultipliedAlpha ? BlendFactor::ONE : BlendFactor::SRC_ALPHA;
curBlendDst = BlendFactor::ONE;
break;
case BlendMode_Multiply:
curBlendSrc = BlendFactor::DST_COLOR;
curBlendDst = BlendFactor::ONE_MINUS_SRC_ALPHA;
break;
case BlendMode_Screen:
curBlendSrc = BlendFactor::ONE;
curBlendDst = BlendFactor::ONE_MINUS_SRC_COLOR;
break;
default:
curBlendSrc = _premultipliedAlpha ? BlendFactor::ONE : BlendFactor::SRC_ALPHA;
curBlendDst = BlendFactor::ONE_MINUS_SRC_ALPHA;
}
renderEffect->setBlend(true, BlendOp::ADD, curBlendSrc, curBlendDst,
BlendOp::ADD, curBlendSrc, curBlendDst);
}
renderEffect->updateHash(effectHash);
}
if (_attachUtil)
{
_attachUtil->syncAttachedNode(_nodeProxy, frameData);
}
}
Skeleton* SkeletonCacheAnimation::getSkeleton() const {
return _skeletonCache->getSkeleton();
@@ -466,7 +822,11 @@ namespace spine {
void SkeletonCacheAnimation::setUseTint(bool enabled) {
_useTint = enabled;
}
void SkeletonCacheAnimation::setUseMulti(bool enabled) {
_useMulti = enabled;
}
void SkeletonCacheAnimation::setAnimation (const std::string& name, bool loop) {
_playTimes = loop ? 0 : 1;
_animationName = name;
@@ -524,6 +884,7 @@ namespace spine {
}
void SkeletonCacheAnimation::setEffect(cocos2d::renderer::EffectVariant* effect) {
_effectTextures.clear();
if (effect == _effect) return;
CC_SAFE_RELEASE(_effect);
_effect = effect;

View File

@@ -47,7 +47,11 @@ namespace spine {
virtual void update(float dt) override;
virtual void render(float dt) override;
virtual uint32_t getRenderOrder() const override;
void renderMulti(float dt);
std::vector<spine::SkeletonCache::SegmentMultiData> toMultiSegments(
const std::vector<spine::SkeletonCache::SegmentData*>& segments);
Skeleton* getSkeleton() const;
void setTimeScale (float scale);
@@ -78,7 +82,8 @@ namespace spine {
void onEnable();
void onDisable();
void setUseTint(bool enabled);
void setUseMulti(bool enabled);
void setAnimation (const std::string& name, bool loop);
void addAnimation (const std::string& name, bool loop, float delay = 0);
Animation* findAnimation(const std::string& name) const;
@@ -118,7 +123,8 @@ namespace spine {
bool _isAniComplete = true;
std::string _animationName = "";
bool _useTint = false;
bool _useMulti = false;
struct AniQueueData {
std::string animationName = "";
bool loop = false;
@@ -127,5 +133,7 @@ namespace spine {
std::queue<AniQueueData*> _animationQueue;
AniQueueData* _headAnimation = nullptr;
CacheModeAttachUtil* _attachUtil = nullptr;
std::unordered_map<GLuint, float> _effectTextures = std::unordered_map<GLuint, float>();
};
}

View File

@@ -39,6 +39,7 @@
#include "SkeletonDataMgr.h"
#include "renderer/gfx/Texture.h"
#include "spine-creator-support/AttachUtil.h"
#include <utility>
USING_NS_CC;
USING_NS_MW;
@@ -51,6 +52,10 @@ using namespace cocos2d::renderer;
static const std::string techStage = "opaque";
static const std::string textureKey = "texture";
static const std::vector<std::string> textureKeys = {
"texture", "texture2", "texture3", "texture4",
"texture5", "texture6", "texture7", "texture8",
};
static Cocos2dTextureLoader textureLoader;
@@ -286,17 +291,17 @@ void SkeletonRenderer::render (float deltaTime) {
Color4F darkColor;
AttachmentVertices* attachmentVertices = nullptr;
bool inRange = _startSlotIndex != -1 || _endSlotIndex != -1 ? false : true;
auto vertexFormat = _useTint? VF_XYUVCC : VF_XYUVC;
auto vertexFormat = _useMulti ? (_useTint ? VF_XYUVCCT : VF_XYUVCT) : (_useTint? VF_XYUVCC : VF_XYUVC);
middleware::MeshBuffer* mb = mgr->getMeshBuffer(vertexFormat);
middleware::IOBuffer& vb = mb->getVB();
middleware::IOBuffer& ib = mb->getIB();
// vertex size int bytes with one color
int vbs1 = sizeof(V2F_T2F_C4B);
// vertex size in floats with one color
int vbs1 = _useMulti ? sizeof(V2F_T2F_C4B_T1F) : sizeof(V2F_T2F_C4B);
// vertex size in floats with one color
int vs1 = vbs1 / sizeof(float);
// vertex size int bytes with two color
int vbs2 = sizeof(V2F_T2F_C4B_C4B);
int vbs2 = _useMulti ? sizeof(V2F_T2F_C4B_C4B_T1F) :sizeof(V2F_T2F_C4B_C4B);
// verex size in floats with two color
int vs2 = vbs2 / sizeof(float);
const cocos2d::Mat4& nodeWorldMat = _nodeProxy->getWorldMatrix();
@@ -310,8 +315,11 @@ void SkeletonRenderer::render (float deltaTime) {
int preBlendMode = -1;
GLuint preTextureIndex = -1;
GLuint curTextureIndex = -1;
int preISegWritePos = -1;
float curTextureId = -1;
bool texInEffect = false;
int preISegWritePos = -1;
int curISegLen = 0;
int materialLen = 0;
@@ -353,8 +361,14 @@ void SkeletonRenderer::render (float deltaTime) {
curBlendSrc = _premultipliedAlpha ? BlendFactor::ONE : BlendFactor::SRC_ALPHA;
curBlendDst = BlendFactor::ONE_MINUS_SRC_ALPHA;
}
double curHash = curTextureIndex + (curBlendMode << 16) + ((int)_useTint << 24) + ((int)_batch << 25) + ((int)_effect->getHash() << 26);
double curHash =
(_useMulti && texInEffect)
? ((curBlendMode << 16) + ((int)_useTint << 24) +
((int)_batch << 25) + ((int)_effect->getHash() << 26))
: (curTextureIndex + (curBlendMode << 16) +
((int)_useTint << 24) + ((int)_batch << 25) +
((int)_effect->getHash() << 26));
EffectVariant* renderEffect = assembler->getEffect(materialLen);
bool needUpdate = false;
if (renderEffect) {
@@ -374,7 +388,10 @@ void SkeletonRenderer::render (float deltaTime) {
}
if (needUpdate) {
renderEffect->setProperty(textureKey, texture->getNativeTexture());
if (!_useMulti || !texInEffect) {
renderEffect->setProperty(textureKey,
texture->getNativeTexture());
}
renderEffect->setBlend(true, BlendOp::ADD, curBlendSrc, curBlendDst,
BlendOp::ADD, curBlendSrc, curBlendDst);
}
@@ -439,6 +456,8 @@ void SkeletonRenderer::render (float deltaTime) {
Triangles triangles;
TwoColorTriangles trianglesTwoColor;
TrianglesTexId trianglesTexId;
TwoColorTrianglesTexId trianglesTwoColorTexId;
if (slot->getAttachment()->getRTTI().isExactly(RegionAttachment::rtti)) {
RegionAttachment* attachment = (RegionAttachment*)slot->getAttachment();
@@ -450,34 +469,68 @@ void SkeletonRenderer::render (float deltaTime) {
continue;
}
if (!_useTint) {
triangles.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = triangles.vertCount * sizeof(V2F_T2F_C4B);
isFull |= vb.checkSpace(vbSize, true);
triangles.verts = (V2F_T2F_C4B*)vb.getCurBuffer();
memcpy(triangles.verts, attachmentVertices->_triangles->verts, vbSize);
attachment->computeWorldVertices(slot->getBone(), (float*)triangles.verts, 0, vs1);
if (!_useMulti) {
if (!_useTint) {
triangles.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = triangles.vertCount * sizeof(V2F_T2F_C4B);
isFull |= vb.checkSpace(vbSize, true);
triangles.verts = (V2F_T2F_C4B*)vb.getCurBuffer();
memcpy(triangles.verts, attachmentVertices->_triangles->verts, vbSize);
attachment->computeWorldVertices(slot->getBone(), (float*)triangles.verts, 0, vs1);
triangles.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = triangles.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
triangles.indices = (unsigned short*)ib.getCurBuffer();
memcpy(triangles.indices, attachmentVertices->_triangles->indices, ibSize);
} else {
trianglesTwoColor.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTwoColor.vertCount * sizeof(V2F_T2F_C4B_C4B);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColor.verts = (V2F_T2F_C4B_C4B*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTwoColor.vertCount; ii++) {
trianglesTwoColor.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
triangles.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = triangles.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
triangles.indices = (unsigned short*)ib.getCurBuffer();
memcpy(triangles.indices, attachmentVertices->_triangles->indices, ibSize);
} else {
trianglesTwoColor.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTwoColor.vertCount * sizeof(V2F_T2F_C4B_C4B);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColor.verts = (V2F_T2F_C4B_C4B*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTwoColor.vertCount; ii++) {
trianglesTwoColor.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
}
attachment->computeWorldVertices(slot->getBone(), (float*)trianglesTwoColor.verts, 0, vs2);
trianglesTwoColor.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTwoColor.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTwoColor.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColor.indices, attachmentVertices->_triangles->indices, ibSize);
}
} else {
if (!_useTint) {
trianglesTexId.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTexId.vertCount * sizeof(V2F_T2F_C4B_T1F);
isFull |= vb.checkSpace(vbSize, true);
trianglesTexId.verts = (V2F_T2F_C4B_T1F*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTexId.vertCount; ii++) {
trianglesTexId.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
}
attachment->computeWorldVertices(slot->getBone(), (float*)trianglesTexId.verts, 0, vs1);
trianglesTexId.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTexId.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTexId.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTexId.indices, attachmentVertices->_triangles->indices, ibSize);
} else {
trianglesTwoColorTexId.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTwoColorTexId.vertCount * sizeof(V2F_T2F_C4B_C4B_T1F);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColorTexId.verts = (V2F_T2F_C4B_C4B_T1F*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTwoColorTexId.vertCount; ii++) {
trianglesTwoColorTexId.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
}
attachment->computeWorldVertices(slot->getBone(), (float*)trianglesTwoColorTexId.verts, 0, vs2);
trianglesTwoColorTexId.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTwoColorTexId.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTwoColorTexId.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColorTexId.indices, attachmentVertices->_triangles->indices, ibSize);
}
attachment->computeWorldVertices(slot->getBone(), (float*)trianglesTwoColor.verts, 0, vs2);
trianglesTwoColor.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTwoColor.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTwoColor.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColor.indices, attachmentVertices->_triangles->indices, ibSize);
}
color.r = attachment->getColor().r;
@@ -488,7 +541,11 @@ void SkeletonRenderer::render (float deltaTime) {
if(_debugSlots) {
_debugBuffer->writeFloat32(DebugType::Slots);
_debugBuffer->writeFloat32(8);
float* vertices = _useTint ? (float*)trianglesTwoColor.verts : (float*)triangles.verts;
float* vertices =
_useMulti ? (_useTint ? (float*)trianglesTwoColorTexId.verts
: (float*)trianglesTexId.verts)
: (_useTint ? (float*)trianglesTwoColor.verts
: (float*)triangles.verts);
int stride = _useTint ? vs2 : vs1;
// Quadrangle has 4 vertex.
for (int ii = 0; ii < 4; ii ++) {
@@ -507,34 +564,68 @@ void SkeletonRenderer::render (float deltaTime) {
continue;
}
if (!_useTint) {
triangles.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = triangles.vertCount * sizeof(V2F_T2F_C4B);
isFull |= vb.checkSpace(vbSize, true);
triangles.verts = (V2F_T2F_C4B*)vb.getCurBuffer();
memcpy(triangles.verts, attachmentVertices->_triangles->verts, vbSize);
attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float*)triangles.verts, 0, vs1);
if (!_useMulti) {
if (!_useTint) {
triangles.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = triangles.vertCount * sizeof(V2F_T2F_C4B);
isFull |= vb.checkSpace(vbSize, true);
triangles.verts = (V2F_T2F_C4B*)vb.getCurBuffer();
memcpy(triangles.verts, attachmentVertices->_triangles->verts, vbSize);
attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float*)triangles.verts, 0, vs1);
triangles.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = triangles.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
triangles.indices = (unsigned short*)ib.getCurBuffer();
memcpy(triangles.indices, attachmentVertices->_triangles->indices, ibSize);
} else {
trianglesTwoColor.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTwoColor.vertCount * sizeof(V2F_T2F_C4B_C4B);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColor.verts = (V2F_T2F_C4B_C4B*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTwoColor.vertCount; ii++) {
trianglesTwoColor.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
triangles.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = triangles.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
triangles.indices = (unsigned short*)ib.getCurBuffer();
memcpy(triangles.indices, attachmentVertices->_triangles->indices, ibSize);
} else {
trianglesTwoColor.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTwoColor.vertCount * sizeof(V2F_T2F_C4B_C4B);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColor.verts = (V2F_T2F_C4B_C4B*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTwoColor.vertCount; ii++) {
trianglesTwoColor.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
}
attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float*)trianglesTwoColor.verts, 0, vs2);
trianglesTwoColor.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTwoColor.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTwoColor.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColor.indices, attachmentVertices->_triangles->indices, ibSize);
}
} else {
if (!_useTint) {
trianglesTexId.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTexId.vertCount * sizeof(V2F_T2F_C4B_T1F);
isFull |= vb.checkSpace(vbSize, true);
trianglesTexId.verts = (V2F_T2F_C4B_T1F*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTexId.vertCount; ii++) {
trianglesTexId.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
}
attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float*)trianglesTexId.verts, 0, vs1);
trianglesTexId.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTexId.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTexId.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTexId.indices, attachmentVertices->_triangles->indices, ibSize);
} else {
trianglesTwoColorTexId.vertCount = attachmentVertices->_triangles->vertCount;
vbSize = trianglesTwoColorTexId.vertCount * sizeof(V2F_T2F_C4B_C4B_T1F);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColorTexId.verts = (V2F_T2F_C4B_C4B_T1F*)vb.getCurBuffer();
for (int ii = 0; ii < trianglesTwoColorTexId.vertCount; ii++) {
trianglesTwoColorTexId.verts[ii].texCoord = attachmentVertices->_triangles->verts[ii].texCoord;
}
attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float*)trianglesTwoColorTexId.verts, 0, vs2);
trianglesTwoColorTexId.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTwoColorTexId.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTwoColorTexId.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColorTexId.indices, attachmentVertices->_triangles->indices, ibSize);
}
attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float*)trianglesTwoColor.verts, 0, vs2);
trianglesTwoColor.indexCount = attachmentVertices->_triangles->indexCount;
ibSize = trianglesTwoColor.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTwoColor.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColor.indices, attachmentVertices->_triangles->indices, ibSize);
}
color.r = attachment->getColor().r;
@@ -543,10 +634,23 @@ void SkeletonRenderer::render (float deltaTime) {
color.a = attachment->getColor().a;
if(_debugMesh) {
int indexCount = _useTint ? trianglesTwoColor.indexCount : triangles.indexCount;
unsigned short* indices = _useTint ? (unsigned short*)trianglesTwoColor.indices : (unsigned short*)triangles.indices;
float* vertices = _useTint ? (float*)trianglesTwoColor.verts : (float*)triangles.verts;
int indexCount =
_useMulti ? (_useTint ? trianglesTwoColorTexId.indexCount
: trianglesTexId.indexCount)
: (_useTint ? trianglesTwoColor.indexCount
: triangles.indexCount);
unsigned short* indices =
_useMulti
? (_useTint ? (unsigned short*)trianglesTwoColorTexId.indices
: (unsigned short*)trianglesTexId.indices)
: (_useTint ? (unsigned short*)trianglesTwoColor.indices
: (unsigned short*)triangles.indices);
float* vertices =
_useMulti ? (_useTint ? (float*)trianglesTwoColorTexId.verts
: (float*)trianglesTexId.verts)
: (_useTint ? (float*)trianglesTwoColor.verts
: (float*)triangles.verts);
int stride = _useTint ? vs2 : vs1;
_debugBuffer->writeFloat32(DebugType::Mesh);
_debugBuffer->writeFloat32(indexCount * 2);
@@ -598,214 +702,465 @@ void SkeletonRenderer::render (float deltaTime) {
darkColor.b = 0;
}
darkColor.a = _premultipliedAlpha ? 255 : 0;
// One color tint logic
if (!_useTint) {
// Cliping logic
if (_clipper->isClipping()) {
_clipper->clipTriangles((float*)&triangles.verts[0].vertex, triangles.indices, triangles.indexCount, (float*)&triangles.verts[0].texCoord, vs1);
if (_clipper->getClippedTriangles().size() == 0) {
_clipper->clipEnd(*slot);
continue;
}
triangles.vertCount = (int)_clipper->getClippedVertices().size() >> 1;
vbSize = triangles.vertCount * sizeof(V2F_T2F_C4B);
isFull |= vb.checkSpace(vbSize, true);
triangles.verts = (V2F_T2F_C4B*)vb.getCurBuffer();
triangles.indexCount = (int)_clipper->getClippedTriangles().size();
ibSize = triangles.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
triangles.indices = (unsigned short*)ib.getCurBuffer();
memcpy(triangles.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
float* verts = _clipper->getClippedVertices().buffer();
float* uvs = _clipper->getClippedUVs().buffer();
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = triangles.vertCount, vv = 0; v < vn; ++v, vv+=2) {
V2F_T2F_C4B* vertex = triangles.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
}
} else {
for (int v = 0, vn = triangles.vertCount, vv = 0; v < vn; ++v, vv+=2) {
V2F_T2F_C4B* vertex = triangles.verts + v;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
}
}
// No cliping logic
} else {
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = triangles.vertCount; v < vn; ++v) {
V2F_T2F_C4B* vertex = triangles.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
}
} else {
for (int v = 0, vn = triangles.vertCount; v < vn; ++v) {
V2F_T2F_C4B* vertex = triangles.verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
}
}
}
}
// Two color tint logic
else {
if (_clipper->isClipping()) {
_clipper->clipTriangles((float*)&trianglesTwoColor.verts[0].vertex, trianglesTwoColor.indices, trianglesTwoColor.indexCount, (float*)&trianglesTwoColor.verts[0].texCoord, vs2);
if (_clipper->getClippedTriangles().size() == 0) {
_clipper->clipEnd(*slot);
continue;
}
trianglesTwoColor.vertCount = (int)_clipper->getClippedVertices().size() >> 1;
vbSize = trianglesTwoColor.vertCount * sizeof(V2F_T2F_C4B_C4B);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColor.verts = (V2F_T2F_C4B_C4B*)vb.getCurBuffer();
trianglesTwoColor.indexCount = (int)_clipper->getClippedTriangles().size();
ibSize = trianglesTwoColor.indexCount * sizeof(unsigned short);
trianglesTwoColor.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColor.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
float* verts = _clipper->getClippedVertices().buffer();
float* uvs = _clipper->getClippedUVs().buffer();
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
for (int v = 0, vn = trianglesTwoColor.vertCount, vv = 0; v < vn; ++v, vv += 2) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = (GLubyte)darkColor.a;
}
} else {
for (int v = 0, vn = trianglesTwoColor.vertCount, vv = 0; v < vn; ++v, vv += 2) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = (GLubyte)darkColor.a;
}
}
} else {
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
if (!_useMulti) {
// One color tint logic
if (!_useTint) {
// Cliping logic
if (_clipper->isClipping()) {
_clipper->clipTriangles((float*)&triangles.verts[0].vertex, triangles.indices, triangles.indexCount, (float*)&triangles.verts[0].texCoord, vs1);
for (int v = 0, vn = trianglesTwoColor.vertCount; v < vn; ++v) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = (GLubyte)darkColor.a;
if (_clipper->getClippedTriangles().size() == 0) {
_clipper->clipEnd(*slot);
continue;
}
triangles.vertCount = (int)_clipper->getClippedVertices().size() >> 1;
vbSize = triangles.vertCount * sizeof(V2F_T2F_C4B);
isFull |= vb.checkSpace(vbSize, true);
triangles.verts = (V2F_T2F_C4B*)vb.getCurBuffer();
triangles.indexCount = (int)_clipper->getClippedTriangles().size();
ibSize = triangles.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
triangles.indices = (unsigned short*)ib.getCurBuffer();
memcpy(triangles.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
float* verts = _clipper->getClippedVertices().buffer();
float* uvs = _clipper->getClippedUVs().buffer();
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = triangles.vertCount, vv = 0; v < vn; ++v, vv+=2) {
V2F_T2F_C4B* vertex = triangles.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
}
} else {
for (int v = 0, vn = triangles.vertCount, vv = 0; v < vn; ++v, vv+=2) {
V2F_T2F_C4B* vertex = triangles.verts + v;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
}
}
// No cliping logic
} else {
for (int v = 0, vn = trianglesTwoColor.vertCount; v < vn; ++v) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = (GLubyte)darkColor.a;
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = triangles.vertCount; v < vn; ++v) {
V2F_T2F_C4B* vertex = triangles.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
}
} else {
for (int v = 0, vn = triangles.vertCount; v < vn; ++v) {
V2F_T2F_C4B* vertex = triangles.verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
}
}
}
}
// Two color tint logic
else {
if (_clipper->isClipping()) {
_clipper->clipTriangles((float*)&trianglesTwoColor.verts[0].vertex, trianglesTwoColor.indices, trianglesTwoColor.indexCount, (float*)&trianglesTwoColor.verts[0].texCoord, vs2);
if (_clipper->getClippedTriangles().size() == 0) {
_clipper->clipEnd(*slot);
continue;
}
trianglesTwoColor.vertCount = (int)_clipper->getClippedVertices().size() >> 1;
vbSize = trianglesTwoColor.vertCount * sizeof(V2F_T2F_C4B_C4B);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColor.verts = (V2F_T2F_C4B_C4B*)vb.getCurBuffer();
trianglesTwoColor.indexCount = (int)_clipper->getClippedTriangles().size();
ibSize = trianglesTwoColor.indexCount * sizeof(unsigned short);
trianglesTwoColor.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColor.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
float* verts = _clipper->getClippedVertices().buffer();
float* uvs = _clipper->getClippedUVs().buffer();
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
for (int v = 0, vn = trianglesTwoColor.vertCount, vv = 0; v < vn; ++v, vv += 2) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = (GLubyte)darkColor.a;
}
} else {
for (int v = 0, vn = trianglesTwoColor.vertCount, vv = 0; v < vn; ++v, vv += 2) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = (GLubyte)darkColor.a;
}
}
} else {
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
for (int v = 0, vn = trianglesTwoColor.vertCount; v < vn; ++v) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = (GLubyte)darkColor.a;
}
} else {
for (int v = 0, vn = trianglesTwoColor.vertCount; v < vn; ++v) {
V2F_T2F_C4B_C4B* vertex = trianglesTwoColor.verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = (GLubyte)darkColor.a;
}
}
}
}
texture = attachmentVertices->_texture;
curTextureIndex =
attachmentVertices->_texture->getNativeTexture()->getHandle();
// If texture or blendMode change,will change material.
if (preTextureIndex != curTextureIndex ||
preBlendMode != slot->getData().getBlendMode() || isFull) {
flush();
}
}
texture = attachmentVertices->_texture;
curTextureIndex = attachmentVertices->_texture->getNativeTexture()->getHandle();
// If texture or blendMode change,will change material.
if (preTextureIndex != curTextureIndex || preBlendMode != slot->getData().getBlendMode() || isFull) {
flush();
else {
texture = attachmentVertices->_texture;
curTextureIndex = attachmentVertices->_texture->getNativeTexture()->getHandle();
auto result = _effectTextures.find(curTextureIndex);
if (result == _effectTextures.end()) {
curTextureId = -1;
for (size_t i = 0; i < textureKeys.size(); i++) {
auto prop = _effect->getProperty(textureKeys[i]);
if (prop->getTexture()->getHandle() == curTextureIndex) {
curTextureId = i;
break;
}
}
_effectTextures.insert(std::make_pair(
curTextureIndex, curTextureId));
} else {
curTextureId = result->second;
}
if (curTextureId == -1) {
curTextureId = 0;
texInEffect = false;
} else {
texInEffect = true;
}
// One color tint logic
if (!_useTint) {
// Cliping logic
if (_clipper->isClipping()) {
_clipper->clipTriangles((float*)&trianglesTexId.verts[0].vertex, trianglesTexId.indices, trianglesTexId.indexCount, (float*)&trianglesTexId.verts[0].texCoord, vs1);
if (_clipper->getClippedTriangles().size() == 0) {
_clipper->clipEnd(*slot);
continue;
}
trianglesTexId.vertCount = (int)_clipper->getClippedVertices().size() >> 1;
vbSize = trianglesTexId.vertCount * sizeof(V2F_T2F_C4B_T1F);
isFull |= vb.checkSpace(vbSize, true);
trianglesTexId.verts = (V2F_T2F_C4B_T1F*)vb.getCurBuffer();
trianglesTexId.indexCount = (int)_clipper->getClippedTriangles().size();
ibSize = trianglesTexId.indexCount * sizeof(unsigned short);
ib.checkSpace(ibSize, true);
trianglesTexId.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTexId.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
float* verts = _clipper->getClippedVertices().buffer();
float* uvs = _clipper->getClippedUVs().buffer();
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = trianglesTexId.vertCount, vv = 0; v < vn; ++v, vv+=2) {
V2F_T2F_C4B_T1F* vertex = trianglesTexId.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->texId = (GLfloat)(curTextureId);
}
} else {
for (int v = 0, vn = trianglesTexId.vertCount, vv = 0; v < vn; ++v, vv+=2) {
V2F_T2F_C4B_T1F* vertex = trianglesTexId.verts + v;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->texId = (GLfloat)(curTextureId);
}
}
// No cliping logic
} else {
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = trianglesTexId.vertCount; v < vn; ++v) {
V2F_T2F_C4B_T1F* vertex = trianglesTexId.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->texId = (GLfloat)(curTextureId);
}
} else {
for (int v = 0, vn = trianglesTexId.vertCount; v < vn; ++v) {
V2F_T2F_C4B_T1F* vertex = trianglesTexId.verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->texId = (GLfloat)(curTextureId);
}
}
}
}
// Two color tint logic
else {
if (_clipper->isClipping()) {
_clipper->clipTriangles((float*)&trianglesTwoColorTexId.verts[0].vertex, trianglesTwoColorTexId.indices, trianglesTwoColorTexId.indexCount, (float*)&trianglesTwoColorTexId.verts[0].texCoord, vs2);
if (_clipper->getClippedTriangles().size() == 0) {
_clipper->clipEnd(*slot);
continue;
}
trianglesTwoColorTexId.vertCount = (int)_clipper->getClippedVertices().size() >> 1;
vbSize = trianglesTwoColorTexId.vertCount * sizeof(V2F_T2F_C4B_C4B_T1F);
isFull |= vb.checkSpace(vbSize, true);
trianglesTwoColorTexId.verts = (V2F_T2F_C4B_C4B_T1F*)vb.getCurBuffer();
trianglesTwoColorTexId.indexCount = (int)_clipper->getClippedTriangles().size();
ibSize = trianglesTwoColorTexId.indexCount * sizeof(unsigned short);
trianglesTwoColorTexId.indices = (unsigned short*)ib.getCurBuffer();
memcpy(trianglesTwoColorTexId.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
float* verts = _clipper->getClippedVertices().buffer();
float* uvs = _clipper->getClippedUVs().buffer();
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
for (int v = 0, vn = trianglesTwoColorTexId.vertCount, vv = 0; v < vn; ++v, vv += 2) {
V2F_T2F_C4B_C4B_T1F* vertex = trianglesTwoColorTexId.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = (GLubyte)darkColor.a;
vertex->texId = (GLfloat)(curTextureId);
}
} else {
for (int v = 0, vn = trianglesTwoColorTexId.vertCount, vv = 0; v < vn; ++v, vv += 2) {
V2F_T2F_C4B_C4B_T1F* vertex = trianglesTwoColorTexId.verts + v;
vertex->vertex.x = verts[vv];
vertex->vertex.y = verts[vv + 1];
vertex->texCoord.u = uvs[vv];
vertex->texCoord.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = (GLubyte)darkColor.a;
vertex->texId = (GLfloat)(curTextureId);
}
}
} else {
if (effect) {
Color light;
Color dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
for (int v = 0, vn = trianglesTwoColorTexId.vertCount; v < vn; ++v) {
V2F_T2F_C4B_C4B_T1F* vertex = trianglesTwoColorTexId.verts + v;
Color lightCopy = light;
Color darkCopy = dark;
effect->transform(vertex->vertex.x, vertex->vertex.y, vertex->texCoord.u, vertex->texCoord.v, lightCopy, darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = (GLubyte)darkColor.a;
vertex->texId = (GLfloat)(curTextureId);
}
} else {
for (int v = 0, vn = trianglesTwoColorTexId.vertCount; v < vn; ++v) {
V2F_T2F_C4B_C4B_T1F* vertex = trianglesTwoColorTexId.verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = (GLubyte)darkColor.a;
vertex->texId = (GLfloat)(curTextureId);
}
}
}
}
if (texInEffect) {
if (preBlendMode != slot->getData().getBlendMode() || isFull) {
flush();
}
} else if (preTextureIndex != curTextureIndex ||
preBlendMode != slot->getData().getBlendMode() ||
isFull) {
flush();
}
}
if (vbSize > 0 && ibSize > 0) {
@@ -999,6 +1354,10 @@ void SkeletonRenderer::setUseTint(bool enabled) {
_useTint = enabled;
}
void SkeletonRenderer::setUseMulti(bool enabled) {
_useMulti = enabled;
}
void SkeletonRenderer::setVertexEffectDelegate(VertexEffectDelegate *effectDelegate) {
if (_effectDelegate == effectDelegate) {
return;
@@ -1075,6 +1434,7 @@ void SkeletonRenderer::bindNodeProxy(cocos2d::renderer::NodeProxy* node) {
}
void SkeletonRenderer::setEffect(cocos2d::renderer::EffectVariant* effect) {
_effectTextures.clear();
if (effect == _effect) return;
CC_SAFE_RELEASE(_effect);
_effect = effect;

View File

@@ -97,7 +97,9 @@ namespace spine {
/* Enables/disables two color tinting for this instance. May break batching */
void setUseTint(bool enabled);
void setUseMulti(bool enabled);
/* Sets the vertex effect to be used, set to 0 to disable vertex effects */
void setVertexEffectDelegate(VertexEffectDelegate* effectDelegate);
/* Sets the range of slots that should be rendered. Use -1, -1 to clear the range */
@@ -164,6 +166,7 @@ namespace spine {
bool _premultipliedAlpha = false;
SkeletonClipping* _clipper = nullptr;
bool _useTint = false;
bool _useMulti = false;
std::string _uuid = "";
int _startSlotIndex = -1;
@@ -172,6 +175,9 @@ namespace spine {
cocos2d::middleware::IOTypedArray* _debugBuffer = nullptr;
cocos2d::renderer::NodeProxy* _nodeProxy = nullptr;
cocos2d::renderer::EffectVariant* _effect = nullptr;
std::unordered_map<GLuint, float> _effectTextures = std::unordered_map<GLuint, float>();
RealTimeAttachUtil* _attachUtil = nullptr;
};

View File

@@ -60,9 +60,12 @@ RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const S
RegionAttachment &attachment = *attachmentP;
attachment.setRendererObject(regionP);
attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate);
attachment.setUVs(region.u, region.v, region.u2, region.v2, region.degrees);
attachment._regionDegrees = region.degrees;
attachment._regionOffsetX = region.offsetX;
attachment._regionOffsetY = region.offsetY;
attachment._regionX = region.x;
attachment._regionY = region.y;
attachment._regionWidth = (float)region.width;
attachment._regionHeight = (float)region.height;
attachment._regionOriginalWidth = (float)region.originalWidth;
@@ -90,6 +93,8 @@ MeshAttachment *AtlasAttachmentLoader::newMeshAttachment(Skin &skin, const Strin
attachment._regionDegrees = region.degrees;
attachment._regionOffsetX = region.offsetX;
attachment._regionOffsetY = region.offsetY;
attachment._regionX = region.x;
attachment._regionY = region.y;
attachment._regionWidth = (float)region.width;
attachment._regionHeight = (float)region.height;
attachment._regionOriginalWidth = (float)region.originalWidth;

View File

@@ -98,8 +98,8 @@ void MeshAttachment::updateUVs() {
return;
}
case 270: {
float textureWidth = _regionWidth / (_regionU2 - _regionU);
float textureHeight = _regionHeight / (_regionV2 - _regionV);
float textureWidth = _regionHeight / (_regionV2 - _regionV);
float textureHeight = _regionWidth / (_regionU2 - _regionU);
u -= _regionOffsetY / textureWidth;
v -= _regionOffsetX / textureHeight;
width = _regionOriginalHeight / textureWidth;
@@ -217,6 +217,22 @@ void MeshAttachment::setRegionOffsetY(float inValue) {
_regionOffsetY = inValue;
}
float MeshAttachment::getRegionX() {
return _regionX;
}
void MeshAttachment::setRegionX(float inValue) {
_regionX = inValue;
}
float MeshAttachment::getRegionY() {
return _regionY;
}
void MeshAttachment::setRegionY(float inValue) {
_regionY = inValue;
}
float MeshAttachment::getRegionWidth() {
return _regionWidth;
}

View File

@@ -91,6 +91,12 @@ namespace spine {
float getRegionOffsetY();
void setRegionOffsetY(float inValue);
float getRegionX();
void setRegionX(float inValue);
float getRegionY();
void setRegionY(float inValue);
float getRegionWidth();
void setRegionWidth(float inValue);
@@ -120,7 +126,7 @@ namespace spine {
MeshAttachment* newLinkedMesh();
private:
float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight;
float _regionOffsetX, _regionOffsetY, _regionX, _regionY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight;
MeshAttachment* _parentMesh;
Vector<float> _uvs;
Vector<float> _regionUVs;

View File

@@ -103,26 +103,35 @@ void RegionAttachment::updateOffset() {
_vertexOffset[BRY] = localYCos + localX2Sin;
}
void RegionAttachment::setUVs(float u, float v, float u2, float v2, bool rotate) {
if (rotate) {
_uvs[URX] = u;
_uvs[URY] = v2;
_uvs[BRX] = u;
_uvs[BRY] = v;
_uvs[BLX] = u2;
_uvs[BLY] = v;
_uvs[ULX] = u2;
_uvs[ULY] = v2;
} else {
_uvs[ULX] = u;
_uvs[ULY] = v2;
_uvs[URX] = u;
_uvs[URY] = v;
_uvs[BRX] = u2;
_uvs[BRY] = v;
_uvs[BLX] = u2;
_uvs[BLY] = v2;
}
void RegionAttachment::setUVs(float u, float v, float u2, float v2, float degrees) {
if (degrees == 90) {
_uvs[URX] = u;
_uvs[URY] = v2;
_uvs[BRX] = u;
_uvs[BRY] = v;
_uvs[BLX] = u2;
_uvs[BLY] = v;
_uvs[ULX] = u2;
_uvs[ULY] = v2;
} else if (degrees == 270) {
_uvs[BLX] = u;
_uvs[BLY] = v2;
_uvs[ULX] = u;
_uvs[ULY] = v;
_uvs[URX] = u2;
_uvs[URY] = v;
_uvs[BRX] = u2;
_uvs[BRY] = v2;
} else {
_uvs[ULX] = u;
_uvs[ULY] = v2;
_uvs[URX] = u;
_uvs[URY] = v;
_uvs[BRX] = u2;
_uvs[BRY] = v;
_uvs[BLX] = u2;
_uvs[BLY] = v2;
}
}
void RegionAttachment::computeWorldVertices(Bone &bone, Vector<float> &worldVertices, size_t offset, size_t stride) {
@@ -223,6 +232,14 @@ void RegionAttachment::setPath(const String &inValue) {
_path = inValue;
}
float RegionAttachment::getRegionDegrees() {
return _regionDegrees;
}
void RegionAttachment::setRegionDegrees(float inValue) {
_regionDegrees = inValue;
}
float RegionAttachment::getRegionOffsetX() {
return _regionOffsetX;
}
@@ -239,6 +256,22 @@ void RegionAttachment::setRegionOffsetY(float inValue) {
_regionOffsetY = inValue;
}
float RegionAttachment::getRegionX() {
return _regionX;
}
void RegionAttachment::setRegionX(float inValue) {
_regionX = inValue;
}
float RegionAttachment::getRegionY() {
return _regionY;
}
void RegionAttachment::setRegionY(float inValue) {
_regionY = inValue;
}
float RegionAttachment::getRegionWidth() {
return _regionWidth;
}

View File

@@ -54,7 +54,7 @@ namespace spine {
void updateOffset();
void setUVs(float u, float v, float u2, float v2, bool rotate);
void setUVs(float u, float v, float u2, float v2, float degress);
/// Transforms the attachment's four vertices to world coordinates.
/// @param bone The parent bone.
@@ -84,12 +84,21 @@ namespace spine {
const String& getPath();
void setPath(const String& inValue);
float getRegionDegrees();
void setRegionDegrees(float inValue);
float getRegionOffsetX();
void setRegionOffsetX(float inValue);
float getRegionOffsetY();
void setRegionOffsetY(float inValue);
float getRegionX();
void setRegionX(float inValue);
float getRegionY();
void setRegionY(float inValue);
float getRegionWidth();
void setRegionWidth(float inValue);
@@ -118,7 +127,7 @@ namespace spine {
static const int BRY;
float _x, _y, _rotation, _scaleX, _scaleY, _width, _height;
float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight;
float _regionOffsetX, _regionOffsetY, _regionX, _regionY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight;
Vector<float> _vertexOffset;
Vector<float> _uvs;
String _path;
@@ -127,6 +136,7 @@ namespace spine {
float _regionU2;
float _regionV2;
Color _color;
float _regionDegrees;
};
}

View File

@@ -143,6 +143,29 @@ Skin::AttachmentMap::Entries Skin::getAttachments() {
return _attachments.getEntries();
}
std::vector<std::map<std::string, Attachment *>> Skin::getAttachmentsForJSB() {
std::vector<std::map<std::string, Attachment *>> vec;
Skin::AttachmentMap::Entries entries = _attachments.getEntries();
size_t slotIndex = -1;
std::map<std::string, Attachment *>* map = nullptr;
while (entries.hasNext()) {
Skin::AttachmentMap::Entry &entry = entries.next();
if (slotIndex != entry._slotIndex){
slotIndex = entry._slotIndex;
vec.emplace_back();
map = &vec.back();
}
map->insert({ entry._name.buffer(), entry._attachment });
}
return vec;
}
void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) {
Vector<Slot *> &slots = skeleton.getSlots();
Skin::AttachmentMap::Entries entries = oldSkin.getAttachments();

View File

@@ -147,6 +147,8 @@ public:
AttachmentMap::Entries getAttachments();
std::vector<std::map<std::string, Attachment *>> getAttachmentsForJSB();
Vector<BoneData*>& getBones();
Vector<ConstraintData*>& getConstraints();