2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
2020-10-17 16:32:16 +08:00
|
|
|
Copyright (c) 2013-2017 Chukong Technologies Inc.
|
2021-07-16 11:04:38 +08:00
|
|
|
Copyright (c) 2021 Bytedance Inc.
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-07-16 11:04:38 +08:00
|
|
|
https://adxe.org
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
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 "2d/CCSpriteFrame.h"
|
|
|
|
#include "2d/CCSpriteFrameCache.h"
|
|
|
|
#include "base/CCDirector.h"
|
|
|
|
#include "renderer/CCRenderer.h"
|
|
|
|
|
2020-10-21 10:12:00 +08:00
|
|
|
#include "CCSkin.h"
|
|
|
|
#include "CCTransformHelp.h"
|
|
|
|
#include "CCArmature.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
using namespace cocos2d;
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
namespace cocostudio
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
#if CC_SPRITEBATCHNODE_RENDER_SUBPIXEL
|
2021-12-25 10:04:45 +08:00
|
|
|
# define RENDER_IN_SUBPIXEL
|
2019-11-23 20:27:39 +08:00
|
|
|
#else
|
2021-12-25 10:04:45 +08:00
|
|
|
# define RENDER_IN_SUBPIXEL(__ARGS__) (ceil(__ARGS__))
|
2019-11-23 20:27:39 +08:00
|
|
|
#endif
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Skin* Skin::create()
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
Skin* skin = new Skin();
|
|
|
|
if (skin->init())
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
skin->autorelease();
|
|
|
|
return skin;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(skin);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-26 23:26:34 +08:00
|
|
|
Skin* Skin::createWithSpriteFrameName(std::string_view pszSpriteFrameName)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
Skin* skin = new Skin();
|
|
|
|
if (skin->initWithSpriteFrameName(pszSpriteFrameName))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
skin->autorelease();
|
|
|
|
return skin;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(skin);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-26 23:26:34 +08:00
|
|
|
Skin* Skin::create(std::string_view pszFileName)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
Skin* skin = new Skin();
|
|
|
|
if (skin->initWithFile(pszFileName))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
skin->autorelease();
|
|
|
|
return skin;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(skin);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Skin::Skin() : _bone(nullptr), _armature(nullptr), _displayName(), _skinTransform(Mat4::IDENTITY) {}
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-26 23:26:34 +08:00
|
|
|
bool Skin::initWithSpriteFrameName(std::string_view spriteFrameName)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
CCAssert(spriteFrameName != "", "");
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
SpriteFrame* pFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(spriteFrameName);
|
|
|
|
bool ret = true;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
if (pFrame != nullptr)
|
|
|
|
{
|
|
|
|
ret = initWithSpriteFrame(pFrame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CCLOG("Can't find CCSpriteFrame with %s. Please check your .plist file", spriteFrameName.c_str());
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_displayName = spriteFrameName;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-12-26 23:26:34 +08:00
|
|
|
bool Skin::initWithFile(std::string_view filename)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
bool ret = Sprite::initWithFile(filename);
|
|
|
|
|
|
|
|
_displayName = filename;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void Skin::setSkinData(const BaseData& var)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
_skinData = var;
|
|
|
|
|
|
|
|
setScaleX(_skinData.scaleX);
|
|
|
|
setScaleY(_skinData.scaleY);
|
|
|
|
setRotationSkewX(CC_RADIANS_TO_DEGREES(_skinData.skewX));
|
|
|
|
setRotationSkewY(CC_RADIANS_TO_DEGREES(-_skinData.skewY));
|
|
|
|
setPosition(_skinData.x, _skinData.y);
|
|
|
|
|
|
|
|
_skinTransform = getNodeToParentTransform();
|
|
|
|
updateArmatureTransform();
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
const BaseData& Skin::getSkinData() const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return _skinData;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Skin::updateArmatureTransform()
|
|
|
|
{
|
|
|
|
_transform = TransformConcat(_bone->getNodeToArmatureTransform(), _skinTransform);
|
2021-12-25 10:04:45 +08:00
|
|
|
// if(_armature && _armature->getBatchNode())
|
|
|
|
// {
|
|
|
|
// _transform = TransformConcat(_transform, _armature->getNodeToParentTransform());
|
|
|
|
// }
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Skin::updateTransform()
|
|
|
|
{
|
|
|
|
// If it is not visible, or one of its ancestors is not visible, then do nothing:
|
2021-12-25 10:04:45 +08:00
|
|
|
if (!_visible)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
_quad.br.vertices.setZero();
|
|
|
|
_quad.tl.vertices.setZero();
|
|
|
|
_quad.tr.vertices.setZero();
|
|
|
|
_quad.bl.vertices.setZero();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// calculate the Quad based on the Affine Matrix
|
|
|
|
//
|
|
|
|
Mat4 transform = getNodeToParentTransform();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Size& size = _rect.size;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
float x1 = _offsetPosition.x;
|
|
|
|
float y1 = _offsetPosition.y;
|
|
|
|
|
|
|
|
float x2 = x1 + size.width;
|
|
|
|
float y2 = y1 + size.height;
|
|
|
|
|
|
|
|
if (_flippedX)
|
|
|
|
{
|
|
|
|
std::swap(x1, x2);
|
|
|
|
}
|
|
|
|
if (_flippedY)
|
|
|
|
{
|
|
|
|
std::swap(y1, y2);
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
float x = transform.m[12];
|
|
|
|
float y = transform.m[13];
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
float cr = transform.m[0];
|
|
|
|
float sr = transform.m[1];
|
2019-11-23 20:27:39 +08:00
|
|
|
float cr2 = transform.m[5];
|
|
|
|
float sr2 = -transform.m[4];
|
2021-12-25 10:04:45 +08:00
|
|
|
float ax = x1 * cr - y1 * sr2 + x;
|
|
|
|
float ay = x1 * sr + y1 * cr2 + y;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
float bx = x2 * cr - y1 * sr2 + x;
|
|
|
|
float by = x2 * sr + y1 * cr2 + y;
|
|
|
|
|
|
|
|
float cx = x2 * cr - y2 * sr2 + x;
|
|
|
|
float cy = x2 * sr + y2 * cr2 + y;
|
|
|
|
|
|
|
|
float dx = x1 * cr - y2 * sr2 + x;
|
|
|
|
float dy = x1 * sr + y2 * cr2 + y;
|
|
|
|
|
|
|
|
_quad.bl.vertices.set(RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), _positionZ);
|
|
|
|
_quad.br.vertices.set(RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), _positionZ);
|
|
|
|
_quad.tl.vertices.set(RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), _positionZ);
|
|
|
|
_quad.tr.vertices.set(RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), _positionZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARMALADE CHANGE: ADDED CHECK FOR nullptr, TO PERMIT SPRITES WITH NO BATCH NODE / TEXTURE ATLAS
|
|
|
|
if (_textureAtlas)
|
|
|
|
{
|
|
|
|
_textureAtlas->updateQuad(&_quad, _textureAtlas->getTotalQuads());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Mat4 Skin::getNodeToWorldTransform() const
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
return TransformConcat(_bone->getArmature()->getNodeToWorldTransform(), _transform);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Mat4 Skin::getNodeToWorldTransformAR() const
|
|
|
|
{
|
|
|
|
Mat4 displayTransform = _transform;
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec2 anchorPoint = _anchorPointInPoints;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
anchorPoint = PointApplyTransform(anchorPoint, displayTransform);
|
|
|
|
|
|
|
|
displayTransform.m[12] = anchorPoint.x;
|
|
|
|
displayTransform.m[13] = anchorPoint.y;
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
return TransformConcat(_bone->getArmature()->getNodeToWorldTransform(), displayTransform);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void Skin::draw(Renderer* renderer, const Mat4& /*transform*/, uint32_t flags)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
auto mv = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
|
2020-08-14 18:57:08 +08:00
|
|
|
pipelineDescriptor.programState = getProgramState();
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
// TODO: implement z order
|
2021-12-25 10:04:45 +08:00
|
|
|
_quadCommand.init(_globalZOrder, _texture, _blendFunc, &_quad, 1, mv, flags);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
renderer->addCommand(&_quadCommand);
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void Skin::setBone(Bone* bone)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
_bone = bone;
|
2021-12-25 10:04:45 +08:00
|
|
|
if (Armature* armature = _bone->getArmature())
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
_armature = armature;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Bone* Skin::getBone() const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return _bone;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
} // namespace cocostudio
|