The getBoundingBox() of LabelTTF does not work properly.How to solve it?

The rectangle returned from the getBoundingBox() of LabelTTF always locate at the Left-down corner in the program.(the cocos2dx version 3.2)

Recently, I define an object of LabelTTF, and I want to reposition the text when I click it.(In the platform of Win32).So I replace the code of the HelloWorld’s init() with the following code:

if ( !Layer::init() )
    {
        return false;
    }
Size visibleSize = Director::getInstance()->getVisibleSize();
LabelTTF* tf = LabelTTF::create("Change Position", "Mv boli", 30);
tf->setPosition(visibleSize.width / 2, visibleSize.height / 2);
this->addChild(tf);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = \[tf](Touch* touch, Event* event)->bool{
if (tf->getBoundingBox().containsPoint(touch->getLocation()))
{
//My Wnd Size is 800 x 600
tf->setPosition(rand() % 800, rand() % 600);
}
return false;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(
listener, tf);
return true;

When I built the project ,I found that only when I click the Left-down corner of the program,can the text change it’s position.
But when I replaced the class type from LabelTTF to TextfieldTTF. It could work !!

The code aboved can work correctly in the version of 3.0 beta 2, 3.0 rc0. But failed in ver 3.2.
I am new to Cocos2dx. How to solve it?

1 Like

You forgot return true; after tf->setPosition(rand() % 800, rand() % 600);
Without it, the event will never be cosumed, as you fall through your conditional:

if (tf->getBoundingBox().containsPoint(touch->getLocation()))
{
    //My Wnd Size is 800 x 600
    tf->setPosition(rand() % 800, rand() % 600);  
    return true;
}
return false;

You also have to convert your coordinates to node space, and you might should get the node the event occured on, instead of hard coding the node itself.

auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = \[tf](Touch* touch, Event* event)->bool{

    // event->getCurrentTarget() returns the *listener's* sceneGraphPriority node.
    LabelTTF *target = static_cast<LabelTTF*>(event->getCurrentTarget());

    // get the position of the current point relative to the button
    Point locationInNode = target->convertToNodeSpace(touch->getLocation());

    Size s = target->getContentSize();
    Rect rect = Rect(0, 0, s.width, s.height);

    if (rect.containsPoint(locationInNode)))
    {
        //My Wnd Size is 800 x 600
        target->setPosition(rand() % 800, rand() % 600);

       return true;
    }

    return false;
};

Thanks for your reply.With the code you gave, the program ran correctly.

But there is still a problem with my code.Though I add the “return true” statement after the “tf->setPosition(rand() % 800, rand() % 600);” , it still can not work .(the version of cocos2dx is 3.2)

Besides , without that “return true” statement, my code can run well in the version 3.0rc0.

What confuses me is the same code but two different results I got.

The return true; statement just ensures, that your touch is consumed. If there was a node underneath your label with an attached listener, it would have also received that touch. By returning true, it swallows the touch on the label and does not forward it to the other listener.
If you want the underlying node to also receive the touch, don’t return true. As you only have one listeners, it does not make a difference. So in your situation it works the same way, regardless of returning true or false.

Regarding the different results: log the coordinates of the touch and the bounding box of your label. Are they any different?
If they are, there must have been some bugfix/change.

I actually came here to report the same problem. I had some Label code running properly with wrapping and all until very recently, I would say in the last week of commits. This is my code that is no longer working:

auto label = createLabel(24.f,
                         Vec2(KDScreenContent::ContentSize.width / 2,
                              KDScreenContent::ContentSize.height / 2),
                         "Please login to enable ranked matches");

label->setDimensions(KDScreenContent::ContentSize.width,
                     KDScreenContent::ContentSize.height);

return label;

Old result:

New result:

Thanks,

I used the MessageBox func to output the information. Maybe it is really a bug because the bounding box’s position is differrent during different Cocos2dx version. I have made a feedback to report it.

And thanks for iQD 's great help.

Same code,but two different results in different version:

It seems they changed a few things. Maybe in favor for LabelTTF and LabelAtlas. May you should try them instead.
Label itself is slow compared to the other ones, if you change the text alot, as it has to recreate the glyphs.

I can’t tell, if those changes were on purpose or not.

Happy to help :smile:.

I checked out the 3.0 RC0 and compared the code.
Yeah, they have some bugs/features there :smile:

In all versions, LabelTTF has a label object embedded.as a child.

In RC0 they returned the node itself, the parent, as bounding box.
That’s why your code works with those old versions.

In the newer versions they return the bounding box of the embedded label, without assigning the location of the LabelTTF parent node to the child. So in fact it returns the child. As the child is at the left corner of the parent, its location is 0,0 and that is why you get a bounding box at location 0,0.

As you are checking against that bounding box, the touch works when clicking into the left bottom corner.

Maybe they did that on purpose, cause you should always convert the touch to the node space, so it will be translated to the child itself.

The code I posted is how you should implement it.

Thanks, I am aware of the restrictions of using Label. I don’t really want to create a bitmap font, I have to support many languages, and the text is static :wink:

The issue is that LabelTTF is deprecated, and the issue seems related, but not quite there maybe… I will investigate further.

LabelTTF does only aligning, if a FontAtlas is defined:

void Label::alignText()
{
    if (_fontAtlas == nullptr)
    {
        return;
    }

May they changed it, cause it is a performance hog.
So you need to make a FontAtlas.

Do you need auto wrap or do just want to explicitly make a line break?

I don’t really want to create a bitmap font, I have to support many languages, and the text is static :wink:

Well, then a Bitmap Atlas is the ideal solution. You can even change the language throughout the game, without a huge performance hog or also (async) pre load the static texts. Also different sizes? Even better then :smile:

1 Like

OK,copy that,thanks a lot :smile: