2013-07-23 02:17:51 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2013 Zynga Inc.
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
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 "CCLabel.h"
|
|
|
|
#include "CCFontDefinition.h"
|
2013-07-25 01:22:46 +08:00
|
|
|
#include "CCFontAtlasCache.h"
|
2013-08-08 07:36:04 +08:00
|
|
|
#include "CCLabelTextFormatter.h"
|
2013-07-23 02:17:51 +08:00
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
#define DISTANCEFIELD_ATLAS_FONTSIZE 50
|
|
|
|
|
2013-07-23 02:17:51 +08:00
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
Label* Label::createWithTTF(const std::string& label, const std::string& fontFilePath, int fontSize, int lineSize, TextHAlignment alignment, GlyphCollection glyphs, const char *customGlyphs, bool useDistanceField)
|
2013-07-23 02:17:51 +08:00
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
FontAtlas *tmpAtlas = nullptr;
|
|
|
|
if(useDistanceField)
|
|
|
|
tmpAtlas = FontAtlasCache::getFontAtlasTTF(fontFilePath.c_str(), DISTANCEFIELD_ATLAS_FONTSIZE, glyphs, customGlyphs,true);
|
|
|
|
else
|
|
|
|
tmpAtlas = FontAtlasCache::getFontAtlasTTF(fontFilePath.c_str(), fontSize, glyphs, customGlyphs,false);
|
2013-08-14 02:28:54 +08:00
|
|
|
|
2013-08-22 11:12:09 +08:00
|
|
|
if (!tmpAtlas)
|
2013-07-25 08:21:51 +08:00
|
|
|
return nullptr;
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-07-25 01:22:46 +08:00
|
|
|
// create the actual label
|
2013-12-13 12:42:15 +08:00
|
|
|
Label* templabel = Label::createWithAtlas(tmpAtlas, alignment, lineSize, useDistanceField,true);
|
2013-07-23 04:08:37 +08:00
|
|
|
|
2013-07-25 01:22:46 +08:00
|
|
|
if (templabel)
|
2013-07-23 05:43:45 +08:00
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
if(useDistanceField)
|
|
|
|
templabel->setFontSize(fontSize);
|
2013-08-13 06:41:29 +08:00
|
|
|
templabel->setText(label, lineSize, alignment, false);
|
2013-07-23 05:43:45 +08:00
|
|
|
return templabel;
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-07-25 08:21:51 +08:00
|
|
|
return nullptr;
|
2013-07-23 02:17:51 +08:00
|
|
|
}
|
|
|
|
|
2013-11-06 11:02:03 +08:00
|
|
|
Label* Label::createWithBMFont(const std::string& label, const std::string& bmfontFilePath, TextHAlignment alignment, int lineSize)
|
2013-07-23 02:17:51 +08:00
|
|
|
{
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-11-06 11:02:03 +08:00
|
|
|
FontAtlas *tmpAtlas = FontAtlasCache::getFontAtlasFNT(bmfontFilePath.c_str());
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-08-22 11:12:09 +08:00
|
|
|
if (!tmpAtlas)
|
2013-07-26 08:58:13 +08:00
|
|
|
return 0;
|
|
|
|
|
2013-08-22 11:12:09 +08:00
|
|
|
Label* templabel = Label::createWithAtlas(tmpAtlas, alignment, lineSize);
|
2013-07-25 01:22:46 +08:00
|
|
|
|
2013-07-26 08:58:13 +08:00
|
|
|
if (templabel)
|
|
|
|
{
|
2013-08-13 06:09:28 +08:00
|
|
|
templabel->setText(label, lineSize, alignment, false);
|
2013-07-26 08:58:13 +08:00
|
|
|
return templabel;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
|
|
|
|
return 0;
|
2013-07-23 02:17:51 +08:00
|
|
|
}
|
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
Label* Label::createWithAtlas(FontAtlas *atlas, TextHAlignment alignment, int lineSize, bool useDistanceField,bool useA8Shader)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
Label *ret = new Label(atlas, alignment, useDistanceField,useA8Shader);
|
2013-08-08 07:36:04 +08:00
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if( ret->init() )
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete ret;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
Label::Label(FontAtlas *atlas, TextHAlignment alignment, bool useDistanceField,bool useA8Shader)
|
2013-11-13 11:22:34 +08:00
|
|
|
: _reusedLetter(nullptr)
|
2013-08-22 11:12:09 +08:00
|
|
|
, _lineBreakWithoutSpaces(false)
|
2013-12-13 12:42:15 +08:00
|
|
|
,_multilineEnable(true)
|
2013-11-13 11:22:34 +08:00
|
|
|
, _alignment(alignment)
|
|
|
|
, _currentUTF16String(0)
|
|
|
|
, _originalUTF16String(0)
|
2013-08-22 11:12:09 +08:00
|
|
|
, _advances(0)
|
2013-11-13 11:22:34 +08:00
|
|
|
, _fontAtlas(atlas)
|
2013-10-29 20:25:03 +08:00
|
|
|
, _isOpacityModifyRGB(true)
|
2013-12-13 12:42:15 +08:00
|
|
|
,_useDistanceField(useDistanceField)
|
|
|
|
,_useA8Shader(useA8Shader)
|
2013-07-23 02:17:51 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Label::~Label()
|
2013-10-29 20:25:03 +08:00
|
|
|
{
|
2013-10-31 17:52:22 +08:00
|
|
|
delete [] _currentUTF16String;
|
|
|
|
delete [] _originalUTF16String;
|
|
|
|
delete [] _advances;
|
2013-08-08 07:36:04 +08:00
|
|
|
|
|
|
|
if (_fontAtlas)
|
|
|
|
FontAtlasCache::releaseFontAtlas(_fontAtlas);
|
2013-10-29 20:25:03 +08:00
|
|
|
|
2013-11-14 07:55:36 +08:00
|
|
|
_reusedLetter->release();
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Label::init()
|
2013-10-29 20:25:03 +08:00
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
bool ret = true;
|
2013-10-29 20:25:03 +08:00
|
|
|
if(_fontAtlas)
|
|
|
|
{
|
2013-11-14 07:55:36 +08:00
|
|
|
_reusedLetter = Sprite::createWithTexture(&_fontAtlas->getTexture(0));
|
2013-10-29 20:25:03 +08:00
|
|
|
_reusedLetter->setOpacityModifyRGB(_isOpacityModifyRGB);
|
2013-12-13 12:42:15 +08:00
|
|
|
ret = SpriteBatchNode::initWithTexture(&_fontAtlas->getTexture(0), 30);
|
2013-11-14 07:55:36 +08:00
|
|
|
_reusedLetter->retain();
|
2013-10-29 20:25:03 +08:00
|
|
|
}
|
2013-12-13 12:42:15 +08:00
|
|
|
if (_useDistanceField)
|
|
|
|
setLabelEffect(LabelEffect::NORMAL,Color3B::BLACK);
|
|
|
|
else if(_useA8Shader)
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_A8_COLOR));
|
2013-08-22 11:12:09 +08:00
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
return ret;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-11-06 11:02:03 +08:00
|
|
|
void Label::setString(const std::string &stringToRender)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
_multilineEnable = true;
|
|
|
|
setText(stringToRender, _width, TextHAlignment::CENTER, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setString(const std::string &stringToRender,bool multilineEnable)
|
|
|
|
{
|
|
|
|
_multilineEnable = multilineEnable;
|
2013-08-13 04:29:54 +08:00
|
|
|
setText(stringToRender, _width, TextHAlignment::CENTER, false);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-11-06 11:02:03 +08:00
|
|
|
bool Label::setText(const std::string& stringToRender, float lineWidth, TextHAlignment alignment, bool lineBreakWithoutSpaces)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
if (!_fontAtlas)
|
|
|
|
return false;
|
|
|
|
|
2013-08-13 04:29:54 +08:00
|
|
|
// carloX
|
|
|
|
// reset the string
|
|
|
|
resetCurrentString();
|
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
_width = lineWidth;
|
|
|
|
_alignment = alignment;
|
|
|
|
_lineBreakWithoutSpaces = lineBreakWithoutSpaces;
|
|
|
|
|
|
|
|
// store locally common line height
|
|
|
|
_commonLineHeight = _fontAtlas->getCommonLineHeight();
|
|
|
|
if (_commonLineHeight <= 0)
|
|
|
|
return false;
|
|
|
|
|
2013-11-05 08:31:36 +08:00
|
|
|
// int numLetter = 0;
|
2013-11-06 11:02:03 +08:00
|
|
|
unsigned short* utf16String = cc_utf8_to_utf16(stringToRender.c_str());
|
2013-08-08 07:36:04 +08:00
|
|
|
if(!utf16String)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_cascadeColorEnabled = true;
|
|
|
|
|
|
|
|
setCurrentString(utf16String);
|
|
|
|
setOriginalString(utf16String);
|
|
|
|
|
|
|
|
// align text
|
|
|
|
alignText();
|
|
|
|
|
|
|
|
// done here
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setAlignment(TextHAlignment alignment)
|
|
|
|
{
|
|
|
|
// store the new alignment
|
|
|
|
if (alignment != _alignment)
|
|
|
|
{
|
|
|
|
// store
|
|
|
|
_alignment = alignment;
|
|
|
|
|
|
|
|
// reset the string
|
|
|
|
resetCurrentString();
|
|
|
|
|
|
|
|
// need to align text again
|
|
|
|
alignText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setWidth(float width)
|
|
|
|
{
|
|
|
|
if (width != _width)
|
|
|
|
{
|
|
|
|
// store
|
|
|
|
_width = width;
|
|
|
|
|
2013-08-13 04:29:54 +08:00
|
|
|
|
|
|
|
// reset the string
|
|
|
|
resetCurrentString();
|
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
// need to align text again
|
|
|
|
alignText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setLineBreakWithoutSpace(bool breakWithoutSpace)
|
|
|
|
{
|
|
|
|
if (breakWithoutSpace != _lineBreakWithoutSpaces)
|
|
|
|
{
|
|
|
|
// store
|
|
|
|
_lineBreakWithoutSpaces = breakWithoutSpace;
|
|
|
|
|
|
|
|
// need to align text again
|
|
|
|
alignText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setScale(float scale)
|
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
if (_useDistanceField)
|
|
|
|
{
|
|
|
|
scale *= 1.0f * _fontSize / DISTANCEFIELD_ATLAS_FONTSIZE;
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
Node::setScale(scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setScaleX(float scaleX)
|
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
if (_useDistanceField)
|
|
|
|
{
|
|
|
|
scaleX *= 1.0f * _fontSize / DISTANCEFIELD_ATLAS_FONTSIZE;
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
Node::setScaleX(scaleX);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setScaleY(float scaleY)
|
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
if (_useDistanceField)
|
|
|
|
{
|
|
|
|
scaleY *= 1.0f * _fontSize / DISTANCEFIELD_ATLAS_FONTSIZE;
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
Node::setScaleY(scaleY);
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
float Label::getScaleY() const
|
|
|
|
{
|
|
|
|
if (_useDistanceField)
|
|
|
|
{
|
|
|
|
return _scaleY / (1.0f * _fontSize / DISTANCEFIELD_ATLAS_FONTSIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _scaleY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float Label::getScaleX() const
|
|
|
|
{
|
|
|
|
if (_useDistanceField)
|
|
|
|
{
|
|
|
|
return _scaleX / (1.0f * _fontSize / DISTANCEFIELD_ATLAS_FONTSIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _scaleX;
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Label::alignText()
|
2013-10-29 20:25:03 +08:00
|
|
|
{
|
|
|
|
if(_textureAtlas)
|
|
|
|
_textureAtlas->removeAllQuads();
|
|
|
|
_fontAtlas->prepareLetterDefinitions(_currentUTF16String);
|
|
|
|
LabelTextFormatter::createStringSprites(this);
|
2013-12-13 12:42:15 +08:00
|
|
|
if(_multilineEnable && LabelTextFormatter::multilineText(this) )
|
2013-08-08 07:36:04 +08:00
|
|
|
LabelTextFormatter::createStringSprites(this);
|
|
|
|
|
|
|
|
LabelTextFormatter::alignText(this);
|
2013-10-29 20:25:03 +08:00
|
|
|
|
2013-11-28 16:02:03 +08:00
|
|
|
int strLen = cc_wcslen(_currentUTF16String);
|
2013-12-19 10:33:04 +08:00
|
|
|
for(const auto &child : _children) {
|
|
|
|
int tag = child->getTag();
|
|
|
|
if(tag < 0 || tag >= strLen)
|
|
|
|
SpriteBatchNode::removeChild(child, true);
|
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
_reusedLetter->setBatchNode(nullptr);
|
|
|
|
|
|
|
|
int vaildIndex = 0;
|
|
|
|
Sprite* child = nullptr;
|
|
|
|
Rect uvRect;
|
|
|
|
for (int ctr = 0; ctr < strLen; ++ctr)
|
|
|
|
{
|
|
|
|
if (_lettersInfo[ctr].def.validDefinition)
|
|
|
|
{
|
2013-10-31 17:52:22 +08:00
|
|
|
child = static_cast<Sprite*>( this->getChildByTag(ctr) );
|
2013-10-29 20:25:03 +08:00
|
|
|
if (child)
|
|
|
|
{
|
|
|
|
uvRect.size.height = _lettersInfo[ctr].def.height;
|
|
|
|
uvRect.size.width = _lettersInfo[ctr].def.width;
|
|
|
|
uvRect.origin.x = _lettersInfo[ctr].def.U;
|
|
|
|
uvRect.origin.y = _lettersInfo[ctr].def.V;
|
|
|
|
|
|
|
|
child->setTexture(&_fontAtlas->getTexture(_lettersInfo[ctr].def.textureID));
|
|
|
|
child->setTextureRect(uvRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateSpriteWithLetterDefinition(_reusedLetter,_lettersInfo[ctr].def,&_fontAtlas->getTexture(_lettersInfo[ctr].def.textureID));
|
|
|
|
_reusedLetter->setPosition(_lettersInfo[ctr].position);
|
|
|
|
insertQuadFromSprite(_reusedLetter,vaildIndex++);
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
2013-07-23 02:17:51 +08:00
|
|
|
}
|
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
bool Label::computeAdvancesForString(unsigned short int *stringToRender)
|
|
|
|
{
|
|
|
|
if (_advances)
|
|
|
|
{
|
|
|
|
delete [] _advances;
|
|
|
|
_advances = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int letterCount = 0;
|
2013-10-31 17:52:22 +08:00
|
|
|
_advances = _fontAtlas->getFont()->getAdvancesForTextUTF16(stringToRender, letterCount);
|
2013-08-08 07:36:04 +08:00
|
|
|
|
|
|
|
if(!_advances)
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Label::setOriginalString(unsigned short *stringToSet)
|
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
if (_originalUTF16String)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
delete [] _originalUTF16String;
|
|
|
|
_originalUTF16String = 0;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int newStringLenght = cc_wcslen(stringToSet);
|
2013-10-29 20:25:03 +08:00
|
|
|
_originalUTF16String = new unsigned short int [newStringLenght + 1];
|
|
|
|
memset(_originalUTF16String, 0, (newStringLenght + 1) * 2);
|
|
|
|
memcpy(_originalUTF16String, stringToSet, (newStringLenght * 2));
|
|
|
|
_originalUTF16String[newStringLenght] = 0;
|
2013-08-08 07:36:04 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Label::setCurrentString(unsigned short *stringToSet)
|
|
|
|
{
|
|
|
|
// set the new string
|
2013-10-29 20:25:03 +08:00
|
|
|
if (_currentUTF16String)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
delete [] _currentUTF16String;
|
|
|
|
_currentUTF16String = 0;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
//
|
2013-10-29 20:25:03 +08:00
|
|
|
_currentUTF16String = stringToSet;
|
2013-08-08 07:36:04 +08:00
|
|
|
// compute the advances
|
|
|
|
return computeAdvancesForString(stringToSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::resetCurrentString()
|
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
if ((!_currentUTF16String) && (!_originalUTF16String))
|
2013-08-13 04:29:54 +08:00
|
|
|
return;
|
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
// set the new string
|
2013-10-29 20:25:03 +08:00
|
|
|
if (_currentUTF16String)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
delete [] _currentUTF16String;
|
|
|
|
_currentUTF16String = 0;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
int stringLenght = cc_wcslen(_originalUTF16String);
|
|
|
|
_currentUTF16String = new unsigned short int [stringLenght + 1];
|
|
|
|
memcpy(_currentUTF16String, _originalUTF16String, stringLenght * 2);
|
|
|
|
_currentUTF16String[stringLenght] = 0;
|
2013-08-13 04:29:54 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
Sprite * Label::updateSpriteWithLetterDefinition(Sprite *spriteToUpdate, const FontLetterDefinition &theDefinition, Texture2D *theTexture)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
if (!spriteToUpdate)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Rect uvRect;
|
|
|
|
uvRect.size.height = theDefinition.height;
|
|
|
|
uvRect.size.width = theDefinition.width;
|
|
|
|
uvRect.origin.x = theDefinition.U;
|
|
|
|
uvRect.origin.y = theDefinition.V;
|
|
|
|
|
|
|
|
SpriteFrame *frame = SpriteFrame::createWithTexture(theTexture, uvRect);
|
|
|
|
if (frame)
|
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
spriteToUpdate->setBatchNode(this);
|
2013-08-08 07:36:04 +08:00
|
|
|
spriteToUpdate->setTexture(theTexture);
|
2013-12-04 10:33:27 +08:00
|
|
|
spriteToUpdate->setSpriteFrame(frame);
|
2013-10-29 20:25:03 +08:00
|
|
|
spriteToUpdate->setAnchorPoint(Point(theDefinition.anchorX, theDefinition.anchorY));
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
|
|
|
|
return spriteToUpdate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
bool Label::recordLetterInfo(const cocos2d::Point& point,unsigned short int theChar, int spriteIndex)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-11-13 11:22:34 +08:00
|
|
|
if (static_cast<std::size_t>(spriteIndex) >= _lettersInfo.size())
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
LetterInfo tmpInfo;
|
|
|
|
_lettersInfo.push_back(tmpInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
_fontAtlas->getLetterDefinitionForChar(theChar, _lettersInfo[spriteIndex].def);
|
|
|
|
_lettersInfo[spriteIndex].position = point;
|
|
|
|
_lettersInfo[spriteIndex].contentSize.width = _lettersInfo[spriteIndex].def.width;
|
|
|
|
_lettersInfo[spriteIndex].contentSize.height = _lettersInfo[spriteIndex].def.height;
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
return _lettersInfo[spriteIndex].def.validDefinition;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
bool Label::recordPlaceholderInfo(int spriteIndex)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-11-13 11:22:34 +08:00
|
|
|
if (static_cast<std::size_t>(spriteIndex) >= _lettersInfo.size())
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
LetterInfo tmpInfo;
|
|
|
|
_lettersInfo.push_back(tmpInfo);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
2013-10-29 20:25:03 +08:00
|
|
|
|
|
|
|
_lettersInfo[spriteIndex].def.validDefinition = false;
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
return false;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
void Label::addChild(Node * child, int zOrder/* =0 */, int tag/* =0 */)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
CCASSERT(0, "addChild: is not supported on Label.");
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
void Label::setLabelEffect(LabelEffect effect,const Color3B& effectColor)
|
|
|
|
{
|
|
|
|
if(_useDistanceField == false)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_currLabelEffect = effect;
|
|
|
|
_effectColor = effectColor;
|
|
|
|
|
|
|
|
switch (_currLabelEffect)
|
|
|
|
{
|
|
|
|
case cocos2d::LabelEffect::NORMAL:
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL));
|
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::OUTLINE:
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE));
|
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::SHADOW:
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_SHADOW));
|
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::GLOW:
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_GLOW));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_uniformEffectColor = glGetUniformLocation(_shaderProgram->getProgram(), "v_effectColor");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setFontSize(int fontSize)
|
|
|
|
{
|
|
|
|
_fontSize = fontSize;
|
|
|
|
Node::setScale(1.0f*_fontSize/DISTANCEFIELD_ATLAS_FONTSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::draw()
|
|
|
|
{
|
|
|
|
CC_PROFILER_START("CCSpriteBatchNode - draw");
|
|
|
|
|
|
|
|
// Optimization: Fast Dispatch
|
|
|
|
if( _textureAtlas->getTotalQuads() == 0 )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_NODE_DRAW_SETUP();
|
|
|
|
|
|
|
|
if (_useDistanceField && _currLabelEffect != LabelEffect::NORMAL)
|
|
|
|
{
|
|
|
|
_shaderProgram->setUniformLocationWith3f(_uniformEffectColor, _effectColor.r/255.0f,_effectColor.g/255.0f,_effectColor.b/255.0f);
|
|
|
|
}
|
|
|
|
|
2013-12-19 10:33:04 +08:00
|
|
|
for(const auto &child: _children)
|
2013-12-13 12:42:15 +08:00
|
|
|
child->updateTransform();
|
|
|
|
|
|
|
|
GL::blendFunc( _blendFunc.src, _blendFunc.dst );
|
|
|
|
|
|
|
|
_textureAtlas->drawQuads();
|
|
|
|
|
|
|
|
CC_PROFILER_STOP("CCSpriteBatchNode - draw");
|
|
|
|
}
|
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
///// PROTOCOL STUFF
|
|
|
|
|
2013-10-31 20:17:30 +08:00
|
|
|
Sprite * Label::getLetter(int ID)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
if (ID < getStringLenght())
|
|
|
|
{
|
|
|
|
if(_lettersInfo[ID].def.validDefinition == false)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
Sprite* sp = static_cast<Sprite*>(this->getChildByTag(ID));
|
|
|
|
|
|
|
|
if (!sp)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
Rect uvRect;
|
|
|
|
uvRect.size.height = _lettersInfo[ID].def.height;
|
|
|
|
uvRect.size.width = _lettersInfo[ID].def.width;
|
|
|
|
uvRect.origin.x = _lettersInfo[ID].def.U;
|
|
|
|
uvRect.origin.y = _lettersInfo[ID].def.V;
|
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
sp = Sprite::createWithTexture(&_fontAtlas->getTexture(_lettersInfo[ID].def.textureID),uvRect);
|
2013-10-29 20:25:03 +08:00
|
|
|
sp->setBatchNode(this);
|
|
|
|
sp->setAnchorPoint(Point(_lettersInfo[ID].def.anchorX, _lettersInfo[ID].def.anchorY));
|
|
|
|
sp->setPosition(_lettersInfo[ID].position);
|
|
|
|
sp->setOpacity(_realOpacity);
|
|
|
|
|
|
|
|
this->addSpriteWithoutQuad(sp, ID, ID);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
2013-10-29 20:25:03 +08:00
|
|
|
return sp;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
return nullptr;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
float Label::getLetterPosXLeft( int index ) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
return _lettersInfo[index].position.x * _scaleX - (_lettersInfo[index].contentSize.width * _scaleX * _lettersInfo[index].def.anchorX);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
float Label::getLetterPosXRight( int index ) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
return _lettersInfo[index].position.x * _scaleX + (_lettersInfo[index].contentSize.width * _scaleX * _lettersInfo[index].def.anchorX);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getCommonLineHeight() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
return _commonLineHeight;
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getKerningForCharsPair(unsigned short first, unsigned short second) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getXOffsetForChar(unsigned short c) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
FontLetterDefinition tempDefinition;
|
|
|
|
bool validDefinition = _fontAtlas->getLetterDefinitionForChar(c, tempDefinition);
|
|
|
|
if (!validDefinition)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return (tempDefinition.offsetX);
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getYOffsetForChar(unsigned short c) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
FontLetterDefinition tempDefinition;
|
|
|
|
bool validDefinition = _fontAtlas->getLetterDefinitionForChar(c, tempDefinition);
|
|
|
|
if (!validDefinition)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return (tempDefinition.offsetY);
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getAdvanceForChar(unsigned short c, int hintPositionInString) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
if (_advances)
|
|
|
|
{
|
|
|
|
// not that advance contains the X offset already
|
|
|
|
FontLetterDefinition tempDefinition;
|
|
|
|
bool validDefinition = _fontAtlas->getLetterDefinitionForChar(c, tempDefinition);
|
|
|
|
if (!validDefinition)
|
|
|
|
return -1;
|
|
|
|
|
2013-08-13 04:29:54 +08:00
|
|
|
return (_advances[hintPositionInString].width);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
Rect Label::getRectForChar(unsigned short c) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-31 17:52:22 +08:00
|
|
|
return _fontAtlas->getFont()->getRectForChar(c);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// string related stuff
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getStringNumLines() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
int quantityOfLines = 1;
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
unsigned int stringLen = _currentUTF16String ? cc_wcslen(_currentUTF16String) : 0;
|
2013-08-08 07:36:04 +08:00
|
|
|
if (stringLen == 0)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
// count number of lines
|
|
|
|
for (unsigned int i = 0; i < stringLen - 1; ++i)
|
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
unsigned short c = _currentUTF16String[i];
|
2013-08-08 07:36:04 +08:00
|
|
|
if (c == '\n')
|
|
|
|
{
|
|
|
|
quantityOfLines++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return quantityOfLines;
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getStringLenght() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
return _currentUTF16String ? cc_wcslen(_currentUTF16String) : 0;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
unsigned short Label::getCharAtStringPosition(int position) const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
return _currentUTF16String[position];
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
unsigned short * Label::getUTF8String() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
return _currentUTF16String;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Label::assignNewUTF8String(unsigned short *newString)
|
|
|
|
{
|
|
|
|
setCurrentString(newString);
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
TextHAlignment Label::getTextAlignment() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
return _alignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
// label related stuff
|
2013-09-13 11:46:46 +08:00
|
|
|
float Label::getMaxLineWidth() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
return _width;
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
bool Label::breakLineWithoutSpace() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
return _lineBreakWithoutSpaces;
|
|
|
|
}
|
|
|
|
|
2013-09-13 11:46:46 +08:00
|
|
|
Size Label::getLabelContentSize() const
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
return getContentSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setLabelContentSize(const Size &newSize)
|
|
|
|
{
|
|
|
|
setContentSize(newSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RGBA protocol
|
|
|
|
|
|
|
|
|
|
|
|
bool Label::isOpacityModifyRGB() const
|
|
|
|
{
|
2013-08-13 04:29:54 +08:00
|
|
|
return _isOpacityModifyRGB;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setOpacityModifyRGB(bool isOpacityModifyRGB)
|
|
|
|
{
|
2013-08-13 04:29:54 +08:00
|
|
|
_isOpacityModifyRGB = isOpacityModifyRGB;
|
2013-11-28 16:02:03 +08:00
|
|
|
|
2013-12-19 10:33:04 +08:00
|
|
|
for(const auto& child: _children) {
|
2013-12-19 17:05:59 +08:00
|
|
|
child->setOpacityModifyRGB(_isOpacityModifyRGB);
|
2013-12-19 10:33:04 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
_reusedLetter->setOpacityModifyRGB(true);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setColor(const Color3B& color)
|
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
_reusedLetter->setColor(color);
|
2013-12-06 18:07:16 +08:00
|
|
|
SpriteBatchNode::setColor(color);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-12-11 16:38:47 +08:00
|
|
|
void Label::updateColor()
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-12-11 16:38:47 +08:00
|
|
|
V3F_C4B_T2F_Quad *quads = _textureAtlas->getQuads();
|
|
|
|
auto count = _textureAtlas->getTotalQuads();
|
|
|
|
Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity );
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-12-11 16:38:47 +08:00
|
|
|
// special opacity for premultiplied textures
|
|
|
|
if (_isOpacityModifyRGB)
|
2013-10-29 20:25:03 +08:00
|
|
|
{
|
2013-12-11 16:38:47 +08:00
|
|
|
color4.r *= _displayedOpacity/255.0f;
|
|
|
|
color4.g *= _displayedOpacity/255.0f;
|
|
|
|
color4.b *= _displayedOpacity/255.0f;
|
|
|
|
}
|
|
|
|
for (int index=0; index<count; ++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);
|
2013-12-06 18:07:16 +08:00
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2013-12-13 06:30:22 +08:00
|
|
|
std::string Label::getDescription() const
|
|
|
|
{
|
2013-12-18 17:47:20 +08:00
|
|
|
return StringUtils::format("<Label | Tag = %d, Label = '%s'>", _tag, cc_utf16_to_utf8(_currentUTF16String,-1,nullptr,nullptr));
|
2013-12-13 06:30:22 +08:00
|
|
|
}
|
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
|
2013-12-06 18:16:26 +08:00
|
|
|
NS_CC_END
|