PDA

View Full Version : How can I create a Rect + Text button?



BigBMan
07-27-2011, 06:06 AM
Trying to figure this out, but running into all kinds of problems. Any ideas?



Entity * CreateRectButtonEntity(Entity *pParentEnt, string name, float x, float y, string text)
{
Entity *pEnt = pParentEnt->AddEntity(new Entity(name));
pEnt->GetVar("pos2d")->Set(x, y);

Entity* pTextEnt = CreateTextLabelEntity(pEnt, name + "Text", x, y, text);
pTextEnt->GetVar("color")->Set(MAKE_RGBA(255,0,0,200));

Entity* pRectEnt = pEnt->AddEntity(new Entity(new RectRenderComponent()));
pTextEnt->GetVar("color")->Set(MAKE_RGBA(0,255,0,200));

pEnt->AddComponent(new TouchHandlerComponent);
pEnt->AddComponent(new Button2DComponent);

AddFocusIfNeeded(pEnt);

return pEnt;
}

Seth
07-27-2011, 06:52 AM
:ninja::excl: A-hah, two things wrong I can see:


The rect entity won't draw because its entity (a child of pEnt) still would have 0,0 as its size. If you manually set that, it will draw

The touchhandler/button components were given to pEnt, which also has 0,0 as the size, so the button cannot be clicked. (entities don't inherit size from their parents.. so in the above code, only the text entity (pTextEnt) has a non 0 size

Try this version with that stuff fixed, also I have it move the rectangle entity to the "bottom" so it draws first, otherwise it will draw over the text.

Note that I'm attaching the button/touch stuff to the rectangle itself, so it will be the rectangle and not the text that highlights when depressed.



Entity * CreateRectButtonEntity(Entity *pParentEnt, string name, float x, float y, string text)
{
Entity *pEnt = pParentEnt->AddEntity(new Entity(name));
pEnt->GetVar("pos2d")->Set(x, y);


Entity* pTextEnt = CreateTextLabelEntity(pEnt, name + "Text", 0, 0, text);
pTextEnt->GetVar("color")->Set(MAKE_RGBA(255,0,0,200));

Entity* pRectEnt = pEnt->AddEntity(new Entity(new RectRenderComponent()));
pRectEnt->GetVar("color")->Set(MAKE_RGBA(0,255,0,200));

//get the size of the text
CL_Vec2f vRectSize = pTextEnt->GetVar("size2d")->GetVector2();
pRectEnt->GetVar("size2d")->Set(vRectSize);

//that works, but the rect is drawn AFTER the text, we want it drawn before. Move the rect ent to draw first:
pEnt->MoveEntityToBottomByAddress(pRectEnt);
pRectEnt->AddComponent(new TouchHandlerComponent);
pRectEnt->AddComponent(new Button2DComponent);

AddFocusIfNeeded(pEnt);

return pEnt;
}

BigBMan
07-27-2011, 04:29 PM
Thanks! What if I want to highlight both the rect and the text? Background color?

BigBMan
07-28-2011, 02:42 AM
Also, how could I tie "OnButtonSelected" in the pRectEnt to the parent Entity that is returned?

Seth
07-29-2011, 07:38 AM
Also, how could I tie "OnButtonSelected" in the pRectEnt to the parent Entity that is returned?
Thanks! What if I want to highlight both the rect and the text? Background color?


Ok, here is a way to do all of that I think (sorry for the slow reply.. been busy, and I don't like to answer until I can sit down and actually test code) ... notice that I'm doing a new technique here, I'm causing my own custom global function to be run by the button when it's clicked, to change colors. This gives you a lot more flexibility with setting colors/bounces, etc.



void ButtonColorTint(VariantList *pVList)
{
Entity *pRectEnt = pVList->Get(1).GetEntity(); //index 1 is the entity who sent it, index 0 would be a Vector2d of the click position
//PulsateColorEntity(pRectEnt, false, MAKE_RGBA(255,0,0,255)); //for a pulsating effect..

//extra little visual effect, have it bob when clicked
OneTimeBobEntity(pRectEnt->GetParent(), -20, 0, 300);

uint32 originalColor = pRectEnt->GetVar("color")->GetUINT32();
//set the rect to red.. we hardcode it, but we could have just read it from a parm setting in the entity,
//assuming we knew to set it somewhere
GetMessageManager()->SetEntityVariable(pRectEnt, 0, "color", MAKE_RGBA(255,0,0,255));

//set back to whatever it was originally in 300 ms
GetMessageManager()->SetEntityVariable(pRectEnt, 300, "color", originalColor);
}

Entity * CreateRectButtonEntity(Entity *pParentEnt, string name, float x, float y, string text)
{
Entity *pEnt = pParentEnt->AddEntity(new Entity(name));
pEnt->GetVar("pos2d")->Set(x, y);

Entity* pTextEnt = CreateTextLabelEntity(pEnt, "Text", 0, 0, text);
pTextEnt->GetVar("color")->Set(MAKE_RGBA(255,0,0,200));

Entity* pRectEnt = pEnt->AddEntity(new Entity(name, new RectRenderComponent()));
pRectEnt->GetVar("color")->Set(MAKE_RGBA(0,255,0,200));

//get the size of the text
CL_Vec2f vRectSize = pTextEnt->GetVar("size2d")->GetVector2();
pRectEnt->GetVar("size2d")->Set(vRectSize);

//that works, but the rect is drawn AFTER the text, we want it drawn before. Move the rect ent to draw first:
pEnt->MoveEntityToBottomByAddress(pRectEnt);
pRectEnt->AddComponent(new TouchHandlerComponent);
pRectEnt->AddComponent(new Button2DComponent);
AddFocusIfNeeded(pEnt);

//NEW STUFF:
//Let's turn the text into a button too, so it will highlight
pTextEnt->AddComponent(new TouchHandlerComponent);
pTextEnt->AddComponent(new Button2DComponent);

//wire pRectEnt getting a "OnButtonSelected" to also be called on its parent entity
pRectEnt->GetFunction("OnButtonSelected")->sig_function.connect(pEnt->GetFunction("OnButtonSelected")->sig_function);

//Oh, let's set the color tinting for when the button is pressed down.. we'll just have it call a custom function
//that will apply the changes, as Button2D doesn't have anything to do that
pRectEnt->GetFunction("OnButtonSelected")->sig_function.connect(&ButtonColorTint);
return pEnt;
}

A note though. You see this part where I wire the click from pRectEnt to also be broadcast from pEnt?


//wire pRectEnt getting a "OnButtonSelected" to also be called on its parent entity
pRectEnt->GetFunction("OnButtonSelected")->sig_function.connect(pEnt->GetFunction("OnButtonSelected")->sig_function);

It does work - and let's you setup the button like this:


Entity *pTestEnt = CreateRectButtonEntity(pBG, "ButtonName", 200, 30, "Testing 123");
//wire it to a button like normal
pTestEnt->GetFunction("OnButtonSelected")->sig_function.connect(&MainMenuOnSelect);

BUT: because internally it's being "forwarded" from the pRectEnt which actually generated the click, the pEntity it sends will be pRectEnt, not its parent (pEnt) which you hooked to. So where you process the click in "MainMenuOnSelect" you'd need to be aware that you need to do pEntity->GetParent() to get at the real parent entity of the button.

A better way to avoid confusion would be to redo things so the click really is generated by the pEnt (not a sub-entity) - either make that the rectangle, or set its size and put the touch/button2d components in that.

For the visual effects, you can just wire to your own custom function like I do above, the rect and text don't really need the Button2D/TouchInput stuff on them at all, as you can use the custom function technique above to set colors or any other effects.

BigBMan
08-01-2011, 10:43 PM
Thanks!

Seems like the better option at this point would be to create a RectButton component that renders everything as one component.