Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scene2D UI Table widget click area is offset from drawn widget #5174

Closed
IronRex opened this issue Apr 15, 2018 · 5 comments
Closed

Scene2D UI Table widget click area is offset from drawn widget #5174

IronRex opened this issue Apr 15, 2018 · 5 comments

Comments

@IronRex
Copy link

@IronRex IronRex commented Apr 15, 2018

Issue details

Create a stage with a table with a checkbox. Clicking the top of the checkbox does not register (checkbox state does not change). Clicking approximately lower 2/3 of the checkbox registers (checkbox state changes). Clicking slightly below the checkbox registers (checkbox state changes). The issue persists with other widgets but is less noticeable for bigger widgets like buttons. Widgets work as expected if you do not table.setFillParent(true); or otherwise set table dimensions. Widgets also work as expected when used without a table.

Reproduction steps/code

Create a stage with a table with a checkbox. Example uses default skin from https://github.com/czyzby/gdx-skins

package com.mygdx.game.tablewidgettest;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class TableWidgetTest extends ApplicationAdapter {
	Skin skin;

	Stage stage;

	Table table;
	CheckBox checkBox;
	
	@Override
	public void create () {
		skin = new Skin(Gdx.files.internal("skin/default/uiskin.json"));

		stage = new Stage(new ScreenViewport());

		table = new Table();
		table.setFillParent(true);

		checkBox = new CheckBox("Test checkbox", skin);
		table.add(checkBox);

		stage.addActor(table);

		Gdx.input.setInputProcessor(stage);
	}

	@Override
	public void render () {
		Gdx.gl.glClearColor(0, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		stage.act();
		stage.draw();
	}

	@Override
	public void resize(int width, int height) {
		stage.getViewport().update(width, height, true);
	}

	@Override
	public void dispose () {
		stage.dispose();
		skin.dispose();
	}
}

Version of LibGDX and/or relevant dependencies

1.9.8
1.9.9-SNAPSHOT (as of 04/14/2018)

Stacktrace

N / A

Please select the affected platforms

  • Android
  • iOS (robovm)
  • iOS (MOE)
  • HTML/GWT
  • Windows
  • Linux
  • MacOS
@tommyettinger
Copy link
Contributor

@tommyettinger tommyettinger commented Apr 15, 2018

I tried this example on libGDX 1.9.6 and 1.9.8, also on Windows (here, Windows 7 64-bit), with LWJGL2 and LWJGL3, but can't reproduce as-is. However, I've had a similar issue where the mouse-responsive area of an input component was offset from the actual screen area, though I don't have the code easily available so I can't be sure if it was scene2d-related or related to my mouse handling. @IronRex , could this be an issue with the monitor resolution being seen incorrectly by scene2d/your application? LWJGL2 does not handle high-DPI monitors very well. My laptop screen has 96 pixels per inch and Windows is configured to apply no scaling, if it helps for comparison.

@IronRex
Copy link
Author

@IronRex IronRex commented Apr 15, 2018

Wow! You are correct. It seems related to high pixel density.
My laptop is 13" 1920x1080 which makes 169PPI. I just tried it on a desktop with 24" 1920x1080 which makes 91PPI. No problem on the desktop.
I tried it on my phone. It too is 1920x1080 but only 5" diagonal (Google Pixel). My fingers are too big to detect any issue. Using an improvised stylus (toothpick and tinfoil) is also too big to detect this issue.
@tommyettinger Any way to forcibly tell monitor resolution or pixel density to LWJGL2?

@tommyettinger
Copy link
Contributor

@tommyettinger tommyettinger commented Apr 15, 2018

I'm only aware of high-DPI code being usable on LWJGL3, since LWJGL2 was written when screen DPI was rarely as high as it is now. LWJGL3 also handles multi-monitor setups instead of only using one monitor. It should be rather easy to change the backend, if you want to try LWJGL3, but I'm not sure if the process is documented here on the wiki. You'd change a few Gradle dependencies from lwjgl to lwjgl3, and then the DesktopLauncher class in the desktop module needs to be slightly different. Nothing in the core module should need to change.

Steps to change, as best as I can remember: Where you see compile "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion" , change it to compile "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion" . This line near it stays the same, compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" . There's a commit in a repo I work on that has a pretty good example of what the changes would look like for going from LWJGL2's configuration to LWJGL3; here's the highlighted file, with '-' to remove LWJGL2 lines and '+' to add LWJGL3 lines. You can see the code is similar, mostly just changing LWJGL to LWJGL3 and going from setting fields to calling setter methods, but there's also some WIP comments there and I hope they don't make it hard to read. The classes to import also change.

It's possible this is a bug in checkbox code for scene2d.ui, it's possible that it might be resolved fully by using LWJGL3, it's possible that it's an operating system bug related to the input not being given correctly to applications, and it's possible that it's not something that could be fixed, but could instead be worked around. I'm hoping LWJGL3 being more aware of HDPI screens will mean it gets more precise input and so can respond correctly to clicks. There's a class in LibGDX that I haven't needed yet called HdpiUtils, and it may have a solution here (maybe it needs to be added to scene2d.ui code, not sure).

Personally, I'm hoping LibGDX makes LWJGL3 the default backend for desktop soon, since it just generally seems better and is actually receiving updates. There may be outstanding bugs, but I don't think there are very many of them. I think the Java 9 issues it had briefly during early access of OpenJDK 9 were resolved, and there were also some early hiccups when LWJGL3 was first released a while ago. I think it's been very stable since those were fixed. It's probably hard for some devs to test multi-monitor setups for their games, but from what I've seen supporting multiple monitors with fullscreen and the like has been a common request from players, and that's a good reason to use LWJGL3.

@IronRex
Copy link
Author

@IronRex IronRex commented Apr 18, 2018

Setting up LWJGL3 was no trouble at all. Thanks for detailed instructions. It should totally become the default.
I also tried updating to Java 9 and Gradle 4.6 and setting things like

config.useVsync(false);
config.setHdpiMode(Lwjgl3ApplicationConfiguration.HdpiMode.Pixels);

All of the above had no impact on widget in table behavior on my laptop.
There is a lot of information on the internet about LWJGL3 and high DPI monitors. It takes a lot of effort to sort through it all and try various things. I may try more things on my own at a later time.

TL;DR
If you have any ideas on what I should try let me know and I will report back with the results.
If you came here searching for any kind of a solution then simply do not use table to layout your widgets. Widgets outside of tables work just fine.

@NathanSweet
Copy link
Member

@NathanSweet NathanSweet commented Apr 20, 2018

I tried the example code with LWJGL2, but it worked fine. You could try Spine on your computer which shows the problem, which is a large scene2d.ui app that uses LWJGL2 and Table heavily.

I've never had an issue like this using Table, also Table doesn't do anything input related that should cause such a problem. That means likely you could have the same problem even sizing and positioning actors manually.

My guess is that maybe the viewport is not the right size. Your code looks good, but maybe there is an issue with the order of events in the backend on your particular computer. You can try this:
http://n4te.com/x/352-4DG9.txt
Paste it next to LwjglTestStarter and you can run without fiddling with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.