Compare commits

..

92 Commits

Author SHA1 Message Date
Kirill Vainer 74a1d8b219 Merge branch 'master' into experimental 9 years ago
Kirill Vainer 3bb01d6963 Merge remote-tracking branch 'origin/master' into experimental 9 years ago
Kirill Vainer 4fcd575c47 MPO: fix unit test 9 years ago
Kirill Vainer 60d9d1b4d8 unit test: more descriptive failure message 9 years ago
Kirill Vainer 4ab5a9f7dd SkeletonControl: fix syntax error 9 years ago
Kirill Vainer 452c307d59 fix misc unit test issues due to merge 9 years ago
Kirill Vainer a8fca2bcf6 Merge branch 'master' into experimental 9 years ago
Kirill Vainer 2fc4e5b607 jinput: fix native loading 9 years ago
Kirill Vainer f28d74a1f6 joystick: use jinput backend for lwjgl3 9 years ago
Kirill Vainer 87af1f30b0 MPO: clone MPOs instead of sharing references 9 years ago
Kirill Vainer e691de4459 fix null checks 9 years ago
Kirill Vainer 2dafd1e485 MPO: add null override list check 9 years ago
Kirill Vainer c586bacbb0 MPO: clear param for null textures 9 years ago
Kirill Vainer fde095458e MPO: add javadoc 9 years ago
Kirill Vainer e8fd22223a MPO: use List instead of ArrayList 9 years ago
Kirill Vainer 53d3b72478 MPO: add ability to disable an override 9 years ago
Kirill Vainer 644b8167b8 MPO: add example 9 years ago
Kirill Vainer 2cdb4a8486 spatial: fix bug in remove/clear MPO 9 years ago
Kirill Vainer 152a7638cd material: fix sort id unit test failure 9 years ago
Kirill Vainer adc5084f5d MPO: implement overrides on uniforms and add test 9 years ago
Kirill Vainer 42d76cfd29 MPO: implement propagation and add test 9 years ago
Kirill Vainer ba22487c38 material: move technique logic into its own package 9 years ago
Kirill Vainer 00b6d904af add StaticPassLightingLogic 9 years ago
Kirill Vainer 2d2c394b42 Merge remote-tracking branch 'origin/master' into experimental 9 years ago
Kirill Vainer 655457ab6a Merge branch 'master' into experimental 9 years ago
Kirill Vainer 7639657fc1 initial implementation of MPO (untested!) 9 years ago
Kirill Vainer e87f008244 build: fix missing version tag 9 years ago
Kirill Vainer 12b3c4a140 build: fix build error 9 years ago
Kirill Vainer ae7fb6984c lwjgl3: re-enable native loading for native bullet 9 years ago
Kirill Vainer 3b9e412f80 build: fix build errors 9 years ago
Kirill Vainer 0aaa28e66b Merge branch 'master' into experimental 9 years ago
Kirill Vainer 9b45189f48 lwjgl3: start jME3 on main thread (needed for mac) 9 years ago
Kirill Vainer 69eaf39da9 lwjgl3: fix syntax error 9 years ago
Kirill Vainer 8024babb47 lwjgl3: use lwjgl's native loader 9 years ago
Kirill Vainer c7da1c4efd desktop: don't show dialogs when headless 9 years ago
Kirill Vainer ab8527770c GLRenderer: support VBO without VAO 9 years ago
Kirill Vainer c6b568c125 test: disable NativeLibraryLoaderIT 9 years ago
Kirill Vainer 772330c308 test: delete ApplicationTest 9 years ago
Kirill Vainer 8413ed715c point particles: various fixes 9 years ago
Kirill Vainer d76cb99772 point particles: improve performance by x3 9 years ago
Kirill Vainer 454e210d3d native library: don't run unit test 9 years ago
Kirill Vainer c6336c0781 version: new versioning scheme for tags 9 years ago
Kirill Vainer fda40563c5 build: don't build SDK or javadoc 9 years ago
Kirill Vainer 34aa21bfd9 Get rid of TestAwtPanels (it sucks) 9 years ago
Kirill Vainer f9969008c3 syntax error fixes 9 years ago
Kirill Vainer 2893ac9156 DDSLoader: fix syntax error 9 years ago
Kirill Vainer a3638f3e0c Merge branch 'master' into experimental 9 years ago
Kirill Vainer 27041e1341 LWJGL3 improvements 9 years ago
Kirill Vainer 962ab22ef4 Merge branch 'fbx-import-animation' into experimental 9 years ago
Kirill Vainer f9500f955f Merge branch 'renderer-rgtc' into experimental 9 years ago
Kirill Vainer c50839796f Merge branch 'renderer-fbreadasync' into experimental 9 years ago
Kirill Vainer ff6b1be725 Merge branch 'renderer-improvements' into experimental 9 years ago
Kirill Vainer 97281de5c4 Merge branch 'new_material_system' into experimental 9 years ago
Kirill Vainer 8f54af3263 Merge remote-tracking branch 'origin/master' into experimental 9 years ago
Kirill Vainer 79125f2f63 remove useless TestNativeLoader 9 years ago
Kirill Vainer 908b37350d remove XXX HACK from native library loader 9 years ago
Kirill Vainer f986043745 minor formatting changes 9 years ago
Kirill Vainer 961bf92734 lwjgl test: fix build exceed timeout 9 years ago
Kirill Vainer 3d82f5c459 lwjgl: add unit test 9 years ago
Kirill Vainer 4a646de49d gitignore: more cleanup 9 years ago
Kirill Vainer 06e8210e5d gitignore: cleanup 9 years ago
Kirill Vainer 85feb305ef SDK: fix build error 9 years ago
Kirill Vainer 15465a020f Merge branch 'master' into expermiental 9 years ago
Kirill Vainer f005c05f8d OffscreenBuffer: check needClose after runLoop 9 years ago
Kirill Vainer 42729b2302 FastMathTest: ignore failing test (for now) 9 years ago
Kirill Vainer 30855f5bb4 TestShaderNodes: fix build error 9 years ago
Kirill Vainer 352c02db8a DefineList: fix build error 9 years ago
Kirill Vainer ea4d750d52 RM: per-pass render method 9 years ago
Kirill Vainer 6db1d15045 Image: support for RGTC format 9 years ago
Kirill Vainer f9ce9e246c FBX: add ear clipping triangulator 9 years ago
Kirill Vainer 18db26292f Add the new material system 9 years ago
Kirill Vainer 0d3ebf75bd GLRenderer: fix NPE when using mesh without index buffer 10 years ago
Kirill Vainer 4e572605a8 GLRenderer: merge changes from master 10 years ago
Kirill Vainer 28e2b5650c GLRenderer: disable global VAO, since VAO is now supported 10 years ago
Kirill Vainer 3d2a9b83e9 JOGL: fix syntax error due to missing renderer 10 years ago
Kirill Vainer 618c8d02eb JOGL: delete old / broken renderer 10 years ago
Kirill Vainer 3a00aff886 GLRenderer: clear VBO bind state after bounding VAO 10 years ago
Kirill Vainer fc680ea121 GLRenderer: use luminance instead of intensity in compare R to texture 10 years ago
Kirill Vainer 12c001addc Uniform: fix crash when using vector4array 10 years ago
Kirill Vainer 7b147171bf VAO: changes to test 10 years ago
Kirill Vainer 2e9a9f9f9e Add test for VAO 10 years ago
Kirill Vainer c72b036c9f VirtualIndexBuffer: fix compile error 10 years ago
Kirill Vainer 81a76fdf69 Mesh: preliminary work to use ubyte weights for hardware skinning 10 years ago
Kirill Vainer 7b64e91681 GLRenderer: remaining portion of VAO support 10 years ago
Kirill Vainer d2f38f8adb GLRenderer: added fast uniforms - still need to fix Uniform.clear() 10 years ago
Kirill Vainer 937d97b8d7 GLRenderer: initial VAO support (still buggy) 10 years ago
Kirill Vainer 9e17f39cfb FBX: include main folder for shared plugins API 10 years ago
Kirill Vainer 2ced7653a7 FBX: more work on importing skeletal animation 10 years ago
Kirill Vainer f0b63e7910 GLRenderer: the actual async FB read changes 10 years ago
Kirill Vainer 860de88298 GLRenderer: initial commit of async FB read (including jme panels) 10 years ago
Kirill Vainer e8f344a0db GLRenderer: remaining portion of VAO support 10 years ago
Kirill Vainer bee759bddc GLRenderer: initial VAO support (still buggy) 10 years ago
  1. 93
      .github/actions/tools/bintray.sh
  2. 85
      .github/actions/tools/uploadToMaven.sh
  3. 554
      .github/workflows/main.yml
  4. 34
      .gitignore
  5. 59
      .travis.yml
  6. 13
      CONTRIBUTING.md
  7. 29
      LICENSE
  8. 39
      README.md
  9. 162
      build.gradle
  10. 6
      common-android-app.gradle
  11. 72
      common.gradle
  12. 91
      gradle.properties
  13. BIN
      gradle/wrapper/gradle-wrapper.jar
  14. 3
      gradle/wrapper/gradle-wrapper.properties
  15. 98
      gradlew
  16. 30
      gradlew.bat
  17. 1
      jme3-android-examples/.gitignore
  18. 66
      jme3-android-examples/build.gradle
  19. 17
      jme3-android-examples/proguard-rules.pro
  20. 13
      jme3-android-examples/src/androidTest/java/org/jmonkeyengine/jme3androidexamples/ApplicationTest.java
  21. 56
      jme3-android-examples/src/main/AndroidManifest.xml
  22. BIN
      jme3-android-examples/src/main/assets/mouse.xcf
  23. 39
      jme3-android-examples/src/main/java/jme3test/android/TestAndroidResources.java
  24. 314
      jme3-android-examples/src/main/java/jme3test/android/TestAndroidSensors.java
  25. 354
      jme3-android-examples/src/main/java/jme3test/android/TestAndroidTouch.java
  26. 12
      jme3-android-examples/src/main/java/jme3test/android/TestChooserAndroid.java
  27. 165
      jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/CustomArrayAdapter.java
  28. 85
      jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/JmeFragment.java
  29. 458
      jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/MainActivity.java
  30. 111
      jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/TestActivity.java
  31. BIN
      jme3-android-examples/src/main/res/drawable-hdpi/drawable_monkey.png
  32. BIN
      jme3-android-examples/src/main/res/drawable-ldpi/drawable_monkey.png
  33. BIN
      jme3-android-examples/src/main/res/drawable-mdpi/drawable_monkey.png
  34. BIN
      jme3-android-examples/src/main/res/drawable-xhdpi/drawable_monkey.png
  35. BIN
      jme3-android-examples/src/main/res/drawable/keyboard.png
  36. BIN
      jme3-android-examples/src/main/res/drawable/monkey256.png
  37. BIN
      jme3-android-examples/src/main/res/drawable/monkey256_9.9.png
  38. BIN
      jme3-android-examples/src/main/res/drawable/monkey512.png
  39. BIN
      jme3-android-examples/src/main/res/drawable/monkey512_9.9.png
  40. BIN
      jme3-android-examples/src/main/res/drawable/mouse_disabled.png
  41. BIN
      jme3-android-examples/src/main/res/drawable/mouse_left.png
  42. BIN
      jme3-android-examples/src/main/res/drawable/mouse_none.png
  43. BIN
      jme3-android-examples/src/main/res/drawable/nonselected.png
  44. BIN
      jme3-android-examples/src/main/res/drawable/phone_landscape.png
  45. BIN
      jme3-android-examples/src/main/res/drawable/selected.png
  46. 25
      jme3-android-examples/src/main/res/layout/activity_test.xml
  47. 119
      jme3-android-examples/src/main/res/layout/test_chooser_layout.xml
  48. 30
      jme3-android-examples/src/main/res/layout/test_chooser_row.xml
  49. 33
      jme3-android-examples/src/main/res/menu/menu_items.xml
  50. 19
      jme3-android-examples/src/main/res/menu/test_menu_items.xml
  51. BIN
      jme3-android-examples/src/main/res/mipmap-hdpi/mipmap_monkey.png
  52. BIN
      jme3-android-examples/src/main/res/mipmap-mdpi/mipmap_monkey.png
  53. BIN
      jme3-android-examples/src/main/res/mipmap-xhdpi/mipmap_monkey.png
  54. BIN
      jme3-android-examples/src/main/res/mipmap-xxhdpi/mipmap_monkey.png
  55. BIN
      jme3-android-examples/src/main/res/mipmap-xxxhdpi/mipmap_monkey.png
  56. 6
      jme3-android-examples/src/main/res/values-w820dp/dimens.xml
  57. 6
      jme3-android-examples/src/main/res/values/colors.xml
  58. 5
      jme3-android-examples/src/main/res/values/dimens.xml
  59. 30
      jme3-android-examples/src/main/res/values/strings.xml
  60. 11
      jme3-android-examples/src/main/res/values/styles.xml
  61. 15
      jme3-android-examples/src/test/java/org/jmonkeyengine/jme3androidexamples/ExampleUnitTest.java
  62. 2
      jme3-android-native/.gitignore
  63. 2
      jme3-android-native/build.gradle
  64. 37
      jme3-android-native/decode.gradle
  65. BIN
      jme3-android-native/libs/decode/arm64-v8a/libdecodejme.so
  66. BIN
      jme3-android-native/libs/decode/armeabi-v7a/libdecodejme.so
  67. BIN
      jme3-android-native/libs/decode/armeabi/libdecodejme.so
  68. BIN
      jme3-android-native/libs/decode/mips/libdecodejme.so
  69. BIN
      jme3-android-native/libs/decode/mips64/libdecodejme.so
  70. BIN
      jme3-android-native/libs/decode/x86/libdecodejme.so
  71. BIN
      jme3-android-native/libs/decode/x86_64/libdecodejme.so
  72. BIN
      jme3-android-native/libs/openalsoft/arm64-v8a/libopenalsoftjme.so
  73. BIN
      jme3-android-native/libs/openalsoft/armeabi-v7a/libopenalsoftjme.so
  74. BIN
      jme3-android-native/libs/openalsoft/armeabi/libopenalsoftjme.so
  75. BIN
      jme3-android-native/libs/openalsoft/mips/libopenalsoftjme.so
  76. BIN
      jme3-android-native/libs/openalsoft/mips64/libopenalsoftjme.so
  77. BIN
      jme3-android-native/libs/openalsoft/x86/libopenalsoftjme.so
  78. BIN
      jme3-android-native/libs/openalsoft/x86_64/libopenalsoftjme.so
  79. 42
      jme3-android-native/openalsoft.gradle
  80. 4
      jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c
  81. 2
      jme3-android-native/src/native/jme_decode/com_jme3_texture_plugins_AndroidNativeImageLoader.c
  82. 2
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.c
  83. 173
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.h
  84. 4
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.c
  85. 77
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.h
  86. 4
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.c
  87. 101
      jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.h
  88. 9
      jme3-android/build.gradle
  89. 16
      jme3-android/src/main/java/com/jme3/app/AndroidHarness.java
  90. 23
      jme3-android/src/main/java/com/jme3/app/AndroidHarnessFragment.java
  91. 22
      jme3-android/src/main/java/com/jme3/app/DefaultAndroidProfiler.java
  92. 20
      jme3-android/src/main/java/com/jme3/app/R.java
  93. 4
      jme3-android/src/main/java/com/jme3/app/state/MjpegFileWriter.java
  94. 27
      jme3-android/src/main/java/com/jme3/app/state/VideoRecorderAppState.java
  95. 136
      jme3-android/src/main/java/com/jme3/asset/AndroidImageInfo.java
  96. 160
      jme3-android/src/main/java/com/jme3/asset/plugins/AndroidLocator.java
  97. 20
      jme3-android/src/main/java/com/jme3/audio/android/AndroidAL.java
  98. 8
      jme3-android/src/main/java/com/jme3/audio/android/AndroidALC.java
  99. 11
      jme3-android/src/main/java/com/jme3/audio/android/AndroidEFX.java
  100. 533
      jme3-android/src/main/java/com/jme3/audio/android/AndroidMediaPlayerAudioRenderer.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,93 +0,0 @@
#!/bin/bash
# bintray_createPackage [REPO] [PACKAGE] [USER] [PASSWORD] [GIT REPO] [LICENSE]
function bintray_createPackage {
repo="$1"
package="$2"
user="$3"
password="$4"
srcrepo="$5"
license="$6"
repoUrl="https://api.bintray.com/packages/$repo"
if [ "`curl -u$user:$password -H Content-Type:application/json -H Accept:application/json \
--write-out %{http_code} --silent --output /dev/null -X GET \"$repoUrl/$package\"`" != "200" ];
then
if [ "$srcrepo" != "" -a "$license" != "" ];
then
echo "Package does not exist... create."
data="{
\"name\": \"${package}\",
\"labels\": [],
\"licenses\": [\"${license}\"],
\"vcs_url\": \"${srcrepo}\"
}"
curl -u$user:$password -H "Content-Type:application/json" -H "Accept:application/json" -X POST \
-d "${data}" "$repoUrl"
else
echo "Package does not exist... you need to specify a repo and license for it to be created."
fi
else
echo "The package already exists. Skip."
fi
}
# uploadFile file destination [REPO] "content" [PACKAGE] [USER] [PASSWORD] [SRCREPO] [LICENSE]
function bintray_uploadFile {
file="$1"
dest="$2"
echo "Upload $file to $dest"
repo="$3"
type="$4"
package="$5"
user="$6"
password="$7"
srcrepo="$8"
license="$9"
publish="${10}"
bintray_createPackage $repo $package $user $password $srcrepo $license
url="https://api.bintray.com/$type/$repo/$package/$dest"
if [ "$publish" = "true" ]; then url="$url;publish=1"; fi
curl -T "$file" -u$user:$password "$url"
}
function bintray_uploadAll {
path="$1"
destpath="$2"
repo="$3"
type="$4"
package="$5"
user="$6"
password="$7"
srcrepo="$8"
license="$9"
publish="${10}"
cdir="$PWD"
cd "$path"
files="`find . -type f -print`"
IFS="
"
set -f
for f in $files; do
destfile="$destpath/${f:2}"
bintray_uploadFile $f $destfile $repo $type $package $user $password $srcrepo $license $publish
done
set +f
unset IFS
cd "$cdir"
}

@ -1,85 +0,0 @@
#!/bin/bash
#############################################
#
# Usage
# uploadAllToMaven path/of/dist/maven https://api.bintray.com/maven/riccardo/sandbox-maven/ riccardo $BINTRAY_PASSWORD gitrepo license
# Note: gitrepo and license are needed only when uploading to bintray if you want to create missing packages automatically
# gitrepo must be a valid source repository
# license must be a license supported by bintray eg "BSD 3-Clause"
# or
# uploadAllToMaven path/of/dist/maven $GITHUB_PACKAGE_REPOSITORY user password
#
#############################################
root="`dirname ${BASH_SOURCE[0]}`"
source $root/bintray.sh
set -e
function uploadToMaven {
file="$1"
destfile="$2"
repourl="$3"
user="$4"
password="$5"
srcrepo="$6"
license="$7"
auth=""
if [ "$user" != "token" ];
then
echo "Upload with username $user and password"
auth="-u$user:$password"
else
echo "Upload with token"
auth="-H \"Authorization: token $password\""
fi
if [[ $repourl == https\:\/\/api.bintray.com\/* ]];
then
package="`dirname $destfile`"
version="`basename $package`"
package="`dirname $package`"
package="`basename $package`"
if [ "$user" = "" -o "$password" = "" ];
then
echo "Error! You need username and password to upload to bintray"
exit 1
fi
echo "Detected bintray"
bintrayRepo="${repourl/https\:\/\/api.bintray.com\/maven/}"
echo "Create package on $bintrayRepo"
bintray_createPackage $bintrayRepo $package $user $password $srcrepo $license
repourl="$repourl/$package"
fi
cmd="curl -T \"$file\" $auth \
\"$repourl/$destfile\" \
-vvv"
echo "Run $cmd"
eval "$cmd"
}
export -f uploadToMaven
function uploadAllToMaven {
path="$1"
cdir="$PWD"
cd "$path"
files="`find . \( -name "*.jar" -o -name "*.pom" \) -type f -print`"
IFS="
"
set -f
for art in $files; do
art="${art:2}"
uploadToMaven "$art" "$art" ${@:2}
done
set +f
unset IFS
cd "$cdir"
}

@ -1,554 +0,0 @@
######################################################################################
# JME CI/CD
######################################################################################
# Quick overview of what is going on in this script:
# - Build natives for android
# - Build natives for linux arm
# - Build natives for windows,mac,linux x86_64 and x86
# - Merge the natives, build the engine, create the zip release, maven artifacts, javadoc and native snapshot
# - (only when there is a change in the native code) Deploy the native snapshot to bintray
# - (only when building a release) Deploy everything else to github releases, github packet registry and bintray
# - (only when building a release) Update javadoc.jmonkeyengine.org
# Note:
# All the actions/upload-artifact and actions/download-artifact steps are used to pass
# stuff between jobs, github actions has some sort of storage that is local to the
# running workflow, we use it to store the result of each job since the filesystem
# is not maintained between jobs.
################# CONFIGURATIONS #####################################################
# >> Configure BINTRAY RELEASE & NATIVE SNAPSHOT
# Configure the following secrets/variables (customize the values with your own)
# BINTRAY_GENERIC_REPO=riccardoblsandbox/jmonkeyengine-files
# BINTRAY_MAVEN_REPO=riccardoblsandbox/jmonkeyengine
# BINTRAY_USER=riccardo
# BINTRAY_APIKEY=XXXXXX
# BINTRAY_LICENSE="BSD 3-Clause"
# >> Configure PACKAGE REGISTRY RELEASE
# Nothing to do here, everything is autoconfigured to work with the account/org that
# is running the build.
# >> Configure JAVADOC
# JAVADOC_GHPAGES_REPO="riccardoblsandbox/javadoc.jmonkeyengine.org.git"
# Generate a deloy key
# ssh-keygen -t rsa -b 4096 -C "actions@users.noreply.github.com" -f javadoc_deploy
# Set
# JAVADOC_GHPAGES_DEPLOY_PRIVKEY="......."
# In github repo -> Settings, use javadoc_deploy.pub as Deploy key with write access
######################################################################################
# Resources:
# - Github actions docs: https://help.github.com/en/articles/about-github-actions
# - Package registry docs: https://help.github.com/en/articles/about-github-package-registry
# - Official actions: https://github.com/actions
# - Community actions: https://github.com/sdras/awesome-actions
######################################################################################
# - Riccardo Balbo
######################################################################################
name: Build jMonkeyEngine
on:
push:
branches:
- master
- newbuild
- v3.3.*
- v3.2
- v3.2.*
pull_request:
release:
types: [published]
jobs:
# Builds the natives on linux arm
BuildLinuxArmNatives:
name: Build natives for linux (arm)
runs-on: ubuntu-18.04
container:
image: riccardoblb/buildenv-jme3:linuxArm
steps:
- name: Clone the repo
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Validate the Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Build
run: |
# Build
# Note: since this is crossbuild we use the buildForPlatforms filter to tell
# the buildscript wich platforms it should build for.
./gradlew -PuseCommitHashAsVersionName=true --no-daemon -PbuildForPlatforms=LinuxArm,LinuxArmHF,LinuxArm64 -PbuildNativeProjects=true \
:jme3-bullet-native:assemble
- name: Upload natives
uses: actions/upload-artifact@master
with:
name: linuxarm-natives
path: build/native
# Build the natives on android
BuildAndroidNatives:
name: Build natives for android
runs-on: ubuntu-18.04
container:
image: riccardoblb/buildenv-jme3:android
steps:
- name: Clone the repo
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Validate the Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Build
run: |
./gradlew -PuseCommitHashAsVersionName=true --no-daemon -PbuildNativeProjects=true \
:jme3-android-native:assemble \
:jme3-bullet-native-android:assemble
- name: Upload natives
uses: actions/upload-artifact@master
with:
name: android-natives
path: build/native
# Build the natives
BuildNatives:
strategy:
fail-fast: true
matrix:
os: [ubuntu-18.04,windows-2019,macOS-latest]
jdk: [8.x.x]
include:
- os: ubuntu-18.04
osName: linux
- os: windows-2019
osName: windows
- os: macOS-latest
osName: mac
name: Build natives for ${{ matrix.osName }}
runs-on: ${{ matrix.os }}
steps:
- name: Clone the repo
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Prepare java environment
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.jdk }}
architecture: x64
- name: Validate the Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Build Natives
shell: bash
env:
OS_NAME: ${{ matrix.osName }}
run: |
# Install dependencies
if [ "$OS_NAME" = "mac" ];
then
echo "Prepare mac"
elif [ "$OS_NAME" = "linux" ];
then
echo "Prepare linux"
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib
else
echo "Prepare windows"
fi
# Build
./gradlew -PuseCommitHashAsVersionName=true --no-daemon -PbuildNativeProjects=true -Dmaven.repo.local="$PWD/dist/maven" \
build \
:jme3-bullet-native:build
# Upload natives to be used later by the BuildJMonkey job
- name: Upload natives
uses: actions/upload-artifact@master
with:
name: ${{ matrix.osName }}-natives
path: build/native
# Build the engine, we only deploy from ubuntu-18.04 jdk8
BuildJMonkey:
needs: [BuildNatives,BuildAndroidNatives]
name: Build on ${{ matrix.osName }} jdk${{ matrix.jdk }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [ubuntu-18.04,windows-2019,macOS-latest]
jdk: [8.x.x,11.x.x]
include:
- os: ubuntu-18.04
osName: linux
deploy: true
- os: windows-2019
osName: windows
- os: macOS-latest
osName: mac
- jdk: 11.x.x
deploy: false
steps:
- name: Clone the repo
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Setup the java environment
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.jdk }}
architecture: x64
- name: Download natives for linux
uses: actions/download-artifact@master
with:
name: linux-natives
path: build/native
- name: Download natives for windows
uses: actions/download-artifact@master
with:
name: windows-natives
path: build/native
- name: Download natives for mac
uses: actions/download-artifact@master
with:
name: mac-natives
path: build/native
- name: Download natives for android
uses: actions/download-artifact@master
with:
name: android-natives
path: build/native
- name: Download natives for linux (arm)
uses: actions/download-artifact@master
with:
name: linuxarm-natives
path: build/native
- name: Validate the Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Build Engine
shell: bash
run: |
# Build
./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true build
if [ "${{ matrix.deploy }}" = "true" ];
then
# We are going to need "zip"
sudo apt-get update
sudo apt-get install -y zip
# Create the zip release and the javadoc
./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true mergedJavadoc createZipDistribution
# We prepare the release for deploy
mkdir -p ./dist/release/
mv build/distributions/*.zip dist/release/
# Create the maven artifacts
mkdir -p ./dist/maven/
./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true install -Dmaven.repo.local="$PWD/dist/maven"
# Zip the natives into a single archive (we are going to use this to deploy native snapshots)
echo "Create native zip"
cdir="$PWD"
cd "build/native"
zip -r "$cdir/dist/jme3-natives.zip" *
cd "$cdir"
echo "Done"
fi
# Used later by DeploySnapshot
- name: Upload merged natives
if: matrix.deploy==true
uses: actions/upload-artifact@master
with:
name: natives
path: dist/jme3-natives.zip
# Upload maven artifacts to be used later by the deploy job
- name: Upload maven artifacts
if: matrix.deploy==true
uses: actions/upload-artifact@master
with:
name: maven
path: dist/maven
- name: Upload javadoc
if: matrix.deploy==true
uses: actions/upload-artifact@master
with:
name: javadoc
path: dist/javadoc
# Upload release archive to be used later by the deploy job
- name: Upload release
if: github.event_name == 'release' && matrix.deploy==true
uses: actions/upload-artifact@master
with:
name: release
path: dist/release
# This job deploys the native snapshot.
# The snapshot is downloaded when people build the engine without setting buildNativeProject
# this is useful for people that want to build only the java part and don't have
# all the stuff needed to compile natives.
DeploySnapshot:
needs: [BuildJMonkey]
name: "Deploy snapshot"
runs-on: ubuntu-18.04
if: github.event_name == 'push'
steps:
# We clone the repo manually, since we are going to push back a reference to the snapshot
- name: Clone the repo
run: |
branch="${GITHUB_REF//refs\/heads\//}"
if [ "$branch" != "" ];
then
git clone --single-branch --branch "$branch" https://github.com/${GITHUB_REPOSITORY}.git .
fi
- name: Download merged natives
uses: actions/download-artifact@master
with:
name: natives
path: dist/
- name: Deploy natives snapshot
run: |
source .github/actions/tools/bintray.sh
NATIVE_CHANGES="yes"
branch="${GITHUB_REF//refs\/heads\//}"
if [ "$branch" != "" ];
then
if [ -f "natives-snapshot.properties" ];
then
nativeSnapshot=`cat "natives-snapshot.properties"`
nativeSnapshot="${nativeSnapshot#*=}"
# We deploy ONLY if GITHUB_SHA (the current commit hash) is newer than $nativeSnapshot
if [ "`git rev-list --count $nativeSnapshot..$GITHUB_SHA`" = "0" ];
then
NATIVE_CHANGES=""
else
# We check if the native code changed.
echo "Detect changes"
NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-bullet-native/)"
if [ "$NATIVE_CHANGES" = "" ];then NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-android-native/)"; fi
if [ "$NATIVE_CHANGES" = "" ];then NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-bullet-native-android/)"; fi
if [ "$NATIVE_CHANGES" = "" ];then NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-bullet/)"; fi
# The bulletUrl (in gradle.properties) might have changed.
if [ "$NATIVE_CHANGES" = "" ];then NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- gradle.properties)"; fi
fi
fi
# We do nothing if there is no change
if [ "$NATIVE_CHANGES" = "" ];
then
echo "No changes, skip."
else
if [ "${{ secrets.BINTRAY_GENERIC_REPO }}" = "" ];
then
echo "Configure the following secrets to enable native snapshot deployment"
echo "BINTRAY_GENERIC_REPO, BINTRAY_USER, BINTRAY_APIKEY"
else
# Deploy snapshot
bintray_uploadFile dist/jme3-natives.zip \
$GITHUB_SHA/$GITHUB_SHA/jme3-natives.zip \
${{ secrets.BINTRAY_GENERIC_REPO }} "content" "natives" \
${{ secrets.BINTRAY_USER }} \
${{ secrets.BINTRAY_APIKEY }} \
"https://github.com/${GITHUB_REPOSITORY}" \
"${{ secrets.BINTRAY_LICENSE }}" "true"
# We reference the snapshot by writing its commit hash in natives-snapshot.properties
echo "natives.snapshot=$GITHUB_SHA" > natives-snapshot.properties
# We commit the updated natives-snapshot.properties
git config --global user.name "Github Actions"
git config --global user.email "actions@users.noreply.github.com"
git add natives-snapshot.properties
git commit -m "[skip ci] update natives snapshot"
# Pull rebase from the remote repo, just in case there was a push in the meantime
git pull -q --rebase
# We need to calculate the header for git authentication
header=$(echo -n "ad-m:${{ secrets.GITHUB_TOKEN }}" | base64)
# Push
(git -c http.extraheader="AUTHORIZATION: basic $header" push origin "$branch" || true)
fi
fi
fi
# This job deploys the release
DeployRelease:
needs: [BuildJMonkey]
name: Deploy Release
runs-on: ubuntu-18.04
if: github.event_name == 'release'
steps:
# We need to clone everything again for uploadToMaven.sh ...
- name: Clone the repo
uses: actions/checkout@v2
with:
fetch-depth: 1
# Download all the stuff...
- name: Download maven artifacts
uses: actions/download-artifact@master
with:
name: maven
path: dist/maven
- name: Download release
uses: actions/download-artifact@master
with:
name: release
path: dist/release
- name: Deploy to github releases
run: |
# We need to get the release id (yeah, it's not the same as the tag)
echo "${GITHUB_EVENT_PATH}"
cat ${GITHUB_EVENT_PATH}
releaseId=$(jq --raw-output '.release.id' ${GITHUB_EVENT_PATH})
# Now that we have the id, we just upload the release zip from before
echo "Upload to release $releaseId"
filename="$(ls dist/release/*.zip)"
url="https://uploads.github.com/repos/${GITHUB_REPOSITORY}/releases/$releaseId/assets?name=$(basename $filename)"
echo "Upload to $url"
curl -L \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Content-Type: application/zip" \
--data-binary @"$filename" \
"$url"
- name: Deploy to bintray
run: |
source .github/actions/tools/uploadToMaven.sh
if [ "${{ secrets.BINTRAY_MAVEN_REPO }}" = "" ];
then
echo "Configure the following secrets to enable bintray deployment"
echo "BINTRAY_MAVEN_REPO, BINTRAY_USER, BINTRAY_APIKEY"
else
uploadAllToMaven dist/maven/ https://api.bintray.com/maven/${{ secrets.BINTRAY_MAVEN_REPO }} ${{ secrets.BINTRAY_USER }} ${{ secrets.BINTRAY_APIKEY }} "https://github.com/${GITHUB_REPOSITORY}" "${{ secrets.BINTRAY_LICENSE }}"
fi
# - name: Deploy to github package registry
# run: |
# source .github/actions/tools/uploadToMaven.sh
# registry="https://maven.pkg.github.com/$GITHUB_REPOSITORY"
# echo "Deploy to github package registry $registry"
# uploadAllToMaven dist/maven/ $registry "token" ${{ secrets.GITHUB_TOKEN }}
# Deploy the javadoc
DeployJavaDoc:
needs: [BuildJMonkey]
name: Deploy Javadoc
runs-on: ubuntu-18.04
if: github.event_name == 'release'
steps:
# We are going to need a deploy key for this, since we need
# to push to a different repo
- name: Set ssh key
run: |
mkdir -p ~/.ssh/
echo "${{ secrets.JAVADOC_GHPAGES_DEPLOY_PRIVKEY }}" > $HOME/.ssh/deploy.key
chmod 600 $HOME/.ssh/deploy.key
# We clone the javadoc repo
- name: Clone gh-pages
run: |
branch="gh-pages"
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $HOME/.ssh/deploy.key"
git clone --single-branch --branch "$branch" git@github.com:${{ secrets.JAVADOC_GHPAGES_REPO }} .
# Download the javadoc in the new directory "newdoc"
- name: Download javadoc
uses: actions/download-artifact@master
with:
name: javadoc
path: newdoc
# The actual deploy
- name: Deploy to github pages
run: |
set -f
IFS=$'\n'
# Get the tag for this release
version="`if [[ $GITHUB_REF == refs\/tags* ]]; then echo ${GITHUB_REF//refs\/tags\//}; fi`"
# If there is no tag, then we do nothing.
if [ "$version" != "" ];
then
echo "Deploy as $version"
# Remove any older version of the javadoc for this tag
if [ -d "$version" ];then rm -Rf "$version"; fi
# Rename newdoc with the version name
mv newdoc "$version"
# if there isn't an index.txt we create one (we need this to list the versions)
if [ ! -f "index.txt" ]; then echo "" > index.txt ; fi
index="`cat index.txt`"
# Check if this version is already in index.txt
addNew=true
for v in $index;
do
if [ "$v" = "$version" ];
then
echo "$v" "$version"
addNew=false
break
fi
done
# If not, we add it to the beginning
if [ "$addNew" = "true" ];
then
echo -e "$version\n$index" > index.txt
index="`cat index.txt`"
fi
# Regenerate the pages
chmod +x make.sh
./make.sh
# Configure git to use the deploy key
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $HOME/.ssh/deploy.key"
# Commit the changes
git config --global user.name "Github Actions"
git config --global user.email "actions@users.noreply.github.com"
git add . || true
git commit -m "$version" || true
branch="gh-pages"
git push origin "$branch" --force || true
fi

34
.gitignore vendored

@ -1,9 +1,4 @@
**/nbproject/private/
**/.classpath
**/.settings
**/.project
**/.vscode
**/out/
/.gradle/
/.nb-gradle/
/.idea/
@ -19,30 +14,21 @@
*.jnilib
*.dylib
*.iml
*.class
*.jtxt
.gradletasknamecache
.DS_Store
/jme3-core/src/main/resources/com/jme3/system/version.properties
/jme3-*/build/
/jme3-*/bin/
/jme3-bullet-native/bullet3.zip
/jme3-bullet-native/bullet3-*/
/jme3-bullet-native/src/native/cpp/com_jme3_bullet_*.h
/jme3-bullet-native/bullet.zip
/jme3-bullet-native/bullet-2.82-r2704/
/jme3-android-native/openal-soft/
/jme3-android-native/OpenALSoft.zip
/jme3-android-native/src/native/jme_decode/STBI/
/jme3-android-native/src/native/jme_decode/Tremor/
/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.h
/jme3-android-native/src/native/jme_decode/com_jme3_texture_plugins_AndroidNativeImageLoader.h
/jme3-android-native/stb_image.h
/jme3-examples/private/
!/jme3-vr/src/main/resources/**/*.dylib
!/jme3-vr/src/main/resources/**/*.so
!/jme3-vr/src/main/resources/**/*.so.dbg
!/jme3-vr/src/main/resources/**/*.dll
!/jme3-vr/src/main/resources/**/*.pdb
/buildMaven.bat
/private
.travis.yml
appveyor.yml
javadoc_deploy
javadoc_deploy.pub
!/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll
!/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll
!/jme3-bullet-native/libs/native/osx/x86/libbulletjme.dylib
!/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib
!/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so
!/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so

@ -0,0 +1,59 @@
language: java
sudo: false
env:
- GRADLE_USER_HOME=gradle-cache
cache:
directories:
- gradle-cache
- netbeans
# branches:
# only:
# - master
notifications:
slack:
on_success: change
on_failure: always
rooms:
secure: "PWEk4+VL986c3gAjWp12nqyifvxCjBqKoESG9d7zWh1uiTLadTHhZJRMdsye36FCpz/c/Jt7zCRO/5y7FaubQptnRrkrRfjp5f99MJRzQVXnUAM+y385qVkXKRKd/PLpM7XPm4AvjvxHCyvzX2wamRvul/TekaXKB9Ti5FCN87s="
install:
- ./gradlew assemble
script:
- ./gradlew check
- ./gradlew createZipDistribution
before_deploy:
- export RELEASE_DIST=$(ls build/distributions/*.zip)
deploy:
provider: releases
api_key:
secure: PuEsJd6juXBH29ByITW3ntSAyrwWs0IeFvXJ5Y2YlhojhSMtTwkoWeB6YmDJWP4fhzbajk4TQ1HlOX2IxJXSW/8ShOEIUlGXz9fHiST0dkSM+iRAUgC5enCLW5ITPTiem7eY9ZhS9miIam7ngce9jHNMh75PTzZrEJtezoALT9w=
file_glob: true
file: "${RELEASE_DIST}"
skip_cleanup: true
on:
repo: jMonkeyEngine/jmonkeyengine
tags: true
before_install:
- git fetch --unshallow
- "[ $TRAVIS_PULL_REQUEST == 'false' ] && openssl aes-256-cbc -K $encrypted_a1949b55824a_key -iv $encrypted_a1949b55824a_iv -in private/www-updater.key.enc -out private/www-updater.key -d || :"
# before_install:
# required libs for android build tools
# sudo apt-get update
# sudo apt-get install -qq p7zip-full
# sudo apt-get install -qq --force-yes libgd2-xpm ia32-libs ia32-libs-multiarch
# newest Android NDK
# wget http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin -O ndk.bin
# 7z x ndk.bin -y > /dev/null
# export ANDROID_NDK=`pwd`/android-ndk-r10c
after_success:
- '[ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && ./gradlew uploadArchives || :'
- '[ -n "$TRAVIS_TAG" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && ./gradlew uploadArchives bintrayUpload || :'

@ -9,8 +9,6 @@ Communication always comes first. **All** code changes and other contributions s
### New Contributors
Check out the [Projects](https://github.com/jMonkeyEngine/jmonkeyengine/projects/1) tab, where the team has prioritized issues that you as a new contributor can undertake that will familiarize you to the workflow of contributing. This highlights some issues the team thinks would be a good start for new contributors but you are free to contribute on any other issues or integration you wish.
When you're ready to submit your code, just make a [pull request](https://help.github.com/articles/using-pull-requests).
- Do not commit your code until you have received proper feedback.
@ -24,15 +22,6 @@ p.s. We will try hold ourselves to a [certain standard](http://www.defmacro.org/
Developers in the Contributors team can push directly to Main instead of submitting pull requests, however for new features it is often a good idea to do a pull request as a means to get a last code review.
## Customs around integration, branching, tagging, and releases
- Most pull requests are integrated directly into the master branch of the repository.
- Integrators should note, unless the history of the pull request is important, it should be integrated to a single commit using “squash and merge”. If the history is important, favor “rebase and merge”. Don’t create a merge commit unless GitHub cannot rebase the PR.
- For each major release (such as v3.0 or v3.3), an appropriately named release branch is created in the repository.
- For each minor (or “dot-dot”) release (such as v3.2.3), an appropriately named tag is created in the repository.
- In general, library changes that plausibly might break existing apps appear only in major releases, not minor ones.
## Building the engine
1. Install [Gradle](http://www.gradle.org/)
@ -66,5 +55,5 @@ We generally abide by the standard Java Code Conventions. Besides that, just mak
## Documentation
- How to edit the [wiki](https://github.com/jMonkeyEngine/wiki).
- How to edit the wiki - WIP
- How to edit JavaDocs - WIP

@ -1,29 +0,0 @@
Copyright (c) 2009-2020 jMonkeyEngine
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of 'jMonkeyEngine' nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -1,33 +1,29 @@
jMonkeyEngine
jMonkeyEngine
=============
[![Build Status](https://github.com/jMonkeyEngine/jmonkeyengine/workflows/Build%20jMonkeyEngine/badge.svg)](https://github.com/jMonkeyEngine/jmonkeyengine/actions)
[![Build Status](https://travis-ci.org/jMonkeyEngine/jmonkeyengine.svg?branch=master)](https://travis-ci.org/jMonkeyEngine/jmonkeyengine)
jMonkeyEngine is a 3-D game engine for adventurous Java developers. It’s open-source, cross-platform, and cutting-edge. 3.2.4 is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll release 3.2.x updates until the major 3.3 release arrives.
jMonkeyEngine is a 3D game engine for adventurous Java developers. It’s open source, cross platform and cutting edge. And it is all beautifully documented. The 3.0 branch is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll be frequently submitting stable 3.0.x updates until the major 3.1 version arrives.
The engine is used by several commercial game studios and computer-science courses. Here's a taste:
![jME3 Games Mashup](https://i.imgur.com/nF8WOW6.jpg)
![jME3 Games Mashup](http://i.imgur.com/hBehW2i.jpg)
- [jME powered games on IndieDB](http://www.indiedb.com/engines/jmonkeyengine/games)
- [Maker's Tale](http://steamcommunity.com/sharedfiles/filedetails/?id=93461954t)
- [Boardtastic 2](https://boardtastic-2.fileplanet.com/apk)
- [Attack of the Gelatinous Blob](https://attack-gelatinous-blob.softwareandgames.com/)
- [Mythruna](http://mythruna.com/)
- [PirateHell (on Steam)](https://store.steampowered.com/app/321080/Pirate_Hell/)
- [3089 (on Steam)](http://store.steampowered.com/app/263360/)
- [3079 (on Steam)](http://store.steampowered.com/app/259620/)
- [Lightspeed Frontier (on Steam)](https://store.steampowered.com/app/548650/Lightspeed_Frontier/)
- [Skullstone](http://www.skullstonegame.com/)
- [Spoxel (on Steam)](https://store.steampowered.com/app/746880/Spoxel/)
- [Nine Circles of Hell (on Steam)](https://store.steampowered.com/app/1200600/Nine_Circles_of_Hell/)
- [Leap](https://gamejolt.com/games/leap/313308)
- [Jumping Jack Flag](http://timealias.bplaced.net/jack/)
- [Boardtastic 2](https://play.google.com/store/apps/details?id=com.boardtastic.skateboarding)
- [Copod](http://herebeben.com/copod)
- [Attack of the Gelatinous Blob](http://attackofthegelatinousblob.com/)
- [Chaos](http://4realms.net/)
- [Mythruna](https://mythruna.com/)
- [PirateHell](http://www.desura.com/games/piratehell)
- [3089 (on steam)](http://store.steampowered.com/app/263360/)
- [3079 (on steam)](http://store.steampowered.com/app/259620/)
## Getting started
Go to https://github.com/jMonkeyEngine/sdk/releases to download the jMonkeyEngine SDK.
[Read the wiki](https://jmonkeyengine.github.io/wiki) for a complete install guide. Power up with some SDK Plugins and AssetPacks and you are off to the races. At this point you're gonna want to [join the forum](http://hub.jmonkeyengine.org/) so our tribe can grow stronger.
Go to http://hub.jmonkeyengine.org/downloads/ to download the jMonkeyEngine SDK.
[Read the wiki](http://hub.jmonkeyengine.org/wiki/doku.php) for a complete install guide. Power up with some SDK Plugins and AssetPacks and you are off to the races. At this point you're gonna want to [join the forum](http://hub.jmonkeyengine.org/) so our tribe can grow stronger.
Note: The master branch on GitHub is a development version of the engine and is NOT MEANT TO BE USED IN PRODUCTION, it will break constantly during development of the stable jME versions!
@ -37,11 +33,11 @@ Note: The master branch on GitHub is a development version of the engine and is
- NetBeans Platform
- Gradle
Plus a bunch of awesome libraries & tight integrations like Bullet, NiftyGUI and other goodies.
Plus a bunch of awesome libraries & tight integrations like Bullet, Blender, NiftyGUI and other goodies.
### Documentation
Did you miss it? Don't sweat it, [here it is again](https://jmonkeyengine.github.io/wiki).
Did you miss it? Don't sweat it, [here it is again](http://hub.jmonkeyengine.org/wiki/doku.php).
### Contributing
@ -50,4 +46,3 @@ Read our [contribution guide](https://github.com/jMonkeyEngine/jmonkeyengine/blo
### License
New BSD (3-clause) License. In other words, you do whatever makes you happy!

@ -1,35 +1,24 @@
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import org.gradle.api.artifacts.*
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
classpath 'me.tatarka:gradle-retrolambda:3.7.1'
}
}
allprojects {
repositories {
google()
jcenter()
classpath 'com.android.tools.build:gradle:1.1.0'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.5'
}
}
apply plugin: 'base'
apply from: file('version.gradle')
apply plugin: 'me.tatarka.retrolambda'
apply from: file('upload.gradle')
// This is applied to all sub projects
subprojects {
if(!project.name.equals('jme3-android-examples')) {
apply from: rootProject.file('common.gradle')
if (!project.name.equals('jme3-testdata')) {
if (!['jme3-testdata', 'sdk'].contains(project.name)) {
apply from: rootProject.file('bintray.gradle')
}
} else {
@ -43,32 +32,31 @@ task run(dependsOn: ':jme3-examples:run') {
defaultTasks 'run'
task libDist(dependsOn: subprojects.build, description: 'Builds and copies the engine binaries, sources and javadoc to build/libDist') {
doLast {
File libFolder = mkdir("$buildDir/libDist/lib")
File sourceFolder = mkdir("$buildDir/libDist/sources")
File javadocFolder = mkdir("$buildDir/libDist/javadoc")
subprojects.each {project ->
if(project.ext.mainClass == ''){
project.tasks.withType(Jar).each {archiveTask ->
if(archiveTask.classifier == "sources"){
copy {
from archiveTask.archivePath
into sourceFolder
rename {project.name + '-' + archiveTask.classifier +'.'+ archiveTask.extension}
}
} else if(archiveTask.classifier == "javadoc"){
copy {
from archiveTask.archivePath
into javadocFolder
rename {project.name + '-' + archiveTask.classifier +'.'+ archiveTask.extension}
}
} else{
copy {
from archiveTask.archivePath
into libFolder
rename {project.name + '.' + archiveTask.extension}
}
task libDist(dependsOn: subprojects.build) << {
// description 'Builds and copies the engine binaries, sources and javadoc to build/libDist'
File libFolder = mkdir("$buildDir/libDist/lib")
File sourceFolder = mkdir("$buildDir/libDist/sources")
File javadocFolder = mkdir("$buildDir/libDist/javadoc")
subprojects.each {project ->
if(project.ext.mainClass == ''){
project.tasks.withType(Jar).each {archiveTask ->
if(archiveTask.classifier == "sources"){
copy {
from archiveTask.archivePath
into sourceFolder
rename {project.name + '-' + archiveTask.classifier +'.'+ archiveTask.extension}
}
} else if(archiveTask.classifier == "javadoc"){
copy {
from archiveTask.archivePath
into javadocFolder
rename {project.name + '-' + archiveTask.classifier +'.'+ archiveTask.extension}
}
} else{
copy {
from archiveTask.archivePath
into libFolder
rename {project.name + '.' + archiveTask.extension}
}
}
}
@ -80,9 +68,9 @@ task createZipDistribution(type:Zip,dependsOn:["dist","libDist"], description:"P
archiveName "jME" + jmeFullVersion + ".zip"
into("/") {
from {"./dist"}
}
}
into("/sources") {
from {"$buildDir/libDist/sources"}
from {"$buildDir/libDist/sources"}
}
}
@ -102,21 +90,21 @@ task dist(dependsOn: [':jme3-examples:dist', 'mergedJavadoc']){
task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the projects.') {
title = 'jMonkeyEngine3'
destinationDir = mkdir("dist/javadoc")
options.encoding = 'UTF-8'
// Allows Javadoc to be generated on Java 8 despite doclint errors.
if (JavaVersion.current().isJava8Compatible()) {
options.addStringOption('Xdoclint:none', '-quiet')
}
options.overview = file("javadoc-overview.html")
// Note: The closures below are executed lazily.
source subprojects.collect {project ->
project.sourceSets*.allJava
}
classpath = files(subprojects.collect {project ->
project.sourceSets*.compileClasspath})
// classpath = files(subprojects.collect {project ->
// project.sourceSets*.compileClasspath})
// source {
// subprojects*.sourceSets*.main*.allSource
// }
@ -125,15 +113,14 @@ task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the pro
}
}
clean.dependsOn('cleanMergedJavadoc')
task cleanMergedJavadoc(type: Delete) {
delete file('dist/javadoc')
}
task mergedSource(type: Copy){
}
task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper to the current directory.') {
gradleVersion = '2.2.1'
}
ext {
ndkCommandPath = ""
ndkExists = false
@ -152,69 +139,13 @@ task configureAndroidNDK {
if (System.env.ANDROID_NDK != null) {
ndkBuildPath = System.env.ANDROID_NDK + File.separator + ndkBuildFile
}
if (new File(ndkBuildPath).exists()) {
ndkExists = true
ndkCommandPath = ndkBuildPath
}
}
gradle.rootProject.ext.set("usePrebuildNatives", buildNativeProjects!="true");
if (skipPrebuildLibraries != "true" && buildNativeProjects != "true") {
String rootPath = rootProject.projectDir.absolutePath
Properties nativesSnasphotProp = new Properties()
File nativesSnasphotPropF = new File("${rootPath}/natives-snapshot.properties");
if (nativesSnasphotPropF.exists()) {
nativesSnasphotPropF.withInputStream { nativesSnasphotProp.load(it) }
String nativesSnasphot = nativesSnasphotProp.getProperty("natives.snapshot");
String nativesUrl = PREBUILD_NATIVES_URL.replace('${natives.snapshot}', nativesSnasphot)
println "Use natives snapshot: " + nativesUrl
String nativesZipFile = "${rootPath}" + File.separator + "build" + File.separator + nativesSnasphot + "-natives.zip"
String nativesPath = "${rootPath}" + File.separator + "build" + File.separator + "native"
task getNativesZipFile {
outputs.file nativesZipFile
doFirst {
File target = file(nativesZipFile);
println("Download natives from " + nativesUrl + " to " + nativesZipFile);
target.getParentFile().mkdirs();
ant.get(src: nativesUrl, dest: target);
}
}
task extractPrebuiltNatives {
inputs.file nativesZipFile
outputs.dir nativesPath
dependsOn getNativesZipFile
doFirst {
for (File src : zipTree(nativesZipFile)) {
String srcRel = src.getAbsolutePath().substring((int) (nativesZipFile.length() + 1));
srcRel = srcRel.substring(srcRel.indexOf(File.separator) + 1);
File dest = new File(nativesPath + File.separator + srcRel);
boolean doCopy = !(dest.exists() && dest.lastModified() > src.lastModified())
if (doCopy) {
println("Copy " + src + " " + dest);
dest.getParentFile().mkdirs();
Files.copy(src.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
}
}
assemble.dependsOn extractPrebuiltNatives
}
}
//class IncrementalReverseTask extends DefaultTask {
// @InputDirectory
// def File inputDir
@ -250,14 +181,3 @@ if (skipPrebuildLibraries != "true" && buildNativeProjects != "true") {
// enableAssertions = true // true by default
// }
//}
wrapper {
gradleVersion = '5.6.4'
}
retrolambda {
javaVersion JavaVersion.VERSION_1_7
incremental true
jvmArgs '-noverify'
}

@ -1,7 +1,7 @@
apply plugin: 'com.android.application'
group = 'org.jmonkeyengine'
version = jmeFullVersion
group = 'com.jme3'
version = jmeVersion + '-' + jmeVersionTag
sourceCompatibility = '1.6'
@ -10,4 +10,4 @@ repositories {
maven {
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
}
}
}

@ -3,49 +3,32 @@
//
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven'
group = 'org.jmonkeyengine'
version = jmeFullVersion
version = jmePomVersion
sourceCompatibility = '1.8'
sourceCompatibility = '1.7'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
gradle.projectsEvaluated {
tasks.withType(JavaCompile) { // compile-time options:
options.compilerArgs << '-Xlint:unchecked'
}
}
repositories {
mavenCentral()
maven {
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
}
flatDir {
dirs rootProject.file('lib')
}
}
configurations {
deployerJars
}
dependencies {
// Adding dependencies here will add the dependencies to each subproject.
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.mockito', name: 'mockito-core', version: '3.0.0'
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.0.28-beta'
testCompile group: 'org.easytesting', name: 'fest-assert-core', version: '2.0M10'
testCompile 'org.codehaus.groovy:groovy-all:2.5.8'
}
// Uncomment if you want to see the status of every test that is run and
// the test output.
/*
test {
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
}
deployerJars "org.apache.maven.wagon:wagon-ssh:2.9"
}
*/
jar {
manifest {
@ -57,13 +40,11 @@ jar {
javadoc {
failOnError = false
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
options.docTitle = "jMonkeyEngine ${jmeFullVersion} ${project.name} Javadoc"
options.windowTitle = "jMonkeyEngine ${jmeFullVersion} ${project.name} Javadoc"
options.header = "<b>jMonkeyEngine ${jmeFullVersion} ${project.name}</b>"
options.docTitle = "jMonkeyEngine ${jmeMainVersion} ${project.name} Javadoc"
options.windowTitle = "jMonkeyEngine ${jmeMainVersion} ${project.name} Javadoc"
options.header = "<b>jMonkeyEngine ${jmeMainVersion} ${project.name}</b>"
options.author = "true"
options.use = "true"
options.charSet = "UTF-8"
options.encoding = "UTF-8"
//disable doclint for JDK8, more quiet output
if (JavaVersion.current().isJava8Compatible()){
options.addStringOption('Xdoclint:none', '-quiet')
@ -86,11 +67,11 @@ task javadocJar(type: Jar, dependsOn: javadoc, description: 'Creates a jar from
from javadoc.destinationDir
}
ext.pomConfig = {
def pomConfig = {
name POM_NAME
description POM_DESCRIPTION
url POM_URL
inceptionYear POM_INCEPTION_YEAR
inceptionYear '2016'
scm {
url POM_SCM_URL
connection POM_SCM_CONNECTION
@ -103,6 +84,7 @@ ext.pomConfig = {
distribution POM_LICENSE_DISTRIBUTION
}
}
// from http://hub.jmonkeyengine.org/introduction/team/
developers {
developer {
name 'jMonkeyEngine Team'
@ -121,7 +103,6 @@ task writeFullPom {
}.writeTo(pomFile)
}
}
assemble.dependsOn(writeFullPom)
install.dependsOn(writeFullPom)
uploadArchives.dependsOn(writeFullPom)
@ -129,9 +110,32 @@ uploadArchives.dependsOn(writeFullPom)
artifacts {
archives jar
archives sourcesJar
if (buildJavaDoc == "true") {
if(buildJavaDoc == "true"){
archives javadocJar
}
archives writeFullPom.outputs.files[0]
}
uploadArchives {
repositories.mavenDeployer {
configuration = configurations.deployerJars
// disable this otherwise it will fill up the server with stale jars
uniqueVersion = false
repository(url: "scp://updates.jmonkeyengine.org/var/www/updates/maven") {
authentication(userName: "www-updater", privateKey: "private/www-updater.key")
}
pom.project pomConfig
}
}
task createFolders(description: 'Creates the source folders if they do not exist.') doLast {
// sourceSets*.allSource*.srcDirs*.each { File srcDir ->
// if (!srcDir.isDirectory()) {
// println "Creating source folder: ${srcDir}"
// srcDir.mkdirs()
// }
// }
}

@ -1,51 +1,40 @@
# Version number: Major.Minor.SubMinor (e.g. 3.3.0)
jmeVersion = 3.4.0
# Leave empty to autogenerate
# (use -PjmeVersionName="myVersion" from commandline to specify a custom version name )
jmeVersionName =
# If true, the version name will contain the commit hash
useCommitHashAsVersionName = false
# Set to true if a non-master branch name should be included in the automatically
# generated version.
includeBranchInVersion = false
# specify if JavaDoc should be built
buildJavaDoc = true
# specify if SDK and Native libraries get built
buildNativeProjects = false
buildAndroidExamples = false
buildForPlatforms = Linux64,Linux32,Windows64,Windows32,Mac64
# Forcefully ignore prebuilt libraries
skipPrebuildLibraries=false
# Path to android NDK for building native libraries
#ndkPath=/Users/normenhansen/Documents/Code-Import/android-ndk-r7
ndkPath = /opt/android-ndk-r16b
# Path for downloading native Bullet
# 2.89+ (circa 26 April 2020, to avoid jMonkeyEngine issue #1283)
bulletUrl = https://github.com/bulletphysics/bullet3/archive/cd8cf7521cbb8b7808126a6adebd47bb83ea166a.zip
bulletFolder = bullet3-cd8cf7521cbb8b7808126a6adebd47bb83ea166a
bulletZipFile = bullet3.zip
# POM settings
POM_NAME=jMonkeyEngine
POM_DESCRIPTION=jMonkeyEngine is a 3-D game engine for adventurous Java developers
POM_URL=http://jmonkeyengine.org
POM_SCM_URL=https://github.com/jMonkeyEngine/jmonkeyengine
POM_SCM_CONNECTION=scm:git:git://github.com/jMonkeyEngine/jmonkeyengine.git
POM_SCM_DEVELOPER_CONNECTION=scm:git:git@github.com:jMonkeyEngine/jmonkeyengine.git
POM_LICENSE_NAME=New BSD (3-clause) License
POM_LICENSE_URL=http://opensource.org/licenses/BSD-3-Clause
POM_LICENSE_DISTRIBUTION=repo
POM_INCEPTION_YEAR=2009
# Bintray settings to override in $HOME/.gradle/gradle.properties or ENV or commandline
bintray_user=
bintray_api_key=
PREBUILD_NATIVES_URL=https://dl.bintray.com/jmonkeyengine/files/${natives.snapshot}/jme3-natives.zip
# Version number used for plugins, only 3 numbers (e.g. 3.1.3)
jmeVersion = 3.1.0
# Version used for application and settings folder, no spaces!
jmeMainVersion = 3.1
# Increment this each time jmeVersionTag changes but jmeVersion stays the same
jmeVersionTagID = 0
# specify if JavaDoc should be built
buildJavaDoc = false
# specify if SDK and Native libraries get built
buildNativeProjects = false
buildAndroidExamples = false
# Path to android NDK for building native libraries
#ndkPath=/Users/normenhansen/Documents/Code-Import/android-ndk-r7
ndkPath = /opt/android-ndk-r10c
# Path for downloading native Bullet
bulletUrl = http://bullet.googlecode.com/files/bullet-2.82-r2704.zip
bulletFolder = bullet-2.82-r2704
bulletZipFile = bullet.zip
# Path for downloading NetBeans Base
netbeansUrl = http://download.netbeans.org/netbeans/8.0.2/final/zip/netbeans-8.0.2-201411181905-javase.zip
# POM settings
POM_NAME=jMonkeyEngine
POM_DESCRIPTION=jMonkeyEngine is a 3D game engine for adventurous Java developers
POM_URL=http://jmonkeyengine.org
POM_SCM_URL=https://github.com/jMonkeyEngine/jmonkeyengine
POM_SCM_CONNECTION=scm:git:git://github.com/jMonkeyEngine/jmonkeyengine.git
POM_SCM_DEVELOPER_CONNECTION=scm:git:git@github.com:jMonkeyEngine/jmonkeyengine.git
POM_LICENSE_NAME=New BSD (3-clause) License
POM_LICENSE_URL=http://opensource.org/licenses/BSD-3-Clause
POM_LICENSE_DISTRIBUTION=repo
# Bintray settings to override in $HOME/.gradle/gradle.properties or ENV or commandline
bintray_user=
bintray_api_key=

Binary file not shown.

@ -1,5 +1,6 @@
#Mon Dec 01 20:04:11 EST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip

98
gradlew vendored

@ -1,20 +1,4 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#!/usr/bin/env bash
##############################################################################
##
@ -22,38 +6,20 @@
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
warn ( ) {
echo "$*"
}
die () {
die ( ) {
echo
echo "$*"
echo
@ -64,7 +30,6 @@ die () {
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
@ -75,11 +40,31 @@ case "`uname`" in
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@ -105,7 +90,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@ -125,11 +110,10 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@ -170,19 +154,11 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "$@"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

30
gradlew.bat vendored

@ -1,19 +1,3 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@ -24,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@ -62,9 +46,10 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@ -75,6 +60,11 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line

@ -1,19 +1,29 @@
apply plugin: 'com.android.application'
dependencies {
compile project(':jme3-core')
compile project(':jme3-android')
compile project(':jme3-effects')
compile project(':jme3-bullet')
compile project(':jme3-bullet-native-android')
compile project(':jme3-networking')
compile project(':jme3-niftygui')
compile project(':jme3-plugins')
compile project(':jme3-terrain')
compile project(':jme3-testdata')
}
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
compileSdkVersion 10
buildToolsVersion "22.0.1"
lintOptions {
// Fix nifty gui referencing "java.awt" package.
disable 'InvalidPackage'
abortOnError false
}
defaultConfig {
applicationId "org.jmonkeyengine.jme3androidexamples"
minSdkVersion 15 // Android 4.0.3 ICE CREAM SANDWICH
targetSdkVersion 28 // Android 9 PIE
applicationId "com.jme3.android"
minSdkVersion 10 // Android 2.3 GINGERBREAD
targetSdkVersion 22 // Android 5.1 LOLLIPOP
versionCode 1
versionName "1.0" // TODO: from settings.gradle
}
@ -21,44 +31,10 @@ android {
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceSets {
main {
java {
srcDir 'src/main/java'
}
assets {
srcDir 'src/assets'
srcDir '../jme3-testdata/src/main/resources'
srcDir '../jme3-examples/src/main/resources'
}
debug {
applicationIdSuffix ".debug"
debuggable true
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:28.0.0'
compile project(':jme3-core')
compile project(':jme3-android')
compile project(':jme3-android-native')
compile project(':jme3-effects')
compile project(':jme3-bullet')
compile project(':jme3-bullet-native-android')
compile project(':jme3-networking')
compile project(':jme3-niftygui')
compile project(':jme3-plugins')
compile project(':jme3-terrain')
compile fileTree(dir: '../jme3-examples/build/libs', include: ['*.jar'], exclude: ['*sources*.*'])
// compile project(':jme3-examples')
}
}

@ -1,17 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\potterec\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

@ -1,13 +0,0 @@
package org.jmonkeyengine.jme3androidexamples;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

@ -1,50 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jmonkeyengine.jme3androidexamples">
<application
android:allowBackup="true"
android:icon="@mipmap/mipmap_monkey"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".TestActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="landscape">
</activity>
</application>
package="com.jme3.android">
<!-- Tell the system that you need ES 2.0. -->
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<!-- Tell the system that you need distinct touches (for the zoom gesture). -->
<uses-feature
android:name="android.hardware.touchscreen.multitouch.distinct"
android:required="true"/>
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="true" />
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<application android:label="@string/app_name" android:allowBackup="true">
<activity android:name="jme3test.android.TestChooserAndroid"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
</manifest>

@ -1,39 +0,0 @@
package jme3test.android;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
/**
* Test case to look for images stored in the Android drawable and mipmap directories. Image files are
* stored in the main->res->drawable-xxxx directories and main->res->mipmap-xxxx directories. The Android OS
* will choose the best matching image based on the device capabilities.
*
* @author iwgeric
*/
public class TestAndroidResources extends SimpleApplication {
@Override
public void simpleInitApp() {
// Create boxes with textures that are stored in the Android Resources Folders
// Images are stored in multiple Drawable and Mipmap directories. Android picks the ones that
// match the device size and density.
Box box1Mesh = new Box(1, 1, 1);
Geometry box1 = new Geometry("Monkey Box 1", box1Mesh);
Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat1.setTexture("ColorMap", assetManager.loadTexture("drawable_monkey.png"));
box1.setMaterial(mat1);
box1.setLocalTranslation(-2, 0, 0);
rootNode.attachChild(box1);
Box box2Mesh = new Box(1, 1, 1);
Geometry box2 = new Geometry("Monkey Box 2", box2Mesh);
Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat2.setTexture("ColorMap", assetManager.loadTexture("mipmap_monkey.png"));
box2.setMaterial(mat2);
box2.setLocalTranslation(2, 0, 0);
rootNode.attachChild(box2);
}
}

@ -1,314 +0,0 @@
package jme3test.android;
import com.jme3.app.SimpleApplication;
import com.jme3.input.Joystick;
import com.jme3.input.JoystickAxis;
import com.jme3.input.MouseInput;
import com.jme3.input.SensorJoystickAxis;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Line;
import com.jme3.texture.Texture;
import com.jme3.util.IntMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Example Test Case to test using Android sensors as Joystick axes. Make sure to enable Joystick Events from
* the test chooser menus. Rotating the device will cause the block to rotate. Tapping the screen will cause the
* sensors to be calibrated (reset to zero) at the current orientation. Continuously tapping the screen causes
* the "rumble" to intensify until it reaches the maximum amount and then it shuts off.
*
* @author iwgeric
*/
public class TestAndroidSensors extends SimpleApplication implements ActionListener, AnalogListener {
private static final Logger logger = Logger.getLogger(TestAndroidSensors.class.getName());
private Geometry geomZero = null;
// Map of joysticks saved with the joyId as the key
private IntMap<Joystick> joystickMap = new IntMap<Joystick>();
// flag to allow for the joystick axis to be calibrated on startup
private boolean initialCalibrationComplete = false;
// mappings used for onAnalog
private final String ORIENTATION_X_PLUS = "Orientation_X_Plus";
private final String ORIENTATION_X_MINUS = "Orientation_X_Minus";
private final String ORIENTATION_Y_PLUS = "Orientation_Y_Plus";
private final String ORIENTATION_Y_MINUS = "Orientation_Y_Minus";
private final String ORIENTATION_Z_PLUS = "Orientation_Z_Plus";
private final String ORIENTATION_Z_MINUS = "Orientation_Z_Minus";
// variables to save the current rotation
// Used when controlling the geometry with device orientation
private float[] anglesCurrent = new float[]{0f, 0f, 0f};
private Quaternion rotationQuat = new Quaternion();
// switch to apply an absolute rotation (geometry.setLocalRotation) or
// an incremental constant rotation (geometry.rotate)
// Used when controlling the geometry with device orientation
private boolean useAbsolute = false;
// rotation speed to use when apply constant incremental rotation
// Used when controlling the geometry with device orientation
private float rotationSpeedX = 1f;
private float rotationSpeedY = 1f;
// current intensity of the rumble
float rumbleAmount = 0f;
// toggle to enable rumble
boolean enableRumble = true;
// toggle to enable device orientation in FlyByCamera
boolean enableFlyByCameraRotation = false;
// toggle to enable controlling geometry rotation
boolean enableGeometryRotation = true;
// Make sure to set joystickEventsEnabled = true in MainActivity for Android
private float toDegrees(float rad) {
return rad * FastMath.RAD_TO_DEG;
}
@Override
public void simpleInitApp() {
// useAbsolute = true;
// enableRumble = true;
if (enableFlyByCameraRotation) {
flyCam.setEnabled(true);
} else {
flyCam.setEnabled(false);
}
Mesh lineX = new Line(Vector3f.ZERO, Vector3f.ZERO.add(Vector3f.UNIT_X.mult(3)));
Mesh lineY = new Line(Vector3f.ZERO, Vector3f.ZERO.add(Vector3f.UNIT_Y.mult(3)));
Mesh lineZ = new Line(Vector3f.ZERO, Vector3f.ZERO.add(Vector3f.UNIT_Z.mult(3)));
Geometry geoX = new Geometry("X", lineX);
Material matX = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
matX.setColor("Color", ColorRGBA.Red);
matX.getAdditionalRenderState().setLineWidth(30);
geoX.setMaterial(matX);
rootNode.attachChild(geoX);
Geometry geoY = new Geometry("Y", lineY);
Material matY = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
matY.setColor("Color", ColorRGBA.Green);
matY.getAdditionalRenderState().setLineWidth(30);
geoY.setMaterial(matY);
rootNode.attachChild(geoY);
Geometry geoZ = new Geometry("Z", lineZ);
Material matZ = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
matZ.setColor("Color", ColorRGBA.Blue);
matZ.getAdditionalRenderState().setLineWidth(30);
geoZ.setMaterial(matZ);
rootNode.attachChild(geoZ);
Box b = new Box(1, 1, 1);
geomZero = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Yellow);
Texture tex_ml = assetManager.loadTexture("Interface/Logo/Monkey.jpg");
mat.setTexture("ColorMap", tex_ml);
geomZero.setMaterial(mat);
geomZero.setLocalTranslation(Vector3f.ZERO);
geomZero.setLocalRotation(Quaternion.IDENTITY);
rootNode.attachChild(geomZero);
// Touch (aka MouseInput.BUTTON_LEFT) is used to record the starting
// orientation when using absolute rotations
inputManager.addMapping("MouseClick", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(this, "MouseClick");
Joystick[] joysticks = inputManager.getJoysticks();
if (joysticks == null || joysticks.length < 1) {
logger.log(Level.INFO, "Cannot find any joysticks!");
} else {
// Joysticks return a value of 0 to 1 based on how far the stick is
// push on the axis. This value is then scaled based on how long
// during the frame the joystick axis has been in that position.
// If the joystick is push all the way for the whole frame,
// then the value in onAnalog is equal to tpf.
// If the joystick is push 1/2 way for the entire frame, then the
// onAnalog value is 1/2 tpf.
// Similarly, if the joystick is pushed to the maximum during a frame
// the value in onAnalog will also be scaled.
// For Android sensors, rotating the device 90deg is the same as
// pushing an actual joystick axis to the maximum.
logger.log(Level.INFO, "Number of joysticks: {0}", joysticks.length);
JoystickAxis axis;
for (Joystick joystick : joysticks) {
// Get and display all axes in joystick.
List<JoystickAxis> axes = joystick.getAxes();
for (JoystickAxis joystickAxis : axes) {
logger.log(Level.INFO, "{0} axis scan Name: {1}, LogicalId: {2}, AxisId: {3}",
new Object[]{joystick.getName(), joystickAxis.getName(), joystickAxis.getLogicalId(), joystickAxis.getAxisId()});
}
// Get specific axis based on LogicalId of the JoystickAxis
// If found, map axis
axis = joystick.getAxis(SensorJoystickAxis.ORIENTATION_X);
if (axis != null) {
axis.assignAxis(ORIENTATION_X_PLUS, ORIENTATION_X_MINUS);
inputManager.addListener(this, ORIENTATION_X_PLUS, ORIENTATION_X_MINUS);
logger.log(Level.INFO, "Found {0} Joystick, assigning mapping for X axis: {1}, with max value: {2}",
new Object[]{joystick.toString(), axis.toString(), ((SensorJoystickAxis) axis).getMaxRawValue()});
}
axis = joystick.getAxis(SensorJoystickAxis.ORIENTATION_Y);
if (axis != null) {
axis.assignAxis(ORIENTATION_Y_PLUS, ORIENTATION_Y_MINUS);
inputManager.addListener(this, ORIENTATION_Y_PLUS, ORIENTATION_Y_MINUS);
logger.log(Level.INFO, "Found {0} Joystick, assigning mapping for Y axis: {1}, with max value: {2}",
new Object[]{joystick.toString(), axis.toString(), ((SensorJoystickAxis) axis).getMaxRawValue()});
}
axis = joystick.getAxis(SensorJoystickAxis.ORIENTATION_Z);
if (axis != null) {
axis.assignAxis(ORIENTATION_Z_PLUS, ORIENTATION_Z_MINUS);
inputManager.addListener(this, ORIENTATION_Z_PLUS, ORIENTATION_Z_MINUS);
logger.log(Level.INFO, "Found {0} Joystick, assigning mapping for Z axis: {1}, with max value: {2}",
new Object[]{joystick.toString(), axis.toString(), ((SensorJoystickAxis) axis).getMaxRawValue()});
}
joystickMap.put(joystick.getJoyId(), joystick);
}
}
}
@Override
public void simpleUpdate(float tpf) {
if (!initialCalibrationComplete) {
// Calibrate the axis (set new zero position) if the axis
// is a sensor joystick axis
for (IntMap.Entry<Joystick> entry : joystickMap) {
for (JoystickAxis axis : entry.getValue().getAxes()) {
if (axis instanceof SensorJoystickAxis) {
logger.log(Level.INFO, "Calibrating Axis: {0}", axis.toString());
((SensorJoystickAxis) axis).calibrateCenter();
}
}
}
initialCalibrationComplete = true;
}
if (enableGeometryRotation) {
rotationQuat.fromAngles(anglesCurrent);
rotationQuat.normalizeLocal();
if (useAbsolute) {
geomZero.setLocalRotation(rotationQuat);
} else {
geomZero.rotate(rotationQuat);
}
anglesCurrent[0] = anglesCurrent[1] = anglesCurrent[2] = 0f;
}
}
public void onAction(String string, boolean pressed, float tpf) {
if (string.equalsIgnoreCase("MouseClick") && pressed) {
// Calibrate the axis (set new zero position) if the axis
// is a sensor joystick axis
for (IntMap.Entry<Joystick> entry : joystickMap) {
for (JoystickAxis axis : entry.getValue().getAxes()) {
if (axis instanceof SensorJoystickAxis) {
logger.log(Level.INFO, "Calibrating Axis: {0}", axis.toString());
((SensorJoystickAxis) axis).calibrateCenter();
}
}
}
if (enableRumble) {
// manipulate joystick rumble
for (IntMap.Entry<Joystick> entry : joystickMap) {
rumbleAmount += 0.1f;
if (rumbleAmount > 1f + FastMath.ZERO_TOLERANCE) {
rumbleAmount = 0f;
}
logger.log(Level.INFO, "rumbling with amount: {0}", rumbleAmount);
entry.getValue().rumble(rumbleAmount);
}
}
}
}
public void onAnalog(String string, float value, float tpf) {
logger.log(Level.INFO, "onAnalog for {0}, value: {1}, tpf: {2}",
new Object[]{string, value, tpf});
float scaledValue = value;
if (string.equalsIgnoreCase(ORIENTATION_X_PLUS)) {
if (useAbsolute) {
// set rotation amount
// divide by tpf to get back to actual axis value (0 to 1)
// multiply by 90deg so that 90deg = full axis (value = tpf)
anglesCurrent[0] = (scaledValue / tpf * FastMath.HALF_PI);
} else {
// apply an incremental rotation amount based on rotationSpeed
anglesCurrent[0] += scaledValue * rotationSpeedX;
}
}
if (string.equalsIgnoreCase(ORIENTATION_X_MINUS)) {
if (useAbsolute) {
// set rotation amount
// divide by tpf to get back to actual axis value (0 to 1)
// multiply by 90deg so that 90deg = full axis (value = tpf)
anglesCurrent[0] = (-scaledValue / tpf * FastMath.HALF_PI);
} else {
// apply an incremental rotation amount based on rotationSpeed
anglesCurrent[0] -= scaledValue * rotationSpeedX;
}
}
if (string.equalsIgnoreCase(ORIENTATION_Y_PLUS)) {
if (useAbsolute) {
// set rotation amount
// divide by tpf to get back to actual axis value (0 to 1)
// multiply by 90deg so that 90deg = full axis (value = tpf)
anglesCurrent[1] = (scaledValue / tpf * FastMath.HALF_PI);
} else {
// apply an incremental rotation amount based on rotationSpeed
anglesCurrent[1] += scaledValue * rotationSpeedY;
}
}
if (string.equalsIgnoreCase(ORIENTATION_Y_MINUS)) {
if (useAbsolute) {
// set rotation amount
// divide by tpf to get back to actual axis value (0 to 1)
// multiply by 90deg so that 90deg = full axis (value = tpf)
anglesCurrent[1] = (-scaledValue / tpf * FastMath.HALF_PI);
} else {
// apply an incremental rotation amount based on rotationSpeed
anglesCurrent[1] -= scaledValue * rotationSpeedY;
}
}
}
}

@ -1,354 +0,0 @@
package jme3test.android;
import com.jme3.app.SimpleApplication;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.font.Rectangle;
import com.jme3.input.*;
import com.jme3.input.controls.*;
import com.jme3.input.event.*;
import com.jme3.math.ColorRGBA;
import com.jme3.ui.Picture;
import java.text.NumberFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Test for Android Touch Input integration into jME3.
*
* @author iwgeric
*/
public class TestAndroidTouch extends SimpleApplication {
private static final Logger logger = Logger.getLogger(TestAndroidTouch.class.getSimpleName());
private Picture picMouseBackground;
private Picture picMouseLeftButton;
private Picture picMouseDisabled;
private BitmapText textMouseAnalog;
private BitmapText textMouseLabel;
private BitmapText textMouseLocation;
private BitmapText textCursorLocation;
private BitmapText textKeyPressed;
private BitmapText textPhoneLabel;
private BitmapText textPhoneLocation;
private Picture picPhone;
private String touchMapping = "touch";
private String mappingKeyPrefix = "key-";
private String mappingMouseLeft = "mouse left";
private String mappingMouseXNeg = "mouse x neg";
private String mappingMouseXPos = "mouse x pos";
private String mappingMouseYNeg = "mouse y neg";
private String mappingMouseYPos = "mouse y pos";
private TouchListener touchListener = new MyTouchListener();
private ActionListener actionListener = new MyActionListener();
private AnalogListener analogListener = new MyAnalogListener();
private RawInputListener rawInputListener = new MyRawInputListener();
private NumberFormat analogFormat = NumberFormat.getNumberInstance();
private NumberFormat locationFormat = NumberFormat.getNumberInstance();
@Override
public void simpleInitApp() {
getViewPort().setBackgroundColor(ColorRGBA.White);
analogFormat.setMaximumFractionDigits(3);
analogFormat.setMinimumFractionDigits(3);
locationFormat.setMaximumFractionDigits(0);
locationFormat.setMinimumFractionDigits(0);
// Setup list of triggers based on different keyboard key codes. For Android, the soft keyboard key events
// are translated into jme key events.
int[] keyCodes = new int[] {
KeyInput.KEY_0, KeyInput.KEY_1, KeyInput.KEY_2, KeyInput.KEY_3, KeyInput.KEY_4, KeyInput.KEY_5,
KeyInput.KEY_6, KeyInput.KEY_7, KeyInput.KEY_8, KeyInput.KEY_9, KeyInput.KEY_DECIMAL, KeyInput.KEY_PERIOD,
KeyInput.KEY_A, KeyInput.KEY_B, KeyInput.KEY_C, KeyInput.KEY_D, KeyInput.KEY_E, KeyInput.KEY_F,
KeyInput.KEY_G, KeyInput.KEY_H, KeyInput.KEY_I, KeyInput.KEY_J, KeyInput.KEY_K, KeyInput.KEY_L,
KeyInput.KEY_M, KeyInput.KEY_N, KeyInput.KEY_O, KeyInput.KEY_P, KeyInput.KEY_Q, KeyInput.KEY_R,
KeyInput.KEY_S, KeyInput.KEY_T, KeyInput.KEY_U, KeyInput.KEY_V, KeyInput.KEY_W, KeyInput.KEY_X,
KeyInput.KEY_Y, KeyInput.KEY_Z, KeyInput.KEY_CAPITAL, KeyInput.KEY_LSHIFT, KeyInput.KEY_RSHIFT,
KeyInput.KEY_UP, KeyInput.KEY_DOWN, KeyInput.KEY_LEFT, KeyInput.KEY_RIGHT
};
for (int idx=0; idx<keyCodes.length; idx++) {
String keyMapping = mappingKeyPrefix + KeyNames.getName(keyCodes[idx]);
inputManager.addMapping(keyMapping, new KeyTrigger(keyCodes[idx]));
inputManager.addListener(actionListener, keyMapping);
logger.log(Level.INFO, "Adding key mapping: {0}", keyMapping);
}
// setup InputManager to trigger our listeners when the various triggers are received.
// Touch inputs are all sent to the TouchTrigger. To have one mapping for all touch events, use TouchInput.ALL.
inputManager.addMapping(touchMapping, new TouchTrigger(TouchInput.ALL));
inputManager.addListener(touchListener, touchMapping);
// If inputManager.isSimulateMouse = true, touch events will be translated into Mouse Button and Axis events.
// To enable this, call inputManager.setSimulateMouse(true).
inputManager.addMapping(mappingMouseLeft, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(actionListener, mappingMouseLeft);
inputManager.addMapping(mappingMouseXNeg, new MouseAxisTrigger(MouseInput.AXIS_X, true));
inputManager.addMapping(mappingMouseXPos, new MouseAxisTrigger(MouseInput.AXIS_X, false));
inputManager.addMapping(mappingMouseYNeg, new MouseAxisTrigger(MouseInput.AXIS_Y, true));
inputManager.addMapping(mappingMouseYPos, new MouseAxisTrigger(MouseInput.AXIS_Y, false));
inputManager.addListener(analogListener, mappingMouseXNeg, mappingMouseXPos, mappingMouseYNeg, mappingMouseYPos);
// add raw input listener to inputManager
inputManager.addRawInputListener(rawInputListener);
float mouseSize = (settings.getWidth() >= settings.getHeight())? settings.getHeight()/2f: settings.getWidth()/2f;
picMouseBackground = new Picture("Mouse Background");
picMouseBackground.setImage(assetManager, "mouse_none.png", true);
picMouseBackground.setWidth(mouseSize);
picMouseBackground.setHeight(mouseSize);
picMouseBackground.setLocalTranslation(settings.getWidth()-mouseSize, 0f, 0f);
picMouseLeftButton = new Picture("Mouse Button Left");
picMouseLeftButton.setImage(assetManager, "mouse_left.png", true);
picMouseLeftButton.setWidth(mouseSize);
picMouseLeftButton.setHeight(mouseSize);
picMouseLeftButton.setLocalTranslation(settings.getWidth()-mouseSize, 0f, 1f);
picMouseDisabled = new Picture("Mouse Disabled");
picMouseDisabled.setImage(assetManager, "mouse_disabled.png", true);
picMouseDisabled.setWidth(mouseSize);
picMouseDisabled.setHeight(mouseSize);
picMouseDisabled.setLocalTranslation(settings.getWidth()-mouseSize, 0f, 1f);
float phoneSize = (settings.getWidth() >= settings.getHeight())? settings.getHeight()/2f: settings.getWidth()/2f;
// preload images to send data to gpu to avoid hesitations during run time the first time the image is displayed
renderManager.preloadScene(picMouseBackground);
renderManager.preloadScene(picMouseLeftButton);
renderManager.preloadScene(picMouseDisabled);
guiNode.attachChild(picMouseBackground);
if (inputManager.isSimulateMouse()) {
picMouseDisabled.removeFromParent();
} else {
guiNode.attachChild(picMouseDisabled);
}
textMouseLabel = new BitmapText(guiFont, false);
textMouseLabel.setSize(mouseSize/10f);
textMouseLabel.setColor(ColorRGBA.Blue);
textMouseLabel.setBox(new Rectangle(0f, 0f, mouseSize, mouseSize/5f));
textMouseLabel.setAlignment(BitmapFont.Align.Center);
textMouseLabel.setVerticalAlignment(BitmapFont.VAlign.Bottom);
textMouseLabel.setText("Mouse Analog\nand Position");
textMouseLabel.setLocalTranslation(settings.getWidth()-mouseSize, mouseSize*1.25f, 1f);
guiNode.attachChild(textMouseLabel);
textMouseAnalog = new BitmapText(guiFont, false);
textMouseAnalog.setSize(mouseSize/10f);
textMouseAnalog.setColor(ColorRGBA.Blue);
textMouseAnalog.setBox(new Rectangle(0f, 0f, mouseSize, mouseSize/10f));
textMouseAnalog.setAlignment(BitmapFont.Align.Center);
textMouseAnalog.setVerticalAlignment(BitmapFont.VAlign.Center);
textMouseAnalog.setText("0.000, 0.000");
textMouseAnalog.setLocalTranslation(settings.getWidth()-mouseSize, mouseSize/2f, 2f);
guiNode.attachChild(textMouseAnalog);
textMouseLocation = new BitmapText(guiFont, false);
textMouseLocation.setSize(mouseSize/10f);
textMouseLocation.setColor(ColorRGBA.Blue);
textMouseLocation.setBox(new Rectangle(0f, 0f, mouseSize, mouseSize/10f));
textMouseLocation.setAlignment(BitmapFont.Align.Center);
textMouseLocation.setVerticalAlignment(BitmapFont.VAlign.Center);
textMouseLocation.setText("0, 0");
textMouseLocation.setLocalTranslation(settings.getWidth()-mouseSize, mouseSize/2f-mouseSize/10f, 2f);
guiNode.attachChild(textMouseLocation);
textCursorLocation = new BitmapText(guiFont, false);
textCursorLocation.setSize(mouseSize/10f);
textCursorLocation.setColor(ColorRGBA.Blue);
textCursorLocation.setBox(new Rectangle(0f, 0f, mouseSize, mouseSize/10f));
textCursorLocation.setAlignment(BitmapFont.Align.Center);
textCursorLocation.setVerticalAlignment(BitmapFont.VAlign.Center);
textCursorLocation.setText("0, 0");
textCursorLocation.setLocalTranslation(settings.getWidth()-mouseSize, mouseSize/2f-mouseSize/10f*2f, 2f);
guiNode.attachChild(textCursorLocation);
textKeyPressed = new BitmapText(guiFont, false);
textKeyPressed.setSize(mouseSize/10f);
textKeyPressed.setColor(ColorRGBA.Blue);
textKeyPressed.setBox(new Rectangle(0f, 0f, settings.getWidth(), mouseSize/10f));
textKeyPressed.setAlignment(BitmapFont.Align.Center);
textKeyPressed.setVerticalAlignment(BitmapFont.VAlign.Top);
textKeyPressed.setText("Last Key Pressed: None");
textKeyPressed.setLocalTranslation(0f, settings.getHeight()-mouseSize/10f, 2f);
guiNode.attachChild(textKeyPressed);
picPhone = new Picture("Phone");
picPhone.setImage(assetManager, "phone_landscape.png", true);
picPhone.setWidth(phoneSize);
picPhone.setHeight(phoneSize);
picPhone.setLocalTranslation(picMouseBackground.getLocalTranslation().x - phoneSize, 0f, 1f);
guiNode.attachChild(picPhone);
textPhoneLocation = new BitmapText(guiFont, false);
textPhoneLocation.setSize(phoneSize/10f);
textPhoneLocation.setColor(ColorRGBA.White);
textPhoneLocation.setBox(new Rectangle(0f, 0f, phoneSize, phoneSize/10f));
textPhoneLocation.setAlignment(BitmapFont.Align.Center);
textPhoneLocation.setVerticalAlignment(BitmapFont.VAlign.Center);
textPhoneLocation.setText("0, 0");
textPhoneLocation.setLocalTranslation(picMouseBackground.getLocalTranslation().x - phoneSize, phoneSize*0.5f, 2f);
guiNode.attachChild(textPhoneLocation);
textPhoneLabel = new BitmapText(guiFont, false);
textPhoneLabel.setSize(phoneSize/10f);
textPhoneLabel.setColor(ColorRGBA.Blue);
textPhoneLabel.setBox(new Rectangle(0f, 0f, phoneSize, phoneSize/10f));
textPhoneLabel.setAlignment(BitmapFont.Align.Center);
textPhoneLabel.setVerticalAlignment(BitmapFont.VAlign.Bottom);
textPhoneLabel.setText("Touch Location");
textPhoneLabel.setLocalTranslation(picMouseBackground.getLocalTranslation().x - phoneSize, picPhone.getLocalTranslation().y + phoneSize*0.75f, 1f);
guiNode.attachChild(textPhoneLabel);
renderManager.preloadScene(picPhone);
}
private class MyTouchListener implements TouchListener {
@Override
public void onTouch(String name, TouchEvent event, float tpf) {
String touchEvent = event.toString();
logger.log(Level.INFO, "TouchListenerEvent: {0}", touchEvent);
switch (event.getType()) {
case DOWN:
case UP:
case MOVE:
case SCROLL:
textPhoneLocation.setText(
String.valueOf(locationFormat.format(event.getX())) + ", " +
String.valueOf(locationFormat.format(event.getY())));
break;
default:
}
}
}
protected class MyActionListener implements ActionListener {
@Override
public void onAction(String name, boolean isPressed, float tpf) {
logger.log(Level.INFO, "ActionListenerEvent[name:{0}, pressed: {1}, tpf: {2}",
new Object[]{name, isPressed, tpf});
if (name.equalsIgnoreCase(mappingMouseLeft)) {
if (isPressed) {
guiNode.attachChild(picMouseLeftButton);
} else {
picMouseLeftButton.removeFromParent();
}
textCursorLocation.setText(
String.valueOf(locationFormat.format(inputManager.getCursorPosition().getX())) + ", " +
String.valueOf(locationFormat.format(inputManager.getCursorPosition().getY())));
} else if (name.startsWith(mappingKeyPrefix)) {
logger.log(Level.INFO, "key event name: {0}, pressed: {1}", new Object[]{name, isPressed});
if (isPressed) {
textKeyPressed.setText("Last Key Pressed: " + name.substring(mappingKeyPrefix.length(), name.length()));
} else {
// textKeyPressed.setText("Key Pressed: None");
}
}
}
}
protected class MyAnalogListener implements AnalogListener {
float lastValueX = 0;
float lastValueY = 0;
@Override
public void onAnalog(String name, float value, float tpf) {
logger.log(Level.INFO, "AnalogListenerEvent[name:{0}, value: {1}, tpf: {2}",
new Object[]{name, value, tpf});
if (name.equalsIgnoreCase(mappingMouseXPos)) {
setValueX(value);
} else if (name.equalsIgnoreCase(mappingMouseXNeg)) {
setValueX(-value);
} else if (name.equalsIgnoreCase(mappingMouseYPos)) {
setValueY(value);
} else if (name.equalsIgnoreCase(mappingMouseYNeg)) {
setValueY(-value);
}
}
public void setValueX(float x) {
lastValueX = x;
textMouseAnalog.setText(
String.valueOf(analogFormat.format(lastValueX)) + ", " + String.valueOf(analogFormat.format(lastValueY)));
textCursorLocation.setText(
String.valueOf(locationFormat.format(inputManager.getCursorPosition().getX())) + ", " +
String.valueOf(locationFormat.format(inputManager.getCursorPosition().getY())));
}
public void setValueY(float y) {
lastValueY = y;
textMouseAnalog.setText(
String.valueOf(analogFormat.format(lastValueX)) + ", " + String.valueOf(analogFormat.format(lastValueY)));
textCursorLocation.setText(
String.valueOf(locationFormat.format(inputManager.getCursorPosition().getX())) + ", " +
String.valueOf(locationFormat.format(inputManager.getCursorPosition().getY())));
}
}
protected class MyRawInputListener implements RawInputListener {
@Override
public void beginInput() {
// logger.log(Level.INFO, "RawInputListenerEvent: BeginInput");
}
@Override
public void endInput() {
// logger.log(Level.INFO, "RawInputListenerEvent: EndInput");
}
@Override
public void onJoyAxisEvent(JoyAxisEvent event) {
logger.log(Level.INFO, "RawInputListenerEvent: {0}", event);
}
@Override
public void onJoyButtonEvent(JoyButtonEvent event) {
logger.log(Level.INFO, "RawInputListenerEvent: {0}", event);
}
@Override
public void onMouseMotionEvent(MouseMotionEvent event) {
logger.log(Level.INFO, "RawInputListenerEvent: {0}", event);
textMouseLocation.setText(
String.valueOf(locationFormat.format(event.getX())) + ", " + String.valueOf(locationFormat.format(event.getY())));
}
@Override
public void onMouseButtonEvent(MouseButtonEvent event) {
logger.log(Level.INFO, "RawInputListenerEvent: {0}", event);
textMouseLocation.setText(
String.valueOf(locationFormat.format(event.getX())) + ", " + String.valueOf(locationFormat.format(event.getY())));
}
@Override
public void onKeyEvent(KeyInputEvent event) {
logger.log(Level.INFO, "RawInputListenerEvent: {0}", event);
}
@Override
public void onTouchEvent(TouchEvent event) {
logger.log(Level.INFO, "RawInputListenerEvent: {0}", event);
}
}
}

@ -0,0 +1,12 @@
package jme3test.android;
import android.content.pm.ActivityInfo;
import android.app.*;
import android.os.Bundle;
public class TestChooserAndroid extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}

@ -1,165 +0,0 @@
package org.jmonkeyengine.jme3androidexamples;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class CustomArrayAdapter extends ArrayAdapter<String> {
private static final String TAG = "CustomArrayAdapter";
/* List of items */
private List<String> entries;
private Context activity;
/* Position of selected answer */
private int selectedPosition = -1;
/* Background Color of selected item */
private int selectedBackgroundColor = 0xffff00;
/* Background Color of non selected item */
private int nonselectedBackgroundColor = 0x000000;
/* Background Drawable Resource ID of selected item */
private int selectedBackgroundResource = 0;
/* Background Drawable Resource ID of non selected items */
private int nonselectedBackgroundResource = 0;
/* Variables to support list filtering */
private ArrayList<String> filteredEntries;
private Filter filter;
public CustomArrayAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
activity = context;
entries = new ArrayList<String>(objects);
filteredEntries = new ArrayList<String>(objects);
filter = new ClassNameFilter();
}
/** Setter for selected item position */
public void setSelectedPosition(int selectedPosition) {
this.selectedPosition = selectedPosition;
Log.i(TAG, "Setting position to: " + this.selectedPosition);
}
/** Setter for selected item background color */
public void setSelectedBackgroundColor(int selectedBackgroundColor) {
this.selectedBackgroundColor = selectedBackgroundColor;
}
/** Setter for non selected background color */
public void setNonSelectedBackgroundColor(int nonselectedBackgroundColor) {
this.nonselectedBackgroundColor = nonselectedBackgroundColor;
}
/** Setter for selected item background resource id*/
public void setSelectedBackgroundResource(int selectedBackgroundResource) {
this.selectedBackgroundResource = selectedBackgroundResource;
}
/** Setter for non selected background resource id*/
public void setNonSelectedBackgroundResource(int nonselectedBackgroundResource) {
this.nonselectedBackgroundResource = nonselectedBackgroundResource;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.i(TAG, "getView for position: " + position + " with selectedItem: " + selectedPosition);
View v = convertView;
ViewHolder holder;
if (v == null) {
LayoutInflater vi =
(LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.test_chooser_row, null);
holder = new ViewHolder();
holder.textView = (TextView) v.findViewById(R.id.txtClassName);
holder.layoutRow = (LinearLayout) v.findViewById(R.id.layoutTestChooserRow);
v.setTag(holder);
} else {
holder=(ViewHolder)v.getTag();
}
final String itemText = filteredEntries.get(position);
if (itemText != null) {
holder.textView.setText(itemText);
if (position == selectedPosition) {
Log.i(TAG, "setting Background Color to: " + selectedBackgroundColor);
// holder.textView.setBackgroundColor(selectedBackgroundColor);
// holder.textView.setBackgroundResource(selectedBackgroundResource);
holder.layoutRow.setBackgroundResource(selectedBackgroundResource);
} else {
Log.i(TAG, "setting Background Color to: " + nonselectedBackgroundColor);
// holder.textView.setBackgroundColor(nonselectedBackgroundColor);
// holder.textView.setBackgroundResource(nonselectedBackgroundResource);
holder.layoutRow.setBackgroundResource(nonselectedBackgroundResource);
}
}
return v;
}
@Override
public Filter getFilter(){
if(filter == null){
filter = new ClassNameFilter();
}
return filter;
}
public static class ViewHolder{
public TextView textView;
public LinearLayout layoutRow;
}
private class ClassNameFilter extends Filter{
@Override
protected FilterResults performFiltering(CharSequence constraint){
FilterResults results = new FilterResults();
String prefix = constraint.toString().toLowerCase();
Log.i(TAG, "performFiltering: entries size: " + entries.size());
if (prefix == null || prefix.length() == 0){
ArrayList<String> list = new ArrayList<String>(entries);
results.values = list;
results.count = list.size();
Log.i(TAG, "clearing filter with size: " + list.size());
}else{
final ArrayList<String> list = new ArrayList<String>(entries);
final ArrayList<String> nlist = new ArrayList<String>();
int count = list.size();
for (int i = 0; i<count; i++){
if(list.get(i).toLowerCase().contains(prefix)){
nlist.add(list.get(i));
}
results.values = nlist;
results.count = nlist.size();
}
Log.i(TAG, "filtered list size: " + nlist.size() + ", entries size: " + entries.size());
}
Log.i(TAG, "Returning filter count: " + results.count);
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredEntries = (ArrayList<String>)results.values;
notifyDataSetChanged();
clear();
int count = filteredEntries.size();
for(int i = 0; i<count; i++){
add(filteredEntries.get(i));
notifyDataSetInvalidated();
}
Log.i(TAG, "publishing results with size: " + count);
}
}
}

@ -1,85 +0,0 @@
package org.jmonkeyengine.jme3androidexamples;
import android.os.Bundle;
import com.jme3.app.AndroidHarnessFragment;
import java.util.logging.Level;
import java.util.logging.LogManager;
/**
* A placeholder fragment containing a jME GLSurfaceView.
*/
public class JmeFragment extends AndroidHarnessFragment {
public JmeFragment() {
// Set the desired EGL configuration
eglBitsPerPixel = 24;
eglAlphaBits = 0;
eglDepthBits = 16;
eglSamples = 0;
eglStencilBits = 0;
// Set the maximum framerate
// (default = -1 for unlimited)
frameRate = -1;
// Set the maximum resolution dimension
// (the smaller side, height or width, is set automatically
// to maintain the original device screen aspect ratio)
// (default = -1 to match device screen resolution)
maxResolutionDimension = -1;
/*
Skip these settings and use the settings stored in the Bundle retrieved during onCreate.
// Set main project class (fully qualified path)
appClass = "";
// Set input configuration settings
joystickEventsEnabled = false;
keyEventsEnabled = true;
mouseEventsEnabled = true;
*/
// Set application exit settings
finishOnAppStop = true;
handleExitHook = true;
exitDialogTitle = "Do you want to exit?";
exitDialogMessage = "Use your home key to bring this app into the background or exit to terminate it.";
// Set splash screen resource id, if used
// (default = 0, no splash screen)
// For example, if the image file name is "splash"...
// splashPicID = R.drawable.splash;
splashPicID = 0;
// splashPicID = R.drawable.android_splash;
// Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info)
LogManager.getLogManager().getLogger("").setLevel(Level.INFO);
}
@Override
public void onCreate(Bundle savedInstanceState) {
Bundle bundle=getArguments();
appClass = bundle.getString(MainActivity.SELECTED_APP_CLASS);
// Log.d(this.getClass().getSimpleName(), "AppClass: " + appClass);
joystickEventsEnabled = bundle.getBoolean(MainActivity.ENABLE_JOYSTICK_EVENTS);
// Log.d(this.getClass().getSimpleName(), "JoystickEventsEnabled: " + joystickEventsEnabled);
keyEventsEnabled = bundle.getBoolean(MainActivity.ENABLE_KEY_EVENTS);
// Log.d(this.getClass().getSimpleName(), "KeyEventsEnabled: " + keyEventsEnabled);
mouseEventsEnabled = bundle.getBoolean(MainActivity.ENABLE_MOUSE_EVENTS);
// Log.d(this.getClass().getSimpleName(), "MouseEventsEnabled: " + mouseEventsEnabled);
boolean verboseLogging = bundle.getBoolean(MainActivity.VERBOSE_LOGGING);
// Log.d(this.getClass().getSimpleName(), "VerboseLogging: " + verboseLogging);
if (verboseLogging) {
// Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info)
LogManager.getLogManager().getLogger("").setLevel(Level.ALL);
} else {
// Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info)
LogManager.getLogManager().getLogger("").setLevel(Level.INFO);
}
super.onCreate(savedInstanceState);
}
}

@ -1,458 +0,0 @@
package org.jmonkeyengine.jme3androidexamples;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import com.jme3.app.Application;
import dalvik.system.DexFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
//TODO: Create onscreen virtual keypad for triggering normal mapped keys used by test apps or modify test apps for touch with onscreen keypad
/**
* Main Activity started by the application. Users select different jME3 test
* applications that are started via TestsHarness Activity.
* @author iwgeric
*/
public class MainActivity extends AppCompatActivity implements OnItemClickListener, View.OnClickListener, TextWatcher {
private static final String TAG = "MainActivity";
/**
* Static String to pass the key for the selected test app to the
* TestsHarness class to start the application. Also used to store the
* current selection to the savedInstanceState Bundle.
*/
public static final String SELECTED_APP_CLASS = "Selected_App_Class";
/**
* Static String to pass the key for the selected list position to the
* savedInstanceState Bundle so the list position can be restored after
* exiting the test application.
*/
public static final String SELECTED_LIST_POSITION = "Selected_List_Position";
/**
* Static String to pass the key for the setting for enabling mouse events to the
* savedInstanceState Bundle.
*/
public static final String ENABLE_MOUSE_EVENTS = "Enable_Mouse_Events";
/**
* Static String to pass the key for the setting for enabling joystick events to the
* savedInstanceState Bundle.
*/
public static final String ENABLE_JOYSTICK_EVENTS = "Enable_Joystick_Events";
/**
* Static String to pass the key for the setting for enabling key events to the
* savedInstanceState Bundle.
*/
public static final String ENABLE_KEY_EVENTS = "Enable_Key_Events";
/**
* Static String to pass the key for the setting for verbose logging to the
* savedInstanceState Bundle.
*/
public static final String VERBOSE_LOGGING = "Verbose_Logging";
/* Fields to contain the current position and display contents of the spinner */
private int currentPosition = 0;
private String currentSelection = "";
private List<String> classNames = new ArrayList<String>();
private List<String> exclusions = new ArrayList<String>();
private String rootPackage;
/* ListView that displays the test application class names. */
private ListView listClasses;
/* ArrayAdapter connects the spinner widget to array-based data. */
private CustomArrayAdapter arrayAdapter;
/* Buttons to start application or stop the activity. */
private Button btnOK;
private Button btnCancel;
/* Filter Edit Box */
EditText editFilterText;
/* Custom settings for the test app */
private boolean enableMouseEvents = true;
private boolean enableJoystickEvents = false;
private boolean enableKeyEvents = true;
private boolean verboseLogging = false;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
Log.d(TAG, "Restoring selections in onCreate: "
+ "position: " + savedInstanceState.getInt(SELECTED_LIST_POSITION, 0)
+ "class: " + savedInstanceState.getString(SELECTED_APP_CLASS)
);
currentPosition = savedInstanceState.getInt(SELECTED_LIST_POSITION, 0);
currentSelection = savedInstanceState.getString(SELECTED_APP_CLASS);
enableMouseEvents = savedInstanceState.getBoolean(ENABLE_MOUSE_EVENTS, true);
enableJoystickEvents = savedInstanceState.getBoolean(ENABLE_JOYSTICK_EVENTS, false);
enableKeyEvents = savedInstanceState.getBoolean(ENABLE_KEY_EVENTS, true);
verboseLogging = savedInstanceState.getBoolean(VERBOSE_LOGGING, true);
}
/* Set content view and register views */
setContentView(R.layout.test_chooser_layout);
btnOK = (Button) findViewById(R.id.btnOK);
btnCancel = (Button) findViewById(R.id.btnCancel);
listClasses = (ListView) findViewById(R.id.listClasses);
editFilterText = (EditText) findViewById(R.id.txtFilter);
/* Define the root package to start with */
rootPackage = "jme3test";
/* Create an array of Strings to define which classes to exclude */
exclusions.add("$"); // inner classes
exclusions.add("TestChooser"); // Desktop test chooser class
exclusions.add("awt"); // Desktop test chooser class
// mExclusions.add("");
/*
* Read the class names from the dex file and filter based on
* name and super class.
*/
Log.d(TAG, "Composing Test list...");
ApplicationInfo ai = this.getApplicationInfo();
String classPath = ai.sourceDir;
DexFile dex = null;
Enumeration<String> apkClassNames = null;
try {
dex = new DexFile(classPath);
apkClassNames = dex.entries();
while (apkClassNames.hasMoreElements()) {
String className = apkClassNames.nextElement();
if (checkClassName(className) && checkClassType(className)) {
classNames.add(className);
}
// classNames.add(className);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dex.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* Create a backing Adapter for the List View from a list of the
* classes. The list is defined by array of class names.
*/
arrayAdapter = new CustomArrayAdapter(
this,
R.layout.test_chooser_row, // text view to display selection
classNames // array of strings to display
);
/* Set the resource id for selected and non selected backgrounds */
Log.d(TAG, "Setting Adapter Background Resource IDs");
arrayAdapter.setSelectedBackgroundResource(R.drawable.selected);
arrayAdapter.setNonSelectedBackgroundResource(R.drawable.nonselected);
/* Attach the Adapter to the spinner */
Log.d(TAG, "Setting ListView Adapter");
listClasses.setAdapter(arrayAdapter);
/* Set initial selection for the list */
setSelection(currentPosition);
/* Set Click and Text Changed listeners */
listClasses.setOnItemClickListener(this);
btnOK.setOnClickListener(this);
btnCancel.setOnClickListener(this);
editFilterText.addTextChangedListener(this);
}
/**
* User selected an application. Sets the current selection and redraws
* the list view to highlight the selected item.
* @param parent AdapterView tied to the list
* @param view The ListView
* @param position Selection position in the list of class names
* @param id
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setSelection(position);
}
/**
* User clicked a view on the screen. Check for the OK and Cancel buttons
* and either start the application or exit.
* @param view
*/
public void onClick(View view) {
if (view.equals(btnOK)) {
/* Get selected class, pack it in the intent and start the test app */
Log.d(TAG, "User selected OK for class: " + currentSelection);
Intent intent = new Intent(this, TestActivity.class);
// intent.putExtra(SELECTED_APP_CLASS, currentSelection);
// intent.putExtra(ENABLE_MOUSE_EVENTS, enableMouseEvents);
// intent.putExtra(ENABLE_JOYSTICK_EVENTS, enableJoystickEvents);
// intent.putExtra(ENABLE_KEY_EVENTS, enableKeyEvents);
Bundle args = new Bundle();
args.putString(MainActivity.SELECTED_APP_CLASS, currentSelection);
// Log.d(this.getClass().getSimpleName(), "AppClass="+currentSelection);
args.putBoolean(MainActivity.ENABLE_MOUSE_EVENTS, enableMouseEvents);
// Log.d(TestActivity.class.getSimpleName(), "MouseEnabled="+enableMouseEvents);
args.putBoolean(MainActivity.ENABLE_JOYSTICK_EVENTS, enableJoystickEvents);
// Log.d(TestActivity.class.getSimpleName(), "JoystickEnabled="+enableJoystickEvents);
args.putBoolean(MainActivity.ENABLE_KEY_EVENTS, enableKeyEvents);
// Log.d(TestActivity.class.getSimpleName(), "KeyEnabled="+enableKeyEvents);
args.putBoolean(MainActivity.VERBOSE_LOGGING, verboseLogging);
// Log.d(TestActivity.class.getSimpleName(), "VerboseLogging="+verboseLogging);
intent.putExtras(args);
startActivity(intent);
} else if (view.equals(btnCancel)) {
/* Exit */
Log.d(TAG, "User selected Cancel");
finish();
}
}
/**
* Check class name to see if the class is in the root package and if it
* contains any of the exclusion strings
* @param className Class name to check
* @return true if the check passes, false otherwise
*/
private boolean checkClassName(String className) {
boolean include = true;
/* check to see if the class in inside the rootPackage package */
if (className.startsWith(rootPackage)) {
/* check to see if the class contains any of the exlusion strings */
for (int i = 0; i < exclusions.size(); i++) {
if (className.contains(exclusions.get(i))) {
Log.d(TAG, "Skipping Class " + className + ". Includes exclusion string: " + exclusions.get(i) + ".");
include = false;
break;
}
}
} else {
include = false;
Log.d(TAG, "Skipping Class " + className + ". Not in the root package: " + rootPackage + ".");
}
return include;
}
/**
* Check to see if the class extends Application or SimpleApplication
* @param className Class name to check
* @return true if the check passes, false otherwise
*/
private boolean checkClassType(String className) {
boolean include = true;
try {
Class<?> clazz = Class.forName(className);
if (Application.class.isAssignableFrom(clazz)) {
Log.d(TAG, "Class " + className + " is a jME Application");
} else {
include = false;
Log.d(TAG, "Skipping Class " + className + ". Not a jME Application");
}
} catch (NoClassDefFoundError ncdf) {
include = false;
Log.d(TAG, "Skipping Class " + className + ". No Class Def found.");
} catch (ClassNotFoundException cnfe) {
include = false;
Log.d(TAG, "Skipping Class " + className + ". Class not found.");
}
return include;
}
private void setSelection(int position) {
if (position == -1) {
arrayAdapter.setSelectedPosition(-1);
currentPosition = -1;
currentSelection = "";
btnOK.setEnabled(false);
listClasses.invalidateViews();
} else {
arrayAdapter.setSelectedPosition(position);
currentPosition = position;
currentSelection = arrayAdapter.getItem(position);
btnOK.setEnabled(true);
listClasses.invalidateViews();
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.d(TAG, "Saving selections in onSaveInstanceState: "
+ "position: " + currentPosition + ", "
+ "class: " + currentSelection + ", "
+ "mouseEvents: " + enableMouseEvents + ", "
+ "joystickEvents: " + enableJoystickEvents + ", "
+ "keyEvents: " + enableKeyEvents + ", "
+ "VerboseLogging: " + verboseLogging + ", "
);
// Save current selections to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putString(SELECTED_APP_CLASS, currentSelection);
savedInstanceState.putInt(SELECTED_LIST_POSITION, currentPosition);
savedInstanceState.putBoolean(ENABLE_MOUSE_EVENTS, enableMouseEvents);
savedInstanceState.putBoolean(ENABLE_JOYSTICK_EVENTS, enableJoystickEvents);
savedInstanceState.putBoolean(ENABLE_KEY_EVENTS, enableKeyEvents);
savedInstanceState.putBoolean(VERBOSE_LOGGING, verboseLogging);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Log.i(TAG, "Restoring selections in onRestoreInstanceState: "
// + "position: " + savedInstanceState.getInt(SELECTED_LIST_POSITION, 0)
// + "class: " + savedInstanceState.getString(SELECTED_APP_CLASS)
// );
// //Restore selections from the savedInstanceState.
// // This bundle has also been passed to onCreate.
// currentPosition = savedInstanceState.getInt(SELECTED_LIST_POSITION, 0);
// currentSelection = savedInstanceState.getString(SELECTED_APP_CLASS);
}
public void beforeTextChanged(CharSequence cs, int i, int i1, int i2) {
}
public void onTextChanged(CharSequence cs, int startPos, int beforePos, int count) {
Log.d(TAG, "onTextChanged with cs: " + cs + ", startPos: " + startPos + ", beforePos: " + beforePos + ", count: " + count);
arrayAdapter.getFilter().filter(cs.toString());
setSelection(-1);
}
public void afterTextChanged(Editable edtbl) {
}
@Override
protected void onDestroy() {
super.onDestroy();
editFilterText.removeTextChangedListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_items, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu (Menu menu) {
MenuItem item;
item = menu.findItem(R.id.optionMouseEvents);
if (item != null) {
Log.d(TAG, "Found EnableMouseEvents menu item");
if (enableMouseEvents) {
item.setTitle(R.string.strOptionDisableMouseEventsTitle);
} else {
item.setTitle(R.string.strOptionEnableMouseEventsTitle);
}
}
item = menu.findItem(R.id.optionJoystickEvents);
if (item != null) {
Log.d(TAG, "Found EnableJoystickEvents menu item");
if (enableJoystickEvents) {
item.setTitle(R.string.strOptionDisableJoystickEventsTitle);
} else {
item.setTitle(R.string.strOptionEnableJoystickEventsTitle);
}
}
item = menu.findItem(R.id.optionKeyEvents);
if (item != null) {
Log.d(TAG, "Found EnableKeyEvents menu item");
if (enableKeyEvents) {
item.setTitle(R.string.strOptionDisableKeyEventsTitle);
} else {
item.setTitle(R.string.strOptionEnableKeyEventsTitle);
}
}
item = menu.findItem(R.id.optionVerboseLogging);
if (item != null) {
Log.d(TAG, "Found EnableVerboseLogging menu item");
if (verboseLogging) {
item.setTitle(R.string.strOptionDisableVerboseLoggingTitle);
} else {
item.setTitle(R.string.strOptionEnableVerboseLoggingTitle);
}
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.optionMouseEvents:
enableMouseEvents = !enableMouseEvents;
Log.d(TAG, "enableMouseEvents set to: " + enableMouseEvents);
break;
case R.id.optionJoystickEvents:
enableJoystickEvents = !enableJoystickEvents;
Log.d(TAG, "enableJoystickEvents set to: " + enableJoystickEvents);
break;
case R.id.optionKeyEvents:
enableKeyEvents = !enableKeyEvents;
Log.d(TAG, "enableKeyEvents set to: " + enableKeyEvents);
break;
case R.id.optionVerboseLogging:
verboseLogging = !verboseLogging;
Log.d(TAG, "verboseLogging set to: " + verboseLogging);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
}

@ -1,111 +0,0 @@
package org.jmonkeyengine.jme3androidexamples;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.jme3.system.JmeSystem;
public class TestActivity extends AppCompatActivity {
JmeFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
fragment = new JmeFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
Bundle bundle = savedInstanceState;
if (bundle == null) {
bundle = getIntent().getExtras();
}
String appClass = bundle.getString(MainActivity.SELECTED_APP_CLASS);
args.putString(MainActivity.SELECTED_APP_CLASS, appClass);
// Log.d(TestActivity.class.getSimpleName(), "AppClass="+appClass);
boolean mouseEnabled = bundle.getBoolean(MainActivity.ENABLE_MOUSE_EVENTS, true);
args.putBoolean(MainActivity.ENABLE_MOUSE_EVENTS, mouseEnabled);
// Log.d(TestActivity.class.getSimpleName(), "MouseEnabled="+mouseEnabled);
boolean joystickEnabled = bundle.getBoolean(MainActivity.ENABLE_JOYSTICK_EVENTS, true);
args.putBoolean(MainActivity.ENABLE_JOYSTICK_EVENTS, joystickEnabled);
// Log.d(TestActivity.class.getSimpleName(), "JoystickEnabled="+joystickEnabled);
boolean keyEnabled = bundle.getBoolean(MainActivity.ENABLE_KEY_EVENTS, true);
args.putBoolean(MainActivity.ENABLE_KEY_EVENTS, keyEnabled);
// Log.d(TestActivity.class.getSimpleName(), "KeyEnabled="+keyEnabled);
boolean verboseLogging = bundle.getBoolean(MainActivity.VERBOSE_LOGGING, true);
args.putBoolean(MainActivity.VERBOSE_LOGGING, verboseLogging);
// Log.d(TestActivity.class.getSimpleName(), "VerboseLogging="+verboseLogging);
fragment.setArguments(args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.add(R.id.fragmentContainer, fragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.test_menu_items, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu (Menu menu) {
MenuItem item;
item = menu.findItem(R.id.optionToggleKeyboard);
if (item != null) {
// Log.d(this.getClass().getSimpleName(), "Found ToggleKeyboard menu item");
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.optionToggleKeyboard:
toggleKeyboard(true);
// Log.d(this.getClass().getSimpleName(), "showing soft keyboard");
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
private void toggleKeyboard(final boolean show) {
fragment.getView().getHandler().post(new Runnable() {
@Override
public void run() {
JmeSystem.showSoftKeyboard(show);
}
});
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:keepScreenOn="true"
tools:context="org.jmonkeyengine.jme3androidexamples.TestActivity">
<!--
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="org.jmonkeyengine.jme3androidexamples.JmeFragment"
android:id="@+id/jMEFragment"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"/>
-->
</RelativeLayout>

@ -1,119 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutTestChooser"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF"
>
<TextView
android:id="@+id/lblTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="@string/strLblTitle"
android:textSize="20sp"
android:textColor="#000000"
/>
<LinearLayout
android:id="@+id/layoutFilter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/lblTitle"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:orientation="horizontal"
>
<TextView
android:id="@+id/lblFindTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="@string/strLblFindTitle"
android:textSize="20sp"
android:textColor="#000000"
/>
<EditText
android:id="@+id/txtFilter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="@string/strTxtFilterHint"
android:inputType="text"
android:textSize="20sp"
android:textColor="#000000"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/layoutButtons"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center"
android:layout_marginTop="20dp"
android:focusable="true"
android:focusableInTouchMode="true"
>
<Button
android:id="@+id/btnOK"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@string/strBtnOK"
android:layout_marginRight="20dp"
android:textSize="20sp"
android:textColor="#000000"
/>
<Button
android:id="@+id/btnCancel"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@string/strBtnCancel"
android:layout_marginLeft="20dp"
android:textSize="20sp"
android:textColor="#000000"
/>
<requestFocus/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@id/layoutButtons"
android:layout_below="@id/layoutFilter"
android:gravity="center"
android:background="@drawable/selected"
>
<ListView
android:id="@+id/listClasses"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:choiceMode="singleChoice"
android:listSelector="@drawable/selected"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:textFilterEnabled="true"
>
</ListView>
</LinearLayout>
</RelativeLayout>

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutTestChooserRow"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp">
<!--
<ImageView android:id="@+id/imgIcon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_marginRight="15dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
-->
<TextView android:id="@+id/txtClassName"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:textStyle="bold"
android:textSize="22sp"
android:textColor="#000000"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
</LinearLayout>

@ -1,33 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.jmonkeyengine.jme3androidexamples.MainActivity">
<item
android:id="@+id/optionMouseEvents"
android:orderInCategory="100"
android:title="@string/strOptionEnableMouseEventsTitle"
app:showAsAction="never" />
<item
android:id="@+id/optionJoystickEvents"
android:orderInCategory="200"
android:title="@string/strOptionEnableJoystickEventsTitle"
app:showAsAction="never" />
<item
android:id="@+id/optionKeyEvents"
android:orderInCategory="300"
android:title="@string/strOptionEnableKeyEventsTitle"
app:showAsAction="never" />
<item
android:id="@+id/optionVerboseLogging"
android:orderInCategory="300"
android:title="@string/strOptionEnableVerboseLoggingTitle"
app:showAsAction="never" />
<!--
android:icon="@mipmap/redmonkey"
android:icon="@mipmap/greenmonkey"
android:icon="@mipmap/bluemonkey"
-->
</menu>

@ -1,19 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.jmonkeyengine.jme3androidexamples.MainActivity">
<item
android:id="@+id/optionToggleKeyboard"
android:orderInCategory="100"
android:title="@string/strOptionShowKeyboard"
app:showAsAction="ifRoom"
android:icon="@drawable/keyboard"
/>
<!--
android:icon="@mipmap/redmonkey"
android:icon="@mipmap/greenmonkey"
android:icon="@mipmap/bluemonkey"
-->
</menu>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

@ -1,6 +0,0 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">0dp</dimen>
</resources>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

@ -1,5 +0,0 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">0dp</dimen>
<dimen name="activity_vertical_margin">0dp</dimen>
</resources>

@ -1,26 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Main Application Title -->
<string name="app_name">jME3 Tests Android</string>
<!-- MainActivity UIF Labels -->
<string name="strLblTitle">Choose a demo to start:</string>
<string name="strLblFindTitle">Find:</string>
<string name="strTxtFilterHint">Enter a Filter</string>
<string name="strBtnOK">OK</string>
<string name="strBtnCancel">Cancel</string>
<!-- MainActivity Menu Labels -->
<string name="strOptionEnableMouseEventsTitle">Enable Mouse Events</string>
<string name="strOptionDisableMouseEventsTitle">Disable Mouse Events</string>
<string name="strOptionEnableJoystickEventsTitle">Enable Joystick Events</string>
<string name="strOptionDisableJoystickEventsTitle">Disable Joystick Events</string>
<string name="strOptionEnableKeyEventsTitle">Enable Key Events</string>
<string name="strOptionDisableKeyEventsTitle">Disable Key Events</string>
<string name="strOptionEnableVerboseLoggingTitle">Enable Verbose Logging</string>
<string name="strOptionDisableVerboseLoggingTitle">Disable Verbose Logging</string>
<!-- TestActivity Menu Labels -->
<string name="strOptionShowKeyboard">Show Keyboard</string>
<string name="strOptionHideKeyboard">Show Keyboard</string>
</resources>
<string name="app_name">JMEAndroidTest</string>
<string name="about">About</string>
<string name="quit">Quit</string>
</resources>

@ -1,11 +0,0 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

@ -1,15 +0,0 @@
package org.jmonkeyengine.jme3androidexamples;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}

@ -1,2 +0,0 @@
# The headers are autogenerated and nobody should try to commit them...
src/native/headers

@ -46,4 +46,4 @@ ext {
apply from: file('openalsoft.gradle')
// apply from: file('stb_image.gradle')
// apply from: file('tremor.gradle')
apply from: file('decode.gradle')
apply from: file('decode.gradle')

@ -1,43 +1,40 @@
String tremorZipFile = "TremorAndroid.zip"
String stbiUrl = 'https://raw.githubusercontent.com/jMonkeyEngine/stb/0224a44a10564a214595797b4c88323f79a5f934/stb_image.h'
String stbiUrl = 'https://raw.githubusercontent.com/nothings/stb/master/stb_image.h'
// Working directories for the ndk build.
String decodeBuildDir = "${buildDir}" + File.separator + 'decode'
String decodeClassesBuildDir = "${buildDir}" + File.separator + 'decode_classes'
String decodeBuildJniDir = decodeBuildDir + File.separator + 'jni'
String decodeBuildLibsDir = decodeBuildDir + File.separator + 'libs'
// Pre-compiled libs directory
def rootPath = rootProject.projectDir.absolutePath
String decodePreCompiledLibsDir = rootPath + File.separator + 'build' + File.separator + 'native' + File.separator + 'android' + File.separator + 'decode'
String decodePreCompiledLibsDir = 'libs' + File.separator + 'decode'
// jME Android Native source files path
String decodeSourceDir = 'src/native/jme_decode'
String jmeHeaders = 'src/native/headers'
task downloadStbImage(type: MyDownload) {
sourceUrl = stbiUrl
target = file(decodeBuildDir + File.separator + 'stb_image.h')
target = file('stb_image.h')
}
// Copy stb_image.h to the jni directory.
// Copy stb_image.h to the source directory.
task copyStbiFiles(type: Copy) {
def sourceDir = file(decodeBuildDir + File.separator + 'stb_image.h')
def outputDir = file(decodeBuildJniDir + File.separator + "STBI")
def sourceDir = file('stb_image.h')
def outputDir = file(decodeSourceDir + File.separator + "STBI")
from sourceDir
into outputDir
}
copyStbiFiles.dependsOn {
def stbiFile = file(decodeBuildDir + File.separator + 'stb_image.h')
def stbiFile = file('stb_image.h')
if (!stbiFile.exists()) {
downloadStbImage
}
}
// Copy libtremor source to the jni directory.
// Copy libtremor source to the source directory.
task copyTremorFiles(type: Copy) {
def zipFile = file(tremorZipFile)
def outputDir = file(decodeBuildJniDir + File.separator + "Tremor")
def outputDir = file(decodeSourceDir + File.separator + "Tremor")
from (zipTree(zipFile)) {
include '*.c'
@ -47,13 +44,17 @@ task copyTremorFiles(type: Copy) {
into outputDir
}
task copyJmeHeadersDecode(type: Copy) {
from file(jmeHeaders)
into file(decodeBuildJniDir + File.separator + "headers")
// Generate headers via javah
task generateJavahHeaders(type: Exec) {
executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
args '-d', decodeSourceDir
args '-classpath', project.projectClassPath
args "com.jme3.audio.plugins.NativeVorbisFile"
args "com.jme3.texture.plugins.AndroidNativeImageLoader"
}
// Copy jME Android native files to jni directory
task copySourceToBuild(type: Copy, dependsOn:[copyTremorFiles, copyStbiFiles, copyJmeHeadersDecode]) {
task copySourceToBuild(type: Copy, dependsOn:[copyTremorFiles, copyStbiFiles, generateJavahHeaders]) {
def sourceDir = file(decodeSourceDir)
def outputDir = file(decodeBuildJniDir)
@ -84,9 +85,7 @@ task copyPreCompiledLibs(type: Copy) {
into outputDir
}
// ndkExists is a boolean from the build.gradle in the root project
// buildNativeProjects is a string set to "true"
if (ndkExists && buildNativeProjects == "true") {
if (rootProject.ndkExists && rootProject.buildNativeProjects) {
// build native libs and update stored pre-compiled libs to commit
compileJava.dependsOn { updatePreCompiledLibs }
} else {

@ -1,42 +1,39 @@
// OpenAL Soft r1.16
String openALSoftUrl = 'https://github.com/jMonkeyEngine/openal-soft/archive/e5016f814a265ed592a88acea95cf912c4bfdf12.zip'
String openALSoftUrl = 'http://repo.or.cz/w/openal-soft.git/snapshot/e5016f814a265ed592a88acea95cf912c4bfdf12.zip'
String openALSoftZipFile = 'OpenALSoft.zip'
// OpenAL Soft directory the download is extracted into
// Typically, the downloaded OpenAL Soft zip file will extract to a directory
// called "openal-soft"
String openALSoftFolder = 'openal-soft-e5016f814a265ed592a88acea95cf912c4bfdf12'
String openALSoftFolder = 'openal-soft'
//Working directories for the ndk build.
String openalsoftBuildDir = "${buildDir}" + File.separator + 'openalsoft'
String openalsoftClassesBuildDir = "${buildDir}" + File.separator + 'openalsoft_classes'
String openalsoftBuildJniDir = openalsoftBuildDir + File.separator + 'jni'
String openalsoftBuildLibsDir = openalsoftBuildDir + File.separator + 'libs'
//Pre-compiled libs directory
def rootPath = rootProject.projectDir.absolutePath
String openalsoftPreCompiledLibsDir = rootPath + File.separator + 'build' + File.separator + 'native' + File.separator + 'android' + File.separator + 'openalsoft'
String openalsoftPreCompiledLibsDir = 'libs' + File.separator + 'openalsoft'
// jME Android Native source files path
String openalsoftJmeAndroidPath = 'src/native/jme_openalsoft'
String jmeHeaders = 'src/native/headers'
// Download external source files if not available
task downloadOpenALSoft(type: MyDownload) {
sourceUrl = openALSoftUrl
target = file(openalsoftBuildDir + File.separator + openALSoftZipFile)
target = file(openALSoftZipFile)
}
// Unzip external source files
task unzipOpenALSoft(type: Copy) {
def zipFile = file(openalsoftBuildDir + File.separator + openALSoftZipFile)
def outputDir = file(openalsoftBuildDir)
def zipFile = file(openALSoftZipFile)
def outputDir = file(".")
from zipTree(zipFile)
into outputDir
}
unzipOpenALSoft.dependsOn {
def zipFilePath = openalsoftBuildDir + File.separator + openALSoftZipFile
def zipFilePath = project.projectDir.absolutePath + File.separator + openALSoftZipFile
def zipFile = new File(zipFilePath)
// println "zipFile path: " + zipFile.absolutePath
// println "zipFile exists: " + zipFile.exists()
@ -47,7 +44,7 @@ unzipOpenALSoft.dependsOn {
// Copy external source files to jni directory
task copyOpenALSoft(type: Copy) {
def sourceDir = file(openalsoftBuildDir + File.separator + openALSoftFolder)
def sourceDir = file(openALSoftFolder)
def outputDir = file(openalsoftBuildJniDir)
// println "copyOpenALSoft sourceDir: " + sourceDir
// println "copyOpenALSoft outputDir: " + outputDir
@ -64,14 +61,8 @@ copyOpenALSoft.dependsOn {
}
}
// Copy JME Headers to jni directory
task copyJmeHeadersOpenAL(type: Copy) {
from file(jmeHeaders)
into file(openalsoftBuildJniDir + File.separator + "headers")
}
// Copy jME Android native files to jni directory
task copyJmeOpenALSoft(type: Copy, dependsOn: [copyOpenALSoft, copyJmeHeadersOpenAL]) {
task copyJmeOpenALSoft(type: Copy, dependsOn:copyOpenALSoft) {
def sourceDir = file(openalsoftJmeAndroidPath)
def outputDir = file(openalsoftBuildJniDir)
// println "copyJmeOpenALSoft sourceDir: " + sourceDir
@ -81,7 +72,16 @@ task copyJmeOpenALSoft(type: Copy, dependsOn: [copyOpenALSoft, copyJmeHeadersOpe
into outputDir
}
task buildOpenAlSoftNativeLib(type: Exec, dependsOn: copyJmeOpenALSoft) {
task generateOpenAlSoftHeaders(type:Exec, dependsOn: copyJmeOpenALSoft) {
executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
args '-d', openalsoftJmeAndroidPath
args '-classpath', project.projectClassPath
args "com.jme3.audio.android.AndroidAL"
args "com.jme3.audio.android.AndroidALC"
args "com.jme3.audio.android.AndroidEFX"
}
task buildOpenAlSoftNativeLib(type: Exec, dependsOn: generateOpenAlSoftHeaders) {
// println "openalsoft build dir: " + openalsoftBuildDir
// println "ndkCommandPath: " + project.ndkCommandPath
workingDir openalsoftBuildDir
@ -111,9 +111,7 @@ task copyPreCompiledOpenAlSoftLibs(type: Copy) {
into outputDir
}
// ndkExists is a boolean from the build.gradle in the root project
// buildNativeProjects is a string set to "true"
if (ndkExists && buildNativeProjects == "true") {
if (rootProject.ndkExists && rootProject.buildNativeProjects) {
// build native libs and update stored pre-compiled libs to commit
compileJava.dependsOn { updatePreCompiledOpenAlSoftLibs }
} else {

@ -4,7 +4,7 @@
#include "Tremor/ivorbisfile.h"
#include "../headers/com_jme3_audio_plugins_NativeVorbisFile.h"
#include "com_jme3_audio_plugins_NativeVorbisFile.h"
#ifndef NDEBUG
#include <android/log.h>
@ -345,4 +345,4 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_close
free(wrapper);
free(ovf);
(*env)->SetObjectField(env, nvf, nvf_field_ovf, NULL);
}
}

@ -1,4 +1,4 @@
#include "../headers/com_jme3_texture_plugins_AndroidNativeImageLoader.h"
#include "com_jme3_texture_plugins_AndroidNativeImageLoader.h"
#include <assert.h>
#ifndef NDEBUG

@ -1,4 +1,4 @@
#include "../headers/com_jme3_audio_android_AndroidAL.h"
#include "com_jme3_audio_android_AndroidAL.h"
#include "AL/al.h"
#include "AL/alext.h"

@ -0,0 +1,173 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jme3_audio_android_AndroidAL */
#ifndef _Included_com_jme3_audio_android_AndroidAL
#define _Included_com_jme3_audio_android_AndroidAL
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGetString
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidAL_alGetString
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGenSources
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGenSources
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGetError
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetError
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alDeleteSources
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteSources
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGenBuffers
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alGenBuffers
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alDeleteBuffers
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteBuffers
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourceStop
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceStop
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcei
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcei
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alBufferData
* Signature: (IILjava/nio/ByteBuffer;II)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alBufferData
(JNIEnv *, jobject, jint, jint, jobject, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcePlay
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePlay
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcePause
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePause
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourcef
* Signature: (IIF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcef
(JNIEnv *, jobject, jint, jint, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSource3f
* Signature: (IIFFF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3f
(JNIEnv *, jobject, jint, jint, jfloat, jfloat, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alGetSourcei
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetSourcei
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourceUnqueueBuffers
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceUnqueueBuffers
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSourceQueueBuffers
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceQueueBuffers
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alListener
* Signature: (ILjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alListenerf
* Signature: (IF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListenerf
(JNIEnv *, jobject, jint, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alListener3f
* Signature: (IFFF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener3f
(JNIEnv *, jobject, jint, jfloat, jfloat, jfloat);
/*
* Class: com_jme3_audio_android_AndroidAL
* Method: alSource3i
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3i
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
#ifdef __cplusplus
}
#endif
#endif

@ -1,5 +1,5 @@
#include "util.h"
#include "../headers/com_jme3_audio_android_AndroidALC.h"
#include "com_jme3_audio_android_AndroidALC.h"
#include "AL/alc.h"
#include "AL/alext.h"
@ -171,4 +171,4 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDeviceResumeSOF
if (device == NULL) return;
alcDeviceResumeSOFT(device);
}
}

@ -0,0 +1,77 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jme3_audio_android_AndroidALC */
#ifndef _Included_com_jme3_audio_android_AndroidALC
#define _Included_com_jme3_audio_android_AndroidALC
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: createALC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_createALC
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: destroyALC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_destroyALC
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: isCreated
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_isCreated
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcGetString
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetString
(JNIEnv *, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcIsExtensionPresent
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_alcIsExtensionPresent
(JNIEnv *, jobject, jstring);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcGetInteger
* Signature: (ILjava/nio/IntBuffer;I)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetInteger
(JNIEnv *, jobject, jint, jobject, jint);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcDevicePauseSOFT
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDevicePauseSOFT
(JNIEnv *, jobject);
/*
* Class: com_jme3_audio_android_AndroidALC
* Method: alcDeviceResumeSOFT
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDeviceResumeSOFT
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

@ -1,5 +1,5 @@
#include "util.h"
#include "../headers/com_jme3_audio_android_AndroidEFX.h"
#include "com_jme3_audio_android_AndroidEFX.h"
#include "AL/alext.h"
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenAuxiliaryEffectSlots
@ -72,4 +72,4 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffectf
(JNIEnv* env, jobject obj, jint effect, jint param, jfloat value)
{
alEffectf((ALuint)effect, (ALenum)param, (ALfloat)value);
}
}

@ -0,0 +1,101 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jme3_audio_android_AndroidEFX */
#ifndef _Included_com_jme3_audio_android_AndroidEFX
#define _Included_com_jme3_audio_android_AndroidEFX
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alGenAuxiliaryEffectSlots
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenAuxiliaryEffectSlots
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alGenEffects
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenEffects
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alEffecti
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffecti
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alAuxiliaryEffectSloti
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alAuxiliaryEffectSloti
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alDeleteEffects
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteEffects
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alDeleteAuxiliaryEffectSlots
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteAuxiliaryEffectSlots
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alGenFilters
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenFilters
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alFilteri
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilteri
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alFilterf
* Signature: (IIF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilterf
(JNIEnv *, jobject, jint, jint, jfloat);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alDeleteFilters
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteFilters
(JNIEnv *, jobject, jint, jobject);
/*
* Class: com_jme3_audio_android_AndroidEFX
* Method: alEffectf
* Signature: (IIF)V
*/
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffectf
(JNIEnv *, jobject, jint, jint, jfloat);
#ifdef __cplusplus
}
#endif
#endif

@ -1,5 +1,3 @@
apply plugin: 'java'
if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
@ -7,10 +5,5 @@ if (!hasProperty('mainClass')) {
dependencies {
compile project(':jme3-core')
compile project(':jme3-plugins')
compileOnly 'android:android'
}
compileJava {
// The Android-Native Project requires the jni headers to be generated, so we do that here
options.compilerArgs += ["-h", "${project.rootDir}/jme3-android-native/src/native/headers"]
compile files('../lib/android.jar')
}

@ -3,6 +3,7 @@ package com.jme3.app;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.opengl.GLSurfaceView;
@ -88,7 +89,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
protected int eglStencilBits = 0;
/**
* Set the desired frame rate. If frameRate higher than 0, the application
* Set the desired frame rate. If frameRate > 0, the application
* will be capped at the desired frame rate.
* (default = -1, no frame rate cap)
*/
@ -239,8 +240,9 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
// Create application instance
try {
if (app == null) {
Class clazz = Class.forName(appClass);
app = (LegacyApplication)clazz.newInstance();
@SuppressWarnings("unchecked")
Class<? extends LegacyApplication> clazz = (Class<? extends LegacyApplication>) Class.forName(appClass);
app = clazz.newInstance();
}
app.setSettings(settings);
@ -361,7 +363,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
* @param dialog
* @param whichButton
*/
@Override
public void onClick(DialogInterface dialog, int whichButton) {
if (whichButton != -2) {
if (app != null) {
@ -473,7 +474,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
handler.setLevel(Level.ALL);
}
@Override
public void initialize() {
app.initialize();
if (handleExitHook) {
@ -489,12 +489,10 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
}
}
@Override
public void reshape(int width, int height) {
app.reshape(width, height);
}
@Override
public void update() {
app.update();
// call to remove the splash screen, if present.
@ -506,12 +504,10 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
}
}
@Override
public void requestClose(boolean esc) {
app.requestClose(esc);
}
@Override
public void destroy() {
if (app != null) {
app.destroy();
@ -521,7 +517,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
}
}
@Override
public void gainFocus() {
logger.fine("gainFocus");
if (view != null) {
@ -553,7 +548,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
}
}
@Override
public void loseFocus() {
logger.fine("loseFocus");
if (app != null) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2020 jMonkeyEngine
* Copyright (c) 2009-2015 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -116,7 +116,7 @@ public class AndroidHarnessFragment extends Fragment implements
protected int eglStencilBits = 0;
/**
* Set the desired frame rate. If frameRate higher than 0, the application
* Set the desired frame rate. If frameRate > 0, the application
* will be capped at the desired frame rate.
* (default = -1, no frame rate cap)
*/
@ -125,11 +125,11 @@ public class AndroidHarnessFragment extends Fragment implements
/**
* Set the maximum resolution for the surfaceview in either the
* width or height screen direction depending on the screen size.
* If the surfaceview is rectangular, the longest side (width or height)
* If the surfaceview is retangular, the longest side (width or height)
* will have the resolution set to a maximum of maxResolutionDimension.
* The other direction will be set to a value that maintains the aspect
* ratio of the surfaceview. </br>
* Any value less than 0 (default = -1) will result in the surfaceview having the
* Any value < 0 (default = -1) will result in the surfaceview having the
* same resolution as the view layout (ie. no max resolution).
*/
protected int maxResolutionDimension = -1;
@ -257,8 +257,9 @@ public class AndroidHarnessFragment extends Fragment implements
// Create application instance
try {
if (app == null) {
Class clazz = Class.forName(appClass);
app = (LegacyApplication)clazz.newInstance();
@SuppressWarnings("unchecked")
Class<? extends LegacyApplication> clazz = (Class<? extends LegacyApplication>) Class.forName(appClass);
app = clazz.newInstance();
}
app.setSettings(settings);
@ -275,17 +276,17 @@ public class AndroidHarnessFragment extends Fragment implements
}
/**
* Called by the system to create the View hierarchy associated with this
* Called by the system to create the View hierchy associated with this
* Fragment. For jME, this is a FrameLayout that contains the GLSurfaceView
* and an overlaying SplashScreen Image (if used). The View that is returned
* will be placed on the screen within the boundaries of the View borders defined
* will be placed on the screen within the boundries of the View borders defined
* by the Activity's layout parameters for this Fragment. For jME, we also
* update the application reference to the new view.
*
* @param inflater
* @param container
* @param savedInstanceState
* @return the new view
* @return
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -683,10 +684,10 @@ public class AndroidHarnessFragment extends Fragment implements
if (viewWidth > viewHeight && viewWidth > maxResolutionDimension) {
// landscape
fixedSizeWidth = maxResolutionDimension;
fixedSizeHeight = (int)(maxResolutionDimension * (viewHeight / (float)viewWidth));
fixedSizeHeight = (int)(maxResolutionDimension * ((float)viewHeight / (float)viewWidth));
} else if (viewHeight > viewWidth && viewHeight > maxResolutionDimension) {
// portrait
fixedSizeWidth = (int)(maxResolutionDimension * (viewWidth / (float)viewHeight));
fixedSizeWidth = (int)(maxResolutionDimension * ((float)viewWidth / (float)viewHeight));
fixedSizeHeight = maxResolutionDimension;
} else if (viewWidth == viewHeight && viewWidth > maxResolutionDimension) {
fixedSizeWidth = maxResolutionDimension;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2020 jMonkeyEngine
* Copyright (c) 2014 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -33,8 +33,8 @@
package com.jme3.app;
import android.os.Build;
import com.jme3.profile.*;
import com.jme3.profile.AppProfiler;
import com.jme3.profile.AppStep;
import static com.jme3.profile.AppStep.BeginFrame;
import static com.jme3.profile.AppStep.EndFrame;
import static com.jme3.profile.AppStep.ProcessAudio;
@ -47,6 +47,7 @@ import static com.jme3.profile.AppStep.RenderPreviewViewPorts;
import static com.jme3.profile.AppStep.SpatialUpdate;
import static com.jme3.profile.AppStep.StateManagerRender;
import static com.jme3.profile.AppStep.StateManagerUpdate;
import com.jme3.profile.VpStep;
import static com.jme3.profile.VpStep.BeginRender;
import static com.jme3.profile.VpStep.EndRender;
import static com.jme3.profile.VpStep.FlushQueue;
@ -63,7 +64,7 @@ import com.jme3.renderer.queue.RenderQueue;
*
* <p>This profiler uses the Android Trace class which is only supported
* on Android SDK rev 18 and higher (ver 4.3 and higher). If the
* device is running a version less than rev 18, the logging will
* device is running a version < rev 18, the logging will
* be skipped.</p>
*
* <p>In the MainActivity class, add the following:</p>
@ -82,7 +83,6 @@ import com.jme3.renderer.queue.RenderQueue;
public class DefaultAndroidProfiler implements AppProfiler {
private int androidApiLevel = Build.VERSION.SDK_INT;
@Override
public void appStep(AppStep appStep) {
if (androidApiLevel >= 18) {
switch(appStep) {
@ -136,12 +136,6 @@ public class DefaultAndroidProfiler implements AppProfiler {
}
}
@Override
public void appSubStep(String... additionalInfo) {
}
@Override
public void vpStep(VpStep vpStep, ViewPort vp, RenderQueue.Bucket bucket) {
if (androidApiLevel >= 18) {
switch (vpStep) {
@ -170,10 +164,4 @@ public class DefaultAndroidProfiler implements AppProfiler {
}
}
}
@Override
public void spStep(SpStep step, String... additionalInfo) {
}
}

@ -0,0 +1,20 @@
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.jme3.app;
public final class R {
public static final class attr {
}
public static final class layout {
public static final int main=0x7f020000;
}
public static final class string {
public static final int app_name=0x7f030000;
public static final int jme3_appclass=0x7f030001;
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2020 jMonkeyEngine
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -478,7 +478,7 @@ public class MjpegFileWriter {
baos.write(fcc);
baos.write(intBytes(swapInt(cb)));
for (int i = 0; i < ind.size(); i++) {
AVIIndex in = ind.get(i);
AVIIndex in = (AVIIndex) ind.get(i);
baos.write(in.toBytes());
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2020 jMonkeyEngine
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,7 +34,6 @@ package com.jme3.app.state;
import android.graphics.Bitmap;
import com.jme3.app.Application;
import com.jme3.post.SceneProcessor;
import com.jme3.profile.AppProfiler;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer;
@ -73,7 +72,6 @@ public class VideoRecorderAppState extends AbstractAppState {
private Application app;
private ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread th = new Thread(r);
th.setName("jME3 Video Processor");
@ -124,6 +122,7 @@ public class VideoRecorderAppState extends AbstractAppState {
* This constructor allows you to specify the output file of the video as well as the quality
* @param file the video file
* @param quality the quality of the jpegs in the video stream (0.0 smallest file - 1.0 largest file)
* @param framerate the frame rate of the resulting video, the application will be locked to this framerate
*/
public VideoRecorderAppState(File file, float quality) {
this.file = file;
@ -227,7 +226,6 @@ public class VideoRecorderAppState extends AbstractAppState {
private LinkedBlockingQueue<WorkItem> usedItems = new LinkedBlockingQueue<WorkItem>();
private MjpegFileWriter writer;
private boolean fastMode = true;
private AppProfiler prof;
public void addImage(Renderer renderer, FrameBuffer out) {
if (freeItems == null) {
@ -240,7 +238,6 @@ public class VideoRecorderAppState extends AbstractAppState {
renderer.readFrameBufferWithFormat(out, item.buffer, Image.Format.BGRA8);
executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
if (fastMode) {
item.data = item.buffer.array();
@ -262,7 +259,6 @@ public class VideoRecorderAppState extends AbstractAppState {
}
}
@Override
public void initialize(RenderManager rm, ViewPort viewPort) {
logger.log(Level.INFO, "initialize in VideoProcessor");
this.camera = viewPort.getCamera();
@ -278,16 +274,13 @@ public class VideoRecorderAppState extends AbstractAppState {
}
}
@Override
public void reshape(ViewPort vp, int w, int h) {
}
@Override
public boolean isInitialized() {
return this.isInitilized;
}
@Override
public void preFrame(float tpf) {
if (null == writer) {
try {
@ -298,17 +291,14 @@ public class VideoRecorderAppState extends AbstractAppState {
}
}
@Override
public void postQueue(RenderQueue rq) {
}
@Override
public void postFrame(FrameBuffer out) {
numFrames++;
addImage(renderManager.getRenderer(), out);
}
@Override
public void cleanup() {
logger.log(Level.INFO, "cleanup in VideoProcessor");
logger.log(Level.INFO, "VideoProcessor numFrames: {0}", numFrames);
@ -323,11 +313,6 @@ public class VideoRecorderAppState extends AbstractAppState {
}
writer = null;
}
@Override
public void setProfiler(AppProfiler profiler) {
this.prof = profiler;
}
}
public static final class IsoTimer extends com.jme3.system.Timer {
@ -341,27 +326,22 @@ public class VideoRecorderAppState extends AbstractAppState {
this.ticks = 0;
}
@Override
public long getTime() {
return (long) (this.ticks * (1.0f / this.framerate) * 1000f);
}
@Override
public long getResolution() {
return 1000L;
}
@Override
public float getFrameRate() {
return this.framerate;
}
@Override
public float getTimePerFrame() {
return 1.0f / this.framerate;
return (float) (1.0f / this.framerate);
}
@Override
public void update() {
long time = System.currentTimeMillis();
long difference = time - lastTime;
@ -378,7 +358,6 @@ public class VideoRecorderAppState extends AbstractAppState {
this.ticks++;
}
@Override
public void reset() {
this.ticks = 0;
}

@ -0,0 +1,136 @@
package com.jme3.asset;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import com.jme3.math.ColorRGBA;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.texture.image.ImageRaster;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* <code>AndroidImageInfo</code> is set in a jME3 image via the {@link Image#setEfficentData(java.lang.Object) }
* method to retrieve a {@link Bitmap} when it is needed by the renderer.
* User code may extend <code>AndroidImageInfo</code> and provide their own implementation of the
* {@link AndroidImageInfo#loadBitmap()} method to acquire a bitmap by their own means.
*
* @author Kirill Vainer
*/
@Deprecated
public class AndroidImageInfo extends ImageRaster {
private static final Logger logger = Logger.getLogger(AndroidImageInfo.class.getName());
protected AssetInfo assetInfo;
protected Bitmap bitmap;
protected Format format;
public AndroidImageInfo(AssetInfo assetInfo) {
this.assetInfo = assetInfo;
}
public Bitmap getBitmap(){
if (bitmap == null || bitmap.isRecycled()){
try {
loadBitmap();
} catch (IOException ex) {
// If called first inside AssetManager, the error will propagate
// correctly. Assuming that if the first calls succeeds
// then subsequent calls will as well.
throw new AssetLoadException("Failed to load image " + assetInfo.getKey(), ex);
}
}
return bitmap;
}
public void notifyBitmapUploaded() {
// Default function is to recycle the bitmap.
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
logger.log(Level.FINE, "Bitmap was deleted. ");
}
}
public Format getFormat(){
return format;
}
@Override
public int getWidth() {
return getBitmap().getWidth();
}
@Override
public int getHeight() {
return getBitmap().getHeight();
}
@Override
public void setPixel(int x, int y, ColorRGBA color) {
getBitmap().setPixel(x, y, color.asIntARGB());
}
@Override
public ColorRGBA getPixel(int x, int y, ColorRGBA store) {
if (store == null) {
store = new ColorRGBA();
}
store.fromIntARGB(getBitmap().getPixel(x, y));
return store;
}
/**
* Loads the bitmap directly from the asset info, possibly updating
* or creating the image object.
*/
protected void loadBitmap() throws IOException{
InputStream in = null;
try {
in = assetInfo.openStream();
bitmap = BitmapFactory.decodeStream(in);
if (bitmap == null) {
throw new IOException("Failed to load image: " + assetInfo.getKey().getName());
}
} finally {
if (in != null) {
in.close();
}
}
switch (bitmap.getConfig()) {
case ALPHA_8:
format = Image.Format.Alpha8;
break;
case ARGB_8888:
format = Image.Format.RGBA8;
break;
case RGB_565:
format = Image.Format.RGB565;
break;
default:
// This should still work as long
// as renderer doesn't check format
// but just loads bitmap directly.
format = null;
}
TextureKey texKey = (TextureKey) assetInfo.getKey();
if (texKey.isFlipY()) {
// Flip the image, then delete the old one.
Matrix flipMat = new Matrix();
flipMat.preScale(1.0f, -1.0f);
Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
bitmap.recycle();
bitmap = newBitmap;
if (bitmap == null) {
throw new IOException("Failed to flip image: " + texKey);
}
}
}
}

@ -1,101 +1,37 @@
package com.jme3.asset.plugins;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import com.jme3.asset.*;
import com.jme3.system.android.JmeAndroidSystem;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AndroidLocator implements AssetLocator {
private static final Logger logger = Logger.getLogger(AndroidLocator.class.getName());
private android.content.res.AssetManager androidManager;
private String rootPath = "";
public AndroidLocator() {
}
@Override
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
@Override
public AssetInfo locate(AssetManager manager, AssetKey key) {
String assetPath = rootPath + key.getName();
// Fix path issues
if (assetPath.startsWith("/")) {
// Remove leading /
assetPath = assetPath.substring(1);
}
assetPath = assetPath.replace("//", "/");
// Not making this a property and storing for future use in case the view stored in JmeAndroidSystem
// is replaced due to device orientation change. Not sure it is necessary to do this yet, but am for now.
android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
String androidPackageName = JmeAndroidSystem.getView().getContext().getPackageName();
// logger.log(Level.INFO, "Asset Key: {0}", key);
// logger.log(Level.INFO, "Asset Name: {0}", key.getName());
// logger.log(Level.INFO, "Asset Path: {0}", assetPath);
// logger.log(Level.INFO, "Asset Extension: {0}", key.getExtension());
// logger.log(Level.INFO, "Asset Key Class: {0}", key.getClass().getName());
// logger.log(Level.INFO, "androidPackageName: {0}", androidPackageName);
// logger.log(Level.INFO, "Resource Name: {0}", getResourceName(assetPath));
// check the assets directory for the asset using assetPath
try {
InputStream in = androidResources.getAssets().open(assetPath);
if (in != null){
return new AndroidAssetInfo(manager, key, assetPath, in, 0);
}
} catch (IOException ex) {
// allow to fall through to the other checks in the resources directories.
// logger.log(Level.INFO, "Resource[{0}] not found in assets directory.", assetPath);
}
// if not found in the assets directory, check the drawable and mipmap directories (only valid for images)
String resourceName = getResourceName(assetPath);
int resourceId = androidResources.getIdentifier(resourceName, "drawable", androidPackageName);
// logger.log(Level.INFO, "drawable resourceId: {0}", resourceId);
if (resourceId == 0) { // drawable resource not found, check mipmap resource type
resourceId = androidResources.getIdentifier(resourceName, "mipmap", androidPackageName);
// logger.log(Level.INFO, "mipmap resourceId: {0}", resourceId);
}
if (resourceId == 0) { // not found in resource directories, return null;
return null;
}
// try to open a stream with the resourceId returned by Android
try {
InputStream in = androidResources.openRawResource(resourceId);
if (in != null){
// logger.log(Level.INFO, "Creating new AndroidResourceInfo.");
return new AndroidAssetInfo(manager, key, assetPath, in, resourceId);
}
} catch (Resources.NotFoundException ex) {
// input stream failed to open, return null
return null;
}
return null;
}
public class AndroidAssetInfo extends AssetInfo {
private InputStream in;
private final String assetPath;
private int resourceId;
AndroidAssetInfo(AssetManager assetManager, AssetKey<?> key, String assetPath, InputStream in, int resourceId) {
public AndroidAssetInfo(com.jme3.asset.AssetManager assetManager, AssetKey<?> key, String assetPath, InputStream in) {
super(assetManager, key);
this.assetPath = assetPath;
this.in = in;
this.resourceId = resourceId;
}
public AssetFileDescriptor openFileDescriptor() {
try {
return androidManager.openFd(assetPath);
} catch (IOException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
}
@Override
@ -107,47 +43,55 @@ public class AndroidLocator implements AssetLocator {
return in2;
}else{
// Create a new stream for subsequent invocations.
android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
if (resourceId == 0) {
try {
return androidResources.getAssets().open(assetPath);
} catch (IOException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
} else {
try {
return androidResources.openRawResource(resourceId);
} catch (Resources.NotFoundException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
}
}
}
public AssetFileDescriptor openFileDescriptor() {
android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
if (resourceId == 0) {
try {
return androidResources.getAssets().openFd(assetPath);
return androidManager.open(assetPath);
} catch (IOException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
} else {
try {
return androidResources.openRawResourceFd(resourceId);
} catch (Resources.NotFoundException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
}
}
}
private String getResourceName(String name) {
int idx = name.lastIndexOf('.');
if (idx <= 0 || idx == name.length() - 1) {
return name;
} else {
return name.substring(0, idx).toLowerCase();
private AndroidAssetInfo create(AssetManager assetManager, AssetKey key, String assetPath) throws IOException {
try {
InputStream in = androidManager.open(assetPath);
if (in == null){
return null;
}else{
return new AndroidAssetInfo(assetManager, key, assetPath, in);
}
} catch (IOException ex) {
// XXX: Prefer to show warning here?
// Should only surpress exceptions for "file missing" type errors.
return null;
}
}
public AndroidLocator() {
androidManager = JmeAndroidSystem.getView().getContext().getAssets();
}
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
@SuppressWarnings("rawtypes")
@Override
public AssetInfo locate(com.jme3.asset.AssetManager manager, AssetKey key) {
String assetPath = rootPath + key.getName();
// Fix path issues
if (assetPath.startsWith("/")) {
// Remove leading /
assetPath = assetPath.substring(1);
}
assetPath = assetPath.replace("//", "/");
try {
return create(manager, key, assetPath);
} catch (IOException ex) {
// This is different handling than URL locator
// since classpath locating would return null at the getResource()
// call, otherwise there's a more critical error...
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
}
}

@ -10,64 +10,44 @@ public final class AndroidAL implements AL {
public AndroidAL() {
}
@Override
public native String alGetString(int parameter);
@Override
public native int alGenSources();
@Override
public native int alGetError();
@Override
public native void alDeleteSources(int numSources, IntBuffer sources);
@Override
public native void alGenBuffers(int numBuffers, IntBuffer buffers);
@Override
public native void alDeleteBuffers(int numBuffers, IntBuffer buffers);
@Override
public native void alSourceStop(int source);
@Override
public native void alSourcei(int source, int param, int value);
@Override
public native void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency);
@Override
public native void alSourcePlay(int source);
@Override
public native void alSourcePause(int source);
@Override
public native void alSourcef(int source, int param, float value);
@Override
public native void alSource3f(int source, int param, float value1, float value2, float value3);
@Override
public native int alGetSourcei(int source, int param);
@Override
public native void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers);
@Override
public native void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers);
@Override
public native void alListener(int param, FloatBuffer data);
@Override
public native void alListenerf(int param, float value);
@Override
public native void alListener3f(int param, float value1, float value2, float value3);
@Override
public native void alSource3i(int source, int param, int value1, int value2, int value3);
}

@ -12,27 +12,19 @@ public final class AndroidALC implements ALC {
public AndroidALC() {
}
@Override
public native void createALC();
@Override
public native void destroyALC();
@Override
public native boolean isCreated();
@Override
public native String alcGetString(int parameter);
@Override
public native boolean alcIsExtensionPresent(String extension);
@Override
public native void alcGetInteger(int param, IntBuffer buffer, int size);
@Override
public native void alcDevicePauseSOFT();
@Override
public native void alcDeviceResumeSOFT();
}

@ -8,36 +8,25 @@ public class AndroidEFX implements EFX {
public AndroidEFX() {
}
@Override
public native void alGenAuxiliaryEffectSlots(int numSlots, IntBuffer buffers);
@Override
public native void alGenEffects(int numEffects, IntBuffer buffers);
@Override
public native void alEffecti(int effect, int param, int value);
@Override
public native void alAuxiliaryEffectSloti(int effectSlot, int param, int value);
@Override
public native void alDeleteEffects(int numEffects, IntBuffer buffers);
@Override
public native void alDeleteAuxiliaryEffectSlots(int numEffectSlots, IntBuffer buffers);
@Override
public native void alGenFilters(int numFilters, IntBuffer buffers);
@Override
public native void alFilteri(int filter, int param, int value);
@Override
public native void alFilterf(int filter, int param, float value);
@Override
public native void alDeleteFilters(int numFilters, IntBuffer buffers);
@Override
public native void alEffectf(int effect, int param, float value);
}

@ -0,0 +1,533 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.audio.android;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import com.jme3.asset.AssetKey;
import com.jme3.audio.*;
import com.jme3.audio.AudioSource.Status;
import com.jme3.audio.openal.ALAudioRenderer;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class is the android implementation for {@link AudioRenderer}
*
* @author larynx
* @author plan_rich
*
* @deprecated No longer supported due to too many limitations.
* Please use the generic {@link ALAudioRenderer} instead.
*/
@Deprecated
public class AndroidMediaPlayerAudioRenderer implements AudioRenderer,
SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
private static final Logger logger = Logger.getLogger(AndroidMediaPlayerAudioRenderer.class.getName());
private final static int MAX_NUM_CHANNELS = 16;
private final HashMap<AudioSource, MediaPlayer> musicPlaying = new HashMap<AudioSource, MediaPlayer>();
private SoundPool soundPool = null;
private final Vector3f listenerPosition = new Vector3f();
// For temp use
private final Vector3f distanceVector = new Vector3f();
private final AssetManager assetManager;
private HashMap<Integer, AudioSource> soundpoolStillLoading = new HashMap<Integer, AudioSource>();
private Listener listener;
private boolean audioDisabled = false;
private final AudioManager manager;
public AndroidMediaPlayerAudioRenderer(Activity context) {
manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
assetManager = context.getAssets();
}
@Override
public void initialize() {
soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC,
0);
soundPool.setOnLoadCompleteListener(this);
}
@Override
public void updateSourceParam(AudioSource src, AudioParam param) {
if (audioDisabled) {
return;
}
if (src.getChannel() < 0) {
return;
}
switch (param) {
case Position:
if (!src.isPositional()) {
return;
}
Vector3f pos = src.getPosition();
break;
case Velocity:
if (!src.isPositional()) {
return;
}
Vector3f vel = src.getVelocity();
break;
case MaxDistance:
if (!src.isPositional()) {
return;
}
break;
case RefDistance:
if (!src.isPositional()) {
return;
}
break;
case ReverbFilter:
if (!src.isPositional() || !src.isReverbEnabled()) {
return;
}
break;
case ReverbEnabled:
if (!src.isPositional()) {
return;
}
if (src.isReverbEnabled()) {
updateSourceParam(src, AudioParam.ReverbFilter);
}
break;
case IsPositional:
break;
case Direction:
if (!src.isDirectional()) {
return;
}
Vector3f dir = src.getDirection();
break;
case InnerAngle:
if (!src.isDirectional()) {
return;
}
break;
case OuterAngle:
if (!src.isDirectional()) {
return;
}
break;
case IsDirectional:
if (src.isDirectional()) {
updateSourceParam(src, AudioParam.Direction);
updateSourceParam(src, AudioParam.InnerAngle);
updateSourceParam(src, AudioParam.OuterAngle);
} else {
}
break;
case DryFilter:
if (src.getDryFilter() != null) {
Filter f = src.getDryFilter();
if (f.isUpdateNeeded()) {
// updateFilter(f);
}
}
break;
case Looping:
if (src.isLooping()) {
}
break;
case Volume:
MediaPlayer mp = musicPlaying.get(src);
if (mp != null) {
mp.setVolume(src.getVolume(), src.getVolume());
} else {
soundPool.setVolume(src.getChannel(), src.getVolume(),
src.getVolume());
}
break;
case Pitch:
break;
}
}
@Override
public void updateListenerParam(Listener listener, ListenerParam param) {
if (audioDisabled) {
return;
}
switch (param) {
case Position:
listenerPosition.set(listener.getLocation());
break;
case Rotation:
Vector3f dir = listener.getDirection();
Vector3f up = listener.getUp();
break;
case Velocity:
Vector3f vel = listener.getVelocity();
break;
case Volume:
// alListenerf(AL_GAIN, listener.getVolume());
break;
}
}
@Override
public void update(float tpf) {
float distance;
float volume;
// Loop over all mediaplayers
for (AudioSource src : musicPlaying.keySet()) {
MediaPlayer mp = musicPlaying.get(src);
// Calc the distance to the listener
distanceVector.set(listenerPosition);
distanceVector.subtractLocal(src.getPosition());
distance = FastMath.abs(distanceVector.length());
if (distance < src.getRefDistance()) {
distance = src.getRefDistance();
}
if (distance > src.getMaxDistance()) {
distance = src.getMaxDistance();
}
volume = src.getRefDistance() / distance;
AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON) {
// Left / Right channel get the same volume by now, only
// positional
mp.setVolume(volume, volume);
audioData.setCurrentVolume(volume);
}
}
}
public void setListener(Listener listener) {
if (audioDisabled) {
return;
}
if (this.listener != null) {
// previous listener no longer associated with current
// renderer
this.listener.setRenderer(null);
}
this.listener = listener;
this.listener.setRenderer(this);
}
@Override
public void cleanup() {
// Cleanup sound pool
if (soundPool != null) {
soundPool.release();
soundPool = null;
}
// Cleanup media player
for (AudioSource src : musicPlaying.keySet()) {
MediaPlayer mp = musicPlaying.get(src);
{
mp.stop();
mp.release();
src.setStatus(Status.Stopped);
}
}
musicPlaying.clear();
}
@Override
public void onCompletion(MediaPlayer mp) {
if (mp.isPlaying()) {
mp.seekTo(0);
mp.stop();
}
// XXX: This has bad performance -> maybe change overall structure of
// mediaplayer in this audiorenderer?
for (AudioSource src : musicPlaying.keySet()) {
if (musicPlaying.get(src) == mp) {
src.setStatus(Status.Stopped);
break;
}
}
}
/**
* Plays using the {@link SoundPool} of Android. Due to hard limitation of
* the SoundPool: After playing more instances of the sound you only have
* the channel of the last played instance.
*
* It is not possible to get information about the state of the soundpool of
* a specific streamid, so removing is not possilbe -&gt; noone knows when
* sound finished.
*/
public void playSourceInstance(AudioSource src) {
if (audioDisabled) {
return;
}
AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
if (!(audioData.getAssetKey() instanceof AudioKey)) {
throw new IllegalArgumentException("Asset is not a AudioKey");
}
AudioKey assetKey = (AudioKey) audioData.getAssetKey();
try {
if (audioData.getId() < 0) { // found something to load
int soundId = soundPool.load(
assetManager.openFd(assetKey.getName()), 1);
audioData.setId(soundId);
}
int channel = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
if (channel == 0) {
soundpoolStillLoading.put(audioData.getId(), src);
} else {
if (src.getStatus() != Status.Stopped) {
soundPool.stop(channel);
src.setStatus(Status.Stopped);
}
src.setChannel(channel); // receive a channel at the last
setSourceParams(src);
// playing at least
}
} catch (IOException e) {
logger.log(Level.SEVERE,
"Failed to load sound " + assetKey.getName(), e);
audioData.setId(-1);
}
}
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
AudioSource src = soundpoolStillLoading.remove(sampleId);
if (src == null) {
logger.warning("Something went terribly wrong! onLoadComplete"
+ " had sampleId which was not in the HashMap of loading items");
return;
}
AudioData audioData = src.getAudioData();
// load was successfull
if (status == 0) {
int channelIndex;
channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
src.setChannel(channelIndex);
setSourceParams(src);
}
}
public void playSource(AudioSource src) {
if (audioDisabled) {
return;
}
AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
MediaPlayer mp = musicPlaying.get(src);
if (mp == null) {
mp = new MediaPlayer();
mp.setOnCompletionListener(this);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
try {
if (src.getStatus() == Status.Stopped) {
mp.reset();
AssetKey<?> key = audioData.getAssetKey();
AssetFileDescriptor afd = assetManager.openFd(key.getName()); // assetKey.getName()
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
afd.getLength());
mp.prepare();
setSourceParams(src, mp);
src.setChannel(0);
src.setStatus(Status.Playing);
musicPlaying.put(src, mp);
mp.start();
} else {
mp.start();
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private void setSourceParams(AudioSource src, MediaPlayer mp) {
mp.setLooping(src.isLooping());
mp.setVolume(src.getVolume(), src.getVolume());
//src.getDryFilter();
}
private void setSourceParams(AudioSource src) {
soundPool.setLoop(src.getChannel(), src.isLooping() ? -1 : 0);
soundPool.setVolume(src.getChannel(), src.getVolume(), src.getVolume());
}
/**
* Pause the current playing sounds. Both from the {@link SoundPool} and the
* active {@link MediaPlayer}s
*/
public void pauseAll() {
if (soundPool != null) {
soundPool.autoPause();
for (MediaPlayer mp : musicPlaying.values()) {
if(mp.isPlaying()){
mp.pause();
}
}
}
}
/**
* Resume all paused sounds.
*/
public void resumeAll() {
if (soundPool != null) {
soundPool.autoResume();
for (MediaPlayer mp : musicPlaying.values()) {
mp.start(); //no resume -> api says call start to resume
}
}
}
public void pauseSource(AudioSource src) {
if (audioDisabled) {
return;
}
MediaPlayer mp = musicPlaying.get(src);
if (mp != null) {
mp.pause();
src.setStatus(Status.Paused);
} else {
int channel = src.getChannel();
if (channel != -1) {
soundPool.pause(channel); // is not very likley to make
} // something useful :)
}
}
public void stopSource(AudioSource src) {
if (audioDisabled) {
return;
}
// can be stream or buffer -> so try to get mediaplayer
// if there is non try to stop soundpool
MediaPlayer mp = musicPlaying.get(src);
if (mp != null) {
mp.stop();
mp.reset();
src.setStatus(Status.Stopped);
} else {
int channel = src.getChannel();
if (channel != -1) {
soundPool.pause(channel); // is not very likley to make
// something useful :)
}
}
}
@Override
public void deleteAudioData(AudioData ad) {
for (AudioSource src : musicPlaying.keySet()) {
if (src.getAudioData() == ad) {
MediaPlayer mp = musicPlaying.remove(src);
mp.stop();
mp.release();
src.setStatus(Status.Stopped);
src.setChannel(-1);
ad.setId(-1);
break;
}
}
if (ad.getId() > 0) {
soundPool.unload(ad.getId());
ad.setId(-1);
}
}
@Override
public void setEnvironment(Environment env) {
// not yet supported
}
@Override
public void deleteFilter(Filter filter) {
}
@Override
public float getSourcePlaybackTime(AudioSource src) {
throw new UnsupportedOperationException("Not supported yet.");
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save