LibGdx - Increase touch-area of Actor - libgdx

Is there a way for me to increase the touch-area of an Actor in LibGdx? In my case its a Label, I don't want to use a large button but its really hard to press the Label on the phone, so can I increase the touch area around the Label?

You should be able to modify the labels boundry.
Try the following method from the Actor class:
setBounds( float x, float y, float width, float height )
To dynamically set the boundry, you might be able to do something like:
float padding = 5f;
label.setBounds(label.getX() - padding, label.getY() - padding,
label.getWidth() + (padding * 2f), label.getHeight() + (padding * 2f));

Related

LibGDX ModelInstance - can't reset scale, setting the transform while scaled deforms the model

Is there any way to reset a modelInstance's scale or set a modelInstances position without using transform.set? I'm making a 3D monster maker, When a part is selected a set of 3D arrows move to the part and become visible allowing the part to be dragged around. It's come to my attention that setting an arrow's position while scaled heavily deforms the arrow for whatever reason. This is a huge problem as I need the arrows to be different sizes depending on the size of the part. Without setting position, with setting position. Using transform.set on a non-scaled ModelInstance (or one scaled by 1) works fine.
I thought a solution would be to reset the size of the arrow before moving it and then re-scaling it after it was moved but there doesn't seem to be any method to do this and using transform.scale(-currentScale, -currentScale, -currentScale) inverts the arrow and increases its size rather than decreasing it.
Here is how I change the arrow's position: arrow[j].transform.set(modelInstance[i].transform.getTranslation(new Vector3(), arrow[j].transform.getRotation(new Quaternion());
Ok, I did some logging and found that scaling changes all values within the matrix4 not just the size of the modelInstance. I didn't find a way to only scale rotation but I figured a way around this: I created an empty Matrix4 and set that to a copy of the arrows matrix before scaling. When the arrows need to be positioned at a part I set the arrow's matrix to the baseMatrix, used transform.set to change the arrows' position, and then rescaled the arrow.
if(Intersector.intersectRayBoundsFast(pickRay, modelInstance[i].boundingBox)) {
modelInstance[i].transform.getTranslation(modelInstance[i].position);//get the part's position and store it
for(int j = 0 ; j < 3 ; j++) {
arrow[j].transform = arrow[j].baseTransform.cpy();//reset the arrows transform
arrow[j].transform.getRotation(arrow[j].rotation);//get the arrow's (unscaled) rotation and store it
arrow[j].transform.set(modelInstance[i].position, arrow[j].rotation);//set the arrow's position and rotation
arrow[j].changeSize('S');//rescale the arrow
}
break;
}
You can use transform.scale(1f/currentScale, 1f/currentScale, 1f/currentScale) to revert the scaling or the function ModelInstance.calculateTransforms()

How do I scale a Libgdx Animation?

I an currently using Libgdx Animation class( com.badlogic.gdx.graphics.g2d.Animation) in a game. However I need the animation to grow in size on certain events. How do I accomplish this?
Animation is used to select the correct frame (TextureRegion) based on the time elapsed. It has nothing to do with how you render that frame. Therefor it is not different as how you render anything else.
You didn't provide enough information for that. But usually you'd render it something like this:
TextureRegion textureRegion = animation.getKeyFrame(time += delta);
spritebatch.draw(textureRegion, x, y, width, height);
So to change the size would be to change the width and height variables. You didn't provide enough information on how you'd like to do that. But you can do that for example using this:
width = 0.8f;
height = 1.9f;

LibGDX - Get width of label cell in ImageTextButton

I have ImageTextButtons within a container Table. I would like to dynamically change the width of this table and have the ImageTextButtons respond in a particular manner. What I would like them to do is fade in the label text depending on the percentage of the text shown.
I believe I am dynamically setting the table width and contents correctly. As per the LibGDX documents we should not explicitly set the widgets dimensions, but the table (container) cell dimensions. So for testing, I have a simple clickListener on what of the buttons like this;
button.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
float max = container.getCell(button).getMaxWidth();
container.getCell(button).width(max*0.9f);
container.invalidate();
}
});
This works fine, I click it and the cell (and the widget) shrink 90% each time.
For the next step, I thought it would be as simple as this, in my custom ImageTextButton's draw() method;
glyphWidth = getLabel().getGlyphLayout().width;
labelCellWidth = getLabelCell().getMinWidth(); ///<--problem here
float glyphOpacityMultiplier = MathUtils.clamp(labelCellWidth/glyphWidth, 0f, 1f);
origLabelColor = getLabel().getColor().cpy();
newLabelColor = origLabelColor.cpy();
newLabelColor = new Color(newLabelColor.r, newLabelColor.g, newLabelColor.b, newLabelColor.a*glyphOpacityMultiplier);
getLabel().setColor(newLabelColor);
super.draw(batch, parentAlpha);
getLabel().setColor(origLabelColor);
This all works, except for the fact I can't find any method to give me with actual width of the Cell that contains the label. Since the ImageTextButton itself is also a Table, I tried to do button.invalidate() in the ClickListener too but it didn't help. These are the methods I have tried so far;
getLabelCell().getMinWidth();
getLabelCell().getMaxWidth();
getLabelCell().getPrefWidth();
getLabelCell().getActorWidth();
getLabelCell().getSpaceLeft();
getLabelCell().getSpaceRight();
None of them seem to update and give me the correct size, however I know something is working somewhere because I turned on "setClip(true)" on the ImageTextButton, and the label text is successfully being clipped within the boundaries of the NinePatch background when it is resized. So how do I get the correct size?
Any help is greatly appreciated!
Oops.. solved it. I thought the cell containing the label would be offset and sized by the NinePatch background but its not, it is full size but has padding. Therefore the answer is;
labelCellWidth = getWidth()-getPadLeft()-getPadRight();

Force an actor to obey the width set in table.add(actor).width()

I am setting the width of actor in table.add(actor).width(width). The padding is set to 1% of screen width. This is the result I get:
As you can see, spacing between actors is way beyond 1% . I tried using fill() methods but it didn't work. I also tried setFillParent(true) on the actor, no success. What is going on here? This is the complete code. The only spacing between actors should be the one I set with padding. How do I achieve this?
private void createScrollPane(){
texture=new Texture("badlogic.jpg");
ImageButton.ImageButtonStyle fibs=new ImageButton.ImageButtonStyle();
fibs.imageUp=new TextureRegionDrawable(new TextureRegion(texture));
button1= new ImageButton(fibs);
button2= new ImageButton(fibs);
button3= new ImageButton(fibs);
button1.setPosition(0, 0);
button2.setPosition(0, 0);
button3.setPosition(0, 0);
scrollTable=new Table();
scrollTable.setBounds(Gdx.graphics.getWidth()*0.03f,0,Gdx.graphics.getWidth()*0.94f, Gdx.graphics.getHeight());
scrollTable.setPosition(Gdx.graphics.getWidth() * 0.03f, 50);
scrollTable.add(button1).width(Gdx.graphics.getWidth() * 0.3f).padLeft(Gdx.graphics.getWidth() * 0.01f).fill();
scrollTable.add(button2).width(Gdx.graphics.getWidth() * 0.3f).padLeft(Gdx.graphics.getWidth() * 0.01f).padRight(Gdx.graphics.getWidth() * 0.01f).fillX();
scrollTable.add(button3).width(Gdx.graphics.getWidth() * 0.3f).padRight(Gdx.graphics.getWidth() * 0.01f).fill();
stage.addActor(scrollTable);
}
ImageButton is a Button with an Image on top of it. If you just want a button then use the Button class and set the up drawable to the drawable you want it to be. Note that you can enable debug drawing of the stage or table to visualize what is going on.
Your function calls are affecting the Table's cells, not the actors in the cells.
Call scrollTable.setDebug(true) to see the cells, padding, etc. You'll be happy to find your function calls are working, just on the cells rather than their contents.
The next step is to build a composite layout with widgets which allow you to expand the buttons but maintain them in a horizontal alignment. You might be able to accomplish that with just a table if you battle the cells hard enough, I'm not sure.
What I did was to use a Table, then add a HorizontalGroup. The HorizontalGroup goes within a cell on the Table. Inside the HorizontalGroup I add my buttons. Laying out the buttons the way I want within the HorizontalGroup is far easier than doing it via the Table.
For an ImageButton you can explicitly set the minHeight and minWidth of the style, which will forcibly scale the attached Image.

Change Label metric unit in LibGDX

I'm using Scene2d to build ui for my screen.
Stage stage = new Stage(new StretchViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()));
Skin skin = ResourceManager.getSkin("uiskin");
Label label = new Label("my text", skin);
When stage.draw() has called, the label appeared in left bottom corner of the screen. But I want to use the viewport with unit size.
float ratio = (float)Gdx.graphics.getWidth() / Gdx.graphics.getHeight();
Stage stage = new Stage(new StretchViewport(ratio, 1));
In this way I can define size of other actors in percents of screen height - 0.5 , 0,23 ect. And it works well for other Actors, ImageActors, but how I can properly change size of my label? Label draw in the same place, I think, but it is tremendous for the stage, be cause its size is in pixel 183 *10 ect. And
label.setBounds(.....);
isn't working.
You need to set the scale on the font. I'm not sure why it doesn't happen automatically, but the fix is to add a line like:
font.GetData().setScale(<viewport width>/Gdx.graphics.getWidth(), <viewport height>/Gdx.graphics.getHeight());