PDA

View Full Version : Something weird from ScrollComponent since last svn update 774



osgoz
02-29-2012, 11:53 AM
Hi all.

Well, for my application I need a "ListItemView" structure to show a list of photos to select one of.
I create the "ListItemView" thing following RTSimpleApp code.
Then I fill it with my own data like this:


void Fill(Entity *pParent)
{
Entity *pScroll = pParent->GetEntityByName("scroll");
CL_Vec2f vTextBoxPos = pScroll->GetVar("pos2d")->GetVector2();
CL_Vec2f vTextBounds = pScroll->GetVar("size2d")->GetVector2();

CL_Vec2f vRealSize = vTextBounds - vTextBoxPos;
//here we add our actual content we want scrolled. At the end, we'll calculate the size used using ResizeScrollBounds and the scroll bars
//can update. If you are adding content over time, (like, downloading highscores or whatever) it's ok to call ResizeScrollBounds
//repeatedly to dynamically resize the scroll area as you go.

pParent = pParent->GetEntityByName("scroll_child");
pParent->RemoveAllEntities(); //clear it out in case we call this more than once, say, to update/change something

float x = 4; //inset
float y = 4;
float spacerY = 4; //space between thingies
float spacerX = 4;

CL_Vec2f fotosize;

//define an area for a text box, so it will wrap in the right places. Height is actually ignored.
// CL_Vec2f vTextBoxPos(x,y);
// CL_Vec2f vTextBounds(434, 200);
// string msg; //we could load text, but let's just manually put junk in there:

string sPhotoName;
string sPhoto;
int c = 0;

while(c < 10){
sPhotoName ="Photo" + char(c+48);
sPhoto = (string)"Lib/Photos/" + sPhotoName + (string)".jpg";
Entity* ppito = CreateOverlayButtonEntity(pParent,sPhotoName,sPhot o,x,y);

ppito->GetShared()->GetFunction("OnButtonSelected")->sig_function.connect(&OnListBoxDClick);

fotosize = ppito->GetVar("size2d")->GetVector2();
x += fotosize.x;
x += spacerX;
if((x + fotosize.x) > vRealSize.x){
x = 4;
y += fotosize.y + spacerY;
}
c++;
}

//actually create the text box with the above text


//do something if someone clicks it

//automatically calculate the total size of this entity with all its children for the scroll bars, do this at the end
VariantList vList(pScroll);
ResizeScrollBounds(&vList);
}


I connect each "Item" to "OnListBoxDClick" function to perform the process of simulate click and select of the "item".
Well, all this works fine until I updated the SDK from svn to 774 version.
Since then, no "Item" can be clicked, that is, the "OnListBoxDClick" function does not calling anymore.

What am I doing wrong?
Is there a better way of doing it?

Regards.

Aki Koskinen
03-01-2012, 08:12 AM
You don't seem to be setting the button style anywhere in the pasted code. Do you call the

SetDefaultButtonStyle(Button2DComponent::eButtonSt yle style);
method somewhere and what do you pass there?

There was a new button style BUTTON_STYLE_CLICK_ON_TOUCH_PRESS_RELEASE introduced recently and it doesn't work inside scroll areas very nicely exactly in situations that you describe.

RTSimpleApp has a clickable button inside a scroll area: the Proton logo in the about screen. Does that work for you (just tried it and it works here). Your code looks pretty similar to that code so I can't immediately think of anything else than the button style.

osgoz
03-01-2012, 09:08 AM
Thanks for your replay.

No I does not calling that function anywhere in my code.
But I just think by default the buttons were BUTTON_STYLE_CLICK_ON_TOUCH.
Anyway I put this line of code
SetDefaultButtonStyle(Button2DComponent::BUTTON_ST YLE_CLICK_ON_TOUCH_RELEASE);
in MainMenuCreate() function and nothing diferent happens.
I noticed something strange yesterday:
If I create the "ListView" 2 times, the second time works ok, like before 774 update.
But the code is the same the 2 times, so I can not see whats going wrong.

And yes the button with the Proton Logo on RTSimpleApp works ok for me, and I do the same in my application.

Regards.

Seth
03-01-2012, 09:23 AM
Hmm, do you have the line pScrollComp->GetVar("fingerTracking")->Set(uint32(1)); when you setup the scroll component?

Try removing that!

Also, I just put an improved ScrollComponent on svn, but it just changes it so when it detects a scroll (instead of a tap) it will stop sending events to the children.

osgoz
03-01-2012, 09:33 AM
Thanks for your replay.

Yes I have that line, but I commented it and nothing happens again.

This is my code for creating the "ListView"


Entity* CreateListBox(Entity *pParent,const CL_Vec2f& pos,const CL_Vec2f& size,const uint32& BackColor)
{
Entity *pBG = NULL;
CL_Rectf rect(pos,size);
pBG = CreateOverlayRectEntity(pParent, rect,BackColor,RectRenderComponent::STYLE_3D);
AddFocusIfNeeded(pBG);
pBG->AddComponent(new FocusRenderComponent);

//setup the dimensions of where the scroll area will go
CL_Vec2f vTextAreaPos = CL_Vec2f(2,2);
float offsetFromBottom = 2.0f;
float offsetFromRight = 6.0f;
CL_Vec2f vTextAreaBounds = (size - CL_Vec2f(offsetFromRight,offsetFromBottom))-vTextAreaPos;

Entity *pScroll = pBG->AddEntity(new Entity("scroll"));
//pScroll->GetVar("pos2d")->Set(pos);
pScroll->GetVar("pos2d")->Set(vTextAreaPos);//la posición es relativa al padre.
pScroll->GetVar("size2d")->Set(vTextAreaBounds);
pScroll->AddComponent(new TouchHandlerComponent);

EntityComponent *pScrollComp = pScroll->AddComponent(new ScrollComponent);

//turn on finger tracking enforcement, it means it will mark the tap as "handled" when touched. Doesn't make a difference here,
//but good to know about in some cases. (some entity types will ignore touches if they've been marked as "Handled")

//pScrollComp->GetVar("fingerTracking")->Set(uint32(1));

//note: If you don't want to see a scroll bar progress indicator, comment out the next line. Also note that it only draws
//a vertical progress bar if needed but doesn't draw a horizontal if needed (I just haven't needed a horizontal scroll bar yet)
EntityComponent *pScrollBarComp = pScroll->AddComponent(new ScrollBarRenderComponent); //add a visual way to see the scroller position

//if we wanted to change the scroll bar color we could do it this way:
pScroll->GetVar("color")->Set(MAKE_RGBA(80,80, 80, 255));

Entity *pScrollChild = pScroll->AddEntity(new Entity("scroll_child"));

pScroll->AddComponent(new RenderScissorComponent()); //so the text/etc won't get drawn outside our scroll box

//actually add all our content that we'll be scrolling (if there is too much for one screen), as much as we want, any kind of entities ok
//AboutMenuAddScrollContent(pBG);

return pBG;
}


As you can see, is a copy/paste from your code.

Regards.

Seth
03-01-2012, 10:00 AM
Well, everything looks right - although I see one possible issue:


void Fill(Entity *pParent)
{
Entity *pScroll = pParent->GetEntityByName("scroll");
...
pParent = pParent->GetEntityByName("scroll_child");
...


Is it possible you have more than one entity named "scroll" and it's grabbing and adding to the wrong one or something like that?

A way to check is after creating everything, do:


GetEntityRoot()->PrintTreeAsText();

And compare that to after you run it the second time - look for any differences in the one that worked.

In the latest version of RTSimpleApp I do it a bit safer way to avoid the possible naming problem:



void AboutMenuAddScrollContent(Entity *pParent)
{
//here we add our actual content we want scrolled. At the end, we'll calculate the size used using ResizeScrollBounds and the scroll bars
//can update. If you are adding content over time, (like, downloading highscores or whatever) it's ok to call ResizeScrollBounds
//repeatedly to dynamically resize the scroll area as you go.

pParent = pParent->GetEntityByName("scroll_child");

osgoz
03-01-2012, 10:51 AM
Ok.
I have done what you pointed and the result is the same.

Here goes the GetEntityRoot()->PrintTreeAsText(); output for the 2 runs because are the same.
Perhaps you can see something wrong on it.



BG (OverlayRender)
(RectRender, FocusRender)
scroll (TouchHandler, Scroll, FilterInput, ScrollBarRender, RenderScissor)
scroll_child
Ventana1 (OverlayRender, TouchHandler, Button2D)
Ventana2 (OverlayRender, TouchHandler, Button2D)
Ventana3 (OverlayRender, TouchHandler, Button2D)
Ventana4 (OverlayRender, TouchHandler, Button2D)
Ventana5 (OverlayRender, TouchHandler, Button2D)


Regards.

Seth
03-01-2012, 12:01 PM
Ah-hah! First thing I noticed is you have a FocusRender but no FocusInput or FocusUpdate components! That's gotta be the problem - it can draw everything, but nothing else, zero input is being processed.

Instead of


pBG->AddComponent(new FocusRenderComponent);


do:

AddFocusIfNeeded(pBG);

(internally, it just adds FocusRenderComponent as well as the other two, if it can't locate them.. )

That will probably fix it.

RTSimpleExample actually does it this way:


AddFocusIfNeeded(pBG, true, 500);
pBG->AddComponent(new FocusRenderComponent);


Well, it's a little weird, basically this says, "turn on rendering now, but don't add the input or update components (if they are needed.. it walks up the hierarchy to see if they already exist) for 500 ms". I think that was to wait for the LAST menu to have time to transition off the screen, and I didn't want people pushing the previous menu's buttons while it was leaving, so the last menu probably killed Input and Update before making this scrolling menu. Sort of unnecessarily complex.

However, I probably should have just called DisableAllButtonsEntity(pMenuThatWeAreKilling); and then I wouldn't have had to worry about it.

osgoz
03-01-2012, 03:42 PM
Thank you very much for your patience.

After following your idea I obtain this.


Dlg(FocusUpdate, FocusInput)
CAP (OverlayRender)
BG (OverlayRender)
(RectRender)
scroll (TouchHandler, Scroll, FilterInput, ScrollBarRender, RenderScissor)
scroll_child
Ventana1 (OverlayRender, TouchHandler, Button2D)
Ventana2 (OverlayRender, TouchHandler, Button2D)
Ventana3 (OverlayRender, TouchHandler, Button2D)
Ventana4 (OverlayRender, TouchHandler, Button2D)
Ventana5 (OverlayRender, TouchHandler, Button2D)
Ventana6 (OverlayRender, TouchHandler, Button2D)
Ventana7 (OverlayRender, TouchHandler, Button2D)
Ventana8 (OverlayRender, TouchHandler, Button2D)
Ventana9 (OverlayRender, TouchHandler, Button2D)
...


I will explain it better in behave it will help us.
I am trying to show something near a modal dialog with a "listview" and a pair of edit boxes and a pair of buttons.
In the text above, Dlg is create like this:


m_pDlg = pParentEnt->AddEntity(new Entity("Dlg"));

AddFocusIfNeeded(m_pDlg,true,500);
m_pDlg->AddComponent(new FocusInputComponent);

CL_Vec2f pos((GetScreenSizeXf()-size.x)*.5f,10);

Entity *pListBox = CreateListBox(m_pDlg,CL_Vec2f(pos.x + 8,pos.y + 34),CL_Vec2f(684.0f,310.0f));
...


And then m_pDlg is the parent of my "Listview"
CAP and BG are the caption image and the background image of the simulated dialog.

As you can see I managed to get a "FocusInput" but nothing new happened.
Still the first time this code does not work, but second run works "magicaly" :(

I know that is something that I do before or after calling the create dialog function. But I don't understand what it is and what change from one version of svn to another to make it work and not work in the same day.

Regards

Seth
03-02-2012, 02:01 AM
Dlg(FocusUpdate, FocusInput)
CAP (OverlayRender)
BG (OverlayRender)
(RectRender)
scroll (TouchHandler, Scroll, FilterInput, ScrollBarRender, RenderScissor)
scroll_child
Ventana1 (OverlayRender, TouchHandler, Button2D)
Ventana2 (OverlayRender, TouchHandler, Button2D)
Ventana3 (OverlayRender, TouchHandler, Button2D)
Ventana4 (OverlayRender, TouchHandler, Button2D)
Ventana5 (OverlayRender, TouchHandler, Button2D)
Ventana6 (OverlayRender, TouchHandler, Button2D)
Ventana7 (OverlayRender, TouchHandler, Button2D)
Ventana8 (OverlayRender, TouchHandler, Button2D)
Ventana9 (OverlayRender, TouchHandler, Button2D)

Hmm, wait, now I don't see a FocusRender component in your list.. ?

I really don't see anything wrong in the code you pasted, but it could have something to do with when you are calling your Fill() function, since I don't see that being called anywhere. ( //AboutMenuAddScrollContent(pBG); is where the example would have called that)

I can only suggest starting with the RTSimpleApp and slowly start changing it, I suspect the error is in some other part of the code. :sweatdrop:

Debugging Proton is a bit tricky, but you can get out your debugger and see if TouchHandlerComponent::HandleClickStart is getting hit, and when it does, look at its m_pParent and you can see the entity name it is owned by. If you keep doing that, youll see every entity that sees the click.

osgoz
03-02-2012, 08:54 AM
I found it.
And, like the other time, it's my fault.
The problem was in the Fill function like you said:


Entity* ppito = CreateOverlayButtonEntity(pParent,sPhotoName,sPhot o,x,y);

OverlayRenderComponent* pComp = (OverlayRenderComponent*)ppito->GetComponentByName("OverlayRender");
if(pComp)
pComp->SetSurface(GetResourceManager()->GetSurfaceAnim(sPhoto,false),false);

ppito->GetShared()->GetFunction("OnButtonSelected")->sig_function.connect(&OnListBoxDClick);


This are the lines of code that put the item image in position.
The problem is that sPhoto does not had a valid path + filename, so CreateOverlayButtonEntity creates the entity but the size is (0,0) because the image does not found.
So them I change the image manually with the OverlayRenderComponent but the size of the button is (0,0) so I can not click on it.
The second time that runs this code, the size of the OverlayButtonEntity is correct because it just been initialized in the first run,so I can click on it without problem.
I solve the problem filling up the sPhoto with an empty texture of the size of the correct one, so once I call OvelayRenderComponent()->SetSurface(...), just have the correct size and it works.

This does not explain why it worked fine in the morning and after updating svn it does not work in afternoon.

I do apologies for make you loose your time again :sweatdrop:

Seth
03-02-2012, 09:57 AM
Thanks for letting me know - and actually, that is a Proton bug.. the way you did it originally should have also worked.

Info on my bug (just in case anybody cares):


In OverlayRenderComponent::SetSurface, it sets the new texture size like this:

*m_pSize2d = <the new size>;

Now, that's works, but when doing this method, nobody who "subscribed" to get notified when the size changes gets notified.

The TouchHandler component DOES subscribe:


GetParent()->GetVar("size2d")->GetSigOnChanged()->connect(boost::bind(&TouchHandlerComponent::UpdateTouchArea, this, _1));

And thus, it still thinks the touch area is 0,0, causing the bug.

So by changing to this:

GetParent()->GetVar("size2d")->Set( <the new size>);

All will work correctly! I'll svn the fix soonish.

Aki Koskinen
03-02-2012, 10:11 PM
Info on my bug (just in case anybody cares):


In OverlayRenderComponent::SetSurface, it sets the new texture size like this:

*m_pSize2d = <the new size>;

Now, that's works, but when doing this method, nobody who "subscribed" to get notified when the size changes gets notified.

The TouchHandler component DOES subscribe:


GetParent()->GetVar("size2d")->GetSigOnChanged()->connect(boost::bind(&TouchHandlerComponent::UpdateTouchArea, this, _1));

And thus, it still thinks the touch area is 0,0, causing the bug.

So by changing to this:

GetParent()->GetVar("size2d")->Set( <the new size>);

All will work correctly! I'll svn the fix soonish.

Hmm, yes. I guess it was my commit that originally changed this. Seems I didn't thoroughly test it :whistling:

A follow-up question (to Seth mostly):

Should Variant::­operator=() actually send the signal? So when it gets reassigned through operator=() all who are subscribed for changes would get notified. The thing with operator=() seems to be that it can change the type of the Variant and all other contents of it. I don't know in what situations the operator=() is supposed to be used really...

Anyway, I think there's a potential memory leak in Variant::­operator=(): it sets m_pSig_onChanged to NULL without deleting it first. All who have potentially subscribed for change notifications are forever left hanging...

Seth
03-03-2012, 12:22 AM
Hmm, yes. I guess it was my commit that originally changed this. Seems I didn't thoroughly test it

Don't think so, looks like it's been there since the initial commit in 401.. :whistling: And I also just noticed the same error in OnFileNameChanged and OnScaleChanged and SetupAnim.. oops! I'll see if I can cleanup the code a bit, maybe I can do everything in UpdateFrameSizeVar() and get rid of the duplication.

Seth
03-03-2012, 12:39 AM
A follow-up question (to Seth mostly):

Should Variant::­operator=() actually send the signal? So when it gets reassigned through operator=() all who are subscribed for changes would get notified. The thing with operator=() seems to be that it can change the type of the Variant and all other contents of it. I don't know in what situations the operator=() is supposed to be used really...

Anyway, I think there's a potential memory leak in Variant::­operator=(): it sets m_pSig_onChanged to NULL without deleting it first. All who have potentially subscribed for change notifications are forever left hanging...

Oops, forgot about this.

Hmm.. good questions.. I guess we should not kill the m_pSig_onChanged and go ahead and send a changed signal in that case?? Maybe I'll try that and see if anything breaks. :sweatdrop:

Figuring it out as we go.. :sweatdrop:

Seth
03-03-2012, 04:36 AM
Ok, committed the various fixes. Let me know if anything seems broke!

osgoz
03-05-2012, 08:11 AM
Hello all.

Ok, thank you very much for your interest.
I had two other problems. Rare stacks overflows that I was having in random times.
I have updated and tested all things that I have noticed and now, it does not crash anymore, and all runs smoothly.
I will continue testing.

Regards.