mirror of https://github.com/axmolengine/axmol.git
233 lines
6.7 KiB
C++
233 lines
6.7 KiB
C++
#include "CCArmatureDisplay.h"
|
|
#include "CCSlot.h"
|
|
|
|
DRAGONBONES_NAMESPACE_BEGIN
|
|
|
|
CCArmatureDisplay* CCArmatureDisplay::create()
|
|
{
|
|
CCArmatureDisplay* displayContainer = new CCArmatureDisplay();
|
|
if (displayContainer->init())
|
|
{
|
|
displayContainer->autorelease();
|
|
}
|
|
else
|
|
{
|
|
AX_SAFE_DELETE(displayContainer);
|
|
}
|
|
|
|
return displayContainer;
|
|
}
|
|
|
|
void CCArmatureDisplay::dbInit(Armature* armature)
|
|
{
|
|
_armature = armature;
|
|
}
|
|
|
|
void CCArmatureDisplay::dbClear()
|
|
{
|
|
setEventDispatcher(ax::Director::getInstance()->getEventDispatcher());
|
|
|
|
_armature = nullptr;
|
|
AX_SAFE_RELEASE(_dispatcher);
|
|
release();
|
|
}
|
|
|
|
void CCArmatureDisplay::dispose(bool disposeProxy)
|
|
{
|
|
if (_armature != nullptr)
|
|
{
|
|
_armature->dispose();
|
|
_armature = nullptr;
|
|
}
|
|
}
|
|
|
|
void CCArmatureDisplay::dbUpdate()
|
|
{
|
|
const auto drawed = DragonBones::debugDraw;
|
|
if (drawed || _debugDraw)
|
|
{
|
|
_debugDraw = drawed;
|
|
if (_debugDraw)
|
|
{}
|
|
else
|
|
{
|
|
// TODO
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCArmatureDisplay::addDBEventListener(std::string_view type, const std::function<void(EventObject*)>& callback)
|
|
{
|
|
auto lambda = [callback](ax::EventCustom* event) -> void {
|
|
callback(static_cast<EventObject*>(event->getUserData()));
|
|
};
|
|
_dispatcher->addCustomEventListener(type, lambda);
|
|
}
|
|
|
|
void CCArmatureDisplay::dispatchDBEvent(std::string_view type, EventObject* value)
|
|
{
|
|
_dispatcher->dispatchCustomEvent(type, value);
|
|
}
|
|
|
|
void CCArmatureDisplay::removeDBEventListener(std::string_view type, const std::function<void(EventObject*)>& callback)
|
|
{
|
|
// TODO
|
|
_dispatcher->removeCustomEventListeners(type);
|
|
}
|
|
|
|
ax::Rect CCArmatureDisplay::getBoundingBox() const
|
|
{
|
|
auto isFirst = true;
|
|
float minX = 0.0f;
|
|
float minY = 0.0f;
|
|
float maxX = 0.0f;
|
|
float maxY = 0.0f;
|
|
|
|
for (const auto slot : _armature->getSlots())
|
|
{
|
|
if (!slot->getVisible() || !slot->getDisplay())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const auto display = static_cast<CCSlot*>(slot)->getCCDisplay();
|
|
const auto bounds = display->getBoundingBox();
|
|
if (isFirst)
|
|
{
|
|
isFirst = false;
|
|
minX = bounds.getMinX();
|
|
minY = bounds.getMinY();
|
|
maxX = bounds.getMaxX();
|
|
maxY = bounds.getMaxY();
|
|
}
|
|
else
|
|
{
|
|
minX = std::min(minX, bounds.getMinX());
|
|
minY = std::min(minY, bounds.getMinY());
|
|
maxX = std::max(maxX, bounds.getMaxX());
|
|
maxY = std::max(maxY, bounds.getMaxY());
|
|
}
|
|
}
|
|
|
|
ax::Rect rect(minX, minY, maxX - minX, maxY - minY);
|
|
|
|
return ax::RectApplyTransform(rect, getNodeToParentTransform());
|
|
}
|
|
|
|
DBCCSprite* DBCCSprite::create()
|
|
{
|
|
DBCCSprite* sprite = new DBCCSprite();
|
|
|
|
if (sprite->init())
|
|
{
|
|
sprite->autorelease();
|
|
}
|
|
else
|
|
{
|
|
AX_SAFE_DELETE(sprite);
|
|
}
|
|
|
|
return sprite;
|
|
}
|
|
|
|
bool DBCCSprite::_checkVisibility(const ax::Mat4& transform, const ax::Size& size, const ax::Rect& rect)
|
|
{
|
|
auto scene = ax::Director::getInstance()->getRunningScene();
|
|
|
|
// If draw to Rendertexture, return true directly.
|
|
// only cull the default camera. The culling algorithm is valid for default camera.
|
|
if (!scene || (scene && scene->getDefaultCamera() != ax::Camera::getVisitingCamera()))
|
|
return true;
|
|
|
|
auto director = ax::Director::getInstance();
|
|
ax::Rect visiableRect(director->getVisibleOrigin(), director->getVisibleSize());
|
|
|
|
// transform center point to screen space
|
|
float hSizeX = size.width / 2;
|
|
float hSizeY = size.height / 2;
|
|
|
|
ax::Vec3 v3p(hSizeX, hSizeY, 0);
|
|
|
|
transform.transformPoint(&v3p);
|
|
ax::Vec2 v2p = ax::Camera::getVisitingCamera()->projectGL(v3p);
|
|
|
|
// convert content size to world coordinates
|
|
float wshw = std::max(fabsf(hSizeX * transform.m[0] + hSizeY * transform.m[4]),
|
|
fabsf(hSizeX * transform.m[0] - hSizeY * transform.m[4]));
|
|
float wshh = std::max(fabsf(hSizeX * transform.m[1] + hSizeY * transform.m[5]),
|
|
fabsf(hSizeX * transform.m[1] - hSizeY * transform.m[5]));
|
|
|
|
// enlarge visible rect half size in screen coord
|
|
visiableRect.origin.x -= wshw;
|
|
visiableRect.origin.y -= wshh;
|
|
visiableRect.size.width += wshw * 2;
|
|
visiableRect.size.height += wshh * 2;
|
|
bool ret = visiableRect.containsPoint(v2p);
|
|
return ret;
|
|
}
|
|
|
|
void DBCCSprite::draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags)
|
|
{
|
|
#if AX_USE_CULLING
|
|
# if COCOS2D_VERSION >= 0x00031400
|
|
const auto& rect = _polyInfo.getRect();
|
|
# else
|
|
const auto& rect = _polyInfo.rect;
|
|
# endif
|
|
|
|
// Don't do calculate the culling if the transform was not updated
|
|
auto visitingCamera = ax::Camera::getVisitingCamera();
|
|
auto defaultCamera = ax::Camera::getDefaultCamera();
|
|
if (visitingCamera == defaultCamera)
|
|
{
|
|
_insideBounds = ((flags & FLAGS_TRANSFORM_DIRTY) || visitingCamera->isViewProjectionUpdated())
|
|
? _checkVisibility(transform, _contentSize, rect)
|
|
: _insideBounds;
|
|
}
|
|
else
|
|
{
|
|
_insideBounds = _checkVisibility(transform, _contentSize, rect);
|
|
}
|
|
|
|
if (_insideBounds)
|
|
#endif
|
|
{
|
|
#if COCOS2D_VERSION >= 0x00040000
|
|
_trianglesCommand.init(_globalZOrder, _texture, _blendFunc, _polyInfo.triangles, transform, flags);
|
|
#else
|
|
_trianglesCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, _polyInfo.triangles,
|
|
transform, flags);
|
|
#endif
|
|
renderer->addCommand(&_trianglesCommand);
|
|
|
|
#if AX_SPRITE_DEBUG_DRAW
|
|
_debugDrawNode->clear();
|
|
auto count = _polyInfo.triangles.indexCount / 3;
|
|
auto indices = _polyInfo.triangles.indices;
|
|
auto verts = _polyInfo.triangles.verts;
|
|
for (ssize_t i = 0; i < count; i++)
|
|
{
|
|
// draw 3 lines
|
|
auto from = verts[indices[i * 3]].vertices;
|
|
auto to = verts[indices[i * 3 + 1]].vertices;
|
|
_debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color4F::WHITE);
|
|
|
|
from = verts[indices[i * 3 + 1]].vertices;
|
|
to = verts[indices[i * 3 + 2]].vertices;
|
|
_debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color4F::WHITE);
|
|
|
|
from = verts[indices[i * 3 + 2]].vertices;
|
|
to = verts[indices[i * 3]].vertices;
|
|
_debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color4F::WHITE);
|
|
}
|
|
#endif // AX_SPRITE_DEBUG_DRAW
|
|
}
|
|
}
|
|
|
|
ax::PolygonInfo& DBCCSprite::getPolygonInfoModify()
|
|
{
|
|
return _polyInfo;
|
|
}
|
|
|
|
DRAGONBONES_NAMESPACE_END
|