mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-06 10:46:53 +08:00
[cocos2dx] SkeletonRenderer:getBoundingBox() recalculates the bounds on each call instead of relying on draw() having calculated it. Closes #1483.
This commit is contained in:
parent
3034d93178
commit
fba357ed74
@ -254,13 +254,12 @@ namespace spine {
|
|||||||
|
|
||||||
void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
|
void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
|
||||||
// Early exit if the skeleton is invisible
|
// Early exit if the skeleton is invisible
|
||||||
if (getDisplayedOpacity() == 0 || _skeleton->getColor().a == 0){
|
if (getDisplayedOpacity() == 0 || _skeleton->getColor().a == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int coordCount = computeTotalCoordCount(*_skeleton, _startSlotIndex, _endSlotIndex);
|
const int coordCount = computeTotalCoordCount(*_skeleton, _startSlotIndex, _endSlotIndex);
|
||||||
if (coordCount == 0)
|
if (coordCount == 0) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(coordCount % 2 == 0);
|
assert(coordCount % 2 == 0);
|
||||||
@ -273,8 +272,7 @@ namespace spine {
|
|||||||
const cocos2d::Rect brect = computeBoundingRect(worldCoords, coordCount / 2);
|
const cocos2d::Rect brect = computeBoundingRect(worldCoords, coordCount / 2);
|
||||||
_boundingRect = brect;
|
_boundingRect = brect;
|
||||||
|
|
||||||
if (camera && cullRectangle(transform, brect, *camera))
|
if (camera && cullRectangle(transform, brect, *camera)) {
|
||||||
{
|
|
||||||
VLA_FREE(worldCoords);
|
VLA_FREE(worldCoords);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -726,7 +724,13 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cocos2d::Rect SkeletonRenderer::getBoundingBox () const {
|
cocos2d::Rect SkeletonRenderer::getBoundingBox () const {
|
||||||
return _boundingRect;
|
const int coordCount = computeTotalCoordCount(*_skeleton, _startSlotIndex, _endSlotIndex);
|
||||||
|
if (coordCount == 0) return { 0, 0, 0, 0 };
|
||||||
|
VLA(float, worldCoords, coordCount);
|
||||||
|
transformWorldVertices(worldCoords, coordCount, *_skeleton, _startSlotIndex, _endSlotIndex);
|
||||||
|
const cocos2d::Rect bb = computeBoundingRect(worldCoords, coordCount / 2);
|
||||||
|
VLA_FREE(worldCoords);
|
||||||
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Convenience methods for Skeleton_* functions.
|
// --- Convenience methods for Skeleton_* functions.
|
||||||
@ -862,8 +866,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
cocos2d::Rect computeBoundingRect(const float* coords, int vertexCount)
|
cocos2d::Rect computeBoundingRect(const float* coords, int vertexCount) {
|
||||||
{
|
|
||||||
assert(coords);
|
assert(coords);
|
||||||
assert(vertexCount > 0);
|
assert(vertexCount > 0);
|
||||||
|
|
||||||
@ -872,8 +875,7 @@ namespace spine {
|
|||||||
float minY = v[1];
|
float minY = v[1];
|
||||||
float maxX = minX;
|
float maxX = minX;
|
||||||
float maxY = minY;
|
float maxY = minY;
|
||||||
for (int i = 1; i < vertexCount; ++i)
|
for (int i = 1; i < vertexCount; ++i) {
|
||||||
{
|
|
||||||
v += 2;
|
v += 2;
|
||||||
float x = v[0];
|
float x = v[0];
|
||||||
float y = v[1];
|
float y = v[1];
|
||||||
@ -885,37 +887,30 @@ namespace spine {
|
|||||||
return { minX, minY, maxX - minX, maxY - minY };
|
return { minX, minY, maxX - minX, maxY - minY };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool slotIsOutRange(Slot& slot, int startSlotIndex, int endSlotIndex)
|
bool slotIsOutRange(Slot& slot, int startSlotIndex, int endSlotIndex) {
|
||||||
{
|
|
||||||
const int index = slot.getData().getIndex();
|
const int index = slot.getData().getIndex();
|
||||||
return startSlotIndex > index || endSlotIndex < index;
|
return startSlotIndex > index || endSlotIndex < index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int computeTotalCoordCount(Skeleton& skeleton, int startSlotIndex, int endSlotIndex)
|
int computeTotalCoordCount(Skeleton& skeleton, int startSlotIndex, int endSlotIndex) {
|
||||||
{
|
|
||||||
int coordCount = 0;
|
int coordCount = 0;
|
||||||
for (size_t i = 0; i < skeleton.getSlots().size(); ++i)
|
for (size_t i = 0; i < skeleton.getSlots().size(); ++i) {
|
||||||
{
|
|
||||||
Slot& slot = *skeleton.getSlots()[i];
|
Slot& slot = *skeleton.getSlots()[i];
|
||||||
Attachment* const attachment = slot.getAttachment();
|
Attachment* const attachment = slot.getAttachment();
|
||||||
if (!attachment)
|
if (!attachment) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (slotIsOutRange(slot, startSlotIndex, endSlotIndex))
|
if (slotIsOutRange(slot, startSlotIndex, endSlotIndex)) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Early exit if slot is invisible
|
// Early exit if slot is invisible
|
||||||
if (slot.getColor().a == 0) {
|
if (slot.getColor().a == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (attachment->getRTTI().isExactly(RegionAttachment::rtti))
|
if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
|
||||||
{
|
|
||||||
coordCount += 8;
|
coordCount += 8;
|
||||||
}
|
}
|
||||||
else if (attachment->getRTTI().isExactly(MeshAttachment::rtti))
|
else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
|
||||||
{
|
|
||||||
MeshAttachment* const mesh = static_cast<MeshAttachment*>(attachment);
|
MeshAttachment* const mesh = static_cast<MeshAttachment*>(attachment);
|
||||||
coordCount += mesh->getWorldVerticesLength();
|
coordCount += mesh->getWorldVerticesLength();
|
||||||
}
|
}
|
||||||
@ -924,36 +919,29 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void transformWorldVertices(float* dstCoord, int coordCount, Skeleton& skeleton, int startSlotIndex, int endSlotIndex)
|
void transformWorldVertices(float* dstCoord, int coordCount, Skeleton& skeleton, int startSlotIndex, int endSlotIndex) {
|
||||||
{
|
|
||||||
float* dstPtr = dstCoord;
|
float* dstPtr = dstCoord;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
float* const dstEnd = dstCoord + coordCount;
|
float* const dstEnd = dstCoord + coordCount;
|
||||||
#endif
|
#endif
|
||||||
for (size_t i = 0; i < skeleton.getSlots().size(); ++i)
|
for (size_t i = 0; i < skeleton.getSlots().size(); ++i) {
|
||||||
{
|
|
||||||
/*const*/ Slot& slot = *skeleton.getDrawOrder()[i]; // match the draw order of SkeletonRenderer::Draw
|
/*const*/ Slot& slot = *skeleton.getDrawOrder()[i]; // match the draw order of SkeletonRenderer::Draw
|
||||||
Attachment* const attachment = slot.getAttachment();
|
Attachment* const attachment = slot.getAttachment();
|
||||||
if (!attachment)
|
if (!attachment) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (slotIsOutRange(slot, startSlotIndex, endSlotIndex))
|
if (slotIsOutRange(slot, startSlotIndex, endSlotIndex)) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (slot.getColor().a == 0) {
|
if (slot.getColor().a == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (attachment->getRTTI().isExactly(RegionAttachment::rtti))
|
if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
|
||||||
{
|
|
||||||
RegionAttachment* const regionAttachment = static_cast<RegionAttachment*>(attachment);
|
RegionAttachment* const regionAttachment = static_cast<RegionAttachment*>(attachment);
|
||||||
assert(dstPtr + 8 <= dstEnd);
|
assert(dstPtr + 8 <= dstEnd);
|
||||||
regionAttachment->computeWorldVertices(slot.getBone(), dstPtr, 0, 2);
|
regionAttachment->computeWorldVertices(slot.getBone(), dstPtr, 0, 2);
|
||||||
dstPtr += 8;
|
dstPtr += 8;
|
||||||
}
|
} else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
|
||||||
else if (attachment->getRTTI().isExactly(MeshAttachment::rtti))
|
|
||||||
{
|
|
||||||
MeshAttachment* const mesh = static_cast<MeshAttachment*>(attachment);
|
MeshAttachment* const mesh = static_cast<MeshAttachment*>(attachment);
|
||||||
assert(dstPtr + mesh->getWorldVerticesLength() <= dstEnd);
|
assert(dstPtr + mesh->getWorldVerticesLength() <= dstEnd);
|
||||||
mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), dstPtr, 0, 2);
|
mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), dstPtr, 0, 2);
|
||||||
@ -963,16 +951,11 @@ namespace spine {
|
|||||||
assert(dstPtr == dstEnd);
|
assert(dstPtr == dstEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interleaveCoordinates(float* dst, const float* src, int count, int dstStride)
|
void interleaveCoordinates(float* dst, const float* src, int count, int dstStride) {
|
||||||
{
|
if (dstStride == 2) {
|
||||||
if (dstStride == 2)
|
|
||||||
{
|
|
||||||
memcpy(dst, src, sizeof(float) * count * 2);
|
memcpy(dst, src, sizeof(float) * count * 2);
|
||||||
}
|
} else {
|
||||||
else
|
for (int i = 0; i < count; ++i) {
|
||||||
{
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
dst[0] = src[0];
|
dst[0] = src[0];
|
||||||
dst[1] = src[1];
|
dst[1] = src[1];
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
@ -982,8 +965,7 @@ namespace spine {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlendFunc makeBlendFunc(int blendMode, bool premultipliedAlpha)
|
BlendFunc makeBlendFunc(int blendMode, bool premultipliedAlpha) {
|
||||||
{
|
|
||||||
BlendFunc blendFunc;
|
BlendFunc blendFunc;
|
||||||
switch (blendMode) {
|
switch (blendMode) {
|
||||||
case BlendMode_Additive:
|
case BlendMode_Additive:
|
||||||
@ -1007,8 +989,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool cullRectangle(const Mat4& transform, const cocos2d::Rect& rect, const Camera& camera)
|
bool cullRectangle(const Mat4& transform, const cocos2d::Rect& rect, const Camera& camera) {
|
||||||
{
|
|
||||||
// Compute rectangle center and half extents in local space
|
// Compute rectangle center and half extents in local space
|
||||||
// TODO: Pass the bounding rectangle with this representation directly
|
// TODO: Pass the bounding rectangle with this representation directly
|
||||||
const float halfRectWidth = rect.size.width * 0.5f;
|
const float halfRectWidth = rect.size.width * 0.5f;
|
||||||
@ -1042,26 +1023,22 @@ namespace spine {
|
|||||||
// e.g. left culling <==> (c_cx + c_ex) / cw < -1 <==> (c_cx + c_ex) < -cw
|
// e.g. left culling <==> (c_cx + c_ex) / cw < -1 <==> (c_cx + c_ex) < -cw
|
||||||
|
|
||||||
// Left
|
// Left
|
||||||
if (c_cx + c_ex < -c_w)
|
if (c_cx + c_ex < -c_w) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right
|
// Right
|
||||||
if (c_cx - c_ex > c_w)
|
if (c_cx - c_ex > c_w) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bottom
|
// Bottom
|
||||||
if (c_cy + c_ey < -c_w)
|
if (c_cy + c_ey < -c_w) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Top
|
// Top
|
||||||
if (c_cy - c_ey > c_w)
|
if (c_cy - c_ey > c_w) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,8 +1046,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Color4B ColorToColor4B(const Color& color)
|
Color4B ColorToColor4B(const Color& color) {
|
||||||
{
|
|
||||||
return { (GLubyte)(color.r * 255.f), (GLubyte)(color.g * 255.f), (GLubyte)(color.b * 255.f), (GLubyte)(color.a * 255.f) };
|
return { (GLubyte)(color.r * 255.f), (GLubyte)(color.g * 255.f), (GLubyte)(color.b * 255.f), (GLubyte)(color.a * 255.f) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user