You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
455 lines
16 KiB
455 lines
16 KiB
/****************************************************************************
|
|
Copyright (c) 2012-2020 DragonBones team and other contributors
|
|
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
|
|
|
http://www.cocos.com
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights to
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "dragonbones-creator-support/CCSlot.h"
|
|
#include "dragonbones-creator-support/CCArmatureDisplay.h"
|
|
#include "dragonbones-creator-support/CCTextureAtlasData.h"
|
|
|
|
using namespace cc;
|
|
|
|
DRAGONBONES_NAMESPACE_BEGIN
|
|
|
|
void CCSlot::_onClear() {
|
|
Slot::_onClear();
|
|
disposeTriangles();
|
|
_localMatrix.setIdentity();
|
|
worldMatrix.setIdentity();
|
|
_worldMatDirty = true;
|
|
}
|
|
|
|
void CCSlot::disposeTriangles() {
|
|
if (worldVerts) {
|
|
delete[] worldVerts;
|
|
worldVerts = nullptr;
|
|
}
|
|
if (triangles.verts) {
|
|
delete[] triangles.verts;
|
|
triangles.verts = nullptr;
|
|
}
|
|
if (triangles.indices) {
|
|
delete[] triangles.indices;
|
|
triangles.indices = nullptr;
|
|
}
|
|
triangles.indexCount = 0;
|
|
triangles.vertCount = 0;
|
|
}
|
|
|
|
void CCSlot::adjustTriangles(const unsigned vertexCount, const unsigned indicesCount) {
|
|
if (triangles.vertCount < vertexCount) {
|
|
if (triangles.verts) {
|
|
delete[] triangles.verts;
|
|
}
|
|
triangles.verts = new middleware::V3F_T2F_C4B[vertexCount];
|
|
|
|
if (worldVerts) {
|
|
delete[] worldVerts;
|
|
}
|
|
worldVerts = new middleware::V3F_T2F_C4B[vertexCount];
|
|
}
|
|
triangles.vertCount = vertexCount;
|
|
|
|
if (triangles.indexCount < indicesCount) {
|
|
if (triangles.indices) {
|
|
delete[] triangles.indices;
|
|
}
|
|
triangles.indices = new unsigned short[indicesCount];
|
|
}
|
|
triangles.indexCount = indicesCount;
|
|
}
|
|
|
|
void CCSlot::_initDisplay(void *value, bool isRetain) {
|
|
}
|
|
|
|
void CCSlot::_disposeDisplay(void *value, bool isRelease) {
|
|
}
|
|
|
|
void CCSlot::_onUpdateDisplay() {
|
|
}
|
|
|
|
void CCSlot::_addDisplay() {
|
|
_visible = true;
|
|
}
|
|
|
|
void CCSlot::_replaceDisplay(void *value, bool isArmatureDisplay) {
|
|
}
|
|
|
|
void CCSlot::_removeDisplay() {
|
|
_visible = false;
|
|
}
|
|
|
|
void CCSlot::_updateZOrder() {
|
|
}
|
|
|
|
void CCSlot::_updateVisible() {
|
|
_visible = _parent->getVisible();
|
|
}
|
|
|
|
middleware::Texture2D *CCSlot::getTexture() const {
|
|
const auto currentTextureData = static_cast<CCTextureData *>(_textureData);
|
|
if (!currentTextureData || !currentTextureData->spriteFrame) {
|
|
return nullptr;
|
|
}
|
|
return currentTextureData->spriteFrame->getTexture();
|
|
}
|
|
|
|
void CCSlot::_updateFrame() {
|
|
const auto currentVerticesData = (_deformVertices != nullptr && _display == _meshDisplay) ? _deformVertices->verticesData : nullptr;
|
|
const auto currentTextureData = static_cast<CCTextureData *>(_textureData);
|
|
|
|
if (_displayIndex >= 0 && _display != nullptr && currentTextureData != nullptr) {
|
|
if (currentTextureData->spriteFrame != nullptr) {
|
|
const auto ®ion = currentTextureData->region;
|
|
const auto texture = currentTextureData->spriteFrame->getTexture();
|
|
const auto textureWidth = texture->getPixelsWide();
|
|
const auto textureHeight = texture->getPixelsHigh();
|
|
|
|
if (currentVerticesData != nullptr) // Mesh.
|
|
{
|
|
const auto data = currentVerticesData->data;
|
|
const auto intArray = data->intArray;
|
|
const auto floatArray = data->floatArray;
|
|
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) {
|
|
vertexOffset += 65536; // Fixed out of bouds bug.
|
|
}
|
|
|
|
const unsigned uvOffset = vertexOffset + vertexCount * 2;
|
|
const unsigned indicesCount = triangleCount * 3;
|
|
adjustTriangles(vertexCount, indicesCount);
|
|
auto vertices = triangles.verts;
|
|
auto vertexIndices = triangles.indices;
|
|
|
|
boundsRect.x = 999999.0f;
|
|
boundsRect.y = 999999.0f;
|
|
boundsRect.width = -999999.0f;
|
|
boundsRect.height = -999999.0f;
|
|
|
|
for (std::size_t i = 0, l = vertexCount * 2; i < l; i += 2) {
|
|
const auto iH = i / 2;
|
|
const auto x = floatArray[vertexOffset + i];
|
|
const auto y = floatArray[vertexOffset + i + 1];
|
|
auto u = floatArray[uvOffset + i];
|
|
auto v = floatArray[uvOffset + i + 1];
|
|
middleware::V3F_T2F_C4B &vertexData = vertices[iH];
|
|
vertexData.vertex.x = x;
|
|
vertexData.vertex.y = -y;
|
|
|
|
if (currentTextureData->rotated) {
|
|
vertexData.texCoord.u = (region.x + (1.0f - v) * region.width) / textureWidth;
|
|
vertexData.texCoord.v = (region.y + u * region.height) / textureHeight;
|
|
} else {
|
|
vertexData.texCoord.u = (region.x + u * region.width) / textureWidth;
|
|
vertexData.texCoord.v = (region.y + v * region.height) / textureHeight;
|
|
}
|
|
|
|
vertexData.color = cc::middleware::Color4B::WHITE;
|
|
|
|
if (boundsRect.x > x) {
|
|
boundsRect.x = x;
|
|
}
|
|
|
|
if (boundsRect.width < x) {
|
|
boundsRect.width = x;
|
|
}
|
|
|
|
if (boundsRect.y > -y) {
|
|
boundsRect.y = -y;
|
|
}
|
|
|
|
if (boundsRect.height < -y) {
|
|
boundsRect.height = -y;
|
|
}
|
|
}
|
|
|
|
boundsRect.width -= boundsRect.x;
|
|
boundsRect.height -= boundsRect.y;
|
|
|
|
for (std::size_t i = 0; i < triangleCount * 3; ++i) {
|
|
vertexIndices[i] = intArray[currentVerticesData->offset + (unsigned)BinaryOffset::MeshVertexIndices + i];
|
|
}
|
|
|
|
const auto isSkinned = currentVerticesData->weight != nullptr;
|
|
if (isSkinned) {
|
|
_identityTransform();
|
|
}
|
|
} else {
|
|
adjustTriangles(4, 6);
|
|
|
|
auto vertices = triangles.verts;
|
|
auto vertexIndices = triangles.indices;
|
|
|
|
float l = region.x / textureWidth;
|
|
float b = (region.y + region.height) / textureHeight;
|
|
float r = (region.x + region.width) / textureWidth;
|
|
float t = region.y / textureHeight;
|
|
|
|
vertices[0].texCoord.u = l;
|
|
vertices[0].texCoord.v = b;
|
|
vertices[1].texCoord.u = r;
|
|
vertices[1].texCoord.v = b;
|
|
vertices[2].texCoord.u = l;
|
|
vertices[2].texCoord.v = t;
|
|
vertices[3].texCoord.u = r;
|
|
vertices[3].texCoord.v = t;
|
|
|
|
vertices[0].vertex.x = vertices[2].vertex.x = 0;
|
|
vertices[1].vertex.x = vertices[3].vertex.x = region.width;
|
|
vertices[0].vertex.y = vertices[1].vertex.y = 0;
|
|
vertices[2].vertex.y = vertices[3].vertex.y = region.height;
|
|
|
|
vertexIndices[0] = 0;
|
|
vertexIndices[1] = 1;
|
|
vertexIndices[2] = 2;
|
|
vertexIndices[3] = 1;
|
|
vertexIndices[4] = 3;
|
|
vertexIndices[5] = 2;
|
|
}
|
|
|
|
memcpy(worldVerts, triangles.verts, triangles.vertCount * sizeof(middleware::V3F_T2F_C4B));
|
|
|
|
_visibleDirty = true;
|
|
_blendModeDirty = true; // Relpace texture will override blendMode and color.
|
|
_colorDirty = true;
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCSlot::_updateMesh() {
|
|
const auto scale = _armature->_armatureData->scale;
|
|
const auto &deformVertices = _deformVertices->vertices;
|
|
const auto &bones = _deformVertices->bones;
|
|
const auto verticesData = _deformVertices->verticesData;
|
|
const auto weightData = verticesData->weight;
|
|
|
|
const auto hasFFD = !deformVertices.empty();
|
|
const auto textureData = static_cast<CCTextureData *>(_textureData);
|
|
const auto vertices = triangles.verts;
|
|
|
|
boundsRect.x = 999999.0f;
|
|
boundsRect.y = 999999.0f;
|
|
boundsRect.width = -999999.0f;
|
|
boundsRect.height = -999999.0f;
|
|
|
|
if (!textureData) {
|
|
return;
|
|
}
|
|
|
|
if (weightData != nullptr) {
|
|
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];
|
|
int weightFloatOffset = intArray[weightData->offset + (unsigned)BinaryOffset::WeigthFloatOffset];
|
|
|
|
if (vertexCount > triangles.vertCount) {
|
|
return;
|
|
}
|
|
|
|
if (weightFloatOffset < 0) {
|
|
weightFloatOffset += 65536; // Fixed out of bouds bug.
|
|
}
|
|
|
|
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++];
|
|
const auto bone = bones[boneIndex];
|
|
if (bone != nullptr) {
|
|
const auto &matrix = bone->globalTransformMatrix;
|
|
const auto weight = floatArray[iV++];
|
|
auto xL = floatArray[iV++] * scale;
|
|
auto yL = floatArray[iV++] * scale;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
auto &vertex = vertices[i];
|
|
auto &vertexPosition = vertex.vertex;
|
|
|
|
vertexPosition.x = xG;
|
|
vertexPosition.y = -yG;
|
|
|
|
if (boundsRect.x > xG) {
|
|
boundsRect.x = xG;
|
|
}
|
|
|
|
if (boundsRect.width < xG) {
|
|
boundsRect.width = xG;
|
|
}
|
|
|
|
if (boundsRect.y > -yG) {
|
|
boundsRect.y = -yG;
|
|
}
|
|
|
|
if (boundsRect.height < -yG) {
|
|
boundsRect.height = -yG;
|
|
}
|
|
}
|
|
} else if (hasFFD) {
|
|
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];
|
|
std::size_t vertexOffset = (std::size_t)intArray[verticesData->offset + (unsigned)BinaryOffset::MeshFloatOffset];
|
|
|
|
if (vertexCount > triangles.vertCount) {
|
|
return;
|
|
}
|
|
|
|
if (vertexOffset < 0) {
|
|
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];
|
|
|
|
auto &vertex = vertices[iH];
|
|
auto &vertexPosition = vertex.vertex;
|
|
|
|
vertexPosition.x = xG;
|
|
vertexPosition.y = -yG;
|
|
|
|
if (boundsRect.x > xG) {
|
|
boundsRect.x = xG;
|
|
}
|
|
|
|
if (boundsRect.width < xG) {
|
|
boundsRect.width = xG;
|
|
}
|
|
|
|
if (boundsRect.y > -yG) {
|
|
boundsRect.y = -yG;
|
|
}
|
|
|
|
if (boundsRect.height < -yG) {
|
|
boundsRect.height = -yG;
|
|
}
|
|
}
|
|
}
|
|
|
|
boundsRect.width -= boundsRect.x;
|
|
boundsRect.height -= boundsRect.y;
|
|
|
|
if (weightData != nullptr) {
|
|
_identityTransform();
|
|
}
|
|
}
|
|
|
|
void CCSlot::_updateTransform() {
|
|
_localMatrix.m[0] = globalTransformMatrix.a;
|
|
_localMatrix.m[1] = globalTransformMatrix.b;
|
|
_localMatrix.m[4] = -globalTransformMatrix.c;
|
|
_localMatrix.m[5] = -globalTransformMatrix.d;
|
|
|
|
if (_childArmature) {
|
|
_localMatrix.m[12] = globalTransformMatrix.tx;
|
|
_localMatrix.m[13] = globalTransformMatrix.ty;
|
|
} else {
|
|
_localMatrix.m[12] = globalTransformMatrix.tx - (globalTransformMatrix.a * _pivotX - globalTransformMatrix.c * _pivotY);
|
|
_localMatrix.m[13] = globalTransformMatrix.ty - (globalTransformMatrix.b * _pivotX - globalTransformMatrix.d * _pivotY);
|
|
}
|
|
|
|
_worldMatDirty = true;
|
|
}
|
|
|
|
void CCSlot::updateWorldMatrix() {
|
|
if (!_armature) return;
|
|
|
|
CCSlot *parent = (CCSlot *)_armature->getParent();
|
|
if (parent) {
|
|
parent->updateWorldMatrix();
|
|
}
|
|
|
|
if (_worldMatDirty) {
|
|
calculWorldMatrix();
|
|
|
|
Armature *childArmature = getChildArmature();
|
|
if (!childArmature) return;
|
|
|
|
auto &slots = childArmature->getSlots();
|
|
for (int i = 0; i < slots.size(); i++) {
|
|
CCSlot *slot = (CCSlot *)slots[i];
|
|
slot->_worldMatDirty = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCSlot::calculWorldMatrix() {
|
|
CCSlot *parent = (CCSlot *)_armature->getParent();
|
|
if (parent) {
|
|
worldMatrix = parent->worldMatrix * _localMatrix;
|
|
} else {
|
|
worldMatrix = _localMatrix;
|
|
}
|
|
|
|
_worldMatDirty = false;
|
|
}
|
|
|
|
void CCSlot::_identityTransform() {
|
|
_localMatrix.m[0] = 1.0f;
|
|
_localMatrix.m[1] = 0.0f;
|
|
_localMatrix.m[4] = -0.0f;
|
|
_localMatrix.m[5] = -1.0f;
|
|
_localMatrix.m[12] = 0.0f;
|
|
_localMatrix.m[13] = 0.0f;
|
|
|
|
_worldMatDirty = true;
|
|
}
|
|
|
|
void CCSlot::_updateBlendMode() {
|
|
if (_childArmature != nullptr) {
|
|
for (const auto slot : _childArmature->getSlots()) {
|
|
slot->_blendMode = _blendMode;
|
|
slot->_updateBlendMode();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCSlot::_updateColor() {
|
|
color.r = _colorTransform.redMultiplier * 255.0f;
|
|
color.g = _colorTransform.greenMultiplier * 255.0f;
|
|
color.b = _colorTransform.blueMultiplier * 255.0f;
|
|
color.a = _colorTransform.alphaMultiplier * 255.0f;
|
|
}
|
|
|
|
DRAGONBONES_NAMESPACE_END
|
|
|