瀏覽代碼

Merge branch 'master' into PBRisComing

* master: (249 commits)
  Gradle: Try to use Bullet Native for the SDK by moving jbullet to optlibs and bullet-native to corelibs
  Gradle Build: Add convenience task `run` for Windows Systems which cannot invoke ant from the command line. (And each project should have a run task, anyway)
  Fix source version
  iOS: Set openGL Context in AppDelegate to prevent Crashes.
  Travis: Try to reduce disk space usage
  Build: Remove HW Skinning Patch as it has been merged into the engine
  Build: Try to fix regular commits erroring due to a faulty engine-version-name
  Updated Bloom filter wizard's name
  Fixes #91 iOS: Automatically download the prebuilt Avian Version to make iOS Deployment working again.
  Fixes #75 - DarkMonkey: We can now change the Diff-Colors and the User can adjust them manually using the Fonts & Colors Dialog. Also see 1e92c2f
  Fixes #88 - TextureBrowser: Release the old Texture when setting the path to a new one.
  Update XBuf Dependency to 0.9.1 (ProtoBuf 3)
  Fix Regression with fixPlatformIndependentBuild Gradle Task.
  iOS: Update Generated Files
  iOS: Update native Image-Loading Code to prevent Crashes
  iOS: Fix crash in GLES Native Code due to changed Method Signatures
  iOS Harness: Use newer GLRenderer over old Implementation.
  Fix Constructor of ProjectExtensionManager
  iOS: Build x86_64 instead of i386, update jar-excludes (new naming scheme of jme), ignore "ios-base" Library since it doesn't seem to be used anymore.
  iOS: Also package the x86_64 avian version
  ...

Conflicts: (solved)
	branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
	branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
	build.gradle
	jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java
	jme3-scenecomposer/src/com/jme3/gde/scenecomposer/gizmo/light/LightGizmoFactory.java
	nbproject/project.properties
MeFisto94 9 年之前
父節點
當前提交
68f1954d09
共有 100 個文件被更改,包括 3985 次插入243 次删除
  1. 13 0
      .gitignore
  2. 94 0
      .travis.yml
  3. 5 5
      BasicGameTemplate/nbproject/project.properties
  4. 2 2
      BasicGameTemplate/src/mygame/Main.java
  5. 3 1
      branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
  6. 二進制
      branding/core/core.jar/org/netbeans/core/startup/about.png
  7. 1 1
      branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties
  8. 127 31
      build.gradle
  9. 14 0
      build_engine.sh
  10. 99 0
      docs/building.md
  11. 38 0
      docs/development.md
  12. 71 0
      docs/maintaining.md
  13. 79 0
      docs/reporting_issues.md
  14. 3 3
      gradle.properties
  15. 37 0
      gradle/libs/digest.gradle
  16. 二進制
      gradle/wrapper/gradle-wrapper.jar
  17. 6 0
      gradle/wrapper/gradle-wrapper.properties
  18. 160 0
      gradlew
  19. 90 0
      gradlew.bat
  20. 18 0
      harness-override/README.md
  21. 二進制
      harness-override/app.exe
  22. 二進制
      harness-override/app64.exe
  23. 6 0
      harness-override/override.properties
  24. 二進制
      harness-override/pre7_app.exe
  25. 17 0
      jdks/README
  26. 1 1
      jdks/build-package.sh
  27. 271 0
      jdks/download-jdks.sh
  28. 4 4
      jme3-android/nbproject/genfiles.properties
  29. 36 4
      jme3-android/nbproject/project.xml
  30. 4 4
      jme3-angelfont/nbproject/genfiles.properties
  31. 17 1
      jme3-angelfont/nbproject/project.xml
  32. 2 2
      jme3-assetpack-support/nbproject/genfiles.properties
  33. 44 3
      jme3-assetpack-support/nbproject/project.xml
  34. 1 2
      jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.java
  35. 1 2
      jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/CleanupProjectAction.java
  36. 1 2
      jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ConvertOgreBinaryMeshesAction.java
  37. 1 2
      jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ImportWorldForgeAction.java
  38. 1 2
      jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/PublishAssetPackAction.java
  39. 4 4
      jme3-blender/nbproject/genfiles.properties
  40. 34 2
      jme3-blender/nbproject/project.xml
  41. 32 2
      jme3-blender/src/com/jme3/gde/blender/BlenderAssetManagerConfigurator.java
  42. 84 18
      jme3-blender/src/com/jme3/gde/blender/BlenderTool.java
  43. 3 3
      jme3-blender/src/com/jme3/gde/blender/Bundle.properties
  44. 85 0
      jme3-blender/src/com/jme3/gde/blender/ConvertToBlendAction.java
  45. 117 0
      jme3-blender/src/com/jme3/gde/blender/ConvertToJ3OAction.java
  46. 99 0
      jme3-blender/src/com/jme3/gde/blender/XbufDataObject.java
  47. 127 31
      jme3-blender/src/com/jme3/gde/blender/filetypes/AbstractBlenderImportDataObject.java
  48. 二進制
      jme3-blender/src/com/jme3/gde/blender/xbuf.png
  49. 4 4
      jme3-cinematics/nbproject/genfiles.properties
  50. 25 1
      jme3-cinematics/nbproject/project.xml
  51. 4 4
      jme3-code-check/nbproject/genfiles.properties
  52. 50 2
      jme3-code-check/nbproject/project.xml
  53. 16 0
      jme3-code-check/src/com/jme3/gde/codecheck/hints/Bundle.properties
  54. 5 4
      jme3-code-check/src/com/jme3/gde/codecheck/hints/InternalMethodHint.java
  55. 5 4
      jme3-code-check/src/com/jme3/gde/codecheck/hints/ReadOnlyPrimitiveHint.java
  56. 5 4
      jme3-code-check/src/com/jme3/gde/codecheck/hints/TempVarsHint.java
  57. 5 4
      jme3-code-check/src/com/jme3/gde/codecheck/hints/UpdateHint.java
  58. 4 4
      jme3-codepalette/nbproject/genfiles.properties
  59. 8 0
      jme3-codepalette/nbproject/project.xml
  60. 4 4
      jme3-core-updatecenters/nbproject/genfiles.properties
  61. 8 0
      jme3-core-updatecenters/nbproject/project.xml
  62. 二進制
      jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/trustedcerts.jks
  63. 82 7
      jme3-core/nbproject/project.xml
  64. 67 0
      jme3-core/src/com/jme3/gde/core/CopyTemplateHandler.java
  65. 32 3
      jme3-core/src/com/jme3/gde/core/Installer.java
  66. 1 2
      jme3-core/src/com/jme3/gde/core/appstates/NewSceneSaveNode.java
  67. 1 3
      jme3-core/src/com/jme3/gde/core/assets/AssetDataObject.java
  68. 53 16
      jme3-core/src/com/jme3/gde/core/assets/AssetsLookupProvider.java
  69. 1 2
      jme3-core/src/com/jme3/gde/core/assets/ExternalChangeScanner.java
  70. 4 3
      jme3-core/src/com/jme3/gde/core/assets/SpatialAssetDataObject.java
  71. 1 2
      jme3-core/src/com/jme3/gde/core/assets/actions/ConvertModel.java
  72. 1 4
      jme3-core/src/com/jme3/gde/core/assets/actions/OpenModel.java
  73. 2 2
      jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.java
  74. 1 0
      jme3-core/src/com/jme3/gde/core/filters/Bundle.properties
  75. 26 11
      jme3-core/src/com/jme3/gde/core/filters/FilterPostProcessorNode.java
  76. 0 2
      jme3-core/src/com/jme3/gde/core/filters/OpenFilterAction.java
  77. 1 1
      jme3-core/src/com/jme3/gde/core/filters/impl/NewBloomFilterAction.java
  78. 2 0
      jme3-core/src/com/jme3/gde/core/icons/IconList.java
  79. 1 0
      jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionManager.java
  80. 6 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/Bundle.properties
  81. 87 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel1.form
  82. 93 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel1.java
  83. 61 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel2.form
  84. 75 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel2.java
  85. 215 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectWizardAction.java
  86. 85 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectWizardPanel1.java
  87. 259 0
      jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectWizardPanel2.java
  88. 1 0
      jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.java
  89. 13 2
      jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java
  90. 2 3
      jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java
  91. 75 2
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java
  92. 2 2
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAnimControl.java
  93. 5 3
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAnimation.java
  94. 52 4
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeControl.java
  95. 0 1
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGenericControl.java
  96. 197 0
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMotionEvent.java
  97. 332 0
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMotionPath.java
  98. 134 0
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMotionPathChildren.java
  99. 16 0
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeNode.java
  100. 4 1
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSkeletonControl.java

+ 13 - 0
.gitignore

@@ -5,6 +5,7 @@ io_export_ogreDotScene.py
 jme3-project-libraries/release/libs
 jme3-project-testdata/release/libs
 jme3-tests-template/src/com/jme3/gde/templates/tests
+jme3-ios/downloads
 JME3TestsTemplate/src/jme3test
 JME3TestsTemplateAndroid/src/jme3test
 platform-private.properties
@@ -16,3 +17,15 @@ JME3TestsTemplateAndroid/src/META-INF
 jme3-project-baselibs/src/com/jme3/gde/project/baselibs
 jme3-core-baselibs/nbproject/project.xml
 jme3-core-libraries/nbproject/project.xml
+build/*
+*/build/*
+*.class
+.gradle
+netbeans/*
+*/nbproject/private/*
+ant-jme/dist
+jdks/local/*
+jdks/*.bin
+jdks/*.exe
+jdks/*.zip
+dist/

+ 94 - 0
.travis.yml

@@ -0,0 +1,94 @@
+language: java
+sudo: false
+jdk: oraclejdk8
+
+before_cache:
+ - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
+cache:
+  directories:
+   - $HOME/.gradle/caches/
+   - $HOME/.gradle/wrapper/
+   - netbeans
+   - jdks/local/8u77-b03/compiled
+
+addons:
+  ssh_known_hosts: updates.jmonkeyengine.org
+  apt:
+    packages:
+    - p7zip-full
+
+# branches:
+#   only:
+#   - master
+
+notifications:
+  slack:
+    on_success: change
+    on_failure: always
+    rooms:
+      secure: cOYkCWyBNtM4QiqNbGvhCE2lFxHSnmLfRl1wLJzeDBYEDbg1nOXayRwyH1dQzWCvhDhqv2qWHHASgddE14JwnVB7p56DcaQWAJ5yn/OyY9GzaHuz59Xm6LbFbz5JfabHY7LczuBlRtISlyfz4eHD5BOvfCzx7D3GI44kQX99BCFr1mqDjQEUyTPwhLolFPL5+zx7J669ud2Ba0TywtaWsXeOUvORAXAdlQv1RRAmQvUK9DIYyq0Z3fzr/uXEBaPAz50JFXkMs00Z8Dutdiu9jd/SsRnEv0O+ns75outu6WK2UwS1xHhcdW7bkMuTmRpGoec7XbbjSaz6oYsHSp8kyuPhLEzS2ba2QIxDmOkF/erejeAMdDlsIKwRMpizRCh/8gMZR2nNEzdHQ0gbgEk83PFYgQw+amtlOk61l6THopwLtVpDiiE1Elz5ev7KqSr//qWQgoHBFabQOgE5KjfxmLDmuUNWaZyuJi6JTwsxB04NGAa3zpQ6RKQ7dgGBZF7QIQ+f648oxVlLIK+T3VAdK47s94XKTRJ0CqRoA6nI2MCaLbU9zvS8uAWoLOIKw6ec2qexPaVCE+TO0780+x6tBFSYexwH8fwmEl1nPqBldipYCLIRZV7XbJh3bhfPksXuz2B6poJ/wL5gLtWNAXnBoWyI7Vu/PHbFsn+VhLUkYSU=
+
+install:
+  - chmod u+x build_engine.sh
+  - ./build_engine.sh
+  # Remove Engine Source and built class files since travis is low on disk space
+  - rm -rf engine/
+  - ./gradlew buildSdk
+  - cd jdks
+  - ./download-jdks.sh
+  - cd ../
+  #- '[ -z "$TRAVIS_TAG" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && ant -Dstorepass="$NBM_SIGN_PASS" hudson-nightly | awk "{printf(\".\"); fflush(stdout)}" || :'
+  #- '[ -z "$TRAVIS_TAG" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && scp -rp -i nbproject/private/www-updater.key build/updates/* [email protected]:/var/www/updates/nightly/3.1/plugins || :'
+  
+#script:
+#  - ./gradlew check
+#  - ./gradlew createZipDistribution
+
+before_deploy:
+  # In case of STABLE (see hudson-stable target)
+  # the above gradlew already sets the correct ant properties to build
+  # Include suite.nbms again, when we upload nbms again.
+  - ant -Dstorepass="$NBM_SIGN_PASS" -Dpack200.enabled=true set-spec-version build-installers unset-spec-version | awk '{printf("."); fflush(stdout)}'
+  
+  # Has to be done before deploy (due to the rm command)
+  #- scp -rp -i nbproject/private/www-updater.key build/updates/* [email protected]:/var/www/updates/stable/3.1/plugins
+  - ./gradlew fixPlatformIndependent
+  - rm -rf build/
+
+deploy:
+  provider: releases
+  api_key:
+    secure: IoGNk8dOmBIB/lXqgd7we7UjyFULww6y43F/Dwx2KZZ6NqC4tvDfBpqEyYhhLC0Ltgpm6vO/+0EepnqmBO5CkDYBECcwpIQX+ndgIOZQLMonXQ3glcjM5yoNtoUbFEn7xvI2ntAKbUkKmWnjNVquHF7t7jT8QfUPymUdV+f1eHapQFtcx2VuDoGF4/1fZuygS5pNPgkw7bduQo8foxlDdzSicNJ8smV0QBUZE/dVlbK1ycitZZrGkkRW/uKvsN/FX+lkl6ANb4y8AE2kcn0EarY6FH5NrQgGp5QNbGdQw1/4voFsR8Bji2UHUYuhjCuV14cgenfSQXrW4rVV/YMGaxxR/BbFB5XfZPCBfIsqfVAGH+Rkvy8/ZTBot+v9L1Pp99RZSCCtJoGPYBQagjzEOOAJplnqNHJ1D8bQo+1XElcuki/qxlO3XvXGQwTs2HMyqrnmlfdRjD5JClxx06Wke4y+KjLWtiQfjihCaQK68ixkCF4U8B2lg8nsuFNmUxUMfPCkKir4XfjuZ27y9ZNBnZQNTKOjW1cjU2GhvGyDWfK5xgfSMP/uKpAopSkWYOMaQVeUlFvMI2NtKdkb7lko6bRizEj/EWlUjhTP7TzvVGE76PJh+XeUkcNQmoFBRYOY2L+TYVs9LlKl+DQbcAHOeMYlxfq/zN7OIAh7T5AsgZk=
+    # Use travis setup releases --force (gem install travis) and then anyone with push access can create the token
+  # file_glob: true
+  file:
+   - dist/jmonkeyplatform-linux-x64.sh
+   - dist/jmonkeyplatform-linux-x86.sh
+   - dist/jmonkeyplatform-windows-x64.exe
+   - dist/jmonkeyplatform-windows-x86.exe
+   - dist/jmonkeyplatform.zip
+   - dist/jmonkeyplatform-macosx.tgz
+  skip_cleanup: true
+  on:
+    repo: jMonkeyEngine/sdk
+    tags: true
+
+before_install:
+  - git fetch --unshallow -q
+  - "[ $TRAVIS_PULL_REQUEST == 'false' ] && openssl aes-256-cbc -K $encrypted_ab3650240afa_key -iv $encrypted_ab3650240afa_iv -in nbproject/private/www-updater.key.enc -out nbproject/private/www-updater.key -d || :"
+  - "[ $TRAVIS_PULL_REQUEST == 'false' ] && chmod 600 nbproject/private/www-updater.key || :"
+  #- "[ $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 || :'

+ 5 - 5
BasicGameTemplate/nbproject/project.properties

@@ -35,23 +35,22 @@ includes=**
 jar.compress=false
 javac.classpath=\
     ${libs.jme3-jogg.classpath}:\
-    ${libs.jme3-blender.classpath}:\
     ${libs.jme3-networking.classpath}:\
     ${libs.jme3-plugins.classpath}:\
     ${libs.jme3-core.classpath}:\
     ${libs.jme3-desktop.classpath}:\
     ${libs.jme3-lwjgl.classpath}:\
-    ${libs.jme3-niftygui.classpath}:\
     ${libs.jme3-effects.classpath}:\
     ${libs.jme3-terrain.classpath}:\
-    ${libs.jme3-jbullet.classpath}
+    ${libs.jme3-bullet.classpath}:\
+    ${libs.jme3-bullet-native.classpath}
 # Space-separated list of extra javac options
 javac.compilerargs=
 javac.deprecation=false
 javac.processorpath=\
     ${javac.classpath}
-javac.source=1.6
-javac.target=1.6
+javac.source=1.7
+javac.target=1.7
 javac.test.classpath=\
     ${javac.classpath}:\
     ${build.classes.dir}
@@ -67,6 +66,7 @@ javadoc.use=true
 javadoc.version=false
 javadoc.windowtitle=
 jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
+jme.project.version=3.1
 jnlp.codebase.type=local
 jnlp.descriptor=application
 jnlp.enabled=false

+ 2 - 2
BasicGameTemplate/src/mygame/Main.java

@@ -3,13 +3,13 @@ package mygame;
 import com.jme3.app.SimpleApplication;
 import com.jme3.material.Material;
 import com.jme3.math.ColorRGBA;
-import com.jme3.math.Vector3f;
 import com.jme3.renderer.RenderManager;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.shape.Box;
 
 /**
- * test
+ * This is the Main Class of your Game. You should only do initialization here.
+ * Move your Logic into AppStates or Controls
  * @author normenhansen
  */
 public class Main extends SimpleApplication {

+ 3 - 1
branding/core/core.jar/org/netbeans/core/startup/Bundle.properties

@@ -1,9 +1,11 @@
 #Updated by build script
 #Sat, 27 Aug 2011 22:46:29 +0200
-currentVersion=jMonkeyEngine SDK PBRisComing-SNAPSHOT
+currentVersion=jMonkeyEngine SDK 3.1.0-alpha5
 LBL_splash_window_title=Starting jMonkeyEngine SDK
 SPLASH_HEIGHT=350
 SPLASH_WIDTH=500
 SplashProgressBarBounds=0,347,500,6
+SplashProgressBarColor=0xF3C802
 SplashRunningTextBounds=3,335,497,12
+SplashRunningTextColor=0xF3C802
 SplashRunningTextFontSize=10

二進制
branding/core/core.jar/org/netbeans/core/startup/about.png


+ 1 - 1
branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties

@@ -1,3 +1,3 @@
-LBL_Copyright=<p><em>Copyright &copy; 2015 jMonkeyEngine.\n<br>Please visit <a style="color: #1E2A60;" href="http://jmonkeyengine.org">http://jmonkeyengine.org</a> for more information.</em></p><p>Icons sets : <ul><li><a href="http://brankic1979.com/icons/">Brankic1979</a></li><li><a href="http://www.entypo.com/index.php">Entypo+</a></li><ul> </p>
+LBL_Copyright=<p><em>Copyright &copy; 2016 jMonkeyEngine.\n<br>Please visit <a style="color: #f3c802;" href="http://jmonkeyengine.org">http://jmonkeyengine.org</a> for more information.</em></p><p>Icons sets : <ul><li><a style="color: #f3c802;" href="http://brankic1979.com/icons/">Brankic1979</a></li><li><a style="color: #f3c802;" href="http://www.entypo.com/index.php">Entypo+</a></li><ul> </p>
 updates_not_found=<p style="margin: 0"><b>Updates:</b> jMonkeyEngine SDK is updated to version {0}</p>\n 
 URL_ON_IMG=http://jmonkeyengine.org/

+ 127 - 31
build.gradle

@@ -2,12 +2,16 @@
 import groovy.xml.MarkupBuilder
 import java.util.zip.ZipFile
 
+apply from: 'gradle/libs/digest.gradle'
+apply from: file('version.gradle')
+
 
 if (!hasProperty('mainClass')) {
     ext.mainClass = ''
 }
 
 repositories {
+    mavenLocal()
     jcenter {
         url "http://jcenter.bintray.com/"
     }
@@ -18,11 +22,18 @@ repositories {
         url 'http://nifty-gui.sourceforge.net/nifty-maven-repo/'
     }
     maven { url "https://jitpack.io" }
-}
 
-ext.jmeFullVersion = "PBRisComing-SNAPSHOT"
-ext.jmeNbmRevision = 0
+}
 
+if (System.getenv('TRAVIS') != null) {
+    if (ext.jmeGitTag != "") {
+        ext.jmeEngineVersion = "3.2.0-" + ext.jmeGitTag + "-SNAPSHOT"
+    } else {
+        ext.jmeEngineVersion = "3.2.0-master-SNAPSHOT"
+    }
+} else {
+    ext.jmeEngineVersion = "3.2.0-SNAPSHOT"
+}
 
 configurations {
     corelibs
@@ -33,30 +44,33 @@ configurations {
 
 dependencies {
 
-    corelibs dep("org.jmonkeyengine:jme3-core:$jmeFullVersion",true,true)
-    corelibs dep("org.jmonkeyengine:jme3-desktop:$jmeFullVersion", true, true)
-    corelibs dep("org.jmonkeyengine:jme3-lwjgl:$jmeFullVersion", true, true)
-    corelibs dep("org.jmonkeyengine:jme3-effects:$jmeFullVersion", true, true)
-    corelibs dep("org.jmonkeyengine:jme3-blender:$jmeFullVersion", true, true)
+    corelibs dep("com.github.xbuf:jme3_xbuf:0.9.1", false, false)
 
-    corelibs dep("org.jmonkeyengine:jme3-jbullet:$jmeFullVersion", true, true)
-    corelibs dep("org.jmonkeyengine:jme3-jogg:$jmeFullVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-core:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-desktop:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-lwjgl:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-effects:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-blender:$jmeEngineVersion", true, true)
 
-    corelibs dep("org.jmonkeyengine:jme3-networking:$jmeFullVersion", true, true)
-    corelibs dep("org.jmonkeyengine:jme3-niftygui:$jmeFullVersion", true, true)
-    corelibs dep("org.jmonkeyengine:jme3-plugins:$jmeFullVersion", true, true)
-    corelibs dep("org.jmonkeyengine:jme3-terrain:$jmeFullVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-bullet:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-bullet-native:$jmeEngineVersion", true, true)
+    corelibs dep(fileTree("lib"), false, false)
+    corelibs dep("org.jmonkeyengine:jme3-jogg:$jmeEngineVersion", true, true)
 
-    optlibs dep("org.jmonkeyengine:jme3-bullet:$jmeFullVersion", true, true)
-    optlibs dep("org.jmonkeyengine:jme3-jogl:$jmeFullVersion", true, true)
-    optlibs dep("org.jmonkeyengine:jme3-android:$jmeFullVersion", true, true)
-    optlibs dep("org.jmonkeyengine:jme3-ios:$jmeFullVersion", true, true)
-    optlibs dep("org.jmonkeyengine:jme3-android-native:$jmeFullVersion", true, true)
-    optlibs dep("org.jmonkeyengine:jme3-bullet-native:$jmeFullVersion", true, true)
-    optlibs dep("org.jmonkeyengine:jme3-bullet-native-android:$jmeFullVersion", true, true)
-    testdatalibs dep("org.jmonkeyengine:jme3-testdata:$jmeFullVersion", false, false)
+    corelibs dep("org.jmonkeyengine:jme3-networking:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-niftygui:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-plugins:$jmeEngineVersion", true, true)
+    corelibs dep("org.jmonkeyengine:jme3-terrain:$jmeEngineVersion", true, true)
 
-    examplelibs dep("org.jmonkeyengine:jme3-examples:$jmeFullVersion", false, true)
+    optlibs dep("org.jmonkeyengine:jme3-jbullet:$jmeEngineVersion", true, true)
+    optlibs dep("org.jmonkeyengine:jme3-jogl:$jmeEngineVersion", true, true)
+    optlibs dep("org.jmonkeyengine:jme3-android:$jmeEngineVersion", true, true)
+    optlibs dep("org.jmonkeyengine:jme3-ios:$jmeEngineVersion", true, true)
+    optlibs dep("org.jmonkeyengine:jme3-android-native:$jmeEngineVersion", true, true)
+    optlibs dep("org.jmonkeyengine:jme3-bullet-native-android:$jmeEngineVersion", true, true)
+    testdatalibs dep("org.jmonkeyengine:jme3-testdata:$jmeEngineVersion", false, false)
+
+    examplelibs dep("org.jmonkeyengine:jme3-examples:$jmeEngineVersion", false, true)
 
 }
 
@@ -82,14 +96,14 @@ task checkPlatformConfig {
     description = "Downloads the NetBeans platform base and registers it in the SDK project if needed"
     def platformFile = file("nbproject/private/platform-private.properties")
     if(!platformFile.exists()){
-        def netbeansFolder = file("../netbeans")
+        def netbeansFolder = file("netbeans")
         if(!netbeansFolder.exists() || netbeansFolder.list().length == 0){
             println "Downloading NetBeans Platform base, this only has to be done once.."
             def f = file("netbeans.zip")
             new URL(netbeansUrl).withInputStream{ i -> f.withOutputStream{ it << i }}
             copy{
                 from zipTree(f)
-                into "../"
+                into "."
             }
             f.delete()
         }
@@ -110,7 +124,7 @@ task copyBaseLibs(dependsOn:configurations.corelibs) <<{
    
     project.configurations.corelibs.collect {file ->
         // copy built jme3 jar files to jme3-core-baselibs
-        if (file.name.startsWith("jme3-") && !isSourceOrJavadoc(file.name)){
+        if (file.name.startsWith("jme3") && !isSourceOrJavadoc(file.name)){
             copy {
                 from file
                 into "jme3-core-baselibs/release/modules/ext/"
@@ -141,7 +155,7 @@ def isJavadoc(dep){
     return dep.endsWith("-javadoc.jar")
 }
 def isJmeDep(dep) {
-    return dep.startsWith("jme3-")
+    return dep.startsWith("jme3")
 }
 
 task createBaseXml(dependsOn: configurations.corelibs) <<{
@@ -153,7 +167,7 @@ task createBaseXml(dependsOn: configurations.corelibs) <<{
     // collect jar files
     project.configurations.corelibs.collect {file ->
         // copy built jme3 jar files to jme3-core-baselibs
-        if (file.name.startsWith("jme3-") && !isSourceOrJavadoc(file.name)){
+        if (file.name.startsWith("jme3") && !isSourceOrJavadoc(file.name)){
         
             //collect jme jars
             if(!jmeJarFiles.contains(file)){
@@ -474,13 +488,65 @@ copyTestSources.outputs.dir "JME3TestsTemplate/src/"
 copyTestSources.outputs.dir "JME3TestsTemplateAndroid/src/"
 
 ant.properties['plugins.version'] = jmeVersion
-ant.properties['app.version']= jmeFullVersion
+ant.properties['app.version']= jmePomVersion
 ant.properties['nbm.revision']= jmeNbmRevision
 
-task buildSdk(dependsOn: [copyBaseLibs, copyProjectLibs, createProjectXml, createBaseXml, copyTestSources]) <<{
+task overrideHarness(dependsOn: checkPlatformConfig) << {
+    def props = new Properties()
+    props.load(new FileInputStream("harness-override/override.properties"))
+
+    def patch_file = { f ->
+        def g = file("harness-override/" + f.getName())
+        if (!f.exists()) {
+            throw new GradleException('Cannot find targetFile: ' +  f.getAbsolutePath());
+        }
+
+        if (!g.exists()) {
+            throw new GradleException('Cannot find sourceFile: ' +  g.getAbsolutePath());
+        }
+
+        if (getSHA256Hash(f) == props[f.getName() + ".hashAfter"]) {
+            println "> Harness file \"" + f.getName() + "\" is already patched!"
+            return; /* Already patched */
+        }
+        if (getSHA256Hash(f) == props[f.getName() + ".hashBefore"]) {
+            println "> Will patch harness file \"" + f.getName() + "\"!"
+
+            if (getSHA256Hash(g) != props[g.getName() + ".hashAfter"]) {
+                throw new GradleException("Dangerous Checksum Mismatch: sourceFile \"" + g.getName() + "\" doesn't equal to its hashAfter hash. This probably means someone changed this file but forgot to update said hash or someone tried to invade the SDK by spreading his exe.")
+            }
+
+            copy {
+                from g
+                into f.getParent()
+            }
+
+        } else {
+            throw new GradleException('Checksum Mismatch: targetFile ' + f.getName() + ' has invalid hash ' + getSHA256Hash(f) +  '. Did you update Netbeans without changing harness-override/override.properties?');
+        }
+    }
+
+    patch_file(file("netbeans/harness/launchers/app.exe"));
+    patch_file(file("netbeans/harness/launchers/app64.exe"));
+    patch_file(file("netbeans/harness/launchers/pre7_app.exe"));
+
+}
+overrideHarness.outputs.files([ 'netbeans/harness/launchers/app.exe', 'netbeans/harness/launchers/app64.exe', 'netbeans/harness/launchers/pre7_app.exe'])
+overrideHarness.inputs.files([ 'netbeans/harness/launchers/app.exe', 'netbeans/harness/launchers/app64.exe', 'netbeans/harness/launchers/pre7_app.exe', 'harness-override/override.properties'])
+
+task downloadAvian() << {
+    def avianFile = file("jme3-ios/src/com/jme3/gde/ios/avian-openjdk-mac.zip")
+    
+    if (!avianFile.exists())
+    {
+        new URL('https://bintray.com/mefisto94/jme-sdk-storage/download_file?file_path=avian-openjdk-mac.zip').withInputStream{ i -> avianFile.withOutputStream{ it << i }}
+    }
+}
+
+task buildSdk(dependsOn: [copyBaseLibs, copyProjectLibs, createProjectXml, createBaseXml, copyTestSources, overrideHarness, downloadAvian]) <<{
     ant.propertyfile(file: "nbproject/project.properties") {
         entry( key: "plugins.version", value: "${jmeVersion}")
-        entry( key: "app.version", value: "${jmeFullVersion}")
+        entry( key: "app.version", value: "${jmePomVersion}")
         entry( key: "nbm.revision", value: "${jmeNbmRevision}")
     }
     ant.ant(dir: ".", antfile: "build.xml", target: "build")
@@ -494,10 +560,16 @@ file('.').eachDir{
 }
 buildSdk.outputs.dir "build"
 
+task run(dependsOn: buildSdk) << {
+    ant.ant(dir: ".", antfile: "build.xml", target: "run")
+}
+
 task cleanSdk() <<{
     ant.ant(dir: ".", antfile: "build.xml", target: "clean")
     file("jme3-core-baselibs/release/").deleteDir()
     file("jme3-core-libraries/release/").deleteDir()
+    file("jme3-core-baselibs/nbproject/project.xml").delete()
+    file("jme3-core-libraries/nbproject/project.xml").delete()
     file("jme3-project-baselibs/release/").deleteDir()
     file("jme3-project-libraries/release/").deleteDir()
     file("jme3-project-testdata/release/").deleteDir()
@@ -505,6 +577,30 @@ task cleanSdk() <<{
     file("JME3TestsTemplateAndroid/src/jme3test/").deleteDir()
 }
 
+task patchPlatformIndependent(type: Copy) {
+    from zipTree('dist/jmonkeyplatform.zip')
+    into "dist/temp/"
+
+    filter { String line ->
+        line.startsWith('jdkhome=') ? '#jdkhome="/path/to/jdk"': line
+    }
+
+    doLast {
+        delete(file('dist/jmonkeyplatform.zip'))
+    }
+}
+
+task fixPlatformIndependent(dependsOn: patchPlatformIndependent, type: Zip) {
+    description = "We compile our installers with the bundled jdk, but the platform independent zip doesn't have the jdk. For this we need to change the jmonkeyplatform.zip after building the installers to not have a jdk bundled"
+
+    from 'dist/temp'
+    archiveName = 'jmonkeyplatform.zip'
+    destinationDir = file('dist')
+
+    doLast {
+        delete("dist/temp")
+    }
+}
 
 //jar.dependsOn(buildSdk)
 //clean.dependsOn(cleanSdk)

+ 14 - 0
build_engine.sh

@@ -0,0 +1,14 @@
+#!/bin/sh
+# This Shell Script will build and use the latest jMonkeyEngine git version, so there might be some undiscovered engine bugs, watch out!
+# Also if you want to revert to releases and bintray builds, you need to uninstall them from your local maven repo...
+echo "Downloading the Engine, this may take some time"
+git clone -b master --single-branch --depth 1 http://github.com/jMonkeyEngine/jMonkeyEngine/ engine # single-branch requires git > 1.7.10, if you see an error, just leave it out.
+
+cd engine
+#echo "Patching the Engine...."
+#patch -s -N -p 1 < ../patches/FixHWSkinningSerialization.diff
+
+echo "Building the Engine and installing them to your local maven repo...."
+./gradlew install # Depends on jarJavadoc, jarSourcecode, assemble, dist etc.
+
+cd ../

+ 99 - 0
docs/building.md

@@ -0,0 +1,99 @@
+# Building the SDK  
+This document is for developers who intend to build the latest SDK on their own.  
+It's not really a big process but you should be familiar with the command line a little bit.  
+We will skip the process of cloning the repo/downloading the zip, as the net is full of examples about this.  
+
+## Defining the Engine Version  
+As the SDK has been split apart from the Engine Core, it simply downloads it as a dependency.  
+This comes in handy when it comes to build time however you're most likely unable to check your own engine changes.  
+
+Currently there are three options available:  
+
+### Official Releases (e.g. alpha2)
+You're all set. This it what happens out of the box. We always use the latest release (to which we are compatible)  
+If you want an older version (or revert back to official releases), just edit this in your build.gradle:  
+
+In the repositories {}, add: (Should already be there)  
+```
+jcenter {
+    url "http://jcenter.bintray.com/"
+}
+```
+Edit `ext.jmeFullVersion` to `3.1.0-alpha2` or whatever fits.
+
+### Official Snapshots (the latest engine version available)
+Keep in mind that you could experience strange bugs in the engine or maybe not even have a successful compile at all. On the other hand you profit off the latest bugfixes out there.  
+For consistency we recommend coding against a release though.  
+
+In the repositories {}, add: (Should already be there):  
+```
+maven {
+url "http://updates.jmonkeyengine.org/maven/"
+}
+```
+Edit `ext.jmeFullVersion` to `3.1.0-SNAPSHOT` (or 3.1.1, once it's out)  
+
+### Automated Builds of other branches/commits
+Say you want to develop the SDK to support more PBRish stuff you need something different:  
+
+In the repositories {}, add: (Should *not* be there)
+```
+maven {
+url "https://jitpack.io"
+}
+```
+Edit `ext.jmeFullVersion` to `PBRisComing-SNAPSHOT` (see [here](https://jitpack.io/docs/) for more information)
+
+## The Actual Build
+This is as easy as it get's:  
+Windows: `gradlew.bat buildSdk`  
+Linux/Mac: `./gradlew buildSdk`  
+
+Now everything is happening in the background: Netbeans is being downloaded to `netbeans/`and the SDK is built.  
+If you don't want to debug/code something in the SDK, skip to Deploying the SDK.  
+
+Fire up the freshly installed Netbeans:  
+Windows: `netbeans/bin/netbeans.exe`  
+Linux/Mac: `netbeans/bin/netbeans`  
+
+Now you click on "File->Open Project" and there just select the folder you downloaded the SDK to. It should show some orange patchwork. That's a Project Group.  
+After that, go to modules and select the module you want to work on. Double click on it to have it opened. Then you can edit it's source code, it'll unfold as a seperate project.  
+
+You can always use the launch buttons (debug, run, profile) from there and the SDK will be built and debugged.  
+Note: Somtimes Netbeans is a bit buggy with it's compile-on-save. For that, just click the Clean & Build Button before launching.  
+
+## Deploying the SDK
+Deploying simply means packaging it for customer use. There are two ways: The full-blown installer deploy (which you shouldn't do for personal use, we already do that when we release a new version) or the smaller "Zip Distribution".  
+
+### ZIP Distribution
+Note that this Name might be a bit misleading, since you could also package it as Mac .app.  
+To do this, just right click on the SDK Project Group and select an option. See here:  
+![Package as...](http://i.imgur.com/5V2uBHf.png)
+
+If you want to do this from command line (Packaging as .zip) you can do the following:  
+Windows: Search the net on how to use Apache ANT on Windows  
+Linux/Mac: `ant build-zip` (Note that ANT has to be installed on your system aswell)  
+
+This will drop you a file called `jmonkeyplatform.zip` into your dist/ folder.  
+It's already in it's usuable form. Just unpack and launch the appropriate file in the bin/ folder.  
+
+Note: This requires a JDK to be installed on your system and the blender integration won't work.  
+
+### Full Blown Installer Deploy
+This is an addition to the zip distribution: It will add the JDK and Blender for each supported platform and will bundle it to installers for said platforms.  
+
+Note: This build takes > 30 Minutes on pretty recent machines and downloads quite much data (though this only has to be done once). Keep that in mind before force quitting it (You'd have to start ALL OVER)  
+
+The download of support JDKs only works on Linux or Mac currently and there are *no plans* to change that.  
+It is untried but maybe you can place some dummy files (like taking the notepad.exe) and placing it under `jdks/windows-x86.exe` (etc.) so the build succeeds.  
+Keep in mind that they *have to be* valid executables or else the installer *WILL* crash.  
+
+```
+./gradlew buildSdk
+cd jdks
+./download-jdks.sh
+cd ../
+ant build-installers
+```
+
+Now you have neat installers under dist/

+ 38 - 0
docs/development.md

@@ -0,0 +1,38 @@
+# Developing for the SDK  
+
+This document is intended to be a loose collection of stuff which is not formatted/complete enough to be added into the Wiki.  
+
+### List of Links for the Nodes API
+http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html  
+http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/Node.html  
+http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/Sheet.html  
+  
+https://platform.netbeans.org/tutorials/nbm-nodesapi2.html  
+http://wiki.netbeans.org/BasicUnderstandingOfTheNetBeansNodesAPI  
+  
+Make Nodes Drag and Droppable / Moving Up and Down  
+https://blogs.oracle.com/geertjan/entry/node_cut_copy_paste_delete  
+https://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.1/misc/DragDrop  
+https://blogs.oracle.com/geertjan/entry/how_users_can_let_children  
+https://blogs.oracle.com/geertjan/entry/how_users_can_let_children1  
+
+Node Children:  
+http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/Children.html  
+http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/Children.Array.html  
+http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/Children.Keys.html  
+http://bits.netbeans.org/8.0/javadoc/org-openide-nodes/org/openide/nodes/Index.html  
+
+Why are my Nodes undeleteable? (Keys were regenerated)  
+https://netbeans.org/projects/platform/lists/dev/archive/2008-07/message/256 
+
+Random Exception when resetting keys (When the hashCode of a key changes):  
+https://huionn.wordpress.com/2012/08/20/api-design-defensive-and-explanatory-error-message/  
+  
+https://blogs.oracle.com/geertjan/entry/lookuplistener_children_keys  
+
+### Dark Monkey
+Dark Monkey is based on Nimrod Look and Feel so see [here](http://nilogonzalez.es/nimrodlf/download-en.html) to download it's source and Subclass whatever is needed. Nimrod also comes with those Icons (which are a bit low res, though.)  
+See [here](https://github.com/frohoff/jdk8u-dev-jdk/blob/master/src/macosx/classes/com/apple/laf/AquaMenuBarUI.java) for AquaMenuBarUI (Apple's Centralized Menu Bar). The Plan was to have Dark Monkey use this bar, but it doesn't work since we can't have those com.apple.laf packages as dependency atm, so Reflection would be needed.
+
+### Own FileTypes (Syntax Highlighting)
+https://platform.netbeans.org/tutorials/nbm-mfsyntax.html  

+ 71 - 0
docs/maintaining.md

@@ -0,0 +1,71 @@
+# Maintaining the SDK  
+This document is _only_ for developers who intend to maintain the SDK.  
+If you don't fulfill this criteria, feel free to skip that part as it won't help you with anything.  
+Actually this is not a real document either but simply a collection of links, hints, notes, etc.  
+
+### How to Release a new Version
+Since we have automated builds with travis you only have to tag a commit and it will be released for you.  
+Keep in mind that I currently have the impression that you can only publish one release at a time.  
+The OAUTH Key for this deployment is found in the .travis.yml along with instructions on how to generate such a file. You only need this when I'm (MeFisto94) no longer permitted to push to the repo.  
+
+The build process with the netbeans installers (`ant build-installers`) is a bit fragile especially in Travis Environment (small diskspace, no root (because caching)) so handle with care.  
+
+### What has to be done for a new Version?
+Now this part is actually for me so I don't forget it :P  
+
+Change http://wiki.jmonkeyengine.org/doku.php/sdk:welcome:3_1 every tag to keep up with the version number and then save it as nbres:/com/jme3/gde/docs/sdk/welcome/local.html  
+
+### How to Upgrade Dependencies
+See `nbi/stub/ext/infra/build/products/README` for now. It will be included in the docs and so the README will only be a link to that.  
+
+See `resources/README.md` and `harness-override/README.md` for how to change the Netbeans Icon (on Windows)  
+
+### How to add a new template to File->New
+This is really easy once we had fixed the issue #33.  
+Basically in your Module, add a `package-info.java`. For example:  
+```
+@TemplateRegistration(folder = "Scene", content = "Scene.j3o", displayName = "#Templates/JME3/Scene.j3o", description = "EmptyScene.html")
+package com.jme3.gde.scenecomposer;
+import org.netbeans.api.templates.TemplateRegistration;
+```
+
+As you can already see here, Folder is where it will appear, content is the package relative path (so you have to place the file inside of the source folder to have it appear in the jar), displayName is the key to look in `Bundle.properties`. Description **HAS TO BE** an external file. Neither keys nor in-line works.  
+
+IF you are using any `.j3XYZ` file, it will work fine, `.blend` also works, however `.jpg` for example wont.  
+The thing here is that Netbeans tries to interpret such files as text, replacing Strings such as the name and date (which is useful for source code indeed), but breaks our binary files (since we don't have valid UTF-8).  
+If you are interested in the background, see Issue 33 and the related code changes, however the simple answer is:  
+In Module `SceneComposer` under `com.jme3.gde.scenecomposer` you'll find the `CopyTemplateHandler.java` file.  
+Edit the following line just so it recognizes the appropriate extensions.  
+```java
+return ext.startsWith("j3") || ext.equals("blend"); /* Add your own binary extensions here !! */
+```
+
+### How to update Avian (iOS JVM)
+Avian is bundled in the jme3-ios.jar as `nbres:/com/jme3/gde/ios/avian-openjdk-mac.zip`.  
+The actual upgrade process is simply downloading the new versions, executing `cd jme3-ios && ant package-avian` and update the avianVersion in `IosCompositeProvider` or rather in it's inner SavePropsListener class.  
+
+- Download [Avian](https://readytalk.github.io/avian/) into any desired directory and extract it (it should create a folder called avian)
+- Download the OpenJDK unofficial builds from [here](https://github.com/alexkasko/openjdk-unofficial-builds). It's an unofficial build since there is only the source available for Mac OS and/or the only way to get official builds would be through the linux package managers. You need the "zip" file (no installer).  
+- Get the OpenJDK Sources. They are a bit hidden, but essentially pick the version [here](http://hg.openjdk.java.net/jdk7/jdk7/jdk/tags). Then click on zip (or whatever you like) on the left menu and extract the sources.
+- Download the Hello iOS Example Project from [here](https://github.com/ReadyTalk/hello-ios) (Click on Download ZIP) and extract it.
+
+Now you have to set-up the paths to the freshly downloaded things.  
+Open `jme3-ios/nbproject/project.properties` and adopt the changes to the few given paths. Let it point to the extracted things you just downloaded.
+Issue `cd jme3-ios && ant package-avian`.
+
+If you experience `ln: /usr/include/netinet/ip.h: No such file or directory` or something, then you didn't have XCode Command Line Tools installed. Type `xcode-select --install` to install them.  
+Note: Personally I was unable to compile Avian from here due to several compilation faults related to the downloaded JDK Sources. I will edit this document once I was able to.  
+
+### How to supply Updates through the internal Update Center
+Supplying updates through our infrastructure is really easy, there are only a few things to keep in mind.  
+Those Updates are supplied as NBM Files (Netbeans Module) which are built by issuing `ant nbms` or rather the targets `hudson-nightly` and `hudson-stable`. What they do is changing the version to "impl" and "spec" (Some Internal Netbeans Stuff).  
+Each NBM is then signed by us and hopefully the SDK won't download unsigned NBMs.  
+For this, you need to have a file called `nbproject/private/keystore`. You can change the keystore location and the username (`alias`) in `nbproject/platform.properties` (`keystore` and `nbm_alias`).  
+To generate a keystore, you issue `keytool -genkey -storepass "SecurePassword" -alias jmeupdates -validity 1068 -keystore nbproject/private/keystore` which generates the keystore with a validity of 3 yrs for the alias `jmeupdates`.  
+Note: When the Storepass contains backticks, you have to escape them with `\`'s.  
+Note: You must never ever upload/save the storepass in the git/web.  
+
+When you then build the nbms, you have to specify the SecurePassword like so: `ant nbms -Dstorepass="SecurePassword"`. Keep in mind that you have to escape each backtick with three (3)! `\\\`'s.  
+To not show the key to the public, you can specify the StorePass as an Environment Variable inside of your CI Build System (Hudson, Travis, ...)  
+
+When all of this is completed, you just have to upload the nbms to the right server, we do that using the SCP Protocol which you can also see for uploading the maven artifacts.  

+ 79 - 0
docs/reporting_issues.md

@@ -0,0 +1,79 @@
+# Reporting Issues
+This document is about Reporting Issues related to the SDK.  
+Reporting Issues is generally no big deal and seeing you reading this, you're likely to overcomplicating it.  
+Anyway in the following sections we'll describe some things about good Issue Reports.  
+
+## General
+Our Issues are all tracked on Github at the moment. If you see this document you're probably already there.  
+At the top of the current repo there is this tab called "Issues". Click on it to open the Issues page.  
+From there you'll have a really simple process:  
+- Make sure it's really an issue (a fault in the system, doesn't work as expected) and not maybe you doing things wrong. If you're looking for support or are in doubt whether this is an issue, join us at the [forums](http://hub.jmonkeyengine.org) and post in the category Troubleshooting -> jmonkeyplatform. Note: The forum allows signing in with github.
+- Look for already existing Issues. (You can use the search box by simply typing some keywords of your issue, e.g. `blender`)
+- IF there are existing Issues, look into them. If there's detailed info being asked feel free to provide your's aswell. You can also comment to tell us that you also experience that Issue (So we can see how many people are effected and what to fix first)
+- IF there are none, click on Create an Issue. Make sure to choose a good (but yet simple) title and just describe your problem.
+- Here it is important that you provide us as much information as possible: What's meant with "doesn't work"? What exactly did you do what way? If there are files involved, pack them as .zip and attach them to the Issue. (If you don't it could be that we are unable to reproduce it)
+- Submit the Issue and wait for further requests
+
+That's basically it. No matter what, we will tell you what further information we need, just make sure to describe it as detailed as possible.  
+See also the following parts on what information you _could_ include depending on the Issue.  
+
+### Version Information
+This is quite important for any release (as long as you are not using the latest version. DOUBLE SUPER TRIPLE CHECK!), since the SDK releases are fast paced.  
+Note: The Welcome Screen doesn't tell the truth about this. It always shows the latest version available.  
+You can try to rely on the window title but the dead safe way is to open the SDK's log and look for information like:  
+```
+Running on jMonkeyEngine 3.1-alpha3
+* Branch: HEAD
+* Git Hash: 0b487ee
+* Build Date: 2016-03-14
+LWJGL 2.9.3 context running on thread jME3 Main
+* Graphics Adapter: null
+[...]
+OpenGL Renderer Information
+* Renderer: NVIDIA GeForce GT 650M OpenGL Engine
+[...]
+Audio Renderer Information
+* Device: Built-in Output
+[...]
+OpenAL EFX not available! Audio effects won't work.
+```
+
+Please also include the information on the About Screen (especially for Build Problems).
+
+### Reporting Exceptions  
+From time to time, you might get an "Exception" being written in your SDK Console after you experienced an Issue.  
+It's important to not only copy the name of it but the full stacktrace (caused by xyz in line u, caught at ...).  
+For that you'll enclose this in three backticks in the line above and below, like so:   
+
+    ```
+    java.lang.NullPointerException
+    at com.jme3.scene.plugins.blender.meshes.MeshHelper.loadVerticesGroups(MeshHelper.java:289)
+    at com.jme3.scene.plugins.blender.meshes.TemporalMesh.<init>(TemporalMesh.java:126)
+    at com.jme3.scene.plugins.blender.meshes.TemporalMesh.<init>(TemporalMesh.java:100)
+    at com.jme3.scene.plugins.blender.meshes.MeshHelper.toTemporalMesh(MeshHelper.java:114)
+    at com.jme3.scene.plugins.blender.BlenderLoader.load(BlenderLoader.java:128)
+    Caused: java.io.IOException: Unexpected importer exception occured: null
+    at com.jme3.scene.plugins.blender.BlenderLoader.load(BlenderLoader.java:223)
+    at com.jme3.scene.plugins.blender.BlenderLoader.load(BlenderLoader.java:88)
+    at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:262)
+    ```
+
+### Reporting Faults in the NetBeans Installer  
+This happens when you try to install the SDK on your computer however get an undetailed error such as "Could not configurate JDK. Maybe wrong platform".  
+To improve that, you can launch the installer from the commandline and hence filling a file with debug output.  
+Search the net for information on how to open a commandline/cmd/terminal/console on your OS and to Change the Directory to the Download Folder.  
+When you're there, you simply issue the following command on windows systems:  
+`jmonkeyplatform-installer-x64.exe --verbose --output log.txt`(Note that the installer name might vary and that the TAB key will autocomplete your file name after typing jmonkey).  
+Under linux it'll be:  
+`./jmonkeyplatform-installer-x64.sh --verbose --output log.txt`  
+  
+Then you just need to upload that log.txt in addition to your error report and we can help you.  
+Without that report it's very unlikely that we can!  
+
+### Reporting Issues with any Model-Importer  
+It's already written above but since this is so important: Please upload your models packed as a .zip file along with your Issue report or we will be completely *unable* to reproduce the Issue.  
+If you can't do that due to licensing problems, try to create an own file/modify the file so you have another model where that issue appears.  
+
+### Reporting Issues with the "Design" (Look and Feel)  
+If you report Issues concering too big fonts or anything like that, go to the SDK's Preferences -> Appearance and tell us what LookandFeel is selected.  
+Note: Also try to use DarkMonkey. It's a theme created by us and as such is the only to be consistent over platforms. All others might differ from platform to platform.  

+ 3 - 3
gradle.properties

@@ -3,9 +3,9 @@ jmeVersion = 3.1.0
 # Version used for application and settings folder, no spaces!
 jmeMainVersion = 3.1
 # Version addition pre-alpha-svn, Stable, Beta
-jmeVersionTag = SNAPSHOT
+#jmeVersionTag = SNAPSHOT
 # Increment this each time jmeVersionTag changes but jmeVersion stays the same
-jmeVersionTagID = 0
+#jmeVersionTagID = 0
 
 # specify if JavaDoc should be built
 buildJavaDoc = true
@@ -25,7 +25,7 @@ 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
+netbeansUrl = http://download.netbeans.org/netbeans/8.1/final/zip/netbeans-8.1-201510222201-javase.zip
 
 # POM settings
 POM_NAME=jMonkeyEngine

+ 37 - 0
gradle/libs/digest.gradle

@@ -0,0 +1,37 @@
+import java.security.MessageDigest
+
+def getMD5Hash(input) {
+    if (!(input instanceof File)) {
+        logger.warn("getMD5Hash(): Input is no File. Maybe you forgot file()?")
+    }
+
+    MessageDigest digest = MessageDigest.getInstance("MD5")
+    digest.update(input.getBytes())
+    return new BigInteger(1, digest.digest()).toString(16).padLeft(32, "0");
+}
+
+def getSHA1Hash(input) {
+    if (!(input instanceof File)) {
+        logger.warn("getSHA1Hash(): Input is no File. Maybe you forgot file()?")
+    }
+
+    MessageDigest digest = MessageDigest.getInstance("SHA-1")
+    digest.update(input.getBytes())
+    return new BigInteger(1, digest.digest()).toString(16).padLeft(40, "0");
+}
+
+def getSHA256Hash(input) {
+    if (!(input instanceof File)) {
+        logger.warn("getSHA256Hash(): Input is no File. Maybe you forgot file()?")
+    }
+
+    MessageDigest digest = MessageDigest.getInstance("SHA-256")
+    digest.update(input.getBytes())
+    return new BigInteger(1, digest.digest()).toString(16).padLeft(64, "0");
+}
+
+ext { /* hax to export the methods */
+    getMD5Hash = this.&getMD5Hash
+    getSHA1Hash = this.&getSHA1Hash
+    getSHA256Hash = this.&getSHA256Hash
+}

二進制
gradle/wrapper/gradle-wrapper.jar


+ 6 - 0
gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Wed Mar 09 22:00:58 CET 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip

+ 160 - 0
gradlew

@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# 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
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+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
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# 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`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

+ 90 - 0
gradlew.bat

@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@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 Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows 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.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+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
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 18 - 0
harness-override/README.md

@@ -0,0 +1,18 @@
+## What does this folder do?
+This is pretty simple:  
+Since our SDK is based on Netbeans we download the so-called Netbeans Harness from official sources.  
+This Harness is basically the skeleton of our SDK.  
+
+In order to change the icon on Windows Systems we need to change files of said Harness.  
+Since this harness could be re-downloaded any time we needed the `overrideHarness` build functionality.  
+It simply overwrites harness files _each build_ (When necessary).  
+  
+In this folder you'll find our patched .exe files which will replace the harness files.  
+The downside is that you have to manually change the icon (or whatever manual editing is required) each time a new netbeans version is used as sdk base. See the `resources/` folder for more information on that.  
+> Note: Fortunately it doesn't have to be that the .exe files are changed aswell, so just look into it.
+
+To prevent patching an older version onto a newer netbeans we have the override.properties,  
+They define an `beforeHash`and an `afterHash` for each file.  
+Before is the official netbeans source and after is our own patch file (we use this to detect an already patched file/unauthorized changes to _THIS_ folder.)
+
+How do I generate such a hash? Those are SHA-256 hashes and either you make the build fail and see what gradle outputs or you issue `shasum -a 256 harness-override/*.exe` to print them out.

二進制
harness-override/app.exe


二進制
harness-override/app64.exe


+ 6 - 0
harness-override/override.properties

@@ -0,0 +1,6 @@
+app.exe.hashBefore=5d3921091a11880c143db8a6f5c55b6fec76f24d4d8bec56a8fc37e0b43b8be2
+app.exe.hashAfter=a55b5f690eb278666c3c55e169d6db2910a929e445bd44ccd0f996af3c44bac8
+app64.exe.hashBefore=909c523f0657650471caa7baa2751525604375d8b82688aad47472fdce1abe3b
+app64.exe.hashAfter=1aef0dd20c88ef4a5566ec2679a8bceda5ad4a11806f78ea5ccf4a30d7c40fa9
+pre7_app.exe.hashBefore=f4ea42a1ec2572b2a65a6d9baef0dd1f7293980c44c5d031c5b2ea5752352e49
+pre7_app.exe.hashAfter=fa8ae6457dad70a65cecb623ef0f60a86c92e856705eaeb2f22e43310fa9226f

二進制
harness-override/pre7_app.exe


+ 17 - 0
jdks/README

@@ -0,0 +1,17 @@
+The JDKs Folder provides the JDKs which are bundled with the SDK when the Installers are made.
+You can change the JDK Version in download-jdks.sh, but don’t change anything apart from that if you don’t know what you are doing.
+
+download-jdks.sh also replaces the functionality of build-osx-zip.sh but requires build-package.sh to be in the same folder.
+
+## Experienced Users: ##
+We need to download the JDKs for 5 platforms (Windows, Linux and MacOSX).
+The Problem is that those JDKs often come in .exe or .dmg files.
+download-jdks.sh hence downloads them and extracts the plain jdk folder out of them so they can be used with build-package.sh to create an SFX archive out of them.
+Unfortunately this doesn’t work for Mac OSX, so we simply zip the contents there.
+
+I could make the build work under Mac OS 10.9.5, however under Linux you could run into troubles because of the mount command: missing permissions, no hfs-drivers, etc pp.
+
+Also you need p7zip to be installed and many other more usual build-tools.
+
+
+- MeFisto94

+ 1 - 1
jdks/build-package.sh

@@ -40,7 +40,7 @@ cd jdk_tmp/jre
 pack200 -J-Xmx1024m lib/rt.jar.pack.gz lib/rt.jar
 rm -rf lib/rt.jar
 cd ..
-zip -9 -r -y ../jdk_tmp_sfx.zip .
+zip -9 -r -y -q ../jdk_tmp_sfx.zip .
 cd ..
 cat $unzipsfxname jdk_tmp_sfx.zip > $name
 chmod +x $name

+ 271 - 0
jdks/download-jdks.sh

@@ -0,0 +1,271 @@
+#!/bin/bash
+#(c) jmonkeyengine.org
+#Author MeFisto94
+set -e # Quit on Error
+
+jdk_version="8u77"
+jdk_build_version="b03"
+platforms=( "linux-x64.tar.gz" "linux-i586.tar.gz" "windows-i586.exe" "windows-x64.exe" "macosx-x64.dmg" )
+
+function install_xar {
+    # This is needed to open Mac OS .pkg files on Linux...
+    echo ">> Compiling xar, just for you..."
+    wget -q https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/xar/xar-1.5.2.tar.gz
+    tar xf xar-1.5.2.tar.gz
+    cd xar-1.5.2
+    ./configure -q > /dev/null
+    make -s > /dev/null
+    cd ../
+    echo "<< OK!"
+}
+
+function install_seven_zip {
+    # This is due to not having root privilegs for apt-get
+    if [ -x "$(command -v 7z)" ]; then
+        return 0
+    fi
+
+    echo "> Installing 7zip"
+
+    if [ -x "7zip/bin/7z" ]; then
+        echo ">> Found cached 7zip, adjusting path"
+        cd 7zip/bin
+        PATH=`pwd`:$PATH
+        cd ../../
+        return 0
+    fi
+
+    echo ">> Compiling 7zip from source"
+    mkdir -p 7zip/bin
+    mkdir -p 7zip/lib
+    cd 7zip
+    wget -q http://downloads.sourceforge.net/project/p7zip/p7zip/15.09/p7zip_15.09_src_all.tar.bz2
+    tar xf p7zip*
+    rm *.bz2
+    cd p7zip*
+    make all3 > /dev/null
+    ./install.sh ../bin ../lib /dev/null /dev/null
+    #mv -v bin/ ../
+    cd ../
+    rm -rf p7zip*
+    cd bin
+    PATH=`pwd`:$PATH
+    cd ../lib
+    PATH=`pwd`:$PATH
+    cd ../../
+}
+
+function download_jdk {
+    echo ">>> Downloading the JDK for $1"
+
+    if [ -f downloads/jdk-$1 ];
+    then
+        echo "<<< Already existing, SKIPPING."
+    else
+        curl -L  -s -o downloads/jdk-$1 http://download.oracle.com/otn-pub/java/jdk/$jdk_version-$jdk_build_version/jdk-$jdk_version-$1 --cookie "gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" #--progress-bar
+        echo "<<< OK!"
+    fi
+}
+
+function unpack_mac_jdk {
+    echo ">> Extracting the Mac JDK..."
+    #cd local/$jdk_version-$jdk_build_version/
+
+    if [ -f "compiled/jdk-macosx.zip" ];
+    then
+        echo "< Already existing, SKIPPING."
+        #cd ../../
+        return 0
+    fi
+
+    download_jdk macosx-x64.dmg
+
+    mkdir -p MacOS
+    cd MacOS
+
+    # MacOS
+    if [ "$(uname)" == "Darwin" ]; then
+        hdiutil attach ../downloads/jdk-macosx-x64.dmg
+        xar -xf /Volumes/JDK*/JDK*.pkg
+        hdiutil detach /Volumes/JDK*
+    else # Linux
+        7z x ../downloads/jdk-macosx-x64.dmg > /dev/null
+        7z x 4.hfs > /dev/null
+        install_xar
+        ./xar-1.5.2/src/xar -xf JDK*/JDK*.pkg
+    fi
+
+    cd jdk1*.pkg
+    cat Payload | gunzip -dc | cpio -i
+    #mkdir -p Contents/jdk/
+    cd Contents/
+    # FROM HERE: build-osx-zip.sh by normen (with changes)
+    mv Home jdk # rename folder
+    zip -9 -r -y -q ../../../compiled/jdk-macosx.zip jdk
+    cd ../../../
+    rm -rf MacOS/
+
+    if [ "$TRAVIS" == "true" ]; then
+        rm -rf downloads/jdk-macosx-x64.dmg
+    fi
+    #cd ../../
+
+    echo "<< OK!"
+}
+
+function build_mac_jdk {
+    echo "> Building the Mac JDK"
+    if ! [ -f "compiled/jdk-macosx.zip" ];
+    then
+        unpack_mac_jdk # Depends on "unpack" which depends on "download" (Unpack includes what compile is to other archs)
+    fi
+
+    rm -rf ../../jdk-macosx.zip
+    ln -s ./local/$jdk_version-$jdk_build_version/compiled/jdk-macosx.zip ../../ # Note that the first part is seen relative to the second one.
+    echo "< OK!"
+}
+
+# PARAMS arch_oracle
+function unpack_windows {
+    echo ">> Extracting the JDK for $1"
+    #cd local/$jdk_version-$jdk_build_version/
+
+    if [ -d $1 ];
+    then
+        echo "<< Already existing, SKIPPING."
+        # cd ../../
+        return 0
+    fi
+
+    download_jdk $1.exe
+
+    mkdir -p $1
+    7z x -o$1 "downloads/jdk-$1.exe" > /dev/null
+    unzip -qq $1/tools.zip -d $1/
+    rm $1/tools.zip
+
+    find $1 -type f \( -name "*.exe" -o -name "*.dll" \) -exec chmod u+rwx {} \; # Make them executable
+
+    find $1 -type f -name "*.pack" | while read eachFile; do
+        echo ">> Unpacking $eachFile ...";
+        unpack200 $eachFile ${eachFile%.pack}.jar;
+        rm $eachFile;
+    done
+
+    if [ "$TRAVIS" == "true" ]; then
+        rm -rf downloads/jdk-$1.exe
+    fi
+    # cd ../../
+    echo "<< OK!"
+}
+
+function unpack_linux {
+    echo ">> Extracting the JDK for $1"
+    #cd local/$jdk_version-$jdk_build_version/
+
+    if [ -d $1 ];
+    then
+        echo "<< Already existing, SKIPPING."
+        #cd ../../
+        return 0
+    fi
+
+    download_jdk $1.tar.gz
+
+    mkdir -p $1
+    cd $1
+    tar -xf "../downloads/jdk-$1.tar.gz"
+    cd jdk1*
+    mv * ../
+    cd ../
+    rm -rf jdk1*
+    cd ../
+
+    if [ "$TRAVIS" == "true" ]; then
+        rm -rf downloads/jdk-$1.tar.gz
+    fi
+
+    echo "<< OK!"
+}
+
+# PARAMS: os arch_usual arch_oracle
+function compile_other {
+    echo "> Compiling JDK for $1-$2"
+
+    if [ $1 == "windows" ]; then
+        name="jdk-$1-$2.exe"
+    elif [ $1 == "linux" ]; then
+        name="jdk-$1-$2.bin"
+    else
+        echo "Unknown Platform $1. ERROR!!!"
+        exit 1
+    fi
+
+    if [ -f "compiled/$name" ]; then
+        echo "< Already existing, SKIPPING."
+        return 0
+    fi
+
+    # Depends on UNPACK and thus DOWNLOAD
+    if [ $1 == "windows" ]; then
+        unpack_windows windows-$3
+    elif [ $1 == "linux" ]; then
+        unpack_linux linux-$3
+    fi
+
+    unzipsfxname="../../unzipsfx/unzipsfx-$1-$2"
+    if [ ! -f "$unzipsfxname" ]; then
+        echo "No unzipsfx for platform $1-$2 found at $unzipsfxname, cannot continue"
+        exit 1
+    fi
+
+    echo "> Creating SFX JDK package $name"
+    if [ -f "$1-$3/jre/lib/rt.jar" ]; then # Already packed?
+        echo "> PACK200 rt.jar"
+        pack200 -J-Xmx1024m $1-$3/jre/lib/rt.jar.pack.gz $1-$3/jre/lib/rt.jar
+        rm -rf $1-$3/jre/lib/rt.jar
+    fi
+
+    echo "> Zipping JDK"
+    cd $1-$3 # zip behaves differently between 7zip and Info-Zip, so simply change wd
+    zip -9 -qry ../jdk_tmp_sfx.zip *
+    cd ../
+    echo "> Building SFX"
+    cat $unzipsfxname jdk_tmp_sfx.zip > compiled/$name
+    chmod +x compiled/$name
+    rm -rf jdk_tmp_sfx.zip
+
+    if [ "$TRAVIS" == "true" ]; then
+        rm -rf $1-$3
+    fi
+
+    echo "< OK!"
+}
+
+# PARAMS: os arch_usual arch_oracle
+function build_other_jdk {
+    echo "> Building Package for $1-$2"
+    compile_other $1 $2 $3 # Depend on Compile
+
+    if [ $1 == "windows" ]; then
+        name="jdk-$1-$2.exe"
+    elif [ $1 == "linux" ]; then
+        name="jdk-$1-$2.bin"
+    fi
+
+    rm -rf ../../$name
+    ln -s ./local/$jdk_version-$jdk_build_version/compiled/$name ../../ # Note that the first part is seen relative to the second one.
+    echo "< OK!"
+}
+
+mkdir -p local/$jdk_version-$jdk_build_version/downloads
+mkdir -p local/$jdk_version-$jdk_build_version/compiled
+
+cd local/$jdk_version-$jdk_build_version
+
+build_mac_jdk
+build_other_jdk windows x86 i586
+build_other_jdk windows x64 x64
+build_other_jdk linux x86 i586
+build_other_jdk linux x64 x64
+cd ../../

+ 4 - 4
jme3-android/nbproject/genfiles.properties

@@ -1,8 +1,8 @@
-build.xml.data.CRC32=01aeea16
+build.xml.data.CRC32=5676c1f4
 build.xml.script.CRC32=6461359b
-build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
[email protected]1.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=01aeea16
+nbproject/build-impl.xml.data.CRC32=5676c1f4
 nbproject/build-impl.xml.script.CRC32=abd1e01a
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 36 - 4
jme3-android/nbproject/project.xml

@@ -21,7 +21,23 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.38.1</specification-version>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -45,7 +61,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.60.1</specification-version>
+                        <specification-version>1.62.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -63,7 +79,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.60.1</specification-version>
+                        <specification-version>1.62.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -105,7 +121,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>8.12.1</specification-version>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -140,6 +164,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages>
                 <package>com.jme3.gde.android</package>

+ 4 - 4
jme3-angelfont/nbproject/genfiles.properties

@@ -1,8 +1,8 @@
-build.xml.data.CRC32=46fd9bc9
+build.xml.data.CRC32=e43885b8
 build.xml.script.CRC32=03444ead
-build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
[email protected]1.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=46fd9bc9
+nbproject/build-impl.xml.data.CRC32=e43885b8
 nbproject/build-impl.xml.script.CRC32=8812c775
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 17 - 1
jme3-angelfont/nbproject/project.xml

@@ -54,7 +54,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>8.12.1</specification-version>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -73,6 +81,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages/>
         </data>

+ 2 - 2
jme3-assetpack-support/nbproject/genfiles.properties

@@ -3,6 +3,6 @@ build.xml.script.CRC32=c0969383
 [email protected]
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=b0dcc26b
+nbproject/build-impl.xml.data.CRC32=246c4420
 nbproject/build-impl.xml.script.CRC32=4d376df0
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 44 - 3
jme3-assetpack-support/nbproject/project.xml

@@ -57,7 +57,23 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.38.1</specification-version>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -87,6 +103,15 @@
                         <specification-version>1.78.1.8</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectuiapi.base</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.83.1.9</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.settings</code-name-base>
                     <build-prerequisite/>
@@ -101,7 +126,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.35.1</specification-version>
+                        <specification-version>6.38.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -133,7 +158,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>8.12.1</specification-version>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -176,6 +209,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.openide.windows</code-name-base>
                     <build-prerequisite/>

+ 1 - 2
jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.java

@@ -22,7 +22,6 @@ import java.util.zip.ZipInputStream;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.NotifyDescriptor.Confirmation;
@@ -56,7 +55,7 @@ public class OnlineBrowser extends javax.swing.JPanel implements HyperlinkListen
             new Thread(new Runnable() {
 
                 public void run() {
-                    ProgressHandle handle = ProgressHandleFactory.createHandle("Downloading AssetPack..");
+                    ProgressHandle handle = ProgressHandle.createHandle("Downloading AssetPack..");
                     handle.start();
                     String name = event.getURL().toString();
                     name = name.substring(name.lastIndexOf("/") + 1, name.length());

+ 1 - 2
jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/CleanupProjectAction.java

@@ -13,7 +13,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.swing.Action;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.filesystems.FileObject;
 import org.openide.util.Exceptions;
 import org.w3c.dom.Element;
@@ -79,7 +78,7 @@ public final class CleanupProjectAction implements Action {
         new Thread(new Runnable() {
 
             public void run() {
-                ProgressHandle handle = ProgressHandleFactory.createHandle("Cleanup unused assets..");
+                ProgressHandle handle = ProgressHandle.createHandle("Cleanup unused assets..");
                 handle.start();
                 scanFiles(context.getAssetsFolder(), files);
                 handle.finish();

+ 1 - 2
jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ConvertOgreBinaryMeshesAction.java

@@ -19,7 +19,6 @@ import java.util.logging.Logger;
 import javax.swing.Action;
 import javax.swing.JComponent;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.netbeans.api.project.Project;
 import org.openide.DialogDisplayer;
 import org.openide.WizardDescriptor;
@@ -58,7 +57,7 @@ public final class ConvertOgreBinaryMeshesAction implements Action {
     }
 
     public void scanDir(String dir2scan, boolean delete) {
-        ProgressHandle handle = ProgressHandleFactory.createHandle("Convert Ogre Binary Files");
+        ProgressHandle handle = ProgressHandle.createHandle("Convert Ogre Binary Files");
         handle.start();
         try {
             File zipDir = new File(dir2scan);

+ 1 - 2
jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ImportWorldForgeAction.java

@@ -35,7 +35,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.swing.Action;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.NotifyDescriptor.Message;
@@ -84,7 +83,7 @@ public final class ImportWorldForgeAction implements Action {
         new Thread(new Runnable() {
 
             public void run() {
-                ProgressHandle handle = ProgressHandleFactory.createHandle("Import WorldForge Models");
+                ProgressHandle handle = ProgressHandle.createHandle("Import WorldForge Models");
                 handle.start();
                 FileObject objects = folder.getFileObject("3d_objects");
                 if (objects == null) {

+ 1 - 2
jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/PublishAssetPackAction.java

@@ -25,7 +25,6 @@ import java.util.zip.ZipOutputStream;
 import javax.swing.Action;
 import javax.swing.JComponent;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.netbeans.api.project.Project;
 import org.openide.DialogDisplayer;
 import org.openide.WizardDescriptor;
@@ -59,7 +58,7 @@ public final class PublishAssetPackAction implements Action {
             new Thread(new Runnable() {
 
                 public void run() {
-                    ProgressHandle handle = ProgressHandleFactory.createHandle("Publishing AssetPack..");
+                    ProgressHandle handle = ProgressHandle.createHandle("Publishing AssetPack..");
                     handle.start();
                     packZip(wizardDescriptor);
                     copyData(wizardDescriptor);

+ 4 - 4
jme3-blender/nbproject/genfiles.properties

@@ -1,8 +1,8 @@
-build.xml.data.CRC32=0bff7456
+build.xml.data.CRC32=666e6265
 build.xml.script.CRC32=0f77a514
-build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
[email protected]1.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=0bff7456
+nbproject/build-impl.xml.data.CRC32=666e6265
 nbproject/build-impl.xml.script.CRC32=5c5042d6
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 34 - 2
jme3-blender/nbproject/project.xml

@@ -30,7 +30,23 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.38.1</specification-version>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -63,7 +79,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>8.12.1</specification-version>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -106,6 +130,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.openide.windows</code-name-base>
                     <build-prerequisite/>

+ 32 - 2
jme3-blender/src/com/jme3/gde/blender/BlenderAssetManagerConfigurator.java

@@ -1,11 +1,39 @@
 /*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
+ *  Copyright (c) 2009-2016 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.gde.blender;
 
 import com.jme3.asset.AssetManager;
 import com.jme3.gde.core.assets.AssetManagerConfigurator;
+import jme3_ext_xbuf.XbufLoader;
 
 /**
  *
@@ -14,8 +42,10 @@ import com.jme3.gde.core.assets.AssetManagerConfigurator;
 @org.openide.util.lookup.ServiceProvider(service = AssetManagerConfigurator.class)
 public class BlenderAssetManagerConfigurator implements AssetManagerConfigurator {
 
+    @Override
     public void prepareManager(AssetManager manager) {
         manager.registerLoader(com.jme3.scene.plugins.blender.BlenderModelLoader.class, "blend");
         manager.registerLoader(com.jme3.scene.plugins.blender.BlenderModelLoader.class, BlenderTool.TEMP_SUFFIX);
+        manager.registerLoader(XbufLoader.class, "xbuf");
     }
 }

+ 84 - 18
jme3-blender/src/com/jme3/gde/blender/BlenderTool.java

@@ -173,17 +173,21 @@ public class BlenderTool {
         }
     }
 
+    /**
+     * We create a lot of own directories to place our scripts inside, have config/preferences files stored there etc.
+     * That's the place were we check for their existance and create them if necessary
+     * Note: We don't use config/scripts folder's anymore in favour of the blender internal paths.
+     * @return 
+     */
     private static boolean checkBlenderFolders() {
         String jmpDir = Places.getUserDirectory().getAbsolutePath();
         FileObject fileObject = FileUtil.toFileObject(new File(jmpDir));
         if (fileObject != null) {
-            FileObject configFileObject = fileObject.getFileObject(configFolderName);
-            //TODO: using installed blender scripts folder, make more flexible by moving
-            //to updateable folder
-            FileObject scriptsFileObject = fileObject.getFileObject(scriptsFolderName);
+            //FileObject configFileObject = fileObject.getFileObject(configFolderName);
+            //FileObject scriptsFileObject = fileObject.getFileObject(scriptsFolderName);
             FileObject jmeScriptsFileObject = fileObject.getFileObject(jmeScriptsFolderName);
             FileObject userScriptsFileObject = fileObject.getFileObject(userScriptsFolderName);
-            if (configFileObject == null) {
+            /* if (configFileObject == null) {
                 try {
                     configFileObject = FileUtil.createFolder(fileObject, configFolderName);
                 } catch (IOException ex) {
@@ -198,7 +202,7 @@ public class BlenderTool {
                     Exceptions.printStackTrace(ex);
                     return false;
                 }
-            }
+            }*/
             if (jmeScriptsFileObject == null) {
                 try {
                     jmeScriptsFileObject = FileUtil.createFolder(fileObject, jmeScriptsFolderName);
@@ -215,7 +219,7 @@ public class BlenderTool {
                     return false;
                 }
             }
-            Scripts.copyToFolder(jmeScriptsFileObject);
+            Scripts.copyToFolder(jmeScriptsFileObject); /* Unpack our converter scripts */
         } else {
             logger.log(Level.SEVERE, "No global settings folder found!");
             return false;
@@ -223,26 +227,51 @@ public class BlenderTool {
         return true;
     }
 
+    /**
+     * This is the Path where blender will store all changes to the config.
+     * Note that this is not the blender default so you'll see different settings when launching blender from inside the SDK
+     * Why? Good question actually.
+     * @return 
+     */
     private static String getConfigEnv() {
         String ret = Places.getUserDirectory().getAbsolutePath() + "/" + configFolderName;
         ret = ret.replace("/", File.separator);
         return ret;
     }
 
-    private static String getScriptsEnv() {
+    /**
+     * This is the Path where blender itself stores it's scripts.
+     * The plan was to take those scripts and reside them into a folder along with all the other scripts (UserScripts, ...),
+     * We don't do this anymore because there's no real reason to copy all the scripts or even maintain them on your own.
+     * Blender automatically takes care.
+     * @return 
+     */
+    private static String getSystemScriptsEnv() {
         //TODO: using installed blender scripts folder
-        String ret = getBlenderSettingsFolder().getAbsolutePath();
-//        String ret = System.getProperty("netbeans.user") + "/" + scriptsFolderName;
+        String ret = getBlenderSettingsFolder().getAbsolutePath() + "/" + "scripts";
+        //String ret = System.getProperty("netbeans.user") + "/" + scriptsFolderName;
         ret = ret.replace("/", File.separator);
         return ret;
     }
 
+    /**
+     * This is the Path where we put custom userscripts inside.
+     * They would be available inside blender (examples would be some jmonkey-animation-helper-addon)
+     * @return The directory where the user scripts are
+     */
     private static String getUserScriptsEnv() {
         String ret = Places.getUserDirectory().getAbsolutePath() + "/" + userScriptsFolderName;
         ret = ret.replace("/", File.separator);
         return ret;
     }
 
+    /**
+     * Get the full path to that script.
+     * Those are the scripts that come with jMonkeyEngine (so neither user nor system)
+     * @param scriptName The name of the Script
+     * @param prefix The prefix like "import" or "tool"
+     * @return The whole absolute path to that script
+     */
     private static String getScriptPath(String scriptName, String prefix) {
         String ret = Places.getUserDirectory().getAbsolutePath() + "/" + jmeScriptsFolderName + "/" + prefix + "_" + scriptName + ".py";
         ret = ret.replace("/", File.separator);
@@ -258,8 +287,17 @@ public class BlenderTool {
         return blender;
     }
 
+    /**
+     * Get the main folder of blender where all resources are found:
+     * System Scripts, Bundled Python, etc.
+     * We don't need this anymore see {@link #getSystemScriptsEnv() }
+     * @return 
+     */
     private static File getBlenderSettingsFolder() {
-        File blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.75", null, false);
+        File blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.76", null, false); /* Update this every new Blender Version you use */
+        if (blender == null) {
+            blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.75", null, false);
+        }
         if (blender == null) {
             blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.69", null, false);
         }
@@ -279,6 +317,12 @@ public class BlenderTool {
         return blender;
     }
 
+    /**
+     * Run Blender to convert .fbx or similar files to a blender file which can then be imported to .j3o
+     * @param type The Filetype (extension)
+     * @param input The FileObject (Input). It will be placed the same but with .blend
+     * @return Success or not.
+     */
     public static boolean runConversionScript(String type, FileObject input) {
         if (!checkBlenderFolders()) {
             logger.log(Level.SEVERE, "Could not create blender settings folders!");
@@ -303,8 +347,8 @@ public class BlenderTool {
                     "-i", inputPath,
                     "-o", outputPath);
             buildr.directory(getBlenderRootFolder());
-            buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
-            buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getScriptsEnv());
+            //buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
+            //buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getSystemScriptsEnv());
             buildr.environment().put("BLENDER_USER_SCRIPTS", getUserScriptsEnv());
             Process proc = buildr.start();
             OutputReader outReader = new OutputReader(proc.getInputStream());
@@ -326,6 +370,13 @@ public class BlenderTool {
         return true;
     }
 
+    /**
+     * This will run a tool instead of an importer.
+     * See {@link #runConversionScript(java.lang.String, org.openide.filesystems.FileObject) }
+     * @param toolName The tool to use
+     * @param input The file to process
+     * @return sucess?
+     */
     public static boolean runToolScript(String toolName, FileObject input) {
         if (!checkBlenderFolders()) {
             logger.log(Level.SEVERE, "Could not create blender settings folders!");
@@ -347,8 +398,8 @@ public class BlenderTool {
                     "--",
                     "-i", inputPath);
             buildr.directory(getBlenderRootFolder());
-            buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
-            buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getScriptsEnv());
+            //buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
+            //buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getSystemScriptsEnv());
             buildr.environment().put("BLENDER_USER_SCRIPTS", getUserScriptsEnv());
             Process proc = buildr.start();
             OutputReader outReader = new OutputReader(proc.getInputStream());
@@ -370,6 +421,12 @@ public class BlenderTool {
         return true;
     }
 
+    /**
+     * Simply open that Blender File
+     * @param file The file/path to open
+     * @param async Should this method lock until blender has finished?
+     * @return sucess?
+     */
     private static boolean runBlender(final String file, boolean async) {
         if (!checkBlenderFolders()) {
             logger.log(Level.SEVERE, "Could not create blender settings folders!");
@@ -395,9 +452,9 @@ public class BlenderTool {
                 try {
                     String command = exe.getAbsolutePath();
                     ProcessBuilder buildr = new ProcessBuilder(command, file);
-                    buildr.directory(getBlenderRootFolder());
-                    buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
-                    buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getScriptsEnv());
+                    buildr.directory(getBlenderRootFolder()); /* Set working Directory to where the executables are */
+                    //buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
+                    //buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getSystemScriptsEnv());
                     buildr.environment().put("BLENDER_USER_SCRIPTS", getUserScriptsEnv());
                     Process proc = buildr.start();
                     OutputReader outReader = new OutputReader(proc.getInputStream());
@@ -434,11 +491,20 @@ public class BlenderTool {
         return successful.get();
     }
 
+    /**
+     * Open the file in Blender.
+     * Note: Path Seperators are automatically converted, so always use the unix "/" way.
+     * @param file The File to open
+     * @return Whether we had success or not
+     */
     public static boolean openInBlender(FileObject file) {
         String path = file.getPath().replace("/", File.separator);
         return runBlender(path, true);
     }
 
+    /**
+     * Simply just run Blender
+     */
     public static void runBlender() {
         if (!runBlender(null, true)) {
             logger.log(Level.INFO, "Could not run blender, already running? Trying to focus window.");

+ 3 - 3
jme3-blender/src/com/jme3/gde/blender/Bundle.properties

@@ -1,5 +1,5 @@
 OpenIDE-Module-Display-Category=jMonkeyEngine
 OpenIDE-Module-Long-Description=\
-    This plugin adds support for Blender .blend files
-OpenIDE-Module-Name=Blender Support
-OpenIDE-Module-Short-Description=Adds support for Blender .blend files
+    This plugin adds support for Blender .blend files and XBuf's .xbuf files
+OpenIDE-Module-Name=Blender (and XBuf) Support
+OpenIDE-Module-Short-Description=Adds support for Blender .blend and XBuf's .xbuf files

+ 85 - 0
jme3-blender/src/com/jme3/gde/blender/ConvertToBlendAction.java

@@ -0,0 +1,85 @@
+/*
+ *  Copyright (c) 2009-2016 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.gde.blender;
+
+import com.jme3.gde.blender.filetypes.AbstractBlenderImportDataObject;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.MultiDataObject;
+import org.openide.util.NbBundle.Messages;
+
+@ActionID(
+        category = "jMonkeyPlatform",
+        id = "com.jme3.gde.blender.ConvertToBlendAction"
+)
+@ActionRegistration(
+        displayName = "#CTL_ConvertToBlendAction"
+)
+@ActionReferences({
+    @ActionReference(path = "Loaders/application/fbx/Actions", position = 150),
+    @ActionReference(path = "Loaders/model/vnd.collada+xml/Actions", position = 150),
+    @ActionReference(path = "Loaders/application/x-3ds/Actions", position = 150)
+})
+@Messages("CTL_ConvertToBlendAction=Convert to .blend file")
+
+/**
+ * The "Convert to .blend" Action is there for all files which are converted by the blender importers.
+ * It allows you to convert an .fbx/.3ds file into a .blend file so that you can modify the file before the final .j3o import.
+ * 
+ * @author MeFisto94
+ */
+public final class ConvertToBlendAction implements ActionListener {
+
+    private final List<MultiDataObject> context;
+
+    public ConvertToBlendAction(List<MultiDataObject> context) {
+        this.context = context;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ev) {
+        /* We need a context list because you can select multiple objects */
+        for (MultiDataObject multiDataObject : context) {
+            if (multiDataObject instanceof AbstractBlenderImportDataObject) {
+                AbstractBlenderImportDataObject obj = (AbstractBlenderImportDataObject)multiDataObject;
+                FileObject file = obj.importFile();
+                // BlenderTool.openInBlender(file);
+            }
+        }
+    }
+}

+ 117 - 0
jme3-blender/src/com/jme3/gde/blender/ConvertToJ3OAction.java

@@ -0,0 +1,117 @@
+/*
+ *  Copyright (c) 2009-2016 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.gde.blender;
+
+import com.jme3.gde.blender.filetypes.AbstractBlenderImportDataObject;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeListener;
+import java.util.List;
+import javax.swing.Action;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+import org.openide.loaders.MultiDataObject;
+import org.openide.util.NbBundle.Messages;
+
+@ActionID(
+        category = "jMonkeyPlatform",
+        id = "com.jme3.gde.blender.ConvertToJ3OAction"
+)
+@ActionRegistration(
+        displayName = "#CTL_ConvertToJ3OAction"
+)
+@ActionReferences({
+    @ActionReference(path = "Loaders/application/fbx/Actions", position = 150),
+    @ActionReference(path = "Loaders/model/vnd.collada+xml/Actions", position = 150),
+    @ActionReference(path = "Loaders/application/x-3ds/Actions", position = 150)
+})
+@Messages("CTL_ConvertToJ3OAction=Convert to .j3o binary")
+
+/**
+ * The "Convert to .j3o" Action is there for all files which are converted by the blender importers.
+ * It allows you to convert an .fbx/.3ds file into a .j3o file using blenders import capabilites.
+ * 
+ * @author MeFisto94
+ */
+public final class ConvertToJ3OAction implements Action {
+
+    private final List<MultiDataObject> context;
+
+    public ConvertToJ3OAction(List<MultiDataObject> context) {
+        this.context = context;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ev) {
+        /* We need a context list because you can select multiple objects */
+        for (MultiDataObject multiDataObject : context) {
+            if (multiDataObject instanceof AbstractBlenderImportDataObject) {
+                AbstractBlenderImportDataObject obj = (AbstractBlenderImportDataObject)multiDataObject;
+                obj.loadAsset();
+            }
+        }
+    }
+
+    @Override
+    public Object getValue(String key) {
+        return null;
+    }
+
+    @Override
+    public void putValue(String key, Object value) {
+        
+    }
+
+    @Override
+    public void setEnabled(boolean b) {
+        
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return true;
+    }
+
+    @Override
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        
+    }
+
+    @Override
+    public void removePropertyChangeListener(PropertyChangeListener listener) {
+        
+    }
+    
+    
+}

+ 99 - 0
jme3-blender/src/com/jme3/gde/blender/XbufDataObject.java

@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2009-2016 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.gde.blender;
+
+import com.jme3.asset.ModelKey;
+import com.jme3.gde.core.assets.SpatialAssetDataObject;
+import java.io.IOException;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.MIMEResolver;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectExistsException;
+import org.openide.loaders.MultiFileLoader;
+import org.openide.util.NbBundle.Messages;
+import jme3_ext_xbuf.*;
+
+@Messages({
+    "LBL_XBUF_LOADER=XBuf Files"
+})
[email protected](
+    displayName="#LBL_XBUF_LOADER",
+    mimeType="application/xbuf",
+    extension={ "xbuf" }
+)
[email protected](
+    mimeType = "application/xbuf", 
+    iconBase = "com/jme3/gde/blender/xbuf.png",
+    displayName="#LBL_XBUF_LOADER",
+    position=300
+)
+@ActionReferences(value = {
+    @ActionReference(id =
+    @ActionID(category = "jMonkeyPlatform", id = "com.jme3.gde.core.assets.actions.ConvertModel"), path = "Loaders/application/xbuf/Actions", position = 10),
+    @ActionReference(id =
+    @ActionID(category = "jMonkeyPlatform", id = "com.jme3.gde.core.assets.actions.OpenModel"), path = "Loaders/application/xbuf/Actions", position = 20),
+    @ActionReference(id =
+    @ActionID(category = "Edit", id = "org.openide.actions.CutAction"), path = "Loaders/application/xbuf/Actions", position = 200, separatorBefore = 100),
+    @ActionReference(id =
+    @ActionID(category = "Edit", id = "org.openide.actions.CopyAction"), path = "Loaders/application/xbuf/Actions", position = 300, separatorAfter = 400),
+    @ActionReference(id =
+    @ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"), path = "Loaders/application/xbuf/Actions", position = 500),
+    @ActionReference(id =
+    @ActionID(category = "System", id = "org.openide.actions.RenameAction"), path = "Loaders/application/xbuf/Actions", position = 600, separatorAfter = 700),
+    @ActionReference(id =
+    @ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"), path = "Loaders/application/xbuf/Actions", position = 800, separatorAfter = 900),
+    @ActionReference(id =
+    @ActionID(category = "System", id = "org.openide.actions.FileSystemAction"), path = "Loaders/application/xbuf/Actions", position = 1000, separatorAfter = 1100),
+    @ActionReference(id =
+    @ActionID(category = "System", id = "org.openide.actions.ToolsAction"), path = "Loaders/application/xbuf/Actions", position = 1200),
+    @ActionReference(id =
+    @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"), path = "Loaders/application/xbuf/Actions", position = 1300)
+})
+public class XbufDataObject extends SpatialAssetDataObject {
+
+    public XbufDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
+        super(pf, loader);
+    }
+
+    @Override
+    public ModelKey getAssetKey() {
+        if(super.getAssetKey() instanceof XbufKey){
+            return (XbufKey)assetKey;
+        }
+        assetKey = new XbufKey(super.getAssetKey().getName());
+        return (XbufKey)assetKey;
+    }
+    
+}

+ 127 - 31
jme3-blender/src/com/jme3/gde/blender/filetypes/AbstractBlenderImportDataObject.java

@@ -1,29 +1,66 @@
 /*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
+ *  Copyright (c) 2009-2016 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.gde.blender.filetypes;
 
 import com.jme3.asset.BlenderKey;
 import com.jme3.gde.blender.BlenderTool;
+import com.jme3.gde.blender.ConvertToJ3OAction;
+import com.jme3.gde.core.assets.AssetDataNode;
 import com.jme3.gde.core.assets.ProjectAssetManager;
 import com.jme3.gde.core.assets.SpatialAssetDataObject;
 import com.jme3.gde.core.util.Beans;
 import com.jme3.gde.core.util.SpatialUtil;
 import com.jme3.scene.Spatial;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.logging.Level;
+import javax.swing.Action;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
-import org.openide.filesystems.FileLock;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileUtil;
+import org.openide.loaders.DataObject;
 import org.openide.loaders.DataObjectExistsException;
+import org.openide.loaders.MultiDataObject;
 import org.openide.loaders.MultiFileLoader;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
 import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.ProxyLookup;
 
 /**
- *
+ * The AbstractBlenderImportDataObject handles all possible Filetypes which should be automatically converted by Blender's Importer.
+ * You have to extend this class and just set the correct suffix. See: {@link BlenderFbxDataObject}
  * @author normenhansen
  */
 public abstract class AbstractBlenderImportDataObject extends SpatialAssetDataObject {
@@ -39,38 +76,12 @@ public abstract class AbstractBlenderImportDataObject extends SpatialAssetDataOb
         if (savable != null) {
             return (Spatial) savable;
         }
-        if (SUFFIX == null) {
-            throw new IllegalStateException("Suffix for blender filetype is null! Set SUFFIX = \"sfx\" in constructor!");
-        }
         ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class);
         if (mgr == null) {
             DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("File is not part of a project!\nCannot load without ProjectAssetManager."));
             return null;
         }
-        //make sure its actually closed and all data gets reloaded
-        closeAsset();
-        FileObject mainFile = getPrimaryFile();
-        if (!BlenderTool.runConversionScript(SUFFIX, mainFile)) {
-            logger.log(Level.SEVERE, "Failed to create model, running blender caused an error");
-            return null;
-        }
-        mainFile.getParent().refresh();
-        FileObject outFile = FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX);
-        if (outFile == null) {
-            logger.log(Level.SEVERE, "Failed to create model, blend file cannot be found");
-            return null;
-        }
-        int i = 1;
-        FileObject blend1File = FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX + i);
-        while (blend1File != null) {
-            try {
-                blend1File.delete();
-            } catch (IOException ex) {
-                Exceptions.printStackTrace(ex);
-            }
-            i++;
-            blend1File = FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX + i);
-        }
+        FileObject outFile = importFile(mgr);
         String assetKeyName = mgr.getRelativeAssetPath(outFile.getPath());
         BlenderKey key = new BlenderKey(assetKeyName);
         Beans.copyProperties(key, getAssetKey());
@@ -84,6 +95,7 @@ public abstract class AbstractBlenderImportDataObject extends SpatialAssetDataOb
             logger.log(Level.INFO, "Loaded asset {0}", getName());
             return spatial;
         } catch (Exception ex) {
+            logger.log(Level.SEVERE, ex.getMessage(), ex);
             Exceptions.printStackTrace(ex);
         } finally {
             try {
@@ -116,4 +128,88 @@ public abstract class AbstractBlenderImportDataObject extends SpatialAssetDataOb
             }
         }
     }
+    
+    /**
+     * Use this method to convert this file into a blender model
+     * Note: This requires a bit of additional code (creating the PAM) so use the version without parameters if you don't plan to modify the blend further
+     * @param mgr The AssetManager which provides access to the Project Files
+     * @return The FileObject of the .blend file
+     */
+    public FileObject importFile(ProjectAssetManager mgr) {
+        if (SUFFIX == null) {
+            throw new IllegalStateException("Suffix for blender filetype is null! Set SUFFIX = \"sfx\" in constructor!");
+        }
+        
+        //make sure its actually closed and all data gets reloaded
+        closeAsset();
+        FileObject mainFile = getPrimaryFile();
+        
+        if (FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX) != null) {
+            logger.log(Level.SEVERE, "Cannot convert " + getName() + " to .blend because there is already a file with this name. Delete it and try again!");
+            return null;
+        }
+        
+        if (!BlenderTool.runConversionScript(SUFFIX, mainFile)) {
+            logger.log(Level.SEVERE, "Failed to create model, running blender caused an error");
+            return null;
+        }
+        mainFile.getParent().refresh();
+        FileObject outFile = FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX);
+        if (outFile == null) {
+            logger.log(Level.SEVERE, "Failed to create model, blend file cannot be found");
+            return null;
+        }
+        int i = 1;
+        FileObject blend1File = FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX + i);
+        while (blend1File != null) {
+            try {
+                blend1File.delete();
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+            i++;
+            blend1File = FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX + i);
+        }
+        
+        return outFile;
+    }
+    
+    /**
+     * Use this method to simply convert any supported file into a .blend file.
+     * @return The FileObject for the converted .blend file
+     */
+    public FileObject importFile() {
+        ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class);
+        if (mgr == null) {
+            DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("File is not part of a project!\nCannot load without ProjectAssetManager."));
+            return null;
+        }
+        FileObject outFile = importFile(mgr);
+        return outFile;
+    }
+
+    @Override
+    protected Node createNodeDelegate() {
+        MyAssetDataNode node = new MyAssetDataNode(this, Children.LEAF, new ProxyLookup(getCookieSet().getLookup(), contentLookup));
+        node.setIconBaseWithExtension("com/jme3/gde/core/icons/model.gif");
+        return node;
+    }
+    
+    private class MyAssetDataNode extends AssetDataNode {
+        public MyAssetDataNode(DataObject obj, Children ch) {
+            super(obj, ch);
+        }
+
+        public MyAssetDataNode(DataObject obj, Children ch, Lookup lookup) {
+            super(obj, ch, lookup);
+        }
+
+        @Override
+        public Action getPreferredAction()
+        {
+            ArrayList<MultiDataObject> ctx = new ArrayList<MultiDataObject>();
+            ctx.add((MultiDataObject)getDataObject());
+            return new ConvertToJ3OAction(ctx);
+        }   
+    }
 }

二進制
jme3-blender/src/com/jme3/gde/blender/xbuf.png


+ 4 - 4
jme3-cinematics/nbproject/genfiles.properties

@@ -1,8 +1,8 @@
-build.xml.data.CRC32=24b896de
+build.xml.data.CRC32=ec8899d4
 build.xml.script.CRC32=d8082083
-build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
[email protected]1.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=24b896de
+nbproject/build-impl.xml.data.CRC32=ec8899d4
 nbproject/build-impl.xml.script.CRC32=a2681ce5
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 25 - 1
jme3-cinematics/nbproject/project.xml

@@ -33,6 +33,14 @@
                         <specification-version>3.1.0</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.settings</code-name-base>
                     <build-prerequisite/>
@@ -63,7 +71,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>8.12.1</specification-version>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -98,6 +114,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.openide.windows</code-name-base>
                     <build-prerequisite/>

+ 4 - 4
jme3-code-check/nbproject/genfiles.properties

@@ -1,8 +1,8 @@
-build.xml.data.CRC32=5f20bdd0
+build.xml.data.CRC32=6f2bff9e
 build.xml.script.CRC32=a481f885
-build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
[email protected]1.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=5f20bdd0
+nbproject/build-impl.xml.data.CRC32=6f2bff9e
 nbproject/build-impl.xml.script.CRC32=0691bb76
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 50 - 2
jme3-code-check/nbproject/project.xml

@@ -24,6 +24,14 @@
                         <specification-version>1.52.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.libs.javacapi</code-name-base>
                     <build-prerequisite/>
@@ -41,6 +49,14 @@
                         <specification-version>1.79.1.5.22.43</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.5.1.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
                     <build-prerequisite/>
@@ -73,7 +89,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>0.138.2.32.2.25.8</specification-version>
+                        <specification-version>0.149.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.java.source.base</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>2.9.1.2.2.25.8.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -85,6 +109,14 @@
                         <specification-version>1.35.1.7.43</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.spi.java.hints</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.27.1.13.2.25.32.2.8</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.openide.awt</code-name-base>
                     <build-prerequisite/>
@@ -98,7 +130,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>8.12.1</specification-version>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -141,6 +181,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages/>
         </data>

+ 16 - 0
jme3-code-check/src/com/jme3/gde/codecheck/hints/Bundle.properties

@@ -0,0 +1,16 @@
+UpdateHint.display-name=Updating is not needed in jME3, check your update order if you need to call this.
+UpdateHint.id=Update States / Bound
+UpdateHint.description=Checks for calls to updateGeometricState(), updateLogicalState() and updateModelBound().
+UpdateHint.fix-text=Remove this call
+TempVarsHint.display-name=TempVars might not be released
+TempVarsHint.id=TempVars release check
+TempVarsHint.description=Checks for calls TempVars.get() and search for correspondinng release() call
+TempVarsHint.fix-text=Add a release() call at the end of the method
+ReadOnlyPrimitiveHint.display-name=This primitive is read only and should not be modified!
+ReadOnlyPrimitiveHint.id=ReadOnly Primitives
+ReadOnlyPrimitiveHint.description=Checks for modifications to readonly primitives. (getLocalTranslation().set())
+ReadOnlyPrimitiveHint.fix-text=Remove this call
+InternalMethodHint.display-name=You should not call this method, its for internal use only!
+InternalMethodHint.id=Internal Methods
+InternalMethodHint.description=Checks for calls to internal methods.
+InternalMethodHint.fix-text=Remove this call

+ 5 - 4
jme3-code-check/src/com/jme3/gde/codecheck/hints/InternalMethodHint.java

@@ -22,6 +22,7 @@ import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
 import org.netbeans.spi.editor.hints.Fix;
 import org.openide.awt.StatusDisplayer;
+import org.openide.util.NbBundle;
 
 public class InternalMethodHint extends AbstractHint {
 
@@ -84,19 +85,19 @@ public class InternalMethodHint extends AbstractHint {
     //Message that the user sees in the left sidebar:
     @Override
     public String getDisplayName() {
-        return "You should not call this method, its for internal use only!";
+        return NbBundle.getMessage(InternalMethodHint.class, "InternalMethodHint.display-name");
     }
 
     //Name of the hint in the Options window:
     @Override
     public String getId() {
-        return "Internal Methods";
+        return NbBundle.getMessage(InternalMethodHint.class, "InternalMethodHint.id");
     }
 
     //Description of the hint in the Options window:
     @Override
     public String getDescription() {
-        return "Checks for calls to internal methods.";
+        return NbBundle.getMessage(InternalMethodHint.class, "InternalMethodHint.description");
     }
 
     class MessagesFix implements EnhancedFix {
@@ -118,7 +119,7 @@ public class InternalMethodHint extends AbstractHint {
 
         @Override
         public String getText() {
-            return "Remove this call";
+            return NbBundle.getMessage(InternalMethodHint.class, "InternalMethodHint.fix-text");
         }
 
         @Override

+ 5 - 4
jme3-code-check/src/com/jme3/gde/codecheck/hints/ReadOnlyPrimitiveHint.java

@@ -21,6 +21,7 @@ import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
 import org.netbeans.spi.editor.hints.Fix;
 import org.openide.awt.StatusDisplayer;
+import org.openide.util.NbBundle;
 
 public class ReadOnlyPrimitiveHint extends AbstractHint {
 
@@ -94,19 +95,19 @@ public class ReadOnlyPrimitiveHint extends AbstractHint {
     //Message that the user sees in the left sidebar:
     @Override
     public String getDisplayName() {
-        return "This primitive is read only and should not be modified!";
+        return NbBundle.getMessage(ReadOnlyPrimitiveHint.class, "ReadOnlyPrimitiveHint.display-name");
     }
 
     //Name of the hint in the Options window:
     @Override
     public String getId() {
-        return "ReadOnly Primitives";
+        return NbBundle.getMessage(ReadOnlyPrimitiveHint.class, "ReadOnlyPrimitiveHint.id");
     }
 
     //Description of the hint in the Options window:
     @Override
     public String getDescription() {
-        return "Checks for modifications to readonly primitives. (getLocalTranslation().set())";
+        return NbBundle.getMessage(ReadOnlyPrimitiveHint.class, "ReadOnlyPrimitiveHint.description");
     }
 
     class MessagesFix implements EnhancedFix {
@@ -128,7 +129,7 @@ public class ReadOnlyPrimitiveHint extends AbstractHint {
 
         @Override
         public String getText() {
-            return "Remove this call";
+            return NbBundle.getMessage(ReadOnlyPrimitiveHint.class, "ReadOnlyPrimitiveHint.fix-text");
         }
 
         @Override

+ 5 - 4
jme3-code-check/src/com/jme3/gde/codecheck/hints/TempVarsHint.java

@@ -24,6 +24,7 @@ import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
 import org.netbeans.spi.editor.hints.Fix;
 import org.openide.awt.StatusDisplayer;
+import org.openide.util.NbBundle;
 
 public class TempVarsHint extends AbstractHint {
 
@@ -135,19 +136,19 @@ public class TempVarsHint extends AbstractHint {
     //Message that the user sees in the left sidebar:
     @Override
     public String getDisplayName() {
-        return "TempVars might not be released";
+        return NbBundle.getMessage(TempVarsHint.class, "TempVarsHint.display-name");
     }
 
     //Name of the hint in the Options window:
     @Override
     public String getId() {
-        return "TempVars release check";
+        return NbBundle.getMessage(TempVarsHint.class, "TempVarsHint.id");
     }
 
     //Description of the hint in the Options window:
     @Override
     public String getDescription() {
-        return "Checks for calls TempVars.get() and search for correspondinng release() call";
+        return NbBundle.getMessage(TempVarsHint.class, "TempVarsHint.description");
     }
 
     class MessagesFix implements EnhancedFix {
@@ -169,7 +170,7 @@ public class TempVarsHint extends AbstractHint {
 
         @Override
         public String getText() {
-            return "Add a release() call at the end of the method";
+            return NbBundle.getMessage(TempVarsHint.class, "TempVarsHint.fix-text");
         }
 
         @Override

+ 5 - 4
jme3-code-check/src/com/jme3/gde/codecheck/hints/UpdateHint.java

@@ -21,6 +21,7 @@ import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
 import org.netbeans.spi.editor.hints.Fix;
 import org.openide.awt.StatusDisplayer;
+import org.openide.util.NbBundle;
 
 public class UpdateHint extends AbstractHint {
 
@@ -86,19 +87,19 @@ public class UpdateHint extends AbstractHint {
     //Message that the user sees in the left sidebar:
     @Override
     public String getDisplayName() {
-        return "Updating is not needed in jME3, check your update order if you need to call this.";
+        return NbBundle.getMessage(UpdateHint.class, "UpdateHint.display-name");
     }
 
     //Name of the hint in the Options window:
     @Override
     public String getId() {
-        return "Update States / Bound";
+        return NbBundle.getMessage(UpdateHint.class, "UpdateHint.id");
     }
 
     //Description of the hint in the Options window:
     @Override
     public String getDescription() {
-        return "Checks for calls to updateGeometricState(), updateLogicalState() and updateModelBound().";
+        return NbBundle.getMessage(UpdateHint.class, "UpdateHint.description");
     }
 
     class MessagesFix implements EnhancedFix {
@@ -120,7 +121,7 @@ public class UpdateHint extends AbstractHint {
 
         @Override
         public String getText() {
-            return "Remove this call";
+            return NbBundle.getMessage(UpdateHint.class, "UpdateHint.fix-text");
         }
 
         @Override

+ 4 - 4
jme3-codepalette/nbproject/genfiles.properties

@@ -1,8 +1,8 @@
-build.xml.data.CRC32=3ed9eec8
+build.xml.data.CRC32=3b9099db
 build.xml.script.CRC32=27967d2c
-build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
[email protected]1.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=3ed9eec8
+nbproject/build-impl.xml.data.CRC32=3b9099db
 nbproject/build-impl.xml.script.CRC32=c9af9eda
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 8 - 0
jme3-codepalette/nbproject/project.xml

@@ -65,6 +65,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages/>
         </data>

+ 4 - 4
jme3-core-updatecenters/nbproject/genfiles.properties

@@ -1,8 +1,8 @@
-build.xml.data.CRC32=e145fa2a
+build.xml.data.CRC32=78701114
 build.xml.script.CRC32=cfa8d5c5
-build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
[email protected]1.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=e145fa2a
+nbproject/build-impl.xml.data.CRC32=78701114
 nbproject/build-impl.xml.script.CRC32=270846fb
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
+nbproject/[email protected]1.1

+ 8 - 0
jme3-core-updatecenters/nbproject/project.xml

@@ -30,6 +30,14 @@
                         <specification-version>8.39.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages/>
         </data>

二進制
jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/trustedcerts.jks


+ 82 - 7
jme3-core/nbproject/project.xml

@@ -71,7 +71,41 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.38.1</specification-version>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.bootstrap</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <implementation-version/>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.core.startup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <implementation-version/>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -97,6 +131,14 @@
                         <specification-version>1.40.1.2</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.5.1.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
                     <build-prerequisite/>
@@ -130,7 +172,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.60.1</specification-version>
+                        <specification-version>1.62.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -138,7 +180,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>0.138.2.32.2.25.8</specification-version>
+                        <specification-version>0.149.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.java.source.base</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>2.9.1.2.2.25.8.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -156,7 +206,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.60.1</specification-version>
+                        <specification-version>1.62.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -165,7 +215,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.47.1</specification-version>
+                        <specification-version>1.51.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -186,6 +236,15 @@
                         <specification-version>1.78.1.8</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectuiapi.base</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.83.1.9</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.settings</code-name-base>
                     <build-prerequisite/>
@@ -218,7 +277,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.35.1</specification-version>
+                        <specification-version>6.38.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -250,7 +309,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>8.12.1</specification-version>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -309,6 +376,14 @@
                         <specification-version>8.25.1</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.4.1</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.openide.windows</code-name-base>
                     <build-prerequisite/>

+ 67 - 0
jme3-core/src/com/jme3/gde/core/CopyTemplateHandler.java

@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2009-2016 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.gde.core;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.netbeans.api.templates.CreateDescriptor;
+import org.netbeans.api.templates.CreateFromTemplateHandler;
+import org.openide.filesystems.FileObject;
+
+/**
+ * This class will handle all .j3o templates to be simply copied.
+ * Starting with NetBeans 8.1 they changed the default action for templates to be using their template engine to parse them.
+ * This lead to Encoding Errors since our binary files are, well, binary.
+ * Unfortunately the only way to change this default behavior were switches inside the template or the Path (i.e. being placed under java)
+ * Also their COPY Action even relies on the StringBuffer, so same issue here.
+ * 
+ * See https://github.com/jMonkeyEngine/sdk/issues/33
+ * @author MeFisto94
+ */
[email protected](service=CreateFromTemplateHandler.class)
+public class CopyTemplateHandler extends CreateFromTemplateHandler {
+
+    @Override
+    protected boolean accept(CreateDescriptor cd) {
+        String ext = cd.getTemplate().getExt();
+        return ext.startsWith("j3") || ext.equals("blend"); /* Add your own binary extensions here !! */
+    }
+
+    @Override
+    protected List<FileObject> createFromTemplate(CreateDescriptor cd) throws IOException {
+        ArrayList<FileObject> list = new ArrayList<FileObject>();
+        FileObject newFile = cd.getTemplate().copy(cd.getTarget(), cd.getProposedName(), cd.getTemplate().getExt()); /* Proposed Name is getName() + default (when name is null) */
+        list.add(newFile);
+        return list;
+    }
+}

+ 32 - 3
jme3-core/src/com/jme3/gde/core/Installer.java

@@ -32,15 +32,20 @@
 package com.jme3.gde.core;
 
 import com.jme3.gde.core.scene.SceneApplication;
+import java.awt.Component;
+import java.awt.Frame;
 import java.io.File;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.swing.JFileChooser;
 import javax.swing.JPopupMenu;
+import javax.swing.filechooser.FileSystemView;
 import org.openide.filesystems.FileChooserBuilder;
 import org.openide.modules.ModuleInstall;
 import org.openide.modules.Places;
 import org.openide.util.NbBundle;
 import org.openide.util.NbPreferences;
+import org.netbeans.core.startup.*;
 
 /**
  * Manages a module's lifecycle. Remember that an installer is optional and
@@ -74,19 +79,43 @@ public class Installer extends ModuleInstall {
         //select project folder
         String projectDir = NbPreferences.forModule(Installer.class).get("projects_path", null);
         if (projectDir == null) {
-            javax.swing.JFileChooser fr = new javax.swing.JFileChooser();
-            javax.swing.filechooser.FileSystemView fw = fr.getFileSystemView();
+            JFileChooser fr = new JFileChooser();
+            FileSystemView fw = fr.getFileSystemView();
             projectDir = fw.getDefaultDirectory().getAbsolutePath();
             FileChooserBuilder builder = new FileChooserBuilder(projectDir);
             builder.setApproveText("Set Project Folder");
             builder.setTitle("Please select folder for storing projects");
             builder.setDirectoriesOnly(true);
-            File file = builder.showOpenDialog();
+            
+            Splash s = Splash.getInstance();
+            
+            Component comp = s.getComponent();
+            while (!(comp instanceof Frame)) { // Loop through the Hierarchy until you have the parental Frame
+                if (comp.getParent() != null)
+                    comp = comp.getParent();
+                else { // No Frame found in Hiarchy
+                    comp = null;
+                    break;
+                }
+            }
+            
+            if (comp != null)
+                comp.setVisible(false);
+            else
+                s.setRunning(false); // Workaround from the Workaround.
+           
+            File file = builder.showOpenDialog(); //*/  chooser.getSelectedFile();
             if (file != null) {
                 projectDir = file.getAbsolutePath();
                 NbPreferences.forModule(Installer.class).put("projects_path", projectDir);
             }
+                
+            if (comp != null)
+                comp.setVisible(true);
+            else
+                s.setRunning(true); // Unfortunately this has no effect
         }
+        
         //netbeans.default_userdir_root
         logger.log(Level.INFO, "Set project dir {0}", projectDir);
         System.setProperty("netbeans.projects.dir", projectDir);

+ 1 - 2
jme3-core/src/com/jme3/gde/core/appstates/NewSceneSaveNode.java

@@ -40,7 +40,6 @@ import java.io.IOException;
 import java.util.concurrent.Callable;
 import javax.swing.filechooser.FileFilter;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.awt.StatusDisplayer;
@@ -107,7 +106,7 @@ public class NewSceneSaveNode extends AbstractNode implements SaveCookie {
                         return null;
                     }
                 }
-                ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Saving File..");
+                ProgressHandle progressHandle = ProgressHandle.createHandle("Saving File..");
                 progressHandle.start();
                 try {
                     BinaryExporter exp = BinaryExporter.getInstance();

+ 1 - 3
jme3-core/src/com/jme3/gde/core/assets/AssetDataObject.java

@@ -35,7 +35,6 @@ import com.jme3.asset.AssetEventListener;
 import com.jme3.asset.AssetKey;
 import com.jme3.export.Savable;
 import com.jme3.export.binary.BinaryExporter;
-import com.jme3.gde.core.scene.ApplicationLogHandler.LogLevel;
 import com.jme3.gde.core.scene.SceneApplication;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -48,7 +47,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.apache.commons.beanutils.BeanUtils;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.netbeans.api.project.Project;
 import org.netbeans.api.project.ProjectManager;
 import org.openide.DialogDisplayer;
@@ -217,7 +215,7 @@ public class AssetDataObject extends MultiDataObject {
             return;
         }
         final Savable savable = this.savable;
-        ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Saving File..");
+        ProgressHandle progressHandle = ProgressHandle.createHandle("Saving File..");
         progressHandle.start();
         BinaryExporter exp = BinaryExporter.getInstance();
 //        FileLock lock = null;

+ 53 - 16
jme3-core/src/com/jme3/gde/core/assets/AssetsLookupProvider.java

@@ -32,6 +32,7 @@
 package com.jme3.gde.core.assets;
 
 import com.jme3.gde.core.j2seproject.ProjectExtensionManager;
+import com.jme3.gde.core.j2seproject.actions.UpgradeProjectWizardAction;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -40,6 +41,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.netbeans.api.project.Project;
 import org.netbeans.api.project.ProjectManager;
+import org.netbeans.api.project.ProjectUtils;
 import org.netbeans.modules.java.j2seproject.J2SEProject;
 import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator;
 import org.netbeans.spi.project.LookupProvider;
@@ -65,6 +67,7 @@ public class AssetsLookupProvider implements LookupProvider {
 
     private static final Logger logger = Logger.getLogger(AssetsLookupProvider.class.getName());
     private Project project;
+    private ProjectOpenedHook openedHook;
     public static final String[] keyList = new String[]{
         "assets.jar.name",
         "assets.folder.name",
@@ -104,6 +107,7 @@ public class AssetsLookupProvider implements LookupProvider {
                 String assetsFolderName = properties.getProperty("assets.folder.name", "assets");
                 if (prj.getProjectDirectory().getFileObject(assetsFolderName) != null) {
                     logger.log(Level.FINE, "Valid jMP project, extending with ProjectAssetManager");
+                    openedHook = genOpenedHook(project);
                     return Lookups.fixed(new ProjectAssetManager(prj, assetsFolderName), openedHook);
                 }
             } catch (Exception ex) {
@@ -117,25 +121,58 @@ public class AssetsLookupProvider implements LookupProvider {
 
         return Lookups.fixed();
     }
-    private ProjectOpenedHook openedHook = new ProjectOpenedHook() {
-        @Override
-        protected void projectClosed() {
-        }
+    
+    private ProjectOpenedHook genOpenedHook(final Project context) {
+        return new ProjectOpenedHook() {
+            @Override
+            protected void projectClosed() {
+            }
 
-        @Override
-        protected void projectOpened() {
-            if (project instanceof J2SEProject) {
-                EditableProperties properties = getProperties(project);
-                if (properties.getProperty("assets.folder.name") != null) {
-                    manager.checkExtension(project);
-//                    String version = properties.getProperty("jme.project.version");
-//                    if(version == null){
-//                        DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("This project is not compatible with the current SDK.",Message.ERROR_MESSAGE));
-//                    }
+            @Override
+            protected void projectOpened() {
+                if (context instanceof J2SEProject) {
+                    EditableProperties properties = getProperties(context);
+                    if (properties.getProperty("assets.folder.name") != null) {
+                        manager.checkExtension(context);
+
+                        String version = properties.getProperty("jme.project.version");
+                        String projectName = ProjectUtils.getInformation(context).getDisplayName();
+                        if (version == null) {
+                            if (UpgradeProjectWizardAction.isJME31(context)) { /* Upgrade project.properties */
+
+                                logger.log(Level.WARNING, "[" + projectName + "] Found 3.1 project, upgrading project.properties");
+
+                                FileObject prProp = context.getProjectDirectory().getFileObject("nbproject/project.properties");
+                                if (prProp != null && prProp.isValid()) {
+                                    FileLock lock = null;
+                                    try {
+                                        lock = prProp.lock();
+                                        InputStream in = prProp.getInputStream();
+                                        EditableProperties edProps = new EditableProperties(true);
+                                        edProps.load(in);
+                                        in.close();
+
+                                        edProps.setProperty("jme.project.version", "3.1"); // Silently accept them.
+                                        OutputStream out = prProp.getOutputStream(lock);
+                                        edProps.store(out);
+                                        out.close();
+                                    } catch (Exception e) {
+                                        logger.log(Level.WARNING, "Error when trying to write project.properties. Exception: {0}", e.getMessage());
+                                    } finally {
+                                        if (lock != null) {
+                                            lock.releaseLock();
+                                        }
+                                    }
+                                }
+                            } else {
+                                DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("The project \"" + projectName + "\" is not compatible with the current SDK.\nIt has to be updated before you can use it.\nRight Click on the Project and select \"Upgrade Project\" (You can choose to keep 3.0 compatibility!)", Message.ERROR_MESSAGE));
+                            }
+                        }
+                    }
                 }
             }
-        }
-    };
+        };
+    }
 
     public static EditableProperties getProperties(Project project) {
         EditableProperties props = new EditableProperties(true);

+ 1 - 2
jme3-core/src/com/jme3/gde/core/assets/ExternalChangeScanner.java

@@ -41,7 +41,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.filesystems.FileAttributeEvent;
@@ -124,7 +123,7 @@ public class ExternalChangeScanner implements AssetDataPropertyChangeListener, F
     }
 
     private void applyExternalData() {
-        ProgressHandle handle = ProgressHandleFactory.createHandle("Updating file data");
+        ProgressHandle handle = ProgressHandle.createHandle("Updating file data");
         handle.start();
         try {
             Spatial original = loadOriginalSpatial();

+ 4 - 3
jme3-core/src/com/jme3/gde/core/assets/SpatialAssetDataObject.java

@@ -40,7 +40,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
-import org.openide.filesystems.FileLock;
 import org.openide.filesystems.FileObject;
 import org.openide.loaders.DataObject;
 import org.openide.loaders.DataObjectExistsException;
@@ -101,7 +100,8 @@ public class SpatialAssetDataObject extends AssetDataObject {
             logger.log(Level.INFO, "Loaded asset {0}", getName());
             return spatial;
         } catch (Exception ex) {
-            Exceptions.printStackTrace(ex);
+            logger.log(Level.SEVERE, "An Exception has occured when trying to load asset {0}", getName());
+            logger.log(Level.SEVERE, ex.getMessage(), ex);
         }
         return null;
     }
@@ -137,7 +137,8 @@ public class SpatialAssetDataObject extends AssetDataObject {
                 logger.log(Level.WARNING, "New object {0} has no AssetData?", getName());
             }
         } catch (Exception ex) {
-            Exceptions.printStackTrace(ex);
+            logger.log(Level.SEVERE, "An Exception has occured when trying to save asset {0}", getName());
+            logger.log(Level.SEVERE, ex.getMessage(), ex);
         }
     }
 }

+ 1 - 2
jme3-core/src/com/jme3/gde/core/assets/actions/ConvertModel.java

@@ -38,7 +38,6 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.List;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.util.Exceptions;
 
 public final class ConvertModel implements ActionListener {
@@ -52,7 +51,7 @@ public final class ConvertModel implements ActionListener {
     public void actionPerformed(ActionEvent ev) {
         Runnable run = new Runnable() {
             public void run() {
-                ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Converting Model");
+                ProgressHandle progressHandle = ProgressHandle.createHandle("Converting Model");
                 progressHandle.start();
                 for (SpatialAssetDataObject spatialAssetDataObject : context) {
                     if (!(spatialAssetDataObject instanceof BinaryModelDataObject)) {

+ 1 - 4
jme3-core/src/com/jme3/gde/core/assets/actions/OpenModel.java

@@ -37,16 +37,13 @@ import com.jme3.gde.core.scene.SceneApplication;
 import com.jme3.gde.core.scene.SceneRequest;
 import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
 import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility;
-import com.jme3.gde.core.util.notify.NotifyUtil;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
-import org.openide.NotifyDescriptor.Confirmation;
 
 public final class OpenModel implements ActionListener {
 
@@ -64,7 +61,7 @@ public final class OpenModel implements ActionListener {
         Runnable call = new Runnable() {
 
             public void run() {
-                ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening Model");
+                ProgressHandle progressHandle = ProgressHandle.createHandle("Opening Model");
                 progressHandle.start();
                 try {
                     manager.clearCache();

+ 2 - 2
jme3-core/src/com/jme3/gde/core/editor/SceneEditorTopComponent.java

@@ -32,8 +32,8 @@ persistenceType = TopComponent.PERSISTENCE_ALWAYS)
 preferredID = "SceneEditorTopComponent")
 @Messages({
     "CTL_SceneEditorAction=SceneEditor",
-    "CTL_SceneEditorTopComponent=SceneEditor Window",
-    "HINT_SceneEditorTopComponent=This is a SceneEditor window"
+    "CTL_SceneEditorTopComponent=SceneEditor",
+    "HINT_SceneEditorTopComponent=Provides Tools to edit your Scene"
 })
 public final class SceneEditorTopComponent extends CloneableTopComponent {
 

+ 1 - 0
jme3-core/src/com/jme3/gde/core/filters/Bundle.properties

@@ -1,3 +1,4 @@
 CTL_FilterExplorerAction=FilterExplorer
 CTL_FilterExplorerTopComponent=FilterExplorer
+CTL_OpenFilterAction=Open Filter
 HINT_FilterExplorerTopComponent=The FilterExplorer provides an Overview over your current Filter

+ 26 - 11
jme3-core/src/com/jme3/gde/core/filters/FilterPostProcessorNode.java

@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  Copyright (c) 2009-2016 jMonkeyEngine
  *  All rights reserved.
  * 
  *  Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import javax.swing.Action;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
@@ -63,8 +65,9 @@ import org.openide.util.lookup.Lookups;
 public class FilterPostProcessorNode extends AbstractNode {
 
     private FilterDataObject dataObject;
-    private static Image smallImage = IconList.eyeOpen.getImage();
+    private final static Image smallImage = IconList.eyeOpen.getImage();
     private FilterPostProcessor fpp;
+    private static final Logger logger = Logger.getLogger(FilterPostProcessorNode.class.getName());
 
     public FilterPostProcessorNode(FilterDataObject dataObject) {
         super(new FilterChildren(dataObject), Lookups.singleton(new FilterIndexSupport()));
@@ -74,7 +77,6 @@ public class FilterPostProcessorNode extends AbstractNode {
         setName(dataObject.getName());
         getLookup().lookup(FilterIndexSupport.class).setFilterPostProcessorNode(this);
         ((FilterChildren) getChildren()).setFilterPostProcessorNode(this);
-
     }
 
     @Override
@@ -89,7 +91,9 @@ public class FilterPostProcessorNode extends AbstractNode {
 
     public FilterPostProcessor getFilterPostProcessor() {
         if (fpp == null) {
-            this.fpp = dataObject.loadAsset();
+            fpp = dataObject.loadAsset();
+            if (fpp == null)
+                logger.log(Level.SEVERE, "Cannot load Filter. Maybe it's not in the Asset Path?");
         }
         return fpp;
     }
@@ -130,7 +134,9 @@ public class FilterPostProcessorNode extends AbstractNode {
         SceneApplication.getApplication().enqueue(new Callable<Object>() {
 
             public Object call() throws Exception {
-                getFilterPostProcessor().addFilter(filter);
+                FilterPostProcessor fp = getFilterPostProcessor();
+                if (fp != null)
+                    fp.addFilter(filter);
                 return null;
             }
         });
@@ -142,7 +148,10 @@ public class FilterPostProcessorNode extends AbstractNode {
         SceneApplication.getApplication().enqueue(new Callable<Object>() {
 
             public Object call() throws Exception {
-                getFilterPostProcessor().removeFilter(filter);
+                FilterPostProcessor fp = getFilterPostProcessor();
+                if (fp != null)
+                    fp.removeFilter(filter);
+                
                 return null;
             }
         });
@@ -163,8 +172,8 @@ public class FilterPostProcessorNode extends AbstractNode {
     public Action[] getActions(boolean context) {
 //        return super.getActions(context);
         return new Action[]{
-            new NewFilterPopup(this)
-        };
+                    new NewFilterPopup(this)
+                };
     }
 
     public static class FilterChildren extends Children.Keys<Object> {
@@ -184,7 +193,9 @@ public class FilterPostProcessorNode extends AbstractNode {
         @Override
         protected void addNotify() {
             super.addNotify();
-            setKeys(createKeys());
+            List<Object> keys = createKeys();
+            if (keys != null)
+                setKeys(keys);
         }
 
         protected void doRefresh() {
@@ -201,7 +212,11 @@ public class FilterPostProcessorNode extends AbstractNode {
 
                     public List<Object> call() throws Exception {
                         List<Object> keys = new LinkedList<Object>();
-                        for (Iterator it = node.getFilterPostProcessor().getFilterIterator(); it.hasNext();) {
+                        FilterPostProcessor fp = node.getFilterPostProcessor();
+                        if (fp == null) /* e.g. Filter not in Asset Path */
+                            return null;
+                        
+                        for (Iterator it = fp.getFilterIterator(); it.hasNext();) {
                             Filter filter = (Filter) it.next();
                             keys.add(filter);
                         }
@@ -220,7 +235,7 @@ public class FilterPostProcessorNode extends AbstractNode {
         protected Node[] createNodes(Object t) {
             Filter filter = (Filter) t;
             //get JmeFilter, the only FilterNode spi
-            FilterNode di = Lookup.getDefault().lookup(FilterNode.class); 
+            FilterNode di = Lookup.getDefault().lookup(FilterNode.class);
             Node[] ret = di.createNodes(filter, dataObject, readOnly);
             return ret;
         }

+ 0 - 2
jme3-core/src/com/jme3/gde/core/filters/OpenFilterAction.java

@@ -38,7 +38,6 @@ import org.openide.awt.ActionID;
 import org.openide.awt.ActionReference;
 import org.openide.awt.ActionReferences;
 import org.openide.awt.ActionRegistration;
-import org.openide.util.NbBundle.Messages;
 
 @ActionID(category = "Filters",
 id = "com.jme3.gde.core.filters.OpenFilterAction")
@@ -46,7 +45,6 @@ id = "com.jme3.gde.core.filters.OpenFilterAction")
 @ActionReferences({
     @ActionReference(path = "Loaders/application/jme3filterpostprocessor/Actions", position = 10)
 })
-@Messages("CTL_OpenFilterAction=Open Filter")
 public final class OpenFilterAction implements ActionListener {
 
     private final FilterDataObject context;

+ 1 - 1
jme3-core/src/com/jme3/gde/core/filters/impl/NewBloomFilterAction.java

@@ -62,7 +62,7 @@ public class NewBloomFilterAction extends AbstractNewFilterWizardAction {
         WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
         // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
         wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
-        wizardDescriptor.setTitle("Your wizard dialog title here");
+        wizardDescriptor.setTitle("New Bloom Filter Wizard");
         Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
         dialog.setVisible(true);
         dialog.toFront();

+ 2 - 0
jme3-core/src/com/jme3/gde/core/icons/IconList.java

@@ -126,6 +126,8 @@ public class IconList {
             ImageUtilities.loadImageIcon("com/jme3/gde/core/icons/light.gif", false);
     public static ImageIcon mesh =
             ImageUtilities.loadImageIcon("com/jme3/gde/core/icons/mesh.gif", false);
+    public static ImageIcon motionEvent =
+            ImageUtilities.loadImageIcon("com/jme3/gde/core/icons/chimpanzee-sad.gif", false); // TODO: Find something better
     public static ImageIcon node =
             ImageUtilities.loadImageIcon("com/jme3/gde/core/icons/node.gif", false);
     public static ImageIcon emitter =

+ 1 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionManager.java

@@ -93,6 +93,7 @@ public class ProjectExtensionManager {
         this.extensionVersion = extensionVersion;
         this.extensionTargets = extensionTargets;
         this.extensionDependencies = extensionDependencies;
+        this.antTaskLibrary = antTaskLibrary;
     }
 
     public ProjectExtensionManager(String extensionName, String extensionVersion, String extensionTargets, String[] extensionDependencies) {

+ 6 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/Bundle.properties

@@ -0,0 +1,6 @@
+UpgradeProjectVisualPanel1.jRadioButton1.text=Keep 3.0 Compatibility (Partial Upgrade)
+UpgradeProjectVisualPanel1.jRadioButton2.text=Upgrade to 3.1
+UpgradeProjectVisualPanel1.jTextPane1.text=As software evolves, old files can get deprecated and need an overhaul.\nThis also happened to SDK Project Files as we moved from 3.0 to 3.1\nLuckily there is this upgrader, which will do all the work for you.\n\n\
+Note: In case of emergency, open "nbproject/project.properties" with Netbeans\nand click on the history button in the upper left corner.\nThere you can revert the changes.\n\n\
+There are two ways I can do the upgrade: I can do a partial upgrade, which means\nyour file will be marked as a 3.0 project and only backwards-compatible changes\nare applied. That way you won't be able to compile the project under 3.1,\nbut it will work under 3.0 (and stop the warnings in 3.1).\nUse this way if you manage your dependencies (libs)\nmanually or if you don't use the Netbeans' compile/deploy.\n\n\
+The other way is the simple upgrade: Your project will be upgraded to 3.1,\nhowever it won't be openable under 3.0 anymore.

+ 87 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel1.form

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <NonVisualComponents>
+    <Component class="javax.swing.ButtonGroup" name="buttonGroup1">
+    </Component>
+  </NonVisualComponents>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
+                  <Component id="jRadioButton1" pref="588" max="32767" attributes="0"/>
+                  <Component id="jRadioButton2" alignment="0" max="32767" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane1" pref="274" max="32767" attributes="0"/>
+              <EmptySpace type="separate" max="-2" attributes="0"/>
+              <Component id="jRadioButton1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jRadioButton2" min="-2" pref="17" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTextPane" name="jTextPane1">
+          <Properties>
+            <Property name="editable" type="boolean" value="false"/>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/jme3/gde/core/j2seproject/actions/Bundle.properties" key="UpgradeProjectVisualPanel1.jTextPane1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JRadioButton" name="jRadioButton1">
+      <Properties>
+        <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
+          <ComponentRef name="buttonGroup1"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/jme3/gde/core/j2seproject/actions/Bundle.properties" key="UpgradeProjectVisualPanel1.jRadioButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JRadioButton" name="jRadioButton2">
+      <Properties>
+        <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
+          <ComponentRef name="buttonGroup1"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/jme3/gde/core/j2seproject/actions/Bundle.properties" key="UpgradeProjectVisualPanel1.jRadioButton2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>

+ 93 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel1.java

@@ -0,0 +1,93 @@
+package com.jme3.gde.core.j2seproject.actions;
+
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import org.netbeans.api.project.Project;
+
+public final class UpgradeProjectVisualPanel1 extends JPanel {
+
+    private final Project context;
+    /**
+     * Creates new form UpgradeProjectVisualPanel1
+     */
+    public UpgradeProjectVisualPanel1(Project context) {
+        this.context = context;
+        initComponents();
+        
+        jRadioButton2.setSelected(true);
+    }
+
+    @Override
+    public String getName() {
+        return "Introduction";
+    }
+    
+    public boolean flatUpgrade() {
+        return (jRadioButton1.isSelected());
+    }
+    
+    public JRadioButton getRadioButton1() {
+        return jRadioButton1;
+    }
+    
+    public JRadioButton getRadioButton2() {
+        return jRadioButton2;
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        buttonGroup1 = new javax.swing.ButtonGroup();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        jTextPane1 = new javax.swing.JTextPane();
+        jRadioButton1 = new javax.swing.JRadioButton();
+        jRadioButton2 = new javax.swing.JRadioButton();
+
+        jTextPane1.setEditable(false);
+        jTextPane1.setText(org.openide.util.NbBundle.getMessage(UpgradeProjectVisualPanel1.class, "UpgradeProjectVisualPanel1.jTextPane1.text")); // NOI18N
+        jScrollPane1.setViewportView(jTextPane1);
+
+        buttonGroup1.add(jRadioButton1);
+        org.openide.awt.Mnemonics.setLocalizedText(jRadioButton1, org.openide.util.NbBundle.getMessage(UpgradeProjectVisualPanel1.class, "UpgradeProjectVisualPanel1.jRadioButton1.text")); // NOI18N
+
+        buttonGroup1.add(jRadioButton2);
+        org.openide.awt.Mnemonics.setLocalizedText(jRadioButton2, org.openide.util.NbBundle.getMessage(UpgradeProjectVisualPanel1.class, "UpgradeProjectVisualPanel1.jRadioButton2.text")); // NOI18N
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jScrollPane1)
+                    .addComponent(jRadioButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 588, Short.MAX_VALUE)
+                    .addComponent(jRadioButton2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 274, Short.MAX_VALUE)
+                .addGap(18, 18, 18)
+                .addComponent(jRadioButton1)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jRadioButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap())
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.ButtonGroup buttonGroup1;
+    private javax.swing.JRadioButton jRadioButton1;
+    private javax.swing.JRadioButton jRadioButton2;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JTextPane jTextPane1;
+    // End of variables declaration//GEN-END:variables
+}

+ 61 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel2.form

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <Properties>
+    <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+      <Dimension value="[600, 350]"/>
+    </Property>
+  </Properties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="jScrollPane1" max="32767" attributes="0"/>
+                  <Component id="jProgressBar1" alignment="0" pref="588" max="32767" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane1" pref="312" max="32767" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jProgressBar1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTextPane" name="jTextPane1">
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JProgressBar" name="jProgressBar1">
+    </Component>
+  </SubComponents>
+</Form>

+ 75 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectVisualPanel2.java

@@ -0,0 +1,75 @@
+package com.jme3.gde.core.j2seproject.actions;
+
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JTextPane;
+import org.netbeans.api.project.Project;
+
+public final class UpgradeProjectVisualPanel2 extends JPanel {
+    
+    Project context;
+    /**
+     * Creates new form UpgradeProjectVisualPanel2
+     */
+    public UpgradeProjectVisualPanel2(Project context) {
+        this.context = context;
+        initComponents();
+    }
+
+    @Override
+    public String getName() {
+        return "Converting the Project";
+    }
+    
+    public JTextPane getTextPane() {
+        return jTextPane1;
+    }
+    
+    public JProgressBar getProgressBar() {
+        return jProgressBar1;
+    }
+    
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jScrollPane1 = new javax.swing.JScrollPane();
+        jTextPane1 = new javax.swing.JTextPane();
+        jProgressBar1 = new javax.swing.JProgressBar();
+
+        setPreferredSize(new java.awt.Dimension(600, 350));
+
+        jScrollPane1.setViewportView(jTextPane1);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jScrollPane1)
+                    .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 588, Short.MAX_VALUE))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 312, Short.MAX_VALUE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap())
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JProgressBar jProgressBar1;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JTextPane jTextPane1;
+    // End of variables declaration//GEN-END:variables
+}

+ 215 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectWizardAction.java

@@ -0,0 +1,215 @@
+package com.jme3.gde.core.j2seproject.actions;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JComponent;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.modules.java.j2seproject.J2SEProject;
+import org.netbeans.spi.project.support.ant.EditableProperties;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.WizardDescriptor;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+import org.openide.filesystems.FileLock;
+import org.openide.filesystems.FileObject;
+import org.openide.util.NbBundle;
+
+// An example action demonstrating how the wizard could be called from within
+// your code. You can move the code below wherever you need, or register an action:
+// @ActionID(category="...", id="com.jme3.gde.core.j2seproject.actions.UpgradeProjectWizardAction")
+// @ActionRegistration(displayName="Open UpgradeProject Wizard")
+// @ActionReference(path="Menu/Tools", position=...)
+@ActionID(
+        category = "Project",
+        id = "com.jme3.gde.core.j2seproject.actions.UpgradeProjectWizardAction"
+)
+@ActionRegistration(
+        iconBase = "com/jme3/gde/core/icons/chimpanzee-smile.gif",
+        displayName = "#CTL_UpgradeProjectWizardAction"
+)
+@ActionReferences({
+    @ActionReference(path = "Menu/File", position = 1415),
+    @ActionReference(path = "Projects/org-netbeans-modules-java-j2seproject/Actions", position = 200)
+})
[email protected]("CTL_UpgradeProjectWizardAction=Upgrade Project")
+
+public final class UpgradeProjectWizardAction implements ActionListener {
+    private final Project context;
+    public final static Logger logger = Logger.getLogger(UpgradeProjectWizardAction.class.getName());
+    private boolean isValidProject = false;
+    
+    /**
+     * This is used for the actual conversion jme30<->jme31.
+     * It is also used to see whether a project is 3.0 or 3.1
+     */
+    public final static HashMap<String, String[]> libraries = new HashMap<String, String[]>() {{
+        put("${libs.jme3.classpath}",           new String[] {"${libs.jme3-core.classpath}"});
+        put("${libs.jme3-libraries.classpath}", new String[] {"${libs.jme3-desktop.classpath}",
+                                                "${libs.jme3-plugins.classpath}",
+                                                "${libs.jme3-effects.classpath}",
+                                                "${libs.jme3-networking.classpath}",
+                                                "${libs.jme3-jogg.classpath}",
+                                                "${libs.jme3-terrain.classpath}",
+                                                "${libs.jme3-lwjgl.classpath}", 
+                                                "${libs.jme3-bullet.classpath}",
+                                                "${libs.jme3-bullet-native.classpath}",
+                                                "${libs.jme3-niftygui.classpath}"});
+    }};
+    
+    public UpgradeProjectWizardAction(Project context) {
+        this.context = context;
+        
+        if (context instanceof J2SEProject) {
+             String assetsFolderName = getProperties(context).getProperty("assets.folder.name");
+             if (assetsFolderName == null)
+                 assetsFolderName = "assets";
+             
+                if (context.getProjectDirectory().getFileObject(assetsFolderName) != null) {
+                    isValidProject = true;// Valid JMP Project
+                }
+        }
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        if (context == null) {
+            DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("There is no project selected. Can't upgrade", NotifyDescriptor.Message.ERROR_MESSAGE));
+            return;
+        }
+        
+        if (!isValidProject) {
+            DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("The Project you selected isn't valid.\nMost likely it's no real JME Project but rather a usual Java Project.", NotifyDescriptor.Message.ERROR_MESSAGE));
+            return;
+        }
+        
+        if (isJME31(context)) {
+            DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Your Project is already 3.1 compliant. There is no need to upgrade it :)", NotifyDescriptor.Message.INFORMATION_MESSAGE));
+            return;
+        }
+        
+        List<WizardDescriptor.Panel<WizardDescriptor>> panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
+        panels.add(new UpgradeProjectWizardPanel1(context));
+        panels.add(new UpgradeProjectWizardPanel2(context));
+        String[] steps = new String[panels.size()];
+        for (int i = 0; i < panels.size(); i++) {
+            Component c = panels.get(i).getComponent();
+            // Default step name to component name of panel.
+            steps[i] = c.getName();
+            if (c instanceof JComponent) { // assume Swing components
+                JComponent jc = (JComponent) c;
+                jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
+                jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
+                jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
+                jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
+                jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
+            }
+        }
+        WizardDescriptor wiz = new WizardDescriptor(new WizardDescriptor.ArrayIterator<WizardDescriptor>(panels));
+        // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
+        wiz.setTitleFormat(new MessageFormat("{0}"));
+        wiz.setTitle("Upgrade jMonkeyPlatform Project");
+        if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
+            // do something
+        }
+    }
+    
+    /**
+     * Return the EditableProperties-Object of the <code>project.properties</code> file, but don't expand variables.
+     * @param project The Project who's Properties you want to change
+     * @return The Properties Object
+     */
+    public static EditableProperties getProperties(Project project) {
+        FileObject propFO = project.getProjectDirectory().getFileObject("nbproject/project.properties");
+        if (propFO != null && propFO.isValid()) {
+            FileLock lock = null;
+            try {
+                lock = propFO.lock();
+                InputStream in = propFO.getInputStream();
+                EditableProperties properties = new EditableProperties(true);
+                properties.load(in);
+                in.close();
+                return properties;
+            } catch (Exception e) {
+                logger.log(Level.WARNING, "Error when trying to open project.properties",e);
+            } finally {
+                if (lock != null) {
+                    lock.releaseLock();
+                }
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Determine if this Project is a JME 3.1 project or rather not.
+     * This is done by first looking for the <code>jme.project.version</code>, introduced in 3.1
+     * If the project doesn't contain that information, we compare the libraries the project depends on.
+     * @param project The Project to Test
+     * @param editableProperties The Properties which contain
+     * @return 
+     */
+    public static boolean isJME31(Project project)
+    {
+        EditableProperties properties = getProperties(project);
+        
+        String jmeVersion = properties.getProperty("jme.project.version");
+        if ("3.1".equals(jmeVersion))
+            return true;
+        
+        String javacClasspath = properties.getProperty("javac.classpath");
+        
+        if (javacClasspath != null) {
+            for (String[] s: libraries.values()) { /* 3.1 library names */
+                for (String t: s) { /* For each name */
+                    if (javacClasspath.contains(t))
+                            return true;
+                }
+            }
+            for (String s: libraries.keySet()) {
+                if (javacClasspath.contains(s)) /* 3.0 library name */
+                    return false;
+            }
+        }
+        
+        logger.log(Level.WARNING, "Could not determine whether the Project {0} is a JME 3.1 project or not. Assuming: No.", ProjectUtils.getInformation(project).getDisplayName());
+        return false;
+    }
+    
+    public static boolean isJME30(Project project)
+    {
+        EditableProperties properties = getProperties(project);
+        String jmeVersion = properties.getProperty("jme.project.version");
+        String javacClasspath = properties.getProperty("javac.classpath");
+        
+        if ("3.0".equals(jmeVersion))
+            return true;
+        
+        if (javacClasspath != null) {
+            for (String s: libraries.keySet()) {
+                if (javacClasspath.contains(s)) /* 3.0 library name */
+                    return true;
+            }
+            for (String[] s: libraries.values()) { /* 3.1 library names */
+                for (String t: s) { /* For each name */
+                    if (javacClasspath.contains(t))
+                            return false;
+                }
+            }
+        }
+        
+        logger.log(Level.WARNING, "Could not determine whether the Project {0} is a JME 3.0 project or not. Assuming: No.", ProjectUtils.getInformation(project).getDisplayName());
+        return false;
+    }
+}

+ 85 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectWizardPanel1.java

@@ -0,0 +1,85 @@
+package com.jme3.gde.core.j2seproject.actions;
+
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.project.Project;
+import org.openide.WizardDescriptor;
+import org.openide.WizardValidationException;
+import org.openide.util.HelpCtx;
+
+
+
+public class UpgradeProjectWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> {
+
+    public UpgradeProjectWizardPanel1(Project context) {
+        this.context = context;
+    }
+    
+    /**
+     * The reference to the project we work on.
+     */
+    private Project context;
+    
+    /**
+     * The visual component that displays this panel. If you need to access the
+     * component from this class, just use getComponent().
+     */
+    private UpgradeProjectVisualPanel1 component;
+
+    // Get the visual component for the panel. In this template, the component
+    // is kept separate. This can be more efficient: if the wizard is created
+    // but never displayed, or not all panels are displayed, it is better to
+    // create only those which really need to be visible.
+    @Override
+    public UpgradeProjectVisualPanel1 getComponent() {
+        if (component == null) {
+            component = new UpgradeProjectVisualPanel1(context);
+        }
+        return component;
+    }
+
+    @Override
+    public HelpCtx getHelp() {
+        // Show no Help button for this panel:
+        return HelpCtx.DEFAULT_HELP;
+        // If you have context help:
+        // return new HelpCtx("help.key.here");
+    }
+
+    @Override
+    public boolean isValid() {
+        // If it is always OK to press Next or Finish, then:
+        return true;
+        // If it depends on some condition (form filled out...) and
+        // this condition changes (last form field filled in...) then
+        // use ChangeSupport to implement add/removeChangeListener below.
+        // WizardDescriptor.ERROR/WARNING/INFORMATION_MESSAGE will also be useful.
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener l) {
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener l) {
+    }
+
+    @Override
+    public void readSettings(WizardDescriptor wiz) {
+        // use wiz.getProperty to retrieve previous panel state
+    }
+
+    @Override
+    public void storeSettings(WizardDescriptor wiz) {
+        UpgradeProjectVisualPanel1 pnl = (UpgradeProjectVisualPanel1)component;
+        wiz.putProperty("flatUpgrade", pnl.flatUpgrade());
+    }
+
+    @Override
+    public void validate() throws WizardValidationException
+    {
+        if (!component.getRadioButton1().isSelected() && !component.getRadioButton2().isSelected()) {
+            throw new WizardValidationException(null, " Select one Upgrade-Type!", null);
+        }
+    }
+    
+}

+ 259 - 0
jme3-core/src/com/jme3/gde/core/j2seproject/actions/UpgradeProjectWizardPanel2.java

@@ -0,0 +1,259 @@
+package com.jme3.gde.core.j2seproject.actions;
+
+import com.jme3.gde.core.j2seproject.ProjectExtensionManager;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.logging.Level;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.support.ant.EditableProperties;
+import org.openide.WizardDescriptor;
+import org.openide.WizardValidationException;
+import org.openide.filesystems.FileLock;
+import org.openide.filesystems.FileObject;
+import org.openide.util.HelpCtx;
+
+public class UpgradeProjectWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> {
+
+    public UpgradeProjectWizardPanel2(Project context) {
+        this.context = context;
+    }
+    
+    /**
+     * The reference to the project we work on.
+     */
+    private Project context;
+    Thread thread = null;
+    private boolean flatUpgrade;
+    
+    /**
+     * The visual component that displays this panel. If you need to access the
+     * component from this class, just use getComponent().
+     */
+    private UpgradeProjectVisualPanel2 component;
+
+    // Get the visual component for the panel. In this template, the component
+    // is kept separate. This can be more efficient: if the wizard is created
+    // but never displayed, or not all panels are displayed, it is better to
+    // create only those which really need to be visible.
+    @Override
+    public UpgradeProjectVisualPanel2 getComponent() {
+        if (component == null) {
+            component = new UpgradeProjectVisualPanel2(context);
+        }
+        return component;
+    }
+
+    @Override
+    public HelpCtx getHelp() {
+        // Show no Help button for this panel:
+        return HelpCtx.DEFAULT_HELP;
+        // If you have context help:
+        // return new HelpCtx("help.key.here");
+    }
+
+    @Override
+    public boolean isValid() {
+        return true;
+    }
+
+    @Override
+    public void validate() throws WizardValidationException {
+        if (thread == null || (thread.isAlive()))
+            throw new WizardValidationException(null, " Wait for the process to finish!", null);
+    }
+    
+    @Override
+    public void addChangeListener(ChangeListener l) {
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener l) {
+    }
+
+    @Override
+    public void readSettings(WizardDescriptor wiz) {
+        Object o = wiz.getProperty("flatUpgrade");
+        if (o != null) {
+            flatUpgrade = (Boolean)o;
+        } else {
+            UpgradeProjectWizardAction.logger.log(Level.WARNING, "Could not read Settings for Panel 2. Got a null Property.");
+        }
+        
+        thread = new Thread(new Runnable() { public void run() {doWork();}}, "Worker");
+        thread.start(); // Evil hack, but Wizards seem to be design to usually execute code AFTER they have been closed...
+    }
+
+    @Override
+    public void storeSettings(WizardDescriptor wiz) {
+    }
+    
+    public void doWork() {
+        final UpgradeProjectVisualPanel2 comp = component;
+        
+        FileObject prProp = context.getProjectDirectory().getFileObject("nbproject/project.properties");
+        if (prProp != null && prProp.isValid()) {
+            FileLock lock = null;
+            try {
+                lock = prProp.lock();
+                InputStream in = prProp.getInputStream();
+                EditableProperties edProps = new EditableProperties(true);
+                edProps.load(in);
+                in.close();
+                
+                setProgress(20);
+                boolean haveDeployment = false;
+                
+                if (flatUpgrade) {
+                    edProps.setProperty("jme.project.version", "3.0");
+                    setProgress(80);
+                } else {
+                    edProps.setProperty("jme.project.version", "3.1");
+                    setProgress(40);
+                    LinkedList<String> newClasspath = new LinkedList<String>(); /* We need this list so we can pass each new library as seperate String */
+                    /* Only then the EditableProperties will correctly split them along the lines. */
+                    boolean foundIt = false;
+                    
+                    for (String key : UpgradeProjectWizardAction.libraries.keySet()) { /* For each to-be-replaced-Library */
+                        for (String cP : edProps.getProperty("javac.classpath").split(":")) { /* For each classpath entry */
+                            if (cP.contains(key)) { /* This entry is our to-be-replaced */
+                                foundIt = true;
+                                newClasspath.addAll(Arrays.asList(UpgradeProjectWizardAction.libraries.get(key)));
+                                appendLog("Found pattern \"" + key + "\"!");
+                            }
+                        }
+                        if (!foundIt) {
+                            appendLog("Missing(!) pattern \"" + key + "\". Did you edit the file manually?");
+                        }
+                        foundIt = false;
+                    }
+                    
+                    setProgress(60);
+                    
+                    for (String cP : edProps.getProperty("javac.classpath").split(":")) {
+                        if (!UpgradeProjectWizardAction.libraries.containsKey(cP)) {
+                            appendLog("Found unknown classpath entry \"" + cP + "\". Passing through.");
+                            newClasspath.add(cP);
+                        }
+                    }
+                    
+                    for (int i = 0; i < newClasspath.size(); i++) { /* add ":"'s, which are needed for netbeans/ant */
+                        if (i != newClasspath.size() - 1) {
+                            String s = newClasspath.get(i);
+                            s += ":";
+                            newClasspath.set(i, s);
+                        }
+                    }
+                    
+                    edProps.setProperty("javac.classpath", newClasspath.toArray(new String[newClasspath.size()]));
+                    setProgress(60);
+                    
+                    if (edProps.getProperty("launch4j.exe.enabled") != null) {
+                        appendLog("Found Windows Deployment! Switching to newer system...");
+                        if (edProps.getProperty("launch4j.exe.enabled").equals("true")) {
+                            appendLog("Removing old ProjectExtension...");
+                            ProjectExtensionManager pem = new ProjectExtensionManager("launch4j", "v1.4", new String[]{"jar", "-launch4j-exe"});
+                            pem.setAntTaskLibrary("launch4j");
+                            try {
+                                pem.removeExtension(context);
+                            } catch (Exception e) {} // When launch4j ant task lib is missing...
+                            
+                            FileObject fo = context.getProjectDirectory().getFileObject("resources/launch4j");
+                            if (fo != null) {
+                                appendLog("Deleting resources/launch4j");
+                                fo.delete();
+                            }
+                            haveDeployment = true;
+                        }
+            
+                        edProps.setProperty("windows-x64.app.enabled", edProps.getProperty("launch4j.exe.enabled"));
+                        edProps.setProperty("windows-x86.app.enabled", edProps.getProperty("launch4j.exe.enabled"));
+                        edProps.remove("launch4j.exe.enabled");
+                    }
+                    if (edProps.getProperty("linux.launcher.enabled") != null) {
+                        appendLog("Found Linux Deployment! Switching to newer system...");
+                        if (edProps.getProperty("linux.launcher.enabled").equals("true")) {
+                            appendLog("Removing old ProjectExtension...");
+                            ProjectExtensionManager pem = new ProjectExtensionManager("linuxlauncher", "v1.1", new String[]{"jar", "-linux-launcher"});
+                            pem.removeExtension(context);
+                            
+                            haveDeployment = true;
+                        }
+                        edProps.setProperty("linux-x64.app.enabled", edProps.getProperty("linux.launcher.enabled"));
+                        edProps.setProperty("linux-x86.app.enabled", edProps.getProperty("linux.launcher.enabled"));
+                        edProps.remove("linux.launcher.enabled");
+                    }
+                    if (edProps.getProperty("mac.app.enabled") != null) {
+                        appendLog("Found Mac Deployment! Switching to newer system...");
+                        if (edProps.getProperty("mac.app.enabled").equals("true")) {
+                            appendLog("Removing old ProjectExtension...");
+                            ProjectExtensionManager pem = new ProjectExtensionManager("macapp", "v2.0", new String[]{"jar", "-mac-app"});
+                            pem.removeExtension(context);
+                            
+                            FileObject fo = context.getProjectDirectory().getFileObject("resources/macapp");
+                            
+                            if (fo != null) {
+                                appendLog("Deleting resources/macapp");
+                                fo.delete();
+                            }
+                            
+                            haveDeployment = true;
+                        }
+                        edProps.setProperty("macosx-x64.app.enabled", edProps.getProperty("mac.app.enabled"));// edProps.setProperty("linux-x86.app.enabled", edProps.getProperty("linux.launcher.enabled"));
+                        edProps.remove("mac.app.enabled");
+                    }
+                    
+                    setProgress(80);
+                }
+                
+                OutputStream out = prProp.getOutputStream(lock);
+                edProps.store(out);
+                out.close();
+                setProgress(90);
+                
+                if (haveDeployment) {
+                    appendLog("\nIMPORTANT: Open the Project Properties -> Application -> Desktop and uncheck/check the options and press Apply, if you encounter errors during clean & build.");
+                }
+                
+                setProgress(100);
+                if (flatUpgrade)
+                    appendLog("Chapeau! We are done :)\nNote: You can always re-run this Wizard, if you feel the need to Upgrade to 3.1");
+                else
+                    appendLog("\n\nChapeau! We are done :)\nNow that your project is 3.1 compatible, feel free to remove the NiftyGUI,\nBullet-Native, Terrain, etc. libraries to your liking, if you don't need them.\nThey were always automatically included in 3.0");
+                
+            } catch (Exception e) {
+                appendLog("Error when trying to write project.properties. Exception: " + e.getMessage());
+            } finally {
+                if (lock != null) {
+                    lock.releaseLock();
+                }
+                
+            }
+        } else {
+            setProgress(0);
+            appendLog("FATAL ERROR: Can't open nbproject/project.properties. The file is either inaccessible or not found.");
+        }
+    }
+    
+    private void appendLog(final String s) {
+        final UpgradeProjectVisualPanel2 comp = component;
+        SwingUtilities.invokeLater(new Runnable () {
+            public void run() {
+                comp.getTextPane().setText(comp.getTextPane().getText() + s + "\n");
+            }
+        });
+    }
+    
+    private void setProgress(final int value) {
+        final UpgradeProjectVisualPanel2 comp = component;
+        SwingUtilities.invokeLater(new Runnable () {
+            public void run() {
+                comp.getProgressBar().setValue(value);
+            }
+        });
+    
+    }
+}

+ 1 - 0
jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.java

@@ -234,6 +234,7 @@ private void noTexturebuttonActionPerformed(java.awt.event.ActionEvent evt) {//G
             selected = selected.substring(0, selected.lastIndexOf("/"));
 //            Texture tex = assetManager.loadTexture(selected);
 //            editor.setValue(tex);
+            editor.setValue(null); // Invalidate the old texture
             editor.setAsText(selected);
             return true;
         }

+ 13 - 2
jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java

@@ -24,7 +24,7 @@
  */
 package com.jme3.gde.core.scene;
 
-import com.jme3.app.Application;
+import com.jme3.app.LegacyApplication;
 import com.jme3.app.StatsView;
 import com.jme3.asset.AssetManager;
 import com.jme3.bullet.BulletAppState;
@@ -88,7 +88,7 @@ import org.openide.util.lookup.Lookups;
  * @author normenhansen
  */
 @SuppressWarnings({"unchecked", "rawtypes"})
-public class SceneApplication extends Application implements LookupProvider {
+public class SceneApplication extends LegacyApplication implements LookupProvider {
 
     private static final Logger logger = Logger.getLogger(SceneApplication.class.getName());
     private static boolean failMessageShown = false;
@@ -664,6 +664,17 @@ public class SceneApplication extends Application implements LookupProvider {
     public Node getGuiNode() {
         return guiNode;
     }
+    
+    /**
+     * Gets the RootNode of this Application.
+     * Warning: With great Power comes great responsibility ;)
+     * You shouldn't use this unless you exactly know about it's implications.
+     * Adding Spatials here won't make them Serialize into the .j3o file...
+     * @return 
+     */
+    public Node getRootNode() {
+        return rootNode;
+    }
 
     public AbstractCameraController getActiveCameraController() {
         return activeCamController;

+ 2 - 3
jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java

@@ -248,9 +248,8 @@ public class SceneToolController implements AppState {
             BoundingBox bbox = (BoundingBox) bound;
             Vector3f extent = new Vector3f();
             bbox.getExtent(extent);
-            WireBox wireBox = new WireBox();
-            wireBox.fromBoundingBox(bbox);
-            final Geometry selectionGeometry = new Geometry("selection_geometry_sceneviewer", wireBox);
+            final Geometry selectionGeometry = WireBox.makeGeometry(bbox);
+            selectionGeometry.setName("selection_geometry_sceneviewer");
             selectionGeometry.setMaterial(blueMat);
             selectionGeometry.setLocalTranslation(bbox.getCenter().subtract(geom.getWorldTranslation()));
             //Vector3f scale = new Vector3f(1,1,1);

+ 75 - 2
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java

@@ -114,7 +114,10 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
     }
 
     /**
-     * @param saveCookie the saveCookie to set
+     * Set this Node as read-only which means it cannot be deleted, cutted or copied.
+     * These are the actions you will see in the Context Menu of this Node.
+     * @param readOnly true/false
+     * @return Returns this Node for conveniance
      */
     public AbstractSceneExplorerNode setReadOnly(boolean readOnly) {
         this.readOnly = readOnly;
@@ -132,6 +135,16 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
         setSheet(createSheet());
     }
 
+    /**
+     * Create a Property to be used in the Properties Sheet. This is actually a helper method for you
+     * See {@link #makeProperty(java.lang.Object, java.lang.Class, java.lang.String, java.lang.String, java.lang.String) } to specify the getter/setter name
+     * 
+     * @param obj The object of which you want to edit the Properties
+     * @param returntype The Type (Class) of the getter/setter
+     * @param method The Name of the Getter/setter Methods (guesses for getValue() and setValue(value))
+     * @param name The Name of this Property.
+     * @return The created Property to use for set.put()
+     */
     protected Property<?> makeProperty(Object obj, Class<?> returntype, String method, String name) {
         Property<?> prop = null;
         try {
@@ -143,6 +156,18 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
         return prop;
     }
 
+    /**
+     * Create a Property to be used in the Properties Sheet. This is actually a helper method for you
+     * See {@link #makeEmbedProperty(java.lang.Object, java.lang.Class, java.lang.Class, java.lang.String, java.lang.String, java.lang.String) } if you get a ClassCastException.
+     * This happens when the getter/setter isn't part of obj but rather of a sub variable
+     * 
+     * @param obj The object of which you want to edit the Properties
+     * @param returntype The Type (Class) of the getter/setter
+     * @param method The name of the getter method
+     * @param setter The name of the setter method
+     * @param name The name for this Property. 
+     * @return The created Property to use for set.put()
+     */
     protected Property<?> makeProperty(Object obj, Class<?> returntype, String method, String setter, String name) {
         Property<?> prop = null;
         try {
@@ -159,10 +184,23 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
         return prop;
     }
 
+    /**
+     * Create a Property to be used in the Properties Sheet. This is actually a helper method for you
+     * See {@link #makeProperty(java.lang.Object, java.lang.Class, java.lang.String, java.lang.String, java.lang.String)  }
+     * Note: Embed is, when the Property isn't directly derived from obj but a getter.
+     * 
+     * @param obj The Object which contains this Property
+     * @param objectClass The Class of obj (when not "embed", we take the Nodes' Type here. So this is for "multi-level" properties)
+     * @param returntype The Type (Class) of the Property
+     * @param method The Getter Method
+     * @param setter The Setter Method (or null, if read only)
+     * @param name The Name to be displayed under Properties
+     * @return The created Property
+     */
     protected Property<?> makeEmbedProperty(Object obj, Class objectClass, Class returntype, String method, String setter, String name) {
         Property<?> prop = null;
         try {
-            if (readOnly) {
+            if (readOnly || setter == null) {
                 prop = new SceneExplorerProperty(objectClass.cast(obj), returntype, method, null);
             } else {
                 prop = new SceneExplorerProperty(objectClass.cast(obj), returntype, method, setter, this);
@@ -175,6 +213,17 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
         return prop;
     }
 
+    /**
+     * Simply adds all of c's fields as a property to the Set set.
+     * This is like the Sledge Hammer method for Properties.
+     * It will however fail when getters/setters are missing or not following the Convention.
+     * It will just skip those fields then.
+     * 
+     * @param c The Class of obj
+     * @param set The Properties Sheet-Set you want to add things to
+     * @param obj The Object for the properties
+     * @throws SecurityException 
+     */
     protected void createFields(Class<?> c, Sheet.Set set, Object obj) throws SecurityException {
         for (Field field : c.getDeclaredFields()) {
             PropertyDescriptor prop = PropertyUtils.getPropertyDescriptor(c, field);
@@ -183,12 +232,32 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
             }
         }
     }
+    
+    /**
+     * Adds all of c's fields as a property to the Set.
+     * See {@link #createFields(java.lang.Class, org.openide.nodes.Sheet.Set, java.lang.Object) }.
+     * Embed additionally takes the object's type over this Nodes. (Compare makeEmbedProperty and makeProperty)
+     * 
+     * @param c The Class to create Properties for
+     * @param set The Properties Sheet-Set you want to add things to
+     * @param obj The Object to take the Properties from
+     * @throws SecurityException 
+     */
+    protected void createEmbedFields(Class<?> c, Sheet.Set set, Object obj) throws SecurityException {
+        for (Field field : c.getDeclaredFields()) {
+            PropertyDescriptor prop = PropertyUtils.getPropertyDescriptor(c, field);
+            if (prop != null) {
+                set.put(makeEmbedProperty(obj, c, prop.getPropertyType(), prop.getReadMethod().getName(), prop.getWriteMethod().getName(), prop.getDisplayName()));
+            }
+        }
+    }
 
     @Override
     protected Sheet createSheet() {
         return Sheet.createDefault();
     }
     
+    @Override
     public void syncSceneData(float tpf) {
         //TODO: precache structure to avoid locks? Do it backwards, sending the actual bean value?
         for (PropertySet propertySet : getPropertySets()) {
@@ -201,6 +270,7 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
         }
     }
 
+    @Override
     public void propertyChange(final String type, final String name, final Object before, final Object after) {
         if (SceneExplorerProperty.PROP_USER_CHANGE.equals(type)) {
             fireSave(true);
@@ -212,12 +282,15 @@ public abstract class AbstractSceneExplorerNode extends AbstractNode implements
         }
     }
 
+    @Override
     public Class<?> getExplorerNodeClass() {
         return this.getClass();
     }
 
+    @Override
     public abstract Class getExplorerObjectClass();
 
+    @Override
     public Node[] createNodes(Object key, DataObject dataObject, boolean readOnly) {
         return new Node[]{Node.EMPTY};
     }

+ 2 - 2
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAnimControl.java

@@ -34,6 +34,7 @@ package com.jme3.gde.core.sceneexplorer.nodes;
 import com.jme3.animation.AnimControl;
 import com.jme3.gde.core.icons.IconList;
 import com.jme3.gde.core.properties.AnimationProperty;
+import com.jme3.gde.core.sceneexplorer.nodes.actions.ControlsPopup;
 import com.jme3.gde.core.sceneexplorer.nodes.actions.TrackVisibilityPopup;
 import java.awt.Image;
 import javax.swing.Action;
@@ -116,10 +117,9 @@ public class JmeAnimControl extends JmeControl {
 
     @Override
     public Action[] getActions(boolean context) {
-
-
         return new Action[]{
                     new TrackVisibilityPopup(this),
+                    new ControlsPopup(this),
                     SystemAction.get(DeleteAction.class)
                 };
     }

+ 5 - 3
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAnimation.java

@@ -277,10 +277,12 @@ public class JmeAnimation extends AbstractSceneExplorerNode {
         channel.setLoopMode(animLoopMode);
         if (animLoopMode == LoopMode.DontLoop) {
             control.addListener(new AnimEventListener() {
+                @Override
                 public void onAnimCycleDone(AnimControl ac, AnimChannel ac1, String animName) {
                     if (animName.equals(animation.getName())) {
                         if (playing) {
-                            control.clearChannels();
+                            ac.removeListener(this);
+                            control.clearChannels(); /* This will call onAnimCycleDone on control, thus we're first removing the Listener*/
                             channel = null;
                             jmeControl.setAnim(null);
                             java.awt.EventQueue.invokeLater(new Runnable() {
@@ -288,9 +290,9 @@ public class JmeAnimation extends AbstractSceneExplorerNode {
                                     stop();
                                 }
                             });
+                        } else {
+                            ac.removeListener(this);
                         }
-
-                        ac.removeListener(this);
                     }
                 }
 

+ 52 - 4
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeControl.java

@@ -32,7 +32,9 @@
 package com.jme3.gde.core.sceneexplorer.nodes;
 
 import com.jme3.gde.core.scene.SceneApplication;
+import com.jme3.gde.core.sceneexplorer.nodes.actions.ControlsPopup;
 import com.jme3.scene.Spatial;
+import com.jme3.scene.control.AbstractControl;
 import com.jme3.scene.control.Control;
 import java.io.IOException;
 import java.util.concurrent.Callable;
@@ -49,11 +51,10 @@ import org.openide.util.actions.SystemAction;
  * The JmeControl implements the Base Behavior of each Control-Node
  * @author MeFisto94
  */
-
-
 public abstract class JmeControl extends AbstractSceneExplorerNode {
 
     protected Control control;
+    
     public JmeControl() {
         super();
     }
@@ -72,10 +73,11 @@ public abstract class JmeControl extends AbstractSceneExplorerNode {
     
     @Override
     public Action[] getActions(boolean context) {
-        return new SystemAction[]{
+        return new Action[]{
                     //                    SystemAction.get(CopyAction.class),
                     //                    SystemAction.get(CutAction.class),
                     //                    SystemAction.get(PasteAction.class),
+                    new ControlsPopup(this),
                     SystemAction.get(DeleteAction.class)
                 };
     }
@@ -89,7 +91,7 @@ public abstract class JmeControl extends AbstractSceneExplorerNode {
     public void destroy() throws IOException {
         super.destroy();
         
-        if (control == null)
+        if (control == null || getParentNode() == null)
             return;
         
         final Spatial spat = getParentNode().getLookup().lookup(Spatial.class);
@@ -120,4 +122,50 @@ public abstract class JmeControl extends AbstractSceneExplorerNode {
             par.fireSave(modified);
         }
     }
+    
+    /**
+     * Enable/Disable the Control.
+     * This only works for extended AbstractControls!!
+     * Also see: {@link #isEnabled() }
+     * @param enabled Whether the Control should be enabled or disabled
+     * @return If we had success (false when an Exception occured or no {@link Control} assigned or not of type {@link AbstractControl} )
+     */
+    public boolean setEnabled(final boolean enabled) {
+        if (!isEnableable())
+            return false;
+        try {
+            SceneApplication.getApplication().enqueue(new Callable<Void>() {
+                public Void call() throws Exception {
+                    ((AbstractControl)control).setEnabled(enabled);
+                    return null;
+                }
+            }).get();
+           
+        } catch (InterruptedException ex) {
+            Exceptions.printStackTrace(ex);
+            return false;
+        } catch (ExecutionException ex) {
+            Exceptions.printStackTrace(ex);
+            return false;
+        }
+        
+        return true;
+    }
+    
+    /**
+     * Returns whether this Control is enabled or disabled.
+     * <b>Note:</b> When the Control doesn't extend AbstractControl, FALSE is returned.
+     * @return -
+     */
+    public boolean isEnabled()
+    {
+        if (isEnableable()) {
+            return ((AbstractControl)control).isEnabled();
+        } else
+            return false;
+    }
+    
+    public boolean isEnableable() {
+        return control instanceof AbstractControl;
+    }
 }

+ 0 - 1
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGenericControl.java

@@ -49,7 +49,6 @@ public class JmeGenericControl extends JmeControl {
     public JmeGenericControl(Control control, DataObject dataObject) {
         //TODO: lookup content! (control etc)
         super(dataObject);
-        this.control = control;
         addToLookup(this);
         addToLookup(control);
         this.control = control;

+ 197 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMotionEvent.java

@@ -0,0 +1,197 @@
+/*
+ *  Copyright (c) 2009-2016 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.gde.core.sceneexplorer.nodes;
+
+import com.jme3.cinematic.events.AbstractCinematicEvent;
+import com.jme3.cinematic.events.MotionEvent;
+import com.jme3.gde.core.icons.IconList;
+import java.awt.Image;
+import java.io.IOException;
+import org.openide.loaders.DataObject;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Node;
+import org.openide.nodes.Sheet;
+
+/**
+ * This is the SceneExplorer Node (Display Component Class) for Motion Events
+ *
+ * @author MeFisto94
+ */
[email protected](service = SceneExplorerNode.class)
+@SuppressWarnings({"unchecked", "rawtypes", "LeakingThisInConstructor"})
+public class JmeMotionEvent extends JmeControl {
+
+    private MotionEvent motionEvent;
+    private static Image smallImage = IconList.motionEvent.getImage();
+
+    public JmeMotionEvent() {
+        super();
+    }
+
+    public JmeMotionEvent(MotionEvent motionEvent, DataObject dataObject, JmeMotionPathChildren children) {
+        super(children, dataObject);
+        this.motionEvent = motionEvent;
+        control = motionEvent; // to have JmeControl work
+
+        lookupContents.add(this);
+        lookupContents.add(control);
+        lookupContents.add(children);
+        setName("MotionEvent");
+        setDisplayName("Motion Event");
+        children.setMotionEventControl(this);
+    }
+
+    @Override
+    public Image getIcon(int type) {
+        return smallImage;
+    }
+
+    @Override
+    public Image getOpenedIcon(int type) {
+        return smallImage;
+    }
+
+    /**
+     * This method creates the Property Sheet (i.e. the Contents for the
+     * Properties Editor).<br>See {@link AbstractNode#createSheet() } for more
+     * information
+     *
+     * @return The created Property Sheet
+     */
+    @Override
+    protected Sheet createSheet() {
+        Sheet sheet = new Sheet(); // Sheet.createDefault(); // Create a sheet with an empty set.
+
+        Sheet.Set abstractSet = Sheet.createPropertiesSet();
+        abstractSet.setName("AbstractCinematicEvent");
+        abstractSet.setDisplayName("Abstract Cinematic Event (Superclass)");
+        abstractSet.setShortDescription("This is the Superclass of MotionEvent: The Abstract Cinematic Event");
+
+        createFields(AbstractCinematicEvent.class, abstractSet, motionEvent);
+        sheet.put(abstractSet);
+
+        Sheet.Set set = Sheet.createPropertiesSet(); // Create a Properties "Set"/Entry for that Sheet. (A category so to say)
+        set.setDisplayName("Motion Event");
+        set.setShortDescription("These are the Properties of this Motion Event");
+        set.setName(MotionEvent.class.getName());
+
+        MotionEvent obj = motionEvent;
+        if (obj == null) {
+            return sheet;
+        }
+
+        createFields(MotionEvent.class, set, obj);
+        set.remove("Spatial"); // since we're a Control we don't set that value, we just belong to it.
+        set.remove("Path");
+
+        sheet.put(set);
+
+        return sheet;
+
+    }
+
+    /**
+     * Returns the class of the underlying Object of this Node.<br>This is how we
+     * are related to things found in the SceneGraph
+     *
+     * @return {@link Class}
+     */
+    @Override
+    public Class getExplorerObjectClass() {
+        return MotionEvent.class;
+    }
+
+    /**
+     * Returns the class of this Node
+     *
+     * @return {@link Class}
+     */
+    @Override
+    public Class getExplorerNodeClass() {
+        return JmeMotionEvent.class;
+    }
+
+    public MotionEvent getMotionEvent() {
+        return motionEvent;
+    }
+
+    @Override
+    public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) {
+        JmeMotionPathChildren children = new JmeMotionPathChildren();
+        children.setReadOnly(cookie);
+        return new org.openide.nodes.Node[]{new JmeMotionEvent((MotionEvent) key, key2, children).setReadOnly(cookie)}; // If we would return null here, we would have the JmeControl default (i.e. auto-exposure of properties, no icon but also no createSheet method)
+    }
+
+    public void refreshChildren() {
+        ((JmeMotionPathChildren) this.jmeChildren).refreshChildren(true);
+        for (Object node : getChildren().getNodes()) {
+            JmeMotionPath mPath = (JmeMotionPath) node;
+            ((JmeVector3fChildren) mPath.getChildren()).refreshChildren(true);
+        }
+    }
+
+    @Override
+    public void destroy() throws IOException {
+        for (Node n : getChildren().getNodes()) {
+            ((JmeMotionPath) n).destroy();
+        }
+        super.destroy();
+    }
+
+    public void setModified(boolean immediate) {
+        dataObject.setModified(immediate);
+    }
+
+    @Override
+    public boolean isEnableable() {
+        return true;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        if (motionEvent == null) {
+            return false;
+        } else {
+            return motionEvent.isEnabled();
+        }
+    }
+
+    @Override
+    public boolean setEnabled(boolean enabled) {
+        if (motionEvent == null) {
+            return false;
+        } else {
+            motionEvent.setEnabled(enabled);
+            return true;
+        }
+    }
+}

+ 332 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMotionPath.java

@@ -0,0 +1,332 @@
+/*
+ *  Copyright (c) 2009-2016 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.gde.core.sceneexplorer.nodes;
+
+import com.jme3.cinematic.MotionPath;
+import com.jme3.gde.core.icons.IconList;
+import com.jme3.gde.core.scene.SceneApplication;
+import com.jme3.gde.core.sceneexplorer.nodes.actions.MotionPathPopup;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Spline;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.Curve;
+import java.awt.Image;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.Action;
+import org.openide.actions.DeleteAction;
+import org.openide.actions.PropertiesAction;
+import org.openide.loaders.DataObject;
+import org.openide.nodes.Node;
+import org.openide.nodes.Sheet;
+import org.openide.util.actions.SystemAction;
+
+/**
+ * This Class actually represents the MotionPath in the SceneComposer.<br>
+ * It is added and managed by {@link JmeMotionPathChildren }
+ *
+ * @author MeFisto94
+ */
[email protected](service = SceneExplorerNode.class)
+@SuppressWarnings({"unchecked", "rawtypes", "OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
+public class JmeMotionPath extends AbstractSceneExplorerNode {
+
+    private static Image smallImage = IconList.chimpSmile.getImage();
+    private MotionPath motionPath;
+    private JmeMotionEvent motionEvent;
+    private float debugBoxExtents = 0.5f;
+    private Spatial spatial;
+
+    public JmeMotionPath() {
+    }
+
+    public JmeMotionPath(MotionPath motionPath, JmeMotionEvent parent, JmeVector3fChildren children) {
+        super(children);
+
+        this.motionPath = motionPath;
+        getLookupContents().add(motionPath);
+        getLookupContents().add(this);
+        getLookupContents().add(children);
+        super.setName("MotionPath");
+        super.setDisplayName("Motion Path");
+        children.setJmeMotionPath(this);
+        motionEvent = parent;
+
+        updateSpline(false);
+    }
+
+    //<editor-fold desc="Some Overrides for the Node">
+    @Override
+    public Image getIcon(int type) {
+        return smallImage;
+    }
+
+    @Override
+    public Image getOpenedIcon(int type) {
+        return smallImage;
+    }
+
+    @Override
+    public Action[] getActions(boolean context) {
+        MotionPathPopup m = new MotionPathPopup(this);
+        return new Action[]{
+            m.getAddAction(),
+            m,
+            SystemAction.get(PropertiesAction.class),
+            SystemAction.get(DeleteAction.class)
+        };
+    }
+    //</editor-fold>
+
+    @Override
+    protected Sheet createSheet() {
+        Sheet sheet = super.createSheet();
+        Sheet.Set set = Sheet.createPropertiesSet();
+        set.setDisplayName("Motion Path");
+        set.setName(MotionPath.class.getName());
+        set.setShortDescription("These are the Properties of the Motion Event's Motion Path");
+
+        if (motionPath == null) {
+            return sheet;
+        }
+
+        Property<?> prop = makeEmbedProperty(this, getExplorerNodeClass(), motionPath.getPathSplineType().getClass(), "getPathSplineType", "setPathSplineType", "PathSplineType");
+        prop.setShortDescription("Sets the Type of the Paths' Spline. This will define how the single waypoints are interpolated (linear, curvy)");
+        set.put(prop);
+
+        prop = makeEmbedProperty(this, getExplorerNodeClass(), float.class, "getCurveTension", "setCurveTension", "Curve Tension");
+        prop.setShortDescription("Sets the Curves' Tension. This defines how \"Curvy\" a curve will be. A tension of 0 would be completely linear.");
+        set.put(prop);
+
+        prop = makeProperty(motionPath, boolean.class, "isCycle", "setCycle", "Cycle?");
+        prop.setShortDescription("Should the Path be a Cycle? This essentially means it will be looped. (Starting from the beginning after we're finished)");
+        set.put(prop);
+
+        prop = makeProperty(motionPath, int.class, "getLength", null, "Path Length");
+        prop.setShortDescription("This is the total length this path has");
+        set.put(prop);
+
+        prop = makeEmbedProperty(motionPath, motionPath.getClass(), int.class, "getNbWayPoints", null, "Number of Waypoints");
+        prop.setShortDescription("Shows the Number of Waypoints this Path consists of");
+        set.put(prop);
+
+        sheet.put(set);
+
+        set = Sheet.createPropertiesSet();
+        set.setDisplayName("Motion Path SDK");
+        set.setName("MotionPathSDK");
+        set.setShortDescription("These are SDK-dependent Settings which have nothing to do with MotionEvent or MotionPath in the first place.");
+
+        prop = makeEmbedProperty(this, JmeMotionPath.class, float.class, "getDebugBoxExtents", "setDebugBoxExtents", "DebugBox Extents");
+        prop.setShortDescription("The DebugBox Extents defines how big the Debug Boxes (i.e. the Boxes you see for each Waypoint) are. Note: The BoxSize is 2 * extents");
+        set.put(prop);
+        sheet.put(set);
+
+        return sheet;
+    }
+
+    public MotionPath getMotionPath() {
+        return motionPath;
+    }
+
+    public JmeMotionEvent getMotionEvent() {
+        return motionEvent;
+    }
+
+    //<editor-fold desc="Properties Getter/Setter">
+    public float getDebugBoxExtents() {
+        return debugBoxExtents;
+    }
+
+    public void setDebugBoxExtents(float extents) {
+        debugBoxExtents = extents;
+
+        if (getChildren() != null) {
+            for (Node n : getChildren().getNodes()) {
+                if (n instanceof JmeVector3f) {
+                    ((JmeVector3f) n).updateBox();
+                } else {
+                    Logger.getLogger(JmeMotionPath.class.getName()).log(Level.WARNING, "JmeMotionPath has some unknown Children...");
+                }
+            }
+        }
+    }
+
+    public Spline.SplineType getPathSplineType() {
+        return motionPath.getPathSplineType();
+    }
+
+    public void setPathSplineType(Spline.SplineType sType) {
+        if (sType == Spline.SplineType.Nurb) {
+            Logger.getLogger(JmeMotionPath.class.getName()).log(Level.SEVERE, "Nurb Curves aren't possible at the moment (they require additional helper points). Reverting to Catmull..");
+            setPathSplineType(Spline.SplineType.CatmullRom);
+            return;
+        } else if (sType == Spline.SplineType.Bezier) {
+            Logger.getLogger(JmeMotionPath.class.getName()).log(Level.SEVERE, "Bezier Curves are bugged and crash the SDK. Reverting to Catmull..");
+            setPathSplineType(Spline.SplineType.CatmullRom);
+            return;
+        }
+
+        motionPath.setPathSplineType(sType);
+        updateSpline(true);
+    }
+
+    public float getCurveTension() {
+        return motionPath.getCurveTension();
+    }
+
+    public void setCurveTension(float f) {
+        motionPath.setCurveTension(f);
+        updateSpline(true);
+    }
+    //</editor-fold>
+
+    @Override
+    public Class getExplorerObjectClass() {
+        return MotionPath.class;
+    }
+
+    @Override
+    public Class getExplorerNodeClass() {
+        return JmeMotionPath.class;
+    }
+
+    @Override
+    public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) {
+        return null;
+    }
+
+    public void refreshChildren() {
+        ((JmeVector3fChildren) this.jmeChildren).refreshChildren(true);
+        updateSpline(false);
+    }
+
+    @Override
+    public void destroy() throws IOException {
+        for (Node n : getChildren().getNodes()) {
+            ((JmeVector3f) n).destroy();
+        }
+        super.destroy();
+        ((AbstractSceneExplorerNode) getParentNode()).refresh(true);
+    }
+
+    public void enableDebugShapes() {
+        for (Node n : getChildren().getNodes()) {
+            if (n instanceof JmeVector3f) {
+                ((JmeVector3f) n).attachBox(((JmeVector3f) n).spatial, this);
+            }
+        }
+
+        updateSpline(false);
+    }
+
+    public void disableDebugShapes() {
+        for (Node n : getChildren().getNodes()) {
+            if (n instanceof JmeVector3f) {
+                ((JmeVector3f) n).detachBox(((JmeVector3f) n).spatial);
+            }
+        }
+
+        if (spatial != null) {
+            final Spatial spat = spatial;
+            SceneApplication.getApplication().enqueue(new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    spat.removeFromParent();
+                    return null;
+                }
+            });
+        }
+
+    }
+
+    /**
+     * Call this to update the visual Spline.
+     *
+     * @param wasModified If the Spatial was Modified and hence the dirty-safe
+     * flag should be triggered (only false for the Constructors first
+     * initiation)
+     */
+    public void updateSpline(boolean wasModified) {
+        if (spatial != null) {
+            final Spatial spat = spatial;
+            SceneApplication.getApplication().enqueue(new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    spat.removeFromParent();
+                    return null;
+                }
+            });
+        }
+
+        Material m = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
+        m.setColor("Color", ColorRGBA.Red);
+        m.getAdditionalRenderState().setLineWidth(4f);
+
+        switch (motionPath.getPathSplineType()) {
+            case CatmullRom:
+                Geometry geo = new Geometry("Curve", new Curve(motionPath.getSpline(), 10));
+                geo.setMaterial(m);
+                spatial = geo;
+                break;
+
+            case Linear:
+                geo = new Geometry("Curve", new Curve(motionPath.getSpline(), 0));
+                geo.setMaterial(m);
+                spatial = geo;
+                break;
+
+            default:
+                geo = new Geometry("Curve", new Curve(motionPath.getSpline(), 10));
+                geo.setMaterial(m);
+                spatial = geo;
+                break;
+        }
+
+        final Spatial spat = spatial;
+        SceneApplication.getApplication().enqueue(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                SceneApplication.getApplication().getRootNode().attachChild(spat);
+                return null;
+            }
+        });
+
+        if (wasModified) {
+            motionEvent.setModified(true);
+        }
+    }
+}

+ 134 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMotionPathChildren.java

@@ -0,0 +1,134 @@
+/*
+ *  Copyright (c) 2009-2016 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.gde.core.sceneexplorer.nodes;
+
+import com.jme3.cinematic.MotionPath;
+import com.jme3.cinematic.events.MotionEvent;
+import com.jme3.gde.core.scene.SceneApplication;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import org.openide.loaders.DataObject;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+
+/**
+ * This Class is responsible for the management of all underlying MotionPaths as
+ * Nodes<br>
+ * (In fact we currently only have one possible MotionPath but we keep this to
+ * be consistent with JmeBoneChildren).<br>
+ * You have to ensure that you set the appropriate JmeMotionEvent for this class
+ * (this happens when JmeMotionEvent is creating it's Nodes)<br>
+ * It will use this class as Children (which are JmeMotionPaths)<br>
+ *
+ * @author MeFisto94
+ */
+public class JmeMotionPathChildren extends Children.Keys<Object> {
+
+    protected MotionPath path;
+    protected JmeMotionEvent jmeMotionEvent;
+    protected boolean readOnly = true;
+    protected HashMap<Object, Node> map = new HashMap<Object, Node>();
+    private DataObject dataObject;
+
+    public JmeMotionPathChildren() {
+    }
+
+    public JmeMotionPathChildren(JmeMotionEvent jmeMotionEvent, MotionPath path) {
+        this.path = path;
+        this.jmeMotionEvent = jmeMotionEvent;
+    }
+
+    public void refreshChildren(boolean immediate) {
+        setKeys(createKeys());
+        refresh();
+    }
+
+    public void setReadOnly(boolean cookie) {
+        this.readOnly = cookie;
+    }
+
+    @Override
+    protected void addNotify() {
+        super.addNotify();
+        setKeys(createKeys());
+    }
+
+    protected List<Object> createKeys() {
+        try {
+            return SceneApplication.getApplication().enqueue(new Callable<List<Object>>() {
+
+                @Override
+                public List<Object> call() throws Exception {
+                    List<Object> keys = new LinkedList<Object>();
+                    if (path != null) {
+                        keys.add(path);
+                    } else {
+                        keys.add(((MotionEvent) jmeMotionEvent.control).getPath());
+                    }
+
+                    return keys;
+                }
+            }).get();
+        } catch (InterruptedException ex) {
+            Exceptions.printStackTrace(ex);
+        } catch (ExecutionException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return null;
+    }
+
+    @Override
+    protected Node[] createNodes(Object key) {
+        if (key instanceof MotionPath) {
+            JmeVector3fChildren children = new JmeVector3fChildren();
+            children.setReadOnly(readOnly);
+            return new Node[]{new JmeMotionPath((MotionPath) key, jmeMotionEvent, children).setReadOnly(readOnly)}; // We pass null so we don't have another MotionPath als Child.
+        }
+        return new Node[]{Node.EMPTY};
+    }
+
+    public void setMotionEventControl(JmeMotionEvent jmeMotionEvent) {
+        this.jmeMotionEvent = jmeMotionEvent;
+    }
+
+    public DataObject getDataObject() {
+        return dataObject;
+    }
+
+    public void setDataObject(DataObject dataObject) {
+        this.dataObject = dataObject;
+    }
+}

+ 16 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeNode.java

@@ -34,6 +34,7 @@ package com.jme3.gde.core.sceneexplorer.nodes;
 import com.jme3.gde.core.icons.IconList;
 import com.jme3.gde.core.scene.SceneApplication;
 import com.jme3.gde.core.sceneexplorer.nodes.actions.AddUserDataAction;
+import com.jme3.gde.core.sceneexplorer.nodes.actions.ControlsPopup;
 import com.jme3.gde.core.sceneexplorer.nodes.actions.NewControlPopup;
 import com.jme3.gde.core.sceneexplorer.nodes.actions.NewLightPopup;
 import com.jme3.gde.core.sceneexplorer.nodes.actions.NewSpatialPopup;
@@ -166,6 +167,7 @@ public class JmeNode extends JmeSpatial {
                         new NewLightPopup(this),
                         Actions.alwaysEnabled(new AddUserDataAction(this), "Add User Data", "", false),
                         new ToolPopup(this),
+                        new ControlsPopup(this),
                         SystemAction.get(RenameAction.class),
                         SystemAction.get(CopyAction.class),
                         SystemAction.get(CutAction.class),
@@ -175,6 +177,20 @@ public class JmeNode extends JmeSpatial {
         }
     }
 
+    @Override
+    public void destroy() throws IOException {
+        super.destroy(); /* super has to be the first call, since it calls spatial.removeFromParent(); */
+        
+        for (org.openide.nodes.Node n : getChildren().getNodes()) {
+            n.destroy(); // Call destroy on children
+        }
+        
+        if (getParentNode() == null) {
+            setName("Scene"); /* You can't delete the rootNode but fake clearing it */
+        }
+        refresh(false);
+    }
+
     @Override
     public Class<?> getExplorerObjectClass() {
         return Node.class;

+ 4 - 1
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSkeletonControl.java

@@ -82,7 +82,10 @@ public class JmeSkeletonControl extends JmeControl {
         if (skeletonControl == null) {
             return sheet;
         }
-
+        Property<?> prop = makeProperty(skeletonControl, boolean.class, "isHardwareSkinningPreferred", "setHardwareSkinningPreferred", "Hardware Skinning");
+        prop.setShortDescription("This Preference enables/disables the usage of HW Skinning for this Skeleton. This will improve your performance and is the default, however you might want to turn it off to debug some failure. Also Note that setting it to true doesn't guarantee that HW Skinning is used, it has to be supported by the Platform.");
+        set.put(prop);
+        
         //  set.put(new AnimationProperty(animControl));
 
         sheet.put(set);

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