axmol/extensions/DragonBones/CCSlot.cpp

477 lines
16 KiB
C++
Raw Normal View History

2021-12-24 21:11:44 +08:00
#include "CCSlot.h"
#include "CCTextureAtlasData.h"
#include "CCArmatureDisplay.h"
DRAGONBONES_NAMESPACE_BEGIN
void CCSlot::_onClear()
{
Slot::_onClear();
2021-12-25 10:04:45 +08:00
_textureScale = 1.0f;
_renderDisplay = nullptr;
}
void CCSlot::_initDisplay(void* value, bool isRetain)
{
2022-08-08 18:02:17 +08:00
const auto renderDisplay = static_cast<ax::Node*>(value);
renderDisplay->retain();
}
void CCSlot::_disposeDisplay(void* value, bool isRelease)
{
2022-08-08 18:02:17 +08:00
const auto renderDisplay = static_cast<ax::Node*>(value);
renderDisplay->release();
}
void CCSlot::_onUpdateDisplay()
{
2022-08-08 18:02:17 +08:00
_renderDisplay = static_cast<ax::Node*>(_display != nullptr ? _display : _rawDisplay);
}
void CCSlot::_addDisplay()
{
const auto container = static_cast<CCArmatureDisplay*>(_armature->getDisplay());
container->addChild(_renderDisplay);
}
void CCSlot::_replaceDisplay(void* value, bool isArmatureDisplay)
{
const auto container = static_cast<CCArmatureDisplay*>(_armature->getDisplay());
2021-12-25 10:04:45 +08:00
const auto prevDisplay =
2022-08-08 18:02:17 +08:00
isArmatureDisplay ? static_cast<ax::Node*>(value) : static_cast<ax::Node*>(value);
container->addChild(_renderDisplay, prevDisplay->getLocalZOrder());
container->removeChild(prevDisplay);
_textureScale = 1.0f;
}
void CCSlot::_removeDisplay()
{
_renderDisplay->removeFromParent();
}
void CCSlot::_updateZOrder()
{
2021-12-25 10:04:45 +08:00
if (_renderDisplay->getLocalZOrder() == _zOrder)
{
return;
}
_renderDisplay->setLocalZOrder(_zOrder);
}
void CCSlot::_updateFrame()
{
2021-12-25 10:04:45 +08:00
const auto currentVerticesData =
(_deformVertices != nullptr && _display == _meshDisplay) ? _deformVertices->verticesData : nullptr;
const auto currentTextureData = static_cast<CCTextureData*>(_textureData);
2021-12-25 10:04:45 +08:00
const auto frameDisplay = static_cast<DBCCSprite*>(
_renderDisplay); // In cocos2dx render meshDisplay and frameDisplay are the same display
if (_displayIndex >= 0 && _display != nullptr && currentTextureData != nullptr)
{
if (currentTextureData->spriteFrame != nullptr)
{
2021-12-25 10:04:45 +08:00
if (currentVerticesData != nullptr) // Mesh.
{
2021-12-25 10:04:45 +08:00
const auto data = currentVerticesData->data;
const auto intArray = data->intArray;
const auto floatArray = data->floatArray;
2021-12-25 10:04:45 +08:00
const unsigned vertexCount =
intArray[currentVerticesData->offset + (unsigned)BinaryOffset::MeshVertexCount];
const unsigned triangleCount =
intArray[currentVerticesData->offset + (unsigned)BinaryOffset::MeshTriangleCount];
int vertexOffset = intArray[currentVerticesData->offset + (unsigned)BinaryOffset::MeshFloatOffset];
if (vertexOffset < 0)
{
2021-12-25 10:04:45 +08:00
vertexOffset += 65536; // Fixed out of bouds bug.
}
const unsigned uvOffset = vertexOffset + vertexCount * 2;
2021-12-25 10:04:45 +08:00
const auto& region = currentTextureData->region;
const auto& textureAtlasSize = currentTextureData->spriteFrame->getTexture()->getContentSizeInPixels();
2022-08-08 18:02:17 +08:00
auto vertices = new ax::V3F_C4B_T2F[vertexCount]; // does cocos2dx release it?
2021-12-25 10:04:45 +08:00
auto vertexIndices = new unsigned short[triangleCount * 3]; // does cocos2dx release it?
2022-08-08 18:02:17 +08:00
ax::Rect boundsRect(999999.0f, 999999.0f, -999999.0f, -999999.0f);
for (std::size_t i = 0, l = vertexCount * 2; i < l; i += 2)
{
const auto iH = i / 2;
2021-12-25 10:04:45 +08:00
const auto x = floatArray[vertexOffset + i];
const auto y = floatArray[vertexOffset + i + 1];
auto u = floatArray[uvOffset + i];
auto v = floatArray[uvOffset + i + 1];
2022-08-08 18:02:17 +08:00
ax::V3F_C4B_T2F vertexData;
vertexData.vertices.set(x, -y, 0.0f);
if (currentTextureData->rotated)
{
vertexData.texCoords.u = (region.x + (1.0f - v) * region.width) / textureAtlasSize.width;
vertexData.texCoords.v = (region.y + u * region.height) / textureAtlasSize.height;
}
else
{
vertexData.texCoords.u = (region.x + u * region.width) / textureAtlasSize.width;
vertexData.texCoords.v = (region.y + v * region.height) / textureAtlasSize.height;
}
2022-08-08 18:02:17 +08:00
vertexData.colors = ax::Color4B::WHITE;
2021-12-25 10:04:45 +08:00
vertices[iH] = vertexData;
if (boundsRect.origin.x > x)
{
boundsRect.origin.x = x;
}
if (boundsRect.size.width < x)
{
boundsRect.size.width = x;
}
if (boundsRect.origin.y > -y)
{
boundsRect.origin.y = -y;
}
if (boundsRect.size.height < -y)
{
boundsRect.size.height = -y;
}
}
boundsRect.size.width -= boundsRect.origin.x;
boundsRect.size.height -= boundsRect.origin.y;
for (std::size_t i = 0; i < triangleCount * 3; ++i)
{
2021-12-25 10:04:45 +08:00
vertexIndices[i] =
intArray[currentVerticesData->offset + (unsigned)BinaryOffset::MeshVertexIndices + i];
}
_textureScale = 1.0f;
2021-12-25 10:04:45 +08:00
frameDisplay->setSpriteFrame(currentTextureData->spriteFrame); // polygonInfo will be override
2022-08-08 18:02:17 +08:00
ax::PolygonInfo polygonInfo;
2021-12-25 10:04:45 +08:00
auto& triangles = polygonInfo.triangles;
triangles.verts = vertices;
triangles.indices = vertexIndices;
triangles.vertCount = vertexCount;
triangles.indexCount = triangleCount * 3;
const auto& transform = frameDisplay->getNodeToParentTransform(); // Backup transform. (Set rect and
// polygon will override transform).
#if COCOS2D_VERSION >= 0x00031400
polygonInfo.setRect(boundsRect);
#else
2021-12-25 10:04:45 +08:00
polygonInfo.rect = boundsRect; // Copy
frameDisplay->setContentSize(boundsRect.size);
#endif
frameDisplay->setPolygonInfo(polygonInfo);
const auto isSkinned = currentVerticesData->weight != nullptr;
2021-12-25 10:04:45 +08:00
if (isSkinned)
{
_identityTransform();
}
2021-12-25 10:04:45 +08:00
else
{
frameDisplay->setNodeToParentTransform(transform);
}
}
2021-12-25 10:04:45 +08:00
else // Normal texture.
{
const auto scale = currentTextureData->parent->scale * _armature->_armatureData->scale;
2022-08-08 18:02:17 +08:00
_textureScale = scale * ax::Director::getInstance()->getContentScaleFactor();
2021-12-25 10:04:45 +08:00
frameDisplay->setSpriteFrame(currentTextureData->spriteFrame); // polygonInfo will be override
}
2021-12-25 10:04:45 +08:00
_visibleDirty = true;
_blendModeDirty = true; // Relpace texture will override blendMode and color.
_colorDirty = true;
return;
}
}
frameDisplay->setTexture(nullptr);
2022-08-08 18:02:17 +08:00
frameDisplay->setTextureRect(ax::Rect::ZERO);
frameDisplay->setPosition(0.0f, 0.0f);
frameDisplay->setVisible(false);
}
2021-12-25 10:04:45 +08:00
void CCSlot::_updateMesh()
{
2021-12-25 10:04:45 +08:00
const auto scale = _armature->_armatureData->scale;
const auto& deformVertices = _deformVertices->vertices;
2021-12-25 10:04:45 +08:00
const auto& bones = _deformVertices->bones;
const auto verticesData = _deformVertices->verticesData;
const auto weightData = verticesData->weight;
2021-12-25 10:04:45 +08:00
const auto hasFFD = !deformVertices.empty();
const auto textureData = static_cast<CCTextureData*>(_textureData);
const auto meshDisplay = static_cast<DBCCSprite*>(_renderDisplay);
2021-12-25 10:04:45 +08:00
const auto vertices = meshDisplay->getPolygonInfoModify().triangles.verts;
2022-08-08 18:02:17 +08:00
ax::Rect boundsRect(999999.0f, 999999.0f, -999999.0f, -999999.0f);
if (!textureData || meshDisplay->getSpriteFrame() != textureData->spriteFrame)
{
return;
}
if (weightData != nullptr)
{
2021-12-25 10:04:45 +08:00
const auto data = verticesData->data;
const auto intArray = data->intArray;
const auto floatArray = data->floatArray;
const auto vertexCount = (std::size_t)intArray[verticesData->offset + (unsigned)BinaryOffset::MeshVertexCount];
2021-12-25 10:04:45 +08:00
int weightFloatOffset = intArray[weightData->offset + (unsigned)BinaryOffset::WeigthFloatOffset];
if (weightFloatOffset < 0)
{
2021-12-25 10:04:45 +08:00
weightFloatOffset += 65536; // Fixed out of bouds bug.
}
2021-12-25 10:04:45 +08:00
for (std::size_t i = 0, iB = weightData->offset + (unsigned)BinaryOffset::WeigthBoneIndices + bones.size(),
iV = (std::size_t)weightFloatOffset, iF = 0;
i < vertexCount; ++i)
{
const auto boneCount = (std::size_t)intArray[iB++];
auto xG = 0.0f, yG = 0.0f;
for (std::size_t j = 0; j < boneCount; ++j)
{
const auto boneIndex = (unsigned)intArray[iB++];
2021-12-25 10:04:45 +08:00
const auto bone = bones[boneIndex];
if (bone != nullptr)
{
const auto& matrix = bone->globalTransformMatrix;
2021-12-25 10:04:45 +08:00
const auto weight = floatArray[iV++];
auto xL = floatArray[iV++] * scale;
auto yL = floatArray[iV++] * scale;
2021-12-25 10:04:45 +08:00
if (hasFFD)
{
xL += deformVertices[iF++];
yL += deformVertices[iF++];
}
xG += (matrix.a * xL + matrix.c * yL + matrix.tx) * weight;
yG += (matrix.b * xL + matrix.d * yL + matrix.ty) * weight;
}
}
2021-12-25 10:04:45 +08:00
auto& vertex = vertices[i];
auto& vertexPosition = vertex.vertices;
vertexPosition.set(xG, -yG, 0.0f);
if (boundsRect.origin.x > xG)
{
boundsRect.origin.x = xG;
}
if (boundsRect.size.width < xG)
{
boundsRect.size.width = xG;
}
if (boundsRect.origin.y > -yG)
{
boundsRect.origin.y = -yG;
}
if (boundsRect.size.height < -yG)
{
boundsRect.size.height = -yG;
}
}
}
else if (hasFFD)
{
2021-12-25 10:04:45 +08:00
const auto data = verticesData->data;
const auto intArray = data->intArray;
const auto floatArray = data->floatArray;
const auto vertexCount = (std::size_t)intArray[verticesData->offset + (unsigned)BinaryOffset::MeshVertexCount];
2021-12-25 10:04:45 +08:00
int vertexOffset = (std::size_t)intArray[verticesData->offset + (unsigned)BinaryOffset::MeshFloatOffset];
if (vertexOffset < 0)
{
2021-12-25 10:04:45 +08:00
vertexOffset += 65536; // Fixed out of bouds bug.
}
for (std::size_t i = 0, l = vertexCount * 2; i < l; i += 2)
{
const auto iH = i / 2;
const auto xG = floatArray[vertexOffset + i] * scale + deformVertices[i];
const auto yG = floatArray[vertexOffset + i + 1] * scale + deformVertices[i + 1];
2021-12-25 10:04:45 +08:00
auto& vertex = vertices[iH];
auto& vertexPosition = vertex.vertices;
vertexPosition.set(xG, -yG, 0.0f);
if (boundsRect.origin.x > xG)
{
boundsRect.origin.x = xG;
}
if (boundsRect.size.width < xG)
{
boundsRect.size.width = xG;
}
if (boundsRect.origin.y > -yG)
{
boundsRect.origin.y = -yG;
}
if (boundsRect.size.height < -yG)
{
boundsRect.size.height = -yG;
}
}
}
boundsRect.size.width -= boundsRect.origin.x;
boundsRect.size.height -= boundsRect.origin.y;
2021-12-25 10:04:45 +08:00
const auto& transform =
meshDisplay->getNodeToParentTransform(); // Backup transform. (Set rect and polygon will override transform).
auto polygonInfo = meshDisplay->getPolygonInfo();
#if COCOS2D_VERSION >= 0x00031400
polygonInfo.setRect(boundsRect);
#else
2021-12-25 10:04:45 +08:00
polygonInfo.rect = boundsRect; // Copy
meshDisplay->setContentSize(boundsRect.size);
#endif
meshDisplay->setPolygonInfo(polygonInfo);
2021-12-25 10:04:45 +08:00
if (weightData != nullptr)
{
2021-12-25 10:04:45 +08:00
_identityTransform(); // ?!?!?!?!?!?!?!?!?!?!?!?!?!?! WTF
}
2021-12-25 10:04:45 +08:00
else
{
meshDisplay->setNodeToParentTransform(transform);
}
}
void CCSlot::_updateTransform()
{
2022-08-08 18:02:17 +08:00
static ax::Mat4 transform;
transform.m[0] = globalTransformMatrix.a;
transform.m[1] = globalTransformMatrix.b;
transform.m[4] = -globalTransformMatrix.c;
transform.m[5] = -globalTransformMatrix.d;
if (_renderDisplay == _rawDisplay || _renderDisplay == _meshDisplay)
{
if (_textureScale != 1.0f)
{
transform.m[0] *= _textureScale;
transform.m[1] *= _textureScale;
transform.m[4] *= _textureScale;
transform.m[5] *= _textureScale;
}
2021-12-25 10:04:45 +08:00
transform.m[12] =
globalTransformMatrix.tx - (globalTransformMatrix.a * _pivotX - globalTransformMatrix.c * _pivotY);
transform.m[13] =
globalTransformMatrix.ty - (globalTransformMatrix.b * _pivotX - globalTransformMatrix.d * _pivotY);
}
else if (_childArmature)
{
transform.m[12] = globalTransformMatrix.tx;
transform.m[13] = globalTransformMatrix.ty;
}
2021-12-25 10:04:45 +08:00
else
{
const auto& anchorPoint = _renderDisplay->getAnchorPoint();
2021-12-25 10:04:45 +08:00
transform.m[12] = globalTransformMatrix.tx -
(globalTransformMatrix.a * anchorPoint.x - globalTransformMatrix.c * anchorPoint.y);
transform.m[13] = globalTransformMatrix.ty -
(globalTransformMatrix.b * anchorPoint.x - globalTransformMatrix.d * anchorPoint.y);
}
_renderDisplay->setNodeToParentTransform(transform);
}
void CCSlot::_identityTransform()
{
2022-08-08 18:02:17 +08:00
static ax::Mat4 transform;
2021-12-25 10:04:45 +08:00
transform.m[0] = 1.0f;
transform.m[1] = 0.0f;
transform.m[4] = -0.0f;
transform.m[5] = -1.0f;
transform.m[12] = 0.0f;
transform.m[13] = 0.0f;
_renderDisplay->setNodeToParentTransform(transform);
}
void CCSlot::_updateVisible()
{
_renderDisplay->setVisible(_parent->getVisible());
}
void CCSlot::_updateBlendMode()
{
2022-08-08 18:02:17 +08:00
ax::Sprite* spriteDisplay = dynamic_cast<ax::Sprite*>(_renderDisplay);
if (spriteDisplay)
{
switch (_blendMode)
{
case BlendMode::Normal:
2022-08-08 18:02:17 +08:00
// spriteDisplay->setBlendFunc(ax::BlendFunc::DISABLE);
break;
case BlendMode::Add:
{
const auto texture = spriteDisplay->getTexture();
if (texture && texture->hasPremultipliedAlpha())
{
#if COCOS2D_VERSION >= 0x00040000
2022-08-08 18:02:17 +08:00
ax::BlendFunc blendFunc = {ax::backend::BlendFactor::ONE, ax::backend::BlendFactor::ONE};
#else
2022-08-08 18:02:17 +08:00
ax::BlendFunc blendFunc = {GL_ONE, GL_ONE};
#endif
spriteDisplay->setBlendFunc(blendFunc);
}
else
{
2022-08-08 18:02:17 +08:00
spriteDisplay->setBlendFunc(ax::BlendFunc::ADDITIVE);
}
break;
}
default:
break;
}
}
else if (_childArmature != nullptr)
{
for (const auto slot : _childArmature->getSlots())
{
slot->_blendMode = _blendMode;
slot->_updateBlendMode();
}
}
}
void CCSlot::_updateColor()
{
_renderDisplay->setOpacity(_colorTransform.alphaMultiplier * 255.0f);
2022-08-08 18:02:17 +08:00
static ax::Color3B helpColor;
helpColor.r = _colorTransform.redMultiplier * 255.0f;
helpColor.g = _colorTransform.greenMultiplier * 255.0f;
helpColor.b = _colorTransform.blueMultiplier * 255.0f;
_renderDisplay->setColor(helpColor);
}
DRAGONBONES_NAMESPACE_END