inputManager.setCursorVisible(false) not working in simpleInitApp()

Hello,

when I set up my cam with a CameraNode and disable the fly by mode, a mouse curser shows up.

I just copied that code (Camera Node section): https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:making_the_camera_follow_a_character

When I try to hide the cursor with inputManager.setCursorVisible(false) in the simpleInitApp() method it wont work. It works when I invoke inputManager.setCursorVisible(false) in the simpleUpdate() method, but it I didn’t intent to hide the cursor 60 times a second =D

Did i miss a point or could i’ve done something wrong?

Thanks in advance!

And of course inputManager.setCursorVisible(false) is the very last thing I did in my simpleInitApp()… But I also tried it the other way around (first cursor hiding, then the CamereNode setup).

simpleInitApp() runs before everything else. It is a good place to add your app states and stuff that will actually do the work of your game. The app states will be initialized after simpleInitApp().

…and this is kind of why. The flyCam is managed with a FlyCamAppState and even if the camera is disabled it is still registered with input… and for whatever reason, flyCam decides to force the cursor state when it is registered with input manager.

If you don’t want flyCam it is easy to remove, though. You can either directly control that default app states that are setup for your game by calling the super() constructor and only passing what you want (or null for nothing) or you can remove the FlyCamAppState in simpleInit(). If you decide you need the fly cam back again for some reason then you can always attach the app state then. (Note to self, chase cam probably deserves an app state treatment as well.)

1 Like

Okay thank you a lot I got it!

The whole concept about appstates (and controls) really should be mentioned much earlier and more prominent in the tutorials/docs. I mean to me it looks like its what defines jMonkeyEngine…

1 Like

I kind of agree. I think the tutorials mislead new developers in a few different ways in an attempt to be simple.

They are great for people who already know what they want to do and just need to know the “how” of some specific thing but they fall down a little in the general “this is how you should do things” level. But it’s hard to get right.

Edit: and I don’t mean to discount the amazing volunteer work that has gone into so many tutorials. They alone are just not the substance of a healthy diet. :slight_smile:

1 Like

Well, it is a wiki, where everyone can write, if you get my drift :slight_smile:

1 Like

Part of the problem is that SimpleApplication has some deficits. In particular, it contains member variables to help implement some AppStates, which is attaching gratuitious strings to disabling some AppStates (I’m looking at you, FlyCamAppState).
Which in turn isn’t that easy to fix, because some AppStates need to define keyboard bindings and InputManager isn’t able to accept such binding configurations from AppStates. (One of the many deficits of InputManager; I’ve been wanting to do something about it but don’t have time. If there’s interest, I could help setting up a list of desirables, and maybe help with the design, but I won’t be able to code much.)

So… at least for me, updating the wiki was something I’d want to do after fixing the code.

I’m now playing around with jME for 3 days so its definitely not the right time for me to start writing in the wiki nor recoding SimpleApplication :-o :wink:

But maybe (when I stick to jME) later it will be a pleasure to me to be helpful 8)

@toolforger said: which is attaching gratuitious strings to disabling some AppStates (I'm looking at you, FlyCamAppState). Which in turn isn't that easy to fix, because some AppStates need to define keyboard bindings and InputManager isn't able to accept such binding configurations from AppStates.

Can you explain what you mean by this? I’m having trouble understanding the “gratuitous strings” part and the “isn’t able to accept binding configurations from app states” part.

JME’s input system binds key presses etc. to names (Strings), which in turn are bound to actions.
The problem with that system is that:
a) The names share a single global namespace, so there can be gratuitious conflicts
b) The binding could be directly to the actions with no loss of functionality
c) The input system cannot diagnose conflicts because AppStates do the registration directly; they’d need to provide a data structure or API to allow the input system to detect and deal with keybinding conflicts.

There’s more:
d) Modifier keys aren’t covered at all. Different AppStates would probably want different modifier key handling (e.g. if a text input is active, you want to have Ctrl-A select the entire text, in-game, the Ctrl key might fire a weapon).
e) There is no place where the input system gives access to key names. Screens like the input configuration screen shown below are really hard to do without that, a US programmer probably won’t even know that there are ä, ö, ü, and ß keys on a German keyboard.
f) Similarly, there is no way to query the position of a key - or find the key at a position. y and z are swapped on German keyboards.
g) Also, there is no way to tell the input subsystem about the names of actions. This would be really handy for programming configuration screens.

Here’s the sample screen:

1 Like

The reason for mapping an input to a name and a name to a listener is so that they could be registered separately. InputManager just does a poor job of this. Lemur’s InputMapper solves most of the problems you list, otherwise, though.

…except for querying key position, a) I don’t see the point of that, and b) it’s not possible to determine.

I hope to add a sample input mapping config screen soon. InputMapper has all of the information I just don’t know if I provide the access methods, yet. But it was central to its design to handle this particular type of screen.

I think a better way to go about it is to have SimpleApplication and QuickStartApplication (which extends SimpleApplication).

Once people kind of have their bearings with jMonkey, I think most people would just want use the update() method funcitonality within SimpleApplication…

The default keybindings and appstates are primarily just useful if youre quickly trying to throw something together as a test or expirement.

If you’re trying to actually start a game project you have to choices:

1- extend Application and make your own SimpleApplication (bassicaly copy and paste the “meat” code from SimpleApplication)

2- extend SimpleApplication and then search for all the default keybindings and appstates and remove them.

both options are a little bit weird.

1 Like
@icamefromspace said: I think a better way to go about it is to have SimpleApplication and QuickStartApplication (which extends SimpleApplication).

Once people kind of have their bearings with jMonkey, I think most people would just want use the update() method funcitonality within SimpleApplication…

The default keybindings and appstates are primarily just useful if youre quickly trying to throw something together as a test or expirement.

If you’re trying to actually start a game project you have to choices:

1- extend Application and make your own SimpleApplication (bassicaly copy and paste the “meat” code from SimpleApplication)

2- extend SimpleApplication and then search for all the default keybindings and appstates and remove them.

both options are a little bit weird.

:facepalm:

Or just extend SimpleApplication and call super(null) in your subclass’s constructor. Done.

Edit: or just pass in your own app states to the super() call and not even bother to have a simpleInitApp or simpleUpdate…

and override start() and setCursorVisible(true) and setPauseOnLostFocus(false) and remove the escape input mapping… (and other stuff I’m probably forgetting), and this is only stuff someone is going to figure out after a certain amount of experimentation and looking in to how the SImpleApplication is made.

@icamefromspace said: and override start() and setCursorVisible(true) and setPauseOnLostFocus(false) and remove the escape input mapping..... (and other stuff I'm probably forgetting), and this is only stuff someone is going to figure out after a certain amount of experimentation and looking in to how the SImpleApplication is made.

Why do you need to override start()?

You only need to setCursorVisible(true) if you are rolling your own GUI since most of them do this for you. And if you don’t start with a GUI then you don’t want it at all.

Some games seem to desire the pause on lost focus bit… which is part of Application and not SimpleApplication anyway.

The only key mapping is the escape mapping… which is a reasonable default until you add your own since otherwise you may not be able to easily exit the application.

…and that’s it. Everything else was moved to an app state some time ago. Hand-waving about “things forgotten” aside. :wink:

So, we are left with the following steps to create a clean JME application:
-extend SimpleApplication and call it’s super() constructor with just the app states you want.
-if you want to turn the cursor on then turn it on.
-if you want to process escape yourself then remove INPUT_MAPPING_EXIT and register your own.

And note that all of them but the first are not universal and the need directly leads to the answer with minimal digging.

I spent a lot of time trying to strike a balance between cleaning up SimpleApplication and backwards compatibility… Unfortunately, SimpleApplication is only adding minimally to the already numerous “all fields protected” sins of its father. This limits solutions without branching to a different application base class (which I’ve considered about 500 times).

The protected fields end up doing more harm than good for the new users, I think. Many of them seem to think they are some magic JME keywords and don’t even understand that they are class fields until they can’t access them elsewhere. Unfortunately, that cat is well out of the bag at this point.

@pspeed said: :facepalm:

Or just extend SimpleApplication and call super(null) in your subclass’s constructor. Done.

Edit: or just pass in your own app states to the super() call and not even bother to have a simpleInitApp or simpleUpdate…

You still have some degree of namespace pollution from those protected SimpleApplication members.
That’s normally not a problem, but if you’re using some third-party code that accesses them, that will crash.

Though I have to admit that the real namespace pollution happens in Application itself, and agree there’s little that can be done about that now.
Hm… well, one could make a new base class (Application2, say), deprecate Application, and restructure the thing.

BTW I did override start(), too, to do
[java] loadSettings();
super.start(JmeContext.Type.Display);
Display.setResizable(true);
[/java]
where loadSettings() configures the Settings object so that super.start(…) does not show the settings dialog (which doesn’t make that much sense for a windowed-mode-only application).
Some applications might want to break the immersion to do GUI and settings stuff, these would probably need Canvas mode and a lot more setup in start().
Just to give examples how overriding start can make sense.

@toolforger said: You still have some degree of namespace pollution from those protected SimpleApplication members. That's normally not a problem, but if you're using some third-party code that accesses them, that will crash.

Though I have to admit that the real namespace pollution happens in Application itself, and agree there’s little that can be done about that now.
Hm… well, one could make a new base class (Application2, say), deprecate Application, and restructure the thing.

BTW I did override start(), too, to do
[java] loadSettings();
super.start(JmeContext.Type.Display);
Display.setResizable(true);
[/java]
where loadSettings() configures the Settings object so that super.start(…) does not show the settings dialog (which doesn’t make that much sense for a windowed-mode-only application).
Some applications might want to break the immersion to do GUI and settings stuff, these would probably need Canvas mode and a lot more setup in start().
Just to give examples how overriding start can make sense.

… but for not showing the settings dialog why not just set that up appropriately in the first place before starting the application?

MyApp app = new MyApp();
app.setShowSettings(false);
…set other app settings like window size, title, icons, etc…
app.start();

Then if you ever did want to pop up the settings dialog then you still have the option to do so without hacking your overridden start method. Could even make it a command line option in your main(). Not to mention that the code becomes properly desktop-specific since desktop is the only place that matters.

P.S.: I use the settings dialog all the time in windowed mode so that I can switch between vsync and non-vsync. Alternately, in the latest Mythruna I’ve completely removed it because the settings are handled in an app-specific screen now. I guess if you are embedding the window… but then there are other things you will be doing anyway and I don’t think of that as even a remotely typical use-case.

Yes, I initially used Canvas mode. The current structure with overriding start() might be a remnant from that. Or maybe I wasn’t aware that the Settings dialog can run before the render loop has started; I had had some issues with stuff that wouldn’t properly initialize unless inside start(), so I moved all the initialization there just to get that issue out of the way.

I think I could start the Settings dialog regardless of whether initialization is in start() or before.
Toggling vsync could be a hotkey. I think I’ll want that, to see how code changes affect the framerate. Though that could get heavy on hotkey usage if I ever want to toggle color depth etc., so eventually I’ll probably end with a Graphics Settings screen, too. Well, I’ll see, so much to do and so little time…

@toolforger said: Yes, I initially used Canvas mode. The current structure with overriding start() might be a remnant from that. Or maybe I wasn't aware that the Settings dialog can run before the render loop has started; I had had some issues with stuff that wouldn't properly initialize unless inside start(), so I moved all the initialization there just to get that issue out of the way.

I think I could start the Settings dialog regardless of whether initialization is in start() or before.
Toggling vsync could be a hotkey. I think I’ll want that, to see how code changes affect the framerate. Though that could get heavy on hotkey usage if I ever want to toggle color depth etc., so eventually I’ll probably end with a Graphics Settings screen, too. Well, I’ll see, so much to do and so little time…

Well, I hate to keep kicking this horse but I thought I would point out…

In the non-embedded case, you are the one calling start() from main(). So anything that was “thread legal” in start() is “thread legal” to do in main(). And anything that was safe to do before calling super.start() is safe to do before calling start().

The difference is that start() is called for all apps (including Applets and Android apps) where as main() is only called for desktop apps.

Ah. I guess that would be a point for keeping the initialization code in a start() override anyway.
Not that I plan on using Applets (not popular anymore, because, eww security holes) or Android (not on my radar yet), but it’s something to keep in mind for writing tutorial code and best practices texts.