diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000000..0d994e8d37
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,38 @@
+FROM registry.fedoraproject.org/fedora:43
+
+RUN dnf -y update && \
+ dnf -y install \
+ git curl unzip which procps-ng psmisc findutils \
+ alsa-lib alsa-plugins-pulseaudio \
+ pulseaudio-libs pulseaudio-utils \
+ # X + desktop
+ xorg-x11-server-Xvfb xterm dbus-x11 \
+ xfce-polkit \
+ xfce4-session xfce4-panel xfce4-settings xfce4-terminal thunar \
+ xfwm4 \
+ feh \
+ # VNC + web VNC
+ x11vnc novnc python3-websockify \
+ # Xpra + dependencies (xpra-html5 not in Fedora repos; installed below from source)
+ xpra python3-gobject python3-paramiko \
+ # OpenGL (Mesa) + GLVND + tools (glxinfo)
+ mesa-dri-drivers mesa-libGL mesa-libEGL mesa-libGLU \
+ libglvnd-glx libglvnd-egl \
+ glx-utils zip weston xorg-x11-server-Xwayland wayland-utils \
+ && dnf clean all
+
+
+
+ENV SDKMAN_DIR=/root/.sdkman
+RUN curl -s "https://get.sdkman.io" | bash \
+ && source "$SDKMAN_DIR/bin/sdkman-init.sh" \
+ && sdk install java 25-tem \
+ && sdk default java 25-tem
+
+ENV JAVA_HOME=${SDKMAN_DIR}/candidates/java/current
+ENV PATH=${JAVA_HOME}/bin:${PATH}
+
+
+COPY assets/wallpaper.jpg /root/wallpaper.jpg
+COPY assets/novnc-index.html /usr/share/novnc/index.html
+
\ No newline at end of file
diff --git a/.devcontainer/assets/novnc-index.html b/.devcontainer/assets/novnc-index.html
new file mode 100644
index 0000000000..1dd03f733b
--- /dev/null
+++ b/.devcontainer/assets/novnc-index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ noVNC
+
+
+
+ Warming up noVNC...
+
+
+
\ No newline at end of file
diff --git a/.devcontainer/assets/wallpaper.jpg b/.devcontainer/assets/wallpaper.jpg
new file mode 100644
index 0000000000..ddbd1cbb09
Binary files /dev/null and b/.devcontainer/assets/wallpaper.jpg differ
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000..a3675f0535
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,43 @@
+{
+ "name": "jME env (SERVER)",
+ "build": {
+ "dockerfile": "Dockerfile"
+ },
+
+ "forwardPorts": [6080],
+ "portsAttributes": {
+ "6080": {
+ "label": "jME Desktop (Xpra HTML5)",
+ "onAutoForward": "openBrowser"
+ },
+ "5900": {
+ "label": "VNC",
+ "onAutoForward": "ignore"
+ }
+ },
+ "containerEnv": {
+ "JME_DEV_ENVIRONMENT": "yesReally",
+ "LIBGL_ALWAYS_SOFTWARE": "1",
+ "MESA_LOADER_DRIVER_OVERRIDE": "llvmpipe",
+ "GALLIUM_DRIVER": "llvmpipe",
+ "WAYLAND_DISPLAY": "",
+ "WAYLAND_SOCKET": "",
+ "XDG_RUNTIME_DIR": "",
+ "GDK_BACKEND": "x11",
+ "SDL_BACKEND": "x11",
+ "GLFW_PLATFORM": "x11",
+ "DISPLAY": ":99"
+
+ },
+ "postCreateCommand": "bash .devcontainer/scripts/setup.sh",
+ "postStartCommand": "bash .devcontainer/scripts/start-desktop.sh",
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "workbench.colorTheme": "GitHub Dark Dimmed",
+ "java.jdt.ls.java.home": "/root/.sdkman/candidates/java/25-tem/"
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/.devcontainer/gpu-nvidia/devcontainer.json b/.devcontainer/gpu-nvidia/devcontainer.json
new file mode 100644
index 0000000000..acafff8749
--- /dev/null
+++ b/.devcontainer/gpu-nvidia/devcontainer.json
@@ -0,0 +1,32 @@
+{
+ "name": "jME env (NVIDIA)",
+ "build": {
+ "dockerfile": "../Dockerfile",
+ "context": ".."
+ },
+ "mounts": [
+ "source=${localEnv:XDG_RUNTIME_DIR}/pulse/native,target=/tmp/pulse/native,type=bind",
+ "source=${localEnv:HOME}/.config/pulse/cookie,target=/tmp/pulse/cookie,type=bind,readonly"
+ ],
+ "runArgs": [
+ "--gpus=all"
+ ],
+ "containerEnv": {
+ "LIBGL_ALWAYS_SOFTWARE": "0",
+ "NVIDIA_VISIBLE_DEVICES": "all",
+ "NVIDIA_DRIVER_CAPABILITIES": "graphics,utility,compute",
+ "__GL_THREADED_OPTIMIZATIONS": "0",
+ "JME3_DIALOGS_FACTORY": "",
+ "PULSE_SERVER": "unix:/tmp/pulse/native",
+ "PULSE_COOKIE": "/tmp/pulse/cookie"
+ },
+ "postCreateCommand": "bash .devcontainer/scripts/setup.sh",
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "workbench.colorTheme": "GitHub Dark Dimmed",
+ "java.jdt.ls.java.home": "/root/.sdkman/candidates/java/25-tem/"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/.devcontainer/gup-soft/devcontainer.json b/.devcontainer/gup-soft/devcontainer.json
new file mode 100644
index 0000000000..769cef0f8c
--- /dev/null
+++ b/.devcontainer/gup-soft/devcontainer.json
@@ -0,0 +1,31 @@
+{
+ "name": "jME env",
+ "build": {
+ "dockerfile": "../Dockerfile",
+ "context": ".."
+ },
+ "mounts": [
+ "source=${localEnv:XDG_RUNTIME_DIR}/pulse/native,target=/tmp/pulse/native,type=bind",
+ "source=${localEnv:HOME}/.config/pulse/cookie,target=/tmp/pulse/cookie,type=bind,readonly"
+ ],
+ "runArgs": [
+ "--device=/dev/dri",
+ "--group-add=video",
+ "--group-add=render"
+ ],
+ "containerEnv": {
+ "LIBGL_ALWAYS_SOFTWARE": "0",
+ "JME3_DIALOGS_FACTORY": "",
+ "PULSE_SERVER": "unix:/tmp/pulse/native",
+ "PULSE_COOKIE": "/tmp/pulse/cookie"
+ },
+ "postCreateCommand": "bash .devcontainer/scripts/setup.sh",
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "workbench.colorTheme": "GitHub Dark Dimmed",
+ "java.jdt.ls.java.home": "/root/.sdkman/candidates/java/25-tem/"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/.devcontainer/scripts/setup.sh b/.devcontainer/scripts/setup.sh
new file mode 100644
index 0000000000..68754c4b53
--- /dev/null
+++ b/.devcontainer/scripts/setup.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+
+# Optional: warm Gradle wrapper so first run is less painful
+if [ -f ./gradlew ]; then
+ ./gradlew --version || true
+fi
\ No newline at end of file
diff --git a/.devcontainer/scripts/start-desktop.sh b/.devcontainer/scripts/start-desktop.sh
new file mode 100755
index 0000000000..def2cb50e6
--- /dev/null
+++ b/.devcontainer/scripts/start-desktop.sh
@@ -0,0 +1,97 @@
+#!/usr/bin/env bash
+set -euo pipefail
+if [ "$JME_DEV_ENVIRONMENT" != "yesReally" ];
+then
+ echo "Not running! This script is meant to be run in the jMonkeyEngine dev container environment, and may do unexpected things if run elsewhere."
+ exit 1
+fi
+
+export DISPLAY="${DISPLAY:-:99}"
+unset WAYLAND_DISPLAY WAYLAND_SOCKET XDG_RUNTIME_DIR
+export GDK_BACKEND=x11
+export SDL_VIDEODRIVER=x11
+export GLFW_PLATFORM=x11
+
+# Fedora noVNC web root path
+NOVNC_WEB="/usr/share/novnc"
+if [ ! -d "$NOVNC_WEB" ]; then
+ echo "ERROR: noVNC web root not found at $NOVNC_WEB"
+ echo "Try checking where novnc installed files are:"
+ rpm -ql novnc | sed -n '1,120p' || true
+ exit 1
+fi
+
+# Start virtual X server
+if ! pgrep -f "Xvfb ${DISPLAY}" >/dev/null 2>&1; then
+ nohup Xvfb "${DISPLAY}" -screen 0 1440x900x24 +extension GLX +render -noreset >/tmp/xvfb.log 2>&1 &
+fi
+
+# Start a dbus session (XFCE wants it)
+if ! pgrep -u "$(id -u)" -f "dbus-daemon.*--session" >/dev/null 2>&1; then
+ # shellcheck disable=SC2046
+ eval "$(dbus-launch --sh-syntax)"
+fi
+
+# Start a PolicyKit agent to avoid XFCE PolicyKitAgent errors (if available)
+start_polkit_agent() {
+ if command -v polkit-gnome-authentication-agent-1 >/dev/null 2>&1; then
+ nohup polkit-gnome-authentication-agent-1 >/tmp/polkit-agent.log 2>&1 &
+ return
+ fi
+ if command -v xfce-polkit >/dev/null 2>&1; then
+ nohup xfce-polkit >/tmp/xfce-polkit.log 2>&1 &
+ return
+ fi
+ if [ -x "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1" ]; then
+ nohup /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 >/tmp/polkit-agent.log 2>&1 &
+ return
+ fi
+ echo "No PolicyKit agent found; PolicyKit dialogs may show an error."
+}
+
+start_polkit_agent
+
+
+
+if [ "$JME_DEV_ENVIRONMENT" != "yesReally" ];
+then
+ echo "Not running! This script is meant to be run in the jMonkeyEngine dev container environment, and may do unexpected things if run elsewhere."
+ exit 1
+fi
+
+# Init home
+mkdir -p "$HOME/.config" "$HOME/.cache" "$HOME/.local/share"
+
+
+# Start window manager
+if ! pgrep -u "$(id -u)" -x xfwm4 >/dev/null 2>&1; then
+ nohup xfwm4 --compositor=off --daemon >/tmp/xfwm4.log 2>&1 &
+fi
+
+
+# Start XFCE session
+if ! pgrep -u "$(id -u)" -x xfce4-session >/dev/null 2>&1; then
+ nohup xfce4-session >/tmp/xfce4-session.log 2>&1 &
+fi
+
+# Set wallpaper
+feh --no-fehbg --bg-fill "/root/wallpaper.jpg"
+
+# Start PulseAudio for app sound forwarding (used by Xpra speaker stream).
+if command -v pulseaudio >/dev/null 2>&1; then
+ if ! pgrep -u "$(id -u)" -x pulseaudio >/dev/null 2>&1; then
+ nohup pulseaudio --start >/tmp/pulseaudio.log 2>&1 || true
+ fi
+fi
+
+# Start VNC server (no password; fine for Codespaces)
+if ! pgrep -f "x11vnc.*-rfbport 5900" >/dev/null 2>&1; then
+ nohup x11vnc -display "${DISPLAY}" -nopw -forever -shared -cursor arrow -rfbport 5900 \
+ -nowf -noxdamage -xwarppointer -noxrecord -noxfixes >/tmp/x11vnc.log 2>&1 &
+fi
+
+# Start noVNC (websockify)
+if ! pgrep -f "websockify.*6080" >/dev/null 2>&1; then
+ python3 -m websockify --web="${NOVNC_WEB}" 6080 localhost:5900
+fi
+
diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
deleted file mode 100644
index 6ff2d099fa..0000000000
--- a/.github/workflows/format.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: auto-format
-on:
- push:
-
-jobs:
- format:
- runs-on: ubuntu-latest
- if: ${{ false }}
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Prettify code
- uses: creyD/prettier_action@v4.3
- with:
- prettier_options: --tab-width 4 --print-width 110 --write **/**/*.java
- prettier_version: "2.8.8"
- only_changed: True
- commit_message: "auto-format"
- prettier_plugins: "prettier-plugin-java"
diff --git a/.gitignore b/.gitignore
index 121fd33ac3..acb22783d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,4 +50,5 @@ javadoc_deploy.pub
!.vscode/settings.json
!.vscode/JME_style.xml
!.vscode/extensions.json
+!.vscode/java.code-snippets
joysticks-*.txt
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index a1538208b3..cf20732ef1 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,6 +1,9 @@
{
- "recommendations": [
- "vscjava.vscode-java-pack",
- "slevesque.shader"
- ]
-}
+ "recommendations": [
+ "vscjava.vscode-java-pack",
+ "slevesque.shader",
+ "ms-vscode-remote.remote-containers",
+ "GitHub.copilot-chat",
+ "ms-vscode.remote-server"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/java.code-snippets b/.vscode/java.code-snippets
new file mode 100644
index 0000000000..7c67647e00
--- /dev/null
+++ b/.vscode/java.code-snippets
@@ -0,0 +1,54 @@
+{
+
+ "logger":{
+ "prefix":"logger",
+ "body": [
+ "private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(${1:${TM_FILENAME_BASE}}.class.getName());"
+ ],
+ "description":"Add java.util Logger"
+ },
+ "log":{
+ "prefix": "log",
+ "body":[
+ "if(logger.isLoggable(java.util.logging.Level.$1 )){\n\tlogger.log(java.util.logging.Level.$1, \"$2\");\n}"
+ ],
+
+ },
+ "logfinest":{
+ "prefix": "logfinest",
+ "body":[
+ "logger.finest($1);"
+ ]
+ },
+ "logfiner":{
+ "prefix": "logfiner",
+ "body":[
+ "logger.finer($1);"
+ ]
+ },
+ "logfine":{
+ "prefix": "logfine",
+ "body":[
+ "logger.fine($1);"
+ ]
+ },
+ "loginfo":{
+ "prefix": "loginfo",
+ "body":[
+ "logger.info($1);"
+ ]
+ },
+ "logwarning":{
+ "prefix": "logwarning",
+ "body":[
+ "logger.warning($1);"
+ ]
+ },
+ "logsevere":{
+ "prefix": "logsevere",
+ "body":[
+ "logger.severe($1);"
+ ]
+ }
+
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 89d691dd52..e6cc75a894 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,15 +1,8 @@
{
- "java.configuration.updateBuildConfiguration": "automatic",
"java.compile.nullAnalysis.mode": "automatic",
- "java.refactor.renameFromFileExplorer": "prompt",
- "java.format.settings.url": "./.vscode/JME_style.xml",
- "editor.formatOnPaste": true,
+ "java.format.settings.url": "${workspaceFolder}/.vscode/JME_style.xml",
+ "editor.formatOnPaste": false,
"editor.formatOnType": false,
- "editor.formatOnSave": true,
- "editor.formatOnSaveMode": "modifications" ,
-
- "prettier.tabWidth": 4,
- "prettier.printWidth": 110,
- "prettier.enable": true,
- "prettier.resolveGlobalModules": true
+ "editor.formatOnSave": false,
+ "editor.formatOnSaveMode": "modifications",
}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e6441136f3..8bdaf60c75 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a4413138c9..2e1113280e 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index b740cf1339..adff685a03 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
#!/bin/sh
#
-# Copyright © 2015-2021 the original authors.
+# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
#
@@ -84,7 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -112,7 +114,6 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -170,7 +171,6 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -203,15 +203,14 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
diff --git a/gradlew.bat b/gradlew.bat
index 7101f8e467..e509b2dd8f 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@@ -68,11 +70,10 @@ goto fail
:execute
@rem Setup the command line
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java b/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java
index ec89b9df06..887f7348e6 100644
--- a/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java
+++ b/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java
@@ -129,7 +129,7 @@ private void initOpenAL() {
if (!alc.isCreated()) {
alc.createALC();
}
- } catch (UnsatisfiedLinkError ex) {
+ } catch (Exception ex) {
logger.log(Level.SEVERE, "Failed to load audio library (OpenAL). Audio will be disabled.", ex);
audioDisabled = true;
return;
diff --git a/jme3-core/src/main/java/com/jme3/system/AppSettings.java b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
index 92354ff91e..8c154b46ea 100644
--- a/jme3-core/src/main/java/com/jme3/system/AppSettings.java
+++ b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
@@ -296,12 +296,12 @@ public final class AppSettings extends HashMap {
static {
defaults.put("Display", 0);
defaults.put("CenterWindow", true);
- defaults.put("Width", 640);
- defaults.put("Height", 480);
+ defaults.put("Width", 1440);
+ defaults.put("Height", 900);
defaults.put("WindowWidth", Integer.MIN_VALUE);
defaults.put("WindowHeight", Integer.MIN_VALUE);
defaults.put("BitsPerPixel", 24);
- defaults.put("Frequency", 60);
+ defaults.put("Frequency", 0);
defaults.put("DepthBits", 24);
defaults.put("StencilBits", 0);
defaults.put("Samples", 0);
@@ -317,7 +317,7 @@ public final class AppSettings extends HashMap {
defaults.put("MinHeight", 0);
defaults.put("MinWidth", 0);
defaults.put("GammaCorrection", true);
- defaults.put("Resizable", false);
+ defaults.put("Resizable", true);
defaults.put("SwapBuffers", true);
defaults.put("OpenCL", false);
defaults.put("OpenCLPlatformChooser", DefaultPlatformChooser.class.getName());
diff --git a/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java b/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
index c9d8b79182..3f31c7adb6 100644
--- a/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
+++ b/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
@@ -66,7 +66,13 @@ public abstract class JmeSystemDelegate {
protected Consumer errorMessageHandler = (message) -> {
JmeDialogsFactory dialogFactory = null;
try {
- dialogFactory = (JmeDialogsFactory)Class.forName("com.jme3.system.JmeDialogsFactoryImpl").getConstructor().newInstance();
+ String dialogFactoryClass = System.getenv("JME3_DIALOGS_FACTORY");
+ if(dialogFactoryClass == null) {
+ dialogFactoryClass = System.getProperty("jme3.dialogsFactory","com.jme3.system.JmeDialogsFactoryImpl");
+ }
+ if(dialogFactoryClass != null && !dialogFactoryClass.trim().isEmpty()){
+ dialogFactory = (JmeDialogsFactory)Class.forName(dialogFactoryClass).getConstructor().newInstance();
+ }
} catch(ClassNotFoundException e){
logger.warning("JmeDialogsFactory implementation not found.");
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
@@ -79,7 +85,14 @@ public abstract class JmeSystemDelegate {
protected BiFunction settingsHandler = (settings,loadFromRegistry) -> {
JmeDialogsFactory dialogFactory = null;
try {
- dialogFactory = (JmeDialogsFactory)Class.forName("com.jme3.system.JmeDialogsFactoryImpl").getConstructor().newInstance();
+ String dialogFactoryClass = System.getenv("JME3_DIALOGS_FACTORY");
+ if(dialogFactoryClass == null) {
+ dialogFactoryClass = System.getProperty("jme3.dialogsFactory","com.jme3.system.JmeDialogsFactoryImpl");
+ }
+ if(dialogFactoryClass != null && !dialogFactoryClass.trim().isEmpty()){
+ dialogFactory = (JmeDialogsFactory)Class.forName(dialogFactoryClass).getConstructor().newInstance();
+ }
+ dialogFactory = (JmeDialogsFactory)Class.forName(dialogFactoryClass).getConstructor().newInstance();
} catch(ClassNotFoundException e){
logger.warning("JmeDialogsFactory implementation not found.");
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {