Plugin-Based JME DevKit

> Task :DacWizard:runSdk FAILED
Exception in thread "main" java.lang.NoClassDefFoundError: javafx/application/Application
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at com.jayfella.devkit.Main.main(Main.java:8)
Caused by: java.lang.ClassNotFoundException: javafx.application.Application
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 13 more
1 Like

I dont think your java8 comes with javafx. I had to install it separately with openjdk.

2 Likes

Ok. So JavaFX appears to be quite difficult to implement for such a wide audience that have a fixed software path. The app should accommodate the users needs - not the other way around.

So java-fx goes out the window for this particular setup. I’ll give Swing a shot and see if we can get some movement with that.

2 Likes

I’d like to suggest another approach, possibly complementary to the gradle plugin.
Instead of running a plugin from gradle, the game dev would add a new submodule to their project. They would add the devkit as a dependency in the submodule, plus any number of publicly available plugins that extend the devkit with the needed functionality.
Because that’s just another java app, the dev could extend the devkit by writing code to do any specific task needed for their game (using the plugin system). In a way providing all the building blocks for creating their own specialized SDK.

I do something like that in my project. I have my own leveleditor, although optimized for doom-like shooters, it doesn’t have any game specific features. Then in my game’s codebase I have a maven module (could be gradle) that extends the leveleditor with the specific functionality of my game (create entities and export to level DSL).
This makes the workflow quite convenient for me, as I have everything I need right there by launching the app from the IDE. And because everything is versioned I don’t have to care about maintaining a SDK installation (keep it up to date, manage plugins, etc.).

1 Like

@jayfella may I ask what went wrong with the Lemur based solution?

1 Like

It was very difficult to overcome the scrolling problem. Some things like a tree view and property list need scrolling. I could overcome it to some extent but it felt more like I was creating a gui more than a devkit.

1 Like

So i took some time this morning to get this running but it doesn’t work on OSX due to running glfw calls off the main thread. Even after adding the -XstartOnFirstThread flag it just crashed with a different off main thread error for a different glfw call:

2020-06-23 08:38:38.226 java[2194:38751] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'nextEventMatchingMask should only be called from the Main Thread!'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff32a12f53 __exceptionPreprocess + 250
	1   libobjc.A.dylib                     0x00007fff68ad8835 objc_exception_throw + 48
	2   AppKit                              0x00007fff2fb6d0c9 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 4157
	3   libglfw.dylib                       0x000000013a1233d3 libglfw.dylib + 74707
	4   ???                                 0x000000010d384297 0x0 + 4516758167
	5   ???                                 0x000000010d37ad1c 0x0 + 4516719900
)
libc++abi.dylib: terminating with uncaught exception of type NSException
1 Like

By the way, remy_vd used a nice solution to overcome this problem using ListBox.

For scene graph view:

https://i.imgur.com/lZVSrTG.png

For open file window:

For properties list, I would list the name of properties inside a ListBox and when clicked on a property I will display the content in another panel.

But yeah I agree that in Lemur (due to JME limits) it not as flexible as Swing or JFX which have clipping.

Anyway I hope you find it helpful :slightly_smiling_face:

For general scrolling, the only mechanism JME provides is a ViewPort. For certain UIs, this is pretty easy to setup.

…for the general “windows can overlap other windows, totally flexible” cases that a framework must deal with… not so easy.

If JME had geometry-level clipping then it would be easier… but that is also it’s own can of worms since a spatial can be in more than one viewport at a time and clipping is necessarily viewport specific.

I tried the list box trick, but it also lacks the anchoring and complexities of a fully fledged GUI framework - which is not a swipe at lemur - it’s supposed to be a game GUI - not an application GUI - where you’d want a lightweight one.

I think it’s entirely possible to use lemur - and I had a good stab at it, but what I need is a desktop framework because it’s a desktop application.

I’ll try the swing approach and see where that takes me.

Thanks for at least giving it a try. Hopefully swing with lwjgl2 should work.

Dropping back to lwjgl2 does work, however, performance is terrible in the viewport. Like jME is running at 300+ fps, but moving around causes it to stutter like crazy.

Same here. The swing one I’m writing now is a virtual pass-through. You get the full output.

There was talk on discord about how ugly swing is, but the alternative is porting a different UI to JME (possibly imgui) which I’m not overly enthusiastic about.

IntelliJ uses swing and the darcula theme looks really well designed, so there’s something I can work on when I’m not in the mood.

@jayfella There is already a ported c gui library (nuklear) in lwjgl if you like to work with that. The imgui port is separate from lwjgl and I don’t know how much it’s maintained up to date

I am aware of it, but admittedly haven’t given it any more than a passing glance. At any rate I’d rather not spend the majority of my time on yet another project to work on this project right now.

But that aside, Nuklear and imgui both look like really cool GUI’s and it would be nice to see a JME implementation.

paging @janvonpichowski

did nuklear gui ever work out for you?

Yes, it works pretty well. I don’t know if I did everything in the correct way because it was a deep dive in the core of the rendering engine and there is almost no documentation on this matter but the code and javadoc is great as always. The most difficult part was to share the native buffers for the whole live time and not to recreate them on every draw call. And of course, some known issues like the interleaved data or clipping needed some love and workarounds. I don’t know if I have addressed them in the correct way, because some previous discussion leaded to no interest in these details. Nevertheless, it works on all renders now.

Still missing is full support of the keyboard, mouse, multiple fonts and clipboard. I just implemented the necessary things for me. Another point is that at the moment I just provide the nuklear context and you have to use the ugly native methods. This is partly a problem because some implementations from LWGL3 are not correct transformed, so you have to add some fixed methods.

Compared to other gui solutions is it faster when you have constantly changing gui elements.
Biggest minus is that the Nuklear wrapper from LWJGL3 does not work with LWJGL2 because those versions doesn’t play nicely together. So I thought there would be no general interest.

I can prepare my work for the public if someone wants to build upon it. Nevertheless, the most important missing feature for me is a clean api. This should be discussed beforehand with the users.
I didn’t need to make changes to the engine but some workarounds are not very clean. I like to see some discussion on the needed changes to the engines before. But you know some topics like interleaved buffers and clipping are very difficult to address right.

So long post but the key is: It is doable with some knowledge of the rendering engine. Using Nuklear is very easy afterwards. For me it was way faster to create rich guis with it.

As for imgui: The basic setup is the same as for Nuklear but you have to write the wrappers yourself. That means more work.

I wouldn’t worry too much about all of that. If people find it of use they tend to chime in and do PRs, so everyone involved wins.

Truth be told I’m not sure I’ve ever created a method I haven’t rewritten, let alone an entire project.

I’ve switched some of the code over to swing and found an open-source theme that has both a light and dark theme built-in. No real issues to speak of. I’ll try to push the first iteration of it over the next day or so to let others give it a try and discuss improvements.

One thing I’d like to add (at least at the early stages is the ability to add and view physics objects using the built-in debugger. Since I don’t want the objects to actually move, would setting the speed of the physicsspace to zero suffice @sgold ?

3 Likes

That should work unless the app invokes space.update() directly. But in that case it’s likely there’s no BulletAppState and no built-in debugger.

1 Like