2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2008-2010 Ricardo Quesada
|
|
|
|
Copyright (c) 2010-2012 cocos2d-x.org
|
|
|
|
Copyright (c) 2011 Zynga Inc.
|
|
|
|
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
|
|
|
2022-10-01 16:24:52 +08:00
|
|
|
https://axmolengine.github.io/
|
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.
|
|
|
|
****************************************************************************/
|
2023-06-11 13:08:08 +08:00
|
|
|
#include "2d/LabelAtlas.h"
|
|
|
|
#include "renderer/TextureAtlas.h"
|
|
|
|
#include "platform/FileUtils.h"
|
|
|
|
#include "base/Director.h"
|
|
|
|
#include "base/UTF8.h"
|
|
|
|
#include "renderer/TextureCache.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
#if AX_LABELATLAS_DEBUG_DRAW
|
2023-06-11 13:08:08 +08:00
|
|
|
# include "renderer/Renderer.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
#endif
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_BEGIN
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// CCLabelAtlas - Creation & Init
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
LabelAtlas* LabelAtlas::create(std::string_view string,
|
|
|
|
std::string_view charMapFile,
|
2021-12-25 10:04:45 +08:00
|
|
|
int itemWidth,
|
|
|
|
int itemHeight,
|
|
|
|
int startCharMap)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-08 00:11:53 +08:00
|
|
|
LabelAtlas* ret = new LabelAtlas();
|
2021-12-25 10:04:45 +08:00
|
|
|
if (ret->initWithString(string, charMapFile, itemWidth, itemHeight, startCharMap))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool LabelAtlas::initWithString(std::string_view string,
|
|
|
|
std::string_view charMapFile,
|
2021-12-25 10:04:45 +08:00
|
|
|
int itemWidth,
|
|
|
|
int itemHeight,
|
|
|
|
int startCharMap)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
Texture2D* texture = _director->getTextureCache()->addImage(charMapFile);
|
2019-11-23 20:27:39 +08:00
|
|
|
return initWithString(string, texture, itemWidth, itemHeight, startCharMap);
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool LabelAtlas::initWithString(std::string_view string,
|
2021-12-25 10:04:45 +08:00
|
|
|
Texture2D* texture,
|
|
|
|
int itemWidth,
|
|
|
|
int itemHeight,
|
|
|
|
int startCharMap)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
if (AtlasNode::initWithTexture(texture, itemWidth, itemHeight, static_cast<int>(string.size())))
|
|
|
|
{
|
|
|
|
_mapStartChar = startCharMap;
|
|
|
|
this->setString(string);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
LabelAtlas* LabelAtlas::create(std::string_view string, std::string_view fntFile)
|
2021-12-25 10:04:45 +08:00
|
|
|
{
|
|
|
|
LabelAtlas* ret = new LabelAtlas();
|
2021-12-08 00:11:53 +08:00
|
|
|
|
|
|
|
if (ret->initWithString(string, fntFile))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
else
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
LabelAtlas* LabelAtlas::create(std::string_view string,
|
2021-12-25 10:04:45 +08:00
|
|
|
Texture2D* texture,
|
|
|
|
int itemWidth,
|
|
|
|
int itemHeight,
|
|
|
|
int startCharMap)
|
2020-09-09 15:29:56 +08:00
|
|
|
{
|
2021-12-08 00:11:53 +08:00
|
|
|
LabelAtlas* ret = new LabelAtlas();
|
|
|
|
|
|
|
|
if (ret->initWithString(string, texture, itemWidth, itemHeight, startCharMap))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
|
|
|
else
|
2020-09-09 15:29:56 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2020-09-09 15:29:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool LabelAtlas::initWithString(std::string_view theString, std::string_view fntFile)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
std::string pathStr = FileUtils::getInstance()->fullPathForFilename(fntFile);
|
|
|
|
std::string relPathStr = pathStr.substr(0, pathStr.find_last_of('/')) + "/";
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(pathStr);
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(dict["version"].asInt() == 1, "Unsupported version. Upgrade cocos2d version");
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
std::string textureFilename = relPathStr + dict["textureFilename"].asString();
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
unsigned int width = static_cast<unsigned int>(dict["itemWidth"].asInt() / AX_CONTENT_SCALE_FACTOR());
|
|
|
|
unsigned int height = static_cast<unsigned int>(dict["itemHeight"].asInt() / AX_CONTENT_SCALE_FACTOR());
|
2020-08-18 11:33:18 +08:00
|
|
|
unsigned int startChar = dict["firstChar"].asInt();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
this->initWithString(theString, textureFilename, width, height, startChar);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// CCLabelAtlas - Atlas generation
|
2019-11-23 20:27:39 +08:00
|
|
|
void LabelAtlas::updateAtlasValues()
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_itemsPerRow == 0)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t n = _string.length();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
const unsigned char* s = (unsigned char*)_string.c_str();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Texture2D* texture = _textureAtlas->getTexture();
|
|
|
|
float textureWide = (float)texture->getPixelsWide();
|
|
|
|
float textureHigh = (float)texture->getPixelsHigh();
|
2022-07-16 10:43:05 +08:00
|
|
|
float itemWidthInPixels = _itemWidth * AX_CONTENT_SCALE_FACTOR();
|
|
|
|
float itemHeightInPixels = _itemHeight * AX_CONTENT_SCALE_FACTOR();
|
2019-11-23 20:27:39 +08:00
|
|
|
if (_ignoreContentScaleFactor)
|
|
|
|
{
|
2021-12-31 12:12:40 +08:00
|
|
|
itemWidthInPixels = static_cast<float>(_itemWidth);
|
|
|
|
itemHeightInPixels = static_cast<float>(_itemHeight);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(n <= _textureAtlas->getCapacity(), "updateAtlasValues: Invalid String length");
|
2019-11-23 20:27:39 +08:00
|
|
|
V3F_C4B_T2F_Quad* quads = _textureAtlas->getQuads();
|
2021-12-25 10:04:45 +08:00
|
|
|
for (ssize_t i = 0; i < n; i++)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
unsigned char a = s[i] - _mapStartChar;
|
2021-12-25 10:04:45 +08:00
|
|
|
float row = (float)(a % _itemsPerRow);
|
|
|
|
float col = (float)(a / _itemsPerRow);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
#if AX_FIX_ARTIFACTS_BY_STRECHING_TEXEL
|
2019-11-23 20:27:39 +08:00
|
|
|
// Issue #938. Don't use texStepX & texStepY
|
2021-12-25 10:04:45 +08:00
|
|
|
float left = (2 * row * itemWidthInPixels + 1) / (2 * textureWide);
|
|
|
|
float right = left + (itemWidthInPixels * 2 - 2) / (2 * textureWide);
|
|
|
|
float top = (2 * col * itemHeightInPixels + 1) / (2 * textureHigh);
|
|
|
|
float bottom = top + (itemHeightInPixels * 2 - 2) / (2 * textureHigh);
|
2019-11-23 20:27:39 +08:00
|
|
|
#else
|
2021-12-25 10:04:45 +08:00
|
|
|
float left = row * itemWidthInPixels / textureWide;
|
|
|
|
float right = left + itemWidthInPixels / textureWide;
|
|
|
|
float top = col * itemHeightInPixels / textureHigh;
|
|
|
|
float bottom = top + itemHeightInPixels / textureHigh;
|
2022-07-16 10:43:05 +08:00
|
|
|
#endif // ! AX_FIX_ARTIFACTS_BY_STRECHING_TEXEL
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
quads[i].tl.texCoords.u = left;
|
|
|
|
quads[i].tl.texCoords.v = top;
|
|
|
|
quads[i].tr.texCoords.u = right;
|
|
|
|
quads[i].tr.texCoords.v = top;
|
|
|
|
quads[i].bl.texCoords.u = left;
|
|
|
|
quads[i].bl.texCoords.v = bottom;
|
|
|
|
quads[i].br.texCoords.u = right;
|
|
|
|
quads[i].br.texCoords.v = bottom;
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
quads[i].bl.vertices.x = (float)(i * _itemWidth);
|
2019-11-23 20:27:39 +08:00
|
|
|
quads[i].bl.vertices.y = 0;
|
|
|
|
quads[i].bl.vertices.z = 0.0f;
|
|
|
|
quads[i].br.vertices.x = (float)(i * _itemWidth + _itemWidth);
|
|
|
|
quads[i].br.vertices.y = 0;
|
|
|
|
quads[i].br.vertices.z = 0.0f;
|
|
|
|
quads[i].tl.vertices.x = (float)(i * _itemWidth);
|
|
|
|
quads[i].tl.vertices.y = (float)(_itemHeight);
|
|
|
|
quads[i].tl.vertices.z = 0.0f;
|
|
|
|
quads[i].tr.vertices.x = (float)(i * _itemWidth + _itemWidth);
|
|
|
|
quads[i].tr.vertices.y = (float)(_itemHeight);
|
|
|
|
quads[i].tr.vertices.z = 0.0f;
|
|
|
|
Color4B c(_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity);
|
|
|
|
quads[i].tl.colors = c;
|
|
|
|
quads[i].tr.colors = c;
|
|
|
|
quads[i].bl.colors = c;
|
|
|
|
quads[i].br.colors = c;
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
if (n > 0)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
_textureAtlas->setDirty(true);
|
|
|
|
ssize_t totalQuads = _textureAtlas->getTotalQuads();
|
2021-12-25 10:04:45 +08:00
|
|
|
if (n > totalQuads)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
_textureAtlas->increaseTotalQuadsWith(static_cast<int>(n - totalQuads));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// CCLabelAtlas - LabelProtocol
|
2021-12-01 03:35:34 +08:00
|
|
|
void LabelAtlas::setString(std::string_view label)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
ssize_t len = label.size();
|
|
|
|
if (len > _textureAtlas->getTotalQuads())
|
|
|
|
{
|
|
|
|
_textureAtlas->resizeCapacity(len);
|
|
|
|
}
|
|
|
|
_string.clear();
|
|
|
|
_string = label;
|
|
|
|
this->updateAtlasValues();
|
|
|
|
|
2021-10-23 23:27:14 +08:00
|
|
|
Vec2 s = Vec2(len * _itemWidth, _itemHeight);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
this->setContentSize(s);
|
|
|
|
|
|
|
|
_quadsToDraw = len;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
std::string_view LabelAtlas::getString() const
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
return _string;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LabelAtlas::updateColor()
|
|
|
|
{
|
|
|
|
if (_textureAtlas)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
Color4B color4(_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity);
|
2019-11-23 20:27:39 +08:00
|
|
|
if (_isOpacityModifyRGB)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
color4.r *= _displayedOpacity / 255.0f;
|
|
|
|
color4.g *= _displayedOpacity / 255.0f;
|
|
|
|
color4.b *= _displayedOpacity / 255.0f;
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
auto quads = _textureAtlas->getQuads();
|
2019-11-23 20:27:39 +08:00
|
|
|
ssize_t length = _string.length();
|
|
|
|
for (int index = 0; index < length; index++)
|
|
|
|
{
|
|
|
|
quads[index].bl.colors = color4;
|
|
|
|
quads[index].br.colors = color4;
|
|
|
|
quads[index].tl.colors = color4;
|
|
|
|
quads[index].tr.colors = color4;
|
|
|
|
_textureAtlas->updateQuad(&quads[index], index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// CCLabelAtlas - draw
|
2022-07-16 10:43:05 +08:00
|
|
|
#if AX_LABELATLAS_DEBUG_DRAW
|
2021-12-25 10:04:45 +08:00
|
|
|
void LabelAtlas::draw(Renderer* renderer, const Mat4& transform, uint32_t flags)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
AtlasNode::draw(renderer, transform, _transformUpdated);
|
|
|
|
|
|
|
|
_debugDrawNode->clear();
|
2021-12-25 10:04:45 +08:00
|
|
|
auto size = getContentSize();
|
|
|
|
Vec2 vertices[4] = {Vec2::ZERO, Vec2(size.width, 0), Vec2(size.width, size.height), Vec2(0.0f, size.height)};
|
2019-11-23 20:27:39 +08:00
|
|
|
_debugDrawNode->drawPoly(vertices, 4, true, Color4F(1.0, 1.0, 1.0, 1.0));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
std::string LabelAtlas::getDescription() const
|
|
|
|
{
|
|
|
|
return StringUtils::format("<LabelAtlas | Tag = %d, Label = '%s'>", _tag, _string.c_str());
|
|
|
|
}
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_END
|