2013-07-23 02:17:51 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2013 Zynga Inc.
|
2014-01-07 11:25:07 +08:00
|
|
|
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
2013-07-23 02:17:51 +08:00
|
|
|
|
|
|
|
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"
|
2013-07-25 01:22:46 +08:00
|
|
|
#include "CCFontAtlasCache.h"
|
2013-08-08 07:36:04 +08:00
|
|
|
#include "CCLabelTextFormatter.h"
|
2014-01-17 13:35:58 +08:00
|
|
|
#include "CCSprite.h"
|
|
|
|
#include "CCShaderCache.h"
|
|
|
|
#include "ccUTF8.h"
|
|
|
|
#include "CCSpriteFrame.h"
|
|
|
|
#include "CCDirector.h"
|
|
|
|
#include "renderer/CCRenderer.h"
|
2014-01-20 11:43:13 +08:00
|
|
|
#include "CCFont.h"
|
2013-07-23 02:17:51 +08:00
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
const int Label::DefultFontSize = 50;
|
|
|
|
|
2014-01-11 22:33:07 +08:00
|
|
|
Label* Label::create()
|
2013-07-23 02:17:51 +08:00
|
|
|
{
|
2014-01-11 22:33:07 +08:00
|
|
|
Label *ret = new Label();
|
2013-08-14 02:28:54 +08:00
|
|
|
|
2014-01-11 22:33:07 +08:00
|
|
|
if (!ret)
|
2013-07-25 08:21:51 +08:00
|
|
|
return nullptr;
|
2014-01-11 22:33:07 +08:00
|
|
|
|
|
|
|
ret->autorelease();
|
|
|
|
|
|
|
|
return ret;
|
2013-07-23 02:17:51 +08:00
|
|
|
}
|
|
|
|
|
2014-01-11 22:33:07 +08:00
|
|
|
Label* Label::createWithTTF(const TTFConfig& ttfConfig, const std::string& text, TextHAlignment alignment /* = TextHAlignment::CENTER */, int lineSize /* = 0 */)
|
2013-07-23 02:17:51 +08:00
|
|
|
{
|
2014-01-23 13:42:27 +08:00
|
|
|
Label *ret = new Label(nullptr,alignment);
|
2014-01-11 22:33:07 +08:00
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
return nullptr;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-01-11 22:33:07 +08:00
|
|
|
if (ret->setTTFConfig(ttfConfig))
|
2013-07-26 08:58:13 +08:00
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
ret->setMaxLineWidth(lineSize);
|
2014-01-23 13:42:27 +08:00
|
|
|
ret->setString(text);
|
2014-01-11 22:33:07 +08:00
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
2013-07-26 08:58:13 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-01-11 22:33:07 +08:00
|
|
|
delete ret;
|
|
|
|
return nullptr;
|
2013-07-26 08:58:13 +08:00
|
|
|
}
|
2013-07-23 02:17:51 +08:00
|
|
|
}
|
|
|
|
|
2014-01-13 16:32:35 +08:00
|
|
|
Label* Label::createWithTTF(const std::string& text, const std::string& fontFilePath, int fontSize, int lineSize /* = 0 */, TextHAlignment alignment /* = TextHAlignment::CENTER */, GlyphCollection glyphs /* = GlyphCollection::NEHE */, const char *customGlyphs /* = 0 */, bool useDistanceField /* = false */)
|
|
|
|
{
|
|
|
|
TTFConfig ttfConfig(fontFilePath.c_str(),fontSize,glyphs,customGlyphs,useDistanceField);
|
|
|
|
return createWithTTF(ttfConfig,text,alignment,lineSize);
|
|
|
|
}
|
|
|
|
|
2014-02-20 22:33:52 +08:00
|
|
|
Label* Label::createWithBMFont(const std::string& bmfontFilePath, const std::string& text,const TextHAlignment& alignment /* = TextHAlignment::LEFT */, int lineWidth /* = 0 */, const Point& imageOffset /* = Point::ZERO */)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-01-23 13:42:27 +08:00
|
|
|
Label *ret = new Label(nullptr,alignment);
|
2014-01-11 22:33:07 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
if (!ret)
|
2014-01-11 22:33:07 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2014-02-20 22:33:52 +08:00
|
|
|
if (ret->setBMFontFilePath(bmfontFilePath,imageOffset))
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-02-20 22:33:52 +08:00
|
|
|
ret->setMaxLineWidth(lineWidth);
|
2014-01-23 13:42:27 +08:00
|
|
|
ret->setString(text);
|
2013-08-08 07:36:04 +08:00
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete ret;
|
2014-01-11 22:33:07 +08:00
|
|
|
return nullptr;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-16 16:37:29 +08:00
|
|
|
Label* Label::createWithCharMap(const std::string& plistFile)
|
|
|
|
{
|
|
|
|
Label *ret = new Label();
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (ret->setCharMap(plistFile))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete ret;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Label* Label::createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap)
|
|
|
|
{
|
|
|
|
Label *ret = new Label();
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (ret->setCharMap(texture,itemWidth,itemHeight,startCharMap))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete ret;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Label* Label::createWithCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap)
|
|
|
|
{
|
|
|
|
Label *ret = new Label();
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (ret->setCharMap(charMapFile,itemWidth,itemHeight,startCharMap))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete ret;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Label::setCharMap(const std::string& plistFile)
|
|
|
|
{
|
|
|
|
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasCharMap(plistFile);
|
|
|
|
|
|
|
|
if (!newAtlas)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return initWithFontAtlas(newAtlas);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Label::setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap)
|
|
|
|
{
|
|
|
|
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasCharMap(texture,itemWidth,itemHeight,startCharMap);
|
|
|
|
|
|
|
|
if (!newAtlas)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return initWithFontAtlas(newAtlas);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Label::setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap)
|
|
|
|
{
|
|
|
|
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasCharMap(charMapFile,itemWidth,itemHeight,startCharMap);
|
|
|
|
|
|
|
|
if (!newAtlas)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return initWithFontAtlas(newAtlas);
|
|
|
|
}
|
|
|
|
|
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-12-27 15:06:16 +08:00
|
|
|
, _commonLineHeight(0.0f)
|
2013-08-22 11:12:09 +08:00
|
|
|
, _lineBreakWithoutSpaces(false)
|
2014-03-07 15:58:49 +08:00
|
|
|
, _maxLineWidth(0)
|
|
|
|
, _labelWidth(0)
|
|
|
|
, _labelHeight(0)
|
2014-03-07 14:58:44 +08:00
|
|
|
, _hAlignment(alignment)
|
2014-01-11 22:33:07 +08:00
|
|
|
, _currentUTF16String(nullptr)
|
|
|
|
, _originalUTF16String(nullptr)
|
2014-01-21 17:55:49 +08:00
|
|
|
, _horizontalKernings(nullptr)
|
2013-11-13 11:22:34 +08:00
|
|
|
, _fontAtlas(atlas)
|
2014-01-26 21:19:40 +08:00
|
|
|
, _isOpacityModifyRGB(false)
|
2013-12-27 15:06:16 +08:00
|
|
|
, _useDistanceField(useDistanceField)
|
|
|
|
, _useA8Shader(useA8Shader)
|
2014-02-19 20:26:14 +08:00
|
|
|
, _fontScale(1.0f)
|
2013-12-27 15:06:16 +08:00
|
|
|
, _uniformEffectColor(0)
|
2014-02-10 11:21:54 +08:00
|
|
|
,_currNumLines(-1)
|
2013-07-23 02:17:51 +08:00
|
|
|
{
|
2014-01-11 22:33:07 +08:00
|
|
|
_cascadeColorEnabled = true;
|
2014-02-18 14:30:51 +08:00
|
|
|
_batchNodes.push_back(this);
|
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;
|
2014-01-21 17:55:49 +08:00
|
|
|
delete [] _horizontalKernings;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
if (_fontAtlas)
|
2014-03-07 14:58:44 +08:00
|
|
|
{
|
2013-08-08 07:36:04 +08:00
|
|
|
FontAtlasCache::releaseFontAtlas(_fontAtlas);
|
2014-03-07 14:58:44 +08:00
|
|
|
}
|
2013-10-29 20:25:03 +08:00
|
|
|
|
2014-03-07 14:58:44 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_reusedLetter);
|
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)
|
|
|
|
{
|
2014-03-05 16:51:16 +08:00
|
|
|
ret = SpriteBatchNode::initWithTexture(_fontAtlas->getTexture(0), 30);
|
2014-01-11 22:33:07 +08:00
|
|
|
if (_reusedLetter == nullptr)
|
|
|
|
{
|
2014-03-05 16:51:16 +08:00
|
|
|
_reusedLetter = Sprite::createWithTexture(_fontAtlas->getTexture(0));
|
2014-01-11 22:33:07 +08:00
|
|
|
_reusedLetter->setOpacityModifyRGB(_isOpacityModifyRGB);
|
|
|
|
_reusedLetter->retain();
|
2014-01-21 17:55:49 +08:00
|
|
|
_reusedLetter->setAnchorPoint(Point::ANCHOR_TOP_LEFT);
|
2014-03-05 15:54:40 +08:00
|
|
|
_reusedLetter->setBatchNode(this);
|
2014-01-11 22:33:07 +08:00
|
|
|
}
|
2013-10-29 20:25:03 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
_currLabelEffect = LabelEffect::NORMAL;
|
|
|
|
initProgram();
|
2014-01-11 22:33:07 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
void Label::initProgram()
|
|
|
|
{
|
|
|
|
switch (_currLabelEffect)
|
|
|
|
{
|
|
|
|
case cocos2d::LabelEffect::NORMAL:
|
|
|
|
case cocos2d::LabelEffect::SHADOW:
|
|
|
|
if (_useDistanceField)
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL));
|
|
|
|
else if (_useA8Shader)
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_A8_COLOR));
|
|
|
|
else
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
|
|
|
|
|
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::OUTLINE:
|
2014-03-05 16:51:16 +08:00
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_OUTLINE));
|
2014-03-05 15:54:40 +08:00
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::GLOW:
|
|
|
|
if (_useDistanceField)
|
|
|
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_GLOW));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_uniformEffectColor = glGetUniformLocation(_shaderProgram->getProgram(), "v_effectColor");
|
|
|
|
}
|
|
|
|
|
2014-01-15 17:21:08 +08:00
|
|
|
bool Label::initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = false */, bool useA8Shader /* = false */)
|
2014-01-11 22:33:07 +08:00
|
|
|
{
|
|
|
|
FontAtlas *oldAtlas = _fontAtlas;
|
|
|
|
bool oldDistanceFieldEnable = _useDistanceField;
|
|
|
|
bool oldA8ShaderEnabel = _useA8Shader;
|
2014-01-15 17:21:08 +08:00
|
|
|
|
|
|
|
_fontAtlas = atlas;
|
|
|
|
_useDistanceField = distanceFieldEnabled;
|
|
|
|
_useA8Shader = useA8Shader;
|
2014-01-11 22:33:07 +08:00
|
|
|
|
|
|
|
bool ret = Label::init();
|
|
|
|
if (oldAtlas)
|
|
|
|
{
|
|
|
|
if (ret)
|
|
|
|
{
|
2014-03-07 14:58:44 +08:00
|
|
|
FontAtlasCache::releaseFontAtlas(oldAtlas);
|
2014-01-11 22:33:07 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_fontAtlas = oldAtlas;
|
|
|
|
_useDistanceField = oldDistanceFieldEnable;
|
|
|
|
_useA8Shader = oldA8ShaderEnabel;
|
|
|
|
Label::init();
|
|
|
|
|
2014-01-15 17:21:08 +08:00
|
|
|
FontAtlasCache::releaseFontAtlas(atlas);
|
2014-01-11 22:33:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_fontAtlas)
|
|
|
|
{
|
|
|
|
_commonLineHeight = _fontAtlas->getCommonLineHeight();
|
2014-01-23 13:42:27 +08:00
|
|
|
if(_currentUTF16String)
|
|
|
|
{
|
|
|
|
resetCurrentString();
|
2014-01-11 22:33:07 +08:00
|
|
|
alignText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-13 12:42:15 +08:00
|
|
|
return ret;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2014-01-15 17:21:08 +08:00
|
|
|
bool Label::setTTFConfig(const TTFConfig& ttfConfig)
|
2014-01-11 22:33:07 +08:00
|
|
|
{
|
2014-03-05 15:54:40 +08:00
|
|
|
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasTTF(ttfConfig);
|
2014-01-11 22:33:07 +08:00
|
|
|
|
|
|
|
if (!newAtlas)
|
|
|
|
return false;
|
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
if (initWithFontAtlas(newAtlas,ttfConfig.distanceFieldEnabled,true))
|
|
|
|
{
|
|
|
|
_fontConfig = ttfConfig;
|
|
|
|
if (ttfConfig.outlineSize > 0)
|
|
|
|
{
|
|
|
|
_fontConfig.distanceFieldEnabled = false;
|
|
|
|
_useDistanceField = false;
|
|
|
|
_useA8Shader = false;
|
|
|
|
_currLabelEffect = LabelEffect::OUTLINE;
|
|
|
|
initProgram();
|
|
|
|
}
|
|
|
|
else if(ttfConfig.distanceFieldEnabled)
|
|
|
|
{
|
|
|
|
this->setFontScale(1.0f * ttfConfig.fontSize / DefultFontSize);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2014-01-11 22:33:07 +08:00
|
|
|
}
|
|
|
|
|
2014-02-20 22:33:52 +08:00
|
|
|
bool Label::setBMFontFilePath(const std::string& bmfontFilePath, const Point& imageOffset /* = Point::ZERO */)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-02-20 22:33:52 +08:00
|
|
|
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasFNT(bmfontFilePath,imageOffset);
|
2013-12-13 12:42:15 +08:00
|
|
|
|
2014-01-15 17:21:08 +08:00
|
|
|
if (!newAtlas)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return initWithFontAtlas(newAtlas);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2014-01-23 13:42:27 +08:00
|
|
|
void Label::setString(const std::string& text)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-03-07 14:58:44 +08:00
|
|
|
auto utf16String = cc_utf8_to_utf16(text.c_str());
|
|
|
|
if(utf16String)
|
|
|
|
{
|
|
|
|
_originalUTF8String = text;
|
|
|
|
setCurrentString(utf16String);
|
|
|
|
setOriginalString(utf16String);
|
|
|
|
alignText();
|
|
|
|
}
|
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-03-07 15:58:49 +08:00
|
|
|
void Label::setAlignment(TextHAlignment hAlignment,bool aligntext /* = true */)
|
2014-03-07 14:58:44 +08:00
|
|
|
{
|
2014-03-07 15:58:49 +08:00
|
|
|
setAlignment(hAlignment,_vAlignment,aligntext);
|
2014-03-07 14:58:44 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-03-07 15:58:49 +08:00
|
|
|
inline void Label::setHorizontalAlignment(TextHAlignment hAlignment,bool aligntext /* = true */)
|
2014-03-07 14:58:44 +08:00
|
|
|
{
|
2014-03-07 15:58:49 +08:00
|
|
|
setAlignment(hAlignment,_vAlignment,aligntext);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2014-03-07 15:58:49 +08:00
|
|
|
inline void Label::setVerticalAlignment(TextVAlignment vAlignment,bool aligntext /* = true */)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-03-07 15:58:49 +08:00
|
|
|
setAlignment(_hAlignment,vAlignment,aligntext);
|
2014-03-07 14:58:44 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-03-07 15:58:49 +08:00
|
|
|
void Label::setAlignment(TextHAlignment hAlignment,TextVAlignment vAlignment,bool aligntext /* = true */)
|
2014-03-07 14:58:44 +08:00
|
|
|
{
|
|
|
|
if (hAlignment != _hAlignment || vAlignment != _vAlignment)
|
|
|
|
{
|
|
|
|
_hAlignment = hAlignment;
|
|
|
|
_vAlignment = vAlignment;
|
2014-03-07 15:58:49 +08:00
|
|
|
if (_currentUTF16String && aligntext)
|
2014-01-23 13:42:27 +08:00
|
|
|
{
|
|
|
|
resetCurrentString();
|
2014-03-07 14:58:44 +08:00
|
|
|
alignText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-23 13:42:27 +08:00
|
|
|
|
2014-03-07 14:58:44 +08:00
|
|
|
void Label::setMaxLineWidth(unsigned int maxLineWidth)
|
|
|
|
{
|
|
|
|
if (_maxLineWidth != maxLineWidth)
|
|
|
|
{
|
|
|
|
_maxLineWidth = maxLineWidth;
|
|
|
|
if (_currentUTF16String)
|
|
|
|
{
|
|
|
|
resetCurrentString();
|
2014-01-23 13:42:27 +08:00
|
|
|
alignText();
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-07 14:58:44 +08:00
|
|
|
inline void Label::setWidth(unsigned int width)
|
|
|
|
{
|
|
|
|
setDimensions(width,_labelHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void Label::setHeight(unsigned int height)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-03-07 14:58:44 +08:00
|
|
|
setDimensions(_labelWidth,height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setDimensions(unsigned int width,unsigned int height)
|
|
|
|
{
|
|
|
|
if (height != _labelHeight || width != _labelWidth)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-03-07 14:58:44 +08:00
|
|
|
_labelHeight = height;
|
|
|
|
_labelWidth = width;
|
2014-02-19 20:26:14 +08:00
|
|
|
_maxLineWidth = width;
|
2014-01-23 13:42:27 +08:00
|
|
|
if (_currentUTF16String)
|
|
|
|
{
|
|
|
|
resetCurrentString();
|
|
|
|
alignText();
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setLineBreakWithoutSpace(bool breakWithoutSpace)
|
|
|
|
{
|
|
|
|
if (breakWithoutSpace != _lineBreakWithoutSpaces)
|
|
|
|
{
|
|
|
|
// store
|
|
|
|
_lineBreakWithoutSpaces = breakWithoutSpace;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
// need to align text again
|
2014-01-23 13:42:27 +08:00
|
|
|
if(_currentUTF16String)
|
|
|
|
{
|
|
|
|
resetCurrentString();
|
|
|
|
alignText();
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::setScale(float scale)
|
|
|
|
{
|
2013-12-13 12:42:15 +08:00
|
|
|
if (_useDistanceField)
|
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
scale *= _fontScale;
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
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)
|
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
scaleX *= _fontScale;
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
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)
|
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
scaleY *= _fontScale;
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
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)
|
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
return _scaleY / _fontScale;
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _scaleY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float Label::getScaleX() const
|
|
|
|
{
|
|
|
|
if (_useDistanceField)
|
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
return _scaleX / _fontScale;
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _scaleX;
|
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Label::alignText()
|
2014-01-23 13:42:27 +08:00
|
|
|
{
|
2014-03-07 14:58:44 +08:00
|
|
|
if (_fontAtlas == nullptr)
|
2014-02-19 20:26:14 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-18 16:41:01 +08:00
|
|
|
for (const auto& batchNode:_batchNodes)
|
2014-02-18 14:30:51 +08:00
|
|
|
{
|
|
|
|
batchNode->getTextureAtlas()->removeAllQuads();
|
|
|
|
}
|
2013-10-29 20:25:03 +08:00
|
|
|
_fontAtlas->prepareLetterDefinitions(_currentUTF16String);
|
2014-02-18 14:30:51 +08:00
|
|
|
auto textures = _fontAtlas->getTextures();
|
|
|
|
if (textures.size() > _batchNodes.size())
|
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
for (auto index = _batchNodes.size(); index < textures.size(); ++index)
|
2014-02-18 14:30:51 +08:00
|
|
|
{
|
|
|
|
auto batchNode = SpriteBatchNode::createWithTexture(textures[index]);
|
|
|
|
batchNode->setAnchorPoint(Point::ANCHOR_TOP_LEFT);
|
|
|
|
batchNode->setPosition(Point::ZERO);
|
|
|
|
Node::addChild(batchNode,0,Node::INVALID_TAG);
|
|
|
|
_batchNodes.push_back(batchNode);
|
|
|
|
}
|
|
|
|
}
|
2013-10-29 20:25:03 +08:00
|
|
|
LabelTextFormatter::createStringSprites(this);
|
2014-02-19 20:26:14 +08:00
|
|
|
if(_maxLineWidth > 0 && _contentSize.width > _maxLineWidth && LabelTextFormatter::multilineText(this) )
|
2013-08-08 07:36:04 +08:00
|
|
|
LabelTextFormatter::createStringSprites(this);
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-03-07 14:58:44 +08:00
|
|
|
if(_labelWidth >0 || (_currNumLines > 1 && _hAlignment != TextHAlignment::LEFT))
|
2014-02-10 11:21:54 +08:00
|
|
|
LabelTextFormatter::alignText(this);
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-11-28 16:02:03 +08:00
|
|
|
int strLen = cc_wcslen(_currentUTF16String);
|
2014-02-19 20:26:14 +08:00
|
|
|
Rect uvRect;
|
|
|
|
Sprite* letterSprite;
|
2013-12-19 10:33:04 +08:00
|
|
|
for(const auto &child : _children) {
|
|
|
|
int tag = child->getTag();
|
2014-02-18 14:30:51 +08:00
|
|
|
if(tag >= strLen)
|
2014-02-19 20:26:14 +08:00
|
|
|
{
|
2013-12-19 10:33:04 +08:00
|
|
|
SpriteBatchNode::removeChild(child, true);
|
2014-02-19 20:26:14 +08:00
|
|
|
}
|
|
|
|
else if(tag >= 0)
|
|
|
|
{
|
|
|
|
letterSprite = dynamic_cast<Sprite*>(child);
|
|
|
|
if (letterSprite)
|
|
|
|
{
|
|
|
|
uvRect.size.height = _lettersInfo[tag].def.height;
|
|
|
|
uvRect.size.width = _lettersInfo[tag].def.width;
|
|
|
|
uvRect.origin.x = _lettersInfo[tag].def.U;
|
|
|
|
uvRect.origin.y = _lettersInfo[tag].def.V;
|
|
|
|
|
|
|
|
letterSprite->setTexture(textures[_lettersInfo[tag].def.textureID]);
|
|
|
|
letterSprite->setTextureRect(uvRect);
|
|
|
|
}
|
|
|
|
}
|
2013-12-19 10:33:04 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-02-19 20:26:14 +08:00
|
|
|
int index;
|
2014-03-07 15:58:49 +08:00
|
|
|
for (int ctr = 0; ctr < _limitShowCount; ++ctr)
|
2013-10-29 20:25:03 +08:00
|
|
|
{
|
|
|
|
if (_lettersInfo[ctr].def.validDefinition)
|
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
updateSpriteWithLetterDefinition(_lettersInfo[ctr].def,textures[_lettersInfo[ctr].def.textureID]);
|
2013-10-29 20:25:03 +08:00
|
|
|
_reusedLetter->setPosition(_lettersInfo[ctr].position);
|
2014-02-19 20:26:14 +08:00
|
|
|
index = _batchNodes[_lettersInfo[ctr].def.textureID]->getTextureAtlas()->getTotalQuads();
|
2014-02-18 14:30:51 +08:00
|
|
|
_batchNodes[_lettersInfo[ctr].def.textureID]->insertQuadFromSprite(_reusedLetter,index);
|
2013-10-29 20:25:03 +08:00
|
|
|
}
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
2014-01-23 16:27:28 +08:00
|
|
|
|
|
|
|
updateColor();
|
2013-07-23 02:17:51 +08:00
|
|
|
}
|
|
|
|
|
2014-01-21 17:55:49 +08:00
|
|
|
bool Label::computeHorizontalKernings(unsigned short int *stringToRender)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-01-21 17:55:49 +08:00
|
|
|
if (_horizontalKernings)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-01-21 17:55:49 +08:00
|
|
|
delete [] _horizontalKernings;
|
2014-03-07 14:58:44 +08:00
|
|
|
_horizontalKernings = nullptr;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
int letterCount = 0;
|
2014-01-21 17:55:49 +08:00
|
|
|
_horizontalKernings = _fontAtlas->getFont()->getHorizontalKerningForTextUTF16(stringToRender, letterCount);
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-01-21 17:55:49 +08:00
|
|
|
if(!_horizontalKernings)
|
2013-08-08 07:36:04 +08:00
|
|
|
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;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
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;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
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;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
_currentUTF16String = stringToSet;
|
2014-02-10 11:21:54 +08:00
|
|
|
computeStringNumLines();
|
2014-03-07 14:58:44 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
// compute the advances
|
2014-01-21 17:55:49 +08:00
|
|
|
return computeHorizontalKernings(stringToSet);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Label::resetCurrentString()
|
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
if ((!_currentUTF16String) && (!_originalUTF16String))
|
2013-08-13 04:29:54 +08:00
|
|
|
return;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
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
|
|
|
}
|
2014-03-05 15:54:40 +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;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2014-02-19 20:26:14 +08:00
|
|
|
void Label::updateSpriteWithLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
_reusedRect.size.height = theDefinition.height;
|
|
|
|
_reusedRect.size.width = theDefinition.width;
|
|
|
|
_reusedRect.origin.x = theDefinition.U;
|
|
|
|
_reusedRect.origin.y = theDefinition.V;
|
|
|
|
|
|
|
|
if(_reusedLetter->getBatchNode() != _batchNodes[theDefinition.textureID])
|
|
|
|
_reusedLetter->setBatchNode(_batchNodes[theDefinition.textureID]);
|
|
|
|
_reusedLetter->setTextureRect(_reusedRect,false,_reusedRect.size);
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2014-02-19 20:26:14 +08:00
|
|
|
bool Label::recordLetterInfo(const cocos2d::Point& point,const FontLetterDefinition& letterDef, 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);
|
2014-02-19 20:26:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
_lettersInfo[spriteIndex].def = letterDef;
|
2013-10-29 20:25:03 +08:00
|
|
|
_lettersInfo[spriteIndex].position = point;
|
|
|
|
_lettersInfo[spriteIndex].contentSize.width = _lettersInfo[spriteIndex].def.width;
|
|
|
|
_lettersInfo[spriteIndex].contentSize.height = _lettersInfo[spriteIndex].def.height;
|
2014-03-07 14:58:44 +08:00
|
|
|
_limitShowCount++;
|
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;
|
2014-03-07 14:58:44 +08:00
|
|
|
_limitShowCount++;
|
2014-03-05 15:54:40 +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)
|
|
|
|
{
|
2014-03-05 15:54:40 +08:00
|
|
|
switch (effect)
|
2013-12-13 12:42:15 +08:00
|
|
|
{
|
2014-03-05 15:54:40 +08:00
|
|
|
case cocos2d::LabelEffect::NORMAL:
|
|
|
|
disableEffect();
|
2013-12-13 12:42:15 +08:00
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::OUTLINE:
|
2014-03-05 15:54:40 +08:00
|
|
|
enableOutline(Color4B(effectColor));
|
2013-12-13 12:42:15 +08:00
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::SHADOW:
|
2014-03-05 15:54:40 +08:00
|
|
|
enableShadow(effectColor);
|
2013-12-13 12:42:15 +08:00
|
|
|
break;
|
|
|
|
case cocos2d::LabelEffect::GLOW:
|
2014-03-05 15:54:40 +08:00
|
|
|
enableGlow(effectColor);
|
2013-12-13 12:42:15 +08:00
|
|
|
break;
|
|
|
|
default:
|
2014-03-05 15:54:40 +08:00
|
|
|
break;
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
}
|
2013-12-13 12:42:15 +08:00
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
void Label::enableGlow(const Color3B& glowColor)
|
|
|
|
{
|
|
|
|
if(_useDistanceField == false)
|
|
|
|
return;
|
|
|
|
_currLabelEffect = LabelEffect::GLOW;
|
|
|
|
_effectColor = glowColor;
|
|
|
|
initProgram();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::enableOutline(const Color4B& outlineColor,int outlineSize /* = 1 */)
|
|
|
|
{
|
|
|
|
_outlineColor = outlineColor;
|
|
|
|
if (outlineSize > 0)
|
|
|
|
{
|
|
|
|
_currLabelEffect = LabelEffect::OUTLINE;
|
|
|
|
if (_fontConfig.outlineSize != outlineSize)
|
|
|
|
{
|
|
|
|
_fontConfig.outlineSize = outlineSize;
|
|
|
|
setTTFConfig(_fontConfig);
|
|
|
|
}
|
|
|
|
initProgram();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::enableShadow(const Color3B& shadowColor /* = Color3B::BLACK */,const Size &offset /* = Size(2 ,-2)*/, float opacity /* = 0.75f */, int blurRadius /* = 0 */)
|
|
|
|
{
|
|
|
|
_shadowOpacity = opacity;
|
|
|
|
_effectColor = shadowColor;
|
|
|
|
_shadowOffset = offset;
|
|
|
|
//todo:support blur for shadow
|
|
|
|
_shadowBlurRadius = 0;
|
|
|
|
_currLabelEffect = LabelEffect::SHADOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::disableEffect()
|
|
|
|
{
|
|
|
|
if (_currLabelEffect == LabelEffect::OUTLINE)
|
|
|
|
{
|
|
|
|
_fontConfig.outlineSize = 0;
|
|
|
|
setTTFConfig(_fontConfig);
|
|
|
|
}
|
|
|
|
_currLabelEffect = LabelEffect::NORMAL;
|
|
|
|
initProgram();
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
|
|
|
|
2014-02-19 20:26:14 +08:00
|
|
|
void Label::setFontScale(float fontScale)
|
2013-12-13 12:42:15 +08:00
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
_fontScale = fontScale;
|
|
|
|
Node::setScale(_fontScale);
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
|
|
|
|
2014-03-06 07:49:08 +08:00
|
|
|
void Label::onDraw(const kmMat4& transform, bool transformUpdated)
|
2013-12-13 12:42:15 +08:00
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
CC_PROFILER_START("Label - draw");
|
2013-12-13 12:42:15 +08:00
|
|
|
|
|
|
|
// Optimization: Fast Dispatch
|
2014-02-18 14:30:51 +08:00
|
|
|
if( _batchNodes.size() == 1 && _textureAtlas->getTotalQuads() == 0 )
|
2013-12-13 12:42:15 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
_shaderProgram->use();
|
|
|
|
GL::blendFunc( _blendFunc.src, _blendFunc.dst );
|
|
|
|
bool trans = false;
|
2013-12-13 12:42:15 +08:00
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
if (_currLabelEffect == LabelEffect::OUTLINE)
|
|
|
|
{
|
|
|
|
_shaderProgram->setUniformLocationWith4f(_uniformEffectColor, _outlineColor.r/255.0f,_outlineColor.g/255.0f,_outlineColor.b/255.0f,_outlineColor.a/255.0f);
|
|
|
|
}
|
|
|
|
else if (_currLabelEffect == LabelEffect::GLOW)
|
2013-12-13 12:42:15 +08:00
|
|
|
{
|
|
|
|
_shaderProgram->setUniformLocationWith3f(_uniformEffectColor, _effectColor.r/255.0f,_effectColor.g/255.0f,_effectColor.b/255.0f);
|
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
else if(_currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0)
|
2014-02-18 16:41:01 +08:00
|
|
|
{
|
2014-03-05 15:54:40 +08:00
|
|
|
trans = true;
|
|
|
|
drawShadowWithoutBlur();
|
2014-02-18 16:41:01 +08:00
|
|
|
}
|
2013-12-13 12:42:15 +08:00
|
|
|
|
2014-03-06 07:49:08 +08:00
|
|
|
_shaderProgram->setUniformsForBuiltins(transform);
|
2014-03-05 15:54:40 +08:00
|
|
|
|
|
|
|
for(const auto &child: _children)
|
|
|
|
{
|
|
|
|
if(child->getTag() >= 0)
|
|
|
|
child->updateTransform();
|
|
|
|
}
|
2013-12-13 12:42:15 +08:00
|
|
|
|
2014-02-18 16:41:01 +08:00
|
|
|
for (const auto& batchNode:_batchNodes)
|
2014-02-18 14:30:51 +08:00
|
|
|
{
|
|
|
|
batchNode->getTextureAtlas()->drawQuads();
|
|
|
|
}
|
2013-12-13 12:42:15 +08:00
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
if (trans)
|
|
|
|
{
|
|
|
|
kmGLPopMatrix();
|
|
|
|
}
|
|
|
|
|
2014-02-19 20:26:14 +08:00
|
|
|
CC_PROFILER_STOP("Label - draw");
|
2013-12-13 12:42:15 +08:00
|
|
|
}
|
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
void Label::drawShadowWithoutBlur()
|
|
|
|
{
|
|
|
|
_position.x += _shadowOffset.width;
|
|
|
|
_position.y += _shadowOffset.height;
|
|
|
|
_transformDirty = _inverseDirty = true;
|
|
|
|
Color3B oldColor = _realColor;
|
|
|
|
GLubyte oldOPacity = _displayedOpacity;
|
|
|
|
_displayedOpacity = _shadowOpacity * _displayedOpacity;
|
|
|
|
setColor(_effectColor);
|
|
|
|
|
|
|
|
_modelViewTransform = transform(_parentTransform);
|
|
|
|
kmGLPushMatrix();
|
|
|
|
kmGLLoadMatrix(&_modelViewTransform);
|
|
|
|
|
|
|
|
_shaderProgram->setUniformsForBuiltins(_modelViewTransform);
|
|
|
|
for(const auto &child: _children)
|
|
|
|
{
|
|
|
|
child->updateTransform();
|
|
|
|
}
|
|
|
|
for (const auto& batchNode:_batchNodes)
|
|
|
|
{
|
|
|
|
batchNode->getTextureAtlas()->drawQuads();
|
|
|
|
}
|
|
|
|
|
|
|
|
_position.x -= _shadowOffset.width;
|
|
|
|
_position.y -= _shadowOffset.height;
|
|
|
|
_transformDirty = _inverseDirty = true;
|
|
|
|
_displayedOpacity = oldOPacity;
|
|
|
|
setColor(oldColor);
|
|
|
|
_modelViewTransform = transform(_parentTransform);
|
|
|
|
kmGLLoadMatrix(&_modelViewTransform);
|
|
|
|
//kmGLPopMatrix();
|
|
|
|
}
|
|
|
|
|
2014-03-01 08:10:48 +08:00
|
|
|
void Label::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
|
2014-01-04 10:56:14 +08:00
|
|
|
{
|
2014-01-19 03:35:27 +08:00
|
|
|
_customCommand.init(_globalZOrder);
|
2014-03-06 07:49:08 +08:00
|
|
|
_customCommand.func = CC_CALLBACK_0(Label::onDraw, this, transform, transformUpdated);
|
2014-03-01 08:10:48 +08:00
|
|
|
renderer->addCommand(&_customCommand);
|
2014-01-04 10:56:14 +08:00
|
|
|
}
|
|
|
|
|
2014-03-01 08:10:48 +08:00
|
|
|
void Label::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
|
2014-02-18 14:30:51 +08:00
|
|
|
{
|
|
|
|
if (! _visible)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2014-03-01 03:20:53 +08:00
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
if (_currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0)
|
|
|
|
{
|
|
|
|
_parentTransform = parentTransform;
|
|
|
|
draw(renderer, _modelViewTransform, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool dirty = parentTransformUpdated || _transformUpdated;
|
|
|
|
|
|
|
|
if(dirty)
|
|
|
|
_modelViewTransform = transform(parentTransform);
|
|
|
|
_transformUpdated = false;
|
2014-02-18 14:30:51 +08:00
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
// IMPORTANT:
|
|
|
|
// To ease the migration to v3.0, we still support the kmGL stack,
|
|
|
|
// but it is deprecated and your code should not rely on it
|
|
|
|
kmGLPushMatrix();
|
|
|
|
kmGLLoadMatrix(&_modelViewTransform);
|
2014-02-18 14:30:51 +08:00
|
|
|
|
2014-03-05 15:54:40 +08:00
|
|
|
draw(renderer, _modelViewTransform, dirty);
|
|
|
|
|
|
|
|
kmGLPopMatrix();
|
|
|
|
}
|
|
|
|
|
2014-02-18 14:30:51 +08:00
|
|
|
setOrderOfArrival(0);
|
|
|
|
}
|
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
///// PROTOCOL STUFF
|
2014-02-19 20:26:14 +08:00
|
|
|
Sprite * Label::getLetter(int lettetIndex)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2014-03-07 15:58:49 +08:00
|
|
|
if (lettetIndex < _limitShowCount)
|
2014-03-07 14:58:44 +08:00
|
|
|
{
|
2014-02-19 20:26:14 +08:00
|
|
|
if(_lettersInfo[lettetIndex].def.validDefinition == false)
|
2013-10-29 20:25:03 +08:00
|
|
|
return nullptr;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-02-19 20:26:14 +08:00
|
|
|
Sprite* sp = static_cast<Sprite*>(this->getChildByTag(lettetIndex));
|
2013-10-29 20:25:03 +08:00
|
|
|
|
|
|
|
if (!sp)
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
2013-10-29 20:25:03 +08:00
|
|
|
Rect uvRect;
|
2014-02-19 20:26:14 +08:00
|
|
|
uvRect.size.height = _lettersInfo[lettetIndex].def.height;
|
|
|
|
uvRect.size.width = _lettersInfo[lettetIndex].def.width;
|
|
|
|
uvRect.origin.x = _lettersInfo[lettetIndex].def.U;
|
|
|
|
uvRect.origin.y = _lettersInfo[lettetIndex].def.V;
|
2013-10-29 20:25:03 +08:00
|
|
|
|
2014-03-05 16:51:16 +08:00
|
|
|
sp = Sprite::createWithTexture(_fontAtlas->getTexture(_lettersInfo[lettetIndex].def.textureID),uvRect);
|
2013-10-29 20:25:03 +08:00
|
|
|
sp->setBatchNode(this);
|
2014-01-21 17:55:49 +08:00
|
|
|
sp->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
2014-02-19 20:26:14 +08:00
|
|
|
sp->setPosition(Point(_lettersInfo[lettetIndex].position.x+uvRect.size.width/2,_lettersInfo[lettetIndex].position.y-uvRect.size.height/2));
|
2013-10-29 20:25:03 +08:00
|
|
|
sp->setOpacity(_realOpacity);
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-02-19 20:26:14 +08:00
|
|
|
this->addSpriteWithoutQuad(sp, lettetIndex, lettetIndex);
|
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
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-10-29 20:25:03 +08:00
|
|
|
return nullptr;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// string related stuff
|
2013-09-13 11:46:46 +08:00
|
|
|
int Label::getStringNumLines() const
|
2014-02-10 11:21:54 +08:00
|
|
|
{
|
|
|
|
return _currNumLines;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Label::computeStringNumLines()
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
int quantityOfLines = 1;
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-01-22 14:57:11 +08:00
|
|
|
unsigned int stringLen = _currentUTF16String ? cc_wcslen(_currentUTF16String) : -1;
|
|
|
|
if (stringLen < 1)
|
2014-02-10 11:21:54 +08:00
|
|
|
{
|
|
|
|
_currNumLines = stringLen;
|
|
|
|
return;
|
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2013-08-08 07:36:04 +08:00
|
|
|
// count number of lines
|
|
|
|
for (unsigned int i = 0; i < stringLen - 1; ++i)
|
|
|
|
{
|
2014-02-10 11:21:54 +08:00
|
|
|
if (_currentUTF16String[i] == '\n')
|
2013-08-08 07:36:04 +08:00
|
|
|
{
|
|
|
|
quantityOfLines++;
|
|
|
|
}
|
|
|
|
}
|
2014-03-05 15:54:40 +08:00
|
|
|
|
2014-02-10 11:21:54 +08:00
|
|
|
_currNumLines = quantityOfLines;
|
2013-08-08 07:36:04 +08:00
|
|
|
}
|
|
|
|
|
2014-03-07 14:58:44 +08:00
|
|
|
int Label::getStringLength() 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
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
2014-03-05 15:54:40 +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)
|
|
|
|
{
|
2014-03-05 15:54:40 +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
|
|
|
{
|
2014-03-05 14:41:59 +08:00
|
|
|
if (nullptr == _textureAtlas)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-11 16:38:47 +08:00
|
|
|
Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity );
|
2014-03-05 14:41:59 +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;
|
|
|
|
}
|
2014-03-05 14:41:59 +08:00
|
|
|
|
|
|
|
cocos2d::TextureAtlas* textureAtlas;
|
|
|
|
V3F_C4B_T2F_Quad *quads;
|
|
|
|
for (const auto& batchNode:_batchNodes)
|
2013-12-11 16:38:47 +08:00
|
|
|
{
|
2014-03-05 14:41:59 +08:00
|
|
|
textureAtlas = batchNode->getTextureAtlas();
|
|
|
|
quads = textureAtlas->getQuads();
|
|
|
|
auto count = textureAtlas->getTotalQuads();
|
|
|
|
|
|
|
|
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-12-06 18:16:26 +08:00
|
|
|
NS_CC_END
|