Cocos2dx Lua RichText关于createWithXML下划线问题。

本文介绍了如何在Cocos2d-x游戏引擎中修改Label组件的下划线颜色和大小,包括通过`enableUnderline`函数和自定义XML标签`u`来设置,以及对lua接口的相应调整。
摘要由CSDN通过智能技术生成

前言。

由于自己最近工作需要用到这个功能。但是通过发现原有的不能设置颜色和大小。以前也没去细看,最近才去看了底层。自己也对此做了底层的修改。希望对各位有所帮助。

通过发现。最后的实现是通过Label的函数enableUnderline中在Label的基础上加上DrawNode实现。您自己也可以通过自己创建LabelDrawNode去实现,也有发现 Cocos2d-Lua-Community 通过在enableUnderline增加设置下划线颜色 在Label的函数 updateContent 中改变颜色。这个方案比较简单 也推荐大家使用。具体实现代码片段在如下

if (_numberOfLines)
        {
            // This is the logic for TTF fonts
            const float charheight = (_textDesiredHeight / _numberOfLines);
            _underlineNode->setLineWidth(charheight/6);

            // atlas font
            for (int i=0; i<_numberOfLines; ++i)
            {
                float offsety = 0;
                if (_strikethroughEnabled)
                    offsety += charheight / 2;
                // FIXME: Might not work with different vertical alignments
                float y = (_numberOfLines - i - 1) * charheight + offsety;

                // Github issue #15214. Uses _displayedColor instead of _textColor for the underline.
                // This is to have the same behavior of SystemFonts.
                Color4F color = _underlineColor4B.a > 0 ? Color4F(_underlineColor4B) : Color4F(_displayedColor);
                _underlineNode->drawLine(Vec2(_linesOffsetX[i] + 1, y), Vec2(_linesWidth[i] + _linesOffsetX[i] - 1, y), color);
            }
        }
        else if (_textSprite)
        {
            // ...and is the logic for System fonts
            float y = 0;
            const auto spriteSize = _textSprite->getContentSize();
            _underlineNode->setLineWidth(spriteSize.height/6);
            if (_strikethroughEnabled)
                // FIXME: system fonts don't report the height of the font correctly. only the size of the texture, which is POT
                y += spriteSize.height / 2;
            // FIXME: Might not work with different vertical alignments
            Color4F color = _underlineColor4B.a > 0 ? Color4F(_underlineColor4B) : Color4F(_textSprite->getDisplayedColor());
            _underlineNode->drawLine(Vec2(0.0f + 1, y), Vec2(spriteSize.width - 1, y), color);
        }
    }

还有一个简单的实现:就是将此函数中 这句代码

_underlineNode->drawLine(Vec2(_linesOffsetX[i] + 1, y), Vec2(_linesWidth[i] + _linesOffsetX[i] - 1, y), color);

的 _displayedColor 改成 _textColor 就是和字体颜色一样了

自己实现部分。

为了方便我自己,实现创建createWithXML时候直接通过原有标识“u”就直接设置颜色和线的宽度。

UIRichText部分

MyXMLVisitor::setTagDescription("u", true, [](const ValueMap& tagAttrValueMap) {
        // no supported attributes
        ValueMap attrValueMap;
        attrValueMap[RichText::KEY_TEXT_LINE] = RichText::VALUE_TEXT_LINE_UNDER;
        if (tagAttrValueMap.find("color") != tagAttrValueMap.end()) {
            attrValueMap[RichText::KEY_TEXT_LINE_COLOR] = tagAttrValueMap.at("color").asString();
        }
        if (tagAttrValueMap.find("size") != tagAttrValueMap.end()) {
            attrValueMap[RichText::KEY_TEXT_LINE_SIZE] = tagAttrValueMap.at("size").asString();
        }
        return make_pair(attrValueMap, nullptr);
    });

这里是添加 u 标识下 识别color和size 的实现部分。其中 KEY_TEXT_LINE_COLOR 和 KEY_TEXT_LINE_SIZE 自行添加 在 KEY_TEXT_LINE 下面。

const std::string RichText::KEY_TEXT_LINE_COLOR("KEY_TEXT_LINE_COLOR");
const std::string RichText::KEY_TEXT_LINE_SIZE("KEY_TEXT_LINE_SIZE");

既然在 MyXMLVisitor 中 那就把在此需要添加的加完。在 struct Attributes 中添加

Color3B underlineColor;                   /*!< the color of the underline */
int underlineSize;                        /*!< the underline effect size value */

在下面 public 函数中添加

std::tuple<bool, Color3B, int> getUnderline() const;

实现如下

std::tuple<bool, Color3B, int>MyXMLVisitor::getUnderline() const
{
    for (auto i = _fontElements.rbegin(), iRend = _fontElements.rend(); i != iRend; ++i)
    {
        if (i->line == StyleLine::UNDERLINE)
        {
            return std::make_tuple(true, i->underlineColor, i->underlineSize);
        }
    }
    return std::make_tuple(false, Color3B::WHITE, -1);

}

 在 MyXMLVisitor::startElement 函数。 在 

keyTextLine == RichText::VALUE_TEXT_LINE_UNDER 和

 keyTextStyle == RichText::VALUE_TEXT_LINE_UNDER 判断下替换以下代码

attributes.line = StyleLine::UNDERLINE;
if (attrValueMap.find(RichText::KEY_TEXT_LINE_COLOR) != attrValueMap.end()) {
    attributes.underlineColor = _richText->color3BWithString(attrValueMap.at(RichText::KEY_TEXT_LINE_COLOR).asString());
}
if (attrValueMap.find(RichText::KEY_TEXT_LINE_SIZE) != attrValueMap.end()) {
                            attributes.underlineSize = attrValueMap.at(RichText::KEY_TEXT_LINE_SIZE).asInt();
}

在 MyXMLVisitor::textHandler下改变这句代码 后面两个是我自己加的。

auto element = RichElementText::create(0, color, 255, text, face, fontSize, flags, url,
        std::get<1>(outline), std::get<2>(outline),
        std::get<1>(shadow), std::get<2>(shadow), std::get<3>(shadow),
        std::get<1>(glow),
        std::get<1>(underline), std::get<2>(underline));

 然后在这两个函数 RichElementText::create、RichElementText::init 中作修改。

RichElementText* RichElementText::create(int tag, const Color3B &color, GLubyte opacity, const std::string& text,

                                         const std::string& fontName, float fontSize, uint32_t flags, const std::string& url,

                                         const Color3B& outlineColor, int outlineSize ,

                                         const Color3B& shadowColor, const cocos2d::Size& shadowOffset, int shadowBlurRadius,

                                         const Color3B& glowColor,

                                         const Color3B& underlineColor, int underlineSize)

{

    RichElementText* element = new (std::nothrow) RichElementText();

    if (element && element->init(tag, color, opacity, text, fontName, fontSize, flags, url,

                                 outlineColor, outlineSize, shadowColor, shadowOffset, shadowBlurRadius, glowColor, underlineColor, underlineSize))

    {

        element->autorelease();

        return element;

    }

    CC_SAFE_DELETE(element);

    return nullptr;

}

    

bool RichElementText::init(int tag, const Color3B &color, GLubyte opacity, const std::string& text,

                           const std::string& fontName, float fontSize, uint32_t flags, const std::string& url,

                           const Color3B& outlineColor, int outlineSize ,

                           const Color3B& shadowColor, const cocos2d::Size& shadowOffset, int shadowBlurRadius,

                           const Color3B& glowColor,

                            const Color3B& underlineColor, int underlineSize)

{

    if (RichElement::init(tag, color, opacity))

    {

        _text = text;

        _fontName = fontName;

        _fontSize = fontSize;

        _flags = flags;

        _url = url;

        _outlineColor = outlineColor;

        _outlineSize = outlineSize;

        _shadowColor = shadowColor;

        _shadowOffset = shadowOffset;

        _shadowBlurRadius = shadowBlurRadius;

        _glowColor = glowColor;

        _underlineColor = underlineColor;

        _underlineSize = underlineSize;

        return true;

    }

    return false;

}

这是我修改后的。 

接下来 在 formatText 函数中 的 判断 if (elmtText->_flags & RichElementText::UNDERLINE_FLAG)下 改成

label->enableUnderline(Color4B(elmtText->_underlineColor), elmtText->_underlineSize);

case RichElement::Type::TEXT: 这个条件下改成

RichElementText* elmtText = static_cast<RichElementText*>(element);
                        handleTextRenderer(elmtText->_text, elmtText->_fontName, elmtText->_fontSize, elmtText->_color,
                                           elmtText->_opacity, elmtText->_flags, elmtText->_url,
                                           elmtText->_outlineColor, elmtText->_outlineSize,
                                           elmtText->_shadowColor, elmtText->_shadowOffset, elmtText->_shadowBlurRadius,
                                           elmtText->_glowColor,
                                           elmtText->_underlineColor, elmtText->_underlineSize);
                        break;

在 handleTextRenderer 中修改如下

void RichText::handleTextRenderer(const std::string& text, const std::string& fontName, float fontSize, const Color3B &color,
                                  GLubyte opacity, uint32_t flags, const std::string& url,
                                  const Color3B& outlineColor, int outlineSize ,
                                  const Color3B& shadowColor, const Size& shadowOffset, int shadowBlurRadius,
                                  const Color3B& glowColor,
                                  const Color3B& underlineColor, int  underlineSize)
if (flags & RichElementText::UNDERLINE_FLAG)
                textRenderer->enableUnderline(Color4B(underlineColor), underlineSize);

CCLabel修改

Label::reset() 中添加

_underlineColor = Color4B::WHITE;
_underlineSize = -1;

 enableUnderline 中为

void Label::enableUnderline(const Color4B& underlineColor, int underlineSize)
{
    // remove it, just in case to prevent adding two or more
    if (!_underlineNode)
    {
        _underlineNode = DrawNode::create();
        addChild(_underlineNode, 100000);
        _contentDirty = true;

        _underlineColor = underlineColor;
        if (underlineSize > 0)
        {
            _underlineSize = underlineSize;
        }
        
    }
}

updateContent 这个函数中的修改部分 两个地方。

// Github issue #15214. Uses _displayedColor instead of _textColor for the underline.
// This is to have the same behavior of SystemFonts.
Color4F Linecolor = _underlineColor != Color4B::WHITE ? Color4F(_underlineColor) : Color4F(_displayedColor);
 _underlineNode->drawLine(Vec2(_linesOffsetX[i], y), Vec2(_linesWidth[i] + _linesOffsetX[i], y), Linecolor);

 lua_cocos2dx_auto

lua_cocos2dx_Label_enableUnderline 部分

int lua_cocos2dx_Label_enableUnderline(lua_State* tolua_S)
{
    int argc = 0;
    cocos2d::Label* cobj = nullptr;
    bool ok  = true;

#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif


#if COCOS2D_DEBUG >= 1
    if (!tolua_isusertype(tolua_S,1,"cc.Label",0,&tolua_err)) goto tolua_lerror;
#endif

    cobj = (cocos2d::Label*)tolua_tousertype(tolua_S,1,0);

#if COCOS2D_DEBUG >= 1
    if (!cobj) 
    {
        tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
        return 0;
    }
#endif

    argc = lua_gettop(tolua_S)-1;
    if (argc == 0)
    {
        if(!ok)
        {
            tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
            return 0;
        }
        cobj->enableUnderline();
        lua_settop(tolua_S, 1);
        return 1;
    }
    if (argc == 1)
    {
        cocos2d::Color4B arg0;

        ok &= luaval_to_color4b(tolua_S, 2, &arg0, "cc.Label:enableUnderline");
        if (!ok)
        {
            tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
            return 0;
        }
        cobj->enableOutline(arg0);
        lua_settop(tolua_S, 1);
        return 1;
    }
    if (argc == 2)
    {
        cocos2d::Color4B arg0;
        int arg1;

        ok &= luaval_to_color4b(tolua_S, 2, &arg0, "cc.Label:enableUnderline");

        ok &= luaval_to_int32(tolua_S, 3, (int*)&arg1, "cc.Label:enableUnderline");
        if (!ok)
        {
            tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
            return 0;
        }
        cobj->enableOutline(arg0, arg1);
        lua_settop(tolua_S, 1);
        return 1;
    }
    luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Label:enableUnderline",argc, 0);
    return 0;

#if COCOS2D_DEBUG >= 1
    tolua_lerror:
    tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Label_enableUnderline'.",&tolua_err);
#endif

    return 0;
}

lua_cocos2dx_ui_RichElementText_init 和 lua_cocos2dx_ui_RichElementText_create 这些并没有做修改。方便使用XML 创建的UIRichText 方式设置下划线颜色 。不过您可以通过enableUnderline 函数去实现改变需要颜色和宽度。 至于其他您可以自己把 lua_cocos2dx_ui_RichElementText_init 和 lua_cocos2dx_ui_RichElementText_create 这个完善。

大概就这样了。本来不想写完的直接上代码。但是坚持把。谢谢阅读!!!

我怕遗漏!所修改资源文件已上传关联资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值