setText jolts TextButton at inital position for a microsecond or two while movement is happening - libgdx

I have an actor and I'm moving it by using moveTo(destinationx, destinationy, time).
The problem is that the actor is a TextButton and I need to change the text while the movement is happening and this poses a serious problem. It seems setText calls invalidate and invalidateHierarchy so when the method is called the position of the TextButton is reset to the initial position for a while so that the movement proceeds with a jolt (jump) of the text button position (position set at initialization - .center()).
All the dynamics of my actor movements are running as planned as long as I don't modify the text while Actions.moveTo is still running. If I do modify it then I see a jolt of the text at the moment I call setText.
How can I solve this pb?

I was able to reproduce your problem by placing a Button in a Table and using moveTo actions on the Button. The problem is that when a widget belongs to a Table, the Table is responsible for controlling the widget's position and size, so actions that affect the position will not work correctly.
If you are moving a widget around the screen to arbitrary positions, it doesn't make sense for you to keep it in a static Table anyway. If you add the Button directly to the stage, the problem goes away.
However, I discovered another problem. If the Button doesn't have a Table parent, it doesn't update its own size correctly when its text changes.
I found a solution. Place the Button in a Container and add the Container to the Stage. Use your MoveToActions on the Container that wraps the Button, not the Button itself.

Related

Added TableView to Sprite is not visible and all other Sprites are visible

I inherited Sprite and I want to put inside TableView but when I add inherited Sprite to scene table is not visible but all others sprites added to inherited sprite are visible ( I checked it creates cells, position and z index are set right, when I add TableView directly to Scene it is visible).
I'm able to add a TableView to a Sprite in Cocos2d-x v3.6, but it's a little hard to say exactly why yours isn't showing up. Here are some things to check:
Have you added the TableView as a child to the Sprite via addChild?
When you add the TableView to the Sprite, is your DataSource set properly? (This seems to be the case given your question).
Are there positioning issues when you add it to the Sprite due to the anchor position(s) of your Sprite and it's parent(s)? It could be the TableView with incorrect positioning, or it could be the TableViewCells themselves. Remember that when you add a child to some Node, its anchor point is Vec2(0.5, 0.5).
You're not forced to override cocos2d::Size cellSizeForTable(cocos2d::extension::TableView *table), and if you don't have cell heights, the cells might not show up.
Try "dumbing down" any logistics you have and follow the code in TableViewTestScene.cpp, which is part of the cpp-tests. (cocos-directory/tests/cpp-tests/Classes/ExtensionsTest/TableViewTest)
Last resort: Try doing something silly like giving your table and cells a large height and width of 500-1000 pixels each. Give them an absolute position somewhere in your Sprite. Give each of them a Label that says "Hello, World!" and see if they show up.
It might be helpful to see your applicable code, too.
A very late edit: I realized today that it seems as though Layer objects (and thus TableViews) always have an Anchor Point of Vec2::ANCHOR_BOTTOM_LEFT. Could this be your issue?

Object changing layer when going between frames?

I have a child of an object that stays on the scene when the frame changes. So I gotoAndStop(2); and the object is still there. However, when I come back to frame one. The object is on the lowest layer, despite the fact that I originally added it using addChildAt(character, 1); I think this adds it to the first layer? Anyone know how I can fix this issue of keeping a movieclip object on the top layer despite changing frames? Thanks.
In AS3/Flash, the bottom most layer is 0. So doing addChildAt(character, 1) would make your character the second to the bottom layer. addChildAt(character, 0) would make it the very bottom/back layer.
If you want to make it the top most layer, you do any one of the following:
addChild(character); //this is the shortest amount of code
addChildAt(character, numChildren-1); //the is exactly the same as above
setChildIndex(character, numChildren-1); //this is also the same but requires the character already be present on the display list
The latter (setChildIndex) may be preferred IF your character originates on the timeline (eg not created through code). The reason being, if you change through code the parentage of something created on the timeline, it will not go away when no longer present on the timeline.
If you want a way to force something to always be on top, you can do something along these lines:
this.addEventListener(Event.ADDED, bringToTop);
function bringToTop(e:Event):void {
setChildIndex(character, numChildren-1);
}
Doing that, makes it so whenever any other object is added as a child of this, it will set the character to the very top most layer/z-index.

cocos2dx - sub layer that covers its parent partially keep capturing all touches

In my cocos2dx game, I have a CCLayer that contains another CCLayer. The sublayer just cover part of the container layer. I 'think' I achieve this through:
this->setContentSize( CCSizeMake( 100, 200 ) );
however, the sublayer always capture touches even though it is outside its size and position area... Is it common?
I can filter through the touches position by comparing it inside the ccTouch** functions, but I think it is a hack, what is the proper way to set the sublayer to properly cover just the partial area of its parent?
The only thing i can think of straight away is making this inner layer a CCNODE and also extent it with CCTouchDelegate.
Now with this, when u register with the TouchDispatcher, you make sure it doesn't Swallowtouches(the boolean value given as the last parameter)...
This way when you receive a touch ... just see if it is within the boundary of this inner layer of urs and if it is not, send let the parent class use this touch.
Hope this helps.

Flex 4 <s:Scroller> Recalculate Range?

I am building a Flex 4 application which uses a <s:Scroller> component to vertically scroll overflown content. Let me explain what happens before I ask my question:
The body of the page is loaded from a database
Once the information has loaded, the "body" of the application (in this case the list of items you see below) is constructed
Once the list is constructed, the entire encapsulating component is transitioned into view using TweenMax, like so:
myComponent.visible = true;
TweenMax.to(myComponent, 1, {
alpha : 1,
y -= 20 //Slides the component up 20px from its original location
});
Below is the result. Notice how the scrollbar is scrolled the whole way down, but you can see the tips of a few white letters that were cut off at the very bottom.
Using my custom menu, I can navigate away from the page, and come back to it, and Flex will correctly recalculate the range of the scroller so I can scroll down and see all of the desired content. This issue only happens if the initial URL that the user enters is a longer page like this one.
Any ideas on how I can force Flex to recalculate the range of the scroller?
Thank you for your time.
Ok, after many hours of researching, piecing together, and trial and error here is what I came up with.
What I was doing wrong:
When I first posted this question, the "component" that I had mentioned was already added as a child element of the <s:Scroller>, but collapsed and hidden away, like this:
<comp:MyComp alpha="0" height="0" visible="false"/>
When the data would be loaded and the component's visual appearance would be restored and transitioned into place, like this:
myComp.visible = true;
myComp.height = NaN;
myComp.invalidateSize();
myComp.height = myComp.measuredHeight;
TweenMax.to(myComp, 1, {
alpha : 1,
y -= 20 //Slides the component up 20px from its original location
});
This method of approach didn't force the <s:Scroller> to recalculate its proper size until later, sometimes not until myComp was transitioned away and another component was transitioned into place using the same method. Even then, the size of the scroller would fit the size of the previous component, not the one that is currently displaying.
Now, what I am doing correctly:
My research showed me that anytime the addElement() method is called, either directly within the <s:Scroller> itself or by any of its children, the scroller's measure() method is called, and properly re-sizes the scroller.
Instead of placing the components inside of the scroller and simply hiding them until I need them, I dynamically created them in ActionScript, set their properties, and added and removed them as needed using the addElement() and removeElement() methods respectively. Now, as old elements are transitioned away and new ones take their place, the scroller re-sizes itself correctly.
There was one final problem that I was faced with. If the very first page the user was viewing (i.e. there was no previous component that was transitioned away and destroyed) required a scroller, it wouldn't show up.
I corrected this final issue by adding an event listener that listened for when the new component had finished transitioning into place. Inside of the event handler, I explicitly set the height of the component using this code:
newComp.height = NaN;
newComp.invalidateSize();
newComp.height = newComp.measuredHeight;
Now that the component has an explicit height, the scroller now appears, even if it is the first page.
The scroller now works as expected in all cases, and does not cut off any content or disappear when it shouldn't.
I hope that it is helpful to someone.

AS3 Dynamic text box over button

In AS3 I have a button on the stage and above it I create a textbox box dynamically with code.
My problem is that the area that is under the text (i.e. that part of the button) is no longer clickable.
I have set:
tBox.selectable = false;
but that doesn't solve it.
Any ideas
Season greetings,
Luben
Use InteractiveObject.mouseEnabled:
textField.mouseEnabled=false;
If you set component.visible to false it does not interact with the user.
So, if you set tBox.visible = false then it will be invisible and the button will become clickable. Just a thought, but overlapping components is really bad UI design. If you have space on your stage, you should consider keeping them separate
The problem is that text field (despite it's transparent) is lying over button. To make click on button possible you have to be sure that button is in front of text. Take a look at AddChildAt method of DisplayObject. Objects with greater position index are lying over objects with lower position index. So all you need is to make sure that button has greater index:
container.addChildAt(button, 1)
...
container.addChildAt(text, 0)
P.S.: you may embed button dirrectly into text field using html <a href="javascript:..."><img src="link_to_image"><a/> or something like that.