I am at a point where I am seeing if lwjgl3 is going to work for me in avoiding reflection warnings thrown out by java 14 with regards to.
Illegal reflective access by com.jme3.util.ReflectionAllocator
After switching to lwjgl3 I found out they no longer provide convenience methods used in the class org.lwjgl.opengl.Display to get the width and height of the screen and the GLFW class that replaces it doesnt have anything like it.
I find it kinda weird to cannibalize code like that but what the hell do I know, I am just the end user, why should they care right?
Anyway, it looks like I am forced to implement my own library just to use their library so before I get stupid, are there any jme GLFW utilities already written somewhere?
This is probably something that could/should be available from GuiGlobals, I guess.
Edit: seems like technically you could now by grabbing:
GuiGlobals.getInstance().getPopupState().getApplication().getCamera()
Edit 2: or even the deprecated: public ViewPort getCollisionViewPort( Spatial s )
…which I’m wondering now if should not be deprecated. I left myself no bread crumbs. lol
/** Returns the current width for this component.
* @return The current width for this component.
*/
public abstract int getWidth();
where component is a lemur node.
@Override
public int getWidth() {
return (int) component.getControl(GuiControl.class).getSize().x;
}
and for max,
/** Returns the maximum width of the component.
* @param hHint The Size hint for the other dimension. An implementation can use this value or the
* current size for the widget in this dimension, or a combination of both, to calculate the correct size.<br>
* Use -1 to denote that there is no hint. This corresponds with SWT.DEFAULT.
* @return The maximum width of the component.
* @since 3.5. Added the hint as a parameter knowing that a correction and recompilation is necessary for
* any implementing classes. This change was worth it though.
*/
public abstract int getMaximumWidth(int hHint);
with what used to be lwjgl2 Display class.
@Override
public int getMaximumWidth(int hHint) {
//lwjgl2
return Display.getWidth();
}
I used what was posted before for lwjgl3.
@Override
public int getMaximumWidth(int hHint) {
//lwjgl3
GLFWVidMode glfwGetVideoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
return glfwGetVideoMode.width();
}
So this implementation is wrong and should just use camera width for both methods?
If you want to work in all cases where your UI could be used (viewports) and it’s already attached to the scene then you can use:
GuiGlobals.getInstance().getCollisionViewport(this) and then ask the viewport. getOutputFrameBuffer().getWidth().
If you only care about screen size then:
GuiGlobals.getInstance().getPopupState().getApplication().getCamera().getWidth()
Edit: and either way, your code will then work on any JME platform, not just lwjgl3.
Also the getWidth/getHeight are not probably always true when you ask it from jME/LWJGL, that is just the resolution. Scale differs… HiDPI… etc. so viewport/camera is what you want most of the time anyway.
The problem for this wrapper is that GuiGlobals gets initialized in simpleUpdate(). The AppStates using Lemur are instantiated at startup in main.
These wrapper methods can be called twice during startup. Whenever you position any component and when guiNode.updateLogicalState gets called after all AppStates are initialized.
When positioning, you get a null viewport as GuiGlobals is not yet fully initialized yet. This may be why the lwjgl values were used originally. They are always available.
By the time guiNode.updateLogicalState is called, everything is ok.
To work around positioning, I moved the AppState using lemur to instantiate after GuiGlobals initializes and using the AppStates update loop to position components since that means guiNode.updateLogicalState has already been called, but that limits you to the default camera anyway. May as well just leave it using lwjgl methods like was already doing.
getOutputFrameBuffer() is null by default. I only see the opportunity to setOutputFrameBuffer() per Component.
public Main() {
super(new StatsAppState(), new DebugKeysAppState(),
new BasicProfilerState(false),
new AnimationState(), // from Lemur
new OptionPanelState(), // from Lemur
new DebugHudState(), // SiO2 utility class
new LogoState(),
new MainMenuState(), // <==== This is the UI here
//new FlyCamAppState(), // temporary
new ScreenshotAppState("", System.currentTimeMillis()));
}
@Override
public void simpleInitApp() {
setPauseOnLostFocus(false);
setDisplayFps(false);
setDisplayStatView(false);
GuiGlobals.initialize(this);
To me, the easiest answer is to allow external setting of some static fields on MigLayout for where it keeps its screen size… or call it a “default screen size”.
Use the automatic ways when they are available (so that you can support viewport UIs or texture mapped UIs) but otherwise fall back on the static defaults.
…then set your static defaults during simpleInit().