no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,419 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2020 DragonBones team and other contributors
*
* 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 "ArmatureCache.h"
#include "CCFactory.h"
#include "base/TypeDef.h"
#include "base/memory/Memory.h"
USING_NS_MW; // NOLINT(google-build-using-namespace)
using namespace cc; // NOLINT(google-build-using-namespace)
DRAGONBONES_NAMESPACE_BEGIN
float ArmatureCache::FrameTime = 1.0F / 60.0F;
float ArmatureCache::MaxCacheTime = 120.0F;
ArmatureCache::SegmentData::SegmentData() = default;
ArmatureCache::SegmentData::~SegmentData() {
CC_SAFE_RELEASE_NULL(_texture);
}
void ArmatureCache::SegmentData::setTexture(cc::middleware::Texture2D *value) {
CC_SAFE_ADD_REF(value);
CC_SAFE_RELEASE(_texture);
_texture = value;
}
cc::middleware::Texture2D *ArmatureCache::SegmentData::getTexture() const {
return _texture;
}
ArmatureCache::FrameData::FrameData() = default;
ArmatureCache::FrameData::~FrameData() {
for (auto &bone : _bones) {
delete bone;
}
_bones.clear();
for (auto &color : _colors) {
delete color;
}
_colors.clear();
for (auto &segment : _segments) {
delete segment;
}
_segments.clear();
}
ArmatureCache::BoneData *ArmatureCache::FrameData::buildBoneData(std::size_t index) {
if (index > _bones.size()) return nullptr;
if (index == _bones.size()) {
auto *boneData = new BoneData;
_bones.push_back(boneData);
}
return _bones[index];
}
std::size_t ArmatureCache::FrameData::getBoneCount() const {
return _bones.size();
}
ArmatureCache::ColorData *ArmatureCache::FrameData::buildColorData(std::size_t index) {
if (index > _colors.size()) return nullptr;
if (index == _colors.size()) {
auto *colorData = new ColorData;
_colors.push_back(colorData);
}
return _colors[index];
}
std::size_t ArmatureCache::FrameData::getColorCount() const {
return _colors.size();
}
ArmatureCache::SegmentData *ArmatureCache::FrameData::buildSegmentData(std::size_t index) {
if (index > _segments.size()) return nullptr;
if (index == _segments.size()) {
auto *segmentData = new SegmentData;
_segments.push_back(segmentData);
}
return _segments[index];
}
std::size_t ArmatureCache::FrameData::getSegmentCount() const {
return _segments.size();
}
ArmatureCache::AnimationData::AnimationData() = default;
ArmatureCache::AnimationData::~AnimationData() {
reset();
}
void ArmatureCache::AnimationData::reset() {
for (auto &frame : _frames) {
delete frame;
}
_frames.clear();
_isComplete = false;
_totalTime = 0.0F;
}
bool ArmatureCache::AnimationData::needUpdate(int toFrameIdx) const {
return !_isComplete && _totalTime <= MaxCacheTime && (toFrameIdx == -1 || _frames.size() < toFrameIdx + 1);
}
ArmatureCache::FrameData *ArmatureCache::AnimationData::buildFrameData(std::size_t frameIdx) {
if (frameIdx > _frames.size()) {
return nullptr;
}
if (frameIdx == _frames.size()) {
auto *frameData = new FrameData();
_frames.push_back(frameData);
}
return _frames[frameIdx];
}
ArmatureCache::FrameData *ArmatureCache::AnimationData::getFrameData(std::size_t frameIdx) const {
if (frameIdx >= _frames.size()) {
return nullptr;
}
return _frames[frameIdx];
}
std::size_t ArmatureCache::AnimationData::getFrameCount() const {
return _frames.size();
}
ArmatureCache::ArmatureCache(const std::string &armatureName, const std::string &armatureKey, const std::string &atlasUUID) {
_armatureDisplay = dragonBones::CCFactory::getFactory()->buildArmatureDisplay(armatureName, armatureKey, "", atlasUUID);
if (_armatureDisplay) {
_armatureDisplay->addRef();
}
}
ArmatureCache::~ArmatureCache() {
if (_armatureDisplay) {
_armatureDisplay->release();
_armatureDisplay = nullptr;
}
for (auto &animationCache : _animationCaches) {
delete animationCache.second;
}
_animationCaches.clear();
}
ArmatureCache::AnimationData *ArmatureCache::buildAnimationData(const std::string &animationName) {
if (!_armatureDisplay) return nullptr;
AnimationData *aniData = nullptr;
auto it = _animationCaches.find(animationName);
if (it == _animationCaches.end()) {
auto *armature = _armatureDisplay->getArmature();
auto *animation = armature->getAnimation();
auto hasAni = animation->hasAnimation(animationName);
if (!hasAni) return nullptr;
aniData = new AnimationData();
aniData->_animationName = animationName;
_animationCaches[animationName] = aniData;
} else {
aniData = it->second;
}
return aniData;
}
ArmatureCache::AnimationData *ArmatureCache::getAnimationData(const std::string &animationName) {
auto it = _animationCaches.find(animationName);
if (it == _animationCaches.end()) {
return nullptr;
}
return it->second;
}
void ArmatureCache::updateToFrame(const std::string &animationName, int toFrameIdx /*= -1*/) {
auto it = _animationCaches.find(animationName);
if (it == _animationCaches.end()) {
return;
}
AnimationData *animationData = it->second;
if (!animationData || !animationData->needUpdate(toFrameIdx)) {
return;
}
if (_curAnimationName != animationName) {
updateToFrame(_curAnimationName);
_curAnimationName = animationName;
}
auto *armature = _armatureDisplay->getArmature();
auto *animation = armature->getAnimation();
// init animation
if (animationData->getFrameCount() == 0) {
animation->play(animationName, 1);
}
do {
armature->advanceTime(FrameTime);
renderAnimationFrame(animationData);
animationData->_totalTime += FrameTime;
if (animation->isCompleted()) {
animationData->_isComplete = true;
}
} while (animationData->needUpdate(toFrameIdx));
}
void ArmatureCache::renderAnimationFrame(AnimationData *animationData) {
std::size_t frameIndex = animationData->getFrameCount();
_frameData = animationData->buildFrameData(frameIndex);
_preColor = Color4B(0, 0, 0, 0);
_color = Color4B(255, 255, 255, 255);
_preBlendMode = -1;
_preTextureIndex = -1;
_curTextureIndex = -1;
_preISegWritePos = -1;
_curISegLen = 0;
_curVSegLen = 0;
_materialLen = 0;
auto *armature = _armatureDisplay->getArmature();
traverseArmature(armature);
if (_preISegWritePos != -1) {
SegmentData *preSegmentData = _frameData->buildSegmentData(_materialLen - 1);
preSegmentData->indexCount = _curISegLen;
preSegmentData->vertexFloatCount = _curVSegLen;
}
auto colorCount = _frameData->getColorCount();
if (colorCount > 0) {
ColorData *preColorData = _frameData->buildColorData(colorCount - 1);
preColorData->vertexFloatOffset = static_cast<int>(_frameData->vb.getCurPos()) / sizeof(float);
}
_frameData = nullptr;
}
void ArmatureCache::traverseArmature(Armature *armature, float parentOpacity /*= 1.0f*/) {
middleware::IOBuffer &vb = _frameData->vb;
middleware::IOBuffer &ib = _frameData->ib;
const auto &bones = armature->getBones();
Bone *bone = nullptr;
const auto &slots = armature->getSlots();
CCSlot *slot = nullptr;
// range [0.0, 1.0]
Color4B preColor(0, 0, 0, 0);
Color4B color;
middleware::Texture2D *texture = nullptr;
auto flush = [&]() {
// fill pre segment count field
if (_preISegWritePos != -1) {
SegmentData *preSegmentData = _frameData->buildSegmentData(_materialLen - 1);
preSegmentData->indexCount = _curISegLen;
preSegmentData->vertexFloatCount = _curVSegLen;
}
SegmentData *segmentData = _frameData->buildSegmentData(_materialLen);
segmentData->setTexture(texture);
segmentData->blendMode = static_cast<int>(slot->_blendMode);
// save new segment count pos field
_preISegWritePos = static_cast<int>(ib.getCurPos() / sizeof(uint16_t));
// reset pre blend mode to current
_preBlendMode = static_cast<int>(slot->_blendMode);
// reset pre texture index to current
_preTextureIndex = _curTextureIndex;
// reset index segmentation count
_curISegLen = 0;
// reset vertex segmentation count
_curVSegLen = 0;
// material length increased
_materialLen++;
};
for (auto *i : bones) {
bone = i;
auto boneCount = _frameData->getBoneCount();
BoneData *boneData = _frameData->buildBoneData(boneCount);
auto &boneOriginMat = bone->globalTransformMatrix;
auto &matm = boneData->globalTransformMatrix.m;
matm[0] = boneOriginMat.a;
matm[1] = boneOriginMat.b;
matm[4] = -boneOriginMat.c;
matm[5] = -boneOriginMat.d;
matm[12] = boneOriginMat.tx;
matm[13] = boneOriginMat.ty;
}
for (auto *i : slots) {
slot = dynamic_cast<CCSlot *>(i); // TODO(zhakasi): refine the logic
if (slot == nullptr) {
return;
}
if (!slot->getVisible()) {
continue;
}
slot->updateWorldMatrix();
Mat4 *worldMatrix = &slot->worldMatrix;
// If slots has child armature,will traverse child first.
Armature *childArmature = slot->getChildArmature();
if (childArmature != nullptr) {
traverseArmature(childArmature, parentOpacity * static_cast<float>(slot->color.a) / 255.0F);
continue;
}
texture = slot->getTexture();
if (!texture) continue;
_curTextureIndex = texture->getRealTextureIndex();
auto vbSize = slot->triangles.vertCount * sizeof(middleware::V3F_T2F_C4B);
vb.checkSpace(vbSize, true);
// If texture or blendMode change,will change material.
if (_preTextureIndex != _curTextureIndex || _preBlendMode != static_cast<int>(slot->_blendMode)) {
flush();
}
// Calculation vertex color.
color.a = static_cast<uint8_t>(slot->color.a * parentOpacity);
color.r = static_cast<uint8_t>(slot->color.r);
color.g = static_cast<uint8_t>(slot->color.g);
color.b = static_cast<uint8_t>(slot->color.b);
if (preColor != color) {
preColor = color;
auto colorCount = _frameData->getColorCount();
if (colorCount > 0) {
ColorData *preColorData = _frameData->buildColorData(colorCount - 1);
preColorData->vertexFloatOffset = vb.getCurPos() / sizeof(float);
}
ColorData *colorData = _frameData->buildColorData(colorCount);
colorData->color = color;
}
// Transform component matrix to global matrix
middleware::Triangles &triangles = slot->triangles;
middleware::V3F_T2F_C4B *worldTriangles = slot->worldVerts;
for (int v = 0, w = 0, vn = triangles.vertCount; v < vn; ++v, w += 2) {
middleware::V3F_T2F_C4B *vertex = triangles.verts + v;
middleware::V3F_T2F_C4B *worldVertex = worldTriangles + v;
vertex->vertex.z = 0; //reset for z value
worldVertex->vertex.transformMat4(vertex->vertex, *worldMatrix);
worldVertex->color.r = color.r;
worldVertex->color.g = color.g;
worldVertex->color.b = color.b;
worldVertex->color.a = color.a;
}
vb.writeBytes(reinterpret_cast<char *>(worldTriangles), vbSize);
auto ibSize = triangles.indexCount * sizeof(uint16_t);
ib.checkSpace(ibSize, true);
auto vertexOffset = _curVSegLen / VF_XYZUVC;
for (int ii = 0, nn = triangles.indexCount; ii < nn; ii++) {
ib.writeUint16(triangles.indices[ii] + vertexOffset);
}
_curISegLen += triangles.indexCount;
_curVSegLen += static_cast<int32_t>(vbSize / sizeof(float));
} // End slot traverse
}
void ArmatureCache::resetAllAnimationData() {
for (auto &animationCache : _animationCaches) {
animationCache.second->reset();
}
}
void ArmatureCache::resetAnimationData(const std::string &animationName) {
for (auto &animationCache : _animationCaches) {
if (animationCache.second->_animationName == animationName) {
animationCache.second->reset();
break;
}
}
}
CCArmatureDisplay *ArmatureCache::getArmatureDisplay() {
return _armatureDisplay;
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,158 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2020 DragonBones team and other contributors
*
* 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.
*/
#pragma once
#include "CCArmatureDisplay.h"
#include "IOBuffer.h"
#include "base/RefCounted.h"
DRAGONBONES_NAMESPACE_BEGIN
class ArmatureCache : public cc::RefCounted {
public:
struct SegmentData {
friend class ArmatureCache;
SegmentData();
~SegmentData();
void setTexture(cc::middleware::Texture2D *value);
cc::middleware::Texture2D *getTexture() const;
public:
int blendMode = 0;
std::size_t indexCount = 0;
std::size_t vertexFloatCount = 0;
private:
cc::middleware::Texture2D *_texture = nullptr;
};
struct BoneData {
cc::Mat4 globalTransformMatrix;
};
struct ColorData {
cc::middleware::Color4B color;
std::size_t vertexFloatOffset = 0;
};
struct FrameData {
friend class ArmatureCache;
FrameData();
~FrameData();
const std::vector<BoneData *> &getBones() const {
return _bones;
}
std::size_t getBoneCount() const;
const std::vector<ColorData *> &getColors() const {
return _colors;
}
std::size_t getColorCount() const;
const std::vector<SegmentData *> &getSegments() const {
return _segments;
}
std::size_t getSegmentCount() const;
private:
// if segment data is empty, it will build new one.
SegmentData *buildSegmentData(std::size_t index);
// if color data is empty, it will build new one.
ColorData *buildColorData(std::size_t index);
// if bone data is empty, it will build new one.
BoneData *buildBoneData(std::size_t index);
std::vector<BoneData *> _bones;
std::vector<ColorData *> _colors;
std::vector<SegmentData *> _segments;
public:
cc::middleware::IOBuffer ib;
cc::middleware::IOBuffer vb;
};
struct AnimationData {
friend class ArmatureCache;
AnimationData();
~AnimationData();
void reset();
FrameData *getFrameData(std::size_t frameIdx) const;
std::size_t getFrameCount() const;
bool isComplete() const { return _isComplete; }
bool needUpdate(int toFrameIdx) const;
private:
// if frame is empty, it will build new one.
FrameData *buildFrameData(std::size_t frameIdx);
std::string _animationName;
bool _isComplete = false;
float _totalTime = 0.0F;
std::vector<FrameData *> _frames;
};
ArmatureCache(const std::string &armatureName, const std::string &armatureKey, const std::string &atlasUUID);
~ArmatureCache() override;
void updateToFrame(const std::string &animationName, int toFrameIdx = -1);
// if animation data is empty, it will build new one.
AnimationData *buildAnimationData(const std::string &animationName);
AnimationData *getAnimationData(const std::string &animationName);
CCArmatureDisplay *getArmatureDisplay();
void resetAllAnimationData();
void resetAnimationData(const std::string &animationName);
private:
void renderAnimationFrame(AnimationData *animationData);
void traverseArmature(Armature *armature, float parentOpacity = 1.0F);
public:
static float FrameTime; // NOLINT
static float MaxCacheTime; // NOLINT
private:
FrameData *_frameData = nullptr;
cc::middleware::Color4F _preColor = cc::middleware::Color4F(-1.0F, -1.0F, -1.0F, -1.0F);
cc::middleware::Color4F _color = cc::middleware::Color4F(1.0F, 1.0F, 1.0F, 1.0F);
CCArmatureDisplay *_armatureDisplay = nullptr;
int _preBlendMode = -1;
int _preTextureIndex = -1;
int _curTextureIndex = -1;
int _preISegWritePos = -1;
int _curISegLen = 0;
int _curVSegLen = 0;
int _materialLen = 0;
std::string _curAnimationName;
std::map<std::string, AnimationData *> _animationCaches;
};
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,52 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2020 DragonBones team and other contributors
*
* 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 "ArmatureCacheMgr.h"
#include "base/DeferredReleasePool.h"
DRAGONBONES_NAMESPACE_BEGIN
ArmatureCacheMgr *ArmatureCacheMgr::_instance = nullptr;
ArmatureCache *ArmatureCacheMgr::buildArmatureCache(const std::string &armatureName, const std::string &armatureKey, const std::string &atlasUUID) {
ArmatureCache *animation = _caches.at(armatureKey);
if (!animation) {
animation = new ArmatureCache(armatureName, armatureKey, atlasUUID);
animation->addRef();
_caches.insert(armatureKey, animation);
cc::DeferredReleasePool::add(animation);
}
return animation;
}
void ArmatureCacheMgr::removeArmatureCache(const std::string &armatureKey) {
for (auto it = _caches.begin(); it != _caches.end();) {
auto found = it->first.find(armatureKey);
if (found != std::string::npos) {
it = _caches.erase(it);
} else {
it++;
}
}
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,56 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2020 DragonBones team and other contributors
*
* 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.
*/
#pragma once
#include "ArmatureCache.h"
#include "base/RefMap.h"
#include "dragonbones/DragonBonesHeaders.h"
DRAGONBONES_NAMESPACE_BEGIN
class ArmatureCacheMgr {
public:
static ArmatureCacheMgr *getInstance() {
if (_instance == nullptr) {
_instance = new ArmatureCacheMgr();
}
return _instance;
}
static void destroyInstance() {
if (_instance) {
delete _instance;
_instance = nullptr;
}
}
void removeArmatureCache(const std::string &armatureKey);
ArmatureCache *buildArmatureCache(const std::string &armatureName, const std::string &armatureKey, const std::string &atlasUUID);
private:
static ArmatureCacheMgr *_instance;
cc::RefMap<std::string, ArmatureCache *> _caches;
};
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,464 @@
/****************************************************************************
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 "CCArmatureCacheDisplay.h"
#include "2d/renderer/RenderDrawInfo.h"
#include "2d/renderer/RenderEntity.h"
#include "ArmatureCacheMgr.h"
#include "CCFactory.h"
#include "MiddlewareManager.h"
#include "SharedBufferManager.h"
#include "base/TypeDef.h"
#include "base/memory/Memory.h"
#include "gfx-base/GFXDef.h"
#include "math/Math.h"
#include "renderer/core/MaterialInstance.h"
using namespace cc; // NOLINT(google-build-using-namespace)
using namespace cc::gfx; // NOLINT(google-build-using-namespace)
static const std::string TECH_STAGE = "opaque";
static const std::string TEXTURE_KEY = "texture";
static const std::string START_EVENT = "start";
static const std::string LOOP_COMPLETE_EVENT = "loopComplete";
static const std::string COMPLETE_EVENT = "complete";
DRAGONBONES_NAMESPACE_BEGIN
USING_NS_MW; // NOLINT(google-build-using-namespace)
CCArmatureCacheDisplay::CCArmatureCacheDisplay(const std::string &armatureName, const std::string &armatureKey, const std::string &atlasUUID, bool isShare) {
_eventObject = BaseObject::borrowObject<EventObject>();
if (isShare) {
_armatureCache = ArmatureCacheMgr::getInstance()->buildArmatureCache(armatureName, armatureKey, atlasUUID);
_armatureCache->addRef();
} else {
_armatureCache = new ArmatureCache(armatureName, armatureKey, atlasUUID);
_armatureCache->addRef();
}
// store global TypedArray begin and end offset
_sharedBufferOffset = new IOTypedArray(se::Object::TypedArrayType::UINT32, sizeof(uint32_t) * 2);
}
CCArmatureCacheDisplay::~CCArmatureCacheDisplay() {
dispose();
if (_sharedBufferOffset) {
delete _sharedBufferOffset;
_sharedBufferOffset = nullptr;
}
for (auto *draw : _drawInfoArray) {
CC_SAFE_DELETE(draw);
}
for (auto &item : _materialCaches) {
CC_SAFE_DELETE(item.second);
}
}
void CCArmatureCacheDisplay::dispose() {
if (_armatureCache) {
_armatureCache->release();
_armatureCache = nullptr;
}
if (_eventObject) {
_eventObject->returnToPool();
_eventObject = nullptr;
}
stopSchedule();
}
void CCArmatureCacheDisplay::update(float dt) {
auto gTimeScale = dragonBones::CCFactory::getFactory()->getTimeScale();
dt *= _timeScale * gTimeScale;
if (_isAniComplete || !_animationData) {
if (_animationData && !_animationData->isComplete()) {
_armatureCache->updateToFrame(_animationName);
}
return;
}
if (_accTime <= 0.00001 && _playCount == 0) {
_eventObject->type = EventObject::START;
dispatchDBEvent(START_EVENT, _eventObject);
}
_accTime += dt;
int frameIdx = floor(_accTime / ArmatureCache::FrameTime);
if (!_animationData->isComplete()) {
_armatureCache->updateToFrame(_animationName, frameIdx);
}
int finalFrameIndex = static_cast<int>(_animationData->getFrameCount()) - 1;
if (_animationData->isComplete() && frameIdx >= finalFrameIndex) {
_playCount++;
_accTime = 0.0F;
if (_playTimes > 0 && _playCount >= _playTimes) {
frameIdx = finalFrameIndex;
_playCount = 0;
_isAniComplete = true;
} else {
frameIdx = 0;
}
_eventObject->type = EventObject::COMPLETE;
dispatchDBEvent(COMPLETE_EVENT, _eventObject);
_eventObject->type = EventObject::LOOP_COMPLETE;
dispatchDBEvent(LOOP_COMPLETE_EVENT, _eventObject);
}
_curFrameIndex = frameIdx;
}
void CCArmatureCacheDisplay::render(float /*dt*/) {
if (!_animationData) return;
ArmatureCache::FrameData *frameData = _animationData->getFrameData(_curFrameIndex);
if (!frameData) return;
auto *mgr = MiddlewareManager::getInstance();
if (!mgr->isRendering) return;
auto *entity = _entity;
entity->clearDynamicRenderDrawInfos();
const auto &segments = frameData->getSegments();
const auto &colors = frameData->getColors();
_sharedBufferOffset->reset();
_sharedBufferOffset->clear();
auto *attachMgr = mgr->getAttachInfoMgr();
auto *attachInfo = attachMgr->getBuffer();
if (!attachInfo) return;
// store attach info offset
_sharedBufferOffset->writeUint32(static_cast<uint32_t>(attachInfo->getCurPos()) / sizeof(uint32_t));
if (segments.empty() || colors.empty()) return;
middleware::MeshBuffer *mb = mgr->getMeshBuffer(VF_XYZUVC);
middleware::IOBuffer &vb = mb->getVB();
middleware::IOBuffer &ib = mb->getIB();
const auto &srcVB = frameData->vb;
const auto &srcIB = frameData->ib;
auto &nodeWorldMat = entity->getNode()->getWorldMatrix();
int colorOffset = 0;
ArmatureCache::ColorData *nowColor = colors[colorOffset++];
auto maxVFOffset = nowColor->vertexFloatOffset;
Color4B color;
float tempR = 0.0F;
float tempG = 0.0F;
float tempB = 0.0F;
float tempA = 0.0F;
float multiplier = 1.0F;
std::size_t srcVertexBytesOffset = 0;
std::size_t srcIndexBytesOffset = 0;
std::size_t vertexBytes = 0;
std::size_t indexBytes = 0;
BlendMode blendMode = BlendMode::Normal;
std::size_t dstVertexOffset = 0;
std::size_t dstIndexOffset = 0;
float *dstVertexBuffer = nullptr;
unsigned int *dstColorBuffer = nullptr;
uint16_t *dstIndexBuffer = nullptr;
bool needColor = false;
int curBlendSrc = -1;
int curBlendDst = -1;
cc::Texture2D *curTexture = nullptr;
RenderDrawInfo *curDrawInfo = nullptr;
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 = [&](ArmatureCache::ColorData *colorData) {
tempA = colorData->color.a * _nodeColor.a;
multiplier = _premultipliedAlpha ? tempA / 255.0f : 1.0f;
tempR = _nodeColor.r * multiplier;
tempG = _nodeColor.g * multiplier;
tempB = _nodeColor.b * multiplier;
color.a = (uint8_t)floorf(tempA);
color.r = (uint8_t)floorf(colorData->color.r * tempR);
color.g = (uint8_t)floorf(colorData->color.g * tempG);
color.b = (uint8_t)floorf(colorData->color.b * tempB);
};
handleColor(nowColor);
int segmentCount = 0;
for (auto *segment : segments) {
vertexBytes = segment->vertexFloatCount * sizeof(float);
curDrawInfo = requestDrawInfo(segmentCount++);
entity->addDynamicRenderDrawInfo(curDrawInfo);
// fill new texture index
curTexture = static_cast<cc::Texture2D *>(segment->getTexture()->getRealTexture());
gfx::Texture *texture = curTexture->getGFXTexture();
gfx::Sampler *sampler = curTexture->getGFXSampler();
curDrawInfo->setTexture(texture);
curDrawInfo->setSampler(sampler);
blendMode = static_cast<BlendMode>(segment->blendMode);
switch (blendMode) {
case BlendMode::Add:
curBlendSrc = static_cast<int>(_premultipliedAlpha ? BlendFactor::ONE : BlendFactor::SRC_ALPHA);
curBlendDst = static_cast<int>(BlendFactor::ONE);
break;
case BlendMode::Multiply:
curBlendSrc = static_cast<int>(BlendFactor::DST_COLOR);
curBlendDst = static_cast<int>(BlendFactor::ONE_MINUS_SRC_ALPHA);
break;
case BlendMode::Screen:
curBlendSrc = static_cast<int>(BlendFactor::ONE);
curBlendDst = static_cast<int>(BlendFactor::ONE_MINUS_SRC_COLOR);
break;
default:
curBlendSrc = static_cast<int>(_premultipliedAlpha ? BlendFactor::ONE : BlendFactor::SRC_ALPHA);
curBlendDst = static_cast<int>(BlendFactor::ONE_MINUS_SRC_ALPHA);
break;
}
// fill new blend src and dst
auto *material = requestMaterial(curBlendSrc, curBlendDst);
curDrawInfo->setMaterial(material);
// fill vertex buffer
vb.checkSpace(vertexBytes, true);
dstVertexOffset = vb.getCurPos() / sizeof(V3F_T2F_C4B);
dstVertexBuffer = reinterpret_cast<float *>(vb.getCurBuffer());
dstColorBuffer = reinterpret_cast<unsigned int *>(vb.getCurBuffer());
vb.writeBytes(reinterpret_cast<char *>(srcVB.getBuffer()) + srcVertexBytesOffset, vertexBytes);
// batch handle
cc::Vec3 *point = nullptr;
for (auto posIndex = 0; posIndex < segment->vertexFloatCount; posIndex += VF_XYZUVC) {
point = reinterpret_cast<cc::Vec3 *>(dstVertexBuffer + posIndex);
point->z = 0;
point->transformMat4(*point, nodeWorldMat);
}
// handle vertex color
if (needColor) {
auto frameFloatOffset = srcVertexBytesOffset / sizeof(float);
for (auto colorIndex = 0; colorIndex < segment->vertexFloatCount; colorIndex += VF_XYZUVC, frameFloatOffset += VF_XYZUVC) {
if (frameFloatOffset >= maxVFOffset) {
nowColor = colors[colorOffset++];
handleColor(nowColor);
maxVFOffset = nowColor->vertexFloatOffset;
}
memcpy(dstColorBuffer + colorIndex + 5, &color, sizeof(color));
}
}
// move src vertex buffer offset
srcVertexBytesOffset += vertexBytes;
// fill index buffer
indexBytes = segment->indexCount * sizeof(uint16_t);
ib.checkSpace(indexBytes, true);
dstIndexOffset = static_cast<int>(ib.getCurPos()) / sizeof(uint16_t);
dstIndexBuffer = reinterpret_cast<uint16_t *>(ib.getCurBuffer());
ib.writeBytes(reinterpret_cast<char *>(srcIB.getBuffer()) + srcIndexBytesOffset, indexBytes);
for (auto indexPos = 0; indexPos < segment->indexCount; indexPos++) {
dstIndexBuffer[indexPos] += dstVertexOffset;
}
srcIndexBytesOffset += indexBytes;
// fill new index and vertex buffer id
UIMeshBuffer *uiMeshBuffer = mb->getUIMeshBuffer();
curDrawInfo->setMeshBuffer(uiMeshBuffer);
// fill new index offset
curDrawInfo->setIndexOffset(dstIndexOffset);
// fill new indice segamentation count
curDrawInfo->setIbCount(segment->indexCount);
}
if (_useAttach) {
const auto &bonesData = frameData->getBones();
auto boneCount = frameData->getBoneCount();
for (int i = 0; i < boneCount; i++) {
auto *bone = bonesData[i];
attachInfo->checkSpace(sizeof(cc::Mat4), true);
attachInfo->writeBytes(reinterpret_cast<const char *>(&bone->globalTransformMatrix), sizeof(cc::Mat4));
}
}
}
void CCArmatureCacheDisplay::beginSchedule() {
MiddlewareManager::getInstance()->addTimer(this);
}
void CCArmatureCacheDisplay::stopSchedule() {
MiddlewareManager::getInstance()->removeTimer(this);
if (_sharedBufferOffset) {
_sharedBufferOffset->reset();
_sharedBufferOffset->clear();
}
}
void CCArmatureCacheDisplay::onEnable() {
beginSchedule();
}
void CCArmatureCacheDisplay::onDisable() {
stopSchedule();
}
Armature *CCArmatureCacheDisplay::getArmature() const {
auto *armatureDisplay = _armatureCache->getArmatureDisplay();
return armatureDisplay->getArmature();
}
Animation *CCArmatureCacheDisplay::getAnimation() const {
auto *armature = getArmature();
return armature->getAnimation();
}
void CCArmatureCacheDisplay::playAnimation(const std::string &name, int playTimes) {
_playTimes = playTimes;
_animationName = name;
_animationData = _armatureCache->buildAnimationData(_animationName);
_isAniComplete = false;
_accTime = 0.0F;
_playCount = 0;
_curFrameIndex = 0;
}
void CCArmatureCacheDisplay::addDBEventListener(const std::string &type) {
_listenerIDMap[type] = true;
}
void CCArmatureCacheDisplay::removeDBEventListener(const std::string &type) {
auto it = _listenerIDMap.find(type);
if (it != _listenerIDMap.end()) {
_listenerIDMap.erase(it);
}
}
void CCArmatureCacheDisplay::dispatchDBEvent(const std::string &type, EventObject *value) {
auto it = _listenerIDMap.find(type);
if (it == _listenerIDMap.end()) {
return;
}
if (_dbEventCallback) {
_dbEventCallback(value);
}
}
void CCArmatureCacheDisplay::updateAnimationCache(const std::string &animationName) {
_armatureCache->resetAnimationData(animationName);
}
void CCArmatureCacheDisplay::updateAllAnimationCache() {
_armatureCache->resetAllAnimationData();
}
void CCArmatureCacheDisplay::setColor(float r, float g, float b, float a) {
_nodeColor.r = r / 255.0F;
_nodeColor.g = g / 255.0F;
_nodeColor.b = b / 255.0F;
_nodeColor.a = a / 255.0F;
}
void CCArmatureCacheDisplay::setAttachEnabled(bool enabled) {
_useAttach = enabled;
}
void CCArmatureCacheDisplay::setBatchEnabled(bool enabled) {
if (enabled != _enableBatch) {
for (auto &item : _materialCaches) {
CC_SAFE_DELETE(item.second);
}
_materialCaches.clear();
_enableBatch = enabled;
}
}
se_object_ptr CCArmatureCacheDisplay::getSharedBufferOffset() const {
if (_sharedBufferOffset) {
return _sharedBufferOffset->getTypeArray();
}
return nullptr;
}
void CCArmatureCacheDisplay::setRenderEntity(cc::RenderEntity *entity) {
_entity = entity;
}
void CCArmatureCacheDisplay::setMaterial(cc::Material *material) {
_material = material;
for (auto &item : _materialCaches) {
CC_SAFE_DELETE(item.second);
}
_materialCaches.clear();
}
cc::RenderDrawInfo *CCArmatureCacheDisplay::requestDrawInfo(int idx) {
if (_drawInfoArray.size() < idx + 1) {
cc::RenderDrawInfo *draw = new cc::RenderDrawInfo();
draw->setDrawInfoType(static_cast<uint32_t>(RenderDrawInfoType::MIDDLEWARE));
_drawInfoArray.push_back(draw);
}
return _drawInfoArray[idx];
}
cc::Material *CCArmatureCacheDisplay::requestMaterial(uint16_t blendSrc, uint16_t blendDst) {
uint32_t key = static_cast<uint32_t>(blendSrc) << 16 | static_cast<uint32_t>(blendDst);
if (_materialCaches.find(key) == _materialCaches.end()) {
const IMaterialInstanceInfo info{
(Material *)_material,
0};
MaterialInstance *materialInstance = new MaterialInstance(info);
PassOverrides overrides;
BlendStateInfo stateInfo;
stateInfo.blendColor = gfx::Color{1.0F, 1.0F, 1.0F, 1.0F};
BlendTargetInfo targetInfo;
targetInfo.blendEq = gfx::BlendOp::ADD;
targetInfo.blendAlphaEq = gfx::BlendOp::ADD;
targetInfo.blendSrc = (gfx::BlendFactor)blendSrc;
targetInfo.blendDst = (gfx::BlendFactor)blendDst;
targetInfo.blendSrcAlpha = (gfx::BlendFactor)blendSrc;
targetInfo.blendDstAlpha = (gfx::BlendFactor)blendDst;
BlendTargetInfoList targetList{targetInfo};
stateInfo.targets = targetList;
overrides.blendState = stateInfo;
materialInstance->overridePipelineStates(overrides);
const MacroRecord macros{{"USE_LOCAL", false}};
materialInstance->recompileShaders(macros);
_materialCaches[key] = materialInstance;
}
return _materialCaches[key];
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,129 @@
/****************************************************************************
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.
****************************************************************************/
#pragma once
#include <utility>
#include "ArmatureCache.h"
#include "CCArmatureDisplay.h"
#include "base/RefCounted.h"
#include "dragonbones/DragonBonesHeaders.h"
namespace cc {
class RenderEntity;
class RenderDrawInfo;
class Material;
}; // namespace cc
DRAGONBONES_NAMESPACE_BEGIN
class CCArmatureCacheDisplay : public cc::RefCounted, public cc::middleware::IMiddleware {
public:
CCArmatureCacheDisplay(const std::string &armatureName, const std::string &armatureKey, const std::string &atlasUUID, bool isShare);
~CCArmatureCacheDisplay() override;
void dispose();
void update(float dt) override;
void render(float dt) override;
void setTimeScale(float scale) {
_timeScale = scale;
}
float getTimeScale() const {
return _timeScale;
}
void beginSchedule();
void stopSchedule();
void onEnable();
void onDisable();
Armature *getArmature() const;
Animation *getAnimation() const;
void setColor(float r, float g, float b, float a);
void setBatchEnabled(bool enabled);
void setAttachEnabled(bool enabled);
void setOpacityModifyRGB(bool value) {
_premultipliedAlpha = value;
}
using dbEventCallback = std::function<void(EventObject *)>;
void setDBEventCallback(dbEventCallback callback) {
_dbEventCallback = std::move(callback);
}
void addDBEventListener(const std::string &type);
void removeDBEventListener(const std::string &type);
void dispatchDBEvent(const std::string &type, EventObject *value);
void playAnimation(const std::string &name, int playTimes);
void updateAnimationCache(const std::string &animationName);
void updateAllAnimationCache();
/**
* @return shared buffer offset, it's a Uint32Array
* format |render info offset|attach info offset|
*/
se_object_ptr getSharedBufferOffset() const;
cc::RenderDrawInfo *requestDrawInfo(int idx);
cc::Material *requestMaterial(uint16_t blendSrc, uint16_t blendDst);
void setMaterial(cc::Material *material);
void setRenderEntity(cc::RenderEntity *entity);
private:
float _timeScale = 1;
int _curFrameIndex = -1;
float _accTime = 0.0F;
int _playCount = 0;
int _playTimes = 0;
bool _isAniComplete = true;
std::string _animationName;
Armature *_armature = nullptr;
ArmatureCache::AnimationData *_animationData = nullptr;
std::map<std::string, bool> _listenerIDMap;
bool _useAttach = false;
bool _enableBatch = true;
cc::middleware::Color4F _nodeColor = cc::middleware::Color4F::WHITE;
bool _premultipliedAlpha = false;
dbEventCallback _dbEventCallback = nullptr;
ArmatureCache *_armatureCache = nullptr;
EventObject *_eventObject;
cc::middleware::IOTypedArray *_sharedBufferOffset = nullptr;
cc::RenderEntity *_entity = nullptr;
cc::Material *_material = nullptr;
ccstd::vector<cc::RenderDrawInfo *> _drawInfoArray;
ccstd::unordered_map<uint32_t, cc::Material *> _materialCaches;
};
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,466 @@
/****************************************************************************
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/CCArmatureDisplay.h"
#include "2d/renderer/RenderDrawInfo.h"
#include "2d/renderer/RenderEntity.h"
#include "MiddlewareMacro.h"
#include "SharedBufferManager.h"
#include "base/DeferredReleasePool.h"
#include "base/TypeDef.h"
#include "base/memory/Memory.h"
#include "dragonbones-creator-support/CCSlot.h"
#include "gfx-base/GFXDef.h"
#include "math/Math.h"
#include "math/Vec3.h"
#include "renderer/core/MaterialInstance.h"
USING_NS_MW; // NOLINT(google-build-using-namespace)
using namespace cc; // NOLINT(google-build-using-namespace)
static const std::string TECH_STAGE = "opaque";
static const std::string TEXTURE_KEY = "texture";
namespace cc {
}
DRAGONBONES_NAMESPACE_BEGIN
CCArmatureDisplay *CCArmatureDisplay::create() {
return new (std::nothrow) CCArmatureDisplay();
}
CCArmatureDisplay::CCArmatureDisplay() {
_sharedBufferOffset = new IOTypedArray(se::Object::TypedArrayType::UINT32, sizeof(uint32_t) * 2);
}
CCArmatureDisplay::~CCArmatureDisplay() {
dispose();
if (_debugBuffer) {
delete _debugBuffer;
_debugBuffer = nullptr;
}
if (_sharedBufferOffset) {
delete _sharedBufferOffset;
_sharedBufferOffset = nullptr;
}
for (auto *draw : _drawInfoArray) {
CC_SAFE_DELETE(draw);
}
for (auto &item : _materialCaches) {
CC_SAFE_DELETE(item.second);
}
}
void CCArmatureDisplay::dispose() {
if (_armature != nullptr) {
_armature->dispose();
_armature = nullptr;
}
}
void CCArmatureDisplay::dbInit(Armature *armature) {
_armature = armature;
}
void CCArmatureDisplay::dbClear() {
_armature = nullptr;
release();
}
void CCArmatureDisplay::dbUpdate() {}
void CCArmatureDisplay::dbRender() {
_sharedBufferOffset->reset();
_sharedBufferOffset->clear();
if (this->_armature->getParent()) {
return;
}
if (!_entity) {
return;
}
auto *entity = _entity;
entity->clearDynamicRenderDrawInfos();
auto *mgr = MiddlewareManager::getInstance();
if (!mgr->isRendering) return;
auto *attachMgr = mgr->getAttachInfoMgr();
auto *attachInfo = attachMgr->getBuffer();
if (!attachInfo) return;
// store attach info offset
_sharedBufferOffset->writeUint32(static_cast<uint32_t>(attachInfo->getCurPos()) / sizeof(uint32_t));
_preBlendMode = -1;
_preISegWritePos = -1;
_curISegLen = 0;
_debugSlotsLen = 0;
_materialLen = 0;
_preTexture = nullptr;
_curTexture = nullptr;
_curDrawInfo = nullptr;
// Traverse all aramture to fill vertex and index buffer.
traverseArmature(_armature);
if (_curDrawInfo) _curDrawInfo->setIbCount(_curISegLen);
if (_useAttach || _debugDraw) {
const auto &bones = _armature->getBones();
std::size_t count = bones.size();
cc::Mat4 boneMat = cc::Mat4::IDENTITY;
if (_debugDraw) {
// If enable debug draw,then init debug buffer.
if (_debugBuffer == nullptr) {
_debugBuffer = new IOTypedArray(se::Object::TypedArrayType::FLOAT32, MAX_DEBUG_BUFFER_SIZE);
}
_debugBuffer->reset();
_debugBuffer->writeFloat32(static_cast<float>(count) * 4);
}
for (int i = 0; i < count; i++) {
Bone *bone = static_cast<Bone *>(bones[i]);
float boneLen = 5;
if (bone->_boneData->length > boneLen) {
boneLen = bone->_boneData->length;
}
boneMat.m[0] = bone->globalTransformMatrix.a;
boneMat.m[1] = bone->globalTransformMatrix.b;
boneMat.m[4] = -bone->globalTransformMatrix.c;
boneMat.m[5] = -bone->globalTransformMatrix.d;
boneMat.m[12] = bone->globalTransformMatrix.tx;
boneMat.m[13] = bone->globalTransformMatrix.ty;
attachInfo->checkSpace(sizeof(boneMat), true);
attachInfo->writeBytes(reinterpret_cast<const char *>(&boneMat), sizeof(boneMat));
if (_debugDraw) {
float bx = bone->globalTransformMatrix.tx;
float by = bone->globalTransformMatrix.ty;
float endx = bx + bone->globalTransformMatrix.a * boneLen;
float endy = by + bone->globalTransformMatrix.b * boneLen;
_debugBuffer->writeFloat32(bx);
_debugBuffer->writeFloat32(by);
_debugBuffer->writeFloat32(endx);
_debugBuffer->writeFloat32(endy);
}
}
if (_debugBuffer && _debugBuffer->isOutRange()) {
_debugBuffer->writeFloat32(0, 0);
CC_LOG_INFO("Dragonbones debug data is too large,debug buffer has no space to put in it!!!!!!!!!!");
CC_LOG_INFO("You can adjust MAX_DEBUG_BUFFER_SIZE in MiddlewareMacro");
}
}
}
const cc::Vec2 &CCArmatureDisplay::convertToRootSpace(float x, float y) const {
auto *slot = reinterpret_cast<CCSlot *>(_armature->getParent());
if (!slot) {
_tmpVec2.set(x, y);
return _tmpVec2;
}
slot->updateWorldMatrix();
cc::Mat4 &worldMatrix = slot->worldMatrix;
_tmpVec2.x = x * worldMatrix.m[0] + y * worldMatrix.m[4] + worldMatrix.m[12];
_tmpVec2.y = x * worldMatrix.m[1] + y * worldMatrix.m[5] + worldMatrix.m[13];
return _tmpVec2;
}
CCArmatureDisplay *CCArmatureDisplay::getRootDisplay() {
Slot *slot = _armature->getParent();
if (!slot) {
return this;
}
Slot *parentSlot = slot->_armature->getParent();
while (parentSlot) {
slot = parentSlot;
parentSlot = parentSlot->_armature->getParent();
}
return static_cast<CCArmatureDisplay *>(slot->_armature->getDisplay());
}
void CCArmatureDisplay::traverseArmature(Armature *armature, float parentOpacity) {
static cc::Mat4 matrixTemp;
auto &nodeWorldMat = _entity->getNode()->getWorldMatrix();
// data store in buffer which 0 to 3 is render order, left data is node world matrix
const auto &slots = armature->getSlots();
auto *mgr = MiddlewareManager::getInstance();
middleware::MeshBuffer *mb = mgr->getMeshBuffer(VF_XYZUVC);
IOBuffer &vb = mb->getVB();
IOBuffer &ib = mb->getIB();
float realOpacity = _nodeColor.a;
auto *attachMgr = mgr->getAttachInfoMgr();
auto *attachInfo = attachMgr->getBuffer();
if (!attachInfo) return;
// range [0.0, 255.0]
Color4B color(0, 0, 0, 0);
CCSlot *slot = nullptr;
int isFull = 0;
auto flush = [&]() {
// fill pre segment count field
if (_curDrawInfo) _curDrawInfo->setIbCount(_curISegLen);
_curDrawInfo = requestDrawInfo(_materialLen);
_entity->addDynamicRenderDrawInfo(_curDrawInfo);
// prepare to fill new segment field
switch (slot->_blendMode) {
case BlendMode::Add:
_curBlendSrc = static_cast<int>(_premultipliedAlpha ? gfx::BlendFactor::ONE : gfx::BlendFactor::SRC_ALPHA);
_curBlendDst = static_cast<int>(gfx::BlendFactor::ONE);
break;
case BlendMode::Multiply:
_curBlendSrc = static_cast<int>(gfx::BlendFactor::DST_COLOR);
_curBlendDst = static_cast<int>(gfx::BlendFactor::ONE_MINUS_SRC_ALPHA);
break;
case BlendMode::Screen:
_curBlendSrc = static_cast<int>(gfx::BlendFactor::ONE);
_curBlendDst = static_cast<int>(gfx::BlendFactor::ONE_MINUS_SRC_COLOR);
break;
default:
_curBlendSrc = static_cast<int>(_premultipliedAlpha ? gfx::BlendFactor::ONE : gfx::BlendFactor::SRC_ALPHA);
_curBlendDst = static_cast<int>(gfx::BlendFactor::ONE_MINUS_SRC_ALPHA);
break;
}
auto *material = requestMaterial(_curBlendSrc, _curBlendDst);
_curDrawInfo->setMaterial(material);
gfx::Texture *texture = _curTexture->getGFXTexture();
gfx::Sampler *sampler = _curTexture->getGFXSampler();
_curDrawInfo->setTexture(texture);
_curDrawInfo->setSampler(sampler);
UIMeshBuffer *uiMeshBuffer = mb->getUIMeshBuffer();
_curDrawInfo->setMeshBuffer(uiMeshBuffer);
_curDrawInfo->setIndexOffset(static_cast<uint32_t>(ib.getCurPos()) / sizeof(uint16_t));
// reset pre blend mode to current
_preBlendMode = static_cast<int>(slot->_blendMode);
// reset pre texture index to current
_preTexture = _curTexture;
// reset index segmentation count
_curISegLen = 0;
// material length increased
_materialLen++;
};
for (auto *i : slots) {
isFull = 0;
slot = dynamic_cast<CCSlot *>(i); //TODO(zhakasi): refine the logic
if (slot == nullptr) {
return;
}
if (!slot->getVisible()) {
continue;
}
slot->updateWorldMatrix();
// If slots has child armature,will traverse child first.
Armature *childArmature = slot->getChildArmature();
if (childArmature != nullptr) {
traverseArmature(childArmature, parentOpacity * static_cast<float>(slot->color.a) / 255.0F);
continue;
}
if (!slot->getTexture()) continue;
_curTexture = static_cast<cc::Texture2D *>(slot->getTexture()->getRealTexture());
auto vbSize = slot->triangles.vertCount * sizeof(middleware::V3F_T2F_C4B);
isFull |= vb.checkSpace(vbSize, true);
// If texture or blendMode change,will change material.
if (_preTexture != _curTexture || _preBlendMode != static_cast<int>(slot->_blendMode) || isFull) {
flush();
}
// Calculation vertex color.
color.a = (uint8_t)(realOpacity * static_cast<float>(slot->color.a) * parentOpacity);
float multiplier = _premultipliedAlpha ? color.a / 255.0F : 1.0F;
color.r = _nodeColor.r * slot->color.r * multiplier;
color.g = _nodeColor.g * slot->color.g * multiplier;
color.b = _nodeColor.b * slot->color.b * multiplier;
// Transform component matrix to global matrix
middleware::Triangles &triangles = slot->triangles;
cc::Mat4 *worldMatrix = &slot->worldMatrix;
cc::Mat4::multiply(nodeWorldMat, *worldMatrix, &matrixTemp);
worldMatrix = &matrixTemp;
middleware::V3F_T2F_C4B *worldTriangles = slot->worldVerts;
for (int v = 0, w = 0, vn = triangles.vertCount; v < vn; ++v, w += 2) {
middleware::V3F_T2F_C4B *vertex = triangles.verts + v;
middleware::V3F_T2F_C4B *worldVertex = worldTriangles + v;
vertex->vertex.z = 0; //reset for z value
worldVertex->vertex.transformMat4(vertex->vertex, *worldMatrix);
worldVertex->color = color;
}
// Fill MiddlewareManager vertex buffer
auto vertexOffset = vb.getCurPos() / sizeof(middleware::V3F_T2F_C4B);
vb.writeBytes(reinterpret_cast<char *>(worldTriangles), vbSize);
auto ibSize = triangles.indexCount * sizeof(uint16_t);
ib.checkSpace(ibSize, true);
// If vertex buffer current offset is zero,fill it directly or recalculate vertex offset.
if (vertexOffset > 0) {
for (int ii = 0, nn = triangles.indexCount; ii < nn; ii++) {
ib.writeUint16(triangles.indices[ii] + vertexOffset);
}
} else {
ib.writeBytes(reinterpret_cast<char *>(triangles.indices), ibSize);
}
// Record this turn index segmentation count,it will store in material buffer in the end.
_curISegLen += triangles.indexCount;
}
}
bool CCArmatureDisplay::hasDBEventListener(const std::string &type) const {
auto it = _listenerIDMap.find(type);
return it != _listenerIDMap.end();
}
void CCArmatureDisplay::addDBEventListener(const std::string &type, const std::function<void(EventObject *)> & /*listener*/) {
_listenerIDMap[type] = true;
}
void CCArmatureDisplay::dispatchDBEvent(const std::string &type, EventObject *value) {
auto it = _listenerIDMap.find(type);
if (it == _listenerIDMap.end()) {
return;
}
if (_dbEventCallback) {
_dbEventCallback(value);
}
}
void CCArmatureDisplay::removeDBEventListener(const std::string &type, const std::function<void(EventObject *)> & /*listener*/) {
auto it = _listenerIDMap.find(type);
if (it != _listenerIDMap.end()) {
_listenerIDMap.erase(it);
}
}
se_object_ptr CCArmatureDisplay::getDebugData() const {
if (_debugBuffer) {
return _debugBuffer->getTypeArray();
}
return nullptr;
}
void CCArmatureDisplay::setColor(float r, float g, float b, float a) {
_nodeColor.r = r / 255.0F;
_nodeColor.g = g / 255.0F;
_nodeColor.b = b / 255.0F;
_nodeColor.a = a / 255.0F;
}
se_object_ptr CCArmatureDisplay::getSharedBufferOffset() const {
if (_sharedBufferOffset) {
return _sharedBufferOffset->getTypeArray();
}
return nullptr;
}
void CCArmatureDisplay::setBatchEnabled(bool enabled) {
if (enabled != _enableBatch) {
for (auto &item : _materialCaches) {
CC_SAFE_DELETE(item.second);
}
_materialCaches.clear();
_enableBatch = enabled;
}
}
void CCArmatureDisplay::setRenderEntity(cc::RenderEntity *entity) {
_entity = entity;
}
void CCArmatureDisplay::setMaterial(cc::Material *material) {
_material = material;
for (auto &item : _materialCaches) {
CC_SAFE_DELETE(item.second);
}
_materialCaches.clear();
}
cc::RenderDrawInfo *CCArmatureDisplay::requestDrawInfo(int idx) {
if (_drawInfoArray.size() < idx + 1) {
cc::RenderDrawInfo *draw = new cc::RenderDrawInfo();
draw->setDrawInfoType(static_cast<uint32_t>(RenderDrawInfoType::MIDDLEWARE));
_drawInfoArray.push_back(draw);
}
return _drawInfoArray[idx];
}
cc::Material *CCArmatureDisplay::requestMaterial(uint16_t blendSrc, uint16_t blendDst) {
uint32_t key = static_cast<uint32_t>(blendSrc) << 16 | static_cast<uint32_t>(blendDst);
if (_materialCaches.find(key) == _materialCaches.end()) {
const IMaterialInstanceInfo info{
(Material *)_material,
0};
MaterialInstance *materialInstance = new MaterialInstance(info);
PassOverrides overrides;
BlendStateInfo stateInfo;
stateInfo.blendColor = gfx::Color{1.0F, 1.0F, 1.0F, 1.0F};
BlendTargetInfo targetInfo;
targetInfo.blendEq = gfx::BlendOp::ADD;
targetInfo.blendAlphaEq = gfx::BlendOp::ADD;
targetInfo.blendSrc = (gfx::BlendFactor)blendSrc;
targetInfo.blendDst = (gfx::BlendFactor)blendDst;
targetInfo.blendSrcAlpha = (gfx::BlendFactor)blendSrc;
targetInfo.blendDstAlpha = (gfx::BlendFactor)blendDst;
BlendTargetInfoList targetList{targetInfo};
stateInfo.targets = targetList;
overrides.blendState = stateInfo;
materialInstance->overridePipelineStates(overrides);
const MacroRecord macros{{"USE_LOCAL", false}};
materialInstance->recompileShaders(macros);
_materialCaches[key] = materialInstance;
}
return _materialCaches[key];
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,211 @@
/****************************************************************************
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.
****************************************************************************/
#ifndef DRAGONBONES_CC_ARMATURE_DISPLAY_CONTAINER_H
#define DRAGONBONES_CC_ARMATURE_DISPLAY_CONTAINER_H
#include <map>
#include <utility>
#include <vector>
#include "IOTypedArray.h"
#include "MiddlewareManager.h"
#include "base/RefCounted.h"
#include "base/RefMap.h"
#include "bindings/event/EventDispatcher.h"
#include "dragonbones-creator-support/CCSlot.h"
#include "dragonbones/DragonBonesHeaders.h"
#include "middleware-adapter.h"
namespace cc {
class RenderEntity;
class RenderDrawInfo;
class Material;
class Texture2D;
}; // namespace cc
DRAGONBONES_NAMESPACE_BEGIN
/**
* CCArmatureDisplay is a armature tree.It can add or remove a childArmature.
* It will not save vertices and indices.Only CCSlot will save these info.
* And CCArmatureDisplay will traverse all tree node and calculate render data.
*/
class CCArmatureDisplay : public cc::RefCounted, public virtual IArmatureProxy {
DRAGONBONES_DISALLOW_COPY_AND_ASSIGN(CCArmatureDisplay)
public:
/**
* @internal
*/
static CCArmatureDisplay *create();
private:
void traverseArmature(Armature *armature, float parentOpacity = 1.0F);
protected:
bool _debugDraw = false;
Armature *_armature = nullptr;
public:
CCArmatureDisplay();
~CCArmatureDisplay() override;
/**
* @inheritDoc
*/
void dbInit(Armature *armature) override;
/**
* @inheritDoc
*/
void dbClear() override;
/**
* @inheritDoc
*/
void dbUpdate() override;
/**
* @inheritDoc
*/
void dbRender() override;
/**
* @inheritDoc
*/
void dispose() override;
/**
* @inheritDoc
*/
bool hasDBEventListener(const std::string &type) const override;
/**
* @inheritDoc
*/
void dispatchDBEvent(const std::string &type, EventObject *value) override;
/**
* @inheritDoc
*/
void addDBEventListener(const std::string &type, const std::function<void(EventObject *)> &listener) override;
/**
* @inheritDoc
*/
void removeDBEventListener(const std::string &type, const std::function<void(EventObject *)> &listener) override;
using dbEventCallback = std::function<void(EventObject *)>;
void setDBEventCallback(dbEventCallback callback) {
_dbEventCallback = std::move(callback);
}
/**
* @inheritDoc
*/
inline Armature *getArmature() const override {
return _armature;
}
/**
* @inheritDoc
*/
inline Animation *getAnimation() const override {
return _armature->getAnimation();
}
/**
* @return debug data,it's a Float32Array,
* format |debug bones length|[beginX|beginY|toX|toY|...loop...]
*/
se_object_ptr getDebugData() const;
/**
* @return shared buffer offset, it's a Uint32Array
* format |render info offset|attach info offset|
*/
se_object_ptr getSharedBufferOffset() const;
void setColor(float r, float g, float b, float a);
void setDebugBonesEnabled(bool enabled) {
_debugDraw = enabled;
}
void setBatchEnabled(bool enabled);
void setAttachEnabled(bool enabled) {
_useAttach = enabled;
}
void setOpacityModifyRGB(bool value) {
_premultipliedAlpha = value;
}
/**
* @brief Convert component position to global position.
* @param[in] pos Component position
* @return Global position
*/
const cc::Vec2 &convertToRootSpace(float x, float y) const;
/**
* @return root display,if this diplay is root,then return itself.
*/
CCArmatureDisplay *getRootDisplay();
cc::RenderDrawInfo *requestDrawInfo(int idx);
cc::Material *requestMaterial(uint16_t blendSrc, uint16_t blendDst);
void setMaterial(cc::Material *material);
void setRenderEntity(cc::RenderEntity *entity);
private:
std::map<std::string, bool> _listenerIDMap;
int _preBlendMode = -1;
int _curBlendSrc = -1;
int _curBlendDst = -1;
cc::Texture2D *_preTexture = nullptr;
cc::Texture2D *_curTexture = nullptr;
cc::RenderDrawInfo *_curDrawInfo = nullptr;
int _preISegWritePos = -1;
int _curISegLen = 0;
int _debugSlotsLen = 0;
int _materialLen = 0;
bool _useAttach = false;
bool _premultipliedAlpha = false;
bool _enableBatch = false;
// NOTE: We bind Vec2 to make JS deserialization works, we need to return const reference in convertToRootSpace method,
// because returning Vec2 JSB object on stack to JS will let JS get mess data.
mutable cc::Vec2 _tmpVec2;
//
cc::middleware::Color4F _nodeColor = cc::middleware::Color4F::WHITE;
dbEventCallback _dbEventCallback = nullptr;
cc::middleware::IOTypedArray *_sharedBufferOffset = nullptr;
cc::middleware::IOTypedArray *_debugBuffer = nullptr;
cc::RenderEntity *_entity = nullptr;
cc::Material *_material = nullptr;
ccstd::vector<cc::RenderDrawInfo *> _drawInfoArray;
ccstd::unordered_map<uint32_t, cc::Material *> _materialCaches;
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_CC_ARMATURE_DISPLAY_CONTAINER_H

View File

@@ -0,0 +1,36 @@
/****************************************************************************
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.
****************************************************************************/
#ifndef DRAGONBONES_CC_HEADERS_H
#define DRAGONBONES_CC_HEADERS_H
#include "dragonbones-creator-support/ArmatureCacheMgr.h"
#include "dragonbones-creator-support/CCArmatureCacheDisplay.h"
#include "dragonbones-creator-support/CCArmatureDisplay.h"
#include "dragonbones-creator-support/CCFactory.h"
#include "dragonbones-creator-support/CCSlot.h"
#include "dragonbones-creator-support/CCTextureAtlasData.h"
#endif // DRAGONBONES_CC_HEADERS_H

View File

@@ -0,0 +1,210 @@
/****************************************************************************
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/CCFactory.h"
#include "dragonbones-creator-support/CCArmatureDisplay.h"
#include "dragonbones-creator-support/CCSlot.h"
#include "dragonbones-creator-support/CCTextureAtlasData.h"
#include "platform/FileUtils.h"
using namespace cc;
DRAGONBONES_NAMESPACE_BEGIN
DragonBones *CCFactory::_dragonBonesInstance = nullptr;
CCFactory *CCFactory::_factory = nullptr;
TextureAtlasData *CCFactory::_buildTextureAtlasData(TextureAtlasData *textureAtlasData, void *textureAtlas) const {
if (textureAtlasData != nullptr) {
const auto pos = _prevPath.find_last_of("/");
if (pos != std::string::npos) {
const auto basePath = _prevPath.substr(0, pos + 1);
textureAtlasData->imagePath = basePath + textureAtlasData->imagePath;
}
if (textureAtlas != nullptr) {
static_cast<CCTextureAtlasData *>(textureAtlasData)->setRenderTexture(static_cast<middleware::Texture2D *>(textureAtlas));
}
} else {
textureAtlasData = BaseObject::borrowObject<CCTextureAtlasData>();
}
return textureAtlasData;
}
Armature *CCFactory::_buildArmature(const BuildArmaturePackage &dataPackage) const {
const auto armature = BaseObject::borrowObject<Armature>();
const auto armatureDisplay = CCArmatureDisplay::create();
// will release when armature destructor
armatureDisplay->addRef();
armature->init(
dataPackage.armature,
armatureDisplay, armatureDisplay, _dragonBones);
return armature;
}
Slot *CCFactory::_buildSlot(const BuildArmaturePackage &dataPackage, const SlotData *slotData, Armature *armature) const {
const auto slot = BaseObject::borrowObject<CCSlot>();
slot->init(
slotData, armature,
slot, slot);
return slot;
}
DragonBonesData *CCFactory::loadDragonBonesData(const std::string &filePath, const std::string &name, float scale) {
if (!name.empty()) {
const auto existedData = getDragonBonesData(name);
if (existedData) {
return existedData;
}
}
const auto fullpath = cc::FileUtils::getInstance()->fullPathForFilename(filePath);
if (cc::FileUtils::getInstance()->isFileExist(filePath)) {
const auto pos = fullpath.find(".json");
if (pos != std::string::npos) {
const auto data = cc::FileUtils::getInstance()->getStringFromFile(filePath);
return parseDragonBonesData(data.c_str(), name, scale);
} else {
cc::Data cocos2dData;
cc::FileUtils::getInstance()->getContents(fullpath, &cocos2dData);
uint8_t *binary = cocos2dData.takeBuffer();
// NOTE: binary is freed in DragonBonesData::_onClear
return parseDragonBonesData(reinterpret_cast<char *>(binary), name, scale);
}
}
return nullptr;
}
DragonBonesData *CCFactory::parseDragonBonesDataByPath(const std::string &filePath, const std::string &name, float scale) {
if (!name.empty()) {
const auto existedData = getDragonBonesData(name);
if (existedData) {
return existedData;
}
}
const auto dbbinPos = filePath.find(".dbbin");
if (dbbinPos != std::string::npos) {
const auto fullpath = cc::FileUtils::getInstance()->fullPathForFilename(filePath);
if (cc::FileUtils::getInstance()->isFileExist(filePath)) {
cc::Data cocos2dData;
cc::FileUtils::getInstance()->getContents(fullpath, &cocos2dData);
uint8_t *binary = cocos2dData.takeBuffer();
// NOTE: binary is freed in DragonBonesData::_onClear
return parseDragonBonesData(reinterpret_cast<char *>(binary), name, scale);
}
} else {
return parseDragonBonesData(filePath.c_str(), name, scale);
}
return nullptr;
}
DragonBonesData *CCFactory::getDragonBonesDataByUUID(const std::string &uuid) {
DragonBonesData *bonesData = nullptr;
for (auto it = _dragonBonesDataMap.begin(); it != _dragonBonesDataMap.end();) {
if (it->first.find(uuid) != std::string::npos) {
bonesData = it->second;
break;
} else {
it++;
}
}
return bonesData;
}
void CCFactory::removeDragonBonesDataByUUID(const std::string &uuid, bool disposeData) {
for (auto it = _dragonBonesDataMap.begin(); it != _dragonBonesDataMap.end();) {
if (it->first.find(uuid) != std::string::npos) {
if (disposeData) {
it->second->returnToPool();
}
it = _dragonBonesDataMap.erase(it);
} else {
it++;
}
}
}
TextureAtlasData *CCFactory::loadTextureAtlasData(const std::string &filePath, const std::string &name, float scale) {
_prevPath = cc::FileUtils::getInstance()->fullPathForFilename(filePath);
const auto data = cc::FileUtils::getInstance()->getStringFromFile(_prevPath);
if (data.empty()) {
return nullptr;
}
return static_cast<CCTextureAtlasData *>(BaseFactory::parseTextureAtlasData(data.c_str(), nullptr, name, scale));
}
CCArmatureDisplay *CCFactory::buildArmatureDisplay(const std::string &armatureName, const std::string &dragonBonesName, const std::string &skinName, const std::string &textureAtlasName) const {
const auto armature = buildArmature(armatureName, dragonBonesName, skinName, textureAtlasName);
if (armature != nullptr) {
return static_cast<CCArmatureDisplay *>(armature->getDisplay());
}
return nullptr;
}
void CCFactory::removeTextureAtlasDataByIndex(const std::string &name, int textureIndex) {
const auto iterator = _textureAtlasDataMap.find(name);
if (iterator != _textureAtlasDataMap.end()) {
auto &textureAtlasDataList = iterator->second;
for (auto it = textureAtlasDataList.begin(); it != textureAtlasDataList.end(); it++) {
middleware::Texture2D *texture = ((CCTextureAtlasData *)*it)->getRenderTexture();
if (texture && texture->getRealTextureIndex() == textureIndex) {
textureAtlasDataList.erase(it);
break;
}
}
if (textureAtlasDataList.size() == 0) {
_textureAtlasDataMap.erase(iterator);
}
}
}
CCTextureAtlasData *CCFactory::getTextureAtlasDataByIndex(const std::string &name, int textureIndex) const {
const auto iterator = _textureAtlasDataMap.find(name);
if (iterator != _textureAtlasDataMap.end()) {
auto &textureAtlasDataList = iterator->second;
for (auto it = textureAtlasDataList.begin(); it != textureAtlasDataList.end(); it++) {
middleware::Texture2D *texture = ((CCTextureAtlasData *)*it)->getRenderTexture();
if (texture && texture->getRealTextureIndex() == textureIndex) {
return (CCTextureAtlasData *)*it;
}
}
}
return nullptr;
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,255 @@
/****************************************************************************
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.
****************************************************************************/
#ifndef DRAGONBONES_CC_FACTORY_H
#define DRAGONBONES_CC_FACTORY_H
#include "MiddlewareManager.h"
#include "dragonbones-creator-support/CCArmatureDisplay.h"
#include "dragonbones/DragonBonesHeaders.h"
DRAGONBONES_NAMESPACE_BEGIN
class CCTextureAtlasData;
/**
* The Cocos2d factory.
* @version DragonBones 3.0
* @language en_US
*/
/**
* Cocos2d 工厂。
* @version DragonBones 3.0
* @language zh_CN
*/
class CCFactory : public BaseFactory, public cc::middleware::IMiddleware {
DRAGONBONES_DISALLOW_COPY_AND_ASSIGN(CCFactory)
private:
static DragonBones *_dragonBonesInstance;
static CCFactory *_factory;
public:
static bool isInit() {
return _factory != nullptr;
}
/**
* A global factory instance that can be used directly.
* @version DragonBones 4.7
* @language en_US
*/
/**
* 一个可以直接使用的全局工厂实例。
* @version DragonBones 4.7
* @language zh_CN
*/
static CCFactory *getFactory() {
if (CCFactory::_factory == nullptr) {
CCFactory::_factory = new CCFactory();
}
return CCFactory::_factory;
}
static void destroyFactory() {
if (_dragonBonesInstance) {
delete _dragonBonesInstance;
_dragonBonesInstance = nullptr;
}
if (_factory) {
delete _factory;
_factory = nullptr;
}
}
protected:
std::string _prevPath;
public:
/**
* @inheritDoc
*/
CCFactory() : _prevPath() {
if (_dragonBonesInstance == nullptr) {
const auto eventManager = CCArmatureDisplay::create();
eventManager->addRef();
_dragonBonesInstance = new DragonBones(eventManager);
cc::middleware::MiddlewareManager::getInstance()->addTimer(this);
}
_dragonBones = _dragonBonesInstance;
}
virtual void update(float dt) override {
_dragonBonesInstance->advanceTime(dt);
}
virtual void render(float dt) override {
_dragonBonesInstance->render();
}
/**
* @note When script engine clean up is trigger,will stop dragonbones timer.
*/
void stopSchedule() {
cc::middleware::MiddlewareManager::getInstance()->removeTimer(this);
}
/**
* @note Destructor call by jsb_dragonbones_manual,when script engine clean up is trigger.
*/
virtual ~CCFactory() {
clear(false);
}
protected:
virtual TextureAtlasData *_buildTextureAtlasData(TextureAtlasData *textureAtlasData, void *textureAtlas) const override;
virtual Armature *_buildArmature(const BuildArmaturePackage &dataPackage) const override;
virtual Slot *_buildSlot(const BuildArmaturePackage &dataPackage, const SlotData *slotData, Armature *armature) const override;
public:
virtual DragonBonesData *loadDragonBonesData(const std::string &filePath, const std::string &name = "", float scale = 1.0f);
/**
* - Load and parse a texture atlas data and texture from the local and cache them to the factory.
* @param filePath - The file path of texture atlas data.
* @param name - Specify a cache name for the instance so that the instance can be obtained through this name. (If not set, use the instance name instead)
* @param scale - Specify a scaling value for the map set. (Not scaled by default)
* @returns The TextureAtlasData instance.
* @version DragonBones 4.5
* @example
* <pre>
* factory.loadTextureAtlasData("hero_tex.json");
* </pre>
* @language en_US
*/
/**
* - 从本地加载并解析一个贴图集数据和贴图并缓存到工厂中。
* @param filePath - 贴图集数据文件路径。
* @param name - 为该实例指定一个缓存名称,以便可以通过此名称获取该实例。 (如果未设置,则使用该实例中的名称)
* @param scale - 为贴图集指定一个缩放值。 (默认不缩放)
* @returns TextureAtlasData 实例。
* @version DragonBones 4.5
* @example
* <pre>
* factory.loadTextureAtlasData("hero_tex.json");
* </pre>
* @language zh_CN
*/
virtual TextureAtlasData *loadTextureAtlasData(const std::string &filePath, const std::string &name = "", float scale = 1.0f);
/**
* - Create a armature from cached DragonBonesData instances and TextureAtlasData instances, then use the {@link #clock} to update it.
* The difference is that the armature created by {@link #buildArmature} is not WorldClock instance update.
* @param armatureName - The armature data name.
* @param dragonBonesName - The cached name of the DragonBonesData instance. (If not set, all DragonBonesData instances are retrieved, and when multiple DragonBonesData instances contain a the same name armature data, it may not be possible to accurately create a specific armature)
* @param skinName - The skin name, you can set a different ArmatureData name to share it's skin data. (If not set, use the default skin data)
* @returns The armature display container.
* @version DragonBones 4.5
* @example
* <pre>
* let armatureDisplay = factory.buildArmatureDisplay("armatureName", "dragonBonesName");
* </pre>
* @language en_US
*/
/**
* - 通过缓存的 DragonBonesData 实例和 TextureAtlasData 实例创建一个骨架,并用 {@link #clock} 更新该骨架。
* 区别在于由 {@link #buildArmature} 创建的骨架没有 WorldClock 实例驱动。
* @param armatureName - 骨架数据名称。
* @param dragonBonesName - DragonBonesData 实例的缓存名称。 (如果未设置,将检索所有的 DragonBonesData 实例,当多个 DragonBonesData 实例中包含同名的骨架数据时,可能无法准确的创建出特定的骨架)
* @param skinName - 皮肤名称,可以设置一个其他骨架数据名称来共享其皮肤数据。 (如果未设置,则使用默认的皮肤数据)
* @returns 骨架的显示容器。
* @version DragonBones 4.5
* @example
* <pre>
* let armatureDisplay = factory.buildArmatureDisplay("armatureName", "dragonBonesName");
* </pre>
* @language zh_CN
*/
virtual CCArmatureDisplay *buildArmatureDisplay(const std::string &armatureName, const std::string &dragonBonesName = "", const std::string &skinName = "", const std::string &textureAtlasName = "") const;
/**
* - A global sound event manager.
* Sound events can be listened to uniformly from the manager.
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 全局声音事件管理器。
* 声音事件可以从该管理器统一侦听。
* @version DragonBones 4.5
* @language zh_CN
*/
virtual CCArmatureDisplay *getSoundEventManager() const {
return dynamic_cast<CCArmatureDisplay *>(static_cast<IArmatureProxy *>(_dragonBones->getEventManager()));
}
/**
* Deprecated, please refer to {@link #clock}.
* @deprecated
* @language en_US
*/
/**
* 已废弃,请参考 {@link #clock}。
* @deprecated
* @language zh_CN
*/
static WorldClock *getClock() {
return _dragonBonesInstance->getClock();
}
void add(Armature *armature) {
_dragonBonesInstance->getClock()->add(armature);
}
void remove(Armature *armature) {
_dragonBonesInstance->getClock()->remove(armature);
}
void setTimeScale(float timeScale) {
_dragonBonesInstance->getClock()->timeScale = timeScale;
}
float getTimeScale() {
return _dragonBonesInstance->getClock()->timeScale;
}
DragonBones *getDragonBones() {
return _dragonBonesInstance;
}
DragonBonesData *getDragonBonesDataByUUID(const std::string &uuid);
void removeTextureAtlasDataByIndex(const std::string &name, int textureIndex);
void removeDragonBonesDataByUUID(const std::string &uuid, bool disposeData = true);
CCTextureAtlasData *getTextureAtlasDataByIndex(const std::string &name, int textureIndex) const;
DragonBonesData *parseDragonBonesDataByPath(const std::string &filePath, const std::string &name = "", float scale = 1.0f);
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_CC_FACTORY_H

View File

@@ -0,0 +1,455 @@
/****************************************************************************
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 &region = 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

View File

@@ -0,0 +1,95 @@
/****************************************************************************
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.
****************************************************************************/
#ifndef DRAGONBONES_CC_SLOT_H
#define DRAGONBONES_CC_SLOT_H
#include "dragonbones/DragonBonesHeaders.h"
#include "math/Geometry.h"
#include "math/Mat4.h"
#include "middleware-adapter.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* The Cocos2d slot.
* @version DragonBones 3.0
* @language en_US
*/
/**
* Cocos2d 插槽。
* @version DragonBones 3.0
* @language zh_CN
*/
class CCSlot : public Slot {
BIND_CLASS_TYPE_A(CCSlot);
public:
// Global matrix (相对于骨骼部件)
cc::Mat4 worldMatrix;
// Global matrix dirty flag
bool _worldMatDirty = true;
// Slot triangles
cc::middleware::Triangles triangles;
// Slot vertex transform to World vertex
cc::middleware::V3F_T2F_C4B *worldVerts = nullptr;
cc::middleware::Color4B color;
cc::Rect boundsRect;
private:
cc::Mat4 _localMatrix;
private:
void disposeTriangles();
void calculWorldMatrix();
void adjustTriangles(const unsigned vertexCount, const unsigned indicesCount);
protected:
virtual void _onClear() override;
virtual void _initDisplay(void *value, bool isRetain) override;
virtual void _disposeDisplay(void *value, bool isRelease) override;
virtual void _onUpdateDisplay() override;
virtual void _addDisplay() override;
virtual void _replaceDisplay(void *value, bool isArmatureDisplay) override;
virtual void _removeDisplay() override;
virtual void _updateZOrder() override;
public:
virtual void _updateVisible() override;
virtual void _updateBlendMode() override;
virtual void _updateColor() override;
void updateWorldMatrix();
cc::middleware::Texture2D *getTexture() const;
protected:
virtual void _updateFrame() override;
virtual void _updateMesh() override;
virtual void _updateTransform() override;
virtual void _identityTransform() override;
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_CC_SLOT_H

View File

@@ -0,0 +1,90 @@
/****************************************************************************
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/CCTextureAtlasData.h"
using namespace cc;
DRAGONBONES_NAMESPACE_BEGIN
void CCTextureAtlasData::_onClear() {
TextureAtlasData::_onClear();
if (_renderTexture != nullptr) {
_renderTexture->release();
_renderTexture = nullptr;
}
}
TextureData *CCTextureAtlasData::createTexture() const {
return (TextureData *)BaseObject::borrowObject<CCTextureData>();
}
void CCTextureAtlasData::setRenderTexture(middleware::Texture2D *value) {
if (_renderTexture == value) {
return;
}
_renderTexture = value;
if (_renderTexture != nullptr) {
_renderTexture->addRef();
for (const auto &pair : textures) {
const auto textureData = static_cast<CCTextureData *>(pair.second);
if (textureData->spriteFrame == nullptr) {
cc::Rect rect(
textureData->region.x, textureData->region.y,
textureData->rotated ? textureData->region.height : textureData->region.width,
textureData->rotated ? textureData->region.width : textureData->region.height);
cc::Vec2 offset(0.0f, 0.0f);
cc::Size originSize(rect.width, rect.height);
textureData->spriteFrame = middleware::SpriteFrame::createWithTexture(_renderTexture, rect, textureData->rotated, offset, originSize); // TODO multiply textureAtlas
textureData->spriteFrame->addRef();
}
}
} else {
for (const auto &pair : textures) {
const auto textureData = static_cast<CCTextureData *>(pair.second);
if (textureData->spriteFrame != nullptr) {
textureData->spriteFrame->release();
textureData->spriteFrame = nullptr;
}
}
}
}
void CCTextureData::_onClear() {
TextureData::_onClear();
if (spriteFrame != nullptr) {
spriteFrame->release();
spriteFrame = nullptr;
}
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,104 @@
/****************************************************************************
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.
****************************************************************************/
#ifndef DRAGONBONES_CC_TEXTUREATLAS_DATA_H
#define DRAGONBONES_CC_TEXTUREATLAS_DATA_H
#include "dragonbones/DragonBonesHeaders.h"
#include "middleware-adapter.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* The Cocos2d texture atlas data.
* @version DragonBones 3.0
* @language en_US
*/
/**
* Cocos2d 贴图集数据。
* @version DragonBones 3.0
* @language zh_CN
*/
class CCTextureAtlasData : public TextureAtlasData {
BIND_CLASS_TYPE_B(CCTextureAtlasData);
private:
cc::middleware::Texture2D *_renderTexture;
public:
CCTextureAtlasData() : _renderTexture(nullptr) {
_onClear();
}
virtual ~CCTextureAtlasData() {
_onClear();
}
protected:
virtual void _onClear() override;
public:
/**
* @inheritDoc
*/
virtual TextureData *createTexture() const override;
/**
* The Cocos2d texture.
* @version DragonBones 3.0
* @language en_US
*/
/**
* Cocos2d 贴图。
* @version DragonBones 3.0
* @language zh_CN
*/
inline cc::middleware::Texture2D *getRenderTexture() const {
return _renderTexture;
}
void setRenderTexture(cc::middleware::Texture2D *value);
};
/**
* @internal
*/
class CCTextureData : public TextureData {
BIND_CLASS_TYPE_B(CCTextureData);
public:
cc::middleware::SpriteFrame *spriteFrame;
CCTextureData() : spriteFrame(nullptr) {
_onClear();
}
virtual ~CCTextureData() {
_onClear();
}
protected:
virtual void _onClear() override;
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_CC_TEXTUREATLAS_DATA_H