diff --git a/sdk/BasicGameTemplate/MANIFEST.MF b/sdk/BasicGameTemplate/MANIFEST.MF new file mode 100644 index 000000000..7e1ad4bb1 --- /dev/null +++ b/sdk/BasicGameTemplate/MANIFEST.MF @@ -0,0 +1 @@ +X-Comment: Created with jMonkeyPlatform diff --git a/sdk/BasicGameTemplate/build.xml b/sdk/BasicGameTemplate/build.xml new file mode 100644 index 000000000..01bd9fefe --- /dev/null +++ b/sdk/BasicGameTemplate/build.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + Builds, tests, and runs the project BasicGameTemplate. + + + + + diff --git a/sdk/BasicGameTemplate/master-application.jnlp b/sdk/BasicGameTemplate/master-application.jnlp new file mode 100644 index 000000000..49cbb12f2 --- /dev/null +++ b/sdk/BasicGameTemplate/master-application.jnlp @@ -0,0 +1,22 @@ + + + ${APPLICATION.TITLE} + ${APPLICATION.VENDOR} + + ${APPLICATION.DESC} + ${APPLICATION.DESC.SHORT} + + + + + + + + + + + + + + + diff --git a/sdk/BasicGameTemplate/nbproject/genfiles.properties b/sdk/BasicGameTemplate/nbproject/genfiles.properties new file mode 100644 index 000000000..5dadef18d --- /dev/null +++ b/sdk/BasicGameTemplate/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=94bf7c61 +build.xml.script.CRC32=79a29eb7 +build.xml.stylesheet.CRC32=958a1d3e@1.32.1.45 +# 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=94bf7c61 +nbproject/build-impl.xml.script.CRC32=0f295843 +nbproject/build-impl.xml.stylesheet.CRC32=f33e10ff@1.38.2.45 diff --git a/sdk/BasicGameTemplate/nbproject/project.properties b/sdk/BasicGameTemplate/nbproject/project.properties new file mode 100644 index 000000000..c819c258c --- /dev/null +++ b/sdk/BasicGameTemplate/nbproject/project.properties @@ -0,0 +1,77 @@ +application.title=MyGame +application.vendor=MyCompany +assets.jar.name=assets.jar +assets.excludes=**/*.mesh\.xml,**/*.skeleton\.xml,**/*.scene,**/*.material,**/*.obj,**/*.mtl,**/*.j3odata +assets.folder.name=assets +assets.compress=true +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/${application.title}.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +includes=** +jar.compress=false +javac.classpath=\ + ${libs.jme3.classpath}:\ + ${libs.jme3-libraries.classpath} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api" +jnlp.codebase.type=local +jnlp.descriptor=application +jnlp.enabled=false +jnlp.offline-allowed=false +jnlp.signed=false +main.class=mygame.Main +meta.inf.dir=${src.dir}/META-INF +manifest.file=MANIFEST.MF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${assets.folder.name} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src diff --git a/sdk/BasicGameTemplate/nbproject/project.xml b/sdk/BasicGameTemplate/nbproject/project.xml new file mode 100644 index 000000000..c95f6b19b --- /dev/null +++ b/sdk/BasicGameTemplate/nbproject/project.xml @@ -0,0 +1,13 @@ + + + org.netbeans.modules.java.j2seproject + + + BasicGameTemplate + + + + + + + diff --git a/sdk/BasicGameTemplate/src/mygame/Main.java b/sdk/BasicGameTemplate/src/mygame/Main.java new file mode 100644 index 000000000..09d7f0b46 --- /dev/null +++ b/sdk/BasicGameTemplate/src/mygame/Main.java @@ -0,0 +1,44 @@ +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 + * @author normenhansen + */ +public class Main extends SimpleApplication { + + public static void main(String[] args) { + Main app = new Main(); + app.start(); + } + + @Override + public void simpleInitApp() { + Box b = new Box(Vector3f.ZERO, 1, 1, 1); + Geometry geom = new Geometry("Box", b); + geom.updateModelBound(); + + Material mat = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md"); + mat.setColor("m_Color", ColorRGBA.Blue); + geom.setMaterial(mat); + + rootNode.attachChild(geom); + } + + @Override + public void simpleUpdate(float tpf) { + //TODO: add update code + } + + @Override + public void simpleRender(RenderManager rm) { + //TODO: add render code + } +} diff --git a/sdk/JME3TestsTemplate/build.xml b/sdk/JME3TestsTemplate/build.xml new file mode 100644 index 000000000..c1f098b99 --- /dev/null +++ b/sdk/JME3TestsTemplate/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + Builds, tests, and runs the project JME3TestsTemplate. + + + diff --git a/sdk/JME3TestsTemplate/nbproject/build-impl.xml b/sdk/JME3TestsTemplate/nbproject/build-impl.xml new file mode 100644 index 000000000..acc4402f2 --- /dev/null +++ b/sdk/JME3TestsTemplate/nbproject/build-impl.xml @@ -0,0 +1,880 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/JME3TestsTemplate/nbproject/genfiles.properties b/sdk/JME3TestsTemplate/nbproject/genfiles.properties new file mode 100644 index 000000000..fd4d19fd4 --- /dev/null +++ b/sdk/JME3TestsTemplate/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=0f706f4a +build.xml.script.CRC32=0b0b23c4 +build.xml.stylesheet.CRC32=28e38971@1.38.1.45 +# 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=0f706f4a +nbproject/build-impl.xml.script.CRC32=7c2e5d21 +nbproject/build-impl.xml.stylesheet.CRC32=f33e10ff@1.38.2.45 diff --git a/sdk/JME3TestsTemplate/nbproject/project.properties b/sdk/JME3TestsTemplate/nbproject/project.properties new file mode 100644 index 000000000..338ab493a --- /dev/null +++ b/sdk/JME3TestsTemplate/nbproject/project.properties @@ -0,0 +1,76 @@ +application.title=JME3TestsTemplate +application.vendor=jMonkeyEngine +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/JME3TestsTemplate.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +includes=** +jar.compress=false +javac.classpath=\ + ${libs.jme3.classpath}:\ + ${libs.jme3-libraries.classpath}:\ + ${libs.jme3-test-data.classpath} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api" +jnlp.applet.class=jme3test.awt.TestApplet +jnlp.applet.height=300 +jnlp.applet.width=300 +jnlp.codebase.type=local +jnlp.descriptor=application +jnlp.enabled=false +jnlp.offline-allowed=false +jnlp.signed=false +main.class=jme3test.TestChooser +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src diff --git a/sdk/JME3TestsTemplate/nbproject/project.xml b/sdk/JME3TestsTemplate/nbproject/project.xml new file mode 100644 index 000000000..f6e7a0c99 --- /dev/null +++ b/sdk/JME3TestsTemplate/nbproject/project.xml @@ -0,0 +1,13 @@ + + + org.netbeans.modules.java.j2seproject + + + JME3TestsTemplate + + + + + + + diff --git a/sdk/README.TXT b/sdk/README.TXT new file mode 100644 index 000000000..0885c29f7 --- /dev/null +++ b/sdk/README.TXT @@ -0,0 +1,41 @@ +What is the jMonkeyEngine SDK? +------------------------------ + +The jMonkeyEngine 3 SDK is a software development kit for Java 3-D game developers. +It contains the jMonkeyEngine3 library and the jMonkeyPlatform, a game development environment. +The jMonkeyEngine and the jMonkeyPlatform are platform-independent, open-source and free. + +This is an alpha release (May 2010). If you encounter any issues, please tell us! +http://www.jmonkeyengine.com/wiki/doku.php/report_bugs +We are looking forward to your feedback. + + +Starting the jMonkeyPlatform +---------------------------- + +Windows: Double-Click the "bin/jmonkeyplatform.exe" file + +Mac OS: Double-Click the "jmonkeyplatform.app" Application + +Linux: chmod u+x bin/jmonkeyplatform; ./bin/jmonkeyplatform & + + +Running jMonkeyEngine Demos +--------------------------- + +Choose File > New Project in the jMonkeyPlatform and create a "JME3 Tests" project. +Run the test project to see JME3 feature demos. +Browse the demo source code to learn from examples. + + +Creating 3-D Games with the jMonkeyPlatform +------------------------------------------- + +Using the jMonkeyPlatform is the easiest method to develop jMonkeyEngine-based 3-D games. +Choose File > New Project and create a "Base Game" project to get started. + +See the online Documentation for jMonkeyPlatform at +http://www.jmonkeyengine.com/wiki/doku.php/jme3:jmonkeyplatform + +Get jMonkeyEngine 3 tutorials at +http://www.jmonkeyengine.com/wiki/doku.php/jme3 diff --git a/sdk/ant-lib/ant-contrib.jar b/sdk/ant-lib/ant-contrib.jar new file mode 100644 index 000000000..ea817cd43 Binary files /dev/null and b/sdk/ant-lib/ant-contrib.jar differ diff --git a/sdk/ant-lib/ant-deb.jar b/sdk/ant-lib/ant-deb.jar new file mode 100644 index 000000000..4b239b3d8 Binary files /dev/null and b/sdk/ant-lib/ant-deb.jar differ diff --git a/sdk/ant-lib/ant-jme.jar b/sdk/ant-lib/ant-jme.jar new file mode 100644 index 000000000..2304eaea7 Binary files /dev/null and b/sdk/ant-lib/ant-jme.jar differ diff --git a/sdk/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/sdk/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties new file mode 100644 index 000000000..5ee096e19 --- /dev/null +++ b/sdk/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -0,0 +1,7 @@ +currentVersion=jMonkeyPlatform Alpha-4 +LBL_splash_window_title=Starting jMonkeyPlatform +SPLASH_HEIGHT=350 +SPLASH_WIDTH=500 +SplashProgressBarBounds=0,250,500,6 +SplashRunningTextBounds=0,235,497,12 +SplashRunningTextFontSize=12 diff --git a/sdk/branding/core/core.jar/org/netbeans/core/startup/frame.gif b/sdk/branding/core/core.jar/org/netbeans/core/startup/frame.gif new file mode 100644 index 000000000..015378c7a Binary files /dev/null and b/sdk/branding/core/core.jar/org/netbeans/core/startup/frame.gif differ diff --git a/sdk/branding/core/core.jar/org/netbeans/core/startup/frame32.gif b/sdk/branding/core/core.jar/org/netbeans/core/startup/frame32.gif new file mode 100644 index 000000000..bfcf30ec1 Binary files /dev/null and b/sdk/branding/core/core.jar/org/netbeans/core/startup/frame32.gif differ diff --git a/sdk/branding/core/core.jar/org/netbeans/core/startup/frame48.gif b/sdk/branding/core/core.jar/org/netbeans/core/startup/frame48.gif new file mode 100644 index 000000000..88748e9b6 Binary files /dev/null and b/sdk/branding/core/core.jar/org/netbeans/core/startup/frame48.gif differ diff --git a/sdk/branding/core/core.jar/org/netbeans/core/startup/splash.gif b/sdk/branding/core/core.jar/org/netbeans/core/startup/splash.gif new file mode 100644 index 000000000..5260f8d8b Binary files /dev/null and b/sdk/branding/core/core.jar/org/netbeans/core/startup/splash.gif differ diff --git a/sdk/branding/modules/ext/updater.jar/org/netbeans/updater/Bundle.properties b/sdk/branding/modules/ext/updater.jar/org/netbeans/updater/Bundle.properties new file mode 100644 index 000000000..ec17083e3 --- /dev/null +++ b/sdk/branding/modules/ext/updater.jar/org/netbeans/updater/Bundle.properties @@ -0,0 +1,21 @@ +UpdaterFrame.TextBackground_R=0 +UpdaterFrame.TextBackground_G=0 +UpdaterFrame.TextBackground_B=0 + +UpdaterFrame.TextForeground_R=255 +UpdaterFrame.TextForeground_G=255 +UpdaterFrame.TextForeground_B=255 + +UpdaterFrame.Background_R=0 +UpdaterFrame.Background_G=0 +UpdaterFrame.Background_B=0 + +UpdaterFrame.outerColor_R=28 +UpdaterFrame.outerColor_G=43 +UpdaterFrame.outerColor_B=29 + +UpdaterFrame.centerColor_R=85 +UpdaterFrame.centerColor_G=73 +UpdaterFrame.centerColor_B=16 + +UpdaterFrame.isGradient=false diff --git a/sdk/branding/modules/ext/updater.jar/org/netbeans/updater/resources/updatersplash.gif b/sdk/branding/modules/ext/updater.jar/org/netbeans/updater/resources/updatersplash.gif new file mode 100644 index 000000000..5fdcd3759 Binary files /dev/null and b/sdk/branding/modules/ext/updater.jar/org/netbeans/updater/resources/updatersplash.gif differ diff --git a/sdk/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/sdk/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties new file mode 100644 index 000000000..760c2931b --- /dev/null +++ b/sdk/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -0,0 +1,2 @@ +CTL_MainWindow_Title=jMonkeyPlatform Alpha-4 +CTL_MainWindow_Title_No_Project=jMonkeyPlatform Alpha-4 diff --git a/sdk/branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties b/sdk/branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties new file mode 100644 index 000000000..b2a54b4e7 --- /dev/null +++ b/sdk/branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties @@ -0,0 +1,2 @@ +LBL_Copyright=

The \u2018Core Team\u2019

\n

Kirill Vainer \u2018Momoko_Fan\u2019
Lead Programmer, jME3 Architect

\n

Erlend Sogge Heggen \u2018erlend_sh\u2019
Project Manager, Junior Webmaster

\n

Skye Book \u2018sbook\u2019
Project Manager, Senior Webmaster

\n

Normen Hansen \u2018normen\u2019
jMP architect & general integrations

\n

Ruth Kusterer \u2018Zathras\u2019
Head of wiki, Docs expert

\n

Copyright © 2010 jMonkeyEngine.\n
Please visit http://www.jmonkeyengine.com for more information.

+URL_ON_IMG=http://www.jmonkeyengine.com/ diff --git a/sdk/branding/modules/org-netbeans-modules-java-j2seproject.jar/org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.png b/sdk/branding/modules/org-netbeans-modules-java-j2seproject.jar/org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.png new file mode 100644 index 000000000..f67785a6e Binary files /dev/null and b/sdk/branding/modules/org-netbeans-modules-java-j2seproject.jar/org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.png differ diff --git a/sdk/build.xml b/sdk/build.xml new file mode 100644 index 000000000..62805dccd --- /dev/null +++ b/sdk/build.xml @@ -0,0 +1,265 @@ + + + + + + Builds the module suite jme-gde. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Setting implementation version for ${module_dir} to revision: ${svn.LastChangedRev} + + + + Removing implementation version for ${module_dir} from revision: ${svn.LastChangedRev} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +jMonkeyEngine 3 was rebuilt from the ground up to be a modern 3D game engine, +compatible with OpenGL 2.0 and above. +Its architecture is shader-based, making it fully capable of current and +next generation graphics standards. The jMonkeyPlatform gives you a complete IDE +for coding and for managing and creating game assets. + + + + diff --git a/sdk/debscripts/postrm b/sdk/debscripts/postrm new file mode 100755 index 000000000..a732bd889 --- /dev/null +++ b/sdk/debscripts/postrm @@ -0,0 +1,2 @@ +#!/bin/bash +rm -rf $HOME/.jmonkeyplatform diff --git a/sdk/harness/README b/sdk/harness/README new file mode 100644 index 000000000..7df5c0e5d --- /dev/null +++ b/sdk/harness/README @@ -0,0 +1,1284 @@ +INTRODUCTION +------------ + +This build harness permits modules outside of the netbeans.org CVS tree to be +built against a NetBeans-based application: the NB platform, the NB IDE, or any +derivative product. The semantics of configuration files is synchronized with +the NBM project type module, so that you can open any module in the NB IDE and +work with it naturally: build and test it using Ant, use Java code completion, +and so on. + +Questions and comments should go to: dev@openide.netbeans.org + +BASIC FILE LAYOUT +----------------- + +Within the netbeans.org CVS tree, modules are detected as projects of the "NBM" +(NetBeans module) type. The project directory may be top-level (e.g. "beans"), +second-level (e.g. "ant/project"), or third-level (e.g. +"objectbrowser/navigator/javanavigation"). The project.xml for the project must +specify + + org.netbeans.modules.apisupport.project + +to indicate that it is an NBM project, and the configuration must be + + + +Note that this schema is a change from the /2 schema used in NetBeans 5.0. +(/2 is still supported for compatibility.) +NetBeans 4.0 and 4.1 use schema /1 which is no longer supported. + +Outside of the netbeans.org CVS tree, modules can take two forms. They may be +marked with + + + +in which case they can build into a platform binary but not refer to any other +source modules. Or they may be marked with + + + +in which case they are contained within a module suite. The suite enumerates +modules it contains, and each module points back to the suite that contains it. + +The meaning of the project.xml elements, as well as property names in +project.properties and other files, will be discussed later. + +The project directory should contain "manifest.mf" (more on this later), +"build.xml" (more later), a directory "src" with the main package root of the +module's classes, optionally "test/unit/src" with unit tests, and perhaps some +other files. + +If there is a subdirectory "javahelp" it is used to keep JavaHelp documentation, +which will be built automatically. + +If there is a file "module-auto-deps.xml" it will automatically be used to +upgrade modules depending on you to new dependencies, as described in the +Modules API. + +STANDALONE MODULES: CONFIGURATION FILES +--------------------------------------- + +Standalone modules may keep configuration in several properties files, in the +following order of loading: + +${basedir}/nbproject/private/platform-private.properties +${basedir}/nbproject/platform.properties +${user.properties.file} +[definition of 'harness.dir' and 'netbeans.dest.dir' or 'cluster.path' based on value of ${nbplatform.active}] +${basedir}/nbproject/private/private.properties +${basedir}/nbproject/project.properties + +Projects generated by NB 6.5 and earlier: +----------------------------------------- +The properties 'harness.dir' and 'netbeans.dest.dir' must be defined by the +project. Usually this is accomplished by defining the property +'nbplatform.active' in platform.properties, and ${user.properties.file} +(normally build.properties in the user directory, usually defined in +platform-private.properties) can define properties like +'nbplatform.NAME.netbeans.dest.dir' (this would be used for 'netbeans.dest.dir' +in case ${nbplatform.active} had the value 'NAME'). + +Projects generated by NB 6.7 and later (for 6.7 platform): +---------------------------------------------------------- +6.7 and newer projects may be distinguished by the presence of 'cluster.path' +property in nbproject/platform.properties file or simply by the fact that an +attempt to build a standalone module without it results in error: + + 'You must specify path to 'platform' cluster in ${cluster.path} property.' + +In such case property 'cluster.path' must be defined by the project. It must +contain classpath-like list of absolute or relative paths to individual clusters +against which will be the module build. "Bare", i.e. not numbered cluster names +can be used, which simplifies later transitions to newer version of the +platform. Content of 'cluster.path' can also reference other properties defined +in the project, properties file generated by the IDE e.g uses property +'nbplatform.active.dir' pointing to root folder of specified active platform. +'nbplatform.active' is used like before. Properties 'netbeans.dest.dir', +'enabled.clusters' and 'disabled.clusters' *must not* be defined in the +projects. They would be ignored anyway so there is a dedicated check that +project is not trying to setup something that would not work anyway. + +For more info on uses of 'cluster.path' property and setting it in IDE, see +http://wiki.netbeans.org/DevFaqHowToReuseModules. + +MODULE SUITES: CONFIGURATION FILES +---------------------------------- + +Modules in a suite have a slightly more complicated list of properties files in +which they may keep configuration: + +${basedir}/nbproject/private/suite-private.properties +${basedir}/nbproject/suite.properties +${suite.dir}/nbproject/private/platform-private.properties +${suite.dir}/nbproject/platform.properties +${user.properties.file} +[definition of 'harness.dir' and 'netbeans.dest.dir' or 'cluster.path' based on value of ${nbplatform.active}] +${basedir}/nbproject/private/private.properties +${basedir}/nbproject/project.properties + +'suite.dir' is normally defined in suite-private.properties (or suite.properties +in case it is a relative path). platform-private.properties and +platform.properties are then used to define the NB platform in the same way as +for standalone modules. + +The suite itself (the project located in ${suite.dir}) can load properties from: + +${basedir}/nbproject/private/platform-private.properties +${basedir}/nbproject/platform.properties +${user.properties.file} +[definition of 'harness.dir' and 'netbeans.dest.dir' or 'cluster.path' based on value of ${nbplatform.active}] +${basedir}/nbproject/private/private.properties +${basedir}/nbproject/project.properties + +It must define a property 'modules' enumerating modules it contains (in path +format, with each entry being a module project directory). This is usually done +in project.properties, perhaps also with private.properties to help with +absolute paths. + +USING A RELATIVE PATH FOR THE PLATFORM WITH A MODULE SUITE +---------------------------------------------------------- + +Though not directly supported by the GUI, it is possible to set up a module +suite in such a way that the path to the NetBeans platform is given as relative, +and sharable in VCS. This may be helpfully especially for multi-developer teams +who frequently develop against new NetBeans builds (or build NetBeans from CVS +sources). You need to: + +1. Make sure that each module's suite.properties specifies 'suite.dir' as +relative to its base directory, not as a bare relative path, e.g. + + suite.dir=${basedir}/.. + +2. Edit the suite's platform.properties to give a fallback value for 'suite.dir' +(so the suite's own master build script can work), and define *both* +netbeans.dest.dir and harness.dir in terms of the suite directory, e.g.: + + suite.dir=${basedir} + + # for platform 6.7 and later, use: + # 'platform.base' is only a helper property, it has no meaning in harness + platform.base=${suite.dir}/../nb_sources/nbbuild/netbeans + cluster.path=${platform.base}/platform: + harness.dir=${platform.base}/harness + + # for platform 6.5 and earlier, use: + netbeans.dest.dir=${suite.dir}/../nb_sources/nbbuild/netbeans + harness.dir=${netbeans.dest.dir}/harness + +platform.properties need not define 'nbplatform.active' in this case. + +Relative-path source and Javadoc associations for the platform is not yet +supported in this scenario (#70876). Each developer with a checkout of the suite +may need to configure a platform (with an arbitrary name) in the NetBeans +Platform Manager dialog with a binary location matching the value you gave for +${netbeans.dest.dir}, and with source and/or Javadoc associations of their +choice. However, as a convenience, special associations may be predefined in the +IDE in the special case that the destination directory is the subsubdirectory +"nbbuild/netbeans" of a netbeans.org CVS checkout (i.e. if you build NetBeans +from sources and then build your suite against that). + +"CHAINING" SUITES (INTER-SUITE DEPENDENCIES HOWTO) +-------------------------------------------------- + +As of platform version 6.7, suite-chaining as described here is superseded by +using 'cluster.path' property, see previous chapters and developer FAQ +http://wiki.netbeans.org/DevFaqHowToReuseModules. For platform versions 6.5 +and older, read on. + +Suppose you have one platform P1, say the bare NetBeans Platform. Then you have +a module suite S1 with modules M1a...M1z which uses P1. Now it may happen that +you want another suite S2 with modules M2a...M2z to depend on S1 as well as P1. +This is possible, though not yet trivial to set up. Basically, you will make a +new platform P2 by building S1 + P1. Here's what you need to do in brief: + +1. Set up S1 with P1 in the normal way. + +2. Edit S1/build.xml to include a target to make a platform P2. For example: + + + + + + +where S1/nbproject/project.properties or S1/nbproject/private/private.properties +defines: + + p2=...path.../myplatform + +Note that the ZIP will currently contain S1's ${app.name} as its top-level dir, +so you can either move the unpacked files up one dir, or use the dir p2/s1name +as the actual platform location. + +As of NetBeans 6.0, you may simply run the 'create-platform' target in your suite's +build.xml, which will create a platform in ${dist.dir}/${app.name}. + +3. Now configure S2 to use P2 as its platform. If an absolute path, you can use +the Platform Manager, else for relative paths see the preceding section. + +(Setting harness.dir to ${netbeans.dest.dir}/harness will only work if P2 +includes a harness/ subdirectory, for example if S1 was configured to include +the harness cluster. Otherwise, try ${netbeans.home}/../harness, or any location +you prefer to keep a standard copy of the harness in.) + +4. To associate sources with binaries for P2, you will need to use the Platform +Manager. You can select multiple source associations. In this case, use a +netbeans.org CVS checkout or source download for the P1 (NetBeans platform) +portion of P2, and use S1 (the suite directory) for the M1a...M1z modules in P2. + +5. In an S2 module like M2a you should be able to depend on any module in P2, +including both NetBeans modules and modules from S1 like M1a. Code completion, +popup Javadoc, etc. should work if source associations have been correctly +configured in step #5. + +6. In case S1 was an application module with configured branding, you might wish +to use S1's branding in S2 rather than making a new app for S2. Or, in place of +a suite S2 you might have a standalone module M2. In either case, you can use +S1's branding by configuring nbproject/project.properties in S2 (or standalone +module M2): + + branding.token=s1 + branding.dir=none + +where 's1' was the branding token you chose for S1. This will permit Run, +Reload, etc. on S2 and its modules like M2a, or standalone module M2, to work +correctly. + +netbeans.org MODULES: CONFIGURATION FILES +----------------------------------------- + +Modules inside the netbeans.org CVS tree need not define a platform; it is +always "nbbuild/netbeans" in the CVS tree. They also do not have an explicit +harness; they use various files located in "nbbuild". Unlike external modules +which by default always use the cluster "devel", netbeans.org modules usually +specify a cluster in "nbbuild/cluster.properties" ("extra" by default). + +PLATFORM DEFINITIONS +-------------------- + +The file build.properties in the user directory is used to store all information +about NetBeans platforms. Each platform has an ID string; the default platform's +ID is 'default'. The available properties for each platform are: + +1. nbplatform.ID.netbeans.dest.dir (mandatory) - absolute path to the +destination directory (i.e. NetBeans platform installation). + +2. nbplatform.ID.harness.dir (mandatory) - path to the build harness. Normally +will be "${nbplatform.ID.netbeans.dest.dir}/harness". + +3. nbplatform.ID.sources (optional) - see next section. + +4. nbplatform.ID.javadoc (optional) - see next section. + +SOURCE AND JAVADOC ASSOCIATIONS +------------------------------- + +Modules inside the netbeans.org CVS tree need not do anything special to +associate sources with binaries (the module JAR files under "nbbuild/netbeans"); +it is automatic. Javadoc may be associated with an API-providing module just by +building its Javadoc (into "nbbuild/build/javadoc"), or by downloading the +NetBeans API Documentation module, which will cause 'nbplatform.default.javadoc' +to be defined in build.properties in the user directory (to the location of a +ZIP of Javadoc). + +For external modules, sources and Javadoc may be associated with the active +platform by defining in build.properties in the user directory these properties: + +1. nbplatform.ID.sources - an Ant-style path (e.g. ':' separated) containing +source roots you wish to associate with the binary modules in +${nbplatform.ID.netbeans.dest.dir}. Entries may be a checkout of the +netbeans.org CVS tree, or source roots of other module suites which are included +in the platform in binary form. Defining a source association permits you to +step through sources while debugging, use Go To Class, get popup Javadoc in code +completion, etc. + +2. nbplatform.ID.javadoc - a path containing roots of Javadoc for API-providing +modules in the platform. Useful in case you wish to get Javadoc in View | +Documentation Indices; or in the code completion popup (if you do not have +sources). Each root may be a directory or a ZIP file. Within a root, the API for +org.netbeans.modules.foo is expected to be inside the subdir named +"org-netbeans-modules-foo". + +For examples of complete and functioning "external" module suites, see +apisupport/project/test/unit/data/example-external-projects in netbeans.org +sources. + +FORMAT OF YOUR project.xml's MAIN CONFIGURATION SECTION +------------------------------------------------------- + +The format of project.xml is controlled by XML Schema. For the main section of +new modules, use: + + http://www.netbeans.org/ns/nb-module-project/3.xsd + +If you wish to edit project.xml by hand rather than using the IDE's GUI, you +should validate all changes against this schema. If using the IDE's XML text +editor, just type Alt-Shift-F9 to validate the current document. (Make sure the +file is valid BEFORE saving it, as the IDE will refuse to load a malformed +project.xml.) + +You must specify the "code name base" of your module. This is the value of +OpenIDE-Module in manifest.mf, *except* without any major release version (e.g. +"/1"). In the future OpenIDE-Module might be generated from this, but not yet. + + org.netbeans.modules.foo + +For external modules, you must specify either or +; for netbeans.org modules, you must not. See above discussion of +file layout. + +Specify your dependencies on other modules: + + + + + some.other.module + + + + + + + + + 1 + + 3.9 + + + + + + +In a you can also use just + + + +in place of , meaning to declare an implementation +dependency on another module. The actual version is taken directly from that +module's current JAR so you do not need to keep track of it. *Important*: if you +either *export* or *import* any implementation dependencies, you should probably +use spec.version.base (see below). + +Specify your test dependencies on other modules [since 5.0u2, requires /3 +schema]. The tags in project.xml are +described below: + + + + + + unit + + + + org.netbeans.modules.java.project + + + + + + + + + + +Source root for a test type: +{project.dir}/test/${test-type.name}/src + +{project.dir}/test/unit/src - source root for unit test + + +For example you have three modules with code name bases A,B,C. A has runtime +dependency on B, B on C. You want to add test dependencies to unit test type +of module D: + +Use case 1: Runtime dependency on module. + + + unit + + A + + + +Runtime classpath is D + A. +Compile classpath is D. + +Use case 2: Runtime dependency on a module and its recursive runtime classpath. + + + unit + + A + + + + +Runtime classpath is A + B + C + D. +Compile classpath is D. + +Use case 3: Compile and runtime dependency on a module its recursive runtime classpath. + + + unit + + A + + + + + +Runtime classpath is A + B + C + D. +Compile classpath is A + B + C + D. +Note one feature of recursive compile-time dependency: modules B and C are added +to compile classpath as well, even if A has only runtime dependency on B and B on C. + +Use case 4: Compile and runtime dependency on a module, its recursive runtime classpath +and tests. + + + unit + + A + + + + + + +Runtime classpath is A + B + C + D + A/test/unit. +Compile classpath is A + B + C + D + A/test/unit. + +Declare any public API/SPI packages you export: + + + org.netbeans.api.foo + org.netbeans.spi.foo + + +If you do not export any API, say so: + + + +If you export an API to selected modules only, you can use (NB 5.0+ only!): + + + org.netbeans.modules.brother + org.netbeans.modules.foo.spi + + +If you bundle a special library which you want to expose to modules depending on +you, you need not enumerate every package explicitly: + + + javax.foo + + +Exported implementation "APIs" do not need to be declared; anyone depending on +your module with an implementation dependency gets access to *all* your +packages. Be careful and avoid this situation whenever possible. + +If your module bundles one or more third-party libraries, declare them: + + + + ext/foolib.jar + + external/foolib.jar + + +You still need to separately copy the JAR to the output directory (see below). +This just declares that Class-Path in your module's manifest should be defined, +and adds a compile-time classpath entry for your module and modules depending on +it. + +If your bundled library is built from sources, just use + + + ext/foolib.jar + + +Sometimes a module will produce some extra JARs (in modules/ext/ for Class-Path, +in ant/nblib/, etc.), or will just need to have some extra sources for +miscellaneous purposes (e.g. custom Ant tasks). You can declare them, somewhat +similarly to how freeform projects permit compilation units to be declared; you +will still need to explicitly compile and JAR them in your build.xml. For +example, for in-IDE automatic Ant tasks you might use: + + + + antsrc + + ${ant.home}/lib/ant.jar:${openide.dir}/core/openide.jar + + build/antclasses + ${cluster}/ant/nblib/${code.name.base.dashes}.jar + + +Or for a Class-Path extension built from sources, you might use: + + + libsrc + + build/libclasses + ${cluster}/modules/ext/foolib.jar + + +A custom Ant task (or set of tasks) you use only during your own build might +look like: + + + antsrc + ${ant.home}/lib/ant.jar + build/antclasses + build/tasks.jar + + +Note that may contain Ant property references, so for a complex +classpath, define it once in project.properties and use that property in + as well as in your Ant script. + +In order for the IDE to recognize references to those classes defined in the +, you may also need add/modify your module's cp.extra +property to include the value specified in the element. + +AN IMPORTANT NOTE: CUSTOMIZATION OF BUILD SCRIPTS +------------------------------------------------- + +Harness scripts allow a great degree of customization in your project's build +script and properties files (see sections on properties and Ant targets +below). Due to open nature of Ant scripts (everything is public) special +attention must be paid to migrating customized build scripts to newer version of +harness. In order to avoid unexpected use of newer version of harness with new +IDE, make sure that your either define harness location explicitly via +harness.dir property or that you use harness supplied with NB platform you are +building against ('Harness supplied with Platform' option on Harness tab in +NetBeans Platform Manager). + +Of course sometimes you want to upgrade to newer version of harness. To minimize +the chances that it will break your (customized) build, follow these +simple rules: + + * Use only properties listed in the following sections and avoid overriding + those marked 'Do not override' or similarly. + * Depend on/override only targets listed in sections 'Targets available for + overriding...' below + * When overriding targets, use only pre- or post-hooks (described below) for + your code and call original target as a whole in 'depends' attribute of the + target. + +Note that even when sticking to these rules, there is always possibility that +migration to newer version of harness will break your build, especially when you +depend on some implementation details, like a property *not* being set in +particular internal target, concrete calling order of targets, etc. + +PROPERTIES WHICH MAY BE DEFINED IN YOUR project.properties +---------------------------------------------------------- + +If needed, these properties may also be defined in private.properties (to make +them applicable to only your own checkout of sources). Only selected properties +are listed here; others may be interpreted, but see the Ant script for details. + +Unless otherwise noted, properties listed here *are* available for use in +selected fields in project.xml, *are* available for use in your build.xml +(depend on some init target to make sure), and *are not* available for use when +defining other properties in project.properties (unless you defined them in +private.properties). + +app.icon.icns [since 6.9] - "${harness.dir}/etc/applicationIcon.icns" by default, +path to application's icon in Mac (.icns) format; used for creating ".app" +directory hierarchy in "build-mac" target. + +basedir - you cannot define this; it is always the project directory of the +module (as in any Ant script). Available in all other properties files. + +build.classes.dir - "build/classes", used to send compiled classes to. + +build.compiler.debug - default "true" to include debugging info when compiling +(needed if you want to step through sources). + +build.compiler.debuglevel - default "source,lines,vars" to include all debugging info. + +build.compiler.deprecation - default "true" to display deprecation warnings when +compiling. If you want to disable deprecations, it is recommended you use +private.properties: + + build.compiler.deprecation=false + +build.test.unit.classes.dir - "build/test/unit/classes", where unit tests are +compiled to. + +buildnumber - generated timestamp for use in +OpenIDE-Module-Implementation-Version (or OpenIDE-Module-Build-Version if +OpenIDE-Module-Implementation-Version was explicitly defined in the manifest). + +catalog.base.url [since 6.9] - distribution base for the suite modules NBMs +location for which the catalog is generated. Default is ".". + +cluster - cluster directory your module is to be built into. For netbeans.org +modules, this is a subdirectory of nbbuild/netbeans/; the subdirectory name is +defined automatically from nbbuild/cluster.properties, with a fallback to +"extra". For suite component modules, it defaults to +"${suite.dir}/build/cluster", though you could override it if you wanted (e.g. +in platform.properties); similarly, for standalone modules, it defaults to +"${basedir}/build/cluster". Available in project.properties for netbeans.org +modules only. + +code.name.base - your code name base as org.netbeans.modules.foo + +code.name.base.dashes - your code name base as org-netbeans-modules-foo + +code.name.base.slashes - ditto, as org/netbeans/modules/foo + +cp.extra - extra JARs you have to compile module sources against. Rarely needed +any more, but if you have defined extra source trees with , +it may be necessary to add/modify this value to include the value specified in +its element. + +extra.module.files - list of special files you build alongside your module JAR +which you want to register for update tracking and include in your NBM. +*Everything* you put into your cluster should be enumerated. Paths are relative +to the cluster directory. Ant-style patternsets (most simply a trailing slash) +are permitted if you can be sure no other modules' files would also match. +Example: + + extra.module.files=\ + ext/foolib.jar,\ + docs/FooAPI.zip,\ + SpecialThirdPartyTool1.0/ + +(You do *not* need to include: the module JAR itself; your JavaHelp JAR if you +build one; your module declaration file; any module-auto-deps.xml; an +ant/nblib/*.jar corresponding to your module; or any files in ${release.dir}. +These are all included by default.) + +foo/bar.dir - absolute path of cluster directory to which the netbeans.org +module "foo/bar" is built. Only defined for netbeans.org modules, and only if +foo/bar was *already* built before yours (specify ). +Available in project.properties. + +harness.dir - location of the build harness (for external modules). Usually +"${netbeans.dest.dir}/harness". + +is.autoload and is.eager - default false, but if true, make this module an +autoload or eager module. + +javac.compilerargs [since 5.0u1] - default none; additional arguments to pass +to the Java compiler, e.g. "-Xlint:unchecked". + +javac.source - default "1.4"; to use JDK 1.5 features like generics: + + javac.source=1.5 + +javac.target - default ${javac.source}; controls version of generated bytecode + +javadoc.apichanges - optional location of an API changes list. Currently for +netbeans.org modules only. + +javadoc.arch - optional location of an architecture XML description. Highly +recommended as it makes your module self-documenting. + + javadoc.arch=${basedir}/arch.xml + +javadoc.overview - optional location of a Javadoc overview page. Discouraged +since it disables the default content which links to various generated documents +which you would need to manually add to your own overview. + +javadoc.title - title for Javadoc build. Optional for external modules. +DEPRECATED since 5.0u1; taken from other module metadata. + +javahelp.base - "${code.name.base.slashes}/docs" by default; directory +containing your help set, under "javahelp/". + +javahelp.excludes - optionally, list of file name patterns to exclude from +JavaHelp search index construction. + +javahelp.jar - "modules/docs/${code.name.base.dashes}.jar". Do not override. +Constructed from ${javahelp.jar.basename} and ${javahelp.jar.dir}. + +javahelp.search - "JavaHelpSearch" by default; name of search database +directory, relative to your help set. Must match what your help set specifies. + +jhall.jar - for external modules, if you wish to build JavaHelp, you must define +the location of jhall.jar from the JavaHelp distribution, as this is needed to +run the search indexer. DEPRECATED since 5.0u1; the 5.0u1 harness now includes +jsearch-*.jar so you do not need to specify this property any longer. + +keystore - Key store for signing NBMs. A candidate for private.properties - you +do *not* want to share this file! Also ${nbm_alias} and ${storepass} are used in +the NBM signing process. + +license.file - optional. Location of license text to use when creating an NBM. +(External modules only.) + +manifest.mf - JAR manifest location. Avoid overriding. + +module.auto.deps.xml - "module-auto-deps.xml" in your project directory by +default. Optional configuration file. + +module.classpath - your main module source's compile-time classpath, according +to . Since 5.0u1 uses public-package-only JARs where +appropriate. + +module.run.classpath [since 5.0u1] - your main module source's run-time +classpath, according to . Similar to ${module.classpath} +except does not use public-package-only JARs; includes run-time-only +dependencies; and processes dependencies transitively. + +module.jar - location of module JAR relative to cluster directory. Do not +override directly; override ${module.jar.basename} (default +"${code.name.base.dashes}.jar") and/or ${module.jar.dir} (default "modules") if +necessary (not without a good reason!). + +module.jar.verifylinkageignores [since 6.0] - regexp pattern for class names +that are excluded from linkage check + +module.javadoc.packages - comma-separated list of packages to be included in +Javadoc. Defaulted according to or , but if +you used (or if you have not specified any public or friend +packages at all) you will need to specify it explicitly. + +nbm.distribution - optional URL to location where your NBM can be downloaded +from. + +nbm.executable.files [since 6.8] - comma- or space- separated list of patterns of +files relative to cluster directory for which executable permissions should be set +on Unix system when building the module and on NBM installation/update in runtime. + +nbm.homepage - optional URL to HTML homepage for background about the module. + +nbm.is.global - set to "true" if NBM cannot be installed in user directory. + +nbm.module.author - author info for an NBM. + +nbm.needs.restart - set to "true" if NBM cannot be installed (even for the first +time) without restarting the IDE. + +nbm.target.cluster [since 5.0u2] - allow to declare a target cluster where +install if NBM install globally. + +autoupdate.catalog.url - if you want to use module's or suite's update target +during build, you need to specify the URL of your NBMs catalog. + +nbplatform.active - optional name of a NB platform to build and run against. See +discussion above for details of how this is used. + +netbeans.dest.dir - [up to 6.5.1] absolute pathname of NB platform (or IDE or +whatever) that you are building your module against, and into which your module +will be built. Available in project.properties (and in all properties files for +netbeans.org modules). Specified folder must exist and must contain valid NB +platform. Do not define in suite modules if suite's platform.properties defines +"cluster.path" property. Also do not depend on this property to be defined, it +will not be in projects created with NB 6.7 or later. + + +netbeans.home - location of "platform*" cluster of the NetBeans IDE installation +you are running. *Only defined* when you run an Ant script *inside* the IDE. + +nbjdk.active [since 5.0u1] - name of a Java platform (JDK) to use when building +and running. Will try to load (e.g. from ${userdir}/build.properties, where Java +Platform Manager stores its information) the properties + + nbjdk.home=${platforms.${nbjdk.active}.home} + - JDK (not JRE!) home directory + nbjdk.bootclasspath=${platforms.${nbjdk.active}.bootclasspath} + - JRE JARs, e.g. rt.jar (default: ${nbjdk.home}/jre/lib/rt.jar) + nbjdk.java=${platforms.${nbjdk.active}.java} + - java executable (default: ${nbjdk.home}/bin/java) + nbjdk.javac=${platforms.${nbjdk.active}.javac} + - javac executable (default: ${nbjdk.home}/bin/javac) + nbjdk.javadoc=${platforms.${nbjdk.active}.javadoc} + - javadoc executable (default: ${nbjdk.home}/bin/javadoc) + +if they are not already defined. Uses to make , , +, , and use this JDK. Optional; if unset (or set to +'default'), will use the current VM's Java platform instead. Define in +platform.properties (in a standalone module, or in the suite for a suite component +module, or in nbbuild/user.build.properties for a netbeans.org module). You may +also define just ${nbjdk.home} directly, without using ${nbjdk.active}, if you do +not need to use the Java Platform Manager to set up the JDK definition. + +use.pack200 [since 6.9] - whether to Pack200 compress NBMs; default true. + +pack200.excludes [since 6.9] - comma- or space- separated list of patterns of +files relative to cluster directory for which pack200 compression should not be used +while creating NBMs. + +project.license [since 6.0] - license to use for newly created files in the project +(applies also to suites); default is 'cddl' for modules inside netbeans.org. + +release.dir - "${basedir}/release"; location of a directory full of files to +copy unmodified to the output cluster. Since 6.0 beta2 also applies to module +suite projects. DO NOT ATTEMPT to create files in this directory during the +build; it is ONLY for static content (versioned files present in a clean source +project). Dynamically generated cluster content should be placed directly in +${cluster} as part of a netbeans-extra target, and be sure to mention such files +in ${extra.module.files}. + +run.app.exe - "bin\netbeans.exe"; name of Windows launcher to start (inside +${netbeans.dest.dir}) if trying to run the application for interactive testing. +Only relevant if ${app.name} is unset. + +run.app.sh - "bin/netbeans"; same but for Unix (and Mac OS X). + +run.args.extra - empty; any added arguments to pass to the launcher. + +run.jdkhome - location of JDK to run application with for interactive testing. +Defaults to JDK the Ant script was using, or that selected by ${nbjdk.active}. +DEPRECATED - for compatibility only. Use ${nbjdk.active} instead. + +spec.version.base - this is a little subtle. If you export an implementation +dependency to other modules, *and/or* depend on one or more other modules using +implementation dependencies, you are advised to use this property *in place of* +writing OpenIDE-Module-Specification-Version explicitly in your manifest. It +should be a dotted number to serve as the base of a specification version; keep +the number of components *fixed* even if you branch the module, so e.g. in a +development version use + + spec.version.base=1.7.0 + +and if you need to increment this in a release branch use e.g. + + spec.version.base=1.7.1 + +The harness will automatically append integers to it as follows to create the +actual specification version: + +1. Your OpenIDE-Module-Implementation-Version, if specified and an integer. + +2. The OpenIDE-Module-Implementation-Version of modules you depend on using +implementation dependencies, if integers; ordered by alphabetizing the +dependencies. + +(Example: if you have impl version 3, and you depend on org.netbeans.modules.foo += 6 and org.netbeans.modules.bar = 7, your actual spec version would be +1.7.0.3.7.6.) + +This is very handy for Auto Update: whenever you or anyone else makes a change +to an implementation API, just increment the +OpenIDE-Module-Implementation-Version of the providing module. That module and +any modules depending on its API will get a higher +OpenIDE-Module-Specification-Version automatically, so the whole set of +interdependent modules can be published to users at once on an update center. + +src.dir - "src", module source directory. Avoid overriding. + +test.timeout [since 6.1] - timeout (in msec) for unit tests, default 600000 (10 +minutes). A test running longer than this will be halted. + +test.run.args [since 6.5] - general VM arguments to pass when running tests. +Defaults to just "-ea". + +test.config [since 6.5] - name of a test configuration to run, specifying a set +of unit and/or functional tests which should be run by the 'test' target. +Defaults to 'default'. ${test.config.NAME.includes} specifies the includes list +(format: classpath resources). The standard value of ${test.config.NAME.includes} +depends on NAME. In case of 'default', it includes every test ('**/*Test.class'). +In case of any other NAME the includes list is empty. +${test.config.NAME.excludes} (default '') specifies an excludes list. + +test.unit.cp.extra - any additional classpath you might need to compile your +unit tests. If left empty, you can compile against JUnit; the NB test extensions +in nbjunit.jar; your module; and anything your module compiled against (since +5.0u1, ${module.run.classpath}). As of 5.0u2 you can and should include other +modules in project.xml's but in earlier releases these must +be listed in this property. + + test.unit.cp.extra=\ + ${tools.jar}:\ + ${basedir}/lib/custom-junit-helpers.jar + +test.unit.run.cp.extra - any additional classpath you might need to *run* your +unit tests with (beyond what they are already compiled with). As of 5.0u2 you +can and should include other modules in project.xml's but in +earlier releases these must be listed in this property. + +test.unit.lib.cp - path to some basic libraries which can be used in unit tests: +junit.jar, nbjunit.jar, and insanelib.jar. Not needed for netbeans.org modules. +For external modules, may be needed if you do not have the junit and testtools +modules installed in the target platform *or* the developing IDE, and the target +platform is not inside a netbeans.org build tree (in nbbuild/netbeans). +DEPRECATED as of 6.5; even basic libraries should instead be declared as regular +test dependencies (they are now included in the harness cluster). + +test.unit.src.dir - "test/unit/src"; avoid overriding. + +test-unit-sys-prop. - will set a system property when running your +unit tests. + +test.dist.dir - directory with test distribution. + +test.unit.folder - output directory for tests of module. + +test.unit.out.folder - this property can be overriden when you want to change +test.unit.folder property. + +continue.after.failing.tests - controls behavior of running tests on all modules +in suite. Default value is "true", which causes suite.test target to continue +with another module even if tests in previous module failed. Set to "false" +in your suite's project.properties to force test target to stop after tests +in one module failed. In module project this controls whether test target +fails when tests fail (when set to "false" or unset) or succeeds even if +test failed (when set to "true"). + +extra.test.libs.dir - directory with extra libraries needed for test run. + +tools.jar [since 5.0u1] - set to location of tools.jar in active JDK. Useful in +case your module needs to compile against JDK-only classes. Meaningless on Mac +OS X. + +To support builds of JNLP-based applications additional properties may be used +or redefined in JNLP-related targets: + +jnlp.servlet.jar - must point to jnlp-servlet.jar as provided by JDK 5 in + the directory sample/jnlp/servlet/jnlp-servlet.jar if one wants to build + a packaged war file of JNLP version of your suite + +jnlp.dest.dir - the location where to generate the JNLP files and signed + jars. By default it is your ${suite.dir}/build/jnlp + +jnlp.master.dir - (category='private') location of a directory in which + to generate pieces of master JNLP file to be included in the resources + section. + +jnlp.signjar.alias - +jnlp.signjar.keystore - +jnlp.signjar.password - allow you to sign your app with your own private key, if + unspecified then a default keystore is generated. Nice for trying things for + the first time, but not for production, then you very likely want to generate + your key and set these properties +jnlp.signjar.vendor - you can override this to be the default dname for the keystore + +jnlp.platform.codebase - can point to a shared repository which can be generated + by ant -f nbbuild/build.xml build-jnlp. Then your WAR file will contain only + modules of your suite and platform modules will be referenced by the value of + this property. Sample values with prebuilt binaries (good for testing): +http://bits.netbeans.org/6.5/jnlp/ +http://bits.netbeans.org/6.7/fcs/jnlp/ +http://deadlock.netbeans.org/hudson/job/ide-jnlp/lastStableBuild/artifact/nbbuild/build/jnlp/ + +jnlp.indirect.jars [since 6.0] - optional pattern of JARs in the cluster to load + in JNLP mode even though they are not listed as Class-Path extensions of the + module JAR. The module ought not directly refer to classes in these JARs (it + could not do so in non-JNLP mode) but it may load them reflectively using + InstalledFileLocator using the same path in regular as in JNLP mode. Note that + the physical path on disk to the resulting JAR will not necessarily contain + the directory prefix that the JAR in the cluster uses, so do not expect that + jar.getParentFile() is meaningful. The implementation creates an empty JAR + entry META-INF/clusterpath/$path where $path is the ('/'-separated) path + within the cluster where the JAR would be found in a normal installation. + +jnlp.indirect.files [since 7.0M1] - optional pattern of files in the cluster to + load in JNLP mode. The module may load these files using InstalledFileLocator + using the same path in regular as in JNLP mode. Note that the physical path on + disk to the resulting file will not necessarily contain the directory prefix + that the file in the cluster uses, so do not expect that file.getParentFile() + is meaningful. The implementation creates a JAR entry META-INF/files/$path + where $path is the ('/'-separated) path within the cluster where the file + would be found in a normal installation. + +jnlp.verify.excludes - the default implementation of "jnlp" task in common.xml + does verification and compares that all files from module NBM are really + referenced from the JNLP file. Sometimes not all of them need to be, for + them you can put their full names (relative to your cluster root) into this + property and separate them by comma. + +jnlp.permissions - allows altering of the fragment in the resulting .jnlp file + that sets the permissions for individual modules. The default value is + <security><all-permissions/></security> when jnlp.sign.jars + is true, <security/> when jnlp.sign.jars is false. + If you want to change the default to something else please define the value + of the property. + +jnlp.sign.jars [since 6.0] - defaults to true. If set to false the jars + will not be signed, only the main (startup) jar. This should allow for + faster startup but might compromise JNLP security. Use with extreme care. + +jnlp.generate.versions [since 6.7] - Defaults to false, which means versioning + info is not generated (see + http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/downloadservletguide.html#resources). + If set true, build-jnlp target creates versioning info in jnlp descriptors and version.xml files. + This allows for incremental updates of Webstart applications, but requires download via + JnlpDownloadServlet (thus run-jnlp and debug-jnlp does not create versioning info even with this + property set to true). + +[XXX some of the above should be listed in "Suite Properties"] + + +TARGETS AVAILABLE FOR OVERRIDING IN YOUR build.xml +-------------------------------------------------- + +Obscure or mostly internal targets are skipped here, but again examine the +actual harness script if in doubt. If you want to keep the original +implementation and just add a before hook, try e.g. + + + + + + +(some original targets are projectized-common.* rather than harness.*). If you +want to add an after hook, try e.g. + + + + + +basic-init - define some properties such as file locations; enough to do a clean +at least. + +build-init - define more properties needed for compiling and other build tasks. + +clean - remove all build products: the "build" directory under your project +directory, and any files left in the build cluster (including +${extra.module.files}). + +compile - compile Java sources for the module. + +compile-single - compile selected Java sources (F9). + +compile-test-single - compile selected unit test classes (F9). + +debug - build module and then start target platform in debug mode. Use from +within the IDE (there is a context menu item for it) to debug the app. + +debug-fix-nb - loads a hotfix for a module class while debugging. Run -> Apply +Code Changes from the IDE. + +debug-fix-test-nb - same, for unit test classes. + +debug-test-single-nb - run one single unit test in the debugger (e.g. to see why +it is failing). Available from the IDE's menus. + +files-init - define list of files in the NBM fileset. Use ${extra.module.files} +rather than overriding this. + +init - all normal initialization. + +jar - build the module JAR. + +jar-prep - prepare to build the module JAR; define ${buildnumber}. + +javadoc - build module Javadoc. + +jnlp - generetes the JNLP component file for this module and all necessary + resources for it into ${jnlp.dest.dir} directory and also a fragment of + the master JNLP into ${jnlp.master.dir} + +javadoc-nb - same, and open it in a web browser (only from the IDE). Available +as Build -> Generate Javadoc. + +javahelp - build JavaHelp. + +nbm - build the NBM. You might override this to give a complex (multipart) +license text. Copy basic impl from common.xml and edit. + +netbeans - build everything needed for the NBM. Do not override; use +netbeans-extra instead. + +netbeans-extra - hook target: does nothing unless overridden, but called when +building a module. Override to insert any additional build tasks you need to do: +copying libraries to the cluster, etc. + +profile - used from inside the IDE (if the NetBeans profiler is installed) to +profile the entire application. + +profile-test-single-nb - run one unit test under the profiler. Available from the +IDE's menus if the NetBeans profiler is installed. + +release - copies contents of ${release.dir} to ${cluster}. + +reload - reloads the module in the target IDE/app to try out changes interactively. + +reload-in-ide - reloads the module in the current IDE to try out changes +interactively. Only available when run from inside NetBeans. Use with care. + +run - build module and then run application interactively. Only for external +modules. Either way, available from context menu in Projects tab. + +test - run all unit tests for the module. Run -> Test... in the IDE. + +test-generate-html [since 6.5 M2] - can be used after test target to generate +test reports in html. + +test-build - build unit tests for the module. + +test-init - define properties used for building and running unit tests. + +test-preinit - I'm not sure, actually. + +test-single - run a selected unit test only. Available in the IDE's menus. + +testuserdir-delete - deletes just the testing user directory (if not currently in use). + +verify-class-linkage [since 5.0u1] - checks for possible linkage errors in your module +and its Class-Path extensions. + +SUITE PROPERTIES +---------------- + +Some properties are shared with module projects, such as ${cluster}. + +app.name - filename of application launchers to create, suite name to create, +etc. + +app.version - version of the application, used in building the MacOS application +bundle for example. (Since 6.0 beta2) + +app.conf - location of an alternative configuration file. If not specified, +default one from harness/etc/app.conf is taken (Since 6.9) + +branding.dir (default "${suite.dir}/branding") - directory containing branding +overrides. + +branding.token - optional token defining an application branding. + +enabled.clusters - comma-separated list of cluster names in the target platform +(e.g. "platform") which should be included in the application. Should be stored +in platform.properties, not project.properties. Available since 5.0u1. Since 6.5, +can elide version numbers from the end, e.g. just "platform" suffices. + +disabled.clusters - comma-separated list of cluster names in the target platform +(e.g. "ide") which should be completely excluded from the application. +DEPRECATED since 5.0u1 in favor of ${enabled.clusters} and ignored if that is nonempty. + +disabled.modules - comma-separated list of code name bases of modules in the +target platform (e.g. "org.netbeans.modules.autoupdate") which should be +excluded from the application. There is no need to specify modules already +excluded by ${disabled.clusters} (if used) or by modules from clusters not included +in ${enabled.clusters}. Since 5.0u1, should be stored in platform.properties, +not project.properties. + +dist.dir - directory (if not 'dist') to place the final application in. Since 6.1. + +modules - list of contained modules. Path format; entries resolved against the +suite directory as needed. + +jnlp.codebase [since 5.0u1] - in case one wants to build a static repository not +packaged in a WAR file, one needs to pass in the full URL for it. By default it +is specified as "$$codebase" and replaced dynamically by the servlet packaged in +the WAR file. + + +TARGETS AVAILABLE FOR OVERRIDING IN YOUR SUITE build.xml +-------------------------------------------------- + +-init - set up properties. Most importantly, ${modules.sorted} contains a list +of absolute path names to the base directories of the modules in the suite, +topologically sorted by build order; suitable for use with , for +example. Some other basic properties like ${netbeans.dest.dir} will also be +defined. + +branding - building branding JARs, if applicable. Example: if ${branding.token} +is "foo", then a file such as + + ${branding.dir}/modules/org-netbeans-modules-x.jar/org/netbeans/modules/x/resources/Bundle.properties + +will be packed into + + ${cluster}/modules/locale/org-netbeans-modules-x_foo.jar!/org/netbeans/modules/x/resources/Bundle_foo.properties + +build - build all suite modules. + +build-jnlp - builds a JNLP WAR file from your application suitable for +publishing in a Java EE container. + +build-mac [since 5.0u2] - creates a Mac OS X application. + +build-zip - builds a ZIP file containing your application including launchers. + +clean - clean everything. + +debug - like run, but run in the JPDA debugger. (Only available from inside the +IDE.) + +debug-jnlp - starts debuging of your JNLP application (works only from NetBeans IDE) + +nbms [since 5.0u1] - creates NBMs for all modules in the suite, and generates +an XML descriptor listing them suitable for use from Auto Update. + +profile - used from inside the NetBeans IDE to profile the entire suite + +run - start application for testing. + +run-jnlp - executes your JNLP application (currently from local files) + +test - run all module unit tests. Since NetBeans 6.8 runs tests of all suite modules +by default, even if some of them fails and target succeeds regardless of test status. +When property 'continue.after.failing.tests' is set to 'false', this target fails +immediately after tests in some module fail and does not continue testing the rest +of the suite (this was the default up to version 6.7). + +testuserdir-delete - deletes just the testing user directory (if not currently in use). + +CONTENTS OF YOUR manifest.mf +---------------------------- + +This file is just a prototype of the module JAR manifest, as described in the +Modules API. It must contain the attribute OpenIDE-Module and is strongly +encouraged to contain also OpenIDE-Module-Localizing-Bundle; other attributes +are generally optional. + +Several attributes in the main section should *not* be written into this file as +they are automatically generated during the build: + + Class-Path + OpenIDE-Module-Build-Version + OpenIDE-Module-Friends + OpenIDE-Module-Implementation-Version (unless you are exporting an impl API) + OpenIDE-Module-Module-Dependencies + OpenIDE-Module-Public-Packages + OpenIDE-Module-Specification-Version (unless you are *not* using spec.version.base) + +Do not forget that manifest files must begin with the magic phrase + + Manifest-Version: 1.0 + +and to be safe should end in *two* newlines. + +TEST COVERAGE SUPPORT SPI +------------------------- + +There is a support for test coverage measurement for apisupport projects +since 6.7. There is a general contract under which alternative +implementations may by added (in case of multiple impls present, only +one is used). NetBeans 6.7 and 6.8 use Cobertura implementation. + +A contract for test coverage implementation for module projects is to +create Ant script testcoverage.xml in 'harness' cluster. Script +must: + + * reside directly in root folder of the cluster + * set property testcoverage.present to true outside of any target + * define target 'coverage-report' in the script + * set property testcoverage.report.dir in 'coverage-report' target to dir + with index.html file with results. + * As of 6.8, unit and functional tests are supported. + +A contract for test coverage implementation for suite projects is to +create Ant script testcoverage-suite.xml in 'harness' cluster. Script +must: + + * reside directly in root folder of the cluster + * set property testcoverage.suite.present to true outside of any target + * define target 'coverage-report' in the script + * set property testcoverage.report.dir in 'coverage-report' target to dir + with index.html file with results. + * As of 6.8, only unit tests are supported for suite projects. + +Clients should make no other assumptions beyond these contracts. All +other related files must be stored in 'testcoverage/' +subfolder. + + +---------------- +Hey Emacs! +Local Variables: +mode: text +fill-column: 80 +End: diff --git a/sdk/harness/antlib/bindex-2.2.jar b/sdk/harness/antlib/bindex-2.2.jar new file mode 100644 index 000000000..8cdbac398 Binary files /dev/null and b/sdk/harness/antlib/bindex-2.2.jar differ diff --git a/sdk/harness/antlib/jsearch-2.0_05.jar b/sdk/harness/antlib/jsearch-2.0_05.jar new file mode 100644 index 000000000..9209c72ee Binary files /dev/null and b/sdk/harness/antlib/jsearch-2.0_05.jar differ diff --git a/sdk/harness/build.xml b/sdk/harness/build.xml new file mode 100644 index 000000000..557ce6125 --- /dev/null +++ b/sdk/harness/build.xml @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [NO LICENSE SPECIFIED] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You must set 'jhall.jar' (e.g. in private.properties) to the location of jsearch.jar from a JavaHelp distribution + + + + + + + + + + + + + + + + + + + + + + + + + + + ${javadoc.title} +
${javadoc.header}
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + +
diff --git a/sdk/harness/common.xml b/sdk/harness/common.xml new file mode 100644 index 000000000..2860f6882 --- /dev/null +++ b/sdk/harness/common.xml @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Basic matching module files: ${module.files.toString} + + + + + + + + + + You have to provide value to jnlp.dest.dir property! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Missing test dependency + Runtime classpath: ${test.@{test.type}.runtime.cp} + Compile classpath: ${test.@{test.type}.compile.cp} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Report URL: ${test.report.url} + + + + + + + + + + + + + Must set test.includes + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + + + Must set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set test.class + + + + + + + + + + + + + + + + + + + + + Must set main.class. + + + + + + + + + + + + + + + + + + + Must set main.class. + + + + + + + + + + + + + + + + + + + + Must set main.class + + + + + + + + + + + + + + + + + Must set fix.class to e.g. org/netbeans/modules/foo/Bar + + + + + + + + + + + + + + + + + + + + + + + + + Must set profile.class + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + + + + + + + + + + + + + + + + You must define e.g. javadoc.arch=$${basedir}/arch.xml in project.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Will not delete ${test.user.dir} because ${test.user.dir.lock} still exists; kill any running process and delete lock file if necessary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Property testcoverage.unit.report.dir not set. Test coverage script may be missing in ${harness.dir}. + + + + + diff --git a/sdk/harness/config/Modules/org-netbeans-insane.xml b/sdk/harness/config/Modules/org-netbeans-insane.xml new file mode 100644 index 000000000..3bbc58be0 --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-insane.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-insane.jar + false + diff --git a/sdk/harness/config/Modules/org-netbeans-libs-nbi-ant.xml b/sdk/harness/config/Modules/org-netbeans-libs-nbi-ant.xml new file mode 100644 index 000000000..435dabeb7 --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-libs-nbi-ant.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-libs-nbi-ant.jar + false + diff --git a/sdk/harness/config/Modules/org-netbeans-libs-nbi-engine.xml b/sdk/harness/config/Modules/org-netbeans-libs-nbi-engine.xml new file mode 100644 index 000000000..427a13634 --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-libs-nbi-engine.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-libs-nbi-engine.jar + false + diff --git a/sdk/harness/config/Modules/org-netbeans-modules-apisupport-harness.xml b/sdk/harness/config/Modules/org-netbeans-modules-apisupport-harness.xml new file mode 100644 index 000000000..b8b90ae97 --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-modules-apisupport-harness.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-modules-apisupport-harness.jar + false + diff --git a/sdk/harness/config/Modules/org-netbeans-modules-apisupport-tc-cobertura.xml b/sdk/harness/config/Modules/org-netbeans-modules-apisupport-tc-cobertura.xml new file mode 100644 index 000000000..c39efe8d0 --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-modules-apisupport-tc-cobertura.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-modules-apisupport-tc-cobertura.jar + false + diff --git a/sdk/harness/config/Modules/org-netbeans-modules-jellytools-platform.xml b/sdk/harness/config/Modules/org-netbeans-modules-jellytools-platform.xml new file mode 100644 index 000000000..eafdf5adf --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-modules-jellytools-platform.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-modules-jellytools-platform.jar + false + diff --git a/sdk/harness/config/Modules/org-netbeans-modules-jemmy.xml b/sdk/harness/config/Modules/org-netbeans-modules-jemmy.xml new file mode 100644 index 000000000..5b409afce --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-modules-jemmy.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-modules-jemmy.jar + false + diff --git a/sdk/harness/config/Modules/org-netbeans-modules-nbjunit.xml b/sdk/harness/config/Modules/org-netbeans-modules-nbjunit.xml new file mode 100644 index 000000000..1cd0bf6f7 --- /dev/null +++ b/sdk/harness/config/Modules/org-netbeans-modules-nbjunit.xml @@ -0,0 +1,9 @@ + + + + true + false + modules/org-netbeans-modules-nbjunit.jar + false + diff --git a/sdk/harness/etc/Info.plist b/sdk/harness/etc/Info.plist new file mode 100644 index 000000000..73b9dd043 --- /dev/null +++ b/sdk/harness/etc/Info.plist @@ -0,0 +1,30 @@ + + + + + + CFBundleName + ${app.name} + + CFBundleVersion + ${app.version} + + CFBundleExecutable + ${app.name} + + CFBundlePackageType + APPL + + CFBundleShortVersionString + ${app.version} + + CFBundleSignature + ???? + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundleIconFile + ${app.name}.icns + + \ No newline at end of file diff --git a/sdk/harness/etc/app.conf b/sdk/harness/etc/app.conf new file mode 100644 index 000000000..c5e2a961a --- /dev/null +++ b/sdk/harness/etc/app.conf @@ -0,0 +1,14 @@ +# ${HOME} will be replaced by user home directory according to platform +default_userdir="${HOME}/.${APPNAME}/dev" +default_mac_userdir="${HOME}/Library/Application Support/${APPNAME}/dev" + +# options used by the launcher by default, can be overridden by explicit +# command line switches +default_options="--branding ${branding.token} -J-Xms24m -J-Xmx64m" +# for development purposes you may wish to append: -J-Dnetbeans.logger.console=true -J-ea + +# default location of JDK/JRE, can be overridden by using --jdkhome switch +#jdkhome="/path/to/jdk" + +# clusters' paths separated by path.separator (semicolon on Windows, colon on Unices) +#extra_clusters= diff --git a/sdk/harness/etc/applicationIcon.icns b/sdk/harness/etc/applicationIcon.icns new file mode 100644 index 000000000..8ffb8d7de Binary files /dev/null and b/sdk/harness/etc/applicationIcon.icns differ diff --git a/sdk/harness/jdk.xml b/sdk/harness/jdk.xml new file mode 100644 index 000000000..1ff38c344 --- /dev/null +++ b/sdk/harness/jdk.xml @@ -0,0 +1,242 @@ + + + + + + Permits selection of a JDK to use when building and running NetBeans. + For details on usage, see apisupport/harness/release/README (in sources) + or harness/README (in binaries). Cf. issue #63541. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nbjdk.active=${nbjdk.active} nbjdk.home=${nbjdk.home} nbjdk.java=${nbjdk.java} nbjdk.javac=${nbjdk.javac} nbjdk.javadoc=${nbjdk.javadoc} nbjdk.bootclasspath=${nbjdk.bootclasspath} nbjdk.valid=${nbjdk.valid} have-jdk-1.4=${have-jdk-1.4} have-jdk-1.5=${have-jdk-1.5} have-jdk-1.6=${have-jdk-1.6} have-jdk-1.7=${have-jdk-1.7} + + + + + Warning: nbjdk.active=${nbjdk.active} or nbjdk.home=${nbjdk.home} is an invalid Java platform; ignoring and using ${jdkhome.presumed} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/jnlp.xml b/sdk/harness/jnlp.xml new file mode 100644 index 000000000..ee464c1f1 --- /dev/null +++ b/sdk/harness/jnlp.xml @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + + + + + + + + $${app.title} + $${app.title} vendor + $${app.name} application + + + + + + + + + + + + + + + --branding + $${branding.token} + + +]]> + + + + + $${app.title} + $${app.title} vendor + $${app.name} application + + + $${jnlp.permissions} + + $${jnlp.branding.jars} + + + +]]> + + + + Must have set at least an application name ('app.name') + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JnlpDownloadServlet + jnlp.sample.servlet.JnlpDownloadServlet + + + JnlpDownloadServlet + *.jnlp + + +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Your JNLP file is generated at ${jnlp.dest.dir}/master.jnlp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/jnlp/jnlp-launcher.jar b/sdk/harness/jnlp/jnlp-launcher.jar new file mode 100644 index 000000000..d4982703b Binary files /dev/null and b/sdk/harness/jnlp/jnlp-launcher.jar differ diff --git a/sdk/harness/launchers/app.exe b/sdk/harness/launchers/app.exe new file mode 100644 index 000000000..fef9f2fc6 Binary files /dev/null and b/sdk/harness/launchers/app.exe differ diff --git a/sdk/harness/launchers/app.sh b/sdk/harness/launchers/app.sh new file mode 100644 index 000000000..d3982ee5c --- /dev/null +++ b/sdk/harness/launchers/app.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +# +# resolve symlinks +# + +PRG=$0 + +while [ -h "$PRG" ]; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null` + if expr "$link" : '^/' 2> /dev/null >/dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi +done + +progdir=`dirname "$PRG"` +APPNAME=`basename "$0"` + +if [ -f "$progdir/../etc/$APPNAME".conf ] ; then + . "$progdir/../etc/$APPNAME".conf +fi + +# XXX does not correctly deal with spaces in non-userdir params +args="" + +case "`uname`" in + Darwin*) + userdir="${default_mac_userdir}" + ;; + *) + userdir="${default_userdir}" + ;; +esac +while [ $# -gt 0 ] ; do + case "$1" in + --userdir) shift; if [ $# -gt 0 ] ; then userdir="$1"; fi + ;; + *) args="$args \"$1\"" + ;; + esac + shift +done + +if [ -f "${userdir}/etc/$APPNAME".conf ] ; then + . "${userdir}/etc/$APPNAME".conf +fi + +if [ -n "$jdkhome" -a \! -d "$jdkhome" -a -d "$progdir/../$jdkhome" ]; then + # #74333: permit jdkhome to be defined as relative to app dir + jdkhome="$progdir/../$jdkhome" +fi + +readClusters() { + if [ -x /usr/ucb/echo ]; then + echo=/usr/ucb/echo + else + echo=echo + fi + while read X; do + if [ "$X" \!= "" ]; then + $echo "$progdir/../$X" + fi + done +} + +clusters=`(cat "$progdir/../etc/$APPNAME".clusters; echo) | readClusters | tr '\012' ':'` + +if [ ! -z "$extra_clusters" ] ; then + clusters="$clusters:$extra_clusters" +fi + +nbexec=`echo "$progdir"/../platform*/lib/nbexec` + +case "`uname`" in + Darwin*) + eval exec sh '"$nbexec"' \ + --jdkhome '"$jdkhome"' \ + -J-Dcom.apple.mrj.application.apple.menu.about.name='"$APPNAME"' \ + -J-Xdock:name='"$APPNAME"' \ + '"-J-Xdock:icon=$progdir/../../$APPNAME.icns"' \ + --clusters '"$clusters"' \ + --userdir '"${userdir}"' \ + ${default_options} \ + "$args" + ;; + *) + sh=sh + # #73162: Ubuntu uses the ancient Bourne shell, which does not implement trap well. + if [ -x /bin/bash ] + then + sh=/bin/bash + fi + eval exec $sh '"$nbexec"' \ + --jdkhome '"$jdkhome"' \ + --clusters '"$clusters"' \ + --userdir '"${userdir}"' \ + ${default_options} \ + "$args" + exit 1 + ;; +esac diff --git a/sdk/harness/launchers/pre7_app.exe b/sdk/harness/launchers/pre7_app.exe new file mode 100644 index 000000000..c078faae1 Binary files /dev/null and b/sdk/harness/launchers/pre7_app.exe differ diff --git a/sdk/harness/launchers/pre7_app_w.exe b/sdk/harness/launchers/pre7_app_w.exe new file mode 100644 index 000000000..83d9e3ecd Binary files /dev/null and b/sdk/harness/launchers/pre7_app_w.exe differ diff --git a/sdk/harness/modules/ext/jemmy-2.3.0.0.jar b/sdk/harness/modules/ext/jemmy-2.3.0.0.jar new file mode 100644 index 000000000..e02d1b50d Binary files /dev/null and b/sdk/harness/modules/ext/jemmy-2.3.0.0.jar differ diff --git a/sdk/harness/modules/ext/locale/nbi-engine_ja.jar b/sdk/harness/modules/ext/locale/nbi-engine_ja.jar new file mode 100644 index 000000000..11867211d Binary files /dev/null and b/sdk/harness/modules/ext/locale/nbi-engine_ja.jar differ diff --git a/sdk/harness/modules/ext/locale/nbi-engine_pt_BR.jar b/sdk/harness/modules/ext/locale/nbi-engine_pt_BR.jar new file mode 100644 index 000000000..9844c6987 Binary files /dev/null and b/sdk/harness/modules/ext/locale/nbi-engine_pt_BR.jar differ diff --git a/sdk/harness/modules/ext/locale/nbi-engine_zh_CN.jar b/sdk/harness/modules/ext/locale/nbi-engine_zh_CN.jar new file mode 100644 index 000000000..363b89d4e Binary files /dev/null and b/sdk/harness/modules/ext/locale/nbi-engine_zh_CN.jar differ diff --git a/sdk/harness/modules/ext/nbi-ant-tasks.jar b/sdk/harness/modules/ext/nbi-ant-tasks.jar new file mode 100644 index 000000000..f3407af3e Binary files /dev/null and b/sdk/harness/modules/ext/nbi-ant-tasks.jar differ diff --git a/sdk/harness/modules/ext/nbi-engine.jar b/sdk/harness/modules/ext/nbi-engine.jar new file mode 100644 index 000000000..b5c6a497d Binary files /dev/null and b/sdk/harness/modules/ext/nbi-engine.jar differ diff --git a/sdk/harness/modules/ext/nbi-registries-management.jar b/sdk/harness/modules/ext/nbi-registries-management.jar new file mode 100644 index 000000000..f88cd12b0 Binary files /dev/null and b/sdk/harness/modules/ext/nbi-registries-management.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-insane_ja.jar b/sdk/harness/modules/locale/org-netbeans-insane_ja.jar new file mode 100644 index 000000000..8bdf8e9c5 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-insane_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-insane_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-insane_pt_BR.jar new file mode 100644 index 000000000..9aab9ee04 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-insane_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-insane_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-insane_zh_CN.jar new file mode 100644 index 000000000..1df98483e Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-insane_zh_CN.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_ja.jar b/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_ja.jar new file mode 100644 index 000000000..86b445851 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_pt_BR.jar new file mode 100644 index 000000000..97f4065de Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_zh_CN.jar new file mode 100644 index 000000000..9de8317b7 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-libs-nbi-ant_zh_CN.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_ja.jar b/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_ja.jar new file mode 100644 index 000000000..5ffb941fc Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_pt_BR.jar new file mode 100644 index 000000000..9f0dc704f Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_zh_CN.jar new file mode 100644 index 000000000..2285633c6 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-libs-nbi-engine_zh_CN.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_ja.jar b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_ja.jar new file mode 100644 index 000000000..f3027701c Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_pt_BR.jar new file mode 100644 index 000000000..8cff7dd5e Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_zh_CN.jar new file mode 100644 index 000000000..0bddd39e3 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-harness_zh_CN.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_ja.jar b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_ja.jar new file mode 100644 index 000000000..68b7901dd Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_pt_BR.jar new file mode 100644 index 000000000..b71ca2cd2 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_zh_CN.jar new file mode 100644 index 000000000..ec7562b2f Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-apisupport-tc-cobertura_zh_CN.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_ja.jar b/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_ja.jar new file mode 100644 index 000000000..5e9a8fced Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_pt_BR.jar new file mode 100644 index 000000000..af87a63be Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_zh_CN.jar new file mode 100644 index 000000000..30a36fee2 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-jellytools-platform_zh_CN.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-jemmy_ja.jar b/sdk/harness/modules/locale/org-netbeans-modules-jemmy_ja.jar new file mode 100644 index 000000000..e7d292e8e Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-jemmy_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-jemmy_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-modules-jemmy_pt_BR.jar new file mode 100644 index 000000000..652c39e20 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-jemmy_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-jemmy_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-modules-jemmy_zh_CN.jar new file mode 100644 index 000000000..be07305d7 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-jemmy_zh_CN.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_ja.jar b/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_ja.jar new file mode 100644 index 000000000..644fd0de3 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_ja.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_pt_BR.jar b/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_pt_BR.jar new file mode 100644 index 000000000..315495ee7 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_pt_BR.jar differ diff --git a/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_zh_CN.jar b/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_zh_CN.jar new file mode 100644 index 000000000..fce112b49 Binary files /dev/null and b/sdk/harness/modules/locale/org-netbeans-modules-nbjunit_zh_CN.jar differ diff --git a/sdk/harness/modules/org-netbeans-insane.jar b/sdk/harness/modules/org-netbeans-insane.jar new file mode 100644 index 000000000..6eabc1485 Binary files /dev/null and b/sdk/harness/modules/org-netbeans-insane.jar differ diff --git a/sdk/harness/modules/org-netbeans-libs-nbi-ant.jar b/sdk/harness/modules/org-netbeans-libs-nbi-ant.jar new file mode 100644 index 000000000..3f8c07337 Binary files /dev/null and b/sdk/harness/modules/org-netbeans-libs-nbi-ant.jar differ diff --git a/sdk/harness/modules/org-netbeans-libs-nbi-engine.jar b/sdk/harness/modules/org-netbeans-libs-nbi-engine.jar new file mode 100644 index 000000000..d20b09381 Binary files /dev/null and b/sdk/harness/modules/org-netbeans-libs-nbi-engine.jar differ diff --git a/sdk/harness/modules/org-netbeans-modules-apisupport-harness.jar b/sdk/harness/modules/org-netbeans-modules-apisupport-harness.jar new file mode 100644 index 000000000..9ff19c182 Binary files /dev/null and b/sdk/harness/modules/org-netbeans-modules-apisupport-harness.jar differ diff --git a/sdk/harness/modules/org-netbeans-modules-apisupport-tc-cobertura.jar b/sdk/harness/modules/org-netbeans-modules-apisupport-tc-cobertura.jar new file mode 100644 index 000000000..b421470cf Binary files /dev/null and b/sdk/harness/modules/org-netbeans-modules-apisupport-tc-cobertura.jar differ diff --git a/sdk/harness/modules/org-netbeans-modules-jellytools-platform.jar b/sdk/harness/modules/org-netbeans-modules-jellytools-platform.jar new file mode 100644 index 000000000..bebda22cc Binary files /dev/null and b/sdk/harness/modules/org-netbeans-modules-jellytools-platform.jar differ diff --git a/sdk/harness/modules/org-netbeans-modules-jemmy.jar b/sdk/harness/modules/org-netbeans-modules-jemmy.jar new file mode 100644 index 000000000..f147f3c3f Binary files /dev/null and b/sdk/harness/modules/org-netbeans-modules-jemmy.jar differ diff --git a/sdk/harness/modules/org-netbeans-modules-nbjunit.jar b/sdk/harness/modules/org-netbeans-modules-nbjunit.jar new file mode 100644 index 000000000..5464ab79d Binary files /dev/null and b/sdk/harness/modules/org-netbeans-modules-nbjunit.jar differ diff --git a/sdk/harness/nbi/stub/build.properties b/sdk/harness/nbi/stub/build.properties new file mode 100644 index 000000000..a0ebacdb4 --- /dev/null +++ b/sdk/harness/nbi/stub/build.properties @@ -0,0 +1,48 @@ +# +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the License at http://www.netbeans.org/cddl.html or +# http://www.netbeans.org/cddl.txt. +# +# When distributing Covered Code, include this CDDL Header Notice in each file and +# include the License file at http://www.netbeans.org/cddl.txt. If applicable, add +# the following below the CDDL Header, with the fields enclosed by brackets [] +# replaced by your own identifying information: +# +# "Portions Copyrighted [year] [name of copyright owner]" +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# + +output.dir=${basedir}/build +jarsigner.enabled=false +pack200.enabled={pack200.enabled} +core.module.name=nbi +ext.module.name=ext + +nbi.all.dir=${basedir}/nbi_all +nbi.core.dir=${nbi.all.dir}/${core.module.name} +nbi.ext.dir=${nbi.all.dir}/${ext.module.name} + +temp.file=${nbi.all.dir}/temp.ant.tmp +environment.properties=${nbi.all.dir}/environment.properties + +context.path.token=/nbi/dev +context.path.replacement=${context.path} + +context.dir.token=ROOT = new File\\(".*?"\\); +context.dir.replacement=ROOT = new File\\("${context.dir}"\); + +custom.tasks.cls={nbi.ant.tasks.jar}${path.separator}{nbi.registries.management.jar}${path.separator}{nbi.engine.jar} +nbi.engine.jar={nbi.engine.jar} + +jdk.home={generator-jdk-location-forward-slashes} +bundles.release.dir={generated-installers-location-forward-slashes} +bundle.files.prefix={generated-installers-prefix} + +target.platforms={product-platforms} +main.product.uid={product-uid} \ No newline at end of file diff --git a/sdk/harness/nbi/stub/build.xml b/sdk/harness/nbi/stub/build.xml new file mode 100644 index 000000000..4e99e9c37 --- /dev/null +++ b/sdk/harness/nbi/stub/build.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +checkout.sources=false +sources.dir=${nbi.all.dir} +cvs.module=ext + +release.to.server=false +release.registry.dir=${output.dir}/registry-temp + +dont.build.custom.tasks=true +custom.tasks.cls=${custom.tasks.cls} + +build.engine=false + +engine.dist.file.name=nbi-engine.jar +engine.dist.file=${nbi.core.dir}/infra/build/engine/dist/nbi-engine.jar + +packaged.data.dir=${basedir}/cache/packaged +downloads.cache.dir=${basedir}/cache/raw + +jarsigner.enabled=${jarsigner.enabled} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Installer(s) for [${target.platforms}] are available at ${bundles.release.dir} + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/build.xml b/sdk/harness/nbi/stub/ext/components/products/helloworld/build.xml new file mode 100644 index 000000000..07f2eba0b --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + Builds, tests, and runs the project helloworld. + + + diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/data/Bundle.properties b/sdk/harness/nbi/stub/ext/components/products/helloworld/data/Bundle.properties new file mode 100644 index 000000000..9a914fa55 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/data/Bundle.properties @@ -0,0 +1,41 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +product.display.name={product-name} +product.description={product-description} diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/data/icon.png b/sdk/harness/nbi/stub/ext/components/products/helloworld/data/icon.png new file mode 100644 index 000000000..f67785a6e Binary files /dev/null and b/sdk/harness/nbi/stub/ext/components/products/helloworld/data/icon.png differ diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/data/icon48.png b/sdk/harness/nbi/stub/ext/components/products/helloworld/data/icon48.png new file mode 100644 index 000000000..e8472fcaa Binary files /dev/null and b/sdk/harness/nbi/stub/ext/components/products/helloworld/data/icon48.png differ diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/manifest.mf b/sdk/harness/nbi/stub/ext/components/products/helloworld/manifest.mf new file mode 100644 index 000000000..7dd53f8c1 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/manifest.mf @@ -0,0 +1 @@ +Configuration-Logic-Class: org.mycompany.ConfigurationLogic \ No newline at end of file diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/build-impl.xml b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/build-impl.xml new file mode 100644 index 000000000..fc868de29 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/build-impl.xml @@ -0,0 +1,631 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/genfiles.properties b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/genfiles.properties new file mode 100644 index 000000000..bb6d89299 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=b5c7f54a +build.xml.script.CRC32=16bbb630 +build.xml.stylesheet.CRC32=be360661 +# 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=b5c7f54a +nbproject/build-impl.xml.script.CRC32=815f74ea +nbproject/build-impl.xml.stylesheet.CRC32=f1d9da08 diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/project.properties b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/project.properties new file mode 100644 index 000000000..28da6c464 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/project.properties @@ -0,0 +1,62 @@ +application.title=helloworld +application.vendor=dlm198383 +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/helloworld.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath=\ + ${reference.Core_NBI_Engine.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +project.Core_NBI_Engine=../../../../nbi/engine +reference.Core_NBI_Engine.jar=${project.Core_NBI_Engine}/dist/nbi-engine.jar +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/project.xml b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/project.xml new file mode 100644 index 000000000..84d37928d --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/nbproject/project.xml @@ -0,0 +1,26 @@ + + + org.netbeans.modules.java.j2seproject + + + helloworld + 1.6.5 + + + + + + + + + + Core_NBI_Engine + jar + + jar + clean + jar + + + + diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/Bundle.properties b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/Bundle.properties new file mode 100644 index 000000000..273df84b3 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/Bundle.properties @@ -0,0 +1,22 @@ +CL.app.name={product-simple-name} +CL.desktop.shortcut.name={product-name} +CL.desktop.shortcut.description= +CL.desktop.shortcut.path= +CL.unix.icon.name={product-icon-name} +CL.unix.icon.resource=org/mycompany/{product-icon-name} + + +CL.start.menu.shortcut.name={product-name} +CL.start.menu.shortcut.name.macosx={product-name} +CL.start.menu.shortcut.description= +CL.start.menu.shortcut.path= + +CL.install.desktop=Creating shortcut on desktop +CL.install.start.menu=Creating shortcut in start menu +CL.uninstall.start.menu=Removing Start Menu entries +CL.uninstall.desktop=Removing desktop shortcut +CL.uninstall.remove.userdir=Removing {product-name} userdir + +CL.uninstall.error.start.menu=Cannot remove desktop shortcut +CL.uninstall.error.desktop=Cannot remove Start Menu entries + diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/ConfigurationLogic.java b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/ConfigurationLogic.java new file mode 100644 index 000000000..803ee8a04 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/ConfigurationLogic.java @@ -0,0 +1,453 @@ +package org.mycompany; + +import java.util.List; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; +import java.util.Map; +import org.mycompany.wizard.panels.HelloWorldPanel; +import org.mycompany.installer.utils.applications.NetBeansRCPUtils; +import org.netbeans.installer.product.components.ProductConfigurationLogic; +import org.netbeans.installer.product.components.Product; +import org.netbeans.installer.utils.FileUtils; +import org.netbeans.installer.utils.helper.RemovalMode; +import org.netbeans.installer.utils.exceptions.InitializationException; +import org.netbeans.installer.utils.exceptions.InstallationException; +import org.netbeans.installer.utils.exceptions.UninstallationException; +import org.netbeans.installer.utils.progress.Progress; +import org.netbeans.installer.utils.system.shortcut.FileShortcut; +import org.netbeans.installer.utils.system.shortcut.LocationType; +import org.netbeans.installer.utils.system.shortcut.Shortcut; +import org.netbeans.installer.utils.SystemUtils; +import org.netbeans.installer.utils.LogManager; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.StreamUtils; +import org.netbeans.installer.utils.StringUtils; +import org.netbeans.installer.utils.exceptions.NativeException; +import org.netbeans.installer.wizard.Wizard; +import org.netbeans.installer.wizard.components.WizardComponent; + +public class ConfigurationLogic extends ProductConfigurationLogic { + + private List wizardComponents; + + // constructor ////////////////////////////////////////////////////////////////// + public ConfigurationLogic() throws InitializationException { + wizardComponents = Wizard.loadWizardComponents( + WIZARD_COMPONENTS_URI, + getClass().getClassLoader()); + } + + public List getWizardComponents() { + return wizardComponents; + } + + @Override + public boolean allowModifyMode() { + return false; + } + + @Override + public void install(Progress progress) throws InstallationException { + final Product product = getProduct(); + final File installLocation = product.getInstallationLocation(); + //final FilesList filesList = product.getInstalledFiles(); + String appName=ResourceUtils.getString(ConfigurationLogic.class, "CL.app.name"); + + if (SystemUtils.isMacOS()) { + //normen: use parent folder of install dir for icon + File f = new File(installLocation.getParentFile(), ICON_MACOSX); + if(!f.exists()) { + try { + FileUtils.writeFile(f, + ResourceUtils.getResource(ICON_MACOSX_RESOURCE, + getClass().getClassLoader())); + getProduct().getInstalledFiles().add(f); + } catch (IOException e) { + LogManager.log( + "... cannot handle icns icon " + f, e); // NOI18N + } + } + + //normen: rename executable + File shortcut=new File(installLocation.getParentFile().getParent()+"/MacOS/executable"); + if(shortcut.exists()){ + shortcut.renameTo(new File(installLocation.getParentFile().getParent()+"/MacOS/"+appName)); + } + + //normen: replace icon + app in Info.plist + try { + File plist=new File(installLocation.getParentFile().getParentFile(),"Info.plist"); + FileUtils.modifyFile(plist, "icon.icns", appName+".icns"); + FileUtils.modifyFile(plist, "executable", appName); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + + + if (Boolean.parseBoolean(getProperty(HelloWorldPanel.CREATE_DESKTOP_SHORTCUT_PROPERTY))) { + LogManager.logIndent( + "creating the desktop shortcut for the application"); // NOI18N + if (!SystemUtils.isMacOS()) { + try { + progress.setDetail(getString("CL.install.desktop")); // NOI18N + + if (SystemUtils.isCurrentUserAdmin()) { + LogManager.log( + "... current user is an administrator " + // NOI18N + "-- creating the shortcut for all users"); // NOI18N + + SystemUtils.createShortcut( + getDesktopShortcut(installLocation), + LocationType.ALL_USERS_DESKTOP); + + product.setProperty( + DESKTOP_SHORTCUT_LOCATION_PROPERTY, + ALL_USERS_PROPERTY_VALUE); + } else { + LogManager.log( + "... current user is an ordinary user " + // NOI18N + "-- creating the shortcut for the current " + // NOI18N + "user only"); // NOI18N + + SystemUtils.createShortcut( + getDesktopShortcut(installLocation), + LocationType.CURRENT_USER_DESKTOP); + + getProduct().setProperty( + DESKTOP_SHORTCUT_LOCATION_PROPERTY, + CURRENT_USER_PROPERTY_VALUE); + } + } catch (NativeException e) { + LogManager.unindent(); + + LogManager.log( + getString("CL.install.error.desktop"), // NOI18N + e); + } + } else { + LogManager.log( + "... skipping this step as we're on Mac OS"); // NOI18N + } + } + LogManager.logUnindent( + "... done"); // NOI18N + + ///////////////////////////////////////////// + // create start menu shortcut + if (Boolean.parseBoolean(getProperty(HelloWorldPanel.CREATE_START_MENU_SHORTCUT_PROPERTY))) { + LogManager.logIndent( + "creating the start menu shortcut for the application"); // NOI18N + try { + progress.setDetail(getString("CL.install.start.menu")); // NOI18N + + if (SystemUtils.isCurrentUserAdmin()) { + LogManager.log( + "... current user is an administrator " + // NOI18N + "-- creating the shortcut for all users"); // NOI18N + + SystemUtils.createShortcut( + getStartMenuShortcut(installLocation), + LocationType.ALL_USERS_START_MENU); + + getProduct().setProperty( + START_MENU_SHORTCUT_LOCATION_PROPERTY, + ALL_USERS_PROPERTY_VALUE); + } else { + LogManager.log( + "... current user is an ordinary user " + // NOI18N + "-- creating the shortcut for the current " + // NOI18N + "user only"); // NOI18N + + SystemUtils.createShortcut( + getStartMenuShortcut(installLocation), + LocationType.CURRENT_USER_START_MENU); + + getProduct().setProperty( + START_MENU_SHORTCUT_LOCATION_PROPERTY, + CURRENT_USER_PROPERTY_VALUE); + } + } catch (NativeException e) { + LogManager.log( + getString("CL.install.error.start.menu"), // NOI18N + e); + } + LogManager.logUnindent( + "... done"); // NOI18N + } + + } + + @Override + public void uninstall(Progress progress) throws UninstallationException { + final Product product = getProduct(); + final File installLocation = product.getInstallationLocation(); + + //NetBeansUtils.warnNetbeansRunning(installLocation); + ///////////////////////////////////////////////////////////////////////////// + if (Boolean.parseBoolean(getProperty(HelloWorldPanel.CREATE_START_MENU_SHORTCUT_PROPERTY))) { + try { + progress.setDetail(getString("CL.uninstall.start.menu")); // NOI18N + + final String shortcutLocation = + getProduct().getProperty(START_MENU_SHORTCUT_LOCATION_PROPERTY); + + if ((shortcutLocation == null) + || shortcutLocation.equals(CURRENT_USER_PROPERTY_VALUE)) { + SystemUtils.removeShortcut( + getStartMenuShortcut(installLocation), + LocationType.CURRENT_USER_START_MENU, + true); + } else { + SystemUtils.removeShortcut( + getStartMenuShortcut(installLocation), + LocationType.ALL_USERS_START_MENU, + true); + } + } catch (NativeException e) { + LogManager.log( + getString("CL.uninstall.error.start.menu"), // NOI18N + e); + } + } + + ///////////////////////////////////////////////////////////////////////////// + if (Boolean.parseBoolean(getProperty(HelloWorldPanel.CREATE_DESKTOP_SHORTCUT_PROPERTY))) { + if (!SystemUtils.isMacOS()) { + try { + progress.setDetail(getString("CL.uninstall.desktop")); // NOI18N + + final String shortcutLocation = getProduct().getProperty( + DESKTOP_SHORTCUT_LOCATION_PROPERTY); + + if ((shortcutLocation == null) + || shortcutLocation.equals(CURRENT_USER_PROPERTY_VALUE)) { + SystemUtils.removeShortcut( + getDesktopShortcut(installLocation), + LocationType.CURRENT_USER_DESKTOP, + false); + } else { + SystemUtils.removeShortcut( + getDesktopShortcut(installLocation), + LocationType.ALL_USERS_DESKTOP, + false); + } + } catch (NativeException e) { + LogManager.log( + getString("CL.uninstall.error.desktop"), // NOI18N + e); + } + } + } + + + if (Boolean.getBoolean("remove.app.userdir")) { + try { + progress.setDetail(getString("CL.uninstall.remove.userdir")); // NOI18N + LogManager.logIndent("Removing application`s userdir... "); + File userDir = NetBeansRCPUtils.getApplicationUserDirFile(installLocation); + LogManager.log("... application userdir location : " + userDir); + if (FileUtils.exists(userDir) && FileUtils.canWrite(userDir)) { + FileUtils.deleteFile(userDir, true); + FileUtils.deleteEmptyParents(userDir); + } + LogManager.log("... application userdir totally removed"); + } catch (IOException e) { + LogManager.log("Can`t remove application userdir", e); + } finally { + LogManager.unindent(); + } + } + + ///////////////////////////////////////////////////////////////////////////// + //remove cluster/update files + /* + try { + progress.setDetail(getString("CL.uninstall.update.files")); // NOI18N + for(String cluster : CLUSTERS) { + File updateDir = new File(installLocation, cluster + File.separator + "update"); + if ( updateDir.exists()) { + FileUtils.deleteFile(updateDir, true); + } + } + } catch (IOException e) { + LogManager.log( + getString("CL.uninstall.error.update.files"), // NOI18N + e); + } + */ + ///////////////////////////////////////////////////////////////////////////// + progress.setPercentage(Progress.COMPLETE); + } + + @Override + public String getExecutable() { + if (SystemUtils.isWindows()) { + return EXECUTABLE_WINDOWS; + } else { + return EXECUTABLE_UNIX; + } + } + + @Override + public String getIcon() { + if (SystemUtils.isWindows()) { + return ICON_WINDOWS; + } else if (SystemUtils.isMacOS()) { + return ICON_MACOSX; + } else { + return ICON_UNIX; + } + } + + public RemovalMode getRemovalMode() { + return RemovalMode.LIST; + } + + @Override + public boolean registerInSystem() { + return true; + } + + @Override + public boolean requireLegalArtifactSaving() { + return false; + } + + @Override + public boolean requireDotAppForMacOs() { + return true; + } + + @Override + public boolean wrapForMacOs() { + return true; + } + + + + private Shortcut getDesktopShortcut(final File directory) { + return getShortcut( + getStrings("CL.desktop.shortcut.name"), // NOI18N + getStrings("CL.desktop.shortcut.description"), // NOI18N + getString("CL.desktop.shortcut.path"), // NOI18N + directory); + } + + private Shortcut getStartMenuShortcut(final File directory) { + if (SystemUtils.isMacOS()) { + return getShortcut( + getStrings("CL.start.menu.shortcut.name.macosx"), // NOI18N + getStrings("CL.start.menu.shortcut.description"), // NOI18N + getString("CL.start.menu.shortcut.path"), // NOI18N + directory); + } else { + return getShortcut( + getStrings("CL.start.menu.shortcut.name"), // NOI18N + getStrings("CL.start.menu.shortcut.description"), // NOI18N + getString("CL.start.menu.shortcut.path"), // NOI18N + directory); + } + } + + private Shortcut getShortcut( + final Map names, + final Map descriptions, + final String relativePath, + final File location) { + final File icon; + final File executable; + + if (SystemUtils.isWindows()) { + icon = new File(location, ICON_WINDOWS); + } else if (SystemUtils.isMacOS()) { + icon = new File(location, ICON_MACOSX); + } else { + icon = new File(location, ICON_UNIX); + LogManager.log("... icon file: " + icon); + if(!FileUtils.exists(icon)) { + LogManager.log("... icon file does not exist: " + icon); + InputStream is = null; + is = ResourceUtils.getResource(ICON_UNIX_RESOURCE, this.getClass().getClassLoader()); + if(is!=null) { + FileOutputStream fos =null; + try { + fos = new FileOutputStream(icon); + StreamUtils.transferData(is, fos); + is.close(); + fos.close(); + getProduct().getInstalledFiles().add(icon); + } catch (IOException e) { + LogManager.log(e); + } finally { + if(fos!=null) { + try { + fos.close(); + } catch (IOException e) { + } + } + } + } + } + } + + if (SystemUtils.isWindows()) { + executable = new File(location, EXECUTABLE_WINDOWS); + } else { + executable = new File(location, EXECUTABLE_UNIX); + } + final String name = names.get(new Locale(StringUtils.EMPTY_STRING)); + final FileShortcut shortcut = new FileShortcut(name, executable); + shortcut.setNames(names); + shortcut.setDescriptions(descriptions); + shortcut.setCategories(SHORTCUT_CATEGORIES); + shortcut.setFileName(SHORTCUT_FILENAME); + shortcut.setIcon(icon); + shortcut.setRelativePath(relativePath); + shortcut.setWorkingDirectory(location); + shortcut.setModifyPath(true); + + return shortcut; + } + public static final String SHORTCUT_FILENAME = + ResourceUtils.getString(ConfigurationLogic.class, "CL.app.name") + ".desktop"; // NOI18N + public static final String[] SHORTCUT_CATEGORIES = new String[]{ + "Application" + }; + public static final String BIN_SUBDIR = + "bin/"; + public static final String EXECUTABLE_WINDOWS = + BIN_SUBDIR + + ResourceUtils.getString(ConfigurationLogic.class, "CL.app.name") + ".exe"; // NOI18N + public static final String EXECUTABLE_UNIX = + BIN_SUBDIR + + ResourceUtils.getString(ConfigurationLogic.class, "CL.app.name"); // NOI18N + public static final String ICON_WINDOWS = + EXECUTABLE_WINDOWS; + public static final String ICON_UNIX = + ResourceUtils.getString(ConfigurationLogic.class, + "CL.unix.icon.name"); // NOI18N + public static final String ICON_UNIX_RESOURCE = + ResourceUtils.getString(ConfigurationLogic.class, + "CL.unix.icon.resource"); // NOI18N + public static final String ICON_MACOSX = + ResourceUtils.getString(ConfigurationLogic.class, "CL.app.name") + ".icns"; // NOI18N + public static final String ICON_MACOSX_RESOURCE = + "org/mycompany/" + ResourceUtils.getString(ConfigurationLogic.class, "CL.app.name") + ".icns"; // NOI18N + public static final String WIZARD_COMPONENTS_URI = + "resource:" + // NOI18N + "org/mycompany/wizard.xml"; // NOI18N + private static final String DESKTOP_SHORTCUT_LOCATION_PROPERTY = + "desktop.shortcut.location"; // NOI18N + private static final String START_MENU_SHORTCUT_LOCATION_PROPERTY = + "start.menu.shortcut.location"; // NOI18N + private static final String ALL_USERS_PROPERTY_VALUE = + "all.users"; // NOI18N + private static final String CURRENT_USER_PROPERTY_VALUE = + "current.user"; // NOI18N +} diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard.xml b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard.xml new file mode 100644 index 000000000..6ce9f158e --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard.xml @@ -0,0 +1,43 @@ + + + + + + diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard/panels/Bundle.properties b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard/panels/Bundle.properties new file mode 100644 index 000000000..11e94d694 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard/panels/Bundle.properties @@ -0,0 +1,51 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +################################################################################ +# HelloWorldPanel.java +P.title={product-name} Installation +P.description=Choose destination folder. +P.destination.label.text=&Install {product-name} to: +P.destination.button.text=B&rowse..... + +P.create.desktop.shortcut=Create Desktop icon +P.create.start.menu.shortcut.windows=Create Start menu entry +P.create.start.menu.shortcut.unix=Create shortcut in Applications menu +P.create.start.menu.shortcut.macosx=Create icon in Dock + diff --git a/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard/panels/HelloWorldPanel.java b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard/panels/HelloWorldPanel.java new file mode 100644 index 000000000..d4c88237f --- /dev/null +++ b/sdk/harness/nbi/stub/ext/components/products/helloworld/src/org/mycompany/wizard/panels/HelloWorldPanel.java @@ -0,0 +1,184 @@ +package org.mycompany.wizard.panels; + +import java.awt.GridBagConstraints; +import java.awt.Insets; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.StringUtils; +import org.netbeans.installer.utils.SystemUtils; +import org.netbeans.installer.utils.helper.swing.NbiCheckBox; +import org.netbeans.installer.wizard.components.panels.DestinationPanel; +import org.netbeans.installer.wizard.containers.SwingContainer; +import org.netbeans.installer.wizard.ui.SwingUi; +import org.netbeans.installer.wizard.ui.WizardUi; + +/** + * + * @author Dmitry Lipin + */ +public class HelloWorldPanel extends DestinationPanel { + + public HelloWorldPanel() { + setProperty(TITLE_PROPERTY, + DEFAULT_TITLE); + setProperty(DESCRIPTION_PROPERTY, + DEFAULT_DESCRIPTION); + + setProperty(DESTINATION_LABEL_TEXT_PROPERTY, + DEFAULT_DESTINATION_LABEL_TEXT); + setProperty(DESTINATION_BUTTON_TEXT_PROPERTY, + DEFAULT_DESTINATION_BUTTON_TEXT); + } + + @Override + public WizardUi getWizardUi() { + if (wizardUi == null) { + wizardUi = new HelloWorldPanelUi(this); + } + + return wizardUi; + } + + @Override + public void initialize() { + super.initialize(); + if(getWizard().getProperty(CREATE_DESKTOP_SHORTCUT_PROPERTY) == null) { + getWizard().setProperty(CREATE_DESKTOP_SHORTCUT_PROPERTY, "" + true); + } + if(getWizard().getProperty(CREATE_START_MENU_SHORTCUT_PROPERTY) == null) { + getWizard().setProperty(CREATE_START_MENU_SHORTCUT_PROPERTY, "" + true); + } + } + + + public static class HelloWorldPanelUi extends DestinationPanelUi { + + protected HelloWorldPanel panel; + + public HelloWorldPanelUi(HelloWorldPanel panel) { + super(panel); + + + this.panel = panel; + } + + public SwingUi getSwingUi(SwingContainer container) { + if (swingUi == null) { + swingUi = new HelloWorldPanelSwingUi(panel, container); + } + + return super.getSwingUi(container); + } + } + + public static class HelloWorldPanelSwingUi extends DestinationPanelSwingUi { + + protected HelloWorldPanel panel; + private NbiCheckBox desktopShortcutComboBox; + private NbiCheckBox startMenuShortcutComboBox; + + public HelloWorldPanelSwingUi( + final HelloWorldPanel panel, + final SwingContainer container) { + super(panel, container); + + this.panel = panel; + + initComponents(); + } + + // protected //////////////////////////////////////////////////////////////// + @Override + protected void initialize() { + desktopShortcutComboBox.setText(CREATE_DESKTOP_SHORTCUT_NAME); + desktopShortcutComboBox.setSelected(false); + if(Boolean.parseBoolean(panel.getWizard().getProperty(CREATE_DESKTOP_SHORTCUT_PROPERTY))) { + desktopShortcutComboBox.doClick(); + } + + startMenuShortcutComboBox.setText( + SystemUtils.isWindows() ? CREATE_START_MENU_SHORTCUT_NAME_WINDOWS : + (SystemUtils.isMacOS() ? CREATE_START_MENU_SHORTCUT_NAME_MAC : + CREATE_START_MENU_SHORTCUT_NAME_UNIX)); + startMenuShortcutComboBox.setSelected(false); + if(Boolean.parseBoolean(panel.getWizard().getProperty(CREATE_START_MENU_SHORTCUT_PROPERTY))) { + startMenuShortcutComboBox.doClick(); + } + + super.initialize(); + } + + @Override + protected void saveInput() { + super.saveInput(); + panel.getWizard().setProperty( + CREATE_DESKTOP_SHORTCUT_PROPERTY, + StringUtils.EMPTY_STRING + desktopShortcutComboBox.isSelected()); + + panel.getWizard().setProperty( + CREATE_START_MENU_SHORTCUT_PROPERTY, + StringUtils.EMPTY_STRING + startMenuShortcutComboBox.isSelected()); + } + + @Override + protected String validateInput() { + String errorMessage = super.validateInput(); + return errorMessage; + } + + // private ////////////////////////////////////////////////////////////////// + private void initComponents() { + // selectedLocationField //////////////////////////////////////////////// + desktopShortcutComboBox = new NbiCheckBox(); + startMenuShortcutComboBox = new NbiCheckBox(); + + // this ///////////////////////////////////////////////////////////////// + add(desktopShortcutComboBox, new GridBagConstraints( + 0, 2, // x, y + 2, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.LINE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(15, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(startMenuShortcutComboBox, new GridBagConstraints( + 0, 3, // x, y + 2, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.LINE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(7, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + + } + } + ///////////////////////////////////////////////////////////////////////////////// + // Constants + public static final String DEFAULT_TITLE = + ResourceUtils.getString(HelloWorldPanel.class, + "P.title"); // NOI18N + public static final String DEFAULT_DESCRIPTION = + ResourceUtils.getString(HelloWorldPanel.class, + "P.description"); // NOI18N + public static final String DEFAULT_DESTINATION_LABEL_TEXT = + ResourceUtils.getString(HelloWorldPanel.class, + "P.destination.label.text"); // NOI18N + public static final String DEFAULT_DESTINATION_BUTTON_TEXT = + ResourceUtils.getString(HelloWorldPanel.class, + "P.destination.button.text"); // NOI18N + public static final String CREATE_DESKTOP_SHORTCUT_NAME = + ResourceUtils.getString(HelloWorldPanel.class, + "P.create.desktop.shortcut"); // NOI18N + public static final String CREATE_START_MENU_SHORTCUT_NAME_WINDOWS = + ResourceUtils.getString(HelloWorldPanel.class, + "P.create.start.menu.shortcut.windows"); // NOI18N + public static final String CREATE_START_MENU_SHORTCUT_NAME_UNIX = + ResourceUtils.getString(HelloWorldPanel.class, + "P.create.start.menu.shortcut.unix"); // NOI18N + public static final String CREATE_START_MENU_SHORTCUT_NAME_MAC = + ResourceUtils.getString(HelloWorldPanel.class, + "P.create.start.menu.shortcut.macosx"); // NOI18N + public static final String CREATE_DESKTOP_SHORTCUT_PROPERTY = + "create.desktop.shortcut"; + public static final String CREATE_START_MENU_SHORTCUT_PROPERTY = + "create.start.menu.shortcut"; +} diff --git a/sdk/harness/nbi/stub/ext/engine/build.properties b/sdk/harness/nbi/stub/ext/engine/build.properties new file mode 100644 index 000000000..bbe1e3e41 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/build.properties @@ -0,0 +1,41 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +jar.contents.list=data/engine.list +jar.contents.includes=native/** org/** com/apple/** data/clioptions.list data/engine*.properties diff --git a/sdk/harness/nbi/stub/ext/engine/build.xml b/sdk/harness/nbi/stub/ext/engine/build.xml new file mode 100644 index 000000000..f49986b7d --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + ${engine.files} + + + + + + diff --git a/sdk/harness/nbi/stub/ext/engine/manifest.mf b/sdk/harness/nbi/stub/ext/engine/manifest.mf new file mode 100644 index 000000000..464ca3d3f --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/manifest.mf @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Main-Class: org.netbeans.installer.Installer diff --git a/sdk/harness/nbi/stub/ext/engine/nbproject/build-impl.xml b/sdk/harness/nbi/stub/ext/engine/nbproject/build-impl.xml new file mode 100644 index 000000000..78ee6da5e --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/nbproject/build-impl.xml @@ -0,0 +1,646 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/nbi/stub/ext/engine/nbproject/genfiles.properties b/sdk/harness/nbi/stub/ext/engine/nbproject/genfiles.properties new file mode 100644 index 000000000..fa5963a15 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=8f661a73 +build.xml.script.CRC32=f2f0e306 +build.xml.stylesheet.CRC32=a12b3d02 +# 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=32036222 +nbproject/build-impl.xml.script.CRC32=ff4c3c7b +nbproject/build-impl.xml.stylesheet.CRC32=65b8de21 diff --git a/sdk/harness/nbi/stub/ext/engine/nbproject/project.properties b/sdk/harness/nbi/stub/ext/engine/nbproject/project.properties new file mode 100644 index 000000000..7651021fd --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/nbproject/project.properties @@ -0,0 +1,102 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +application.title=NetBeans Installer Engine +application.vendor=ks152834 +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/nbi-engine.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +file.reference.reglib-src=../../reglib/src +includes=** +jar.compress=false +javac.classpath=\ + ${reference.NBI_Engine.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=org.netbeans.installer.Installer +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +project.NBI_Engine=../../nbi/engine +reference.NBI_Engine.jar=${project.NBI_Engine}/dist/nbi-engine.jar +run.classpath=\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs=-Dnbi.product.bundled.registry.uri=file:/D:/temp/nbi-build/dist/registry-temp/registry.xml +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/sdk/harness/nbi/stub/ext/engine/nbproject/project.xml b/sdk/harness/nbi/stub/ext/engine/nbproject/project.xml new file mode 100644 index 000000000..3d5888d98 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/nbproject/project.xml @@ -0,0 +1,64 @@ + + + + org.netbeans.modules.java.j2seproject + + + HelloWorld Engine + 1.6.5 + + + + + + + + + + NBI_Engine + jar + + jar + clean + jar + + + + diff --git a/sdk/harness/nbi/stub/ext/engine/src/data/engine.properties b/sdk/harness/nbi/stub/ext/engine/src/data/engine.properties new file mode 100644 index 000000000..bd92d3a37 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/data/engine.properties @@ -0,0 +1,89 @@ + +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +nbi.wizard.components.instance.uri=resource:org/mycompany/installer/wizard/wizard-components.xml +nbi.wizard.ui.swing.frame.icon=resource:org/mycompany/installer/wizard/wizard-icon.png +nbi.wizard.ui.swing.frame.title.prefix= {product-name} Installer +nbi.wizard.ui.swing.frame.title.pattern={0} +nbi.macosx.application.directory.name={product-name} Installer +nbi.product.remove.corrupted.products.silently=true + +nbi.wizard.ui.swing.frame.head.right.image=resource:org/mycompany/installer/wizard/wizard-description-background-right.png +nbi.wizard.ui.swing.frame.head.left.image=resource:org/mycompany/installer/wizard/wizard-description-background-left.png + +nbi.wizard.ui.swing.welcome.left.top.image=resource:org/mycompany/installer/wizard/components/panels/resources/welcome-left-top.png +nbi.wizard.ui.swing.welcome.left.bottom.image=resource:org/mycompany/installer/wizard/components/panels/resources/welcome-left-bottom.png + +nbi.local.directory.path=$S{user.home}/.{product-uid}-installer + +nbi.wizard.ui.swing.frame.width.default=600 +nbi.wizard.ui.swing.frame.height.default=500 +nbi.wizard.ui.swing.frame.width.win.classic=588 +nbi.wizard.ui.swing.frame.height.win.classic=442 +nbi.wizard.ui.swing.frame.width.win.xp=600 +nbi.wizard.ui.swing.frame.height.win.xp=450 +nbi.wizard.ui.swing.frame.width.motif=624 +nbi.wizard.ui.swing.frame.height.motif=470 +nbi.wizard.ui.swing.frame.width.metal=624 +nbi.wizard.ui.swing.frame.height.metal=470 +nbi.wizard.ui.swing.frame.width.aqua=640 +nbi.wizard.ui.swing.frame.height.aqua=480 +nbi.wizard.ui.swing.frame.width.gtk=704 +nbi.wizard.ui.swing.frame.height.gtk=528 +nbi.wizard.ui.swing.frame.width.nimbus=624 +nbi.wizard.ui.swing.frame.height.nimbus=512 + + +nbi.wizard.ui.swing.frame.minimum.width.default=600 +nbi.wizard.ui.swing.frame.minimum.height.default=500 +nbi.wizard.ui.swing.frame.minimum.width.win.classic=588 +nbi.wizard.ui.swing.frame.minimum.height.win.classic=442 +nbi.wizard.ui.swing.frame.minimum.width.win.xp=600 +nbi.wizard.ui.swing.frame.minimum.height.win.xp=450 +nbi.wizard.ui.swing.frame.minimum.width.motif=624 +nbi.wizard.ui.swing.frame.minimum.height.motif=470 +nbi.wizard.ui.swing.frame.minimum.width.metal=624 +nbi.wizard.ui.swing.frame.minimum.height.metal=470 +nbi.wizard.ui.swing.frame.minimum.width.aqua=640 +nbi.wizard.ui.swing.frame.minimum.height.aqua=480 +nbi.wizard.ui.swing.frame.minimum.width.gtk=704 +nbi.wizard.ui.swing.frame.minimum.height.gtk=528 +nbi.wizard.ui.swing.frame.minimum.width.nimbus=624 +nbi.wizard.ui.swing.frame.minimum.height.nimbus=512 diff --git a/sdk/harness/nbi/stub/ext/engine/src/native/launcher/unix/i18n/launcher.properties b/sdk/harness/nbi/stub/ext/engine/src/native/launcher/unix/i18n/launcher.properties new file mode 100644 index 000000000..82243321b --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/native/launcher/unix/i18n/launcher.properties @@ -0,0 +1,71 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +nlu.jvm.notfoundmessage=Java SE Development Kit (JDK) was not found on this computer\nJDK 6 is required for installing {product-name}. Make sure that the JDK is properly installed and run installer again.\nYou can specify valid JDK location using {0} installer argument.\n\nTo download the JDK, visit http://java.sun.com/javase/downloads +nlu.jvm.usererror=Java Runtime Environment (JRE) was not found at the specified location {0} +nlu.jvm.uncompatible=Unsupported JVM version at {0}.\nTry to specify another JVM location using parameter {1} +nlu.freespace=There is not enough free disk space to extract installation data\n{0} MB of free disk space is required in a temporary folder.\nClean up the disk space and run installer again. You can specify a temporary folder with sufficient disk space using {1} installer argument +nlu.integrity=\nInstaller file {0} seems to be corrupted +nlu.missing.external.resource=Can`t run {product-name} Installer.\nAn external file with necessary data is required but missing:\n{0} +nlu.cannot.create.tmpdir=Cannot create temporary directory {0} +nlu.cannot.extract.bundled.jvm=Cannot extract bundled JVM +nlu.cannot.unpack.jvm.file=Cannot unpack file {0} +nlu.error.verify.bundled.jvm=Cannot verify bundled JVM, try to search JVM on the system + +nlu.running=Running the installer wizard... +nlu.starting=Configuring the installer... +nlu.extracting=Extracting installation data... +nlu.prepare.jvm=Preparing bundled JVM ... +nlu.jvm.search=Searching for JVM on the system... + +nlu.msg.usage=\nUsage: +nlu.arg.javahome=\t{0}\t\tUsing java from for running application +nlu.arg.verbose=\t{0}\t\tUse verbose output +nlu.arg.output=\t{0}\t\tRedirect all output to file +nlu.arg.disable.space.check=\t{0}\t\tDisable free space check +nlu.arg.extract=\t{0}\t[dir]\tExtract all bundled data to .\n\t\t\t\tIf is not specified then extract to the current directory +nlu.arg.tempdir=\t{0}\t\tUse for extracting temporary data +nlu.arg.cpa=\t{0} \tAppend classpath with +nlu.arg.cpp=\t{0} \tPrepend classpath with +nlu.arg.locale=\t{0}\t\tOverride default locale with specified +nlu.arg.silent=\t{0}\t\tRun installer silently +nlu.arg.help=\t{0}\t\tShow this help + + +nlu.java.application.name.macosx={product-name} Installer diff --git a/sdk/harness/nbi/stub/ext/engine/src/native/launcher/windows/i18n/launcher.properties b/sdk/harness/nbi/stub/ext/engine/src/native/launcher/windows/i18n/launcher.properties new file mode 100644 index 000000000..16b66faf3 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/native/launcher/windows/i18n/launcher.properties @@ -0,0 +1,74 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +nlw.jvm.notfoundmessage=Java SE Development Kit (JDK) was not found on this computer\nJDK 6 is required for installing {product-name}. Make sure that the JDK is properly installed and run installer again. You can specify valid JDK location using {0} installer argument.\n\nTo download the JDK, visit http://java.sun.com/javase/downloads +nlw.jvm.usererror=Java Runtime Environment (JRE) was not found\nThere is no JRE at the specified location {0} +nlw.jvm.unsupportedversion=Unsupported Java VM version\nThe Java VM at {0} has the unsupported version +nlw.freespace=There is not enough free disk space to extract installation data\n{0} MB of free disk space is required in a temporary folder. Clean up the disk space and run installer again. You can specify a temporary folder with sufficient disk space using {1} installer argument +nlw.tmpdir=Can't create temporary directory\nThe temporary directory for extracting data {0} was not created +nlw.integrity=Installer file is corrupted\nInstaller file {0} seems to be corrupted +nlw.output.error=Data extraction error\nCan't create file {0}!\nThe following error occured :\n{1} +nlw.java.process.error=An error occured while running java process\n{0} +nlw.missing.external.resource=Can`t run {product-name} Installer.\nAn external file with necessary data is required but missing:\n{0} +nlw.bundled.jvm.extract.error=Cannot prepare bundled JVM to run the installer.\nMost probably the bundled JVM is not compatible with the current platform. +nlw.bundled.jvm.verify.error=An error occured while verifying bundled JVM.\nMost probably the bundled JVM is not compatible with the current platform. + +nlw.arg.output={0} \n\tRedirect output to file +nlw.arg.javahome={0} \n\tRun jar file using JVM from +nlw.arg.verbose={0}\n\tUse verbose output +nlw.arg.tempdir={0} \n\tUse for extracting data +nlw.arg.extract={0} [directory]\n\tExtract all bundled data to the specific directory.\n\tIf directory is not specified then extract to the current directory +nlw.arg.classpatha={0} \n\tAppend classpath with +nlw.arg.classpathp={0} \n\tPrepend classpath with +nlw.arg.disable.space.check={0}\n\tDisable free space check +nlw.arg.locale={0} \n\tOverride system default locale with +nlw.arg.silent={0} \n\tRun installer silently +nlw.arg.help={0}\n\tShow help message + + +nlw.msg.create.tmpdir=Creating temporary directory ... +nlw.msg.extract=Extracting data ... +nlw.msg.jvmsearch=Finding JVM on your system ... +nlw.msg.setoptions=Setting command options ... +nlw.msg.running=Running JVM ... +nlw.msg.title=Please wait while the launcher prepares data to run the installer ... +nlw.msg.messagebox.title={product-name} Installer +nlw.msg.progress.title=Configuring the installer ... +nlw.msg.button.error=Exit Installer +nlw.msg.main.title={product-name} Installer diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/utils/applications/Bundle.properties b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/utils/applications/Bundle.properties new file mode 100644 index 000000000..ece892d53 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/utils/applications/Bundle.properties @@ -0,0 +1,43 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +############################################################################ +# NetBeansRCPUtils.java + +NU.error.cannot.get.userdir=Can`t get application userdir from {0} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/utils/applications/NetBeansRCPUtils.java b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/utils/applications/NetBeansRCPUtils.java new file mode 100644 index 000000000..d0e2e0914 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/utils/applications/NetBeansRCPUtils.java @@ -0,0 +1,191 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU General + * Public License Version 2 only ("GPL") or the Common Development and Distribution + * License("CDDL") (collectively, the "License"). You may not use this file except in + * compliance with the License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the + * License for the specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header Notice in + * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle + * designates this particular file as subject to the "Classpath" exception as + * provided by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License Header, + * with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original Software + * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All + * Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL or only the + * GPL Version 2, indicate your decision by adding "[Contributor] elects to include + * this software in this distribution under the [CDDL or GPL Version 2] license." If + * you do not indicate a single choice of license, a recipient has the option to + * distribute your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. However, if + * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then + * the option applies only if the new code is made subject to such option by the + * copyright holder. + */ + +package org.mycompany.installer.utils.applications; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.netbeans.installer.utils.FileUtils; +import org.netbeans.installer.utils.LogManager; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.StringUtils; +import org.netbeans.installer.utils.SystemUtils; +import org.netbeans.installer.utils.exceptions.NativeException; +import org.netbeans.installer.utils.system.WindowsNativeUtils; +import org.netbeans.installer.utils.system.WindowsNativeUtils; +import org.netbeans.installer.utils.system.windows.WindowsRegistry; + +/** + * + * @author Dmitry Lipin + */ +public class NetBeansRCPUtils { + + + /** + * Get resolved application user directory + * @param appLocation Application home directory + * @throws IOException if can`t get application default userdir + */ + public static File getApplicationUserDirFile(File appLocation) throws IOException { + String dir = getApplicationUserDir(appLocation); + String userHome = System.getProperty("user.home"); + if(SystemUtils.isWindows()) { + WindowsNativeUtils wnu = (WindowsNativeUtils) SystemUtils.getNativeUtils(); + WindowsRegistry reg = wnu.getWindowsRegistry(); + String key = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; + try { + if(reg.keyExists(reg.HKCU, key) && + reg.valueExists(reg.HKCU, key, "AppData")) { + userHome = reg.getStringValue(reg.HKCU, key, "AppData", false); + + } + } catch (NativeException e) { + LogManager.log(e); + } + } + dir = dir.replace(USER_HOME_TOKEN, userHome); + dir = dir.replace(APPNAME_TOKEN, getApplicationName(appLocation)); + return new File(dir); + } + + /** + * Get application user directory as it is written in application`s configuration file + * @param appLocation Application home directory + * @throws IOException if can`t get default userdir + */ + public static String getApplicationUserDir(File appLocation) throws IOException { + File []confFiles = new File(appLocation, "etc").listFiles(new FilenameFilter() { + + public boolean accept(File dir, String name) { + return name.endsWith(".conf"); + } + }); + File conf = null; + if(confFiles.length == 1) { + conf = confFiles[0]; + } else if(confFiles.length >2) { + for(File f : confFiles) { + String prefix = f.getName().substring(0, f.getName().indexOf(".conf")); + if((SystemUtils.isUnix() && new File(appLocation, "bin/" + prefix).exists()) || + (SystemUtils.isWindows() && new File(appLocation, "bin/" + prefix + ".exe").exists())) { + conf = f; + break; + } + } + } + if(conf == null) { + return null; + } + + String contents = FileUtils.readFile(conf); + Matcher matcher = Pattern.compile( + NEW_LINE_PATTERN + SPACES_PATTERN + + (SystemUtils.isMacOS() ? DEFAULT_USERDIR_MAC : DEFAULT_USERDIR) + + "\"(.*?)\"").matcher(contents); + if(matcher.find() && matcher.groupCount() == 1) { + return matcher.group(1); + } else { + throw new IOException(StringUtils.format( + ERROR_CANNOT_GET_USERDIR_STRING,conf)); + } + } + + /** + * Get application name - i.e. in bin/.exe and etc/.conf + * @param appLocation Application home directory + */ + public static String getApplicationName(File appLocation) { + File []confFiles = new File(appLocation, "etc").listFiles(new FilenameFilter() { + + public boolean accept(File dir, String name) { + return name.endsWith(".conf"); + } + }); + + if(confFiles.length == 1) { + String name = confFiles[0].getName(); + return name.substring(0, name.indexOf(".conf")); + } else if(confFiles.length >2) { + for(File f : confFiles) { + String name = f.getName(); + String prefix = name.substring(0, name.indexOf(".conf")); + if((SystemUtils.isUnix() && new File(appLocation, "bin/" + prefix).exists()) || + (SystemUtils.isWindows() && new File(appLocation, "bin/" + prefix + ".exe").exists())) { + return prefix; + } + } + } + return null; + } + + + ///////////////////////////////////////////////////////////////////////////////// + // Instance + private NetBeansRCPUtils() { + // does nothing + } + + ///////////////////////////////////////////////////////////////////////////////// + // Constants + + public static final String NEW_LINE_PATTERN = + "[\r\n|\n|\r]"; // NOI18N + public static final String SPACES_PATTERN = + "\\ *"; // NOI18N + + public static final String DEFAULT_USERDIR = + "default_userdir="; // NOI18N + public static final String DEFAULT_USERDIR_MAC = + "default_mac_userdir="; // NOI18N + + public static final String USER_HOME_TOKEN = + "${HOME}"; // NOI18N + public static final String APPNAME_TOKEN = + "${APPNAME}"; // NOI18N + + public static final String ERROR_CANNOT_GET_USERDIR_STRING = + ResourceUtils.getString(NetBeansRCPUtils.class, + "NU.error.cannot.get.userdir");//NOI18N + + +} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/actions/Bundle.properties b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/actions/Bundle.properties new file mode 100644 index 000000000..12de891ea --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/actions/Bundle.properties @@ -0,0 +1,3 @@ +IA.title=Installer Initialization +IA.progress.title=Initialization in progress... +IA.description=Please wait while initialization is completed. \ No newline at end of file diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/actions/InitializeAction.java b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/actions/InitializeAction.java new file mode 100644 index 000000000..be955d7d2 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/actions/InitializeAction.java @@ -0,0 +1,112 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU General + * Public License Version 2 only ("GPL") or the Common Development and Distribution + * License("CDDL") (collectively, the "License"). You may not use this file except in + * compliance with the License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the + * License for the specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header Notice in + * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle + * designates this particular file as subject to the "Classpath" exception as + * provided by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License Header, + * with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original Software + * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All + * Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL or only the + * GPL Version 2, indicate your decision by adding "[Contributor] elects to include + * this software in this distribution under the [CDDL or GPL Version 2] license." If + * you do not indicate a single choice of license, a recipient has the option to + * distribute your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. However, if + * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then + * the option applies only if the new code is made subject to such option by the + * copyright holder. + */ + +package org.mycompany.installer.wizard.components.actions; + +import org.netbeans.installer.product.Registry; +import org.netbeans.installer.utils.StringUtils; +import org.netbeans.installer.utils.helper.ErrorLevel; +import org.netbeans.installer.utils.ErrorManager; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.progress.Progress; +import org.netbeans.installer.wizard.components.WizardAction; +import org.netbeans.installer.wizard.components.actions.*; + +/** + * + * @author Dmitry Lipin + */ +public class InitializeAction extends WizardAction { + ///////////////////////////////////////////////////////////////////////////////// + // Instance + public InitializeAction() { + setProperty(TITLE_PROPERTY, + DEFAULT_TITLE); + setProperty(DESCRIPTION_PROPERTY, + DEFAULT_DESCRIPTION); + + downloadLogic = new DownloadConfigurationLogicAction(); + initReg = new InitializeRegistryAction(); + } + private DownloadConfigurationLogicAction downloadLogic; + private InitializeRegistryAction initReg; + + public void execute() { + final Progress progress = new Progress(); + + //getWizardUi().setProgress(progress); + + + progress.setTitle(getProperty(PROGRESS_TITLE_PROPERTY)); + + //progress.synchronizeDetails(false); + + if (initReg.canExecuteForward()) { + initReg.setWizard(getWizard()); + initReg.execute(); + } + + if (downloadLogic.canExecuteForward()) { + downloadLogic.setWizard(getWizard()); + downloadLogic.execute(); + } + } + + @Override + public boolean isCancelable() { + return false; + } + + public WizardActionUi getWizardUi() { + return null; // this action does not have a ui + } + + ///////////////////////////////////////////////////////////////////////////////// + // Constants + public static final String DEFAULT_TITLE = ResourceUtils.getString( + InitializeAction.class, + "IA.title"); // NOI18N + public static final String PROGRESS_TITLE_PROPERTY = ResourceUtils.getString( + InitializeAction.class, + "IA.progress.title"); // NOI18N + public static final String DEFAULT_DESCRIPTION = ResourceUtils.getString( + InitializeAction.class, + "IA.description"); // NOI18N + +} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/Bundle.properties b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/Bundle.properties new file mode 100644 index 000000000..a5264f3f6 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/Bundle.properties @@ -0,0 +1,94 @@ +WP.title={product-name} Introduction +WP.description={product-name} is a really good app +WP.welcome.text=\ +

Hello to {product-name} Installer Wizard


\ + This program will install {product-name} application on your computer.

\ + Click Next to continue. +WP.already.installed.text=\ +

Hello to {product-name} Installer Wizard


\ +{0} is already installed at {1}.
It is not possible to install it again.

\ +Click Exit to close this wizard. +WP.already.installed.next.button.text=&Exit +WP.incompatible.platform.text=\ +

Hello to {product-name} Installer Wizard


\ +The {0} installer was not designed to run on this operating system so it is not possible to install it. \ +Please run the installer for the appropriate platform.

\ +Click Exit to close this wizard. + +PoISP.title=Setup Complete +PoISP.description=Click Finish to finish {product-name} setup. + +PoISP.message.text.success=\ + Installation Complete


\ + {0} has been installed on your computer. +#NOI18N +PoISP.message.content.type.success=text/html + +PoISP.message.text.warnings=\ +Installation Complete


\ +{0} has been installed on your computer but some not critical warnings were encountered.\ +

For more details consult the installation log file:
{1}
+ +PoISP.message.text.finish=Click Finish to close this wizard. +PoISP.message.text.finish.content.type=text/html + +#NOI18N +PoISP.message.content.type.warnings=text/html + +PoISP.message.text.errors=Installation Failed


\ + {0} has not been installed on your computer.

\ + Try to run installer again or consult the installation log file for more details:
{1} +#NOI18N +PoISP.message.content.type.errors=text/html + +PoISP.message.text.success.uninstall=\ + Uninstallation Complete


\ + {0} has been uninstalled. +#NOI18N +PoISP.message.content.type.success.uninstall=text/html + +PoISP.message.text.warnings.uninstall=\ + Uninstallation Complete


\ + {0} has been uninstalled with warnings.

\ + For more details consult the installation log file:
{1}
+#NOI18N +PoISP.message.content.type.warnings.uninstall=text/html + +PoISP.message.text.errors.uninstall=Uninstallation Failed

\ +Uninstallation of {0} was not completed.

\ +Try to run uninstaller again or consult the uninstallation log file for more details:
{1}
\ + +#NOI18N +PoISP.message.content.type.errors.uninstall=text/html + +PoISP.message.run.application.now=Launch {0} after the installer closes. + +PoISP.next.button.text=&Finish + + + +################################################################################ +# PreInstallSummaryPanel.java +PrISP.title=Summary +PrISP.description=Click Install to start the installation. +PrISP.description.uninstall=Click Uninstall to start the uninstallation. + +PrISP.installation.folder={0} Installation Folder: +PrISP.uninstall.list.label.text=
Click Uninstall to remove {0} from the system. +PrISP.installation.size=Total Installation Size: +PrISP.download.size=Total Download Size: + +PrISP.next.button.text=&Install +PrISP.next.button.text.uninstall=&Uninstall + +PrISP.error.not.enough.space=Insufficient disk space for proper installation. Additional {1} is required in {0}. +PrISP.error.cannot.check.space=Cannot check the free disk space +PrISP.error.logic.access=Could not access product's configuration logic +PrISP.error.fsroots=Cannot get the list of file system roots +PrISP.error.non.existent.root={0} is set up to be installed to {1} which does not belong to any of the file system roots. +PrISP.error.cannot.write=The wizard does not have write access to {1}, the installation directory of {0}. Please correct the permissions before proceeding. + +PrISP.remove.app.userdir.text=\ +\ +If you wish to remove the application settings directory that stores user configuration data for {0}, check the following option.
+PrISP.remove.app.userdir.checkbox=Remove directory {0} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/PostInstallSummaryPanel.java b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/PostInstallSummaryPanel.java new file mode 100644 index 000000000..b622d68fa --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/PostInstallSummaryPanel.java @@ -0,0 +1,457 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU General + * Public License Version 2 only ("GPL") or the Common Development and Distribution + * License("CDDL") (collectively, the "License"). You may not use this file except in + * compliance with the License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the + * License for the specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header Notice in + * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle + * designates this particular file as subject to the "Classpath" exception as + * provided by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License Header, + * with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original Software + * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All + * Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL or only the + * GPL Version 2, indicate your decision by adding "[Contributor] elects to include + * this software in this distribution under the [CDDL or GPL Version 2] license." If + * you do not indicate a single choice of license, a recipient has the option to + * distribute your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. However, if + * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then + * the option applies only if the new code is made subject to such option by the + * copyright holder. + */ +package org.mycompany.installer.wizard.components.panels; + +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import org.netbeans.installer.product.Registry; +import org.netbeans.installer.product.components.Product; +import org.netbeans.installer.product.components.ProductConfigurationLogic; +import org.netbeans.installer.utils.LogManager; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.StringUtils; +import org.netbeans.installer.utils.exceptions.InitializationException; +import org.netbeans.installer.utils.helper.swing.NbiCheckBox; +import org.netbeans.installer.utils.helper.swing.NbiTextPane; +import org.netbeans.installer.wizard.components.WizardPanel; +import org.netbeans.installer.wizard.containers.SwingContainer; +import org.netbeans.installer.wizard.containers.SwingFrameContainer; +import org.netbeans.installer.wizard.ui.SwingUi; +import org.netbeans.installer.wizard.ui.WizardUi; +import static org.netbeans.installer.utils.helper.DetailedStatus.INSTALLED_SUCCESSFULLY; +import static org.netbeans.installer.utils.helper.DetailedStatus.INSTALLED_WITH_WARNINGS; +import static org.netbeans.installer.utils.helper.DetailedStatus.FAILED_TO_INSTALL; +import static org.netbeans.installer.utils.helper.DetailedStatus.UNINSTALLED_SUCCESSFULLY; +import static org.netbeans.installer.utils.helper.DetailedStatus.UNINSTALLED_WITH_WARNINGS; +import static org.netbeans.installer.utils.helper.DetailedStatus.FAILED_TO_UNINSTALL; + +/** + * + * @author Dmitry Lipin + */ +public class PostInstallSummaryPanel extends WizardPanel { + ///////////////////////////////////////////////////////////////////////////////// + // Instance + + public PostInstallSummaryPanel() { + setProperty(TITLE_PROPERTY, + DEFAULT_TITLE); + setProperty(DESCRIPTION_PROPERTY, + DEFAULT_DESCRIPTION); + + setProperty(MESSAGE_TEXT_SUCCESS_PROPERTY, + DEFAULT_MESSAGE_TEXT_SUCCESS); + setProperty(MESSAGE_CONTENT_TYPE_SUCCESS_PROPERTY, + DEFAULT_MESSAGE_CONTENT_TYPE_SUCCESS); + setProperty(MESSAGE_TEXT_WARNINGS_PROPERTY, + DEFAULT_MESSAGE_TEXT_WARNINGS); + setProperty(MESSAGE_CONTENT_TYPE_WARNINGS_PROPERTY, + DEFAULT_MESSAGE_CONTENT_TYPE_WARNINGS); + setProperty(MESSAGE_TEXT_ERRORS_PROPERTY, + DEFAULT_MESSAGE_TEXT_ERRORS); + setProperty(MESSAGE_CONTENT_TYPE_ERRORS_PROPERTY, + DEFAULT_MESSAGE_CONTENT_TYPE_ERRORS); + + setProperty(MESSAGE_TEXT_SUCCESS_UNINSTALL_PROPERTY, + DEFAULT_MESSAGE_TEXT_SUCCESS_UNINSTALL); + setProperty(MESSAGE_CONTENT_TYPE_SUCCESS_UNINSTALL_PROPERTY, + DEFAULT_MESSAGE_CONTENT_TYPE_SUCCESS_UNINSTALL); + setProperty(MESSAGE_TEXT_WARNINGS_UNINSTALL_PROPERTY, + DEFAULT_MESSAGE_TEXT_WARNINGS_UNINSTALL); + setProperty(MESSAGE_CONTENT_TYPE_WARNINGS_UNINSTALL_PROPERTY, + DEFAULT_MESSAGE_CONTENT_TYPE_WARNINGS_UNINSTALL); + setProperty(MESSAGE_TEXT_ERRORS_UNINSTALL_PROPERTY, + DEFAULT_MESSAGE_TEXT_ERRORS_UNINSTALL); + setProperty(MESSAGE_CONTENT_TYPE_ERRORS_UNINSTALL_PROPERTY, + DEFAULT_MESSAGE_CONTENT_TYPE_ERRORS_UNINSTALL); + + + setProperty(NEXT_BUTTON_TEXT_PROPERTY, + DEFAULT_NEXT_BUTTON_TEXT); + } + + @Override + public boolean isPointOfNoReturn() { + return true; + } + + @Override + public WizardUi getWizardUi() { + if (wizardUi == null) { + wizardUi = new PostInstallSummaryPanelUi(this); + } + + return wizardUi; + } + + ///////////////////////////////////////////////////////////////////////////////// + // Inner Classes + public static class PostInstallSummaryPanelUi extends WizardPanelUi { + + protected PostInstallSummaryPanel component; + + public PostInstallSummaryPanelUi(PostInstallSummaryPanel component) { + super(component); + + this.component = component; + } + + public SwingUi getSwingUi(SwingContainer container) { + if (swingUi == null) { + swingUi = new PostInstallSummaryPanelSwingUi(component, container); + } + + return super.getSwingUi(container); + } + } + + public static class PostInstallSummaryPanelSwingUi extends WizardPanelSwingUi { + + protected PostInstallSummaryPanel component; + private NbiTextPane messagePaneInstall; + private NbiTextPane messagePaneUninstall; + + + private NbiTextPane messagePaneFinish; + private NbiCheckBox runAppNow; + private Product app; + + public PostInstallSummaryPanelSwingUi( + final PostInstallSummaryPanel component, + final SwingContainer container) { + super(component, container); + + this.component = component; + + initComponents(); + } + + protected void initializeContainer() { + super.initializeContainer(); + + // set up the back button + container.getBackButton().setVisible(false); + container.getBackButton().setEnabled(false); + + // set up the next (or finish) button + container.getNextButton().setVisible(true); + container.getNextButton().setEnabled(true); + + container.getNextButton().setText( + component.getProperty(NEXT_BUTTON_TEXT_PROPERTY)); + + // set up the cancel button + container.getCancelButton().setVisible(false); + container.getCancelButton().setEnabled(false); + } + + @Override + public void evaluateNextButtonClick() { + container.getNextButton().setEnabled(false); + final Product product = app; + if (app != null) { + ProductConfigurationLogic l = null; + try { + l = app.getLogic(); + } catch (InitializationException e) { + } + final File executable = l != null ? new File(app.getInstallationLocation(), l.getExecutable()) : null; + + if (executable != null && runAppNow.isSelected()) { + LogManager.log("... running: " + executable.getAbsolutePath()); + ProcessBuilder pb = new ProcessBuilder(new String[]{executable.getAbsolutePath()}); + try { + pb.start(); + } catch (IOException e) { + LogManager.log(e); + } + + } + } + super.evaluateNextButtonClick(); + } + + protected void initialize() { + final Registry registry = Registry.getInstance(); + final List successfulInstall = registry.getProducts(INSTALLED_SUCCESSFULLY); + final List warningInstall = registry.getProducts(INSTALLED_WITH_WARNINGS); + final List errorInstall = registry.getProducts(FAILED_TO_INSTALL); + + final List successfulUninstall = registry.getProducts(UNINSTALLED_SUCCESSFULLY); + final List warningUninstall = registry.getProducts(UNINSTALLED_WITH_WARNINGS); + final List errorUninstall = registry.getProducts(FAILED_TO_UNINSTALL); + + if (errorInstall.size() > 0) { + messagePaneInstall.setContentType(component.getProperty(MESSAGE_CONTENT_TYPE_ERRORS_PROPERTY)); + messagePaneInstall.setText(StringUtils.format( + component.getProperty(MESSAGE_TEXT_ERRORS_PROPERTY), + errorInstall.get(0).getDisplayName(), + LogManager.getLogFile())); + } else if (warningInstall.size() > 0) { + messagePaneInstall.setContentType(component.getProperty(MESSAGE_CONTENT_TYPE_WARNINGS_PROPERTY)); + messagePaneInstall.setText(StringUtils.format( + component.getProperty(MESSAGE_TEXT_WARNINGS_PROPERTY), + warningInstall.get(0).getDisplayName(), + LogManager.getLogFile())); + } else if (successfulInstall.size() > 0) { + messagePaneInstall.setContentType(component.getProperty(MESSAGE_CONTENT_TYPE_SUCCESS_PROPERTY)); + messagePaneInstall.setText(StringUtils.format( + component.getProperty(MESSAGE_TEXT_SUCCESS_PROPERTY), + successfulInstall.get(0).getDisplayName(), + LogManager.getLogFile())); + } else { + messagePaneInstall.setVisible(false); + } + + messagePaneFinish.setVisible(true); + messagePaneFinish.setContentType(DEFAULT_MESSAGE_FINISH_PROCESS_CONTENT_TYPE); + messagePaneFinish.setText(DEFAULT_MESSAGE_FINISH_PROCESS); + + if (errorUninstall.size() > 0) { + messagePaneUninstall.setContentType(component.getProperty(MESSAGE_CONTENT_TYPE_ERRORS_UNINSTALL_PROPERTY)); + messagePaneUninstall.setText(StringUtils.format( + component.getProperty(MESSAGE_TEXT_ERRORS_UNINSTALL_PROPERTY), + errorUninstall.get(0).getDisplayName(), + LogManager.getLogFile())); + } else if (warningUninstall.size() > 0) { + messagePaneUninstall.setContentType(component.getProperty(MESSAGE_CONTENT_TYPE_WARNINGS_UNINSTALL_PROPERTY)); + messagePaneUninstall.setText(StringUtils.format( + component.getProperty(MESSAGE_TEXT_WARNINGS_UNINSTALL_PROPERTY), + warningUninstall.get(0).getDisplayName(), + LogManager.getLogFile())); + } else if (successfulUninstall.size() > 0) { + messagePaneUninstall.setContentType(component.getProperty(MESSAGE_CONTENT_TYPE_SUCCESS_UNINSTALL_PROPERTY)); + messagePaneUninstall.setText(StringUtils.format( + component.getProperty(MESSAGE_TEXT_SUCCESS_UNINSTALL_PROPERTY), + successfulUninstall.get(0).getDisplayName(), + LogManager.getLogFile())); + } else { + messagePaneUninstall.setVisible(false); + } + + + + final List products = new LinkedList(); + products.addAll(successfulInstall); + products.addAll(warningInstall); + runAppNow.setSelected(false); + if (!products.isEmpty()) { + runAppNow.setText(StringUtils.format(DEFAULT_MESSAGE_LAUNCH_APPLICATION_NOW, + products.get(0).getDisplayName())); + runAppNow.doClick(); + app = products.get(0); + } else { + runAppNow.setVisible(false); + } + + + } + + private void initComponents() { + // messagePaneInstall /////////////////////////////////////////////////// + messagePaneInstall = new NbiTextPane(); + + // messagePaneUninstall ///////////////////////////////////////////////// + messagePaneUninstall = new NbiTextPane(); + + // messagePaneRunApplication /////////////////////////////////////////////////// + + + messagePaneFinish = new NbiTextPane(); + + runAppNow = new NbiCheckBox(); + + + // this ///////////////////////////////////////////////////////////////// + add(messagePaneInstall, new GridBagConstraints( + 0, 0, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(31, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(messagePaneUninstall, new GridBagConstraints( + 0, 1, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.BOTH, // fill + new Insets(31, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + + add(messagePaneFinish, new GridBagConstraints( + 0, 3, // x, y + 1, 1, // width, height + 1.0, 1.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(11, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + /* + add(new NbiPanel(), new GridBagConstraints( + 0, 4, // x, y + 1, 1, // width, height + 1.0, 1.0, // weight-x, weight-y + GridBagConstraints.CENTER, // anchor + GridBagConstraints.BOTH, // fill + new Insets(0, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + */ + add(runAppNow, new GridBagConstraints( + 0, 4, // x, y + 1, 1, // width, height + 1.0, 1.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(11, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + + + + if (container instanceof SwingFrameContainer) { + final SwingFrameContainer sfc = (SwingFrameContainer) container; + sfc.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent event) { + SwingUi currentUi = component.getWizardUi().getSwingUi(container); + if (currentUi != null) { + if (!container.getCancelButton().isEnabled() && // cancel button is disabled + !container.getCancelButton().isVisible() && // no cancel button at this panel + !container.getBackButton().isVisible() && // no back button at this panel + container.getNextButton().isVisible() && // next button is visible + container.getNextButton().isEnabled()) { // and enabled + currentUi.evaluateNextButtonClick(); + sfc.removeWindowListener(this); + } + } + } + }); + } + } + } + ///////////////////////////////////////////////////////////////////////////////// + // Constants + public static final String MESSAGE_TEXT_SUCCESS_PROPERTY = + "message.text.success"; // NOI18N + public static final String MESSAGE_CONTENT_TYPE_SUCCESS_PROPERTY = + "message.content.type.success"; // NOI18N + public static final String MESSAGE_TEXT_WARNINGS_PROPERTY = + "message.text.warnings"; // NOI18N + public static final String MESSAGE_CONTENT_TYPE_WARNINGS_PROPERTY = + "message.content.type.warnings"; // NOI18N + public static final String MESSAGE_TEXT_ERRORS_PROPERTY = + "message.text.errors"; // NOI18N + public static final String MESSAGE_CONTENT_TYPE_ERRORS_PROPERTY = + "message.content.type.errors"; // NOI18N + public static final String MESSAGE_TEXT_SUCCESS_UNINSTALL_PROPERTY = + "message.text.success.uninstall"; // NOI18N + public static final String MESSAGE_CONTENT_TYPE_SUCCESS_UNINSTALL_PROPERTY = + "message.content.type.success.uninstall"; // NOI18N + public static final String MESSAGE_TEXT_WARNINGS_UNINSTALL_PROPERTY = + "message.text.warnings.uninstall"; // NOI18N + public static final String MESSAGE_CONTENT_TYPE_WARNINGS_UNINSTALL_PROPERTY = + "message.content.type.warnings.uninstall"; // NOI18N + public static final String MESSAGE_TEXT_ERRORS_UNINSTALL_PROPERTY = + "message.text.errors.uninstall"; // NOI18N + public static final String MESSAGE_CONTENT_TYPE_ERRORS_UNINSTALL_PROPERTY = + "message.content.type.errors.uninstall"; // NOI18N + public static final String DEFAULT_MESSAGE_TEXT_SUCCESS = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.success"); // NOI18N + public static final String DEFAULT_MESSAGE_CONTENT_TYPE_SUCCESS = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.content.type.success"); // NOI18N + public static final String DEFAULT_MESSAGE_TEXT_WARNINGS = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.warnings"); // NOI18N + public static final String DEFAULT_MESSAGE_CONTENT_TYPE_WARNINGS = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.content.type.warnings"); // NOI18N + public static final String DEFAULT_MESSAGE_TEXT_ERRORS = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.errors"); // NOI18N + public static final String DEFAULT_MESSAGE_CONTENT_TYPE_ERRORS = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.content.type.errors"); // NOI18N + public static final String DEFAULT_MESSAGE_TEXT_SUCCESS_UNINSTALL = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.success.uninstall"); // NOI18N + public static final String DEFAULT_MESSAGE_CONTENT_TYPE_SUCCESS_UNINSTALL = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.content.type.success.uninstall"); // NOI18N + public static final String DEFAULT_MESSAGE_TEXT_WARNINGS_UNINSTALL = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.warnings.uninstall"); // NOI18N + public static final String DEFAULT_MESSAGE_CONTENT_TYPE_WARNINGS_UNINSTALL = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.content.type.warnings.uninstall"); // NOI18N + public static final String DEFAULT_MESSAGE_TEXT_ERRORS_UNINSTALL = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.errors.uninstall"); // NOI18N + public static final String DEFAULT_MESSAGE_CONTENT_TYPE_ERRORS_UNINSTALL = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.content.type.errors.uninstall"); // NOI18N + + public static final String DEFAULT_TITLE = ResourceUtils.getString( + PostInstallSummaryPanel.class, + "PoISP.title"); // NOI18N + public static final String DEFAULT_DESCRIPTION = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.description"); // NOI18N + public static final String DEFAULT_NEXT_BUTTON_TEXT = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.next.button.text"); // NOI18N + public static final String DEFAULT_MESSAGE_FINISH_PROCESS = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.finish"); // NOI18N + public static final String DEFAULT_MESSAGE_FINISH_PROCESS_CONTENT_TYPE = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.text.finish.content.type"); // NOI18N + public static final String DEFAULT_MESSAGE_LAUNCH_APPLICATION_NOW = + ResourceUtils.getString(PostInstallSummaryPanel.class, + "PoISP.message.run.application.now");//NOI18N +} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/PreInstallSummaryPanel.java b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/PreInstallSummaryPanel.java new file mode 100644 index 000000000..1edaf1808 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/PreInstallSummaryPanel.java @@ -0,0 +1,620 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU General + * Public License Version 2 only ("GPL") or the Common Development and Distribution + * License("CDDL") (collectively, the "License"). You may not use this file except in + * compliance with the License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the + * License for the specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header Notice in + * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle + * designates this particular file as subject to the "Classpath" exception as + * provided by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License Header, + * with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original Software + * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All + * Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL or only the + * GPL Version 2, indicate your decision by adding "[Contributor] elects to include + * this software in this distribution under the [CDDL or GPL Version 2] license." If + * you do not indicate a single choice of license, a recipient has the option to + * distribute your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. However, if + * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then + * the option applies only if the new code is made subject to such option by the + * copyright holder. + */ +package org.mycompany.installer.wizard.components.panels; + +import java.awt.ComponentOrientation; +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.swing.border.EmptyBorder; +import org.netbeans.installer.Installer; +import org.netbeans.installer.product.Registry; +import org.netbeans.installer.product.RegistryNode; +import org.netbeans.installer.product.RegistryType; +import org.netbeans.installer.product.components.Product; +import org.netbeans.installer.utils.ErrorManager; +import org.netbeans.installer.utils.FileUtils; +import org.netbeans.installer.utils.LogManager; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.StringUtils; +import org.netbeans.installer.utils.SystemUtils; +import org.mycompany.installer.utils.applications.NetBeansRCPUtils; +import org.netbeans.installer.utils.exceptions.NativeException; +import org.netbeans.installer.utils.helper.swing.NbiCheckBox; +import org.netbeans.installer.utils.helper.swing.NbiLabel; +import org.netbeans.installer.utils.helper.swing.NbiPanel; +import org.netbeans.installer.utils.helper.swing.NbiTextPane; +import org.netbeans.installer.wizard.components.panels.ErrorMessagePanel; +import org.netbeans.installer.wizard.components.panels.ErrorMessagePanel.ErrorMessagePanelSwingUi; +import org.netbeans.installer.wizard.components.panels.ErrorMessagePanel.ErrorMessagePanelUi; +import org.netbeans.installer.wizard.containers.SwingContainer; +import org.netbeans.installer.wizard.ui.SwingUi; +import org.netbeans.installer.wizard.ui.WizardUi; + +/** + * + * @author Dmitry Lipin + */ +public class PreInstallSummaryPanel extends ErrorMessagePanel { + ///////////////////////////////////////////////////////////////////////////////// + // Instance + + public PreInstallSummaryPanel() { + setProperty(TITLE_PROPERTY, + DEFAULT_TITLE); + setProperty(DESCRIPTION_PROPERTY, + DEFAULT_DESCRIPTION); + + setProperty(INSTALLATION_FOLDER_PROPERTY, + DEFAULT_INSTALLATION_FOLDER); + + setProperty(UNINSTALL_LABEL_TEXT_PROPERTY, + DEFAULT_UNINSTALL_LABEL_TEXT); + + setProperty(INSTALLATION_SIZE_PROPERTY, + DEFAULT_INSTALLATION_SIZE); + setProperty(DOWNLOAD_SIZE_PROPERTY, + DEFAULT_DOWNLOAD_SIZE); + + setProperty(NEXT_BUTTON_TEXT_PROPERTY, + DEFAULT_NEXT_BUTTON_TEXT); + + setProperty(ERROR_NOT_ENOUGH_SPACE_PROPERTY, + DEFAULT_ERROR_NOT_ENOUGH_SPACE); + setProperty(ERROR_CANNOT_CHECK_SPACE_PROPERTY, + DEFAULT_ERROR_CANNOT_CHECK_SPACE); + setProperty(ERROR_LOGIC_ACCESS_PROPERTY, + DEFAULT_ERROR_LOGIC_ACCESS); + setProperty(ERROR_FSROOTS_PROPERTY, + DEFAULT_ERROR_FSROOTS); + setProperty(ERROR_NON_EXISTENT_ROOT_PROPERTY, + DEFAULT_ERROR_NON_EXISTENT_ROOT); + setProperty(ERROR_CANNOT_WRITE_PROPERTY, + DEFAULT_ERROR_CANNOT_WRITE); + setProperty(REMOVE_APP_USERDIR_TEXT_PROPERTY, + DEFAULT_REMOVE_APP_USERDIR_TEXT); + setProperty(REMOVE_APP_USERDIR_CHECKBOX_PROPERTY, + DEFAULT_REMOVE_APP_USERDIR_CHECKBOX); + + } + + @Override + public WizardUi getWizardUi() { + if (wizardUi == null) { + wizardUi = new PreInstallSummaryPanelUi(this); + } + + return wizardUi; + } + + @Override + public void initialize() { + final List toInstall = + Registry.getInstance().getProductsToInstall(); + + if (toInstall.size() > 0) { + setProperty(NEXT_BUTTON_TEXT_PROPERTY, DEFAULT_NEXT_BUTTON_TEXT); + setProperty(DESCRIPTION_PROPERTY, DEFAULT_DESCRIPTION); + } else { + setProperty(NEXT_BUTTON_TEXT_PROPERTY, DEFAULT_NEXT_BUTTON_TEXT_UNINSTALL); + setProperty(DESCRIPTION_PROPERTY, DEFAULT_DESCRIPTION_UNINSTALL); + } + } + + ///////////////////////////////////////////////////////////////////////////////// + // Inner Classes + public static class PreInstallSummaryPanelUi extends ErrorMessagePanelUi { + + protected PreInstallSummaryPanel component; + + public PreInstallSummaryPanelUi(PreInstallSummaryPanel component) { + super(component); + + this.component = component; + } + + @Override + public SwingUi getSwingUi(SwingContainer container) { + if (swingUi == null) { + swingUi = new PreInstallSummaryPanelSwingUi(component, container); + } + + return super.getSwingUi(container); + } + } + + public static class PreInstallSummaryPanelSwingUi extends ErrorMessagePanelSwingUi { + + protected PreInstallSummaryPanel component; + private NbiTextPane locationsPane; + private NbiLabel uninstallListLabel; + private NbiTextPane uninstallListPane; + private NbiLabel installationSizeLabel; + private NbiLabel installationSizeValue; + private NbiLabel downloadSizeLabel; + private NbiLabel downloadSizeValue; + private NbiCheckBox removeUserdirCheckbox; + private NbiTextPane removeUserdirPane; + private NbiPanel spacer; + private int gridy = 0; + + public PreInstallSummaryPanelSwingUi( + final PreInstallSummaryPanel component, + final SwingContainer container) { + super(component, container); + + this.component = component; + initComponents(); + } + + // protected //////////////////////////////////////////////////////////////// + @Override + protected void initializeContainer() { + super.initializeContainer(); + + container.getNextButton().setText( + panel.getProperty(NEXT_BUTTON_TEXT_PROPERTY)); + } + + @Override + protected void initialize() { + final Registry registry = Registry.getInstance(); + + final StringBuilder text = new StringBuilder(); + long installationSize = 0; + long downloadSize = 0; + + for (Product product : registry.getProductsToInstall()) { + installationSize += product.getRequiredDiskSpace(); + downloadSize += product.getDownloadSize(); + + + } + + // add top-level components like nb-base, glassfish, tomcat, jdk + for (Product product : registry.getProductsToInstall()) { + text.append(StringUtils.LF); + text.append(StringUtils.format(panel.getProperty(INSTALLATION_FOLDER_PROPERTY), + product.getDisplayName())); + text.append(StringUtils.LF); + text.append(" " + product.getInstallationLocation()); + text.append(StringUtils.LF); + } + locationsPane.setText(text); + + List toUninstall = registry.getProductsToUninstall(); + String uninstallLabelText = toUninstall.size() > 0 ? StringUtils.format( + panel.getProperty(UNINSTALL_LABEL_TEXT_PROPERTY), + toUninstall.get(0).getDisplayName()) : ""; + + uninstallListLabel.setText(uninstallLabelText); + + + installationSizeLabel.setText( + panel.getProperty(INSTALLATION_SIZE_PROPERTY)); + installationSizeValue.setText(StringUtils.formatSize( + installationSize)); + + downloadSizeLabel.setText( + panel.getProperty(DOWNLOAD_SIZE_PROPERTY)); + downloadSizeValue.setText(StringUtils.formatSize( + downloadSize)); + + if (registry.getProductsToInstall().size() == 0) { + locationsPane.setVisible(false); + installationSizeLabel.setVisible(false); + installationSizeValue.setVisible(false); + } else { + locationsPane.setVisible(true); + installationSizeLabel.setVisible(true); + installationSizeValue.setVisible(true); + } + + if (registry.getProductsToUninstall().size() == 0) { + uninstallListLabel.setVisible(false); + uninstallListPane.setVisible(false); + } else { + uninstallListLabel.setVisible(true); + uninstallListPane.setVisible(true); + } + + downloadSizeLabel.setVisible(false); + downloadSizeValue.setVisible(false); + for (RegistryNode remoteNode : registry.getNodes(RegistryType.REMOTE)) { + if (remoteNode.isVisible()) { + downloadSizeLabel.setVisible(true); + downloadSizeValue.setVisible(true); + } + } + + if (Boolean.getBoolean(REMOVE_APP_USERDIR_PROPERTY)) { + removeUserdirCheckbox.doClick(); + } + + removeUserdirCheckbox.setVisible(false); + removeUserdirPane.setVisible(false); + + for (Product product : Registry.getInstance().getProductsToUninstall()) { + + try { + File installLocation = product.getInstallationLocation(); + LogManager.log("... product installation directory: " + installLocation); + File userDir = NetBeansRCPUtils.getApplicationUserDirFile(installLocation); + LogManager.log("... product userdir: " + userDir); + if (FileUtils.exists(userDir) && FileUtils.canWrite(userDir)) { + removeUserdirCheckbox.setText( + StringUtils.format( + panel.getProperty(REMOVE_APP_USERDIR_CHECKBOX_PROPERTY), + userDir.getAbsolutePath())); + removeUserdirCheckbox.setBorder(new EmptyBorder(0, 0, 0, 0)); + removeUserdirCheckbox.setVisible(true); + + removeUserdirPane.setVisible(true); + removeUserdirPane.setContentType("text/html"); + + removeUserdirPane.setText( + StringUtils.format( + panel.getProperty(REMOVE_APP_USERDIR_TEXT_PROPERTY), + product.getDisplayName())); + + } + break; + } catch (IOException e) { + LogManager.log(e); + } + + } + + //if(productCheckboxList!=null) { + // for(Pair pair : productCheckboxList) { + // pair.getSecond().doClick(); + // } + //} + super.initialize(); + } + + @Override + protected String validateInput() { + try { + if (!Boolean.getBoolean(SystemUtils.NO_SPACE_CHECK_PROPERTY)) { + final List roots = + SystemUtils.getFileSystemRoots(); + final List toInstall = + Registry.getInstance().getProductsToInstall(); + final Map spaceMap = + new HashMap(); + + LogManager.log("Available roots : " + StringUtils.asString(roots)); + + File downloadDataDirRoot = FileUtils.getRoot( + Installer.getInstance().getLocalDirectory(), roots); + long downloadSize = 0; + for (Product product : toInstall) { + downloadSize += product.getDownloadSize(); + } + // the critical check point - we download all the data + spaceMap.put(downloadDataDirRoot, new Long(downloadSize)); + long lastDataSize = 0; + for (Product product : toInstall) { + final File installLocation = product.getInstallationLocation(); + final File root = FileUtils.getRoot(installLocation, roots); + final long productSize = product.getRequiredDiskSpace(); + + LogManager.log(" [" + root + "] <- " + installLocation); + + if (root != null) { + Long ddSize = spaceMap.get(downloadDataDirRoot); + // remove space that was freed after the remove of previos product data + spaceMap.put(downloadDataDirRoot, + Long.valueOf(ddSize - lastDataSize)); + + // add space required for next product installation + Long size = spaceMap.get(root); + size = Long.valueOf( + (size != null ? size.longValue() : 0L) + + productSize); + spaceMap.put(root, size); + lastDataSize = product.getDownloadSize(); + } else { + return StringUtils.format( + panel.getProperty(ERROR_NON_EXISTENT_ROOT_PROPERTY), + product, installLocation); + } + } + + for (File root : spaceMap.keySet()) { + try { + final long availableSpace = + SystemUtils.getFreeSpace(root); + final long requiredSpace = + spaceMap.get(root) + REQUIRED_SPACE_ADDITION; + + if (availableSpace < requiredSpace) { + return StringUtils.format( + panel.getProperty(ERROR_NOT_ENOUGH_SPACE_PROPERTY), + root, + StringUtils.formatSize(requiredSpace - availableSpace)); + } + } catch (NativeException e) { + ErrorManager.notifyError( + panel.getProperty(ERROR_CANNOT_CHECK_SPACE_PROPERTY), + e); + } + } + } + + final List toUninstall = + Registry.getInstance().getProductsToUninstall(); + for (Product product : toUninstall) { + if (!FileUtils.canWrite(product.getInstallationLocation())) { + return StringUtils.format( + panel.getProperty(ERROR_CANNOT_WRITE_PROPERTY), + product, + product.getInstallationLocation()); + } + } + + } catch (IOException e) { + ErrorManager.notifyError( + panel.getProperty(ERROR_FSROOTS_PROPERTY), e); + } + + return null; + } + + // private ////////////////////////////////////////////////////////////////// + private void initComponents() { + gridy = 0; + + // locationsPane //////////////////////////////////////////////////////// + locationsPane = new NbiTextPane(); + + // uninstallListPane //////////////////////////////////////////////////// + uninstallListPane = new NbiTextPane(); + + // uninstallListLabel /////////////////////////////////////////////////// + uninstallListLabel = new NbiLabel(); + uninstallListLabel.setLabelFor(uninstallListPane); + + // installationSizeValue //////////////////////////////////////////////// + installationSizeValue = new NbiLabel(); + //installationSizeValue.setFocusable(true); + + // installationSizeLabel //////////////////////////////////////////////// + installationSizeLabel = new NbiLabel(); + installationSizeLabel.setLabelFor(installationSizeValue); + + // downloadSizeValue //////////////////////////////////////////////////// + downloadSizeValue = new NbiLabel(); + //downloadSizeValue.setFocusable(true); + + // downloadSizeLabel //////////////////////////////////////////////////// + downloadSizeLabel = new NbiLabel(); + downloadSizeLabel.setLabelFor(downloadSizeValue); + + // spacer /////////////////////////////////////////////////////////////// + spacer = new NbiPanel(); + + // this ///////////////////////////////////////////////////////////////// + add(locationsPane, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(11, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(uninstallListLabel, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(11, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(uninstallListPane, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(0, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + int gridy0 = gridy; + gridy++; + + removeUserdirPane = new NbiTextPane(); + add(removeUserdirPane, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(11, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + + removeUserdirCheckbox = new NbiCheckBox(); + add(removeUserdirCheckbox, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.PAGE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(4, 20, 0, 11), // padding + 0, 0)); // padx, pady - ??? + + removeUserdirCheckbox.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + System.setProperty(REMOVE_APP_USERDIR_PROPERTY, + "" + removeUserdirCheckbox.isSelected()); + } + }); + + add(installationSizeLabel, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.LINE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(22, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(installationSizeValue, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.LINE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(4, 22, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(downloadSizeLabel, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.LINE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(4, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(downloadSizeValue, new GridBagConstraints( + 0, gridy++, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.LINE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(4, 22, 0, 11), // padding + 0, 0)); // padx, pady - ??? + add(spacer, new GridBagConstraints( + 0, gridy + 10, // x, y + 1, 1, // width, height + 1.0, 1.0, // weight-x, weight-y + GridBagConstraints.CENTER, // anchor + GridBagConstraints.BOTH, // fill + new Insets(0, 11, 0, 11), // padding + 0, 0)); // padx, pady - ??? + } + } +///////////////////////////////////////////////////////////////////////////////// +// Constants + public static final String INSTALLATION_FOLDER_PROPERTY = + "installation.folder"; // NOI18N + public static final String UNINSTALL_LABEL_TEXT_PROPERTY = + "uninstall.list.label.text"; // NOI18N + public static final String INSTALLATION_SIZE_PROPERTY = + "installation.size"; // NOI18N + public static final String DOWNLOAD_SIZE_PROPERTY = + "download.size"; // NOI18N + public static final String ERROR_NOT_ENOUGH_SPACE_PROPERTY = + "error.not.enough.space"; // NOI18N + public static final String ERROR_CANNOT_CHECK_SPACE_PROPERTY = + "error.cannot.check.space"; // NOI18N + public static final String ERROR_LOGIC_ACCESS_PROPERTY = + "error.logic.access"; // NOI18N + public static final String ERROR_FSROOTS_PROPERTY = + "error.fsroots"; // NOI18N + public static final String ERROR_NON_EXISTENT_ROOT_PROPERTY = + "error.non.existent.root"; // NOI18N + public static final String ERROR_CANNOT_WRITE_PROPERTY = + "error.cannot.write"; // NOI18N + public static final String REMOVE_APP_USERDIR_PROPERTY = + "remove.app.userdir"; + public static final String REMOVE_APP_USERDIR_TEXT_PROPERTY = + "remove.app.userdir.text"; + public static final String REMOVE_APP_USERDIR_CHECKBOX_PROPERTY = + "remove.app.userdir.checkbox"; + public static final String DEFAULT_TITLE = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.title"); // NOI18N + public static final String DEFAULT_DESCRIPTION = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.description"); // NOI18N + public static final String DEFAULT_DESCRIPTION_UNINSTALL = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.description.uninstall"); // NOI18N + public static final String DEFAULT_INSTALLATION_FOLDER = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.installation.folder"); // NOI18N + public static final String DEFAULT_UNINSTALL_LABEL_TEXT = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.uninstall.list.label.text"); // NOI18N + public static final String DEFAULT_INSTALLATION_SIZE = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.installation.size"); // NOI18N + public static final String DEFAULT_DOWNLOAD_SIZE = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.download.size"); // NOI18N + public static final String DEFAULT_NEXT_BUTTON_TEXT = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.next.button.text"); // NOI18N + public static final String DEFAULT_NEXT_BUTTON_TEXT_UNINSTALL = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.next.button.text.uninstall"); // NOI18N + public static final String DEFAULT_ERROR_NOT_ENOUGH_SPACE = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.error.not.enough.space"); // NOI18N + public static final String DEFAULT_ERROR_CANNOT_CHECK_SPACE = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.error.cannot.check.space");// NOI18N + public static final String DEFAULT_ERROR_LOGIC_ACCESS = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.error.logic.access");// NOI18N + public static final String DEFAULT_ERROR_FSROOTS = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.error.fsroots"); // NOI18N + public static final String DEFAULT_ERROR_NON_EXISTENT_ROOT = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.error.non.existent.root"); // NOI18N + public static final String DEFAULT_ERROR_CANNOT_WRITE = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.error.cannot.write"); // NOI18N + public static final String DEFAULT_REMOVE_APP_USERDIR_TEXT = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.remove.app.userdir.text"); // NOI18N + + public static final String DEFAULT_REMOVE_APP_USERDIR_CHECKBOX = + ResourceUtils.getString(PreInstallSummaryPanel.class, + "PrISP.remove.app.userdir.checkbox"); // NOI18N + public static final long REQUIRED_SPACE_ADDITION = + 10L * 1024L * 1024L; // 10MB +} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/WelcomePanel.java b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/WelcomePanel.java new file mode 100644 index 000000000..c1cc01575 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/WelcomePanel.java @@ -0,0 +1,333 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU General + * Public License Version 2 only ("GPL") or the Common Development and Distribution + * License("CDDL") (collectively, the "License"). You may not use this file except in + * compliance with the License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the + * License for the specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header Notice in + * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle + * designates this particular file as subject to the "Classpath" exception as + * provided by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License Header, + * with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original Software + * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All + * Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL or only the + * GPL Version 2, indicate your decision by adding "[Contributor] elects to include + * this software in this distribution under the [CDDL or GPL Version 2] license." If + * you do not indicate a single choice of license, a recipient has the option to + * distribute your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. However, if + * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then + * the option applies only if the new code is made subject to such option by the + * copyright holder. + */ +package org.mycompany.installer.wizard.components.panels; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.io.File; +import java.util.List; +import org.netbeans.installer.product.Registry; +import org.netbeans.installer.product.components.Product; +import org.netbeans.installer.utils.ErrorManager; +import org.netbeans.installer.utils.LogManager; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.StringUtils; +import org.netbeans.installer.utils.SystemUtils; +import org.netbeans.installer.utils.exceptions.InitializationException; +import org.netbeans.installer.utils.helper.Platform; +import org.netbeans.installer.utils.helper.swing.NbiPanel; +import org.netbeans.installer.utils.helper.swing.NbiTextPane; +import org.netbeans.installer.wizard.components.panels.ErrorMessagePanel; +import org.netbeans.installer.wizard.components.panels.ErrorMessagePanel.ErrorMessagePanelSwingUi; +import org.netbeans.installer.wizard.components.panels.ErrorMessagePanel.ErrorMessagePanelUi; +import org.netbeans.installer.wizard.containers.SwingContainer; +import org.netbeans.installer.wizard.ui.SwingUi; +import org.netbeans.installer.wizard.ui.WizardUi; + +/** + * + * @author Dmitry Lipin + */ +public class WelcomePanel extends ErrorMessagePanel { + ///////////////////////////////////////////////////////////////////////////////// + private Registry bundledRegistry; + private Registry defaultRegistry; + + public WelcomePanel() { + setProperty(TITLE_PROPERTY, + DEFAULT_TITLE); + setProperty(DESCRIPTION_PROPERTY, + DEFAULT_DESCRIPTION); + + setProperty(WELCOME_TEXT_PROPERTY, + DEFAULT_WELCOME_TEXT); + + setProperty(WELCOME_ALREADY_INSTALLED_TEXT_PROPERTY, + DEFAULT_WELCOME_ALREADY_INSTALLED_TEXT); + setProperty(WELCOME_ALREADY_INSTALLED_NEXT_BUTTON_TEXT_PROPERTY, + DEFAULT_WELCOME_ALREADY_INSTALLED_NEXT_BUTTON_TEXT); + + try { + defaultRegistry = Registry.getInstance(); + bundledRegistry = new Registry(); + + final String bundledRegistryUri = System.getProperty( + Registry.BUNDLED_PRODUCT_REGISTRY_URI_PROPERTY); + if (bundledRegistryUri != null) { + bundledRegistry.loadProductRegistry(bundledRegistryUri); + } else { + bundledRegistry.loadProductRegistry( + Registry.DEFAULT_BUNDLED_PRODUCT_REGISTRY_URI); + } + } catch (InitializationException e) { + ErrorManager.notifyError("Cannot load bundled registry", e); + } + + } + + Registry getBundledRegistry() { + return bundledRegistry; + } + + @Override + public WizardUi getWizardUi() { + if (wizardUi == null) { + wizardUi = new WelcomePanelUi(this); + } + + return wizardUi; + } + + @Override + public boolean canExecuteForward() { + return canExecute(); + } + + @Override + public boolean canExecuteBackward() { + return canExecute(); + } + + // private ////////////////////////////////////////////////////////////////////// + private boolean canExecute() { + return bundledRegistry.getNodes().size() > 1; + } + + ///////////////////////////////////////////////////////////////////////////////// + // Inner Classes + public static class WelcomePanelUi extends ErrorMessagePanelUi { + + protected WelcomePanel component; + + public WelcomePanelUi(WelcomePanel component) { + super(component); + + this.component = component; + } + + @Override + public SwingUi getSwingUi(SwingContainer container) { + if (swingUi == null) { + swingUi = new WelcomePanelSwingUi(component, container); + } + + return super.getSwingUi(container); + } + } + + public static class WelcomePanelSwingUi extends ErrorMessagePanelSwingUi { + + protected WelcomePanel panel; + private NbiTextPane textPane; + + private NbiPanel leftImagePanel; + ValidatingThread validatingThread; + + public WelcomePanelSwingUi( + final WelcomePanel component, + final SwingContainer container) { + super(component, container); + + this.panel = component; + + initComponents(); + } + + @Override + public String getTitle() { + return null; // the welcome page does not have a title + } + + // protected //////////////////////////////////////////////////////////////// + @Override + protected void initializeContainer() { + super.initializeContainer(); + + container.getBackButton().setVisible(false); + } + + @Override + protected void initialize() { + + textPane.setContentType("text/html"); + textPane.setText(StringUtils.format(panel.getProperty(WELCOME_TEXT_PROPERTY))); + List toInstall = Registry.getInstance().getProductsToInstall(); + if(toInstall.isEmpty()) { + List list = panel.getBundledRegistry().getProducts(); + if(list.size() == 1) { + if(SystemUtils.getCurrentPlatform().isCompatibleWith(list.get(0).getPlatforms())) { + File installationLocation = list.get(0).getInstallationLocation(); + textPane.setText( + StringUtils.format( + panel.getProperty(WELCOME_ALREADY_INSTALLED_TEXT_PROPERTY), + list.get(0).getDisplayName(), + installationLocation.getAbsolutePath())); + } else { + textPane.setText( + StringUtils.format( + WELCOME_INCOMPATIBLE_PLATFORM_TEXT, + list.get(0).getDisplayName())); + } + container.getCancelButton().setVisible(false); + container.getNextButton().setText(panel.getProperty( + WELCOME_ALREADY_INSTALLED_NEXT_BUTTON_TEXT_PROPERTY)); + } + } + + super.initialize(); + } + + // private ////////////////////////////////////////////////////////////////// + private void initComponents() { + // textPane ///////////////////////////////////////////////////////////// + textPane = new NbiTextPane(); + + leftImagePanel = new NbiPanel(); + int width = 0; + int height = 0; + final String topLeftImage = SystemUtils.resolveString( + System.getProperty( + WELCOME_PAGE_LEFT_TOP_IMAGE_PROPERTY)); + final String bottomLeftImage = SystemUtils.resolveString( + System.getProperty( + WELCOME_PAGE_LEFT_BOTTOM_IMAGE_PROPERTY)); + + int bottomAnchor = NbiPanel.ANCHOR_BOTTOM_LEFT; + + if (topLeftImage != null) { + leftImagePanel.setBackgroundImage(topLeftImage, ANCHOR_TOP_LEFT); + width = leftImagePanel.getBackgroundImage(NbiPanel.ANCHOR_TOP_LEFT).getIconWidth(); + height += leftImagePanel.getBackgroundImage(NbiPanel.ANCHOR_TOP_LEFT).getIconHeight(); + } + if (bottomLeftImage != null) { + leftImagePanel.setBackgroundImage(bottomLeftImage, bottomAnchor); + width = leftImagePanel.getBackgroundImage(bottomAnchor).getIconWidth(); + height += leftImagePanel.getBackgroundImage(bottomAnchor).getIconHeight(); + } + + leftImagePanel.setPreferredSize(new Dimension(width, height)); + leftImagePanel.setMaximumSize(new Dimension(width, height)); + leftImagePanel.setMinimumSize(new Dimension(width, 0)); + leftImagePanel.setSize(new Dimension(width, height)); + + leftImagePanel.setOpaque(false); + // this ///////////////////////////////////////////////////////////////// + int dy = 0; + add(leftImagePanel, new GridBagConstraints( + 0, 0, // x, y + 1, 100, // width, height + 0.0, 1.0, // weight-x, weight-y + GridBagConstraints.WEST, // anchor + GridBagConstraints.VERTICAL, // fill + new Insets(0, 0, 0, 0), // padding + 0, 0)); // padx, pady - ??? + add(textPane, new GridBagConstraints( + 1, dy++, // x, y + 4, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.LINE_START, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(10, 11, 11, 11), // padding + 0, 0)); // padx, pady - ??? + + NbiTextPane separatorPane = new NbiTextPane(); + + separatorPane = new NbiTextPane(); + add(separatorPane, new GridBagConstraints( + 3, dy, // x, y + 1, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.CENTER, // anchor + GridBagConstraints.BOTH, // fill + new Insets(0, 0, 0, 0), // padding + 0, 0)); // padx, pady - ??? + + + // move error label after the left welcome image + Component errorLabel = getComponent(0); + getLayout().removeLayoutComponent(errorLabel); + add(errorLabel, new GridBagConstraints( + 1, 99, // x, y + 99, 1, // width, height + 1.0, 0.0, // weight-x, weight-y + GridBagConstraints.CENTER, // anchor + GridBagConstraints.HORIZONTAL, // fill + new Insets(4, 11, 4, 0), // padding + 0, 0)); // ??? (padx, pady) + + + } + } + ///////////////////////////////////////////////////////////////////////////////// + // Constants + public static final String DEFAULT_TITLE = + ResourceUtils.getString(WelcomePanel.class, + "WP.title"); + public static final String DEFAULT_DESCRIPTION = + ResourceUtils.getString(WelcomePanel.class, + "WP.description"); // NOI18N + public static final String WELCOME_TEXT_PROPERTY = + "welcome.text"; // NOI18N + public static final String WELCOME_ALREADY_INSTALLED_TEXT_PROPERTY = + "welcome.already.installed.text"; // NOI18N + public static final String WELCOME_ALREADY_INSTALLED_NEXT_BUTTON_TEXT_PROPERTY = + "welcome.already.installed.next.button.text";//NOI18N + public static final String WELCOME_INCOMPATIBLE_PLATFORM_TEXT = + ResourceUtils.getString(WelcomePanel.class, + "WP.incompatible.platform.text");//NOI18N + + public static final String DEFAULT_WELCOME_ALREADY_INSTALLED_NEXT_BUTTON_TEXT = + ResourceUtils.getString(WelcomePanel.class, + "WP.already.installed.next.button.text");//NOI18N + + public static final String DEFAULT_WELCOME_TEXT = + ResourceUtils.getString(WelcomePanel.class, + "WP.welcome.text"); // NOI18N + + public static final String DEFAULT_WELCOME_ALREADY_INSTALLED_TEXT = + ResourceUtils.getString(WelcomePanel.class, + "WP.already.installed.text"); // NOI18N + + public static final String WELCOME_PAGE_LEFT_TOP_IMAGE_PROPERTY = + "nbi.wizard.ui.swing.welcome.left.top.image";//NOI18N + public static final String WELCOME_PAGE_LEFT_BOTTOM_IMAGE_PROPERTY = + "nbi.wizard.ui.swing.welcome.left.bottom.image";//NOI18N +} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/resources/welcome-left-bottom.png b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/resources/welcome-left-bottom.png new file mode 100644 index 000000000..6d9585bf2 Binary files /dev/null and b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/resources/welcome-left-bottom.png differ diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/resources/welcome-left-top.png b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/resources/welcome-left-top.png new file mode 100644 index 000000000..13adb1221 Binary files /dev/null and b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/panels/resources/welcome-left-top.png differ diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/sequences/Bundle.properties b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/sequences/Bundle.properties new file mode 100644 index 000000000..62ce479bb --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/sequences/Bundle.properties @@ -0,0 +1,43 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +##################################################################################### +# MainSequence.java +MS.IA.title=Installation +MS.IA.description=Please wait while the installer installs {product-name}. diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/sequences/MainSequence.java b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/sequences/MainSequence.java new file mode 100644 index 000000000..86534f690 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/components/sequences/MainSequence.java @@ -0,0 +1,154 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU General + * Public License Version 2 only ("GPL") or the Common Development and Distribution + * License("CDDL") (collectively, the "License"). You may not use this file except in + * compliance with the License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the + * License for the specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header Notice in + * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle + * designates this particular file as subject to the "Classpath" exception as + * provided by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License Header, + * with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original Software + * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All + * Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL or only the + * GPL Version 2, indicate your decision by adding "[Contributor] elects to include + * this software in this distribution under the [CDDL or GPL Version 2] license." If + * you do not indicate a single choice of license, a recipient has the option to + * distribute your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. However, if + * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then + * the option applies only if the new code is made subject to such option by the + * copyright holder. + */ +package org.mycompany.installer.wizard.components.sequences; + +import org.netbeans.installer.wizard.components.sequences.ProductWizardSequence; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.mycompany.installer.wizard.components.panels.PostInstallSummaryPanel; +import org.mycompany.installer.wizard.components.panels.PreInstallSummaryPanel; +import org.netbeans.installer.product.components.Product; +import org.netbeans.installer.product.Registry; +import org.netbeans.installer.utils.ResourceUtils; +import org.netbeans.installer.utils.helper.ExecutionMode; +import org.netbeans.installer.wizard.components.WizardSequence; +import org.netbeans.installer.wizard.components.actions.DownloadConfigurationLogicAction; +import org.netbeans.installer.wizard.components.actions.DownloadInstallationDataAction; +import org.netbeans.installer.wizard.components.actions.InstallAction; +import org.netbeans.installer.wizard.components.actions.UninstallAction; +import org.netbeans.installer.wizard.components.panels.LicensesPanel; + +/** + * + * @author Dmitry Lipin + */ +public class MainSequence extends WizardSequence { + ///////////////////////////////////////////////////////////////////////////////// + // Instance + + private DownloadConfigurationLogicAction downloadConfigurationLogicAction; + private LicensesPanel licensesPanel; + private PreInstallSummaryPanel preInstallSummaryPanel; + private UninstallAction uninstallAction; + private DownloadInstallationDataAction downloadInstallationDataAction; + private InstallAction installAction; + private PostInstallSummaryPanel postInstallSummaryPanel; + private Map productSequences; + + public MainSequence() { + downloadConfigurationLogicAction = new DownloadConfigurationLogicAction(); + licensesPanel = new LicensesPanel(); + preInstallSummaryPanel = new PreInstallSummaryPanel(); + uninstallAction = new UninstallAction(); + downloadInstallationDataAction = new DownloadInstallationDataAction(); + installAction = new InstallAction(); + postInstallSummaryPanel = new PostInstallSummaryPanel(); + productSequences = new HashMap(); + + installAction.setProperty(InstallAction.TITLE_PROPERTY, + DEFAULT_IA_TITLE); + installAction.setProperty(InstallAction.DESCRIPTION_PROPERTY, + DEFAULT_IA_DESCRIPTION); + } + + @Override + public void executeForward() { + final Registry registry = Registry.getInstance(); + final List toInstall = registry.getProductsToInstall(); + final List toUninstall = registry.getProductsToUninstall(); + + // remove all current children (if there are any), as the components + // selection has probably changed and we need to rebuild from scratch + getChildren().clear(); + + // the set of wizard components differs greatly depending on the execution + // mode - if we're installing, we ask for input, run a wizard sequence for + // each selected component and then download and install; if we're creating + // a bundle, we only need to download and package things + + if (toInstall.size() > 0) { + addChild(downloadConfigurationLogicAction); + addChild(licensesPanel); + + for (Product product : toInstall) { + if (!productSequences.containsKey(product)) { + productSequences.put( + product, + new ProductWizardSequence(product)); + } + + addChild(productSequences.get(product)); + } + } + + addChild(preInstallSummaryPanel); + + if (toUninstall.size() > 0) { + addChild(uninstallAction); + } + + if (toInstall.size() > 0) { + addChild(downloadInstallationDataAction); + addChild(installAction); + } + + addChild(postInstallSummaryPanel); + + super.executeForward(); + } + + @Override + public boolean canExecuteForward() { + return ExecutionMode.NORMAL == ExecutionMode.getCurrentExecutionMode() && + (Registry.getInstance().getProductsToInstall().size() > 0 || + Registry.getInstance().getProductsToUninstall().size() > 0); + } + ///////////////////////////////////////////////////////////////////////////////// + // Constants + public static final String DEFAULT_IA_TITLE = + ResourceUtils.getString( + MainSequence.class, + "MS.IA.title"); // NOI18N + public static final String DEFAULT_IA_DESCRIPTION = + ResourceUtils.getString( + MainSequence.class, + "MS.IA.description"); // NOI18N + +} diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-components.xml b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-components.xml new file mode 100644 index 000000000..6b9509d7c --- /dev/null +++ b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-components.xml @@ -0,0 +1,52 @@ + + + + + + + + + + diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-description-background-left.png b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-description-background-left.png new file mode 100644 index 000000000..6fe816aed Binary files /dev/null and b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-description-background-left.png differ diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-description-background-right.png b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-description-background-right.png new file mode 100644 index 000000000..f395ba518 Binary files /dev/null and b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-description-background-right.png differ diff --git a/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-icon.png b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-icon.png new file mode 100644 index 000000000..a8c0f8c34 Binary files /dev/null and b/sdk/harness/nbi/stub/ext/engine/src/org/mycompany/installer/wizard/wizard-icon.png differ diff --git a/sdk/harness/nbi/stub/ext/infra/build/engine/build.properties b/sdk/harness/nbi/stub/ext/infra/build/engine/build.properties new file mode 100644 index 000000000..13c71c7ac --- /dev/null +++ b/sdk/harness/nbi/stub/ext/infra/build/engine/build.properties @@ -0,0 +1,77 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +# path to the directory where the base build scripts library and properties +# reside +common.dir=../../../../.common + +# path to the local working directory; this directory which will be the target +# for checking out the sources and will be used for the build process +# * this path can be either absolute or relative in any unix environment, +# however, only relative paths are supported on windows, as the cygwin scp +# command does not properly handle colon in local paths +work.dir=./build + +# path to the local distributive directory; this directory will contain the +# distributive file, when (if) the build script finishes successfully +dist.dir=./dist + +# path to the engine sources within the cvs module; it should be a relative +# path from the module's root, e.g. for 'nbi/engine', where 'nbi is the module +# name, the path should be 'engine' +cvs.path=engine + +# name of the engine's distributive file +engine.dist.file.name=nbi-engine.jar + +# we do not need to build anything native for the netbeans-specific engine, as it +# does not contain any native components +build.native=false + +# custom parameter for the netbeans project build script - in case of the netbeans +# nbi engine - the location of the core engine jar file +nb.custom.parameter=-Dreference.NBI_Engine.jar=${core.engine.dist.file} + +# sources parameters; a search-and-replace will be run over the sources after +# check-out, replacing [token] => [value]; regular expressions are not allowed +# * ${sources.params.length} - total number of the parameters +# * indices should start with 1 +# * parameters are not i18n compliant + +sources.params.length=0 diff --git a/sdk/harness/nbi/stub/ext/infra/build/engine/build.xml b/sdk/harness/nbi/stub/ext/infra/build/engine/build.xml new file mode 100644 index 000000000..eec305c73 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/infra/build/engine/build.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + In order to 'clean', 'checkout' and 'build' the engine use the + 'build-all' target. To 'clean', 'checkout', 'build' and + 'release' - use 'release-all'. + + For more details, please see the source of this build script. + + + diff --git a/sdk/harness/nbi/stub/ext/infra/build/products/helloworld/build.properties b/sdk/harness/nbi/stub/ext/infra/build/products/helloworld/build.properties new file mode 100644 index 000000000..b2084d4c7 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/infra/build/products/helloworld/build.properties @@ -0,0 +1,159 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU General Public +# License Version 2 only ("GPL") or the Common Development and Distribution +# License("CDDL") (collectively, the "License"). You may not use this file except in +# compliance with the License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the +# License for the specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header Notice in +# each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle +# designates this particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that accompanied this code. +# If applicable, add the following below the License Header, with the fields enclosed +# by brackets [] replaced by your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original Software +# is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All +# Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL or only the +# GPL Version 2, indicate your decision by adding "[Contributor] elects to include +# this software in this distribution under the [CDDL or GPL Version 2] license." If +# you do not indicate a single choice of license, a recipient has the option to +# distribute your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. However, if you +# add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the +# option applies only if the new code is made subject to such option by the copyright +# holder. +# + +# path to the directory where the base build scripts library and properties +# reside +common.dir=../../../../../.common + +# path to the local working directory; this directory which will be the target +# for checking out the sources and will be used for the build process +# * this path can be either absolute or relative in any unix environment, +# however, only relative paths are supported on windows, as the cygwin scp +# command does not properly handle colon in local paths +work.dir=./build + +# path to the local distributive directory; this directory will contain the +# distributive file, when (if) the build script finishes successfully +dist.dir=./dist + +# path to the products's sources within the cvs module; it should be a relative +# path from the module's root, e.g. for 'nbi/engine', where 'nbi is the module +# name, the path should be 'engine' +cvs.path=components/products/helloworld + +# core product properties: +# * ${product.uid} - product "family" (e.g. nb-ide) +# * ${product.version} - actual products' version; together with the uid it +# forms the unique identifier for the product) +# * ${product.platforms} - the list of platforms that are supported by this +# product (note that this property is not related to native libraries) +product.uid={product-uid} +product.version=0.6.1.0.0 +product.platforms=generic + +# miscellaneous product properties: +# * ${product.status} - default status that the product will have in the +# registry. it is meant to be always "not-installed", unless you want +# something really exotic +# * ${product.offset} - order of the product's node among its parent's +# children, the bigger the offset value, the further the product's node will +# be +# * ${product.expand} - whether to automatically expand the product's node in +# the components tree or not; 'true'/'false' +# * ${product.visible} - whether the product's node is visible or not (note +# that this value will be modified at nbi runtime, 'true' may become 'false' +# if the product is filtered out); 'true'/'false' +# * ${product.features} - list of features that this porduct belongs to; the +# list should be space-separated +product.status=not-installed +product.offset=20000 +product.expand=false +product.visible=true +product.features= + +# list of configuration logic jar files; normally the first one would be the +# distributive file of the product's netbeans project +# * ${product.logic.length} - total number of the files +# * indices should start with 1 +product.logic.length=1 +product.logic.1.path=${nbproject.dist.dir}/${nbproject.dist.file.name} + +# list of product installation data files +# * ${product.data.length} - total number of the files +# * ${product.data.N.uri} - uri at which the installation data file is located +# * ${product.data.N.zip} - whether the data file is a zip archive which needs to +# be extracted or it is a file that should be used directly; 'true'/'false' +# * indices should start with 1 +product.data.length=1 +product.data.1.zip=true +product.data.1.path={product-data-path} +product.data.sub.dir={product-data-sub-dir} + +# modificator for the required disk space parameter; the core value will be the +# sum of unzipped unstallation data files +# * the measurement unit is one byte +product.disk.space.modificator=0 + +# product's requirements (i.e. other products that should be installed +# in order for this product to succesfully install and function) +# * ${product.requirements.length} - total number of the requirements +# * indices should start with 1 +product.requirements.length=0 +#product.requirements.1.uid= +#product.requirements.1.version-lower= +#product.requirements.1.version-upper= + +# product's conflicts (i.e. other products that prevent this product from +# functioning correctly, and thus cannot be installed together with it) +# * ${product.conflicts.length} - total number of the conflicts +# * indices should start with 1 +product.conflicts.length=0 +#product.conflicts.1.uid= +#product.conflicts.1.version-lower= +#product.conflicts.1.version-upper= + +# other products that should be installed prior to this product; these +# dependencies do not imply that the dependent product will be installed at +# all, but if both the current and the dependent product are selected for +# installation, the latter will be installed first +# * ${product.install-afters.length} - total number of the install-afters +# * indices should start with 1 +product.install-afters.length=0 +#product.install-afters.1.uid= + +# additional product's properties; these will appear in the product's +# descriptor and in the registry in the form of +# value tags. +# * ${product.properties.length} - total number of the properties +# * indices should start with 1 +# * properties are not i18n compliant +product.properties.length=3 +product.properties.1.name=installation.location +product.properties.1.value=$N{install}/{product-install-directory-name} +product.properties.2.name=installation.location.windows +product.properties.2.value=$N{install}/{product-install-directory-name-windows} +product.properties.3.name=installation.location.macosx +product.properties.3.value=$N{install}/{product-install-directory-name-macosx}.app + +# sources parameters; a search-and-replace will be run over the sources after +# check-out, replacing [token] => [value]; regular expressions are not allowed +# * ${sources.params.length} - total number of the parameters +# * indices should start with 1 +# * parameters are not i18n compliant +sources.params.length=0 \ No newline at end of file diff --git a/sdk/harness/nbi/stub/ext/infra/build/products/helloworld/build.xml b/sdk/harness/nbi/stub/ext/infra/build/products/helloworld/build.xml new file mode 100644 index 000000000..00fbe27f3 --- /dev/null +++ b/sdk/harness/nbi/stub/ext/infra/build/products/helloworld/build.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + In order to 'clean', 'checkout' and 'build' the group use the + 'build-all' target. To 'clean', 'checkout', 'build' and + 'release' - use 'release-all'. + + For more details, please see the source of this build script. + + + diff --git a/sdk/harness/nbi/stub/template.xml b/sdk/harness/nbi/stub/template.xml new file mode 100644 index 000000000..1a0b4d03b --- /dev/null +++ b/sdk/harness/nbi/stub/template.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/nbi/stub/tmpl.properties b/sdk/harness/nbi/stub/tmpl.properties new file mode 100644 index 000000000..e8b316a9c --- /dev/null +++ b/sdk/harness/nbi/stub/tmpl.properties @@ -0,0 +1,16 @@ +suite.location=C:/Documents and Settings/Lipin/My Documents/NetBeansProjects/MyApp + +nbi.cluster.location=D:/space/NB-IDE/proto/nbbuild/netbeans/extra + +nbi.stub.location=${nbi.cluster.location}/nbi/stub +nbi.stub.common.location=${nbi.cluster.location}/nbi/.common +nbi.ant.tasks.jar=${nbi.cluster.location}/modules/ext/nbi-ant-tasks.jar +nbi.registries.management.jar=${nbi.cluster.location}/modules/ext/nbi-registries-management.jar +nbi.engine.jar=${nbi.cluster.location}/modules/ext/nbi-engine.jar + +generate.installer.for.platforms=windows linux macosx + +generator-jdk-location-forward-slashes=C:/Program Files/Java/jdk1.5.0_16 +pack200.enabled=false + +suite.nbi.product.uid=myapp \ No newline at end of file diff --git a/sdk/harness/no-testcoverage.xml b/sdk/harness/no-testcoverage.xml new file mode 100644 index 000000000..8f53325a7 --- /dev/null +++ b/sdk/harness/no-testcoverage.xml @@ -0,0 +1,12 @@ + + + + + +No test coverage implementation found in ${harness.dir}. + + + diff --git a/sdk/harness/osgi.xml b/sdk/harness/osgi.xml new file mode 100644 index 000000000..d0ae88d02 --- /dev/null +++ b/sdk/harness/osgi.xml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/run.xml b/sdk/harness/run.xml new file mode 100644 index 000000000..5fc85e6d9 --- /dev/null +++ b/sdk/harness/run.xml @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + netbeans_extraclusters="${run.extra.clusters}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The application is already running within the test user directory. +You must shut it down before trying to run it again. + + + + + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/suite.xml b/sdk/harness/suite.xml new file mode 100644 index 000000000..e8c43fd40 --- /dev/null +++ b/sdk/harness/suite.xml @@ -0,0 +1,609 @@ + + + + + + + + + + + + + Using build harness in ${harness.dir} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Suite in ${basedir} with clusters ${cluster.path.final}, build cluster ${cluster}, and sorted modules ${modules.sorted} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must have set at least an application name ('app.name') + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Note: As of NetBeans 6.7, you can use the property 'cluster.path' instead of the 'create-platform' target. +See: http://wiki.netbeans.org/DevFaqHowToReuseModules + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +You MacOS Application bundle was created at ${dist.dir}/${app.name}.app. For final packaging, use hdiutil or other tools to create a .dmg image. +Alternatively use "zip -yr ${app.name}.app" to create a simple zipped distribution. + + + + + + + + + + + + + + Will not delete ${test.user.dir} because ${test.user.dir.lock} still exists; kill any running process and delete lock file if necessary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OSGi support is EXPERIMENTAL for now; see: http://wiki.netbeans.org/NetBeansInOSGi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Property testcoverage.report.dir not set. Test coverage script may be missing in ${harness.dir}. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/tasks.jar b/sdk/harness/tasks.jar new file mode 100644 index 000000000..8166a3abc Binary files /dev/null and b/sdk/harness/tasks.jar differ diff --git a/sdk/harness/testcoverage-suite.xml b/sdk/harness/testcoverage-suite.xml new file mode 100644 index 000000000..cff283953 --- /dev/null +++ b/sdk/harness/testcoverage-suite.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/testcoverage.xml b/sdk/harness/testcoverage.xml new file mode 100644 index 000000000..027ddbd9c --- /dev/null +++ b/sdk/harness/testcoverage.xml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Test coverage tasks can be currently run only with default java platform, that is +with property nbjdk.active unset or set to 'default' and with property nbjdk.home +unset. + +For NB.org module, specify properties: +nbjdk.home.defaulted=true +permit.jdk6.builds=true +when running the target. + +Current java platform setup is: + nbjdk.active: ${nbjdk.active.print} + nbjdk.home: ${nbjdk.home.print} + nbjdk.home defaulted: ${nbjdk.home.defaulted.print} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + diff --git a/sdk/harness/testcoverage/cobertura/cobertura-1.9.3.jar b/sdk/harness/testcoverage/cobertura/cobertura-1.9.3.jar new file mode 100644 index 000000000..32d69353e Binary files /dev/null and b/sdk/harness/testcoverage/cobertura/cobertura-1.9.3.jar differ diff --git a/sdk/harness/testcoverage/cobertura/lib/asm-3.0.jar b/sdk/harness/testcoverage/cobertura/lib/asm-3.0.jar new file mode 100644 index 000000000..112f5bd4a Binary files /dev/null and b/sdk/harness/testcoverage/cobertura/lib/asm-3.0.jar differ diff --git a/sdk/harness/testcoverage/cobertura/lib/asm-tree-3.0.jar b/sdk/harness/testcoverage/cobertura/lib/asm-tree-3.0.jar new file mode 100644 index 000000000..2a4b20856 Binary files /dev/null and b/sdk/harness/testcoverage/cobertura/lib/asm-tree-3.0.jar differ diff --git a/sdk/harness/testcoverage/cobertura/lib/jakarta-oro-2.0.8.jar b/sdk/harness/testcoverage/cobertura/lib/jakarta-oro-2.0.8.jar new file mode 100644 index 000000000..23488d260 Binary files /dev/null and b/sdk/harness/testcoverage/cobertura/lib/jakarta-oro-2.0.8.jar differ diff --git a/sdk/harness/testcoverage/cobertura/lib/log4j-1.2.9.jar b/sdk/harness/testcoverage/cobertura/lib/log4j-1.2.9.jar new file mode 100644 index 000000000..a6568b01a Binary files /dev/null and b/sdk/harness/testcoverage/cobertura/lib/log4j-1.2.9.jar differ diff --git a/sdk/harness/update_tracking/org-netbeans-insane.xml b/sdk/harness/update_tracking/org-netbeans-insane.xml new file mode 100644 index 000000000..647d0c592 --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-insane.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sdk/harness/update_tracking/org-netbeans-libs-nbi-ant.xml b/sdk/harness/update_tracking/org-netbeans-libs-nbi-ant.xml new file mode 100644 index 000000000..68457f7ca --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-libs-nbi-ant.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/update_tracking/org-netbeans-libs-nbi-engine.xml b/sdk/harness/update_tracking/org-netbeans-libs-nbi-engine.xml new file mode 100644 index 000000000..57101b2ae --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-libs-nbi-engine.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/harness/update_tracking/org-netbeans-modules-apisupport-harness.xml b/sdk/harness/update_tracking/org-netbeans-modules-apisupport-harness.xml new file mode 100644 index 000000000..16c9a9f2c --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-modules-apisupport-harness.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/harness/update_tracking/org-netbeans-modules-apisupport-tc-cobertura.xml b/sdk/harness/update_tracking/org-netbeans-modules-apisupport-tc-cobertura.xml new file mode 100644 index 000000000..358bf2a75 --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-modules-apisupport-tc-cobertura.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/sdk/harness/update_tracking/org-netbeans-modules-jellytools-platform.xml b/sdk/harness/update_tracking/org-netbeans-modules-jellytools-platform.xml new file mode 100644 index 000000000..0268921b2 --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-modules-jellytools-platform.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sdk/harness/update_tracking/org-netbeans-modules-jemmy.xml b/sdk/harness/update_tracking/org-netbeans-modules-jemmy.xml new file mode 100644 index 000000000..565ad9350 --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-modules-jemmy.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/harness/update_tracking/org-netbeans-modules-nbjunit.xml b/sdk/harness/update_tracking/org-netbeans-modules-nbjunit.xml new file mode 100644 index 000000000..65088b75e --- /dev/null +++ b/sdk/harness/update_tracking/org-netbeans-modules-nbjunit.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sdk/jme3-assetpack-support/build.xml b/sdk/jme3-assetpack-support/build.xml new file mode 100644 index 000000000..c55b2748e --- /dev/null +++ b/sdk/jme3-assetpack-support/build.xml @@ -0,0 +1,12 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.assetpack. + + + + + + diff --git a/sdk/jme3-assetpack-support/manifest.mf b/sdk/jme3-assetpack-support/manifest.mf new file mode 100644 index 000000000..55152c16b --- /dev/null +++ b/sdk/jme3-assetpack-support/manifest.mf @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.assetpack +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Install: com/jme3/gde/assetpack/Installer.class +OpenIDE-Module-Layer: com/jme3/gde/assetpack/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/assetpack/Bundle.properties +OpenIDE-Module-Requires: org.openide.windows.WindowManager + diff --git a/sdk/jme3-assetpack-support/nbproject/build-impl.xml b/sdk/jme3-assetpack-support/nbproject/build-impl.xml new file mode 100644 index 000000000..f62520687 --- /dev/null +++ b/sdk/jme3-assetpack-support/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-assetpack-support/nbproject/genfiles.properties b/sdk/jme3-assetpack-support/nbproject/genfiles.properties new file mode 100644 index 000000000..3e43796f0 --- /dev/null +++ b/sdk/jme3-assetpack-support/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=69b2b49f +build.xml.script.CRC32=c0969383 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=71a82056 +nbproject/build-impl.xml.script.CRC32=4d376df0 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-assetpack-support/nbproject/project.properties b/sdk/jme3-assetpack-support/nbproject/project.properties new file mode 100644 index 000000000..00311e62a --- /dev/null +++ b/sdk/jme3-assetpack-support/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.7.0 diff --git a/sdk/jme3-assetpack-support/nbproject/project.xml b/sdk/jme3-assetpack-support/nbproject/project.xml new file mode 100644 index 000000000..fa88b8a9b --- /dev/null +++ b/sdk/jme3-assetpack-support/nbproject/project.xml @@ -0,0 +1,182 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.assetpack + + + + com.jme3.gde.core + + + + 1 + 0.9 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.7 + + + + com.jme3.gde.ogretools + + + + 1 + 0.6.1 + + + + com.jme3.gde.scenecomposer + + + + 1 + 0.6.1 + + + + org.netbeans.api.progress + + + + 1 + 1.19 + + + + org.netbeans.modules.options.api + + + + 1 + 1.18 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.30 + + + + org.netbeans.modules.projectuiapi + + + + 1 + 1.40 + + + + org.netbeans.modules.settings + + + + 1 + 1.20 + + + + org.openide.actions + + + + 6.1 + + + + org.openide.awt + + + + 7.20 + + + + org.openide.dialogs + + + + 7.1 + + + + org.openide.explorer + + + + 6.20 + + + + org.openide.filesystems + + + + 7.35 + + + + org.openide.loaders + + + + 7.1 + + + + org.openide.modules + + + + 7.16 + + + + org.openide.nodes + + + + 7.16 + + + + org.openide.util + + + + 8.5 + + + + org.openide.util.lookup + + + + 8.3 + + + + org.openide.windows + + + + 6.30 + + + + + + + diff --git a/sdk/jme3-assetpack-support/nbproject/suite.properties b/sdk/jme3-assetpack-support/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-assetpack-support/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-assetpack-support/project-template/assetpack.xml b/sdk/jme3-assetpack-support/project-template/assetpack.xml new file mode 100644 index 000000000..959c437b2 --- /dev/null +++ b/sdk/jme3-assetpack-support/project-template/assetpack.xml @@ -0,0 +1,7 @@ + + + Description + No License + + + diff --git a/sdk/jme3-assetpack-support/src/META-INF/services/org.netbeans.spi.project.ProjectFactory b/sdk/jme3-assetpack-support/src/META-INF/services/org.netbeans.spi.project.ProjectFactory new file mode 100644 index 000000000..005611bee --- /dev/null +++ b/sdk/jme3-assetpack-support/src/META-INF/services/org.netbeans.spi.project.ProjectFactory @@ -0,0 +1 @@ +com.jme3.gde.assetpack.project.AssetPackProjectFactory diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackBrowserTopComponentSettings.xml b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackBrowserTopComponentSettings.xml new file mode 100644 index 000000000..63a4cea95 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackBrowserTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackBrowserTopComponentWstcref.xml b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackBrowserTopComponentWstcref.xml new file mode 100644 index 000000000..0a8c88263 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackBrowserTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackLoader.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackLoader.java new file mode 100644 index 000000000..5484e2628 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackLoader.java @@ -0,0 +1,348 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack; + +import com.jme3.animation.AnimControl; +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.asset.ModelKey; +import com.jme3.gde.assetpack.actions.AddAssetAction; +import com.jme3.gde.assetpack.project.wizards.FileDescription; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.material.Material; +import com.jme3.material.MaterialList; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.plugins.ogre.OgreMeshKey; +import com.jme3.scene.plugins.ogre.matext.MaterialExtension; +import com.jme3.scene.plugins.ogre.matext.MaterialExtensionSet; +import com.jme3.scene.plugins.ogre.matext.OgreMaterialKey; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * + * @author normenhansen + */ +public class AssetPackLoader { + + public static Spatial loadAssetPackModel(Element assetElement, ProjectAssetManager pm) { + NodeList fileNodeList = assetElement.getElementsByTagName("file"); + Element fileElement = XmlHelper.findChildElementWithAttribute(assetElement, "file", "main", "true"); + if (fileElement == null) { + fileElement = XmlHelper.findChildElement(assetElement, "file"); + } + Spatial model = null; + Node node = null; + while (fileElement != null) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.INFO, "Load main file {0}",fileElement.getAttribute("path")); + if (model != null && node == null) { + node = new Node(assetElement.getAttribute("name")); + node.attachChild(model); + } + model = AssetPackLoader.loadSingleMesh(fileElement, fileNodeList, pm); + if (model != null && node != null) { + node.attachChild(model); + } else { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.WARNING, "Error loading model"); + } + //TODO:doesnt work? + fileElement = XmlHelper.findNextElementWithAttribute(fileElement, "file", "main", "true"); + } + if (node != null) { + return node; + } + return model; + } + + // TODO: merge animation controls for multi meshes + private static void moveControls(Spatial from, Node to) { + AnimControl control = to.getControl(AnimControl.class); + AnimControl control2 = from.getControl(AnimControl.class); + if (control == null) { + control = new AnimControl(to, control2.getTargets(), control2.getSkeleton()); + } + Collection names = control.getAnimationNames(); + Collection names2 = new LinkedList(control2.getAnimationNames()); + //add tracks from anims interface second that exist in first + for (Iterator it = names.iterator(); it.hasNext();) { + String string = it.next(); + names2.remove(string); + BoneAnimation anim = control.getAnim(string); + BoneTrack[] tracks = anim.getTracks(); + BoneAnimation anim2 = control2.getAnim(string); + if (anim2 != null) { + BoneTrack[] tracks2 = anim2.getTracks(); + BoneTrack[] newTracks = new BoneTrack[tracks.length + tracks2.length]; + for (int i = 0; i < tracks.length; i++) { + newTracks[i] = tracks[i]; + } + for (int i = tracks.length; i < tracks2.length; i++) { + newTracks[i] = tracks2[i - tracks.length]; + } + anim.setTracks(newTracks); + } + } + //add tracks from anims in second to first + for (Iterator it = names2.iterator(); it.hasNext();) { + String string = it.next(); + BoneAnimation anim2 = control2.getAnim(string); + BoneTrack[] tracks2 = anim2.getTracks(); + BoneAnimation anim = control.getAnim(string); + if (anim != null) { + BoneTrack[] tracks = anim.getTracks(); + BoneTrack[] newTracks = new BoneTrack[tracks.length + tracks2.length]; + for (int i = 0; i < tracks.length; i++) { + newTracks[i] = tracks[i]; + } + for (int i = tracks.length; i < tracks2.length; i++) { + newTracks[i] = tracks2[i - tracks.length]; + } + anim.setTracks(newTracks); + } else { + control.addAnim(anim2); + } + } + } + + private static Spatial loadSingleMesh(Element fileElement, NodeList fileNodeList, ProjectAssetManager pm) { + ModelKey key = null; + Material mat = null; + Spatial model; + MaterialList matList = null; + String name = fileElement.getAttribute("path"); + String materialName = fileElement.getAttribute("material"); + if ("".equals(materialName)) { + materialName = null; + } + + //PREPARE MATEXT + MaterialExtensionSet matExts = new MaterialExtensionSet(); + /** + * /base/simple + * /base/normalmap + */ + MaterialExtension baseLightExt = new MaterialExtension("/base/normalmap/specular", + "Common/MatDefs/Light/Lighting.j3md"); + baseLightExt.setTextureMapping("DiffuseMap", "DiffuseMap"); + baseLightExt.setTextureMapping("NormalHeightMap", "NormalMap"); + baseLightExt.setTextureMapping("SpecularMap", "SpecularMap"); + matExts.addMaterialExtension(baseLightExt); + + MaterialExtension baseLightExt2 = new MaterialExtension("/base/normalmap", + "Common/MatDefs/Light/Lighting.j3md"); + baseLightExt2.setTextureMapping("DiffuseMap", "DiffuseMap"); + baseLightExt2.setTextureMapping("NormalHeightMap", "NormalMap"); + baseLightExt2.setTextureMapping("SpecularMap", "SpecularMap"); + matExts.addMaterialExtension(baseLightExt2); + + MaterialExtension baseLightExt3 = new MaterialExtension("/base/simple", + "Common/MatDefs/Light/Lighting.j3md"); + baseLightExt3.setTextureMapping("DiffuseMap", "DiffuseMap"); + baseLightExt3.setTextureMapping("NormalHeightMap", "NormalMap"); + baseLightExt3.setTextureMapping("SpecularMap", "SpecularMap"); + matExts.addMaterialExtension(baseLightExt3); + + //TODO: mesh.xml!! + if (hasExtension(name, "xml") || hasExtension(name, "scene")) { + for (int i = 0; i < fileNodeList.getLength(); i++) { + Element fileElem = (Element) fileNodeList.item(i); + String type = fileElem.getAttribute("type"); + String path = fileElem.getAttribute("path"); + if ("material".equals(type) && (materialName == null || materialName.equals(path))) { + if (hasExtension(path, "j3m")) { + mat = pm.getManager().loadMaterial(path); + } else if (hasExtension(path, "material")) { + if (matList == null) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.INFO, "Load Ogre Material"); + OgreMaterialKey matKey = new OgreMaterialKey(path); + matKey.setMaterialExtensionSet(matExts); + matList = pm.getManager().loadAsset(matKey); + key = new OgreMeshKey(name, matList); + } else { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.INFO, "Add Ogre Material"); + OgreMaterialKey matKey = new OgreMaterialKey(path); + matKey.setMaterialExtensionSet(matExts); + MaterialList newMatList = pm.getManager().loadAsset(matKey); + matList.putAll(newMatList); + } + } + } + } + } else if (hasExtension(name, "obj")) { + for (int i = 0; i < fileNodeList.getLength(); i++) { + Element fileElem = (Element) fileNodeList.item(i); + String type = fileElem.getAttribute("type"); + String path = fileElem.getAttribute("path"); + if ("material".equals(type) && (materialName == null || materialName.equals(path))) { + if (hasExtension(path, "j3m")) { + mat = pm.getManager().loadMaterial(path); + } + } + } + } else if (hasExtension(name, "j3o")) { + //should have all info inside + } + if (key != null && mat != null) { + Logger.getLogger(AddAssetAction.class.getName()).log(Level.WARNING, "j3m and ogre material defined for asset {0}.", name); + } + if (key != null) { + model = pm.getManager().loadAsset(key); + } else { + model = pm.getManager().loadModel(name); + } + if (model == null) { + Logger.getLogger(AddAssetAction.class.getName()).log(Level.SEVERE, "Could not load model {0}!", name); + return null; + } + if (mat != null) { + model.setMaterial(mat); + } + return model; + } + + private static boolean hasExtension(String name, String extension) { + int idx = name.lastIndexOf("."); + if (idx < 0) { + return false; + } + String ext = name.substring(idx + 1, name.length()); + if (ext.equalsIgnoreCase(extension)) { + return true; + } + return false; + } + + public static FileDescription getFileDescription(File file) { + FileObject fileObject = FileUtil.toFileObject(file); + return getFileDescription(fileObject); + } + + public static FileDescription getFileDescription(FileObject fileObject) { + FileDescription description = new FileDescription(); + description.setFile(fileObject); + if ("material".equals(fileObject.getExt())) { + description.setType("material"); + } else if ("j3m".equals(fileObject.getExt())) { + description.setType("material"); + } else if ("mat".equals(fileObject.getExt())) { + description.setType("material"); + } else if ("scene".equals(fileObject.getExt())) { + description.setType("scene"); + description.setMainFile(true); + } else if ("obj".equals(fileObject.getExt())) { + description.setType("mesh"); + description.setMainFile(true); + } else if ("j3o".equals(fileObject.getExt())) { + description.setType("scene"); + description.setMainFile(true); + } else if ("xml".equals(fileObject.getExt())) { + if (fileObject.getName().endsWith(".mesh")) { + description.setType("mesh"); + } + if (fileObject.getName().endsWith(".skeleton")) { + description.setType("skeleton"); + } + } else if ("png".equals(fileObject.getExt())) { + description.setType("texture"); + } else if ("jpg".equals(fileObject.getExt())) { + description.setType("texture"); + } else if ("jpeg".equals(fileObject.getExt())) { + description.setType("texture"); + } else if ("gif".equals(fileObject.getExt())) { + description.setType("texture"); + } else if ("dds".equals(fileObject.getExt())) { + description.setType("texture"); + } else if (fileObject.getName().endsWith(".mesh")) { + description.setType("mesh"); + } else if (fileObject.getName().endsWith(".skeleton")) { + description.setType("skeleton"); + } + return description; + } + + public static void addAllFiles(Element assetElement, ProjectAssetManager pm) { + //TODO: not good :/ + NodeList list = assetElement.getElementsByTagName("file"); + ProjectAssetManager proman = null; + try { + proman = SceneApplication.getApplication().getCurrentSceneRequest().getManager(); + if (proman == null) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not get project asset manager!"); + return; + } + } catch (Exception e) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not get project asset manager!"); + return; + } + for (int i = 0; i < list.getLength(); i++) { + Element fileElem = (Element) list.item(i); + try { + String src = pm.getAbsoluteAssetPath(fileElem.getAttribute("path")); + if (src == null) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not find texture with manager!"); + return; + } + FileObject srcFile = FileUtil.toFileObject(new File(src)); + String destName = proman.getAssetFolderName() + "/" + fileElem.getAttribute("path"); + String destFolder = destName.replace("\\", "/"); + destFolder = destFolder.substring(0, destFolder.lastIndexOf("/")); + FileObject folder = FileUtil.createFolder(new File(destFolder)); + srcFile.copy(folder, srcFile.getName(), srcFile.getExt()); + } catch (IOException ex) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not copy texture: {0}", ex.getMessage()); + } + } + return; + } + + public static void addModelFiles(Element assetElement, ProjectAssetManager pm) { + //TODO: not good :/ + NodeList fileNodeList = assetElement.getElementsByTagName("file"); + ProjectAssetManager currentProjectAssetManager = null; + try { + currentProjectAssetManager = SceneApplication.getApplication().getCurrentSceneRequest().getManager(); + if (currentProjectAssetManager == null) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not get project asset manager!"); + return; + } + } catch (Exception e) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not get project asset manager!"); + return; + } + for (int i = 0; i < fileNodeList.getLength(); i++) { + Element fileElem = (Element) fileNodeList.item(i); + String type = fileElem.getAttribute("type"); + if ("texture".equals(type) || "sound".equals(type) || "materialdef".equals(type) || "shader".equals(type) || "other".equals(type)) { + try { + String src = pm.getAbsoluteAssetPath(fileElem.getAttribute("path")); + if (src == null) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not find texture with manager!"); + return; + } + FileObject srcFile = FileUtil.toFileObject(new File(src)); + String destName = currentProjectAssetManager.getAssetFolderName() + "/" + fileElem.getAttribute("path"); + String destFolder = destName.replace("\\", "/"); + destFolder = destFolder.substring(0, destFolder.lastIndexOf("/")); + FileObject folder = FileUtil.createFolder(new File(destFolder)); + srcFile.copy(folder, srcFile.getName(), srcFile.getExt()); + } catch (IOException ex) { + Logger.getLogger(AssetPackLoader.class.getName()).log(Level.SEVERE, "Could not copy texture: {0}", ex.getMessage()); + } + } + } + return; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackProject.zip b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackProject.zip new file mode 100644 index 000000000..aa78f973f Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/AssetPackProject.zip differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/Bundle.properties b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/Bundle.properties new file mode 100644 index 000000000..37e904bbf --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/Bundle.properties @@ -0,0 +1,6 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + AssetPack Support +OpenIDE-Module-Name=AssetPack Support +OpenIDE-Module-Short-Description=AssetPack Support +Templates/Project/AssetPack/AssetPackProject.zip=Asset Pack diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/Installer.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/Installer.java new file mode 100644 index 000000000..c77763070 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/Installer.java @@ -0,0 +1,34 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack; + +import java.io.File; +import org.openide.modules.ModuleInstall; +import org.openide.util.NbPreferences; +import org.openide.util.Utilities; + +/** + * Manages a module's lifecycle. Remember that an installer is optional and + * often not needed at all. + */ +public class Installer extends ModuleInstall { + + @Override + public void restored() { + String path = NbPreferences.forModule(Installer.class).get("assetpack_path", null); + if (path == null) { + //set extraction dir for platform natives + if (Utilities.isMac()) { + String jmpDir = System.getProperty("user.home") + "/Library/Application Support/jmonkeyplatform/assetpacks/"; + NbPreferences.forModule(Installer.class).put("assetpack_path", jmpDir); + new File(jmpDir).mkdirs(); + } else { + String jmpDir = System.getProperty("user.home") + File.separator + ".jmonkeyplatform" + File.separator + "assetpacks" + File.separator; + NbPreferences.forModule(Installer.class).put("assetpack_path", jmpDir); + new File(jmpDir).mkdirs(); + } + } + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/XmlHelper.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/XmlHelper.java new file mode 100644 index 000000000..e44fb91b1 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/XmlHelper.java @@ -0,0 +1,73 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.assetpack; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * + * @author normenhansen + */ +public class XmlHelper { + public static Element findFirstChildElement(Element parent) { + org.w3c.dom.Node ret = parent.getFirstChild(); + while (ret != null && (!(ret instanceof Element))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findChildElement(Element parent, String name) { + if (parent == null) { + return null; + } + org.w3c.dom.Node ret = parent.getFirstChild(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findNextElement(Node ret, String name) { + ret = ret.getNextSibling(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findChildElementWithAttribute(Element parent, String name, String attribute, String value) { + if (parent == null) { + return null; + } + org.w3c.dom.Node ret = parent.getFirstChild(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name) || ((Element)ret).getAttribute(attribute)==null || !((Element)ret).getAttribute(attribute).equals(value))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findNextElementWithAttribute(Node ret, String name, String attribute, String value) { + ret = ret.getNextSibling(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name) || ((Element)ret).getAttribute(attribute)==null || !((Element)ret).getAttribute(attribute).equals(value))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findNextSiblingElement(Element current) { + org.w3c.dom.Node ret = current.getNextSibling(); + while (ret != null) { + if (ret instanceof Element) { + return (Element) ret; + } + ret = ret.getNextSibling(); + } + return null; + } + +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/AddAssetAction.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/AddAssetAction.java new file mode 100644 index 000000000..534c12dd2 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/AddAssetAction.java @@ -0,0 +1,120 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.actions; + +import com.jme3.gde.assetpack.AssetPackLoader; +import com.jme3.gde.assetpack.XmlHelper; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.scene.Spatial; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.Action; +import org.openide.nodes.Node; +import org.w3c.dom.Element; +import com.jme3.gde.scenecomposer.SceneComposerTopComponent; +import java.io.File; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.w3c.dom.NodeList; + +public final class AddAssetAction implements Action { + + private final Node context; + + public AddAssetAction(Node context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + ProjectAssetManager pm = context.getLookup().lookup(ProjectAssetManager.class); + if (pm == null) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "AssetManager not found!"); + return; + } + Element assetElement = context.getLookup().lookup(Element.class); + String type = assetElement.getAttribute("type"); + if ("model".equals(type) || "scene".equals(type)) { + addModelToScene(assetElement, pm); + AssetPackLoader.addModelFiles(assetElement, pm); + } else { + AssetPackLoader.addAllFiles(assetElement, pm); + } + } + + private void addModelToScene(Element assetElement, ProjectAssetManager pm) { +// Element fileElement = XmlHelper.findChildElementWithAttribute(assetElement, "file", "main", "true"); + Spatial model = AssetPackLoader.loadAssetPackModel(assetElement, pm); + if (model != null) { + SceneComposerTopComponent.findInstance().addModel(model); + } else { + Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error loading model"); + return; + } + } + + private void copyModelData(NodeList fileNodeList, ProjectAssetManager pm) { + //TODO: not good :/ + ProjectAssetManager currentProjectAssetManager = null; + try { + currentProjectAssetManager = SceneApplication.getApplication().getCurrentSceneRequest().getManager(); + if (currentProjectAssetManager == null) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Could not get project asset manager!"); + return; + } + } catch (Exception e) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Could not get project asset manager!"); + return; + } + for (int i = 0; i < fileNodeList.getLength(); i++) { + Element fileElem = (Element) fileNodeList.item(i); + String type = fileElem.getAttribute("type"); + if ("texture".equals(type) || "sound".equals(type) || "materialdef".equals(type) || "shader".equals(type) || "other".equals(type)) { + try { + String src = pm.getAbsoluteAssetPath(fileElem.getAttribute("path")); + if (src == null) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Could not find texture with manager!"); + return; + } + FileObject srcFile = FileUtil.toFileObject(new File(src)); + String destName = currentProjectAssetManager.getAssetFolderName() + "/" + fileElem.getAttribute("path"); + String destFolder = destName.replace("\\", "/"); + destFolder = destFolder.substring(0, destFolder.lastIndexOf("/")); + FileObject folder = FileUtil.createFolder(new File(destFolder)); + srcFile.copy(folder, srcFile.getName(), srcFile.getExt()); + } catch (IOException ex) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Could not copy texture: {0}", ex.getMessage()); + } + } + } + return; + } + + public Object getValue(String key) { + if (key.equals(NAME)) { + return "Add to SceneComposer.."; + } + return null; + } + + public void putValue(String key, Object value) { + } + + public void setEnabled(boolean b) { + } + + public boolean isEnabled() { + return true; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/Bundle.properties b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/Bundle.properties new file mode 100644 index 000000000..e330aa8f0 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/Bundle.properties @@ -0,0 +1 @@ +CTL_PreviewAssetPackItem=Preview diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/PreviewAssetAction.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/PreviewAssetAction.java new file mode 100644 index 000000000..505c36c0d --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/actions/PreviewAssetAction.java @@ -0,0 +1,71 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.actions; + +import com.jme3.gde.assetpack.AssetPackLoader; +import com.jme3.gde.core.assets.ProjectAssetManager; +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.scene.Spatial; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.Action; +import org.openide.nodes.Node; +import org.w3c.dom.Element; + +public final class PreviewAssetAction implements Action { + + private final Node context; + + public PreviewAssetAction(Node context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + ProjectAssetManager pm = context.getLookup().lookup(ProjectAssetManager.class); + if (pm == null) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "AssetManager not found!"); + return; + } + Element assetElement = context.getLookup().lookup(Element.class); + com.jme3.scene.Node node = new com.jme3.scene.Node("PreviewRootNode"); + Spatial model = null; + model = AssetPackLoader.loadAssetPackModel(assetElement, pm); + node.attachChild(model); + JmeNode jmeNode = NodeUtility.createNode(node); + SceneApplication app = SceneApplication.getApplication(); + SceneRequest request = new SceneRequest(app, jmeNode, pm); + request.setWindowTitle("SceneViewer - PreView AssetPack Model"); + app.requestScene(request); + + } + + public Object getValue(String key) { + if (key.equals(NAME)) { + return "Preview Asset.."; + } + return null; + } + + public void putValue(String key, Object value) { + } + + public void setEnabled(boolean b) { + } + + public boolean isEnabled() { + return true; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackBrowserTopComponent.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackBrowserTopComponent.form new file mode 100644 index 000000000..70e2658d7 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackBrowserTopComponent.form @@ -0,0 +1,170 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackBrowserTopComponent.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackBrowserTopComponent.java new file mode 100644 index 000000000..adfc81468 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackBrowserTopComponent.java @@ -0,0 +1,335 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.browser; + +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +//import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.actions.CopyAction; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; +import org.openide.explorer.view.BeanTreeView; +import org.openide.nodes.Node; +import org.openide.util.actions.SystemAction; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.assetpack.browser//AssetPackBrowser//EN", +autostore = false) +public final class AssetPackBrowserTopComponent extends TopComponent implements ExplorerManager.Provider { + + private static AssetPackBrowserTopComponent instance; + private transient ExplorerManager explorerManager = new ExplorerManager(); + /** path to the icon used by the component and its open action */ +// static final String ICON_PATH = "SET/PATH/TO/ICON/HERE"; + private static final String PREFERRED_ID = "AssetPackBrowserTopComponent"; + AssetPackLibrary lib; + Node rootNode; + + public AssetPackBrowserTopComponent() { + initComponents(); + initLibrary(); + initActions(); + associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap())); + setName(NbBundle.getMessage(AssetPackBrowserTopComponent.class, "CTL_AssetPackBrowserTopComponent")); + setToolTipText(NbBundle.getMessage(AssetPackBrowserTopComponent.class, "HINT_AssetPackBrowserTopComponent")); + } + + private void initLibrary() { + lib = new AssetPackLibrary(); + rootNode = lib.getRootNode(); + explorerManager.setRootContext(rootNode); + List cats = lib.getCategories(); + for (Iterator it = cats.iterator(); it.hasNext();) { + jComboBox1.addItem(it.next()); + } + } + + private void updateLibrary(){ + rootNode = lib.getRootNode(); + getExplorerManager().setRootContext(rootNode); + jComboBox1.removeAllItems(); + jComboBox1.addItem("All Categories"); + List cats = lib.getCategories(); + for (Iterator it = cats.iterator(); it.hasNext();) { + jComboBox1.addItem(it.next()); + } + } + + private void initActions() { +// CutAction cut = SystemAction.get(CutAction.class); +// getActionMap().put(cut.getActionMapKey(), ExplorerUtils.actionCut(explorerManager)); + CopyAction copy = SystemAction.get(CopyAction.class); + getActionMap().put(copy.getActionMapKey(), ExplorerUtils.actionCopy(explorerManager)); +// PasteAction paste = SystemAction.get(PasteAction.class); +// getActionMap().put(paste.getActionMapKey(), ExplorerUtils.actionPaste(explorerManager)); +// DeleteAction delete = SystemAction.get(DeleteAction.class); +// getActionMap().put(delete.getActionMapKey(), ExplorerUtils.actionDelete(explorerManager, true)); + } + + public ExplorerManager getExplorerManager() { + return explorerManager; + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jToolBar1 = new javax.swing.JToolBar(); + jComboBox1 = new javax.swing.JComboBox(); + jButton1 = new javax.swing.JButton(); + jPanel3 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + jPanel2 = new javax.swing.JPanel(); + jScrollPane1 = new BeanTreeView(); + jToolBar2 = new javax.swing.JToolBar(); + jButton3 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jComboBox1.setFont(new java.awt.Font("Lucida Grande", 0, 12)); // NOI18N + jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "All Categories" })); + jComboBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jComboBox1ActionPerformed(evt); + } + }); + jToolBar1.add(jComboBox1); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(AssetPackBrowserTopComponent.class, "AssetPackBrowserTopComponent.jButton1.text")); // NOI18N + jButton1.setFocusable(false); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar1.add(jButton1); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 10, Short.MAX_VALUE) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel3); + + jTextField1.setFont(new java.awt.Font("Lucida Grande", 0, 12)); // NOI18N + jTextField1.setText(org.openide.util.NbBundle.getMessage(AssetPackBrowserTopComponent.class, "AssetPackBrowserTopComponent.jTextField1.text")); // NOI18N + jTextField1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jTextField1ActionPerformed(evt); + } + }); + jToolBar1.add(jTextField1); + + jPanel2.setLayout(new javax.swing.BoxLayout(jPanel2, javax.swing.BoxLayout.LINE_AXIS)); + jPanel2.add(jScrollPane1); + + jToolBar2.setFloatable(false); + jToolBar2.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jButton3, org.openide.util.NbBundle.getMessage(AssetPackBrowserTopComponent.class, "AssetPackBrowserTopComponent.jButton3.text")); // NOI18N + jButton3.setFocusable(false); + jButton3.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton3.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton3.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton3ActionPerformed(evt); + } + }); + jToolBar2.add(jButton3); + + org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(AssetPackBrowserTopComponent.class, "AssetPackBrowserTopComponent.jButton2.text")); // NOI18N + jButton2.setFocusable(false); + jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + jToolBar2.add(jButton2); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 312, Short.MAX_VALUE) + .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 312, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 312, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 409, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed + rootNode = lib.getRootNode(jTextField1.getText().split(",")); + getExplorerManager().setRootContext(rootNode); + }//GEN-LAST:event_jTextField1ActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + updateLibrary(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + jPanel2.removeAll(); + jPanel2.add(new OnlineBrowser(lib)); + jPanel2.validate(); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed + jPanel2.removeAll(); + jPanel2.add(new BeanTreeView()); + jPanel2.validate(); + }//GEN-LAST:event_jButton3ActionPerformed + + private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed + if (!"All Categories".equals((String) jComboBox1.getSelectedItem())) { + rootNode = lib.getRootNode((String) jComboBox1.getSelectedItem()); + getExplorerManager().setRootContext(rootNode); + }else{ + rootNode = lib.getRootNode(); + getExplorerManager().setRootContext(rootNode); + } + }//GEN-LAST:event_jComboBox1ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JButton jButton3; + private javax.swing.JComboBox jComboBox1; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextField jTextField1; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToolBar jToolBar2; + // End of variables declaration//GEN-END:variables + + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized AssetPackBrowserTopComponent getDefault() { + if (instance == null) { + instance = new AssetPackBrowserTopComponent(); + } + return instance; + } + + /** + * Obtain the AssetPackBrowserTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized AssetPackBrowserTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(AssetPackBrowserTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof AssetPackBrowserTopComponent) { + return (AssetPackBrowserTopComponent) win; + } + Logger.getLogger(AssetPackBrowserTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public HelpCtx getHelpCtx() { + return new HelpCtx("sdk.asset_packs"); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + // TODO add custom code on component closing + } + + @Override + protected void componentActivated() { + ExplorerUtils.activateActions(explorerManager, true); + } + + @Override + protected void componentDeactivated() { + ExplorerUtils.activateActions(explorerManager, false); + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackLibrary.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackLibrary.java new file mode 100644 index 000000000..dc75b62e8 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/AssetPackLibrary.java @@ -0,0 +1,152 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.browser; + +import com.jme3.gde.assetpack.browser.nodes.AssetPackBrowserFolder; +import com.jme3.gde.assetpack.Installer; +import com.jme3.gde.assetpack.XmlHelper; +import com.jme3.gde.core.assets.ProjectAssetManager; +import java.io.File; +import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.project.Project; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.NbPreferences; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +/** + * + * @author normenhansen + */ +public class AssetPackLibrary implements Project { + + FileObject library; + Element[] assetElements = new Element[0]; + InstanceContent content = new InstanceContent(); + Lookup lookup = new AbstractLookup(content); + private ProjectAssetManager projectAssetManager; + private List categories = new LinkedList(); + + public AssetPackLibrary() { + content.add(this); + } + + private void initLibrary() { + String path = NbPreferences.forModule(Installer.class).get("assetpack_path", null); + library = FileUtil.toFileObject(new File(path)); + } + + public Node getRootNode() { + parseLibrary(); + AssetPackBrowserFolder multi = new AssetPackBrowserFolder(assetElements, this); + return multi; + } + + public Node getRootNode(String[] categories, String[] tags) { + parseLibrary(); + AssetPackBrowserFolder multi = new AssetPackBrowserFolder(assetElements, this, categories, tags); + return multi; + } + + public Node getRootNode(String category) { + parseLibrary(); + AssetPackBrowserFolder multi = new AssetPackBrowserFolder(assetElements, this, new String[]{category}, null); + return multi; + } + + public Node getRootNode(String[] tags) { + parseLibrary(); + AssetPackBrowserFolder multi = new AssetPackBrowserFolder(assetElements, this, null, tags); + return multi; + } + + private void parseLibrary() { + initLibrary(); + categories.clear(); + FileObject[] object = library.getChildren(); + List assetElements = new LinkedList(); + for (int i = 0; i < object.length; i++) { + FileObject fileObject = object[i]; + if (fileObject.isFolder()) { + FileObject config = fileObject.getFileObject("assetpack.xml"); + if (config != null) { + + InputStream in; + try { + in = config.getInputStream(); + Document doc = XMLUtil.parse(new InputSource(in), false, false, null, null); + in.close(); + Element assets = XmlHelper.findChildElement(doc.getDocumentElement(), "assets"); + if (assets != null) { + assetElements.add(assets); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + if (projectAssetManager == null) { + projectAssetManager = new ProjectAssetManager(this, fileObject.getNameExt() + "/assets/"); + content.add(projectAssetManager); + } else { + projectAssetManager.addFileLocator(fileObject.getNameExt() + "/assets/"); + } + } else { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Error in assetpack, could not load assetpack.xml!"); + } + } + } + this.assetElements = new Element[assetElements.size()]; + for (int i = 0; i < assetElements.size(); i++) { + Element element = assetElements.get(i); + this.assetElements[i] = element; + Element child = XmlHelper.findChildElement(element, "asset"); + while (child != null) { + String cats = child.getAttribute("categories"); + String[] categs = cats.split(","); + for (int j = 0; j < categs.length; j++) { + String string = categs[j]; + string = string.trim(); + if (!categories.contains(string)) { + categories.add(string); + } + } + child = XmlHelper.findNextElement(child, "asset"); + } + } + } + + public FileObject getProjectDirectory() { + return library; + } + + public Lookup getLookup() { + return lookup; + } + + /** + * @return the projectAssetManager + */ + public ProjectAssetManager getProjectAssetManager() { + return projectAssetManager; + } + + /** + * @return the categories + */ + public List getCategories() { + return categories; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/Bundle.properties b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/Bundle.properties new file mode 100644 index 000000000..515f491de --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/Bundle.properties @@ -0,0 +1,7 @@ +CTL_AssetPackBrowserAction=AssetPackBrowser +CTL_AssetPackBrowserTopComponent=AssetPackBrowser Window +HINT_AssetPackBrowserTopComponent=This is a AssetPackBrowser window +AssetPackBrowserTopComponent.jTextField1.text=search +AssetPackBrowserTopComponent.jButton1.text=update +AssetPackBrowserTopComponent.jButton2.text=online assetpacks +AssetPackBrowserTopComponent.jButton3.text=view library diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.form new file mode 100644 index 000000000..89b619728 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.form @@ -0,0 +1,47 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.java new file mode 100644 index 000000000..d444557c6 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/OnlineBrowser.java @@ -0,0 +1,132 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * OnlineBrowser.java + * + * Created on 25.10.2010, 23:18:26 + */ +package com.jme3.gde.assetpack.browser; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +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.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class OnlineBrowser extends javax.swing.JPanel implements HyperlinkListener { + + private AssetPackLibrary lib; + + /** Creates new form OnlineBrowser */ + public OnlineBrowser(AssetPackLibrary lib) { + initComponents(); + this.lib = lib; + jEditorPane1.addHyperlinkListener(this); + try { + URL url = new URL("http://jmonkeyengine.org/assetpacks/list.php"); + jEditorPane1.setPage(url); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void hyperlinkUpdate(final HyperlinkEvent event) { + if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + new Thread(new Runnable() { + + public void run() { + ProgressHandle handle = ProgressHandleFactory.createHandle("Downloading AssetPack.."); + handle.start(); + String name = event.getURL().toString(); + name = name.substring(name.lastIndexOf("/") + 1, name.length()); + name = name.substring(0, name.lastIndexOf(".")); + name = lib.getProjectDirectory().getPath() + "/" + name; + File folder = new File(name); + folder.mkdirs(); + try { + unZipFile(event.getURL().openStream(), FileUtil.toFileObject(folder)); + } catch (IOException ex) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Error creating URL: {0}", ex.toString()); + } + handle.finish(); + } + }).start(); + } + } + + private void unZipFile(InputStream source, FileObject projectRoot) throws IOException { + try { + ZipInputStream str = new ZipInputStream(source); + ZipEntry entry; + while ((entry = str.getNextEntry()) != null) { + if (entry.isDirectory()) { + FileUtil.createFolder(projectRoot, entry.getName()); + } else { + FileObject fo = FileUtil.createData(projectRoot, entry.getName()); + writeFile(str, fo); + } + } + } finally { + source.close(); + } + } + + private void writeFile(ZipInputStream str, FileObject fo) throws IOException { + OutputStream out = fo.getOutputStream(); + try { + FileUtil.copy(str, out); + } finally { + out.close(); + } + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + jEditorPane1 = new javax.swing.JEditorPane(); + + jEditorPane1.setEditable(false); + jEditorPane1.setFont(new java.awt.Font("Lucida Grande", 0, 12)); // NOI18N + jScrollPane1.setViewportView(jEditorPane1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JEditorPane jEditorPane1; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserChildren.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserChildren.java new file mode 100644 index 000000000..482af13b4 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserChildren.java @@ -0,0 +1,120 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.browser.nodes; + +import com.jme3.gde.assetpack.XmlHelper; +import java.util.LinkedList; +import java.util.List; +import org.netbeans.api.project.Project; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.w3c.dom.Element; + +/** + * + * @author normenhansen + */ +public class AssetPackBrowserChildren extends Children.Keys { + + private Project project; + private Element[] xmlNode; + private String[] categories; + private String[] tags; + + public AssetPackBrowserChildren(Element xmlNode, Project project, String[] categories, String[] tags) { + this.xmlNode = new Element[]{xmlNode}; + this.categories = categories; + this.tags = tags; + this.project = project; + } + + public AssetPackBrowserChildren(Element xmlNode, Project project) { + this.xmlNode = new Element[]{xmlNode}; + this.project = project; + } + + public AssetPackBrowserChildren(Element[] xmlNode, Project project, String[] categories, String[] tags) { + this.xmlNode = xmlNode; + this.categories = categories; + this.tags = tags; + this.project = project; + } + + public AssetPackBrowserChildren(Element[] xmlNode, Project project) { + this.xmlNode = xmlNode; + this.project = project; + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(createKeys()); + } + + protected List createKeys() { + LinkedList ret = new LinkedList(); + for (int i = 0; i < xmlNode.length; i++) { + Element element = xmlNode[i]; + Element curElement = XmlHelper.findFirstChildElement(element); + while (curElement != null) { + if (checkElement(curElement)) { + ret.add(curElement); + + } + curElement = XmlHelper.findNextSiblingElement(curElement); + } + + } + return ret; + } + + private boolean checkElement(Element curElement) { + if (!"asset".equals(curElement.getTagName())) { + return false; + } + boolean checkCategories = false; + boolean checkTags = false; + if (categories != null) { + for (int i = 0; i < categories.length; i++) { + String string = categories[i].trim(); + String cats = curElement.getAttribute("categories"); + if (cats != null) { + String[] catg = cats.split(","); + for (int j = 0; j < catg.length; j++) { + String string1 = catg[j].trim(); + if (string.equalsIgnoreCase(string1)) { + checkCategories = true; + } + } + } + } + } else { + checkCategories = true; + } + if (tags != null) { + for (int i = 0; i < tags.length; i++) { + String string = tags[i].trim(); + String tags = curElement.getAttribute("tags"); + if (tags != null) { + String[] catg = tags.split(","); + for (int j = 0; j < catg.length; j++) { + String string1 = catg[j].trim(); + if (string.equalsIgnoreCase(string1)) { + checkTags = true; + } + } + } + } + } else { + checkTags = true; + } + return checkTags && checkCategories; + } + + @Override + protected Node[] createNodes(Element key) { + return new Node[]{new AssetPackBrowserItem(key, project)}; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserFolder.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserFolder.java new file mode 100644 index 000000000..6c33d362e --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserFolder.java @@ -0,0 +1,63 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.browser.nodes; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import com.jme3.gde.assetpack.project.actions.ImportAssetAction; +import java.awt.Image; +import javax.swing.Action; +import org.netbeans.api.project.Project; +import org.openide.nodes.AbstractNode; +import org.openide.util.ImageUtilities; +import org.w3c.dom.Element; + +/** + * + * @author normenhansen + */ +public class AssetPackBrowserFolder extends AbstractNode { + + Image icon = ImageUtilities.loadImage("/com/jme3/gde/assetpack/icons/assets.gif"); + Project proj; + + public AssetPackBrowserFolder(Element[] elem, Project lib, String[] categories, String[] tags) { + super(new AssetPackBrowserChildren(elem, lib, categories, tags)); + proj = lib; + setName("Assets"); + } + + public AssetPackBrowserFolder(Element[] elem, Project lib) { + super(new AssetPackBrowserChildren(elem, lib)); + proj = lib; + setName("Assets"); + } + + public void refresh() { + ((AssetPackBrowserChildren) getChildren()).addNotify(); + } + + public Action[] getActions(boolean context) { + if (proj instanceof AssetPackProject) { + return new Action[]{new ImportAssetAction((AssetPackProject)proj)}; + } else { + return new Action[]{ // SystemAction.get(RenameAction.class), + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + // SystemAction.get(DeleteAction.class) + }; + } + } + + @Override + public Image getIcon(int type) { + return icon; + } + + @Override + public Image getOpenedIcon(int type) { + return icon; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserItem.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserItem.java new file mode 100644 index 000000000..6c5f1a3e8 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/nodes/AssetPackBrowserItem.java @@ -0,0 +1,109 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.browser.nodes; + +import com.jme3.gde.assetpack.actions.AddAssetAction; +import com.jme3.gde.assetpack.actions.PreviewAssetAction; +import com.jme3.gde.assetpack.browser.AssetPackLibrary; +import com.jme3.gde.assetpack.browser.properties.ElementAttributeProperty; +import com.jme3.gde.assetpack.browser.properties.ElementNodeTextProperty; +import com.jme3.gde.core.assets.ProjectAssetManager; +import java.awt.Image; +import javax.swing.Action; +import org.netbeans.api.project.Project; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.nodes.Sheet.Set; +import org.openide.util.ImageUtilities; +import org.openide.util.lookup.Lookups; +import org.w3c.dom.Element; + +/** + * + * @author normenhansen + */ +public class AssetPackBrowserItem extends AbstractNode { + + public static final String[] ASSET_TYPES = new String[]{ + "model", + "texture", + "sound", + "material", + "other"}; +// public static final String[] ASSET_FORMATS = new String[]{ +// "ogrexml", +// "wavefront", +// "j3o", +// "image", +// "sound", +// "other"}; + private Element item; + private Image icon; + private Project project; + private PreviewAssetAction previewAction; + private AddAssetAction addAction; + + public AssetPackBrowserItem(Element item, Project proj) { + super(Children.LEAF, proj != null ? Lookups.fixed(item, proj, proj.getLookup().lookup(ProjectAssetManager.class)) : Lookups.fixed(item)); + addAction = new AddAssetAction(this); + previewAction = new PreviewAssetAction(this); + this.item = item; + this.project = proj; + setName(item.getAttribute("name")); + setImage(); + } + + private void setImage() { + try { + String add = item.getAttribute("type"); + icon = ImageUtilities.loadImage("/com/jme3/gde/assetpack/icons/" + add + ".gif"); + } catch (Exception e) { + } + } + + @Override + public Image getIcon(int type) { + if (icon != null) { + return icon; + } + return super.getIcon(type); + } + + public Action[] getActions(boolean context) { + if (project.getLookup().lookup(AssetPackLibrary.class) != null) { + return new Action[]{ + addAction, + previewAction + }; + } else { + return new Action[]{previewAction}; + } + } + + @Override + public Action getPreferredAction() { +// if (project.getLookup().lookup(AssetPackLibrary.class) != null) { +// return addAction; +// } else { + return previewAction; +// } + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Set set = Sheet.createPropertiesSet(); + set.put(new ElementAttributeProperty(project, item, "name")); + set.put(new ElementNodeTextProperty(project, item, "description")); + set.put(new ElementAttributeProperty(project, item, "categories")); + set.put(new ElementAttributeProperty(project, item, "tags")); + set.put(new ElementNodeTextProperty(project, item, "license")); + set.put(new ElementAttributeProperty(project, item, "type", ASSET_TYPES)); +// set.put(new ElementAttributeProperty(project, item, "format", ASSET_FORMATS)); + sheet.put(set); + return sheet; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/ElementAttributeProperty.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/ElementAttributeProperty.java new file mode 100644 index 000000000..3b7d85888 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/ElementAttributeProperty.java @@ -0,0 +1,87 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.browser.properties; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import java.beans.PropertyEditor; +import java.lang.reflect.InvocationTargetException; +import org.netbeans.api.project.Project; +import org.openide.nodes.Node.Property; +import org.w3c.dom.Element; + +/** + * + * @author normenhansen + */ +public class ElementAttributeProperty extends Property { + + private boolean readOnly; + private Element element; + private String attribute; + private PropertyEditor editor; + private Project project; + + public ElementAttributeProperty(Project project, Element element, String attribute) { + this(project, element, attribute, false); + } + + public ElementAttributeProperty(Project project, Element element, String attribute, String[] tags) { + this(project, element, attribute, tags, false); + } + + public ElementAttributeProperty(Project project, Element element, String attribute, boolean readOnly) { + this(project, element, attribute, null, readOnly); + } + + public ElementAttributeProperty(Project project, Element element, String attribute, String[] tags, boolean readOnly) { + super(String.class); + this.project = project; + this.readOnly = readOnly; + this.element = element; + this.attribute = attribute; + setName(attribute); + if (tags != null) { + editor = new SelectionPropertyEditor(tags, element.getAttribute(attribute)); + } + } + + @Override + public PropertyEditor getPropertyEditor() { + if (editor != null) { + return editor; + } + return super.getPropertyEditor(); + } + + @Override + public boolean canRead() { + return true; + } + + @Override + public String getValue() throws IllegalAccessException, InvocationTargetException { + return element.getAttribute(attribute); + } + + @Override + public boolean canWrite() { + if (this.project != null && this.project.getLookup().lookup(AssetPackProject.class) == null) { + return false; + } + return !readOnly; + } + + @Override + public void setValue(String val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + element.setAttribute(attribute, val); + if (this.project == null) { + return; + } + AssetPackProject project = this.project.getLookup().lookup(AssetPackProject.class); + if (project != null) { + project.saveSettings(); + } + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/ElementNodeTextProperty.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/ElementNodeTextProperty.java new file mode 100644 index 000000000..91580b7af --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/ElementNodeTextProperty.java @@ -0,0 +1,88 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.browser.properties; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import java.beans.PropertyEditor; +import java.lang.reflect.InvocationTargetException; +import org.openide.nodes.Node.Property; +import org.w3c.dom.Element; +import com.jme3.gde.assetpack.XmlHelper; +import org.netbeans.api.project.Project; + +/** + * + * @author normenhansen + */ +public class ElementNodeTextProperty extends Property { + + private boolean readOnly; + private Element element; + private String attribute; + private PropertyEditor editor; + private Project project; + + public ElementNodeTextProperty(Project project, Element element, String attribute) { + this(project, element, attribute, false); + } + + public ElementNodeTextProperty(Project project, Element element, String attribute, String[] tags) { + this(project, element, attribute, tags, false); + } + + public ElementNodeTextProperty(Project project, Element element, String attribute, boolean readOnly) { + this(project, element, attribute, null, readOnly); + } + + public ElementNodeTextProperty(Project project, Element element, String attribute, String[] tags, boolean readOnly) { + super(String.class); + this.readOnly = readOnly; + this.element = element; + this.attribute = attribute; + this.project = project; + setName(attribute); + if (tags != null) { + editor = new SelectionPropertyEditor(tags, element.getAttribute(attribute)); + } + } + + @Override + public PropertyEditor getPropertyEditor() { + if (editor != null) { + return editor; + } + return super.getPropertyEditor(); + } + + @Override + public boolean canRead() { + return true; + } + + @Override + public String getValue() throws IllegalAccessException, InvocationTargetException { + return XmlHelper.findChildElement(element, attribute).getTextContent();// element.getAttribute(attribute); + } + + @Override + public boolean canWrite() { + if (this.project != null && this.project.getLookup().lookup(AssetPackProject.class) == null) { + return false; + } + return !readOnly; + } + + @Override + public void setValue(String val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + XmlHelper.findChildElement(element, attribute).setTextContent(val); + if (this.project == null) { + return; + } + AssetPackProject project = this.project.getLookup().lookup(AssetPackProject.class); + if (project != null) { + project.saveSettings(); + } + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/SelectionPropertyEditor.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/SelectionPropertyEditor.java new file mode 100644 index 000000000..191bbe2f9 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/browser/properties/SelectionPropertyEditor.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2009-2010 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.assetpack.browser.properties; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author normenhansen + */ +public class SelectionPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private String value = new String(); + String[] tags = new String[0]; + + public SelectionPropertyEditor(String[] tags, String value) { + this.tags = tags; + this.value = value; + } + + public void setValue(Object value) { + if (value instanceof String) { + value = (String) value; + } + } + + public Object getValue() { + return value; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + return value.toString(); + } + + public void setAsText(final String text) throws IllegalArgumentException { + String old = value; + value = text; + notifyListeners(old, value); + } + + public String[] getTags() { + return tags; + } + + public Component getCustomEditor() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(String before, String after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack.png b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack.png new file mode 100644 index 000000000..c866d25e5 Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack.png differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack_24.png b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack_24.png new file mode 100644 index 000000000..39f043ce4 Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack_24.png differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack_48.png b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack_48.png new file mode 100644 index 000000000..c6e17fdd5 Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assetpack_48.png differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assets.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assets.gif new file mode 100644 index 000000000..941730bab Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/assets.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/font.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/font.gif new file mode 100644 index 000000000..3747a103e Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/font.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/gui.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/gui.gif new file mode 100644 index 000000000..421d54335 Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/gui.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/material.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/material.gif new file mode 100644 index 000000000..7f524523f Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/material.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/model.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/model.gif new file mode 100644 index 000000000..eeab8ff3a Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/model.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/scene.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/scene.gif new file mode 100644 index 000000000..95ca42aba Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/scene.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/sound.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/sound.gif new file mode 100644 index 000000000..6b7af790a Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/sound.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/texture.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/texture.gif new file mode 100644 index 000000000..638f48ff0 Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/icons/texture.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/layer.xml b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/layer.xml new file mode 100644 index 000000000..586c50b9f --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/layer.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/online/MultiPartFormOutputStream.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/online/MultiPartFormOutputStream.java new file mode 100644 index 000000000..f901a563d --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/online/MultiPartFormOutputStream.java @@ -0,0 +1,401 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.online; + +import java.io.*; +import java.net.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.progress.ProgressHandle; + +/** + * MultiPartFormOutputStream is used to write + * "multipart/form-data" to a java.net.URLConnection for + * POSTing. This is primarily for file uploading to HTTP servers. + * + * @since JDK1.3 + */ +public class MultiPartFormOutputStream { + + /** + * The line end characters. + */ + private static final String NEWLINE = "\r\n"; + /** + * The boundary prefix. + */ + private static final String PREFIX = "--"; + /** + * The output stream to write to. + */ + private DataOutputStream out = null; + /** + * The multipart boundary string. + */ + private String boundary = null; + + /** + * Creates a new MultiPartFormOutputStream object using + * the specified output stream and boundary. The boundary is required + * to be created before using this method, as described in the + * description for the getContentType(String) method. + * The boundary is only checked for null or empty string, + * but it is recommended to be at least 6 characters. (Or use the + * static createBoundary() method to create one.) + * + * @param os the output stream + * @param boundary the boundary + * @see #createBoundary() + * @see #getContentType(String) + */ + public MultiPartFormOutputStream(OutputStream os, String boundary) { + if (os == null) { + throw new IllegalArgumentException("Output stream is required."); + } + if (boundary == null || boundary.length() == 0) { + throw new IllegalArgumentException("Boundary stream is required."); + } + this.out = new DataOutputStream(os); + this.boundary = boundary; + } + + /** + * Writes an boolean field value. + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, boolean value) + throws java.io.IOException { + writeField(name, new Boolean(value).toString()); + } + + /** + * Writes an double field value. + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, double value) + throws java.io.IOException { + writeField(name, Double.toString(value)); + } + + /** + * Writes an float field value. + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, float value) + throws java.io.IOException { + writeField(name, Float.toString(value)); + } + + /** + * Writes an long field value. + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, long value) + throws java.io.IOException { + writeField(name, Long.toString(value)); + } + + /** + * Writes an int field value. + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, int value) + throws java.io.IOException { + writeField(name, Integer.toString(value)); + } + + /** + * Writes an short field value. + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, short value) + throws java.io.IOException { + writeField(name, Short.toString(value)); + } + + /** + * Writes an char field value. + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, char value) + throws java.io.IOException { + writeField(name, new Character(value).toString()); + } + + /** + * Writes an string field value. If the value is null, an empty string + * is sent (""). + * + * @param name the field name (required) + * @param value the field value + * @throws java.io.IOException on input/output errors + */ + public void writeField(String name, String value) + throws java.io.IOException { + if (name == null) { + throw new IllegalArgumentException("Name cannot be null or empty."); + } + if (value == null) { + value = ""; + } + /* + --boundary\r\n + Content-Disposition: form-data; name=""\r\n + \r\n + \r\n + */ + // write boundary + out.writeBytes(PREFIX); + out.writeBytes(boundary); + out.writeBytes(NEWLINE); + // write content header + out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\""); + out.writeBytes(NEWLINE); + out.writeBytes(NEWLINE); + // write content + out.writeBytes(value); + out.writeBytes(NEWLINE); + out.flush(); + } + + /** + * Writes a file's contents. If the file is null, does not exists, or + * is a directory, a java.lang.IllegalArgumentException + * will be thrown. + * + * @param name the field name + * @param mimeType the file content type (optional, recommended) + * @param file the file (the file must exist) + * @throws java.io.IOException on input/output errors + */ + public void writeFile(String name, String mimeType, File file) + throws java.io.IOException { + if (file == null) { + throw new IllegalArgumentException("File cannot be null."); + } + if (!file.exists()) { + throw new IllegalArgumentException("File does not exist."); + } + if (file.isDirectory()) { + throw new IllegalArgumentException("File cannot be a directory."); + } + writeFile(name, mimeType, file.getCanonicalPath(), new FileInputStream(file)); + } + + /** + * Writes a input stream's contents. If the input stream is null, a + * java.lang.IllegalArgumentException will be thrown. + * + * @param name the field name + * @param mimeType the file content type (optional, recommended) + * @param fileName the file name (required) + * @param is the input stream + * @throws java.io.IOException on input/output errors + */ + public void writeFile(String name, String mimeType, + String fileName, InputStream is) + throws java.io.IOException { + if (is == null) { + throw new IllegalArgumentException("Input stream cannot be null."); + } + if (fileName == null || fileName.length() == 0) { + throw new IllegalArgumentException("File name cannot be null or empty."); + } + /* + --boundary\r\n + Content-Disposition: form-data; name=""; filename=""\r\n + Content-Type: \r\n + \r\n + \r\n + */ + // write boundary + out.writeBytes(PREFIX); + out.writeBytes(boundary); + out.writeBytes(NEWLINE); + // write content header + out.writeBytes("Content-Disposition: form-data; name=\"" + name + + "\"; filename=\"" + fileName + "\""); + out.writeBytes(NEWLINE); + if (mimeType != null) { + out.writeBytes("Content-Type: " + mimeType); + out.writeBytes(NEWLINE); + } + out.writeBytes(NEWLINE); + // write content + byte[] data = new byte[1024]; + int r = 0; + while ((r = is.read(data, 0, data.length)) != -1) { + out.write(data, 0, r); + } + // close input stream, but ignore any possible exception for it + try { + is.close(); + } catch (Exception e) { + } + out.writeBytes(NEWLINE); + out.flush(); + } + + /** + * Writes the given bytes. The bytes are assumed to be the contents + * of a file, and will be sent as such. If the data is null, a + * java.lang.IllegalArgumentException will be thrown. + * + * @param name the field name + * @param mimeType the file content type (optional, recommended) + * @param fileName the file name (required) + * @param data the file data + * @throws java.io.IOException on input/output errors + */ + public void writeFile(String name, String mimeType, + String fileName, byte[] data) + throws java.io.IOException { + if (data == null) { + throw new IllegalArgumentException("Data cannot be null."); + } + if (fileName == null || fileName.length() == 0) { + throw new IllegalArgumentException("File name cannot be null or empty."); + } + /* + --boundary\r\n + Content-Disposition: form-data; name=""; filename=""\r\n + Content-Type: \r\n + \r\n + \r\n + */ + // write boundary + out.writeBytes(PREFIX); + out.writeBytes(boundary); + out.writeBytes(NEWLINE); + // write content header + out.writeBytes("Content-Disposition: form-data; name=\"" + name + + "\"; filename=\"" + fileName + "\""); + out.writeBytes(NEWLINE); + if (mimeType != null) { + out.writeBytes("Content-Type: " + mimeType); + out.writeBytes(NEWLINE); + } + out.writeBytes(NEWLINE); + // write content + out.write(data, 0, data.length); + out.writeBytes(NEWLINE); + out.flush(); + } + + /** + * Flushes the stream. Actually, this method does nothing, as the only + * write methods are highly specialized and automatically flush. + * + * @throws java.io.IOException on input/output errors + */ + public void flush() throws java.io.IOException { + // out.flush(); + } + + /** + * Closes the stream.
+ *
+ * NOTE: This method MUST be called to finalize the + * multipart stream. + * + * @throws java.io.IOException on input/output errors + */ + public void close() throws java.io.IOException { + // write final boundary + out.writeBytes(PREFIX); + out.writeBytes(boundary); + out.writeBytes(PREFIX); + out.writeBytes(NEWLINE); + out.flush(); + out.close(); + } + + /** + * Gets the multipart boundary string being used by this stream. + * + * @return the boundary + */ + public String getBoundary() { + return this.boundary; + } + + /** + * Creates a new java.net.URLConnection object from the + * specified java.net.URL. This is a convenience method + * which will set the doInput, doOutput, + * useCaches and defaultUseCaches fields to + * the appropriate settings in the correct order. + * + * @return a java.net.URLConnection object for the URL + * @throws java.io.IOException on input/output errors + */ + public static URLConnection createConnection(URL url) + throws java.io.IOException { + URLConnection urlConn = url.openConnection(); + if (urlConn instanceof HttpURLConnection) { + HttpURLConnection httpConn = (HttpURLConnection) urlConn; + httpConn.setRequestMethod("POST"); + } + urlConn.setDoInput(true); + urlConn.setDoOutput(true); + urlConn.setUseCaches(false); + urlConn.setDefaultUseCaches(false); + return urlConn; + } + + /** + * Creates a multipart boundary string by concatenating 20 hyphens (-) + * and the hexadecimal (base-16) representation of the current time in + * milliseconds. + * + * @return a multipart boundary string + * @see #getContentType(String) + */ + public static String createBoundary() { + return "--------------------" + + Long.toString(System.currentTimeMillis(), 16); + } + + /** + * Gets the content type string suitable for the + * java.net.URLConnection which includes the multipart + * boundary string.
+ *
+ * This method is static because, due to the nature of the + * java.net.URLConnection class, once the output stream + * for the connection is acquired, it's too late to set the content + * type (or any other request parameter). So one has to create a + * multipart boundary string first before using this class, such as + * with the createBoundary() method. + * + * @param boundary the boundary string + * @return the content type string + * @see #createBoundary() + */ + public static String getContentType(String boundary) { + return "multipart/form-data; boundary=" + boundary; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/online/OnlinePacksConnector.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/online/OnlinePacksConnector.java new file mode 100644 index 000000000..8269d82c3 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/online/OnlinePacksConnector.java @@ -0,0 +1,75 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.online; + +import java.io.*; +import java.net.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Confirmation; +import org.openide.filesystems.FileUtil; + +/** + * + * @author normenhansen + */ +public class OnlinePacksConnector { + + public static void upload(String exsistingFileName, String user, String pass) { + upload("http://jmonkeyengine.org/assetpacks/upload.php", exsistingFileName, user, pass); + } + + public static void upload(String urlString, String exsistingFileName, String user, String pass) { + try { + File file = new File(exsistingFileName); + int size = (int) FileUtil.toFileObject(file).getSize(); + Logger.getLogger(OnlinePacksConnector.class.getName()).log(Level.FINE, "Upload file size: {0}", size); + + URL url = new URL(urlString); + String boundary = MultiPartFormOutputStream.createBoundary(); + URLConnection urlConn = MultiPartFormOutputStream.createConnection(url); + urlConn.setRequestProperty("Accept", "*/*"); + urlConn.setRequestProperty("Content-Type", MultiPartFormOutputStream.getContentType(boundary)); + urlConn.setRequestProperty("Connection", "Keep-Alive"); + urlConn.setRequestProperty("Cache-Control", "no-cache"); + MultiPartFormOutputStream out = new MultiPartFormOutputStream(urlConn.getOutputStream(), boundary); + // write a text field element + out.writeField("user", user); + out.writeField("pass", pass); + // upload a file + out.writeFile("file", "application/zip", file); + // can also write bytes directly + //out.writeFile("myFile", "text/plain", "C:\\test.txt", + // "This is some file text.".getBytes("ASCII")); + out.close(); + // read response from server + BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream())); + String line = ""; + while ((line = in.readLine()) != null) { + if (line.startsWith("Error:")) { + line = line.substring(6, line.length()).trim(); + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error uploading to jmonkeyengine.org!\n" + line, + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + }else{ + Confirmation msg = new NotifyDescriptor.Confirmation( + "Successfully uploaded to jmonkeyengine.org!\n" + line, + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.INFORMATION_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + System.out.println(line); + } + in.close(); + } catch (Exception ex) { + Logger.getLogger(OnlinePacksConnector.class.getName()).log(Level.SEVERE, null, ex); + } finally { + } + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProject.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProject.java new file mode 100644 index 000000000..0cbb013c7 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProject.java @@ -0,0 +1,397 @@ +package com.jme3.gde.assetpack.project; + +import com.jme3.gde.assetpack.XmlHelper; +import com.jme3.gde.assetpack.browser.nodes.AssetPackBrowserFolder; +import com.jme3.gde.assetpack.project.properties.GeneralSettingsPanel; +import com.jme3.gde.assetpack.project.properties.LicensePanel; +import com.jme3.gde.core.assets.ProjectAssetManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectInformation; +import org.netbeans.spi.project.ActionProvider; +import org.netbeans.spi.project.DeleteOperationImplementation; +import org.netbeans.spi.project.CopyOperationImplementation; +import org.netbeans.spi.project.ProjectState; +import org.netbeans.spi.project.ui.CustomizerProvider; +import org.netbeans.spi.project.ui.LogicalViewProvider; +import org.netbeans.spi.project.ui.support.DefaultProjectOperations; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; +import org.netbeans.spi.project.ui.support.ProjectCustomizer.Category; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; +import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +public class AssetPackProject implements Project { + + private final FileObject projectDir; + private LogicalViewProvider logicalView = new AssetPackProjectLogicalView(this); + private String assetsFolder = "assets"; + private final ProjectState state; + private Lookup lkp; + private ProjectAssetManager projectAssetManager; + private Document configuration; + private AssetPackProjectCustomizer projectCustomizer; + private AssetPackBrowserFolder assetPackFolder; + + public AssetPackProject(FileObject projectDir, ProjectState state) { + this.projectDir = projectDir; + this.state = state; + projectAssetManager = new ProjectAssetManager(this, assetsFolder); + loadProjectFile(); + projectCustomizer = new AssetPackProjectCustomizer(this); + } + + @Override + public FileObject getProjectDirectory() { + return projectDir; + } + + private FileObject getConfigFile() { + FileObject folder = projectDir; + FileObject file = folder.getFileObject(AssetPackProjectFactory.CONFIG_NAME); + if (file == null) { + try { + return folder.createData(AssetPackProjectFactory.CONFIG_NAME); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + return file; + } + + private void loadProjectFile() { + InputStream in = null; + try { + FileObject file = getConfigFile(); + in = file.getInputStream(); + configuration = XMLUtil.parse(new InputSource(in), false, false, null, null); + in.close(); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } finally { + } + } + + public FileObject getAssetsFolder() { + FileObject result = + projectDir.getFileObject(assetsFolder); + try { + if (result == null) { + result = projectDir.createFolder(assetsFolder); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + return result; + } + + public String getDescription() { + Element properties = null; + properties = XmlHelper.findChildElement(configuration.getDocumentElement(), "description"); + if (properties == null) { + return ""; + } + return properties.getTextContent().trim(); + } + + public void setDescription(String description) { + Element properties = null; + properties = XmlHelper.findChildElement(configuration.getDocumentElement(), "description"); + if (properties == null) { + return; + } + properties.setTextContent(description); + } + + public String getLicense() { + Element properties = null; + properties = XmlHelper.findChildElement(configuration.getDocumentElement(), "license"); + if (properties == null) { + return ""; + } + return properties.getTextContent().trim(); + } + + public void setLicense(String description) { + Element properties = null; + properties = XmlHelper.findChildElement(configuration.getDocumentElement(), "license"); + if (properties == null) { + properties = configuration.createElement("license"); + configuration.appendChild(properties); + } + properties.setTextContent(description); + } + + public String getProjectName() { + return configuration.getDocumentElement().getAttribute("name"); + } + + public void setProjectName(String name) { + configuration.getDocumentElement().setAttribute("name", name); + } + + public String getDistributorName() { + return configuration.getDocumentElement().getAttribute("distributor"); + } + + public void setDistributorName(String name) { + configuration.getDocumentElement().setAttribute("distributor", name); + } + + public String getVersion() { + return configuration.getDocumentElement().getAttribute("version"); + } + + public void setVersion(String name) { + configuration.getDocumentElement().setAttribute("version", name); + } + + public void saveSettings() { + FileLock lock = null; + try { + FileObject file = getConfigFile(); + lock = file.lock(); + OutputStream out = file.getOutputStream(lock); + XMLUtil.write(configuration, out, "UTF-8"); + if (out != null) { + out.close(); + + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } finally { + if (lock != null) { + lock.releaseLock(); + } + } + } + + public Element getProjectAssets() { + return XmlHelper.findChildElement(configuration.getDocumentElement(), "assets"); + } + + public Element getProjectDescription() { + return XmlHelper.findChildElement(configuration.getDocumentElement(), "description"); + } + + public Element getProjectLicense() { + return XmlHelper.findChildElement(configuration.getDocumentElement(), "license"); + } + + @Override + public Lookup getLookup() { + if (lkp == null) { + lkp = Lookups.fixed(new Object[]{ + this, //project spec requires a project be in its own lookup + state, //allow outside code to mark the project as needing saving + logicalView, //Logical view of project implementation + projectAssetManager, + projectCustomizer, + new ActionProviderImpl(), //Provides standard actions like Build and Clean + new DemoDeleteOperation(), + new DemoCopyOperation(this), + new Info(), //Project information implementation + }); + } + return lkp; + } + + public ProjectAssetManager getProjectAssetManager() { + return projectAssetManager; + } + + public AssetPackProjectCustomizer getProjectCustomizer() { + return projectCustomizer; + } + + /** + * @return the configuration + */ + public Document getConfiguration() { + return configuration; + } + + public AssetPackBrowserFolder getAssetPackFolder() { + return assetPackFolder; + } + + public AssetPackBrowserFolder setAssetPackFolder(AssetPackBrowserFolder folder) { + assetPackFolder = folder; + return assetPackFolder; + } + +// public void showProjectCustomizer(){ +// ProjectCustomizer.createCustomizerDialog("com-jme3-gde-assetpack", this.getLookup(), "General", null, HelpCtx.DEFAULT_HELP).setVisible(true); +// } + private final class ActionProviderImpl implements ActionProvider { + + private String[] supported = new String[]{ + ActionProvider.COMMAND_DELETE, + ActionProvider.COMMAND_COPY,}; + + @Override + public String[] getSupportedActions() { + return supported; + } + + @Override + public void invokeAction(String string, Lookup lookup) throws IllegalArgumentException { + if (string.equalsIgnoreCase(ActionProvider.COMMAND_DELETE)) { + DefaultProjectOperations.performDefaultDeleteOperation(AssetPackProject.this); + } + if (string.equalsIgnoreCase(ActionProvider.COMMAND_COPY)) { + DefaultProjectOperations.performDefaultCopyOperation(AssetPackProject.this); + } + } + + @Override + public boolean isActionEnabled(String command, Lookup lookup) throws IllegalArgumentException { + if ((command.equals(ActionProvider.COMMAND_DELETE))) { + return true; + } else if ((command.equals(ActionProvider.COMMAND_COPY))) { + return true; + } else { + throw new IllegalArgumentException(command); + } + } + } + + private final class DemoDeleteOperation implements DeleteOperationImplementation { + + public void notifyDeleting() throws IOException { + } + + public void notifyDeleted() throws IOException { + } + + public List getMetadataFiles() { + List dataFiles = new ArrayList(); + return dataFiles; + } + + public List getDataFiles() { + List dataFiles = new ArrayList(); + return dataFiles; + } + } + + private final class DemoCopyOperation implements CopyOperationImplementation { + + private final AssetPackProject project; + private final FileObject projectDir; + + public DemoCopyOperation(AssetPackProject project) { + this.project = project; + this.projectDir = project.getProjectDirectory(); + } + + public List getMetadataFiles() { + return Collections.EMPTY_LIST; + } + + public List getDataFiles() { + return Collections.EMPTY_LIST; + } + + public void notifyCopying() throws IOException { + } + + public void notifyCopied(Project arg0, File arg1, String arg2) throws IOException { + } + } + + private final class AssetPackProjectCustomizer implements CustomizerProvider, ProjectCustomizer.CategoryComponentProvider, ActionListener { + + private Category[] propertyCategories = new Category[]{ + Category.create("General", "General", null), + Category.create("License", "License", null),}; + AssetPackProject project; + GeneralSettingsPanel panel1; + LicensePanel panel2; + + public AssetPackProjectCustomizer(AssetPackProject project) { + this.project = project; + } + + public void showCustomizer() { + ProjectCustomizer.createCustomizerDialog(propertyCategories, this, "General", this, new HelpCtx("sdk.asset_packs")).setVisible(true); + } + + public JComponent create(Category category) { + if (category.getName().equals("General")) { + panel1 = + new GeneralSettingsPanel(project); + return panel1; + } else if (category.getName().equals("License")) { + panel2 = + new LicensePanel(project); + return panel2; + } else { + return new JPanel(); + } + + } + + public void actionPerformed(ActionEvent e) { + panel1.actionPerformed(null); + panel2.actionPerformed(null); + saveSettings(); + } + } + + /** Implementation of project system's ProjectInformation class */ + private final class Info implements ProjectInformation { + + @Override + public Icon getIcon() { + return new ImageIcon(ImageUtilities.loadImage( + "com/jme3/gde/assetpack/icons/assetpack.png")); + } + + @Override + public String getName() { + return getProjectName(); + } + + @Override + public String getDisplayName() { + return getProjectName(); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener pcl) { + //do nothing, won't change + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener pcl) { + //do nothing, won't change + } + + @Override + public Project getProject() { + return AssetPackProject.this; + } + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectDescription.html b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectDescription.html new file mode 100644 index 000000000..c8fcf1de5 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectDescription.html @@ -0,0 +1,15 @@ + + + + + + + An AssetPack allows you to pack models, textures, sounds and other assets + into packages that you can browse inside jMP and easily add the assets to any project. + You can also distribute your AssetPack to other users in the form of zip files + or via jmonkeyengine.org + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectFactory.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectFactory.java new file mode 100644 index 000000000..31e1508d9 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectFactory.java @@ -0,0 +1,39 @@ +package com.jme3.gde.assetpack.project; + +import java.io.IOException; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ProjectFactory; +import org.netbeans.spi.project.ProjectState; +import org.openide.filesystems.FileObject; + +public class AssetPackProjectFactory implements ProjectFactory { + + public static final String CONFIG_NAME = "assetpack.xml"; + + //Specifies when a project is a project, i.e. properties file exists + @Override + public boolean isProject(FileObject projectDirectory) { + if (projectDirectory.getFileObject(CONFIG_NAME) != null) { + return true; + } + return false; + } + + //Specifies when the project will be opened, i.e., + //if the project exists: + @Override + public Project loadProject(FileObject dir, ProjectState state) throws IOException { + return isProject(dir) ? new AssetPackProject(dir, state) : null; + } + + @Override + public void saveProject(final Project project) throws IOException, ClassCastException { + FileObject projectRoot = project.getProjectDirectory(); + if (projectRoot.getFileObject(CONFIG_NAME) == null) { + throw new IOException("Project Settings " + projectRoot.getPath() + + " deleted," + + " cannot save project"); + } + ((AssetPackProject)project).saveSettings(); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectLogicalView.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectLogicalView.java new file mode 100644 index 000000000..6984d82f2 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/AssetPackProjectLogicalView.java @@ -0,0 +1,148 @@ +package com.jme3.gde.assetpack.project; + +import com.jme3.gde.assetpack.project.actions.PublishAssetPackAction; +import com.jme3.gde.assetpack.browser.nodes.AssetPackBrowserFolder; +import com.jme3.gde.assetpack.project.actions.ConvertOgreBinaryMeshesAction; +import java.awt.Image; +import java.util.LinkedList; +import java.util.List; +import javax.swing.Action; +import org.netbeans.spi.project.ui.LogicalViewProvider; +import org.netbeans.spi.project.ui.support.CommonProjectActions; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; +import org.w3c.dom.Element; + +class AssetPackProjectLogicalView implements LogicalViewProvider { + + private final AssetPackProject project; + + public AssetPackProjectLogicalView(AssetPackProject project) { + this.project = project; + } + + @Override + public org.openide.nodes.Node createLogicalView() { + + try { + return new ProjectNode(project); + } catch (DataObjectNotFoundException donfe) { + Exceptions.printStackTrace(donfe); + //Fallback—the directory couldn't be created - + //read-only filesystem or something evil happened + return new AbstractNode(Children.LEAF); + } + } + + /** This is the node you actually see in the project tab for the project */ + private static final class ProjectNode extends AbstractNode { + + private InstanceContent instanceContent; + final AssetPackProject project; + + public ProjectNode(AssetPackProject project) throws DataObjectNotFoundException { + super(new ProjectChildren(project), new ProjectLookup(new InstanceContent())); + this.project = project; + instanceContent = ((ProjectLookup) getLookup()).getInstanceContent(); + instanceContent.add(project); + instanceContent.add(project.getProjectAssetManager()); +// instanceContent.add(project.getProjectCustomizer()); + } + + @Override + public Action[] getActions(boolean arg0) { + Action[] nodeActions = new Action[8]; + nodeActions[0] = new PublishAssetPackAction(project); + nodeActions[1] = new ConvertOgreBinaryMeshesAction(project); + nodeActions[2] = CommonProjectActions.copyProjectAction(); + nodeActions[3] = CommonProjectActions.deleteProjectAction(); + nodeActions[5] = CommonProjectActions.setAsMainProjectAction(); + nodeActions[6] = CommonProjectActions.closeProjectAction(); + nodeActions[7] = CommonProjectActions.customizeProjectAction(); + return nodeActions; + } + + @Override + public Image getIcon(int type) { + return ImageUtilities.loadImage("com/jme3/gde/assetpack/icons/assetpack.png"); + } + + @Override + public Image getOpenedIcon(int type) { + return getIcon(type); + } + + @Override + public String getDisplayName() { + return project.getProjectName(); + } + } + + public static final class ProjectLookup extends AbstractLookup { + + private static final long serialVersionUID = 1214314412L; + private InstanceContent instanceContent; + + public ProjectLookup(InstanceContent instanceContent) { + super(instanceContent); + this.instanceContent = instanceContent; + instanceContent.add(this); + } + + public InstanceContent getInstanceContent() { + return instanceContent; + } + } + + private static final class ProjectChildren extends Children.Keys { + + AssetPackProject project; + Node node; + + public ProjectChildren(AssetPackProject project) { + this.project = project; + node = project.getAssetPackFolder(); + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(createKeys()); + } + + protected List createKeys() { + LinkedList ret = new LinkedList(); + ret.add(new Object()); + return ret; + } + + @Override + protected Node[] createNodes(Object key) { + if (node == null) { +// try { +// ProjectAssetManager manager = project.getProjectAssetManager(); +// FileObject assets = project.getAssetsFolder(); +// node = new ProjectAssetsNode(manager, project, DataFolder.find(assets).getNodeDelegate()); +// } catch (DataObjectNotFoundException ex) { +// Exceptions.printStackTrace(ex); +// node = new AbstractNode(Children.LEAF); +// node.setDisplayName("error"); +// } + node = project.setAssetPackFolder(new AssetPackBrowserFolder(new Element[]{project.getProjectAssets()}, project)); + } + return new Node[]{node}; + } + } + + @Override + public Node findPath(Node root, Object target) { + //leave unimplemented for now + return null; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ConvertOgreBinaryMeshesAction.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ConvertOgreBinaryMeshesAction.java new file mode 100644 index 000000000..3d647a4f8 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ConvertOgreBinaryMeshesAction.java @@ -0,0 +1,147 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.actions; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import com.jme3.gde.assetpack.project.wizards.ConvertOgreBinaryWizardPanel1; +import com.jme3.gde.ogretools.convert.OgreXMLConvert; +import com.jme3.gde.ogretools.convert.OgreXMLConvertOptions; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.text.MessageFormat; +import java.util.logging.Level; +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; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + +public final class ConvertOgreBinaryMeshesAction implements Action { + + private final Project context; + private WizardDescriptor.Panel[] panels; + + public ConvertOgreBinaryMeshesAction(Project context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle("Convert Ogre Binary Meshes"); + wizardDescriptor.putProperty("project", context); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + final boolean deleteFiles = (Boolean) wizardDescriptor.getProperty("deleteoriginal"); + if (!cancelled) { + new Thread(new Runnable() { + + public void run() { + scanDir(((AssetPackProject) context).getAssetsFolder().getPath(), deleteFiles); + } + }).start(); + } + } + + public void scanDir(String dir2scan, boolean delete) { + ProgressHandle handle = ProgressHandleFactory.createHandle("Convert Ogre Binary Files"); + handle.start(); + try { + File zipDir = new File(dir2scan); + String[] dirList = zipDir.list(); + for (int i = 0; i < dirList.length; i++) { + File f = new File(zipDir, dirList[i]); + if (f.isDirectory()) { + String filePath = f.getPath(); + scanDir(filePath, delete); + continue; + } + FileObject fobj = FileUtil.toFileObject(f); + if (fobj.getExt().equalsIgnoreCase("mesh")||fobj.getExt().equalsIgnoreCase("skeleton")) { + OgreXMLConvertOptions options = new OgreXMLConvertOptions(fobj.getPath()); + options.setBinaryFile(true); + OgreXMLConvert conv = new OgreXMLConvert(); + conv.doConvert(options, handle); + if (delete) { + fobj.delete(); + } + } + } + } catch (Exception e) { + Logger.getLogger(ConvertOgreBinaryMeshesAction.class.getName()).log(Level.SEVERE, "Error scanning directory", e); + } finally { + handle.finish(); + } + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new ConvertOgreBinaryWizardPanel1() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } + + public Object getValue(String key) { + if (key.equals(NAME)) { + return "Convert Binary Ogre Meshes.."; + } + return null; + } + + public void putValue(String key, Object value) { + } + + public void setEnabled(boolean b) { + } + + public boolean isEnabled() { + return true; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ImportAssetAction.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ImportAssetAction.java new file mode 100644 index 000000000..608f57759 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/ImportAssetAction.java @@ -0,0 +1,156 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.actions; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import com.jme3.gde.assetpack.project.wizards.FileDescription; +import com.jme3.gde.assetpack.project.wizards.ImportWizardPanel1; +import com.jme3.gde.assetpack.project.wizards.ImportWizardPanel2; +import com.jme3.gde.core.assets.ProjectAssetManager; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.text.MessageFormat; +import java.util.Iterator; +import java.util.List; +import javax.swing.Action; +import javax.swing.JComponent; +import org.openide.DialogDisplayer; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileUtil; +import org.w3c.dom.Element; + +public final class ImportAssetAction implements Action { + + private final AssetPackProject context; + private WizardDescriptor.Panel[] panels; + + public ImportAssetAction(AssetPackProject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle("Import Asset to AssetPack.."); + wizardDescriptor.putProperty("project", context); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + if (!cancelled) { + importAsset(wizardDescriptor); + } + } + + private void importAsset(WizardDescriptor desc) { + ProjectAssetManager pm = context.getProjectAssetManager(); + Element asset = context.getConfiguration().createElement("asset"); + asset.setAttribute("name", (String) desc.getProperty("name")); + asset.setAttribute("type", (String) desc.getProperty("type")); +// asset.setAttribute("format", (String) desc.getProperty("format")); + asset.setAttribute("tags", (String) desc.getProperty("tags")); + asset.setAttribute("categories", (String) desc.getProperty("categories")); + Element description = context.getConfiguration().createElement("description"); + description.setTextContent((String) desc.getProperty("description")); + asset.appendChild(description); + Element license = context.getConfiguration().createElement("license"); + license.setTextContent((String) desc.getProperty("license")); + asset.appendChild(license); + + List files = (List) desc.getProperty("filelist"); + for (Iterator it = files.iterator(); it.hasNext();) { + FileDescription fileObject = it.next(); + Element file = context.getConfiguration().createElement("file"); + asset.appendChild(file); + file.setAttribute("path", fileObject.getPath() + fileObject.getFile().getNameExt()); + file.setAttribute("type", fileObject.getType()); + if (fileObject.isMainFile()) { + file.setAttribute("main", "true"); + } + if(!"default".equals(fileObject.getMaterial())){ + file.setAttribute("material", fileObject.getMaterial()); + } + String[] extraProps = fileObject.getExtraPropsNames(); + String[] extraValues = fileObject.getExtraPropsValues(); + for (int i = 0; i < extraProps.length; i++) { + file.setAttribute(extraProps[i], extraValues[i]); + } + if (!fileObject.isExisting()) { + File ffile = new File(context.getAssetsFolder().getPath() + "/" + fileObject.getPath()); + try { + ffile.mkdirs(); + fileObject.getFile().copy(FileUtil.toFileObject(ffile), fileObject.getFile().getName(), fileObject.getFile().getExt()); + } catch (Exception e) { + } + } + } + context.getProjectAssets().appendChild(asset); + context.saveSettings(); + context.getAssetPackFolder().refresh(); + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new ImportWizardPanel1(), + new ImportWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } + + public Object getValue(String key) { + if (key.equals(NAME)) { + return "Add Asset.."; + } + return null; + } + + public void putValue(String key, Object value) { + } + + public void setEnabled(boolean b) { + } + + public boolean isEnabled() { + return true; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/PublishAssetPackAction.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/PublishAssetPackAction.java new file mode 100644 index 000000000..c3a8e0b73 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/actions/PublishAssetPackAction.java @@ -0,0 +1,201 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.actions; + +import com.jme3.gde.assetpack.Installer; +import com.jme3.gde.assetpack.online.OnlinePacksConnector; +import com.jme3.gde.assetpack.project.AssetPackProject; +import com.jme3.gde.assetpack.project.wizards.PublishAssetPackWizardPanel1; +import com.jme3.gde.assetpack.project.wizards.PublishAssetPackWizardPanel2; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.MessageFormat; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +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; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.NbPreferences; + +public final class PublishAssetPackAction implements Action { + + private final Project context; + private WizardDescriptor.Panel[] panels; + + public PublishAssetPackAction(Project context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle("Publish AssetPack"); + wizardDescriptor.putProperty("project", context); + String projectName = ((AssetPackProject) context).getProjectName().replaceAll(" ", "_") + ".zip"; + wizardDescriptor.putProperty("filename", projectName); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + if (!cancelled) { + new Thread(new Runnable() { + + public void run() { + ProgressHandle handle = ProgressHandleFactory.createHandle("Publishing AssetPack.."); + handle.start(); + packZip(wizardDescriptor); + copyData(wizardDescriptor); + handle.progress("Uploading AssetPack.."); + uploadData(wizardDescriptor); + cleanup(wizardDescriptor); + handle.finish(); + } + }).start(); + } + } + + private void packZip(WizardDescriptor wiz) { + try { + String outFilename = context.getProjectDirectory().getPath() + "/" + wiz.getProperty("filename"); + ZipOutputStream out = new ZipOutputStream(new FileOutputStream(new File(outFilename))); + zipDir(((AssetPackProject) context).getProjectDirectory(), out, (String) wiz.getProperty("filename")); + out.close(); + } catch (IOException e) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Error creating ZIP file!"); + } + } + + public void zipDir(FileObject dir2zip, ZipOutputStream zos, String fileName) { + try { + FileObject[] dirList = dir2zip.getChildren(); + byte[] readBuffer = new byte[2156]; + int bytesIn = 0; + for (int i = 0; i < dirList.length; i++) { + FileObject f = dirList[i]; + if (f.isFolder()) { + zipDir(f, zos, fileName); + //loop again + continue; + } + InputStream fis = f.getInputStream(); + if (!f.getNameExt().equals(fileName) && !f.getNameExt().startsWith(".")) { + String filePathName = f.getPath().replaceAll(context.getProjectDirectory().getPath(), ""); + ZipEntry anEntry = new ZipEntry(filePathName); + zos.putNextEntry(anEntry); + while ((bytesIn = fis.read(readBuffer)) != -1) { + zos.write(readBuffer, 0, bytesIn); + } + fis.close(); + } + } + } catch (Exception e) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Error creating ZIP file!"); + } + } + + private void copyData(WizardDescriptor wiz) { + String folder = (String) wiz.getProperty("publish_folder"); + if (folder == null) { + return; + } + String zipFilename = context.getProjectDirectory().getPath() + "/" + wiz.getProperty("filename"); + try { + FileObject source = FileUtil.toFileObject(new File(zipFilename)); + FileObject destination = FileUtil.toFileObject(new File(folder)); + source.copy(destination, source.getName(), source.getExt()); + } catch (Exception ex) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Error copying ZIP file!"); + } + } + + private void uploadData(WizardDescriptor wiz) { + if (wiz.getProperty("publish_jmeorg") == null) { + return; + } + String file = context.getProjectDirectory().getPath() + "/" + wiz.getProperty("filename"); + String user = NbPreferences.forModule(Installer.class).get("assetpack_user", null); + String pass = NbPreferences.forModule(Installer.class).get("assetpack_pass", null); + OnlinePacksConnector.upload(file, user, pass); + } + + private void cleanup(WizardDescriptor wiz) { + String file = context.getProjectDirectory().getPath() + "/" + wiz.getProperty("filename"); + new File(file).delete(); + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new PublishAssetPackWizardPanel1(), + new PublishAssetPackWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } + + public Object getValue(String key) { + if (key.equals(NAME)) { + return "Publish AssetPack.."; + } + return null; + } + + public void putValue(String key, Object value) { + } + + public void setEnabled(boolean b) { + } + + public boolean isEnabled() { + return true; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/Bundle.properties b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/Bundle.properties new file mode 100644 index 000000000..d123984d6 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/Bundle.properties @@ -0,0 +1,7 @@ +GeneralSettingsPanel.jLabel1.text=Asset Pack Name & Version: +GeneralSettingsPanel.jTextField1.text=jTextField1 +GeneralSettingsPanel.jLabel2.text=Asset Pack Description: +LicensePanel.jLabel1.text=AssetPack License: +GeneralSettingsPanel.jLabel3.text=Distributor: +GeneralSettingsPanel.jTextField2.text=jTextField2 +GeneralSettingsPanel.jTextField3.text=jTextField3 diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/GeneralSettingsPanel.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/GeneralSettingsPanel.form new file mode 100644 index 000000000..a127584ea --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/GeneralSettingsPanel.form @@ -0,0 +1,126 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/GeneralSettingsPanel.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/GeneralSettingsPanel.java new file mode 100644 index 000000000..40eed5616 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/GeneralSettingsPanel.java @@ -0,0 +1,142 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * GeneralSettingsPanel.java + * + * Created on 21.10.2010, 22:43:59 + */ +package com.jme3.gde.assetpack.project.properties; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * + * @author normenhansen + */ +public class GeneralSettingsPanel extends javax.swing.JPanel implements ActionListener{ + + AssetPackProject project; + + /** Creates new form GeneralSettingsPanel */ + public GeneralSettingsPanel(AssetPackProject project) { + this.project = project; + initComponents(); + setName("General"); + jTextField1.setText(project.getProjectName()); + jTextField2.setText(project.getDistributorName()); + jTextField3.setText(project.getVersion()); + jTextArea1.setText(project.getDescription()); + } + + public void actionPerformed(ActionEvent e) { + project.setDescription(jTextArea1.getText()); + project.setProjectName(jTextField1.getText()); + project.setDistributorName(jTextField2.getText()); + project.setVersion(jTextField3.getText()); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + jLabel3 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jTextField3 = new javax.swing.JTextField(); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(GeneralSettingsPanel.class, "GeneralSettingsPanel.jLabel1.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(GeneralSettingsPanel.class, "GeneralSettingsPanel.jTextField1.text")); // NOI18N + jTextField1.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + updateName(evt); + } + }); + + jLabel2.setText(org.openide.util.NbBundle.getMessage(GeneralSettingsPanel.class, "GeneralSettingsPanel.jLabel2.text")); // NOI18N + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jTextArea1.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + updateDescription(evt); + } + }); + jScrollPane1.setViewportView(jTextArea1); + + jLabel3.setText(org.openide.util.NbBundle.getMessage(GeneralSettingsPanel.class, "GeneralSettingsPanel.jLabel3.text")); // NOI18N + + jTextField2.setText(org.openide.util.NbBundle.getMessage(GeneralSettingsPanel.class, "GeneralSettingsPanel.jTextField2.text")); // NOI18N + + jTextField3.setText(org.openide.util.NbBundle.getMessage(GeneralSettingsPanel.class, "GeneralSettingsPanel.jTextField3.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() + .addComponent(jLabel1) + .addContainerGap(224, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel3) + .addContainerGap()) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addContainerGap()) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 306, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 156, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void updateDescription(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_updateDescription + }//GEN-LAST:event_updateDescription + + private void updateName(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_updateName + }//GEN-LAST:event_updateName + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + private javax.swing.JTextField jTextField3; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/LicensePanel.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/LicensePanel.form new file mode 100644 index 000000000..2b6a1adf3 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/LicensePanel.form @@ -0,0 +1,60 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/LicensePanel.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/LicensePanel.java new file mode 100644 index 000000000..27653e9e0 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/properties/LicensePanel.java @@ -0,0 +1,86 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * LicensePanel.java + * + * Created on 21.10.2010, 22:58:39 + */ +package com.jme3.gde.assetpack.project.properties; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * + * @author normenhansen + */ +public class LicensePanel extends javax.swing.JPanel implements ActionListener{ + + private AssetPackProject project; + + /** Creates new form LicensePanel */ + public LicensePanel(AssetPackProject project) { + this.project = project; + initComponents(); + setName("License"); + jTextArea1.setText(project.getLicense()); + } + + public void actionPerformed(ActionEvent e) { + project.setLicense(jTextArea1.getText()); + } + + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + jLabel1 = new javax.swing.JLabel(); + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jTextArea1.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + updateLicense(evt); + } + }); + jScrollPane1.setViewportView(jTextArea1); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(LicensePanel.class, "LicensePanel.jLabel1.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void updateLicense(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_updateLicense + }//GEN-LAST:event_updateLicense + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/Bundle.properties b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/Bundle.properties new file mode 100644 index 000000000..185af0361 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/Bundle.properties @@ -0,0 +1,47 @@ +CTL_Import_Wizard=Import Asset +CreateProjectVisualPanel1.jLabel1.text=Project Folder: +CreateProjectVisualPanel1.jButton1.text=set.. +CreateProjectVisualPanel1.jLabel2.text=AssetPack Name / Version: +CreateProjectVisualPanel1.jTextField2.text=MyAssetPack +CreateProjectVisualPanel1.jLabel4.text=Description: +CreateProjectVisualPanel1.jLabel5.text=Distributor: +CreateProjectVisualPanel1.jTextField4.text=1.0 +CreateProjectVisualPanel1.jTextField5.text=MyCompany +CreateProjectVisualPanel1.jTextArea1.text=Great Asset Pack +CreateProjectVisualPanel2.jLabel1.text=License: +CreateProjectVisualPanel2.jTextArea1.text=No License +CreateProjectVisualPanel1.jTextField1.text= +CTL_ImportAssetAction=Import Asset +ImportVisualPanel1.jLabel1.text=Asset Name, Type & Format: +ImportVisualPanel1.jTextField1.text=MyAsset +ImportVisualPanel1.jLabel2.text=Description: +ImportVisualPanel1.jLabel3.text=Categories: +ImportVisualPanel1.jTextField2.text= +ImportVisualPanel1.jLabel4.text=(comma separated, start with captial letter) +ImportVisualPanel1.jLabel5.text=Tags: +ImportVisualPanel1.jLabel6.text=(comma separated, start with lowercase letter) +ImportVisualPanel1.jTextField3.text= +ImportVisualPanel2.jLabel1.text=Asset Files: +ImportVisualPanel2.jButton1.text=add.. +ImportVisualPanel2.jButton2.text=existing.. +SingleAssetFilePanel.jCheckBox1.text=load as model with material +SingleAssetFilePanel.jTextField1.text= +SingleAssetFilePanel.jTextField2.text= +SingleAssetFilePanel.jButton1.text=x +ImportVisualPanel2.jButton1.toolTipText=add a new file to the assetpack +ImportVisualPanel2.jButton2.toolTipText=reference an existing file.. +PublishAssetPackVisualPanel2.jCheckBox1.text=Publish Asset Pack to jMonkeyEngine.org +PublishAssetPackVisualPanel2.jLabel1.text=Please check your jmonkeyengine.org username and password +PublishAssetPackVisualPanel2.jLabel3.text=in the settings window (jMonkeyPlatform -> Settings). +PublishAssetPackVisualPanel1.jLabel2.text=Export Filename: +PublishAssetPackVisualPanel1.jTextField1.text=jTextField1 +PublishAssetPackVisualPanel1.jLabel1.text=Name of AssetPack +PublishAssetPackVisualPanel1.jLabel3.text=Distributor +PublishAssetPackVisualPanel1.jLabel4.text=Version +PublishAssetPackVisualPanel2.jCheckBox2.text=Publish Asset Pack to Folder: +PublishAssetPackVisualPanel2.jButton1.text=set.. +SelectExistingAsset.jButton1.text=OK +SelectExistingAsset.jButton2.text=Cancel +ConvertOgreBinaryVisualPanel1.jCheckBox1.text=delete original files +ConvertOgreBinaryVisualPanel1.jLabel1.text=This action converts all binary ogre meshes in your project +ConvertOgreBinaryVisualPanel1.jLabel2.text=to xml ogre meshes so they can be loaded in jME3. diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/Computer_File_054.gif b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/Computer_File_054.gif new file mode 100644 index 000000000..0183edd59 Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/Computer_File_054.gif differ diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryVisualPanel1.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryVisualPanel1.form new file mode 100644 index 000000000..d7c676cb2 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryVisualPanel1.form @@ -0,0 +1,68 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryVisualPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryVisualPanel1.java new file mode 100644 index 000000000..1f26f1da4 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryVisualPanel1.java @@ -0,0 +1,81 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import javax.swing.JPanel; +import org.openide.WizardDescriptor; + +public final class ConvertOgreBinaryVisualPanel1 extends JPanel { + private WizardDescriptor wiz; + + /** Creates new form ConvertOgreBinaryVisualPanel1 */ + public ConvertOgreBinaryVisualPanel1() { + initComponents(); + } + + @Override + public String getName() { + return "Specify Settings"; + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("deleteoriginal", jCheckBox1.isSelected()); + } + + public void loadSettings(WizardDescriptor wiz) { + this.wiz = wiz; +// updateList(); +// existingSelector = new SelectExistingAsset(new JFrame(), true, ((AssetPackProject) wiz.getProperty("project")).getAssetsFolder(), ((AssetPackProject) wiz.getProperty("project")), list); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jCheckBox1 = new javax.swing.JCheckBox(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + + jCheckBox1.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(ConvertOgreBinaryVisualPanel1.class, "ConvertOgreBinaryVisualPanel1.jCheckBox1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ConvertOgreBinaryVisualPanel1.class, "ConvertOgreBinaryVisualPanel1.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ConvertOgreBinaryVisualPanel1.class, "ConvertOgreBinaryVisualPanel1.jLabel2.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(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 370, Short.MAX_VALUE) + .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 370, Short.MAX_VALUE) + .addComponent(jCheckBox1, javax.swing.GroupLayout.DEFAULT_SIZE, 370, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBox1) + .addContainerGap(207, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryWizardPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryWizardPanel1.java new file mode 100644 index 000000000..bad21128c --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ConvertOgreBinaryWizardPanel1.java @@ -0,0 +1,88 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class ConvertOgreBinaryWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private ConvertOgreBinaryVisualPanel1 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. + public Component getComponent() { + if (component == null) { + component = new ConvertOgreBinaryVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.asset_packs"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + component.loadSettings((WizardDescriptor)settings); + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor)settings); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel1.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel1.form new file mode 100644 index 000000000..623a8d9d7 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel1.form @@ -0,0 +1,163 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel1.java new file mode 100644 index 000000000..ed5a84c73 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel1.java @@ -0,0 +1,176 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import com.jme3.gde.assetpack.Installer; +import java.io.File; +import javax.swing.JPanel; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileChooserBuilder; +import org.openide.util.NbPreferences; + +public final class CreateProjectVisualPanel1 extends JPanel { + + String projectPath = NbPreferences.forModule(Installer.class).get("assetpack_path", null); +// String projectPath = ProjectChooser.getProjectsFolder().getPath(); + + /** Creates new form CreateProjectVisualPanel1 */ + public CreateProjectVisualPanel1() { + initComponents(); + jTextField1.setText(projectPath + File.separator + jTextField2.getText()); + } + + @Override + public String getName() { + return "AssetPack Details"; + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("name", jTextField2.getText()); + wiz.putProperty("version", jTextField4.getText()); + wiz.putProperty("distributor", jTextField5.getText()); + wiz.putProperty("folder", jTextField1.getText()); + wiz.putProperty("description", jTextArea1.getText()); + wiz.putProperty("name", jTextField2.getText()); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jTextField1 = new javax.swing.JTextField(); + jLabel1 = new javax.swing.JLabel(); + jButton1 = new javax.swing.JButton(); + jLabel2 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jLabel4 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + jLabel5 = new javax.swing.JLabel(); + jTextField4 = new javax.swing.JTextField(); + jTextField5 = new javax.swing.JTextField(); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jTextField1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jLabel2.text")); // NOI18N + + jTextField2.setText(org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jTextField2.text")); // NOI18N + jTextField2.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + updateProjectFolder(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jLabel4.text")); // NOI18N + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jTextArea1.setText(org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jTextArea1.text")); // NOI18N + jScrollPane1.setViewportView(jTextArea1); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jLabel5.text")); // NOI18N + + jTextField4.setText(org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jTextField4.text")); // NOI18N + + jTextField5.setText(org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel1.class, "CreateProjectVisualPanel1.jTextField5.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() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2) + .addComponent(jLabel5) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 338, Short.MAX_VALUE)) + .addGap(10, 10, 10) + .addComponent(jTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jTextField5, javax.swing.GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 330, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1) + .addGap(8, 8, 8)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel4) + .addContainerGap()) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 204, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jButton1))) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed +// File path = new File(jTextField1.getText()); +// if (path.isDirectory()) { + + FileChooserBuilder builder = new FileChooserBuilder(this.getClass()); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Project Folder"); + File file = builder.showOpenDialog(); + if (file != null) { + try { + jTextField1.setText(file.getAbsolutePath() + File.separator + jTextField2.getText()); + } catch (Exception e) { + } + } +// } + }//GEN-LAST:event_jButton1ActionPerformed + + private void updateProjectFolder(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_updateProjectFolder + jTextField1.setText(projectPath + jTextField2.getText()); + }//GEN-LAST:event_updateProjectFolder + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + private javax.swing.JTextField jTextField4; + private javax.swing.JTextField jTextField5; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel2.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel2.form new file mode 100644 index 000000000..5becef95e --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel2.form @@ -0,0 +1,63 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel2.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel2.java new file mode 100644 index 000000000..ab9b7eabe --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectVisualPanel2.java @@ -0,0 +1,67 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import javax.swing.JPanel; +import org.openide.WizardDescriptor; + +public final class CreateProjectVisualPanel2 extends JPanel { + + /** Creates new form CreateProjectVisualPanel2 */ + public CreateProjectVisualPanel2() { + initComponents(); + } + + @Override + public String getName() { + return "AssetPack License"; + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("license", jTextArea1.getText()); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel2.class, "CreateProjectVisualPanel2.jLabel1.text")); // NOI18N + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jTextArea1.setText(org.openide.util.NbBundle.getMessage(CreateProjectVisualPanel2.class, "CreateProjectVisualPanel2.jTextArea1.text")); // NOI18N + jScrollPane1.setViewportView(jTextArea1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addContainerGap(349, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardIterator.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardIterator.java new file mode 100644 index 000000000..67bdc105c --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardIterator.java @@ -0,0 +1,207 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.LinkedHashSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import javax.swing.JComponent; +import javax.swing.event.ChangeListener; +import org.netbeans.spi.project.ui.support.ProjectChooser; +import org.netbeans.spi.project.ui.templates.support.Templates; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +// An example action demonstrating how the wizard could be called from within +// your code. You can copy-paste the code below wherever you need. +public final class CreateProjectWizardIterator implements WizardDescriptor.InstantiatingIterator { + + private int index; + private WizardDescriptor.Panel[] panels; + private WizardDescriptor wiz; + private String name = "Create AssetPack Project"; + + public static CreateProjectWizardIterator createIterator() { + return new CreateProjectWizardIterator(); + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new CreateProjectWizardPanel1(), + new CreateProjectWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } + + public void addChangeListener(ChangeListener l) { +// throw new UnsupportedOperationException("Not supported yet."); + } + + public void removeChangeListener(ChangeListener l) { +// throw new UnsupportedOperationException("Not supported yet."); + } + + public void initialize(WizardDescriptor wizard) { + wiz = wizard; + getPanels(); + } + + public void uninitialize(WizardDescriptor wizard) { +// this.wiz.putProperty("projdir", null); +// this.wiz.putProperty("name", null); + this.wiz = null; + panels = null; + } + + public Set instantiate() throws IOException { + Set mySet = new LinkedHashSet(); + //create folders + File dirF = FileUtil.normalizeFile(new File((String) wiz.getProperty("folder"))); + dirF.mkdirs(); + + //unzip file + FileObject template = Templates.getTemplate(wiz); + FileObject dir = FileUtil.toFileObject(dirF); + unZipFile(template.getInputStream(), dir); + + // Always open top dir as a project: + mySet.add(dir); + + File parent = dirF.getParentFile(); + if (parent != null && parent.exists()) { + ProjectChooser.setProjectsFolder(parent); + } + + return mySet; + } + + public boolean hasNext() { + return index < panels.length - 1; + } + + public boolean hasPrevious() { + return index > 0; + } + + public void nextPanel() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + index++; + } + + public void previousPanel() { + if (!hasPrevious()) { + throw new NoSuchElementException(); + } + index--; + } + + public WizardDescriptor.Panel current() { + return panels[index]; + } + + public String name() { + return name; + } + + private void unZipFile(InputStream source, FileObject projectRoot) throws IOException { + try { + ZipInputStream str = new ZipInputStream(source); + ZipEntry entry; + while ((entry = str.getNextEntry()) != null) { + if (entry.isDirectory()) { + FileUtil.createFolder(projectRoot, entry.getName()); + } else { + FileObject fo = FileUtil.createData(projectRoot, entry.getName()); + if ("assetpack.xml".equals(entry.getName())) { + // Special handling for setting name of Ant-based projects; customize as needed: + filterProjectXML(fo, str, projectRoot.getName()); + } else { + writeFile(str, fo); + } + } + } + } finally { + source.close(); + } + } + + private void writeFile(ZipInputStream str, FileObject fo) throws IOException { + OutputStream out = fo.getOutputStream(); + try { + FileUtil.copy(str, out); + } finally { + out.close(); + } + } + + private void filterProjectXML(FileObject fo, ZipInputStream str, String name) throws IOException { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + FileUtil.copy(str, baos); + Document doc = XMLUtil.parse(new InputSource(new ByteArrayInputStream(baos.toByteArray())), false, false, null, null); + doc.getDocumentElement().setAttribute("name", (String) wiz.getProperty("name")); + doc.getDocumentElement().setAttribute("version", (String) wiz.getProperty("version")); + doc.getDocumentElement().setAttribute("distributor", (String) wiz.getProperty("distributor")); +// doc.getDocumentElement().setAttribute("filename", (String) wiz.getProperty("filename")); + doc.getDocumentElement().setAttribute("name", (String) wiz.getProperty("name")); + XMLUtil.findElement(doc.getDocumentElement(), "description", null).setTextContent((String) wiz.getProperty("description")); + XMLUtil.findElement(doc.getDocumentElement(), "license", null).setTextContent((String) wiz.getProperty("license")); + OutputStream out = fo.getOutputStream(); + try { + XMLUtil.write(doc, out, "UTF-8"); + } finally { + out.close(); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + writeFile(str, fo); + } + + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardPanel1.java new file mode 100644 index 000000000..76535a465 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardPanel1.java @@ -0,0 +1,89 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import java.io.File; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class CreateProjectWizardPanel1 implements WizardDescriptor.Panel { + WizardDescriptor wiz; + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private CreateProjectVisualPanel1 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. + public Component getComponent() { + if (component == null) { + component = new CreateProjectVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.asset_packs"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + wiz=(WizardDescriptor)settings; + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor)settings); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardPanel2.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardPanel2.java new file mode 100644 index 000000000..4e4b4d1a1 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/CreateProjectWizardPanel2.java @@ -0,0 +1,87 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class CreateProjectWizardPanel2 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private CreateProjectVisualPanel2 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. + public Component getComponent() { + if (component == null) { + component = new CreateProjectVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.asset_packs"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor)settings); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/FileDescription.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/FileDescription.java new file mode 100644 index 000000000..2189f79a1 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/FileDescription.java @@ -0,0 +1,142 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import org.openide.filesystems.FileObject; + +/** + * + * @author normenhansen + */ +public class FileDescription { + + private FileObject file; + private String type = "scene"; + private String path = ""; + private boolean mainFile = false; + private boolean existing = false; + private String material = "default"; + private String[] extraPropsNames = new String[0]; + private String[] extraPropsValues = new String[0]; + + /** + * @return the file + */ + public FileObject getFile() { + return file; + } + + /** + * @param file the file to set + */ + public void setFile(FileObject file) { + this.file = file; + } + + public String getName() { + if (file == null) { + return "not available"; + } + return file.getNameExt(); + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the path + */ + public String getPath() { + return path; + } + + /** + * @param path the path to set + */ + public void setPath(String path) { + this.path = path; + } + + /** + * @return the extraPropsNames + */ + public String[] getExtraPropsNames() { + return extraPropsNames; + } + + /** + * @param extraPropsNames the extraPropsNames to set + */ + public void setExtraPropsNames(String[] extraPropsNames) { + this.extraPropsNames = extraPropsNames; + } + + /** + * @return the extraPropsValues + */ + public String[] getExtraPropsValues() { + return extraPropsValues; + } + + /** + * @param extraPropsValues the extraPropsValues to set + */ + public void setExtraPropsValues(String[] extraPropsValues) { + this.extraPropsValues = extraPropsValues; + } + + /** + * @return the mainFile + */ + public boolean isMainFile() { + return mainFile; + } + + /** + * @param mainFile the mainFile to set + */ + public void setMainFile(boolean mainFile) { + this.mainFile = mainFile; + } + + /** + * @return the existing + */ + public boolean isExisting() { + return existing; + } + + /** + * @param existing the existing to set + */ + public void setExisting(boolean existing) { + this.existing = existing; + } + + /** + * @return the material name + */ + public String getMaterial() { + return material; + } + + /** + * @param target the material name to set + */ + public void setMaterial(String material) { + this.material = material; + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel1.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel1.form new file mode 100644 index 000000000..254261384 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel1.form @@ -0,0 +1,175 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel1.java new file mode 100644 index 000000000..9388d88e1 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel1.java @@ -0,0 +1,143 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import javax.swing.JPanel; +import org.openide.WizardDescriptor; + +public final class ImportVisualPanel1 extends JPanel { + + /** Creates new form ImportVisualPanel1 */ + public ImportVisualPanel1() { + initComponents(); + } + + @Override + public String getName() { + return "Asset Info"; + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("name", jTextField1.getText()); + wiz.putProperty("type", jComboBox1.getSelectedItem()); +// wiz.putProperty("format", jComboBox2.getSelectedItem()); + wiz.putProperty("categories", jTextField2.getText()); + wiz.putProperty("tags", jTextField3.getText()); + wiz.putProperty("description", jTextArea1.getText()); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jComboBox1 = new javax.swing.JComboBox(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jLabel4 = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jTextField3 = new javax.swing.JTextField(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jLabel1.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jTextField1.text")); // NOI18N + + jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "model", "scene", "texture", "sound", "shader", "other" })); + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jScrollPane1.setViewportView(jTextArea1); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jLabel2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jLabel3.text")); // NOI18N + + jTextField2.setText(org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jTextField2.text")); // NOI18N + + jLabel4.setFont(new java.awt.Font("Lucida Grande", 0, 10)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jLabel4.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jLabel5.text")); // NOI18N + + jLabel6.setFont(new java.awt.Font("Lucida Grande", 0, 10)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jLabel6.text")); // NOI18N + + jTextField3.setText(org.openide.util.NbBundle.getMessage(ImportVisualPanel1.class, "ImportVisualPanel1.jTextField3.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() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE)) + .addComponent(jLabel1) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 310, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 118, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addContainerGap()) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) + .addComponent(jTextField3, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3) + .addComponent(jLabel4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(jLabel6)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JComboBox jComboBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + private javax.swing.JTextField jTextField3; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel2.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel2.form new file mode 100644 index 000000000..2930d8c01 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel2.form @@ -0,0 +1,104 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel2.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel2.java new file mode 100644 index 000000000..e780c6993 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportVisualPanel2.java @@ -0,0 +1,193 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import com.jme3.gde.assetpack.AssetPackLoader; +import com.jme3.gde.assetpack.project.AssetPackProject; +import java.io.File; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import javax.swing.JFrame; +import javax.swing.JPanel; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileChooserBuilder; + +public final class ImportVisualPanel2 extends JPanel { + + List list = new LinkedList(); + WizardDescriptor wiz; + SelectExistingAsset existingSelector; + + /** Creates new form ImportVisualPanel2 */ + public ImportVisualPanel2() { + initComponents(); + } + + @Override + public String getName() { + return "Asset Files"; + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("filelist", list); + } + + public void loadSettings(WizardDescriptor wiz) { + this.wiz = wiz; + updateList(); + existingSelector = new SelectExistingAsset(new JFrame(), true, ((AssetPackProject) wiz.getProperty("project")).getAssetsFolder(), ((AssetPackProject) wiz.getProperty("project")), list); + } + + public void updateList() { + jPanel1.removeAll(); + for (Iterator it = list.iterator(); it.hasNext();) { + FileDescription fileDescription = it.next(); + SingleAssetFilePanel panel = new SingleAssetFilePanel(fileDescription); + jPanel1.add(panel); + } + updateModelSelection(); + revalidate(); + repaint(); + } + + public void updateModelSelection() { + LinkedList strings = new LinkedList(); + for (Iterator it = list.iterator(); it.hasNext();) { + FileDescription fileDescription = it.next(); + if ("material".equals(fileDescription.getType())) { + strings.add(fileDescription.getPath() + fileDescription.getName()); + } + } + for (int i = 0; i < jPanel1.getComponents().length; i++) { + SingleAssetFilePanel component = (SingleAssetFilePanel) jPanel1.getComponents()[i]; + component.setModelList(strings); + } + } + + private void selectFile() { + FileChooserBuilder builder = new FileChooserBuilder(this.getClass()); + builder.setFilesOnly(true); + builder.setTitle("Select Asset File"); + File[] file = builder.showMultiOpenDialog(); + if (file != null) { + for (int i = 0; i < file.length; i++) { + File file1 = file[i]; + FileDescription description = AssetPackLoader.getFileDescription(file1); + description.setPath(pathString()); + list.add(description); + } + updateList(); + } + } + + private String pathString() { + String string = ""; + String type = (String) wiz.getProperty("type"); + if (type.equals("model")) { + string += "/Models/"; + } else if (type.equals("scene")) { + string += "/Scenes/"; + } else if (type.equals("texture")) { + string += "/Textures/"; + } else if (type.equals("sound")) { + string += "/Sounds/"; + } else if (type.equals("shader")) { + string += "/Shaders/"; + } else if (type.equals("other")) { + string += "/Misc/"; + } + String category = ((String) wiz.getProperty("categories")).split(",")[0].trim(); + string += category + "/"; + string += (String) wiz.getProperty("name") + "/"; + return string; + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jPanel1 = new javax.swing.JPanel(); + jToolBar1 = new javax.swing.JToolBar(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ImportVisualPanel2.class, "ImportVisualPanel2.jLabel1.text")); // NOI18N + + jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.PAGE_AXIS)); + jScrollPane1.setViewportView(jPanel1); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(ImportVisualPanel2.class, "ImportVisualPanel2.jButton1.text")); // NOI18N + jButton1.setToolTipText(org.openide.util.NbBundle.getMessage(ImportVisualPanel2.class, "ImportVisualPanel2.jButton1.toolTipText")); // NOI18N + jButton1.setFocusable(false); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar1.add(jButton1); + + org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(ImportVisualPanel2.class, "ImportVisualPanel2.jButton2.text")); // NOI18N + jButton2.setToolTipText(org.openide.util.NbBundle.getMessage(ImportVisualPanel2.class, "ImportVisualPanel2.jButton2.toolTipText")); // NOI18N + jButton2.setFocusable(false); + jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + jToolBar1.add(jButton2); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addComponent(jLabel1)) + .addContainerGap()) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 420, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + selectFile(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + existingSelector.setVisible(true); + updateList(); + }//GEN-LAST:event_jButton2ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportWizardPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportWizardPanel1.java new file mode 100644 index 000000000..8b46306e3 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportWizardPanel1.java @@ -0,0 +1,87 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class ImportWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private ImportVisualPanel1 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. + public Component getComponent() { + if (component == null) { + component = new ImportVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.asset_packs"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor)settings); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportWizardPanel2.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportWizardPanel2.java new file mode 100644 index 000000000..024a4ed1b --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/ImportWizardPanel2.java @@ -0,0 +1,88 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class ImportWizardPanel2 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private ImportVisualPanel2 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. + public Component getComponent() { + if (component == null) { + component = new ImportVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.asset_packs"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + component.loadSettings((WizardDescriptor)settings); + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor)settings); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel1.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel1.form new file mode 100644 index 000000000..35ccf5554 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel1.form @@ -0,0 +1,113 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel1.java new file mode 100644 index 000000000..4b514666b --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel1.java @@ -0,0 +1,109 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import com.jme3.gde.assetpack.project.AssetPackProject; +import javax.swing.JPanel; +import org.openide.WizardDescriptor; + +public final class PublishAssetPackVisualPanel1 extends JPanel { + + /** Creates new form PublishAssetPackVisualPanel1 */ + public PublishAssetPackVisualPanel1() { + initComponents(); + } + + @Override + public String getName() { + return "Export Settings"; + } + + public void loadSettings(WizardDescriptor wiz) { + AssetPackProject project=(AssetPackProject)wiz.getProperty("project"); + jTextArea1.setText(project.getDescription()); + jLabel1.setText(project.getProjectName()); + jLabel3.setText(project.getDistributorName()); + jLabel4.setText(project.getVersion()); + jTextField1.setText((String)wiz.getProperty("filename")); + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("filename", jTextField1.getText()); + } + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel2 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jLabel1 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel1.class, "PublishAssetPackVisualPanel1.jLabel2.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel1.class, "PublishAssetPackVisualPanel1.jTextField1.text")); // NOI18N + + jLabel1.setFont(new java.awt.Font("Lucida Grande", 1, 13)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel1.class, "PublishAssetPackVisualPanel1.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel1.class, "PublishAssetPackVisualPanel1.jLabel4.text")); // NOI18N + + jLabel3.setFont(new java.awt.Font("Lucida Grande", 2, 13)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel1.class, "PublishAssetPackVisualPanel1.jLabel3.text")); // NOI18N + + jTextArea1.setColumns(20); + jTextArea1.setEditable(false); + jTextArea1.setRows(5); + jScrollPane1.setViewportView(jTextArea1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel4) + .addContainerGap(217, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 285, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(jLabel4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 216, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2))) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel2.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel2.form new file mode 100644 index 000000000..49fda821a --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel2.form @@ -0,0 +1,97 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel2.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel2.java new file mode 100644 index 000000000..87c0c0ecd --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackVisualPanel2.java @@ -0,0 +1,121 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.io.File; +import javax.swing.JPanel; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileChooserBuilder; + +public final class PublishAssetPackVisualPanel2 extends JPanel { + + /** Creates new form PublishAssetPackVisualPanel2 */ + public PublishAssetPackVisualPanel2() { + initComponents(); + } + + @Override + public String getName() { + return "Publishing"; + } + + public void applySettings(WizardDescriptor wiz) { + if(jCheckBox1.isSelected()){ + wiz.putProperty("publish_jmeorg", "true"); + }else{ + wiz.putProperty("publish_jmeorg", null); + } + if(jCheckBox2.isSelected()){ + wiz.putProperty("publish_folder", jTextField1.getText()); + }else{ + wiz.putProperty("publish_folder", null); + } + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jCheckBox1 = new javax.swing.JCheckBox(); + jLabel1 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jCheckBox2 = new javax.swing.JCheckBox(); + jTextField1 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel2.class, "PublishAssetPackVisualPanel2.jCheckBox1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel2.class, "PublishAssetPackVisualPanel2.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel2.class, "PublishAssetPackVisualPanel2.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox2, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel2.class, "PublishAssetPackVisualPanel2.jCheckBox2.text")); // NOI18N + + jTextField1.setText(System.getProperty("user.home")); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(PublishAssetPackVisualPanel2.class, "PublishAssetPackVisualPanel2.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE) + .addComponent(jCheckBox2, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE) + .addComponent(jCheckBox1, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 309, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(35, 35, 35) + .addComponent(jCheckBox1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBox2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jButton1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 107, Short.MAX_VALUE) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel3)) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + FileChooserBuilder builder = new FileChooserBuilder(this.getClass()); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Export Folder"); + File file = builder.showOpenDialog(); + if (file != null) { + try { + jTextField1.setText(file.getAbsolutePath()); + } catch (Exception e) { + } + } + }//GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JCheckBox jCheckBox2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel3; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackWizardPanel1.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackWizardPanel1.java new file mode 100644 index 000000000..007acf657 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackWizardPanel1.java @@ -0,0 +1,88 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class PublishAssetPackWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private PublishAssetPackVisualPanel1 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. + public Component getComponent() { + if (component == null) { + component = new PublishAssetPackVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.asset_packs"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + component.loadSettings((WizardDescriptor) settings); + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor) settings); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackWizardPanel2.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackWizardPanel2.java new file mode 100644 index 000000000..8c9bab31c --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/PublishAssetPackWizardPanel2.java @@ -0,0 +1,87 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class PublishAssetPackWizardPanel2 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private PublishAssetPackVisualPanel2 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. + public Component getComponent() { + if (component == null) { + component = new PublishAssetPackVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.asset_packs"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor) settings); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SelectExistingAsset.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SelectExistingAsset.form new file mode 100644 index 000000000..97d68ae6e --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SelectExistingAsset.form @@ -0,0 +1,76 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SelectExistingAsset.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SelectExistingAsset.java new file mode 100644 index 000000000..a95e2a4d3 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SelectExistingAsset.java @@ -0,0 +1,160 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SelectExistingAsset.java + * + * Created on 27.10.2010, 14:58:54 + */ +package com.jme3.gde.assetpack.project.wizards; + +import com.jme3.gde.assetpack.AssetPackLoader; +import com.jme3.gde.assetpack.project.AssetPackProject; +import java.io.File; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.view.BeanTreeView; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class SelectExistingAsset extends javax.swing.JDialog implements ExplorerManager.Provider { + + private transient ExplorerManager explorerManager = new ExplorerManager(); + private AssetPackProject project; + private List list; + + /** Creates new form SelectExistingAsset */ + public SelectExistingAsset(java.awt.Frame parent, boolean modal, FileObject folder, AssetPackProject project, List list) { + super(parent, modal); + this.project = project; + this.list = list; + Node node = null; + initComponents(); + setLocationRelativeTo(null); + try { + node = DataObject.find(folder).getNodeDelegate(); + } catch (DataObjectNotFoundException ex) { + Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error loading asset folder!"); + Exceptions.printStackTrace(ex); + } + if (node != null) { + explorerManager.setRootContext(node); + explorerManager.getRootContext().setDisplayName(node.getName()); + } + } + + public ExplorerManager getExplorerManager() { + return explorerManager; + } + + public void applyInfo() { + Node[] nodes = explorerManager.getSelectedNodes(); + for (int i = 0; i < nodes.length; i++) { + Node node = nodes[i]; + String path = node.getLookup().lookup(DataObject.class).getPrimaryFile().getPath(); + FileObject file1 = FileUtil.toFileObject(new File(path)); + FileDescription description = AssetPackLoader.getFileDescription(file1); + description.setExisting(true); + String pathName = project.getProjectAssetManager().getRelativeAssetPath(path); + pathName=pathName.replaceAll("\\\\", "/"); + pathName = pathName.substring(0, pathName.lastIndexOf("/")+1); + description.setPath(pathName); + list.add(description); + } + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new BeanTreeView(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jButton1.setText(org.openide.util.NbBundle.getMessage(SelectExistingAsset.class, "SelectExistingAsset.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText(org.openide.util.NbBundle.getMessage(SelectExistingAsset.class, "SelectExistingAsset.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 258, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jButton1)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 387, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1) + .addComponent(jButton2))) + ); + + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + applyInfo(); + setVisible(false); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + setVisible(false); + }//GEN-LAST:event_jButton2ActionPerformed + /** + * @param args the command line arguments + */ +// public static void main(String args[]) { +// java.awt.EventQueue.invokeLater(new Runnable() { +// public void run() { +// SelectExistingAsset dialog = new SelectExistingAsset(new javax.swing.JFrame(), true); +// dialog.addWindowListener(new java.awt.event.WindowAdapter() { +// public void windowClosing(java.awt.event.WindowEvent e) { +// System.exit(0); +// } +// }); +// dialog.setVisible(true); +// } +// }); +// } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SingleAssetFilePanel.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SingleAssetFilePanel.form new file mode 100644 index 000000000..d15fe14a6 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SingleAssetFilePanel.form @@ -0,0 +1,135 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SingleAssetFilePanel.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SingleAssetFilePanel.java new file mode 100644 index 000000000..3904f2987 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/project/wizards/SingleAssetFilePanel.java @@ -0,0 +1,170 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * AddAssetFilePanel.java + * + * Created on 24.10.2010, 04:15:22 + */ +package com.jme3.gde.assetpack.project.wizards; + +import java.awt.Dimension; +import java.util.Iterator; +import java.util.List; + +/** + * + * @author normenhansen + */ +public class SingleAssetFilePanel extends javax.swing.JPanel { + + FileDescription desc; + + /** Creates new form AddAssetFilePanel */ + public SingleAssetFilePanel(FileDescription desc) { + initComponents(); + this.desc = desc; + updateInfo(); + } + + public void setModelList(List models){ + jComboBox2.removeAllItems(); + jComboBox2.addItem("default"); + for (Iterator it = models.iterator(); it.hasNext();) { + String string = it.next(); + jComboBox2.addItem(string); + } + jComboBox2.setPreferredSize(new Dimension(200,25)); + } + + public void updateInfo() { + jTextField1.setText(desc.getPath()); + jTextField2.setText(desc.getName()); + jComboBox1.setSelectedItem(desc.getType()); + jCheckBox1.setSelected(desc.isMainFile()); + jComboBox2.setSelectedItem(desc.getMaterial()); + if (desc.isExisting()) { + jTextField1.setEditable(false); + } else { + jTextField1.setEditable(true); + } + if(!"mesh".equals(desc.getType())&&!"scene".equals(desc.getType())){ + jToolBar2.setVisible(false); + setPreferredSize(new Dimension(100, 25)); + }else{ + jToolBar2.setVisible(true); + setPreferredSize(new Dimension(100, 50)); + } + } + + public void saveInfo() { + desc.setPath(jTextField1.getText()); + desc.setMainFile(jCheckBox1.isSelected()); + desc.setType((String) jComboBox1.getSelectedItem()); + desc.setMaterial((String) jComboBox2.getSelectedItem()); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jTextField1 = new javax.swing.JTextField(); + jTextField2 = new javax.swing.JTextField(); + jComboBox1 = new javax.swing.JComboBox(); + jButton1 = new javax.swing.JButton(); + jToolBar2 = new javax.swing.JToolBar(); + jCheckBox1 = new javax.swing.JCheckBox(); + jComboBox2 = new javax.swing.JComboBox(); + + setMaximumSize(new java.awt.Dimension(32767, 50)); + setMinimumSize(new java.awt.Dimension(0, 50)); + setPreferredSize(new java.awt.Dimension(474, 50)); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(SingleAssetFilePanel.class, "SingleAssetFilePanel.jTextField1.text")); // NOI18N + jTextField1.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + saveInfo(evt); + } + }); + jToolBar1.add(jTextField1); + + jTextField2.setEditable(false); + jTextField2.setText(org.openide.util.NbBundle.getMessage(SingleAssetFilePanel.class, "SingleAssetFilePanel.jTextField2.text")); // NOI18N + jToolBar1.add(jTextField2); + + jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "scene", "mesh", "texture", "material", "materialdef", "shader", "skeleton", "other" })); + jComboBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + saveInfo2(evt); + } + }); + jToolBar1.add(jComboBox1); + + jButton1.setText(org.openide.util.NbBundle.getMessage(SingleAssetFilePanel.class, "SingleAssetFilePanel.jButton1.text")); // NOI18N + jToolBar1.add(jButton1); + + jToolBar2.setFloatable(false); + jToolBar2.setRollover(true); + + jCheckBox1.setText(org.openide.util.NbBundle.getMessage(SingleAssetFilePanel.class, "SingleAssetFilePanel.jCheckBox1.text")); // NOI18N + jCheckBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + saveInfo3(evt); + } + }); + jToolBar2.add(jCheckBox1); + + jComboBox2.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "default" })); + jComboBox2.setMaximumSize(new java.awt.Dimension(200, 30)); + jComboBox2.setPreferredSize(new java.awt.Dimension(200, 27)); + jToolBar2.add(jComboBox2); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE) + .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// //GEN-END:initComponents + + private void saveInfo(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_saveInfo + saveInfo(); + }//GEN-LAST:event_saveInfo + + private void saveInfo2(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveInfo2 + saveInfo(); + }//GEN-LAST:event_saveInfo2 + + private void saveInfo3(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveInfo3 + saveInfo(); + }//GEN-LAST:event_saveInfo3 + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JComboBox jComboBox1; + private javax.swing.JComboBox jComboBox2; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToolBar jToolBar2; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksOptionsPanelController.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksOptionsPanelController.java new file mode 100644 index 000000000..118aa54a5 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksOptionsPanelController.java @@ -0,0 +1,77 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.properties; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import javax.swing.JComponent; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; + +@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_AssetPacks", +iconBase = "com/jme3/gde/assetpack/icons/assetpack_24.png", +keywords = "#OptionsCategory_Keywords_AssetPacks", +keywordsCategory = "AssetPacks", +position = 610) +public final class AssetPacksOptionsPanelController extends OptionsPanelController { + + private AssetPacksPanel panel; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private boolean changed; + + public void update() { + getPanel().load(); + changed = false; + } + + public void applyChanges() { + getPanel().store(); + changed = false; + } + + public void cancel() { + // need not do anything special, if no changes have been persisted yet + } + + public boolean isValid() { + return getPanel().valid(); + } + + public boolean isChanged() { + return changed; + } + + public HelpCtx getHelpCtx() { + return new HelpCtx("sdk.asset_packs"); + } + + public JComponent getComponent(Lookup masterLookup) { + return getPanel(); + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + pcs.addPropertyChangeListener(l); + } + + public void removePropertyChangeListener(PropertyChangeListener l) { + pcs.removePropertyChangeListener(l); + } + + private AssetPacksPanel getPanel() { + if (panel == null) { + panel = new AssetPacksPanel(this); + } + return panel; + } + + void changed() { + if (!changed) { + changed = true; + pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true); + } + pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null); + } +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksPanel.form b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksPanel.form new file mode 100644 index 000000000..8a9e51249 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksPanel.form @@ -0,0 +1,116 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksPanel.java b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksPanel.java new file mode 100644 index 000000000..7a2fb3640 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/AssetPacksPanel.java @@ -0,0 +1,121 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.assetpack.properties; + +import com.jme3.gde.assetpack.Installer; +import org.openide.util.NbPreferences; + +final class AssetPacksPanel extends javax.swing.JPanel { + + private final AssetPacksOptionsPanelController controller; + + AssetPacksPanel(AssetPacksOptionsPanelController controller) { + this.controller = controller; + initComponents(); + // TODO listen to changes in form fields and call controller.changed() + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel3 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jLabel1 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jLabel5 = new javax.swing.JLabel(); + jPasswordField1 = new javax.swing.JPasswordField(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(AssetPacksPanel.class, "AssetPacksPanel.jLabel3.text")); // NOI18N + + jTextField2.setText(org.openide.util.NbBundle.getMessage(AssetPacksPanel.class, "AssetPacksPanel.jTextField2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AssetPacksPanel.class, "AssetPacksPanel.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(AssetPacksPanel.class, "AssetPacksPanel.jLabel4.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(AssetPacksPanel.class, "AssetPacksPanel.jTextField1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(AssetPacksPanel.class, "AssetPacksPanel.jLabel5.text")); // NOI18N + + jPasswordField1.setText(org.openide.util.NbBundle.getMessage(AssetPacksPanel.class, "AssetPacksPanel.jPasswordField1.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) + .addGroup(layout.createSequentialGroup() + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 468, Short.MAX_VALUE) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel4) + .addComponent(jLabel5)) + .addGap(58, 58, 58) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE) + .addComponent(jPasswordField1, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE)))) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel3) + .addContainerGap(329, Short.MAX_VALUE)))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(31, 31, 31) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel4) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(jPasswordField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(266, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + void load() { + jTextField2.setText(NbPreferences.forModule(Installer.class).get("assetpack_path", null)); + jTextField1.setText(NbPreferences.forModule(Installer.class).get("assetpack_user", null)); + jPasswordField1.setText(NbPreferences.forModule(Installer.class).get("assetpack_pass", null)); + } + + void store() { + NbPreferences.forModule(Installer.class).put("assetpack_path", jTextField2.getText()); + NbPreferences.forModule(Installer.class).put("assetpack_user", jTextField1.getText()); + NbPreferences.forModule(Installer.class).put("assetpack_pass", new String(jPasswordField1.getPassword())); + } + + boolean valid() { + return true; + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JPasswordField jPasswordField1; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/Bundle.properties b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/Bundle.properties new file mode 100644 index 000000000..f113ed7e8 --- /dev/null +++ b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/Bundle.properties @@ -0,0 +1,9 @@ +OptionsCategory_Keywords_AssetPacks=asset packs +OptionsCategory_Name_AssetPacks=Asset Packs +AssetPacksPanel.jLabel3.text=Path to store AssetPacks: +AssetPacksPanel.jTextField2.text=jTextField2 +AssetPacksPanel.jLabel1.text=User data for upload to jmonkeyengine.org: +AssetPacksPanel.jLabel4.text=Name: +AssetPacksPanel.jTextField1.text=jTextField1 +AssetPacksPanel.jLabel5.text=Password: +AssetPacksPanel.jPasswordField1.text=jPasswordField1 diff --git a/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/jme-logo48.png b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/jme-logo48.png new file mode 100644 index 000000000..e8472fcaa Binary files /dev/null and b/sdk/jme3-assetpack-support/src/com/jme3/gde/assetpack/properties/jme-logo48.png differ diff --git a/sdk/jme3-cinematics/build.xml b/sdk/jme3-cinematics/build.xml new file mode 100644 index 000000000..8bc115155 --- /dev/null +++ b/sdk/jme3-cinematics/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.cinematics. + + diff --git a/sdk/jme3-cinematics/manifest.mf b/sdk/jme3-cinematics/manifest.mf new file mode 100644 index 000000000..48d4387f4 --- /dev/null +++ b/sdk/jme3-cinematics/manifest.mf @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.cinematics/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/cinematics/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/cinematics/Bundle.properties +OpenIDE-Module-Requires: org.openide.windows.WindowManager + diff --git a/sdk/jme3-cinematics/nbproject/build-impl.xml b/sdk/jme3-cinematics/nbproject/build-impl.xml new file mode 100644 index 000000000..caa9a3a8b --- /dev/null +++ b/sdk/jme3-cinematics/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-cinematics/nbproject/genfiles.properties b/sdk/jme3-cinematics/nbproject/genfiles.properties new file mode 100644 index 000000000..af5574724 --- /dev/null +++ b/sdk/jme3-cinematics/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=50d0728b +build.xml.script.CRC32=d8082083 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=50d0728b +nbproject/build-impl.xml.script.CRC32=a2681ce5 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-cinematics/nbproject/project.properties b/sdk/jme3-cinematics/nbproject/project.properties new file mode 100644 index 000000000..03f070ffb --- /dev/null +++ b/sdk/jme3-cinematics/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=R\u00e9my Bouquet +nbm.needs.restart=true +spec.version.base=0.1.0 diff --git a/sdk/jme3-cinematics/nbproject/project.xml b/sdk/jme3-cinematics/nbproject/project.xml new file mode 100644 index 000000000..fc1320911 --- /dev/null +++ b/sdk/jme3-cinematics/nbproject/project.xml @@ -0,0 +1,113 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.cinematics + + + + com.jme3.gde.core + + + + 1 + 0.1 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.5 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.5 + + + + org.netbeans.modules.settings + + + + 1 + 1.22.1.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.30.1 + + + + + + + diff --git a/sdk/jme3-cinematics/nbproject/suite.properties b/sdk/jme3-cinematics/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-cinematics/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/Bundle.properties b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/Bundle.properties new file mode 100644 index 000000000..30f2e4a5e --- /dev/null +++ b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/Bundle.properties @@ -0,0 +1,13 @@ +CTL_CinematicsAction=Cinematics +CTL_CinematicsTopComponent=Cinematics Window +CTL_TimelineAction=Timeline +CTL_TimelineTopComponent=Timeline Window +HINT_CinematicsTopComponent=This is a Cinematics window +HINT_TimelineTopComponent=This is a Timeline window +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides a cinematics editor for jMonkeyPlatform (WIP). +OpenIDE-Module-Name=Cinematics Editor +OpenIDE-Module-Short-Description=Provides Cinematics Editor for jMP +Services/MIMEResolver/SequenceResolver.xml=Sequence Files +Templates/Other/SequenceTemplate.mcs=Empty Sequence file diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponent.form b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponent.form new file mode 100644 index 000000000..c1002383a --- /dev/null +++ b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponent.form @@ -0,0 +1,28 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponent.java b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponent.java new file mode 100644 index 000000000..fc682cca2 --- /dev/null +++ b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponent.java @@ -0,0 +1,126 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.cinematics; + +import java.util.logging.Logger; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.cinematics//Cinematics//EN", +autostore = false) +public final class CinematicsTopComponent extends TopComponent { + + private static CinematicsTopComponent instance; + /** path to the icon used by the component and its open action */ + static final String ICON_PATH = "com/jme3/gde/cinematics/objects_016.gif"; + private static final String PREFERRED_ID = "CinematicsTopComponent"; + + public CinematicsTopComponent() { + initComponents(); + setName(NbBundle.getMessage(CinematicsTopComponent.class, "CTL_CinematicsTopComponent")); + setToolTipText(NbBundle.getMessage(CinematicsTopComponent.class, "HINT_CinematicsTopComponent")); + setIcon(ImageUtilities.loadImage(ICON_PATH, true)); + + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized CinematicsTopComponent getDefault() { + if (instance == null) { + instance = new CinematicsTopComponent(); + } + return instance; + } + + /** + * Obtain the CinematicsTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized CinematicsTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(CinematicsTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof CinematicsTopComponent) { + return (CinematicsTopComponent) win; + } + Logger.getLogger(CinematicsTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + // TODO add custom code on component closing + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } +} diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponentSettings.xml b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponentSettings.xml new file mode 100644 index 000000000..d020a18e9 --- /dev/null +++ b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponentWstcref.xml b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponentWstcref.xml new file mode 100644 index 000000000..fdd97483b --- /dev/null +++ b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/CinematicsTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_002.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_002.gif new file mode 100644 index 000000000..b10c1a9bf Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_002.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_003.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_003.gif new file mode 100644 index 000000000..db1ebc27d Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_003.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_004.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_004.gif new file mode 100644 index 000000000..7199cce0b Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_004.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_005.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_005.gif new file mode 100644 index 000000000..61145ea78 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_005.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_054.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_054.gif new file mode 100644 index 000000000..0183edd59 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_054.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_055.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_055.gif new file mode 100644 index 000000000..800a26da1 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_055.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_056.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_056.gif new file mode 100644 index 000000000..941730bab Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_056.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_057.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_057.gif new file mode 100644 index 000000000..3604be77b Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_057.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_058.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_058.gif new file mode 100644 index 000000000..6dafd27da Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_058.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_059.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_059.gif new file mode 100644 index 000000000..b258c46f8 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_059.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_065.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_065.gif new file mode 100644 index 000000000..98e8c067a Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_065.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_066.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_066.gif new file mode 100644 index 000000000..78aafce02 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_066.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_067.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_067.gif new file mode 100644 index 000000000..669b21456 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_067.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_068.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_068.gif new file mode 100644 index 000000000..638f48ff0 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_068.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_069.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_069.gif new file mode 100644 index 000000000..ab9be0d23 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_069.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_070.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_070.gif new file mode 100644 index 000000000..fd6347702 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_070.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_071.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_071.gif new file mode 100644 index 000000000..068b90f18 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_071.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_072.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_072.gif new file mode 100644 index 000000000..043260076 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_072.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_080.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_080.gif new file mode 100644 index 000000000..33b1bf98d Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_080.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_081.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_081.gif new file mode 100644 index 000000000..4744322d4 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_081.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_082.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_082.gif new file mode 100644 index 000000000..48e7885fd Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_082.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_083.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_083.gif new file mode 100644 index 000000000..7f524523f Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_083.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_097.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_097.gif new file mode 100644 index 000000000..7891205c3 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_097.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_104.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_104.gif new file mode 100644 index 000000000..cbf624345 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_104.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_108.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_108.gif new file mode 100644 index 000000000..4b07af826 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_108.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_110.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_110.gif new file mode 100644 index 000000000..521448605 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_110.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_112.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_112.gif new file mode 100644 index 000000000..105bd1550 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_112.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_113.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_113.gif new file mode 100644 index 000000000..07cecfb25 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_113.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_114.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_114.gif new file mode 100644 index 000000000..6fd48d2c2 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_114.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_115.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_115.gif new file mode 100644 index 000000000..2933b770c Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_115.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_125.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_125.gif new file mode 100644 index 000000000..219e2253a Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_125.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_126.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_126.gif new file mode 100644 index 000000000..d5aa1074a Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_126.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_127.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_127.gif new file mode 100644 index 000000000..97bfebcb3 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_127.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_128.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_128.gif new file mode 100644 index 000000000..d7a7e0cfd Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/Computer_File_128.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_002.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_002.gif new file mode 100644 index 000000000..edbe0b002 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_002.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_003.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_003.gif new file mode 100644 index 000000000..071edb9bc Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_003.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_004.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_004.gif new file mode 100644 index 000000000..c571b4a75 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_004.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_005.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_005.gif new file mode 100644 index 000000000..75627aac6 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_005.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_006.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_006.gif new file mode 100644 index 000000000..6ff86e829 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_006.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_009.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_009.gif new file mode 100644 index 000000000..d4258a070 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_009.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_010.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_010.gif new file mode 100644 index 000000000..8f89c599d Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_010.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_011.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_011.gif new file mode 100644 index 000000000..960f97b43 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_011.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_012.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_012.gif new file mode 100644 index 000000000..8f2a5f3e3 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_012.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_013.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_013.gif new file mode 100644 index 000000000..e81054eb3 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_013.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_014.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_014.gif new file mode 100644 index 000000000..dacffca85 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_014.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_015.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_015.gif new file mode 100644 index 000000000..6e2a604fe Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_015.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_016.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_016.gif new file mode 100644 index 000000000..7a3e07819 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_016.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_050.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_050.gif new file mode 100644 index 000000000..7d0780c23 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_050.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_051.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_051.gif new file mode 100644 index 000000000..4687a22a6 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_051.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_052.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_052.gif new file mode 100644 index 000000000..956c953eb Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_052.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_053.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_053.gif new file mode 100644 index 000000000..6b7af790a Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/icons/objects_053.gif differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/jme-logo.png b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/jme-logo.png new file mode 100644 index 000000000..f67785a6e Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/jme-logo.png differ diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/layer.xml b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/layer.xml new file mode 100644 index 000000000..ada54ed03 --- /dev/null +++ b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/layer.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/objects_016.gif b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/objects_016.gif new file mode 100644 index 000000000..7a3e07819 Binary files /dev/null and b/sdk/jme3-cinematics/src/com/jme3/gde/cinematics/objects_016.gif differ diff --git a/sdk/jme3-code-check/build.xml b/sdk/jme3-code-check/build.xml new file mode 100644 index 000000000..a0e60f010 --- /dev/null +++ b/sdk/jme3-code-check/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.codecheck. + + diff --git a/sdk/jme3-code-check/manifest.mf b/sdk/jme3-code-check/manifest.mf new file mode 100644 index 000000000..a6f0fa1fb --- /dev/null +++ b/sdk/jme3-code-check/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.codecheck +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/codecheck/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/codecheck/Bundle.properties + diff --git a/sdk/jme3-code-check/nbproject/build-impl.xml b/sdk/jme3-code-check/nbproject/build-impl.xml new file mode 100644 index 000000000..b38bed8eb --- /dev/null +++ b/sdk/jme3-code-check/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-code-check/nbproject/genfiles.properties b/sdk/jme3-code-check/nbproject/genfiles.properties new file mode 100644 index 000000000..b0278d135 --- /dev/null +++ b/sdk/jme3-code-check/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=9d32300f +build.xml.script.CRC32=a481f885 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=9d32300f +nbproject/build-impl.xml.script.CRC32=0691bb76 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-code-check/nbproject/project.properties b/sdk/jme3-code-check/nbproject/project.properties new file mode 100644 index 000000000..8a2d04126 --- /dev/null +++ b/sdk/jme3-code-check/nbproject/project.properties @@ -0,0 +1,3 @@ +javac.source=1.6 +javac.compilerargs=-Xlint -Xlint:-serial +spec.version.base=0.1.0 diff --git a/sdk/jme3-code-check/nbproject/project.xml b/sdk/jme3-code-check/nbproject/project.xml new file mode 100644 index 000000000..4a1b7770a --- /dev/null +++ b/sdk/jme3-code-check/nbproject/project.xml @@ -0,0 +1,131 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.codecheck + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.8 + + + + org.netbeans.api.java + + + + 1 + 1.28.1 + + + + org.netbeans.libs.javacapi + + + + 0.13.1.1 + + + + org.netbeans.modules.editor + + + + 3 + 1.50.1.3.10.2 + + + + org.netbeans.modules.editor.lib2 + + + + 1 + 1.28.1.2 + + + + org.netbeans.modules.java.hints + + + + 1 + + + + + org.netbeans.modules.java.source + + + + 0.60.2.10.8.4 + + + + org.netbeans.spi.editor.hints + + + + 0 + + + + + org.openide.awt + + + + 7.23.1 + + + + org.openide.filesystems + + + + 7.38.2 + + + + org.openide.loaders + + + + 7.16.1 + + + + org.openide.nodes + + + + 7.16.1 + + + + org.openide.text + + + + 6.30.1 + + + + org.openide.util + + + + 8.6.1 + + + + + + + diff --git a/sdk/jme3-code-check/nbproject/suite.properties b/sdk/jme3-code-check/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-code-check/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-code-check/src/com/jme3/gde/codecheck/Bundle.properties b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/Bundle.properties new file mode 100644 index 000000000..638b0cee6 --- /dev/null +++ b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/Bundle.properties @@ -0,0 +1,5 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + Gives code hints and performs checks on code during compile +OpenIDE-Module-Name=jME3 Code Checks +OpenIDE-Module-Short-Description=Gives code hints and performs checks on code during compile diff --git a/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/Bundle.properties b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/Bundle.properties new file mode 100644 index 000000000..e69de29bb diff --git a/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/InternalMethodHint.java b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/InternalMethodHint.java new file mode 100644 index 000000000..ec39de343 --- /dev/null +++ b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/InternalMethodHint.java @@ -0,0 +1,133 @@ +package com.jme3.gde.codecheck.hints; + +import com.jme3.system.Annotations.Internal; +import com.sun.source.tree.Tree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreePath; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import javax.lang.model.element.Element; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorRegistry; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.modules.java.hints.spi.AbstractHint; +import org.netbeans.spi.editor.hints.ChangeInfo; +import org.netbeans.spi.editor.hints.EnhancedFix; +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; + +public class InternalMethodHint extends AbstractHint { + + //This hint does not enable the IDE to fix the problem: + private static final List NO_FIXES = Collections.emptyList(); + //This hint applies to method invocations: + private static final Set TREE_KINDS = + EnumSet.of(Tree.Kind.METHOD_INVOCATION); + + public InternalMethodHint() { + super(true, true, AbstractHint.HintSeverity.WARNING); + } + + //Specify the kind of code that the hint applies to, in this case, + //the hint applies to method invocations: + @Override + public Set getTreeKinds() { + return TREE_KINDS; + } + + @Override + public List run(CompilationInfo info, TreePath treePath) { + + Tree t = treePath.getLeaf(); + + Element el = info.getTrees().getElement(treePath); + + if (el.getAnnotation(Internal.class) != null) { + //prepare selection for removing + JTextComponent editor = EditorRegistry.lastFocusedComponent(); + Document doc = editor.getDocument(); + SourcePositions sp = info.getTrees().getSourcePositions(); + int start = (int) sp.getStartPosition(info.getCompilationUnit(), t); + int end = (int) sp.getEndPosition(info.getCompilationUnit(), t); + String bodyText = info.getText().substring(start, end); + //prepare fix + List fixes = new ArrayList(); + fixes.add(new MessagesFix(doc, start, bodyText)); + + return Collections.singletonList( + ErrorDescriptionFactory.createErrorDescription( + getSeverity().toEditorSeverity(), + getDisplayName(), + fixes, + info.getFileObject(), + (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), t), + (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), t))); + + } + + return null; + + } + + //This is called if/when the hint processing is cancelled: + @Override + public void cancel() { + } + + //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!"; + } + + //Name of the hint in the Options window: + @Override + public String getId() { + return "Internal Methods"; + } + + //Description of the hint in the Options window: + @Override + public String getDescription() { + return "Checks for calls to internal methods."; + } + + class MessagesFix implements EnhancedFix { + + Document doc = null; + int start = 0; + String bodyText = null; + + public MessagesFix(Document doc, int start, String bodyText) { + this.doc = doc; + this.start = start; + this.bodyText = bodyText; + } + + @Override + public CharSequence getSortText() { + return "charsequence"; + } + + @Override + public String getText() { + return "Remove this call"; + } + + @Override + public ChangeInfo implement() throws Exception { + //Add 1 character, for the semi-colon: + doc.remove(start, bodyText.length() + 1); + //Display message to user in status bar: + StatusDisplayer.getDefault().setStatusText("Removed: " + bodyText); + return null; + } + } +} diff --git a/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/ReadOnlyPrimitiveHint.java b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/ReadOnlyPrimitiveHint.java new file mode 100644 index 000000000..3d7ff7bc6 --- /dev/null +++ b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/ReadOnlyPrimitiveHint.java @@ -0,0 +1,143 @@ +package com.jme3.gde.codecheck.hints; + +import com.jme3.system.Annotations.ReadOnly; +import com.sun.source.tree.Tree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreePath; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorRegistry; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.modules.java.hints.spi.AbstractHint; +import org.netbeans.spi.editor.hints.ChangeInfo; +import org.netbeans.spi.editor.hints.EnhancedFix; +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; + +public class ReadOnlyPrimitiveHint extends AbstractHint { + + //This hint does not enable the IDE to fix the problem: + private static final List NO_FIXES = Collections.emptyList(); + //This hint applies to method invocations: + private static final Set TREE_KINDS = + EnumSet.of(Tree.Kind.METHOD_INVOCATION); + + public ReadOnlyPrimitiveHint() { + super(true, true, AbstractHint.HintSeverity.WARNING); + } + + //Specify the kind of code that the hint applies to, in this case, + //the hint applies to method invocations: + @Override + public Set getTreeKinds() { + return TREE_KINDS; + } + + @Override + public List run(CompilationInfo info, TreePath treePath) { + +// MethodInvocationTree mit = (MethodInvocationTree) treePath.getLeaf(); +// ExpressionTree select = mit.getMethodSelect(); +// TreePath method = new TreePath(treePath, select); +// Element el = info.getTrees().getElement(method); +// TypeElement invokedClass = (TypeElement) el.getEnclosingElement(); + + if (info.getTrees().getElement(treePath).getAnnotation(ReadOnly.class) != null) { + Tree t = treePath.getLeaf(); + //prepare selection for removing + JTextComponent editor = EditorRegistry.lastFocusedComponent(); +// Document doc = editor.getDocument(); + SourcePositions sp = info.getTrees().getSourcePositions(); +// int start = (int) sp.getStartPosition(info.getCompilationUnit(), t); + int end = (int) sp.getEndPosition(info.getCompilationUnit(), t); + + //TODO: add more checks + boolean fail = false; + if (info.getText().length() >= end + 4) { + String dotText = info.getText().substring(end, end + 4); + if (".set".equals(dotText)) { + fail = true; + } + } + + if (fail) { + return Collections.singletonList( + ErrorDescriptionFactory.createErrorDescription( + getSeverity().toEditorSeverity(), + getDisplayName(), + NO_FIXES, + info.getFileObject(), + (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), t), + (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), t))); + } + return null; + + } + + return null; + + } + + //This is called if/when the hint processing is cancelled: + @Override + public void cancel() { + } + + //Message that the user sees in the left sidebar: + @Override + public String getDisplayName() { + return "This primitive is read only and should not be modified!"; + } + + //Name of the hint in the Options window: + @Override + public String getId() { + return "ReadOnly Primitives"; + } + + //Description of the hint in the Options window: + @Override + public String getDescription() { + return "Checks for modifications to readonly primitives. (getLocalTranslation().set())"; + } + + class MessagesFix implements EnhancedFix { + + Document doc = null; + int start = 0; + String bodyText = null; + + public MessagesFix(Document doc, int start, String bodyText) { + this.doc = doc; + this.start = start; + this.bodyText = bodyText; + } + + @Override + public CharSequence getSortText() { + return "charsequence"; + } + + @Override + public String getText() { + return "Remove this call"; + } + + @Override + public ChangeInfo implement() throws Exception { + //Add 1 character, for the semi-colon: + doc.remove(start, bodyText.length() + 1); + //Display message to user in status bar: + StatusDisplayer.getDefault().setStatusText("Removed: " + bodyText); + return null; + } + } +} diff --git a/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/UpdateHint.java b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/UpdateHint.java new file mode 100644 index 000000000..330adea2e --- /dev/null +++ b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/hints/UpdateHint.java @@ -0,0 +1,135 @@ +package com.jme3.gde.codecheck.hints; + +import com.sun.source.tree.Tree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreePath; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import javax.lang.model.element.Element; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorRegistry; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.modules.java.hints.spi.AbstractHint; +import org.netbeans.spi.editor.hints.ChangeInfo; +import org.netbeans.spi.editor.hints.EnhancedFix; +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; + +public class UpdateHint extends AbstractHint { + + //This hint does not enable the IDE to fix the problem: + private static final List NO_FIXES = Collections.emptyList(); + //This hint applies to method invocations: + private static final Set TREE_KINDS = + EnumSet.of(Tree.Kind.METHOD_INVOCATION); + + public UpdateHint() { + super(true, true, AbstractHint.HintSeverity.WARNING); + } + + //Specify the kind of code that the hint applies to, in this case, + //the hint applies to method invocations: + @Override + public Set getTreeKinds() { + return TREE_KINDS; + } + + @Override + public List run(CompilationInfo info, TreePath treePath) { + + Tree t = treePath.getLeaf(); + + Element el = info.getTrees().getElement(treePath); + String name = el.getSimpleName().toString(); + + //This is where it all happens: if the method invocation is 'showMessageDialog', + //then the hint infrastructure kicks into action: + if (name.equals("updateGeometricState") || name.equals("updateLogicalState") || name.equals("updateModelBound")) { + //prepare selection for removing + JTextComponent editor = EditorRegistry.lastFocusedComponent(); + Document doc = editor.getDocument(); + SourcePositions sp = info.getTrees().getSourcePositions(); + int start = (int) sp.getStartPosition(info.getCompilationUnit(), t); + int end = (int) sp.getEndPosition(info.getCompilationUnit(), t); + String bodyText = info.getText().substring(start, end); + //prepare fix + List fixes = new ArrayList(); + fixes.add(new MessagesFix(doc, start, bodyText)); + + return Collections.singletonList( + ErrorDescriptionFactory.createErrorDescription( + getSeverity().toEditorSeverity(), + getDisplayName(), + fixes, + info.getFileObject(), + (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), t), + (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), t))); + + } + + return null; + + } + + //This is called if/when the hint processing is cancelled: + @Override + public void cancel() { + } + + //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."; + } + + //Name of the hint in the Options window: + @Override + public String getId() { + return "Update States / Bound"; + } + + //Description of the hint in the Options window: + @Override + public String getDescription() { + return "Checks for calls to updateGeometricState(), updateLogicalState() and updateModelBound()."; + } + + class MessagesFix implements EnhancedFix { + + Document doc = null; + int start = 0; + String bodyText = null; + + public MessagesFix(Document doc, int start, String bodyText) { + this.doc = doc; + this.start = start; + this.bodyText = bodyText; + } + + @Override + public CharSequence getSortText() { + return "charsequence"; + } + + @Override + public String getText() { + return "Remove this call"; + } + + @Override + public ChangeInfo implement() throws Exception { + //Add 1 character, for the semi-colon: + doc.remove(start, bodyText.length() + 1); + //Display message to user in status bar: + StatusDisplayer.getDefault().setStatusText("Removed: " + bodyText); + return null; + } + } +} diff --git a/sdk/jme3-code-check/src/com/jme3/gde/codecheck/layer.xml b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/layer.xml new file mode 100644 index 000000000..25335f453 --- /dev/null +++ b/sdk/jme3-code-check/src/com/jme3/gde/codecheck/layer.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/sdk/jme3-codepalette/build.xml b/sdk/jme3-codepalette/build.xml new file mode 100644 index 000000000..a94e83093 --- /dev/null +++ b/sdk/jme3-codepalette/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.codepalette. + + diff --git a/sdk/jme3-codepalette/manifest.mf b/sdk/jme3-codepalette/manifest.mf new file mode 100644 index 000000000..3e2b5b8e4 --- /dev/null +++ b/sdk/jme3-codepalette/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.codepalette/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/codepalette/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/codepalette/Bundle.properties + diff --git a/sdk/jme3-codepalette/nbproject/build-impl.xml b/sdk/jme3-codepalette/nbproject/build-impl.xml new file mode 100644 index 000000000..b384dbe21 --- /dev/null +++ b/sdk/jme3-codepalette/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-codepalette/nbproject/genfiles.properties b/sdk/jme3-codepalette/nbproject/genfiles.properties new file mode 100644 index 000000000..6913b2d39 --- /dev/null +++ b/sdk/jme3-codepalette/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=ef6b2954 +build.xml.script.CRC32=27967d2c +build.xml.stylesheet.CRC32=a56c6a5b@1.42.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=ef6b2954 +nbproject/build-impl.xml.script.CRC32=c9af9eda +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.1 diff --git a/sdk/jme3-codepalette/nbproject/project.properties b/sdk/jme3-codepalette/nbproject/project.properties new file mode 100644 index 000000000..dbaf5c9f4 --- /dev/null +++ b/sdk/jme3-codepalette/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.1.0 diff --git a/sdk/jme3-codepalette/nbproject/project.xml b/sdk/jme3-codepalette/nbproject/project.xml new file mode 100644 index 000000000..df78da8e3 --- /dev/null +++ b/sdk/jme3-codepalette/nbproject/project.xml @@ -0,0 +1,72 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.codepalette + + + + org.netbeans.modules.editor.codetemplates + + + + 1 + 1.14.1.1 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.28.1 + + + + org.netbeans.spi.palette + + + + 1 + 1.20.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.text + + + + 6.27.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + + + + diff --git a/sdk/jme3-codepalette/nbproject/suite.properties b/sdk/jme3-codepalette/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-codepalette/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/Bundle.properties b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/Bundle.properties new file mode 100644 index 000000000..05ed4cbf5 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/Bundle.properties @@ -0,0 +1,5 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + The code palette gives you quick access to code snippets of the most commonly used jME3 objects. +OpenIDE-Module-Name=jME3 Code Palette +OpenIDE-Module-Short-Description=Code Palette with jME3 Objects diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/JavaSourceFileLayerPaletteFactory.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/JavaSourceFileLayerPaletteFactory.java new file mode 100644 index 000000000..fe37a5023 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/JavaSourceFileLayerPaletteFactory.java @@ -0,0 +1,73 @@ +/* + * JavaSourceFileLayerPaletteFactory.java + * + * Created on Jun 4, 2007, 12:33:34 PM + * + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.codepalette; + +import java.io.IOException; +import javax.swing.Action; +import org.netbeans.spi.palette.PaletteActions; +import org.netbeans.spi.palette.PaletteController; +import org.netbeans.spi.palette.PaletteFactory; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + + +/** + * + * @author gw152771 + */ +public class JavaSourceFileLayerPaletteFactory { + + public static final String JAVA_PALETTE_FOLDER = "JavaPalette"; + private static PaletteController palette = null; + + public JavaSourceFileLayerPaletteFactory() { + } + + public static PaletteController createPalette() { + try { + if (null == palette) + palette = PaletteFactory.createPalette(JAVA_PALETTE_FOLDER, new MyActions()); + return palette; + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + private static class MyActions extends PaletteActions { + + //Add new buttons to the Palette Manager here: + public Action[] getImportActions() { + return null; + } + + //Add new contextual menu items to the palette here: + public Action[] getCustomPaletteActions() { + return null; + } + + //Add new contextual menu items to the categories here: + public Action[] getCustomCategoryActions(Lookup arg0) { + return null; + } + + //Add new contextual menu items to the items here: + public Action[] getCustomItemActions(Lookup arg0) { + return null; + } + + //Define the default action here: + public Action getPreferredAction(Lookup arg0) { + return null; + } + + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/JmePaletteUtilities.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/JmePaletteUtilities.java new file mode 100644 index 000000000..9646cf408 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/JmePaletteUtilities.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2009-2010 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.codepalette; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import javax.swing.text.StyledDocument; +import org.openide.text.NbDocument; + +public class JmePaletteUtilities { + + public static void insert(final String s,final JTextComponent target) throws BadLocationException { + + final StyledDocument doc = (StyledDocument)target.getDocument(); + + class AtomicChange implements Runnable { + + public void run() { + Document value = target.getDocument(); + if (value == null) + return; + try { + insert(s, target, doc); + } catch (BadLocationException e) {} + } + } + + try { + NbDocument.runAtomicAsUser(doc, new AtomicChange()); + } catch (BadLocationException ex) {} + + } + + private static int insert(String s, JTextComponent target, Document doc) throws BadLocationException { + + int start = -1; + + try { + + //firstly, find selected text range: + Caret caret = target.getCaret(); + int p0 = Math.min(caret.getDot(), caret.getMark()); + int p1 = Math.max(caret.getDot(), caret.getMark()); + doc.remove(p0, p1 - p0); + + //then, replace selected text range with the inserted one: + start = caret.getDot(); + doc.insertString(start, s, null); + + } catch (BadLocationException ble) {} + + return start; + + } + +} \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/layer.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/layer.xml new file mode 100644 index 000000000..8b778b52d --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/layer.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/AmbLight.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/AmbLight.xml new file mode 100644 index 000000000..fcc4dbc75 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/AmbLight.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + AmbientLight + light source (ambient) + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/BleedCube.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/BleedCube.xml new file mode 100644 index 000000000..f36474703 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/BleedCube.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + BleedCube + textured cube with color bleeding through + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Explosion.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Explosion.xml new file mode 100644 index 000000000..e86d22c56 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Explosion.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Explosion + explosion effect + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Fire.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Fire.xml new file mode 100644 index 000000000..c9d4fbb0a --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Fire.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Fire + fire effect + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/HUDText.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/HUDText.xml new file mode 100644 index 000000000..306621f16 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/HUDText.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + HUDText + displaying text on screen (HUD) + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteAmbientLight.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteAmbientLight.java new file mode 100644 index 000000000..c163a8633 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteAmbientLight.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteAmbientLight implements ActiveEditorDrop { + + public JmePaletteAmbientLight() { + } + + private String createBody() { + + String body = " /** A white ambient light source. */ \n AmbientLight ambient = new AmbientLight();\n ambient.setColor(ColorRGBA.White);\n rootNode.addLight(ambient); "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteBleedCube.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteBleedCube.java new file mode 100644 index 000000000..b910f9c85 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteBleedCube.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen + */ +public class JmePaletteBleedCube implements ActiveEditorDrop { + + public JmePaletteBleedCube() { + } + + private String createBody() { + + String body = " /** A cube with a color \"bleeding\" through transparent texture. Uses Texture from jme3-test-data library! */ \n Box boxshape4 = new Box(Vector3f.ZERO, 1f,1f,1f);\n Geometry cube_leak = new Geometry(\"Bleed-through color cube\", boxshape4);\n Material mat_tl = new Material(assetManager, \"Common/MatDefs/Misc/Unshaded.j3md\");\n mat_tl.setTexture(\"ColorMap\", assetManager.loadTexture(\"Textures/ColoredTex/Monkey.png\"));\n mat_tl.setColor(\"Color\", new ColorRGBA(1f,0f,1f, 1f)); // purple\n cube_leak.setMaterial(mat_tl);\n rootNode.attachChild(cube_leak); "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteExplosion.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteExplosion.java new file mode 100644 index 000000000..641c06a35 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteExplosion.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteExplosion implements ActiveEditorDrop { + + public JmePaletteExplosion() { + } + + private String createBody() { + + String body = " /** Explosion effect. Uses Texture from jme3-test-data library! */ \n ParticleEmitter debris = new ParticleEmitter(\"Debris\", ParticleMesh.Type.Triangle, 10);\n Material debris_mat = new Material(assetManager, \"Common/MatDefs/Misc/Particle.j3md\");\n debris_mat.setTexture(\"Texture\", assetManager.loadTexture(\"Effects/Explosion/Debris.png\"));\n debris.setMaterial(debris_mat);\n debris.setImagesX(3); debris.setImagesY(3); // 3x3 texture animation\n debris.setRotateSpeed(4);\n debris.setSelectRandomImage(true);\n debris.setStartVel(new Vector3f(0, 4, 0));\n debris.setStartColor(new ColorRGBA(1f, 1f, 1f, 1f));\n debris.setGravity(6f);\n debris.setVariation(.60f);\n rootNode.attachChild(debris);\n debris.emitAllParticles();\n"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteFire.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteFire.java new file mode 100644 index 000000000..fb5d959d4 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteFire.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteFire implements ActiveEditorDrop { + + public JmePaletteFire() { + } + + private String createBody() { + + String body = " /** Uses Texture from jme3-test-data library! */\n ParticleEmitter fire = new ParticleEmitter(\"Emitter\", ParticleMesh.Type.Triangle, 30);\n Material mat_red = new Material(assetManager, \"Common/MatDefs/Misc/Particle.j3md\");\n //mat_red.setTexture(\"Texture\", assetManager.loadTexture(\"Effects/Explosion/flame.png\"));\n fire.setMaterial(mat_red);\n fire.setImagesX(2); fire.setImagesY(2); // 2x2 texture animation\n fire.setEndColor( new ColorRGBA(1f, 0f, 0f, 1f)); // red\n fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow\n fire.setStartVel(new Vector3f(0, 2, 0));\n fire.setStartSize(0.6f);\n fire.setEndSize(0.1f);\n fire.setGravity(0);\n fire.setLowLife(0.5f);\n fire.setHighLife(3f);\n fire.setVariation(0.3f);\n rootNode.attachChild(fire);\n"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteHUDText.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteHUDText.java new file mode 100644 index 000000000..12c0521d9 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteHUDText.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen + */ +public class JmePaletteHUDText implements ActiveEditorDrop { + + public JmePaletteHUDText() { + } + + private String createBody() { + String body = " /** Write text on the screen (HUD) */\n guiNode.detachAllChildren();\n guiFont = assetManager.loadFont(\"Interface/Fonts/Default.fnt\");\n BitmapText helloText = new BitmapText(guiFont, false);\n helloText.setSize(guiFont.getCharSet().getRenderedSize());\n helloText.setText(\"Hello World\");\n helloText.setLocalTranslation(300, helloText.getLineHeight(), 0);\n guiNode.attachChild(helloText);\n "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteModel.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteModel.java new file mode 100644 index 000000000..1de0dee9e --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteModel.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen + */ +public class JmePaletteModel implements ActiveEditorDrop { + + public JmePaletteModel() { + } + + private String createBody() { + + String body = " /** Load a model. Uses model and texture from jme3-test-data library! */ \n Spatial teapot = assetManager.loadModel(\"Models/Teapot/Teapot.obj\");\n Material mat_default = new Material( assetManager, \"Common/MatDefs/Misc/ShowNormals.j3md\");\n teapot.setMaterial(mat_default);\n rootNode.attachChild(teapot);"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteNode.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteNode.java new file mode 100644 index 000000000..3b199a825 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteNode.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen + */ +public class JmePaletteNode implements ActiveEditorDrop { + + public JmePaletteNode() { + } + + private String createBody() { + String body = "Node node = new Node();"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch045.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch045.java new file mode 100644 index 000000000..59b5cf209 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch045.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePalettePitch045 implements ActiveEditorDrop { + + public JmePalettePitch045() { + } + + private String createBody() { + + String body = "public static final Quaternion PITCH045 = new Quaternion().fromAngleAxis(FastMath.PI/4, new Vector3f(1,0,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch090.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch090.java new file mode 100644 index 000000000..945ba91f4 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch090.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePalettePitch090 implements ActiveEditorDrop { + + public JmePalettePitch090() { + } + + private String createBody() { + + String body = "public static final Quaternion PITCH090 = new Quaternion().fromAngleAxis(FastMath.PI/2, new Vector3f(1,0,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch180.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch180.java new file mode 100644 index 000000000..741f320f5 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch180.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePalettePitch180 implements ActiveEditorDrop { + + public JmePalettePitch180() { + } + + private String createBody() { + + String body = "public static final Quaternion PITCH180 = new Quaternion().fromAngleAxis(FastMath.PI , new Vector3f(1,0,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch270.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch270.java new file mode 100644 index 000000000..f3e412c43 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePitch270.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePalettePitch270 implements ActiveEditorDrop { + + public JmePalettePitch270() { + } + + private String createBody() { + + String body = "public static final Quaternion PITCH270 = new Quaternion().fromAngleAxis(FastMath.PI*3/2, new Vector3f(1,0,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePointLight.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePointLight.java new file mode 100644 index 000000000..b706f2b4a --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePalettePointLight.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePalettePointLight implements ActiveEditorDrop { + + public JmePalettePointLight() { + } + + private String createBody() { + + String body = " /** A white, spot light source. */ \n PointLight lamp = new PointLight();\n lamp.setPosition(Vector3f.ZERO);\n lamp.setColor(ColorRGBA.White);\n rootNode.addLight(lamp); "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll045.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll045.java new file mode 100644 index 000000000..64a6139a1 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll045.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteRoll045 implements ActiveEditorDrop { + + public JmePaletteRoll045() { + } + + private String createBody() { + + String body = "public static final Quaternion ROLL045 = new Quaternion().fromAngleAxis(FastMath.PI/4, new Vector3f(0,0,1));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll090.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll090.java new file mode 100644 index 000000000..1261e1753 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll090.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteRoll090 implements ActiveEditorDrop { + + public JmePaletteRoll090() { + } + + private String createBody() { + + String body = "public static final Quaternion ROLL090 = new Quaternion().fromAngleAxis(FastMath.PI/2, new Vector3f(0,0,1));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll180.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll180.java new file mode 100644 index 000000000..9e090b59b --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll180.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteRoll180 implements ActiveEditorDrop { + + public JmePaletteRoll180() { + } + + private String createBody() { + + String body = "public static final Quaternion ROLL180 = new Quaternion().fromAngleAxis(FastMath.PI , new Vector3f(0,0,1));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll270.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll270.java new file mode 100644 index 000000000..90d597dac --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteRoll270.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteRoll270 implements ActiveEditorDrop { + + public JmePaletteRoll270() { + } + + private String createBody() { + + String body = "public static final Quaternion ROLL270 = new Quaternion().fromAngleAxis(FastMath.PI*3/2, new Vector3f(0,0,1));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteSetJ3M.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteSetJ3M.java new file mode 100644 index 000000000..c2ad45a1d --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteSetJ3M.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteSetJ3M implements ActiveEditorDrop { + + public JmePaletteSetJ3M() { + } + + private String createBody() { + + String body = " myj3oModel.setMaterial( (Material)assetManager.loadAsset( \"mymaterial.j3m\") );\n"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteShinySphere.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteShinySphere.java new file mode 100644 index 000000000..a9415d379 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteShinySphere.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteShinySphere implements ActiveEditorDrop { + + public JmePaletteShinySphere() { + } + + private String createBody() { + + String body = " /** Bumpy rock with shiny light effect. Uses Texture from jme3-test-data library! Needs light source! */\n Sphere rock = new Sphere(32,32, 2f);\n Geometry shiny_rock = new Geometry(\"Shiny rock\", rock);\n rock.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres\n TangentBinormalGenerator.generate(rock); // for lighting effect\n Material mat_lit = new Material(assetManager, \"Common/MatDefs/Light/Lighting.j3md\");\n mat_lit.setTexture(\"DiffuseMap\", assetManager.loadTexture(\"Textures/Terrain/Pond/Pond.png\"));\n mat_lit.setTexture(\"NormalMap\", assetManager.loadTexture(\"Textures/Terrain/Pond/Pond_normal.png\"));\n mat_lit.setFloat(\"Shininess\", 5f); // [0,128]\n shiny_rock.setMaterial(mat_lit);\n rootNode.attachChild(shiny_rock);\n "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteSunLight.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteSunLight.java new file mode 100644 index 000000000..d4c55d2f8 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteSunLight.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteSunLight implements ActiveEditorDrop { + + public JmePaletteSunLight() { + } + + private String createBody() { + + String body = " /** A white, directional light source */ \n DirectionalLight sun = new DirectionalLight();\n sun.setDirection(new Vector3f(1,0,-2).normalizeLocal());\n sun.setColor(ColorRGBA.White);\n rootNode.addLight(sun); "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteTextureCube.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteTextureCube.java new file mode 100644 index 000000000..9c307fe5e --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteTextureCube.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteTextureCube implements ActiveEditorDrop { + + public JmePaletteTextureCube() { + } + + private String createBody() { + + String body = "/** A simple textured cube. Uses Texture from jme3-test-data library! */ \n Box boxshape1 = new Box(Vector3f,ZERO, 1f,1f,1f); \n Geometry cube = new Geometry(\"A Textured Box\", boxshape1); \n Material mat_stl = new Material(assetManager, \"Common/MatDefs/Misc/Unshaded.j3md\"); \n Texture tex_ml = assetManager.loadTexture(\"Interface/Logo/Monkey.jpg\"); \n mat_stl.setTexture(\"ColorMap\", tex_ml); \n cube.setMaterial(mat_stl); \n rootNode.attachChild(cube); "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteTrnspCube.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteTrnspCube.java new file mode 100644 index 000000000..25cf441c8 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteTrnspCube.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteTrnspCube implements ActiveEditorDrop { + + public JmePaletteTrnspCube() { + } + + private String createBody() { + + String body = " /** Translucent/transparent cube. Uses Texture from jme3-test-data library! */\n Box boxshape3 = new Box(Vector3f.ZERO, 1f,1f,1f);\n Geometry cube_translucent = new Geometry(\"translucent cube\", boxshape3);\n Material mat_tt = new Material(assetManager, \"Common/MatDefs/Misc/Unshaded.j3md\");\n mat_tt.setTexture(\"ColorMap\", assetManager.loadTexture(\"Textures/ColoredTex/Monkey.png\"));\n mat_tt.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);\n cube_translucent.setMaterial(mat_tt); \n rootNode.attachChild(cube_translucent); "; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw045.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw045.java new file mode 100644 index 000000000..11e895d3f --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw045.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteYaw045 implements ActiveEditorDrop { + + public JmePaletteYaw045() { + } + + private String createBody() { + + String body = "public static final Quaternion YAW045 = new Quaternion().fromAngleAxis(FastMath.PI/4, new Vector3f(0,1,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw090.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw090.java new file mode 100644 index 000000000..caefd7d6d --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw090.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteYaw090 implements ActiveEditorDrop { + + public JmePaletteYaw090() { + } + + private String createBody() { + + String body = "public static final Quaternion YAW090 = new Quaternion().fromAngleAxis(FastMath.PI/2, new Vector3f(0,1,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw180.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw180.java new file mode 100644 index 000000000..23b8ceab5 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw180.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteYaw180 implements ActiveEditorDrop { + + public JmePaletteYaw180() { + } + + private String createBody() { + + String body = "public static final Quaternion YAW180 = new Quaternion().fromAngleAxis(FastMath.PI , new Vector3f(0,1,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw270.java b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw270.java new file mode 100644 index 000000000..aff80cf5d --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteYaw270.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009-2010 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.codepalette.scene; +import com.jme3.gde.codepalette.JmePaletteUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.openide.text.ActiveEditorDrop; + +/** + * + * @author normenhansen, zathras + */ +public class JmePaletteYaw270 implements ActiveEditorDrop { + + public JmePaletteYaw270() { + } + + private String createBody() { + + String body = "public static final Quaternion YAW270 = new Quaternion().fromAngleAxis(FastMath.PI*3/2, new Vector3f(0,1,0));"; + return body; + } + + public boolean handleTransfer(JTextComponent targetComponent) { + String body = createBody(); + try { + JmePaletteUtilities.insert(body, targetComponent); + } catch (BadLocationException ble) { + return false; + } + return true; + } + +} diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Model.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Model.xml new file mode 100644 index 000000000..7c66a210b --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Model.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Model + loading model from assets + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Node.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Node.xml new file mode 100644 index 000000000..278d4e219 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Node.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Node + new node + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch045.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch045.xml new file mode 100644 index 000000000..4883546ab --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch045.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Pitch 45° + Quaternion pitch 45° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch090.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch090.xml new file mode 100644 index 000000000..dcd955a51 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch090.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Pitch 90° + Quaternion pitch 90° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch180.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch180.xml new file mode 100644 index 000000000..7b17cdec8 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch180.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Pitch 180° + Quaternion pitch 180° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch270.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch270.xml new file mode 100644 index 000000000..df6769057 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Pitch270.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Pitch 270° + Quaternion pitch 270° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/PointLight.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/PointLight.xml new file mode 100644 index 000000000..864c47a14 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/PointLight.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + PointLight + light source (lamp) + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll045.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll045.xml new file mode 100644 index 000000000..725b11e45 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll045.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Roll 45° + Quaternion roll 45° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll090.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll090.xml new file mode 100644 index 000000000..e8dab4e22 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll090.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Roll 90° + Quaternion roll 90° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll180.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll180.xml new file mode 100644 index 000000000..12b8b92ca --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll180.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Roll 180° + Quaternion roll 180° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll270.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll270.xml new file mode 100644 index 000000000..9fd7230c7 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Roll270.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Roll 270° + Quaternion roll 270° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/SetJ3M.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/SetJ3M.xml new file mode 100644 index 000000000..539fe0304 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/SetJ3M.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Set j3m + Set j3m Material + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/ShinySphere.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/ShinySphere.xml new file mode 100644 index 000000000..6aec250db --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/ShinySphere.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + ShinySphere + shiny bumpy textured sphere + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/SunLight.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/SunLight.xml new file mode 100644 index 000000000..8ea05170e --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/SunLight.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + SunLight + light source (sun light) + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/TextureCube.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/TextureCube.xml new file mode 100644 index 000000000..86666898f --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/TextureCube.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + TextureCube + plain textured Cube + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/TrnspCube.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/TrnspCube.xml new file mode 100644 index 000000000..94eab2a34 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/TrnspCube.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + TrnspCube + transparent/translucent textured cube + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw045.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw045.xml new file mode 100644 index 000000000..0284e9f74 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw045.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Yaw 45° + Quaternion yaw 45° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw090.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw090.xml new file mode 100644 index 000000000..54358504e --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw090.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Yaw 90° + Quaternion yaw 90° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw180.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw180.xml new file mode 100644 index 000000000..77a6ca468 --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw180.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Yaw 180° + Quaternion yaw 180° + + + \ No newline at end of file diff --git a/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw270.xml b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw270.xml new file mode 100644 index 000000000..b871daefc --- /dev/null +++ b/sdk/jme3-codepalette/src/com/jme3/gde/codepalette/scene/Yaw270.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + Yaw 270° + Quaternion yaw 270° + + + \ No newline at end of file diff --git a/sdk/jme3-core-baselibs/build.xml b/sdk/jme3-core-baselibs/build.xml new file mode 100644 index 000000000..7a2e30f24 --- /dev/null +++ b/sdk/jme3-core-baselibs/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.core.baselibs. + + diff --git a/sdk/jme3-core-baselibs/manifest.mf b/sdk/jme3-core-baselibs/manifest.mf new file mode 100644 index 000000000..610ce52d2 --- /dev/null +++ b/sdk/jme3-core-baselibs/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.core.baselibs/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/core/baselibs/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/core/baselibs/Bundle.properties + diff --git a/sdk/jme3-core-baselibs/nbproject/build-impl.xml b/sdk/jme3-core-baselibs/nbproject/build-impl.xml new file mode 100644 index 000000000..d3af39cf2 --- /dev/null +++ b/sdk/jme3-core-baselibs/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core-baselibs/nbproject/genfiles.properties b/sdk/jme3-core-baselibs/nbproject/genfiles.properties new file mode 100644 index 000000000..7a951c614 --- /dev/null +++ b/sdk/jme3-core-baselibs/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=f8e0e6a8 +build.xml.script.CRC32=cdae6a36 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=f8e0e6a8 +nbproject/build-impl.xml.script.CRC32=246f9b81 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-core-baselibs/nbproject/project.properties b/sdk/jme3-core-baselibs/nbproject/project.properties new file mode 100644 index 000000000..1bf79513d --- /dev/null +++ b/sdk/jme3-core-baselibs/nbproject/project.properties @@ -0,0 +1,9 @@ +file.reference.jME3-lwjgl-natives.jar=release/modules/ext/jME3-lwjgl-natives.jar +file.reference.jMonkeyEngine3.jar=release/modules/ext/jMonkeyEngine3.jar +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=jMonkeyEngine +nbm.needs.restart=true +spec.version.base=0.8.0 diff --git a/sdk/jme3-core-baselibs/nbproject/project.xml b/sdk/jme3-core-baselibs/nbproject/project.xml new file mode 100644 index 000000000..79694c2d3 --- /dev/null +++ b/sdk/jme3-core-baselibs/nbproject/project.xml @@ -0,0 +1,123 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.core.baselibs + + + + com.jme3.gde.core.libraries + + + + 1 + 0.5 + + + + + com.jme3.animation + com.jme3.app + com.jme3.app.state + com.jme3.asset + com.jme3.asset.pack + com.jme3.asset.plugins + com.jme3.audio + com.jme3.audio.lwjgl + com.jme3.audio.plugins + com.jme3.bounding + com.jme3.bullet + com.jme3.bullet.collision + com.jme3.bullet.collision.shapes + com.jme3.bullet.collision.shapes.infos + com.jme3.bullet.control + com.jme3.bullet.joints + com.jme3.bullet.joints.motors + com.jme3.bullet.nodes + com.jme3.bullet.objects + com.jme3.bullet.objects.infos + com.jme3.bullet.util + com.jme3.cinematic + com.jme3.cinematic.events + com.jme3.collision + com.jme3.collision.bih + com.jme3.effect + com.jme3.export + com.jme3.export.binary + com.jme3.export.xml + com.jme3.font + com.jme3.font.plugins + com.jme3.input + com.jme3.input.awt + com.jme3.input.controls + com.jme3.input.dummy + com.jme3.input.event + com.jme3.input.lwjgl + com.jme3.light + com.jme3.material + com.jme3.material.plugins + com.jme3.math + com.jme3.network.connection + com.jme3.network.events + com.jme3.network.message + com.jme3.network.queue + com.jme3.network.rmi + com.jme3.network.serializing + com.jme3.network.serializing.serializers + com.jme3.network.service + com.jme3.network.streaming + com.jme3.network.sync + com.jme3.niftygui + com.jme3.post + com.jme3.post.filters + com.jme3.post.ssao + com.jme3.renderer + com.jme3.renderer.layer + com.jme3.renderer.lwjgl + com.jme3.renderer.queue + com.jme3.scene + com.jme3.scene.control + com.jme3.scene.debug + com.jme3.scene.mesh + com.jme3.scene.plugins + com.jme3.scene.plugins.ogre + com.jme3.scene.plugins.ogre.matext + com.jme3.scene.shape + com.jme3.shader + com.jme3.shader.plugins + com.jme3.shadow + com.jme3.system + com.jme3.system.lwjgl + com.jme3.terrain + com.jme3.terrain.geomipmap + com.jme3.terrain.geomipmap.lodcalc + com.jme3.terrain.geomipmap.lodcalc.util + com.jme3.terrain.geomipmap.picking + com.jme3.terrain.heightmap + com.jme3.texture + com.jme3.texture.plugins + com.jme3.ui + com.jme3.util + com.jme3.util.xml + com.jme3.video + com.jme3.video.plugins.jheora + com.jme3.water + jme3tools.converters + jme3tools.converters.model + jme3tools.converters.model.strip + jme3tools.navigation + jme3tools.nvtex + jme3tools.optimize + + + ext/jMonkeyEngine3.jar + release/modules/ext/jMonkeyEngine3.jar + + + ext/jME3-lwjgl-natives.jar + release/modules/ext/jME3-lwjgl-natives.jar + + + + diff --git a/sdk/jme3-core-baselibs/nbproject/suite.properties b/sdk/jme3-core-baselibs/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-core-baselibs/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-core-baselibs/src/com/jme3/gde/core/baselibs/Bundle.properties b/sdk/jme3-core-baselibs/src/com/jme3/gde/core/baselibs/Bundle.properties new file mode 100644 index 000000000..2ad2cbba1 --- /dev/null +++ b/sdk/jme3-core-baselibs/src/com/jme3/gde/core/baselibs/Bundle.properties @@ -0,0 +1,5 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides the core jME3 libraries for jMonkeyPlatform +OpenIDE-Module-Name=jMonkeyPlatform Core jME3 +OpenIDE-Module-Short-Description=Provides the Core jME3 Libraries for jMP diff --git a/sdk/jme3-core-baselibs/src/com/jme3/gde/core/baselibs/layer.xml b/sdk/jme3-core-baselibs/src/com/jme3/gde/core/baselibs/layer.xml new file mode 100644 index 000000000..c16a8a0fe --- /dev/null +++ b/sdk/jme3-core-baselibs/src/com/jme3/gde/core/baselibs/layer.xml @@ -0,0 +1,4 @@ + + + + diff --git a/sdk/jme3-core-libraries/build.xml b/sdk/jme3-core-libraries/build.xml new file mode 100644 index 000000000..50c29349a --- /dev/null +++ b/sdk/jme3-core-libraries/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.core.libraries. + + diff --git a/sdk/jme3-core-libraries/manifest.mf b/sdk/jme3-core-libraries/manifest.mf new file mode 100644 index 000000000..a4343d76c --- /dev/null +++ b/sdk/jme3-core-libraries/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.core.libraries/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/core/libraries/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/core/libraries/Bundle.properties + diff --git a/sdk/jme3-core-libraries/nbproject/build-impl.xml b/sdk/jme3-core-libraries/nbproject/build-impl.xml new file mode 100644 index 000000000..e74a10694 --- /dev/null +++ b/sdk/jme3-core-libraries/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core-libraries/nbproject/genfiles.properties b/sdk/jme3-core-libraries/nbproject/genfiles.properties new file mode 100644 index 000000000..e135c3f67 --- /dev/null +++ b/sdk/jme3-core-libraries/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=0e75b8bc +build.xml.script.CRC32=f48eacdc +build.xml.stylesheet.CRC32=79c3b980@1.31.1.7 +# 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=0e75b8bc +nbproject/build-impl.xml.script.CRC32=4c1550d4 +nbproject/build-impl.xml.stylesheet.CRC32=261c4bef@1.31.1.7 diff --git a/sdk/jme3-core-libraries/nbproject/project.properties b/sdk/jme3-core-libraries/nbproject/project.properties new file mode 100644 index 000000000..462961c87 --- /dev/null +++ b/sdk/jme3-core-libraries/nbproject/project.properties @@ -0,0 +1,19 @@ +file.reference.j-ogg-oggd.jar=release/modules/ext/j-ogg-oggd.jar +file.reference.j-ogg-vorbisd.jar=release/modules/ext/j-ogg-vorbisd.jar +file.reference.jbullet.jar=release/modules/ext/jbullet.jar +file.reference.jinput.jar=release/modules/ext/jinput.jar +file.reference.lwjgl.jar=release/modules/ext/lwjgl.jar +file.reference.nifty-1.2-SNAPSHOT.jar=release/modules/ext/nifty-1.1.jar +file.reference.nifty-1.3-SNAPSHOT.jar=release/modules/ext/nifty-1.3-SNAPSHOT.jar +file.reference.nifty-default-controls-1.3-SNAPSHOT.jar=release/modules/ext/nifty-default-controls-1.3-SNAPSHOT.jar +file.reference.nifty-style-black-1.3-SNAPSHOT.jar=release/modules/ext/nifty-style-black-1.3-SNAPSHOT.jar +file.reference.stack-alloc.jar=release/modules/ext/stack-alloc.jar +file.reference.vecmath.jar=release/modules/ext/vecmath.jar +file.reference.xmlpull-xpp3-1.1.4c.jar=release/modules/ext/xmlpull-xpp3-1.1.4c.jar +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=jMonkeyEngine +nbm.needs.restart=true +spec.version.base=0.8.0 diff --git a/sdk/jme3-core-libraries/nbproject/project.xml b/sdk/jme3-core-libraries/nbproject/project.xml new file mode 100644 index 000000000..d091dd3ca --- /dev/null +++ b/sdk/jme3-core-libraries/nbproject/project.xml @@ -0,0 +1,172 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.core.libraries + + + + com.bulletphysics + com.bulletphysics.collision.broadphase + com.bulletphysics.collision.dispatch + com.bulletphysics.collision.narrowphase + com.bulletphysics.collision.shapes + com.bulletphysics.dom + com.bulletphysics.dynamics + com.bulletphysics.dynamics.character + com.bulletphysics.dynamics.constraintsolver + com.bulletphysics.dynamics.vehicle + com.bulletphysics.extras.gimpact + com.bulletphysics.linearmath + com.bulletphysics.linearmath.convexhull + com.bulletphysics.util + cz.advel.stack + cz.advel.stack.instrument + de.jarnbjo.ogg + de.jarnbjo.util.io + de.jarnbjo.vorbis + de.lessvoid.nifty + de.lessvoid.nifty.builder + de.lessvoid.nifty.controls + de.lessvoid.nifty.controls.button + de.lessvoid.nifty.controls.button.builder + de.lessvoid.nifty.controls.checkbox + de.lessvoid.nifty.controls.checkbox.builder + de.lessvoid.nifty.controls.console.controller + de.lessvoid.nifty.controls.dragndrop + de.lessvoid.nifty.controls.dragndrop.controller + de.lessvoid.nifty.controls.dropdown + de.lessvoid.nifty.controls.dropdown.builder + de.lessvoid.nifty.controls.dynamic + de.lessvoid.nifty.controls.dynamic.attributes + de.lessvoid.nifty.controls.imageSelect + de.lessvoid.nifty.controls.label + de.lessvoid.nifty.controls.label.builder + de.lessvoid.nifty.controls.listbox + de.lessvoid.nifty.controls.listbox.builder + de.lessvoid.nifty.controls.nullobjects + de.lessvoid.nifty.controls.scrollbar + de.lessvoid.nifty.controls.scrollbar.builder + de.lessvoid.nifty.controls.scrollpanel + de.lessvoid.nifty.controls.scrollpanel.builder + de.lessvoid.nifty.controls.shared + de.lessvoid.nifty.controls.slider + de.lessvoid.nifty.controls.slider.builder + de.lessvoid.nifty.controls.textfield + de.lessvoid.nifty.controls.textfield.builder + de.lessvoid.nifty.controls.window + de.lessvoid.nifty.controls.window.controller + de.lessvoid.nifty.effects + de.lessvoid.nifty.effects.impl + de.lessvoid.nifty.elements + de.lessvoid.nifty.elements.render + de.lessvoid.nifty.elements.tools + de.lessvoid.nifty.input + de.lessvoid.nifty.input.keyboard + de.lessvoid.nifty.input.mapping + de.lessvoid.nifty.input.mouse + de.lessvoid.nifty.layout + de.lessvoid.nifty.layout.align + de.lessvoid.nifty.layout.manager + de.lessvoid.nifty.loaderv2 + de.lessvoid.nifty.loaderv2.types + de.lessvoid.nifty.loaderv2.types.apply + de.lessvoid.nifty.loaderv2.types.helper + de.lessvoid.nifty.loaderv2.types.resolver.parameter + de.lessvoid.nifty.loaderv2.types.resolver.style + de.lessvoid.nifty.nulldevice + de.lessvoid.nifty.render + de.lessvoid.nifty.screen + de.lessvoid.nifty.sound + de.lessvoid.nifty.spi.input + de.lessvoid.nifty.spi.render + de.lessvoid.nifty.spi.sound + de.lessvoid.nifty.tools + de.lessvoid.nifty.tools.pulsate + de.lessvoid.nifty.tools.pulsate.provider + de.lessvoid.nifty.tools.resourceloader + de.lessvoid.nifty.tools.time + de.lessvoid.nifty.tools.time.interpolator + de.lessvoid.xml.lwxs + de.lessvoid.xml.lwxs.elements + de.lessvoid.xml.lwxs.processor + de.lessvoid.xml.tools + de.lessvoid.xml.xpp3 + javax.vecmath + net.java.games.input + net.java.games.util + net.java.games.util.plugins + net.java.games.util.plugins.test + org.bushe.swing.event + org.bushe.swing.event.annotation + org.bushe.swing.event.generics + org.bushe.swing.exception + org.lwjgl + org.lwjgl.input + org.lwjgl.openal + org.lwjgl.opengl + org.xmlpull.mxp1 + org.xmlpull.mxp1_serializer + org.xmlpull.v1 + org.xmlpull.v1.builder + org.xmlpull.v1.builder.adapter + org.xmlpull.v1.builder.impl + org.xmlpull.v1.dom2_builder + org.xmlpull.v1.parser_pool + org.xmlpull.v1.sax2 + org.xmlpull.v1.util + org.xmlpull.v1.wrapper + org.xmlpull.v1.wrapper.classic + + + ext/eventbus-1.4.jar + release/modules/ext/eventbus-1.4.jar + + + ext/j-ogg-vorbisd.jar + release/modules/ext/j-ogg-vorbisd.jar + + + ext/jinput.jar + release/modules/ext/jinput.jar + + + ext/j-ogg-oggd.jar + release/modules/ext/j-ogg-oggd.jar + + + ext/stack-alloc.jar + release/modules/ext/stack-alloc.jar + + + ext/nifty-default-controls-1.3-SNAPSHOT.jar + release/modules/ext/nifty-default-controls-1.3-SNAPSHOT.jar + + + ext/vecmath.jar + release/modules/ext/vecmath.jar + + + ext/nifty-style-black-1.3-SNAPSHOT.jar + release/modules/ext/nifty-style-black-1.3-SNAPSHOT.jar + + + ext/nifty-1.3-SNAPSHOT.jar + release/modules/ext/nifty-1.3-SNAPSHOT.jar + + + ext/jbullet.jar + release/modules/ext/jbullet.jar + + + ext/lwjgl.jar + release/modules/ext/lwjgl.jar + + + ext/xmlpull-xpp3-1.1.4c.jar + release/modules/ext/xmlpull-xpp3-1.1.4c.jar + + + + diff --git a/sdk/jme3-core-libraries/nbproject/suite.properties b/sdk/jme3-core-libraries/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-core-libraries/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-core-libraries/src/com/jme3/gde/core/libraries/Bundle.properties b/sdk/jme3-core-libraries/src/com/jme3/gde/core/libraries/Bundle.properties new file mode 100644 index 000000000..49c80f5b2 --- /dev/null +++ b/sdk/jme3-core-libraries/src/com/jme3/gde/core/libraries/Bundle.properties @@ -0,0 +1,5 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides the external libraries for jME3. +OpenIDE-Module-Name=jMonkeyPlatform Core Libraries +OpenIDE-Module-Short-Description=Provides the External Libraries for jME3 diff --git a/sdk/jme3-core-libraries/src/com/jme3/gde/core/libraries/layer.xml b/sdk/jme3-core-libraries/src/com/jme3/gde/core/libraries/layer.xml new file mode 100644 index 000000000..3af08d7e2 --- /dev/null +++ b/sdk/jme3-core-libraries/src/com/jme3/gde/core/libraries/layer.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sdk/jme3-core-updatecenters/build.xml b/sdk/jme3-core-updatecenters/build.xml new file mode 100644 index 000000000..67eed59ec --- /dev/null +++ b/sdk/jme3-core-updatecenters/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.core.updatecenters. + + diff --git a/sdk/jme3-core-updatecenters/manifest.mf b/sdk/jme3-core-updatecenters/manifest.mf new file mode 100644 index 000000000..3687d3f4d --- /dev/null +++ b/sdk/jme3-core-updatecenters/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.core.updatecenters +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/core/updatecenters/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/core/updatecenters/Bundle.properties + diff --git a/sdk/jme3-core-updatecenters/nbproject/build-impl.xml b/sdk/jme3-core-updatecenters/nbproject/build-impl.xml new file mode 100644 index 000000000..c7d0976e2 --- /dev/null +++ b/sdk/jme3-core-updatecenters/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core-updatecenters/nbproject/genfiles.properties b/sdk/jme3-core-updatecenters/nbproject/genfiles.properties new file mode 100644 index 000000000..e23da7152 --- /dev/null +++ b/sdk/jme3-core-updatecenters/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=344d2805 +build.xml.script.CRC32=cfa8d5c5 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.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=344d2805 +nbproject/build-impl.xml.script.CRC32=270846fb +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.1 diff --git a/sdk/jme3-core-updatecenters/nbproject/project.properties b/sdk/jme3-core-updatecenters/nbproject/project.properties new file mode 100644 index 000000000..df192b859 --- /dev/null +++ b/sdk/jme3-core-updatecenters/nbproject/project.properties @@ -0,0 +1,3 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +spec.version.base=0.6.0 diff --git a/sdk/jme3-core-updatecenters/nbproject/project.xml b/sdk/jme3-core-updatecenters/nbproject/project.xml new file mode 100644 index 000000000..99edbedeb --- /dev/null +++ b/sdk/jme3-core-updatecenters/nbproject/project.xml @@ -0,0 +1,12 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.core.updatecenters + + + + + + diff --git a/sdk/jme3-core-updatecenters/nbproject/suite.properties b/sdk/jme3-core-updatecenters/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-core-updatecenters/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/Bundle.properties b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/Bundle.properties new file mode 100644 index 000000000..09a2364ce --- /dev/null +++ b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/Bundle.properties @@ -0,0 +1,29 @@ +#jMP update centers +com_jme3_platform_update_center_nightly=http://jmonkeyengine.com/platform/base/alpha/updates.xml.gz +com_jme3_platform_update_center_stable=http://jmonkeyengine.com/platform/base/stable/updates.xml.gz +com_jme3_gde_core_update_center_nightly=http://jmonkeyengine.com/platform/updatecenter/alpha/updates.xml +com_jme3_gde_core_update_center_stable=http://jmonkeyengine.com/platform/updatecenter/stable/updates.xml +com_jme3_jmp_contributions_update_center=http://jmonkeyengine.com/platform/updatecenter/jmp-contributions/updates.xml +#jMP update centers +Services/AutoupdateType/com_jme3_platform_update_center_nightly.instance=Base Platform Alpha +Services/AutoupdateType/com_jme3_platform_update_center_stable.instance=Base Platform Stable +Services/AutoupdateType/com_jme3_gde_core_update_center_nightly.instance=jMonkeyEngine SDK Nightly +Services/AutoupdateType/com_jme3_gde_core_update_center_stable.instance=jMonkeyEngine SDK Stable +Services/AutoupdateType/com_jme3_jmp_contributions_update_center.instance=jMonkeyEngine SDK User Contributions + +#NB 6.9 update centers +com_jme3_gde_core_netbeans_update_center=http://updates.netbeans.org/netbeans/updates/6.9/uc/final/stable/catalog.xml.gz +com_jme3_gde_core_netbeans_beta_update_center=http://updates.netbeans.org/netbeans/updates/6.9/uc/final/stable/catalog.xml.gz +com_jme3_gde_core_thirdparty_update_center=http://updates.netbeans.org/netbeans/updates/6.9/uc/final/thirdparty/catalog.xml.gz +com_jme3_gde_core_plugin_portal_update_center=http://plugins.netbeans.org/nbpluginportal/updates/6.9/catalog.xml.gz +#NB 6.9 update centers +Services/AutoupdateType/com_jme3_gde_core_netbeans_update_center.instance=NetBeans Platform +Services/AutoupdateType/com_jme3_gde_core_netbeans_beta_update_center.instance=NetBeans Platform beta +Services/AutoupdateType/com_jme3_gde_core_thirdparty_update_center.instance=NB 3rd Party Plugins +Services/AutoupdateType/com_jme3_gde_core_plugin_portal_update_center.instance=NB Plugin Portal + +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + jMonkeyPlatform Core Update Center list +OpenIDE-Module-Name=jMonkeyPlatform Core Update Centers +OpenIDE-Module-Short-Description=jMonkeyPlatform Core Update Centers diff --git a/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/layer.xml b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/layer.xml new file mode 100644 index 000000000..d0d165159 --- /dev/null +++ b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/layer.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sdk/jme3-core/build.xml b/sdk/jme3-core/build.xml new file mode 100644 index 000000000..eb10553b6 --- /dev/null +++ b/sdk/jme3-core/build.xml @@ -0,0 +1,56 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.core. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-about.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-about.html new file mode 100644 index 000000000..9842948e7 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-about.html @@ -0,0 +1,88 @@ + + + + About jMonkeyPlatform + + + + +

About jMonkeyPlatform

+

+ The jMonkeyPlatform is a game development environment for jMonkeyEngine 3. +

+

+ jMonkeyPlatform is based on the NetBeans Platform so you automatically have access to all of the + developer tools of the NetBeans IDE to create, compile and deploy Java applications. + On top of that, the jMonkeyPlatform provides you with specialized plugins for creating jMonkeyEngine 3 game content. +

+

Documentation

+

+ This help contains info about most of jMonkeyPlatforms functions, take a look at the + "Introduction" section of the help to get started with creating projects. The sections + on model and material handling will give you information on how you can manage and edit + your game assets. Finally theres information about how jMonkeyPlatform helps you + edit your code and deploy your application to multiple platforms. +

+

Getting started

+

+ If you are completely new to jMonkeyEngine we suggest you go through the jMonkeyEngine3 tutorials + first, they will give you an idea on how jMonkeyEngine works and contain lots of little + good-to-knows that will help you getting your Application up and running in no time. +

+

+ To see some code examples of jMonkeyEngine3 functions, press the "New Project" button and + create a new "JME3Tests" project. To start coding, create a new "BasicGame" project. +

+

+ Have fun coding!
+ + + + + + +

+ + + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-development.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-development.html new file mode 100644 index 000000000..7f4762f13 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-development.html @@ -0,0 +1,57 @@ + + + + + + + + +

Devloping plugins for jMonkeyPlatform

+

+ In general, developing plugins for jMonkeyPlatform is not much different than creating plugins for the NetBeans Platform which in turn is not much different than creating Swing applications. +

+

+ So if you feel like you want to make an addition to jMonkeyPlatform dont hesitate to contact the jme team regardless of your knowledge in NetBeans platform development. For new plugins, the basic project creation and layout of the plugin can always be handled by a core developer and you can go on from there creating a jme / swing application like you are used to. +
Note however that by using the Platform functions, your plugin feels more like a Platform application (global save button, file type support etc.). +

+

+ Learn more about NetBeans Plugin Development at + + + + + + . +

+ + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-hs.xml b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-hs.xml new file mode 100644 index 000000000..da9eda39a --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-hs.xml @@ -0,0 +1,53 @@ + + + + + jMonkeyEngine SDK Core Help + + com.jme3.gde.core.about + + + + + TOC + + javax.help.TOCView + core-toc.xml + + + Search + + javax.help.SearchView + JavaHelpSearch + + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-map.xml b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-map.xml new file mode 100644 index 000000000..0b5861ebe --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-map.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-sceneviewer.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-sceneviewer.html new file mode 100644 index 000000000..a792e2ba6 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-sceneviewer.html @@ -0,0 +1,54 @@ + + + + + + + + +

The SceneViewer

+
+ +

+ The SceneViewer and SceneExplorer windows are shared among plugins to save system resources. This means that you will have to keep an eye on what plugin is using the scene right now and what you are actually modifying in these windows. +

+ +

+ Most plugins will deliver their own UI elements to modify the scene so the SceneExplorer is more of a global tool. The simple SceneComposer however heavily relies on its functions as other plugins might too in the future. + +

+ +
+ + + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-toc.xml b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-toc.xml new file mode 100644 index 000000000..cabeed099 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-toc.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-updating.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-updating.html new file mode 100644 index 000000000..5d3477237 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/core-updating.html @@ -0,0 +1,53 @@ + + + + + + + + +

Automatically Updating jMonkeyEngine SDK

+ The jMonkeyPlatform software includes an automatic web update feature. + To have your complete SDK being updated to the most current nightly version of jME3 and jMP do the following: +
    +
  • Go to Tools→Plugins
  • +
  • Select the “Settings” tab
  • +
  • Select the checkbox for “jMonkeyPlatform nightly svn”
  • +
  • Select the “Updates” tab
  • +
  • Press “Reload Catalog”
  • +
  • Press “Update”
  • +
+ There you go, the jMP will check for updates in the intervals set on the “Settings” tab. + Be warned however, the changes in the nightly versions might break your current game project if heavy changes have been committed. + + diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme2/terrain-from-float-array.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme2/terrain-from-float-array.png new file mode 100644 index 000000000..c19cbeee8 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme2/terrain-from-float-array.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme2/terrain-from-heightmap.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme2/terrain-from-heightmap.png new file mode 100644 index 000000000..eaa8f6049 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme2/terrain-from-heightmap.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/3d_models.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/3d_models.html new file mode 100644 index 000000000..5e1b4ec6c --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/3d_models.html @@ -0,0 +1,83 @@ + +

Models and Scenes

+
+ +

+ +Like Shapes, 3D models are also made up of Meshes, but models are more complex than Shapes. While Shapes are built into jME3, you typically create models in external 3D Mesh Editors. +

+ +
+ +

Using Models and Scenes with jME3

+
+ +

+ +To use 3D models in a jME3 application: +

+
    +
  1. Export the 3D model in Ogre XML or Wavefront OBJ format. Export Scenes as Ogre DotScene format.
    +
  2. +
  3. Save the files into a subdirectory of your jME3 project's assets directory.
    +
  4. +
  5. In your code, you use the Asset Manager to load models as Spatials into a jME application.
    Spatial model = assetManager.loadModel(
    +    "Models/MonkeyHead/MonkeyHead.mesh.xml" );
    +
  6. +
  7. (For the release build:) Use the jMonkeyPlatform to convert models to .j3o format. You don't need this step as long you still develop and test the aplication within the jMonkeyPlatform.
    +
  8. +
+ +
+ +

Creating Models and Scenes

+
+ +

+ +To create 3D models and scenes, you need a 3D Mesh Editor such as , with an OgreXML Exporter plugin. +

+ +

+Tip: Consider creating for more complex models, it looks more professional. +

+ +

+3D mesh editors are third-party products, so please consult their documentation for instructions how to use them. Here is an example workflow for Blender users: +

+ +

+To export your models as Ogre XML meshes with materials: +

+
    +
  1. Open the menu File > Export > OgreXML Exporter to open the exporter dialog.
    +
  2. +
  3. In the Export Materials field: Give the material the same name as the model. For example, the model something.mesh.xml goes with something.material, plus (optionally) something.skeleton.xml, and some JPG files.
    +
  4. +
  5. In the Export Meshes field: Select a target subdirectory of your assets/Models/ directory. E.g. assets/Models/something/.
    +
  6. +
  7. Activate the following exporter settings:
    +
      +
    • Copy Textures: YES
      +
    • +
    • Rendering Materials: YES
      +
    • +
    • Flip Axis: YES
      +
    • +
    • Require Materials: YES
      +
    • +
    • Skeleton name follows mesh: YES
      +
    • +
    +
  8. +
  9. Click export.
    +
  10. +
+ +

+ +You can now use the jMonkeyPlatform to load and view models. You can create scenes from them and write cde that loads them into your application. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/animation.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/animation.html new file mode 100644 index 000000000..2c2417c9f --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/animation.html @@ -0,0 +1,353 @@ + +

Animation in jME3

+
+ +

+ +In 3D games, you do not only load static 3D models, you also want to be able to trigger animations in the model from the Java code. Animated models must be created in an external mesh editor (for example, Blender). +

+ +

+What is required for the model? +

+
    +
  1. For each model, you have to define a skeleton (bones rigging).
    +
  2. +
  3. For each motion, you have to specify how it distorts the model (skinning).
    +
  4. +
  5. For each animation, you have to specify a series of snapshots of how the bones are positioned (keyframes).
    +
  6. +
  7. One model can contain several animations. You give every animation a name when you save it in the mesh editor.
    +
  8. +
+ +

+ +More information: Animation +

+ +

+What is required in your java class? +

+
    +
  • One animation controller per animated Model
    +
  • +
  • As many channels per controller as you need to play several animations in parallel. In simple cases one channel is enough, sometimes you need two or more per model.
    +
  • +
+ +
+ +

Controlling Animations

+
+ +
+ +

The Controller

+
+ +

+ +Create one com.jme3.animation.AnimControl object in your JME3 application for each animated model that you want to control. You have to register each animated model to one of these Animation Controllers. The control object gives you access to the available animation sequences in the model. +

+
  AnimControl playerControl; // you need one controller per model
+  Node player = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml"); // load a model
+  playerControl = player.getControl(AnimControl.class); // get control over this model
+  playerControl.addListener(this); // add listener
+
+ +

Channels

+
+ +

+ +A controller has several animation channels (com.jme3.animation.AnimChannel). Each channel can play one animation sequence at a time. +

+ +

+There often are situations where you want to run several animation sequences at the same time, e.g. “shooting while walking” or “boxing while jumping”. In this case, you create several channels, assign an animation to each, and play them in parallel. + + +

+
  AnimChannel channel_walk = playerControl.createChannel();
+  AnimChannel channel_jump = playerControl.createChannel();
+  ...
+

+To reset a controller, call control.clearChannels(); +

+ +
+ +

Animation Control Properties

+
+ +

+ +The following information is available for an AnimControl. + +

+ + + + + + + + + + + + + + + + + + + +
AnimControl PropertyUsage
createChannel()Returns a new channel, controlling all bones by default.
getNumChannels()The number of channels registered to this Control.
getChannel(0)Gets individual channels by index number. At most getNumChannels().
clearChannels()Clear all channels in this control.
addListener(animEventListener)
+ removeListener(animEventListener)
+ clearListeners()
Adds or removes listeners to receive animation related events.
+ + + + + + + + + + + + + + + + + + + +
AnimControl PropertyUsage
setAnimations(aniHashMap)Sets the animations that this AnimControl is capable of playing. The animations must be compatible with the skeleton given in the constructor.
addAnim(boneAnim)
+ removeAnim(boneAnim)
Adds or removes an animation from this Control.
getAnimationNames()A String Collection of names of all animations that this Control can play for this model.
getAnim(“anim”)Retrieve an animation from the list of animations.
getAnimationLength(“anim”)Returns the length of the given named animation in seconds
+ + + + + + + + + + + + + +
AnimControl PropertyUsage
getSkeleton()The Skeleton object controlled by this Control.
getTargets()The Skin objects controlled by this Control, as Mesh array.
getAttachmentsNode(“bone”)Returns the attachment node of a bone. Attach models and effects to this node to make them follow this bone's motions.
+ +
+ +

Animation Channel Properties

+
+ +

+ +The following properties are set per AnimChannel. + +

+ + + + + + + + + + + + + + + + + + + +
AnimChannel PropertyUsage
setLoopMode(LoopMode.Loop); From now on, the animation on this channel will repeat from the beginning when it ends.
setLoopMode(LoopMode.DontLoop); From now on, the animation on this channel will play once, and the freeze at the last keyframe.
setLoopMode(LoopMode.Cycle); From now on, the animation on this channel will play forward, then backward, then again forward, and so on.
setSpeed(1f); From now on, play this animation slower (<1f) or faster (>1f), or with default speed (1f).
setTime(1.3f); Fast-forward or rewind to a certain moment in time of this animation.
+ +

+ +The following information is available for a channel. + +

+ + + + + + + + + + + + + + + + + + + +
AnimChannel PropertyUsage
getAnimationName()The name of the animation playing on this channel. Returns null when no animation is playing.
getLoopMode()The current loop mode on this channel. The returned com.jme3.animation enum can be LoopMode.Loop, LoopMode.DontLoop, or LoopMode.Cycle.
getAnimMaxTime()The total length of the animation on this channel. Or 0f if nothing is playing.
getTime()How long the animation on this channel has been playing. It returns 0f if the channel has not started playing yet, or a value up to getAnimMaxTime().
getControl()The AnimControl that belongs to this AnimChannel.
+ +

+ +Use the following methods to add or remove individual bones to an AnimChannel. This is useful when you play two animations in parallel on two channels, and each controls a subset of the bones (e.g. one the arms, and the other the legs). + +

+ + + + + + + + + + + + + + + + +
AnimChannel MethodsUsage
addAllBones()Add all the bones of the model's skeleton to be influenced by this animation channel. (default)
addBone(“bone1”)
+ addBone(bone1)
Add a single bone to be influenced by this animation channel.
addToRootBone(“bone1”)
+ addToRootBone(bone1)
Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given bone, to the root bone.
addFromRootBone(“bone1”)
+ addFromRootBone(bone1)
Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given root bone, going towards the children bones.
+ +
+ +

Playing Animations

+
+ +

+ +Animations are played by channel. Note: Whether the animation channel plays continuously or only once, depends on the Loop properties you have set. + +

+ + + + + + + +
Channel MethodUsage
channel_walk.setAnim(“Walk”,0.50f); Start the animation named “Walk” on channel channel_walk.
+ The float value specifies the time how long the animation should overlap with the previous one on this channel. If set to 0f, then no blending will occur and the new animation will be applied instantly.
+ +

+ +Tip: Use the AnimEventLister below to react at the end or start of an animation cycle. +

+ +
+ +

Usage Example

+
+ +

+ +In this short example, we define the space key to trigger playing the “Walk” animation on channel2. +

+
  public void simpleInitApp() {
+    ...
+    inputManager.addMapping("Walk", new KeyTrigger(KeyInput.KEY_SPACE));
+    inputManager.addListener(actionListener, "Walk");
+    ...
+  }
+ 
+  private ActionListener() {
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Walk") && !keyPressed) {
+        if (!channel2.getAnimationName().equals("Walk")) {
+          channel2.setLoopMode(LoopMode.Loop);
+          channel2.setAnim("Walk", 0.50f);
+        }
+      }
+    }
+  };
+
+ +

Animation Event Listener

+
+ +

+ +A jME3 application that contains animations can implement the com.jme3.animation.AnimEventListener interface. +

+
public class HelloAnimation extends SimpleApplication
+                     implements AnimEventListener { ... }
+

+This optional Listener enables you to respond to animation start and end events, onAnimChange() and onAnimCycleDone(). +

+ +
+ +

Responding to Animation End

+
+ +

+ +The onAnimCycleDone() event is invoked when an animation cycle has ended. For non-looping animations, this event is invoked when the animation is finished playing. For looping animations, this even is invoked each time the animation loop is restarted. +

+ +

+You have access to the following objects: +

+
    +
  • The controller to which the listener is assigned.
    +
  • +
  • The animation channel being played.
    +
  • +
  • The name of the animation that has just finished playing.
    +
  • +
+
  public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
+    // test for a condition you are interested in, e.g. ...
+    if (animName.equals("Walk")) {
+      // respond to the event here, e.g. ...
+      channel.setAnim("Stand", 0.50f);
+    }
+  }
+
+ +

Responding to Animation Start

+
+ +

+ +The onAnimChange() event is invoked every time before an animation is set by the user to be played on a given channel (channel.setAnim()). +

+ +

+You have access to the following objects +

+
    +
  • The controller to which the listener is assigned.
    +
  • +
  • The animation channel being played.
    +
  • +
  • The name of the animation that will start playing.
    +
  • +
+
  public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
+    // test for a condition you are interested in, e.g. ...
+    if (animName.equals("Walk")) {
+      // respond to the event here, e.g. ...
+      channel.setAnim("Reset", 0.50f);
+    }
+  }
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/application_states.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/application_states.html new file mode 100644 index 000000000..3efc69507 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/application_states.html @@ -0,0 +1,189 @@ + +

Application States

+
+ +

+ +com.jme3.app.state.AppState is a customizable jME3 interface that allows you to control the global game logic (game mechanics). To control the behaviour of a type of Spatial, see Custom Controls instead – both can be used together. +

+ +

+To implement game logic: +

+
    +
  1. You define a custom AppState and implement its behaviour in the AppState's update() method.
    +
      +
    • You can pass arguments and manipulate everything inside the app's scope.
      +
    • +
    +
  2. +
  3. Attach the AppState to your application's AppStateManager (stateManager.attach(myState);) to activate it.
    +
  4. +
  5. Create one AppState for each type of game behavior. When you add several AppStates to one Application, they will be executed in the order they were added.
    +
  6. +
+ +
+ +

Usage Examples

+
+ +

+ +JME3 comes with a BulletAppState that implements Physical behaviour (using the jBullet library). You, for example, could write an Artificial Intelligence AppState to control all your enemy units. Existing examples in the code base include: + +

+
    +
  • controls physical behaviour in PhysicsControl'ed Spatials.
    +
  • +
  • an exmaple of a custom AppState
    +
      +
    • +
    • +
    +
  • +
+ +
+ +

AppState

+
+ +

+ +The AppState interface allows you to hook a continously executing piece of code into the main loop. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AppState MethodUsage
isActive()Test whether AppState is enabled or disabled.
stateAttached(asm)
+ stateDetached(asm)
The AppState knows when it is attached to, or detached from, the AppStateManager. Then it triggers these methods that you implement.
isInitialized()Your implementations of this interface should return the correct respective boolean value.
initialize(asm,app)The RenderThread initialized the AppState and then calls this method.
setActive(true)
+ setActive(false)
Temporarily enables or disables an AppState.
update(float tpf)Here you implement the behaviour that you want to hook into the main update loop.
cleanup()Called when when the AppState is de-initialized.
render(RenderManager rm)Renders the state.
postRender()Called after all rendering commands are flushed.
+ +
+ +

AbstractAppState

+
+ +

+ +The AbstractAppState class already implements some common methods and makes creation of custom AppStates a bit easier: isInitialized(), setActive(), isActive(), cleanUp(). Just extend it and override the remaining AppState methods. +

+ +

+ +Definition: +

+
public class MyAppState extends AbstractAppState {
+    private Node x = new Node("x"); // some class field
+ 
+    public Node getX(){
+        return x;
+    }
+ 
+    @Override
+    public void update(float tpf) {
+        x.doSomething();             // implement behaviour
+    }
+}
+

+Usage: +

+
public class TestAppStates extends Application {
+  public static void main(String[] args){
+    TestAppStates app = new TestAppStates();
+    app.start();
+  }
+ 
+  @Override
+  public void start(JmeContext.Type contextType){
+    super.start(contextType);
+  }
+ 
+  @Override
+  public void initialize(){
+    super.initialize();MyAppState state = new MyAppState();
+    stateManager.attach(state);
+    System.out.println("Use the state's methods... " + state.getX());
+  }
+ 
+  @Override
+  public void update(){
+    super.update();
+    stateManager.update(tpf);
+    stateManager.render(renderManager);
+    renderManager.render(tpf);
+  }
+ 
+  @Override
+  public void destroy(){
+    super.destroy();
+  }
+
+ +

AppStateManager

+
+ +

+ +The com.jme3.app.state.AppStateManager holds the list of AppStates for an application. AppStateManager ensures that active AppStates are updated and rendered. When an AppState is attached, AppStateManager calls its stateAttached() method. When an AppState is detached, AppStateManager calls its stateDetached() method. +

+ +

+There is one AppStateManager per application. You can attach several AppStates to one AppStateManager, but the same state can only be attached once. + +

+ + + + + + + + + + +
AppStateManager MethodUsage
hasState(s)Is AppState s attached?
getState(Class<T> stateClass)Returns the first state that is an instance of a subclass of the specified class.
+ +

+ +The AppStateManager's update(), render(), postRender(), and cleanUp() methods are internal, users never call them directly. +

+ +
+ +

Best Practices

+
+
app.getState(MyState.class).doStuff()
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html new file mode 100644 index 000000000..bab9f0021 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html @@ -0,0 +1,145 @@ + +

AssetManager

+
+ +

+ +JME3 has an integrated an asset manager that helps you keep your project assets organized. By assets we mean media files, such as 3D models, materials, textures, scenes, shaders, sounds, and fonts. +

+ +

+The assetManager object is an com.jme3.asset.AssetManager instance that every com.jme3.app.Application can access. It maintains a root that also includes your project's classpath by default, so you can load any asset that's on the classpath, that is, the top level of your project directory. +

+ +

+You can use the inherited assetManager object directly, or use the accessor getAssetManager(). +

+ +

+Here is an example how you load assets using the AssetManager. This lines loads a default Material from the Common directory: +

+
Material mat = (Material) assetManager.loadAsset(
+    new AssetKey("Common/Materials/RedColor.j3m"));
+

+The Material is “somewhere” in the jME3 JAR, but the default Asset Manager is configured to handle a Common/… path correctly, so you don't have to specify the whole path. +

+ +

+Additionally, You can configure the Asset Manager and add any path to its root. This means, you can load assets from any project directory you specify. +

+ +

+In project created with jMonkeyPlatform, jME3 searches for models in the assets directory of your project by default. This is our recommended directory structure for storing assets: +

+
+MyGame/assets/Interface/
+MyGame/assets/MatDefs/
+MyGame/assets/Materials/
+MyGame/assets/Models/
+MyGame/assets/Scenes/
+MyGame/assets/Shaders/
+MyGame/assets/Sounds/
+MyGame/assets/Textures/
+MyGame/build.xml
+MyGame/src/...
+
+ +

+These are just the most common examples, you can name the directories inside the assets directory how you like. +

+ +
+ +

Loading Assets

+
+
      Material mat_brick = new Material( 
+          assetManager, "Common/MatDefs/Misc/SimpleTextured.j3md");
+
      mat_brick.setTexture("m_ColorMap", 
+          assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));
+
      guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
+
      Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
+
    assetManager.registerLocator("town.zip", ZipLocator.class.getName());
+    Spatial scene = assetManager.loadModel("main.scene");
+    rootNode.attachChild(scene);
+

+Here is a HttpZipLocator that can download zipped models: +

+
    assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/wildhouse.zip", 
+                                 HttpZipLocator.class.getName());
+    Spatial scene = assetManager.loadModel("main.scene");
+    rootNode.attachChild(scene);
+

+JME3 offers ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, and UrlLocator (see com.jme3.asset.plugins). +

+ + + + + + + + + + + + + +
Task? Solution!
Load a model with materials Use the asset managers loadModel() method and attach the Spatial to the rootNode.
Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml");
+rootNode.attachChild(elephant);
Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.j3o");
+rootNode.attachChild(elephant);
Load a model without materials If you have a model without materials, you have to add a default material to make it visible.
Spatial teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
+Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
+teapot.setMaterial(mat);
+rootNode.attachChild(teapot);
Load a scene You load scenes just like you load models:
Spatial scene = assetManager.loadModel("Scenes/house/main.scene");
+rootNode.attachChild(scene);
+ +
+ +

NullPointerException: Cannot locate resource?

+
+ +

+ +An error mesage similar to the following can occur in the console when you run executables, even if the game runs fine when started from the jMoneykPlatform. +

+
com.jme3.asset.DesktopAssetManager loadAsset
+WARNING: Cannot locate resource: Scenes/town/main.scene
+com.jme3.app.Application handleError
+SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
+java.lang.NullPointerException
+
+ +

+Reason: If you use the default build script created by the jMonkeyPlatform then the original OgreXML files are not included in the executable. +

+ +

+For a stand-alone build, you work with .j3o files only. The default build script makes sure to include .j3o files in the executable. +

+ +

+You must use the jMonkeyPlatform's context menu action to convert OgreXML models to .j3o format to get rid of this error. + +

+
    +
  1. Open the JME3 Project in the jMonkeyplatform.
    +
  2. +
  3. Browse the Assets directory in the Projects window.
    +
  4. +
  5. Right-click a .mesh.xml file, and choose “convert to JME3 binary”.
    +
  6. +
  7. The converted file appears in the same directory as the .mesh.xml file. It has the same name and a .j3o suffix.
    +
  8. +
+ +
+ +

Asset Handling: Codeless Projects

+
+ +

+ +If you are using another IDE than jMonkeyPlatform, you can create a codeless project in the jMonkeyPlatform to maintain assets. This method will not meddle with your sources or custom build scripts, but you can still browse your assets, and preview, arrange, and convert models. You can, for example, give the designers in your team access to such a codeless project. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/audio.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/audio.html new file mode 100644 index 000000000..74804dd20 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/audio.html @@ -0,0 +1,148 @@ + +

Audio in jME3

+
+ +

+ +There are two ways to handle audio data: Short audio files are to be stored entirely in memory, while long audio files (music) is streamed from the hard drive as it is played. +

+ +

+Place audio files in the assets/Sound/ directory of your project. jME3 supports Ogg Vorbis (.ogg) and Wave (.wav) formats. +

+ +
+ +

Creating Audio Nodes

+
+ +

+ +The main class to look at is com.jme3.audio.AudioNode. +

+ +

+By default, a new audio node loads the whole file into memory: + +

+
AudioNode boom = new AudioNode(assetManager, "Sound/boom.wav");
+

+If it is a long file, you set the boolean to true to stream the audio. + +

+
AudioNode music = new AudioNode(assetManager, "Sound/music.wav", true);
+
+ +

Setting AudioNode Properties

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AudioNode methodUsage
getStatus()Returns either Status.Playing, Status.Stopped, or Status.Paused.
setVolume(5)Set the volume between 0 (mute) and 10 (loud).
setPitch(1)Make the sound play higher or lower.
setLooping(false)Play it once and stop.
setLooping(true)Play it over and over again from the beginning, until stopSource() or pauseSource() is called. E.g. for background noises.
setPositional(true)
+ setLocalTranslation()
Activates 3D audio, the sound appears to come from a certain position. Good for Players or NPCs.
setReverbEnabled(true)A 3D echo effect that only makes sense to use with moving positional AudioNodes.
setDirectional(true)
+ setDirection()
Activates 3D audio, sound can only be heard from a certain direction. Good for noises that should not be heard through a wall.
setInnerAngle()
+ setOuterAngle()
?
setPositional(false)
+ setDirectional(false)
The sound comes from a everywhere. Good for environmental background sounds and music.
setLocalTranslation()Position the AudioNode in the 3D scene if you have set setPositional() to true.
setTimeOffset(0.5f)Start playing after a pause?
setMaxDistance(100f)Maximum distance the sound can be heard, in world units.
+ +
+ +

Playing Audio Nodes

+
+ +

+ +For playing you use the com.jme3.audio.AudioRenderer. A default audioRenderer object is provided by the com.jme3.app.Application class. +

+
audioRenderer.playSource( myAudioNode );
+

+Note: Whether the AudioNode plays continuously or only once, depends on the Loop properties you have set. +

+ +

+You pause and stop music with the following methods: +

+
audioRenderer.pauseSource( myAudioNode );
audioRenderer.stopSource( myAudioNode );
+
+ +

Setting Environment Properties

+
+ +

+ +You can choose from the following environmental presets from com.jme3.audio.Environment. + +

+ + + + + + + + + + + + + + + + + + + +
EnvironmentdensitydiffusiongaingainHfdecayTimedecayHfreflGainreflDelaylateGainlateDelay
Garage 1.00f1.0f1.0f1.00f0.90f0.5f0.751f0.0039f0.661f0.0137f
Dungeon 0.75f1.0f1.0f0.75f1.60f1.0f0.950f0.0026f0.930f0.0103f
Cavern 0.50f1.0f1.0f0.50f2.25f1.0f0.908f0.0103f0.930f0.0410f
AcousticLab 0.50f1.0f1.0f1.00f0.28f1.0f0.870f0.0020f0.810f0.0080f
Closet 1.00f1.0f1.0f1.00f0.15f1.0f0.600f0.0025f0.500f0.0006f
+ +

+ +Activate the preset with: +

+
audioRenderer.setEnvironment(new Environment.Dungeon));
+

+Alternatively you can create a com.​jme3.​audio.Environment object to specify custom environment factors. Activate your custom environment settings in the Environment constructor: +

+
audioRenderer.setEnvironment(
+        new Environment( density, diffusion, gain, gainHf, decayTime, decayHf, 
+                reflGain, reflDelay, lateGain, lateDelay ) );
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/blomsky.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/blomsky.png new file mode 100644 index 000000000..cb5ba7a9f Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/blomsky.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html new file mode 100644 index 000000000..49d0822fa --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html @@ -0,0 +1,295 @@ + +

Bloom and Glow

+
+ +

+ +Bloom is a popular shader effect in 3D games industry. It usually consist in displaying a glowing halo around light sources or bright areas of a scene. +In practice, the bright areas are extracted from the rendered scene, blurred and finally added up to the render. +

+ +

+Those images gives an idea of what bloom does. The left image has no bloom effect, the right image does.
+ + +

+ +
+ +

Bloom Usage

+
+
    +
  1. Create a FilterPostProcessor
    +
  2. +
  3. Create a BloomFilter
    +
  4. +
  5. Add the filter to the processor
    +
  6. +
  7. Add the processor to the viewPort
    +
  8. +
+
 FilterPostProcessor fpp=new FilterPostProcessor(assetManager);
+ BloomFilter bloom=new BloomFilter();
+ fpp.addFilter(bloom);
+ viewPort.addProcessor(fpp);
+

+Here are the parameters that you can tweak : +

+ + + + + + + + + + + + + + + + +
Parameter Method Default Description
blur scale setBlurScale(float) 1.5f the scale of the bloom effect, but be careful, high values does artifacts
exposure Power setExposurePower(float) 5.0f the glowing channel color is raised to the value power
exposure cut-off setExposureCutOff(float) 0.0f the threshold of color to bloom during extraction
bloom intensity setBloomIntensity(float) 2.0f the resulting bloom value is multiplied by this intensity
+ +

+ +You'll probably need to adjust those parameters depending on your scene. +

+ +
+ +

Bloom with a glow map

+
+ +

+ +Sometimes, you want to have more control over what glows and does not glow. +The bloom filter supports a glow map or a glow color. +

+ +
+ +
Creating a glow-map
+
+ +

+ +Let's take the hover tank example bundled with JME3 test data.
+ +Here you can see the diffuse map of the tank, and the associated glow map that only contains the parts of the texture that will glow and their glowing color:
+ + + +

+ +

+Glow maps works with Lighting.j3md, Particles.j3md and SolidColor.j3md material definitions. +The tank material looks like that : + +

+
+Material My Material : Common/MatDefs/Light/Lighting.j3md {
+     MaterialParameters {
+        SpecularMap : Models/HoverTank/tank_specular.png
+        Shininess : 8
+        NormalMap : Models/HoverTank/tank_normals.png
+        DiffuseMap : Models/HoverTank/tank_diffuse.png
+        GlowMap : Models/HoverTank/tank_glow_map_highres.png
+        UseMaterialColors : true
+        Ambient  : 0.0 0.0 0.0 1.0
+        Diffuse  : 1.0 1.0 1.0 1.0
+        Specular : 1.0 1.0 1.0 1.0
+     }
+}
+
+ +

+ +The glow map is defined here : GlowMap : Models/HoverTank/tank_glow_map_highres.png +

+ +
+ +
Usage
+
+
    +
  1. Create a FilterPostProcessor
    +
  2. +
  3. Create a BloomFilter with the GlowMode.Objects parameter
    +
  4. +
  5. Add the filter to the processor
    +
  6. +
  7. Add the processor to the viewPort
    +
  8. +
+
+  FilterPostProcessor fpp=new FilterPostProcessor(assetManager);
+  BloomFilter bf=new BloomFilter(BloomFilter.GlowMode.Objects);
+  fpp.addFilter(bf);
+  viewPort.addProcessor(fpp);
+
+ +

+Here is the result :
+ + +

+ +
+ +

Bloom with a glow color

+
+ +

+ +Sometimes you need an entire object to glow, not just parts of it. +In this case you'll need to use the glow color parameter. +

+ +
+ +
Usage
+
+
    +
  1. Create a material for your object and set the GlowColor parameter
    +
  2. +
  3. Create a FilterPostProcessor
    +
  4. +
  5. Create a BloomFilter with the GlowMode.Objects parameter
    +
  6. +
  7. Add the filter to the processor
    +
  8. +
  9. Add the processor to the viewPort
    +
  10. +
+
+    Material mat = new Material(getAssetManager(), "Common/MatDefs/Misc/SolidColor.j3md");
+    mat.setColor("Color", ColorRGBA.Green);
+    mat.setColor("GlowColor", ColorRGBA.Green);
+    fpp=new FilterPostProcessor(assetManager);
+    bloom= new BloomFilter(BloomFilter.GlowMode.Objects);        
+    fpp.addFilter(bloom);
+    viewPort.addProcessor(fpp);
+
+ +

+Here is the result on Oto's plasma ball (before and after) :
+ + + +

+ +
+ +

Hints and tricks

+
+ +
+ +
Increasing the blur range and reducing fps cost
+
+ +

+ +The glow render is sampled on a texture that has the same dimensions as the viewport. +You can reduce the size of the bloom sampling just by using the setDownSamplingFactor method like this :
+ + +

+
 BloomFilter bloom=new BloomFilter();
+ bloom.setDownSamplingFactor(2.0f);
+

+ +In this example the sampling size is divided by 4 (width/2,height/2), resulting in less work to blur the scene. +The resulting texture is then up sampled to the screen size using hardware bilinear filtering. this results in a wider blur range. +

+ +
+ +
Using classic bloom combined with a glow map
+
+ +

+let's say you want a global bloom on your scene, but you have also a glowing object on it. +You can use only one bloom filter for both effects like that +

+
BloomFilter bloom=new BloomFilter(BloomFilter.GlowMode.SceneAndObjects);
+

+However, note that both effects will share the same values of attribute, and sometimes, it won't be what you need. +

+ +
+ +
Making your home brewed material definition support Glow
+
+ +

+ +Let's say you have made a custom material on your own, and that you want it to support glow maps and glow color. +In your material definition you need to add those lines in the MaterialParameters section : +

+
+ MaterialParameters {
+        
+        ....
+
+        // Texture of the glowing parts of the material
+        Texture2D GlowMap
+        // The glow color of the object
+        Color GlowColor
+    }
+
+ +

+Then add the following technique : + +

+
+    Technique Glow {
+
+        LightMode SinglePass
+
+        VertexShader GLSL100:   Common/MatDefs/Misc/SimpleTextured.vert
+        FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag
+
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+
+        Defines {
+            HAS_GLOWMAP : GlowMap
+            HAS_GLOWCOLOR : GlowColor
+        }
+    }
+
+ +

+Then you can use this material with the BloomFilter +

+ +
+ +
Make a glowing object stop to glow
+
+ +

+ +If you are using a glow map, remove the texture from the material. + +

+
+material.clearTextureParam("GlowMap");
+
+ +

+If you are using a glow color, set it to black + +

+
+material.setColor("GlowColor",ColorRGBA.Black);
+
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/butterfly-particle-emitter.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/butterfly-particle-emitter.png new file mode 100644 index 000000000..958bc0924 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/butterfly-particle-emitter.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html new file mode 100644 index 000000000..ce7bf2f42 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html @@ -0,0 +1,168 @@ + +

The jME3 Camera

+
+ +
+ +

Default Camera

+
+ +

+ +The default com.jme3.renderer.Camera object is cam in com.jme3.app.Application. +

+ +

+The camera object is created with the following defaults: +

+
    +
  • Width and height are set to the current Application's settings.getWidth() and settings.getHeight() values.
    +
  • +
  • Frustum Perspective:
    +
      +
    • Frame of view angle of 45° along the Y axis
      +
    • +
    • Aspect ratio of width divided by height
      +
    • +
    • Near view plane of 1 wu
      +
    • +
    • Far view plane of 1000 wu
      +
    • +
    +
  • +
  • Start location at (0f, 0f, 10f).
    +
  • +
  • Start direction is looking at the origin.
    +
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodUsage
cam.getLocation(), setLocation()The camera position
cam.getRotation(), setRotation()The camera rotation
cam.getLeft(), setLeft()The left axis of the camera
cam.getUp(), setUp()The up axis of the camera, usually Vector3f(0,1,0)
cam.getDirection(), setDirection()The vector the camera is facing
cam.getAxes(), setAxes(left,up,dir)One accessor for the three properties left/up/direction.
cam.getFrame(), setFrame(loc,left,up,dir)One accessor for the four properties location/left/up/direction.
cam.resize(width, height, fixAspect)Resize an existing camera object while keeping all other settings. Set fixAspect to true to adjust the aspect ratio (?)
cam.setFrustum( near, far, left, right, top, bottom )The frustrum is defined by the near/far plane, left/rught plane, top/bottom plane (all distances as float values)
cam.setFrustumPerspective( fovY, aspect ratio, near, far)The frustrum is defined by view angle along the Y axis (in degrees), aspect ratio, and the near/far plane.
cam.lookAt(target,up)Turn the camera to look at Coordinate target, and rotate it around the up axis.
cam.setParallelProjection(false)Normal perspective
cam.setParallelProjection(true)Parallel projection perspective
cam.getScreenCoordinates()?
+ +

+Tip: After you change view port, frustrum, or frame, call cam.update(); +

+ +
+ +

FlyBy Camera

+
+ +

+ +The flyby camera is an extension of the default camera in com.jme3.app.SimpleApplication. It is preconfigured to respond to the WASD keys for walking forwards and backwards, and for strafing to the sides. Move the mouse to rotate the camera, scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera. + +

+ + + + + + + + + + + + + + + + +
MethodUsage
flyCam.setEnabled(true);Activate the flyby cam
flyCam.setMoveSpeed(10);Control the move speed
flyCam.setRotationSpeed(10);Control the rotation speed
flyCam.setDragToRotate(true)Must keep mouse button pressed to rotate camera. Used e.g. for Applets. if false, all mouse movement will be captured and interpreted as rotations.
+ +
+ +

Chase Camera

+
+ +

+ +jME3 also supports a Chase Cam that can follow a moving target Spatial (com.jme3.input.ChaseCamera). Click and hold the mouse button to rotate around the target. +

+
flyCam.setEnabled(false);
+ChaseCamera chaseCam = new ChaseCamera(cam, target, inputManager);
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodUsage
chaseCam.setSmoothMotion(true);Interpolates a smoother acceleration/deceleration when the camera moves.
chaseCam.setChasingSensitivity(5f)The lower the chasing sensitivity, the slower the camera will follow the target when it moves.
chaseCam.setTrailingSensitivity(0.5f)The lower the traling sensitivity, the slower the camera will begin to go after the target when it moves. Default is 0.5;
chaseCam.setRotationSensitivity(5f)The lower the sensitivity, the slower the camera will rotate around the target when the mosue is dragged. Default is 5.
chaseCam.setTrailingRotationInertia(0.1f)This prevents the camera to stop too abruptly when the target stops rotating before the camera has reached the target's trailing position. Default is 0.1f.
chaseCam.setDefaultDistance(40);The default distance to the target at the start of the application.
chaseCam.setMaxDistance(40);The maximum zoom distance. Default is 40f.
chaseCam.setMinDistance(1);The minimum zoom distance. Default is 1f.
chaseCam.setMinVerticalRotation(-FastMath.PI/2);The minimal vertical rotation angle of the camera around the target. Default is 0.
chaseCam.setDefaultVerticalRotation(-FastMath.PI/2);The default vertical rotation angle of the camera around the target at the start of the application.
chaseCam.setDefaultHorizontalRotation(-FastMath.PI/2);The default horizontal rotation angle of the camera around the target at the start of the application.
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/cinematics.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/cinematics.html new file mode 100644 index 000000000..2bc22dacf --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/cinematics.html @@ -0,0 +1,387 @@ + +

jME3 Cinematics

+
+ +

+ +JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game. You use cinematics to script and record scenes. Use it for example to create of your game. +

+ +

+Cinematics are implemented as AppStates. Attach the scene that you want to be visible in the cinematic to one Node. You create a Cinematic object, and add individual CinematicEvents to it. +

+ +
+ +

Overview

+
+
Cinematic cinematic = new Cinematic(sceneNode, duration);
+cinematic.addCinematicEvent(triggerTime, cinematicEvent);
    +
  1. Create one Cinematic per scene.
    +
      +
    • sceneNode is the node containing the scene
      +
    • +
    • duration is the duration of the cinematic scene in seconds
      +
    • +
    +
  2. +
  3. Create CinematicEvents to script your “movie”. Each Cinematic is a set of CinematicEvents, that are triggered at a given time.
    +
      +
    • cinematicEvent is the cinematic event. More details below.
      +
    • +
    • triggerTime is the time when this particular cinematic event starts. Specify the start time in seconds since the beginning of the scene.
      +
    • +
    +
  4. +
  5. Play and pause the Cinematic using cinematic.pause() and cinematic.play();
    +
  6. +
+ +
+ +

CinematicEvents

+
+ +

+ +There are several kinds of cinematic events: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
CinematicEventDescription
MotionTrackUse this to move a Spatial non-linearly over time. A motionPath is a list of several waypoints added to a MotionPath. The path is interpolated using Catmull-Rom Splines between waypoints.
PositionTrackUse this to move a Spatial linearly over time. It translates the Spatial to a destination in the given amount of time by linearly interpolating the positions.
RotationTrackUse this to change the rotation of a Spatial over time. It rotates the Spatial in the given amount of time by linearly interpolating the rotation.
ScaleTrackUse this to change the size of a Spatial over time. It scales the Spatial in the given amount of time by linearly interpolating the scale.
SoundTrackUse this to play a sound at a given time for the given duration.
GuiTrackDisplays a Nifty GUI at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty GUI XML to the cinematic using cinematic.bindUi(“path/to/nifty/file.xml”);
AnimationTrackUse this to start playing a model animation at a given time (a character walking animation for example)
+ +

+ +We will add more types of track implementions over time. +

+ +

+Each CinematicEvent supports the following methods to control the event. + +

+ + + + + + + + + + + + + +
CinematicEvent methodUsage
play()Starts playing the cinematic.
stop()Stops playing the cinematic.
pause()Pauses the cinematic.
+ +

+ +Those methods, must be called on the Cinematic and are propagated to the events. Don't use them directly on a sub cinematic event +

+ +
+ +

MotionTrack & MotionPath

+
+ +

+ +A motion track is made up of MotionPaths. +

+
MotionPath path = new MotionPath();
+ + + + + + + + + + + + + + + + + + + + + + + + +
MotionPath Method Usage
setCycle(true)Sets whether the motion along this path should be closed (true) or not (false).
addWayPoint(vector)Adds individual waypoints to this path. The order is relevant.
removeWayPoint(vector)
+ removeWayPoint(index)
Removes individual waypoints from this path. You can specify a vector or the integer index.
setCurveTension(0.83f)Sets the tension of the curve (only for Catmull Rom Spline). A value of 0.0f will give a straight linear line, 1.0 a round curve.
enableDebugShape(assetManager,rootNode)Shows a line to visualize the path. Used for debugging.
disableDebugShape()Hides the line that visualizes the path. Used for debugging.
getNbWayPoints()Returns the number of waypoints in this path.
+
MotionTrack thingMotionControl = new MotionTrack(thingNode, path);
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
MotionTrack methodUsage
setLoopMode(LoopMode.Loop)Sets whether the animation along this path should loop (true) or play only once (false).
setDirectionType(MotionTrack.Direction.None)Sets the direction behavior type of the controled node. Direction.None deactivates this feature. See the following options:
setDirectionType(MotionTrack.Direction.LookAt)Rotate to keep facing a point. Specify the point with setLookAt().
setDirectionType(MotionTrack.Direction.Path)Face the direction of the path.
setDirectionType(MotionTrack.Direction.PathAndRotation)Face the direction of the path, plus an added rotation. Use together with the setRotation() method.
setDirectionType(MotionTrack.Direction.Rotation)Rotate while moving. Use together with the setRotation() method.
setLookAt(teapot.getWorldTranslation(), Vector3f.UNIT_Y)Optional: Make the moving face towards a certain location. Use together with setDirectionType().
setRotation(quaternion)Optional: Sets the rotation. Use together with MotionTrack.Direction.Rotation or MotionTrack.Direction.PathAndRotation.
+ +
+ +

MotionPathListener

+
+ +

+ +You can register a MotionPathListener to the MotionPath to track whether waypoints have been reached, and then trigger a custom action. In this example we just print the status. The onWayPointReach() method of the interface gives you access to the MotionTrack object control, and an integer value representing the current wayPointIndex. +

+
path.addListener( new MotionPathListener() {
+  public void onWayPointReach(MotionTrack control, int wayPointIndex) {
+    if (path.getNbWayPoints() == wayPointIndex + 1) {
+      println(control.getSpatial().getName() + "Finished!!! ");
+    } else {
+      println(control.getSpatial().getName() + " Reached way point " + wayPointIndex);
+    }
+  }
+});
+
+ +

PositionTrack

+
+
PositionTrack thingPositionControl = new PositionTrack(
+    thingNode, endPosition,  duration, loopMode);
+

+Details of the constructor: +

+
    +
  • thingNode is the Spatial to be moved.
    +
  • +
  • endPosition is the target location as Vector3f.
    +
  • +
  • duration is the time that it should take from start to end point.
    +
  • +
  • loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.
    +
  • +
+ +

+ +The start location is always the current location of the Spatial. +

+ +
+ +

RotationTrack

+
+
RotationTrack thingRotationControl = new RotationTrack(
+    thingNode, endRotation,  duration, loopMode);
+

+Details of the constructor: +

+
    +
  • thingNode is the Spatial to be rotated.
    +
  • +
  • endRotation is the target rotation in Quaternion format.
    +
  • +
  • duration is the time that it should take from start to target rotation.
    +
  • +
  • loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.
    +
  • +
+ +
+ +

ScaleTrack

+
+
ScaleTrack thingScaleControl = new ScaleTrack(
+    thingNode, endScale,  duration, loopMode);
+

+Details of the constructor: +

+
    +
  • thingNode is the Spatial to be resized.
    +
  • +
  • endScale is the target Scale in Vector3f format.
    +
  • +
  • duration is the time that it should take from start to target scale.
    +
  • +
  • loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.
    +
  • +
+ +
+ +

SoundTrack

+
+
SoundTrack( audioPath, isStream, duration, loopMode )
+

+ +Details of the constructor: +

+
    +
  • audioPath is the path to an audio file as String, e.g. “Sounds/mySound.wav”.
    +
  • +
  • isStream Set this to true to play a longer audio file as stream, or to false to play a short sound without streaming.
    +
  • +
  • duration is the time that it should take to play.
    +
  • +
  • loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.
    +
  • +
+ +
+ +

GuiTrack

+
+
GuiTrack( screen, duration, loopMode )
+

+ +You must use this together with bindUI() to specify the Nifty GUI XML file that you want to load: + +

+
cinematic.bindUi("Interface/subtitle.xml");
+

+Details of the constructor: +

+
    +
  • screen is the name of the Nifty GUI screen to load, as String.
    +
  • +
  • duration is the time that it should take to play.
    +
  • +
  • loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.
    +
  • +
+ +
+ +

AnimationTrack

+
+
AnimationTrack( thingNode, animationName, duration, loopMode )
+

+ +Details of the constructor: +

+
    +
  • thingNode is the Spatial whose animation you want to play.
    +
  • +
  • AnimationName the animation of the animated model that you want to trigger, as a String.
    +
  • +
  • duration is the time that it should take to play.
    +
  • +
  • loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.
    +
  • +
+ +
+ +

Customizations

+
+ +

+ +You can extend individual CinematicEvents. The shows how to extend a GuiTrack to script subtitles. See how the subtitles are used in the . +

+ +

+You can also create new CinematicEvent by extending . An AbstractCinematicEvent implements the CinematicEvent interface and provides duration, time, speed, etc… management. Look at the is to use this for a custom fadeIn/fadeOut effect in combination with a com.jme3.post.filters.FadeFilter. +

+ +
+ +

Camera Handling

+
+ +

+ +The camera management is handled as follows: + +

+
    +
  1. Create a camera Node and bind the camera object to the cinematic. Note that we also give the camera node a name in this step.
    CameraNode camNode = cinematic.bindCamera("topView", cam);
    +
  2. +
  3. Position the camera node in its start location.
    +
  4. +
  5. Use activateCamera() to give the control of the camera to this node. You now see the scene from this camera's point of view. For example to see through the camera node named “top view”, 6 seconds after the start of the cinematic, you'd write
    cinematic.activateCamera(6, "topView");
    +
  6. +
  7. If desired, attach the camNode to a MotionTrack to let it travel along waypoints. This is demonstrated in the .
    +
  8. +
+ +

+ +Code samples: +

+
flyCam.setEnabled(false);
+ 
+CameraNode camNodeTop = cinematic.bindCamera("topView", cam);
+camNodeTop.setControlDir(ControlDirection.SpatialToCamera);
+camNodeTop.getControl(0).setEnabled(false);
+ 
+CameraNode camNodeSide = cinematic.bindCamera("sideView", cam);
+camNodeSide.setControlDir(ControlDirection.CameraToSpatial);
+camNodeSide.getControl(0).setEnabled(false);
+
+ +

Physics Interaction

+
+ +

+ +Upcoming. +

+ +
+ +

More Information

+
+ +

+See also: + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/collision_and_intersection.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/collision_and_intersection.html new file mode 100644 index 000000000..7a9851e2c --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/collision_and_intersection.html @@ -0,0 +1,211 @@ + +

Collision and Intersection

+
+ +

+ +The term collision can be used to refer to physical interactions (where physical objects collide and bump off one another), and also to non-physical intersections. This article is about non-physical (mathematical) collisions. +

+ +

+Non-physical collisions are interesting because they take less resources than physical ones. You cn optimize your game if you find a way to simulate a certain effect in a non-physical way, using mathematical techniques such as ray casting. +

+ +

+One example for an optimization is a physical vehicle's wheels. You could make the wheels fully physical disks, and have jME calculate every tiny force – sounds very accurate, but is total overkill. An more performant solution is to cast four rays down from the vehicle and calculate the intersections with the floor and other obstacles. These non-physical wheels require (in the simplest case) only four calculations to achieve an effect that players can hardly distinguish from the real thing. +

+ +
+ +

Bounding Volumes

+
+ +

+ +A com.jme3.bounding.BoundingVolume is an interface for dealing with containment of a collection of points. All BoundingVolumes are Collidable and are used as optimization to calculate non-physical collisions more quickly: It's faster to calculate an intersection between simple shapes like spheres and boxes than between complex shapes. In cases where precision is not relevant, you wrap a complex model in a simpler shape to improve collision detection performance. + +

+
    +
  • Type.Sphere: com.jme3.bounding.BoundingSphere is a sphere used as a container for a group of vertices of a piece of geometry. A BoundingSphere has a center and a radius.
    +
  • +
  • Type.AABB = Axis-aligned bounding box. A com.jme3.bounding.BoundingBox is an axis-aligned cuboid used as a container for a group of vertices of a piece of geometry. A BoundingBox has a center and extents from that center along the x, y and z axis.
    +
  • +
  • Type.OBB = Oriented bounding box. (not in use)
    +
  • +
  • Type.Capsule
    +
  • +
+ +

+ +Note: Physical objects have their own “bounding volumes” called CollisionShapes. +

+ +
+ +

Collisions

+
+ +

+ +The interface com.jme3.collision.Collidable declares one method that returns how many collisions were found between two Collidables: collideWith(Collidable other, CollisionResults results). +

+ +

+A com.jme3.collision.CollisionResults object is an ArrayList of comparable com.jme3.collision.CollisionResult objects. +

+ +

+You can iterate over the CollisionResults to identify the other parties involved in the collision. Note that jME counts all collisions, this means a ray intersecting a box will be counted as two hits, one on the front where the ray enters, and one on the back where the ray exits. + +

+ + + + + + + + + + + + + + + + +
CollisionResults MethodUsage
size() Returns the number of CollisionResult objects.
getClosestCollision() Returns the CollisionResult with the lowest distance.
getFarthestCollision()Returns the CollisionResult with the farthest distance.
getCollision(i) Returns the CollisionResult at index i.
+ +

+ +A CollisionResult object contains information about the second party of the collision event. + +

+ + + + + + + + + + + + + + + + + + + + + + +
CollisionResult MethodUsage
getContactPoint()Returns the contact point coordinate on the second party, as Vector3f.
getContactNormal()Returns the Normal vector at the contact point, as Vector3f.
getDistance()Returns the distance between the Collidable and the second party, as float.
getGeometry()Returns the Geometry of the second party.
getTriangle(t)Binds t to the triangle t on the second party's mesh that was hit.
getTriangleIndex()Returns the index of the triangle on the second party's mesh that was hit. (?)
+ +

+Assume you have two collidables a and b and want to detect collisions between them. The collision parties can be Geometries, Nodes with Geometries attached (including the rootNode), Planes, Quads, Lines, or Rays. +

+ +

+The following code snippet can be triggered by listeners (e.g. after an input action such as a click), or timed in the update loop. +

+
  // Calculate Results
+  CollisionResults results = new CollisionResults();
+  a.collideWith(b, results);
+ 
+  System.out.println("Number of Collisions between" + a.getName()+ " and " 
+   + b.getName() " : " + results.size());
+ 
+  // Use the results
+  if (results.size() > 0) {
+    CollisionResult closest  = results.getClosestCollision();
+    System.out.println("What was hit? " + closest.getGeometry().getName() );
+    System.out.println("Where was it hit? " + closest.getContactPoint() );
+    System.out.println("Distance? " + closest.getDistance() );
+  } else {
+    // how to react when no collision occured
+  }
+}
+

+You can also loop over all results and trigger different reactions depending on what was hit and where it was hit. In this example, we simply print info about them. +

+
  // Calculate Results
+  CollisionResults results = new CollisionResults();
+  a.collideWith(b, results);
+ 
+  System.out.println("Number of Collisions between" + a.getName()+ " and " 
+   + b.getName() " : " + results.size());
+ 
+  // Use the results
+  for (int i = 0; i < results.size(); i++) {
+    // For each hit, we know distance, impact point, name of geometry.
+    float     dist = results.getCollision(i).getDistance();
+    Vector3f    pt = results.getCollision(i).getContactPoint();
+    String   party = results.getCollision(i).getGeometry().getName();
+    int        tri = results.getCollision(i).getTriangleIndex();
+    Vector3f  norm = results.getCollision(i).getTriangle(new Triangle()).getNormal();
+ 
+    System.out.println("Details of Collision #" + i + ":");
+    System.out.println("  Party " + party + " was hit at " + pt + ", " + dist + " wu away.");
+    System.out.println("  The hit triangle #" + tri + " has a normal vector of " + norm);
+  }
+

+Knowing the distance of the collisions is useful for example when you intersect Lines and Rays with other objects. +

+ +
+ +

Intersection

+
+ +

+ +A com.jme3.math.Ray is an infinite line with a beginning, a direction, and no end; whereas a com.jme3.math.Line is an infinite line with only a direction (no beginning, no end). +

+ +

+Rays are used to detect where a 3D object is “looking” and whether one object can “see” the other. +

+
    +
  • You can determine where a user has clicked by casting a ray from the camera in the direction of the camera. Now identify the closest collision of the ray with e.g. the rootNode.
    +
  • +
  • Or you cast a ray from a player in the direction of another player. Then you detect all collisions of this ray with other entities (walls, foliage, window panes) and use this to calculate whether one can see the other.
    +
  • +
+ +

+ +These simple ray-surface intersection tests are called Ray Casting. (As opposed to the more advanced Ray Tracing, Ray Casting does not follow a ray's reflection after the first hit, but the ray goes straight on.) +

+ +
+ +

Bounding Interval Hierarchy

+
+ +

+ +com.jme3.collision.bih.BIHNode +com.jme3.scene.CollisionData +

+ +
+ +

SweepSphere

+
+ +

+ +A com.jme3.collision.SweepSphere implements a collidable “stretched” sphere that is shaped like a capsule (an upright cylinder with half a sphere on top and the second half at the bottom). +

+ +

+This shape is usually used to simulate simple non-physcial collisions for character entities in games. The sweep sphere can be used to check collision against a triangle or another sweep sphere. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/combo_moves.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/combo_moves.html new file mode 100644 index 000000000..facf4d0d7 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/combo_moves.html @@ -0,0 +1,259 @@ + +

Combo Moves

+
+ +

+The ComboMoves class allows you to define combinations of inputs that trigger special actions. Entering an input combo correctly can bring the player incremental rewards, such as an increased chance to hit, an increased effectiveness, or decreased change of being blocked, whatever the game designer chooses. +

+ +

+Combos are usually a series of inputs, in a fixed order: For example a keyboard combo can look like: “press Down, then Down+Right together, then Right”. +

+ +

+Usage: +

+
    +
  1. Create input triggers
    +
  2. +
  3. Define combos
    +
  4. +
  5. Detect combos in ActionListener
    +
  6. +
  7. Execute combos in update loop
    +
  8. +
+ +

+ +Copy the two classes ComboMoveExecution.java and ComboMove.java into your application and adjust them to your package paths. +

+ +
+ +

Example Code

+
+
    +
  • +
  • +
  • ← required
    +
  • +
  • ← required
    +
  • +
+ +
+ +

Create Input Triggers

+
+ +

+ +First you define your game's inputs as you usually do: Implement the com.jme3.input.controls.ActionListener interface for your class, and add triggers mappings such as com.jme3.input.controls.KeyTrigger and com.jme3.input.KeyInput. +

+ +

+For example: +

+
inputManager.addMapping("Left",    new KeyTrigger(KeyInput.KEY_LEFT));
+inputManager.addMapping("Right",   new KeyTrigger(KeyInput.KEY_RIGHT));
+inputManager.addMapping("Up",      new KeyTrigger(KeyInput.KEY_UP));
+inputManager.addMapping("Down",    new KeyTrigger(KeyInput.KEY_DOWN));
+inputManager.addMapping("Attack1", new KeyTrigger(KeyInput.KEY_SPACE));
+...
+inputManager.addListener(this, "Left", "Right", "Up", "Down", "Attack1");
+
+ +

Define Combos

+
+ +

+ +For each of your combo moves, you specify the series of inputs that will trigger it. The order in which you define them is the order the player has to press them for the step to be recorded. When all steps have been recorded, the combo is triggered. +

+ +

+The following example shows how a fireball combo move is triggered by pressing the navigation keys for “down, down+right, right”, in this order. +

+
ComboMove fireball = new ComboMove("Fireball");
+fireball.press("Down").notPress("Right").done();
+fireball.press("Right", "Down").done();
+fireball.press("Right").notPress("Down").done();
+fireball.notPress("Right", "Down").done();
+fireball.setUseFinalState(false);
+

+Also create a ComboMoveExecution object for each ComboMove. You need it later to execute the detected combo. +

+
ComboMoveExecution fireballExec = new ComboMoveExecution(fireball);
+
+ +

ComboMove Class Methods

+
+ +

+ +Use the following ComboMove methods to specify the combo: + +

+ + + + + + + + + + + + + + + + + + + + + + +
ComboMove MethodDescription
press(“A”).done();
+ press(“A”,”B”).done();
Combo step is recorded if A is entered.
+ Combo step is recorded if A and B are entered simultaneously.
notPress(“A”).done();
+ notPress(“A”,”B”).done();
Combo step is recorded if A is released.
+ Combo step is recorded if A and B are both released.
press(“A”).notPress(“B”).done();Combo step is recorded if A is entered, and not B
press(“A”).notPress(“B”).timeElapsed(0.11f).done();Combo step is recorded a certain time after A and not B is entered.
+ etc, etc …
setPriority(0.5f);If there is an ambiguity, a high-priority combo will trigger instead of a low-priority combo. This prevents that a similar looking combo step “hijacks” another Combo. Use only once per ComboMove.
setUseFinalState(false);
+ setUseFinalState(true);
This is the final command of the series.
+ False: Do not wait on a final state, chain combo steps. (?)
+ True: This is the final state, do not chain combo steps. (?)
+ +

+ +The press() and notPress() methods accept sets of Input Triggers, e.g. fireball.press(“A”,”B”,”C”).done(). +

+ +

+The following getters give you more information about the game state: + +

+ + + + + + + + + + + + + +
ComboMove MethodUsage
getCastTime()Returns the time since the last step has been recorded. (?)
getMoveName()Returns the string of the current combo
getPriority()Returns the priority of this move
+ +
+ +

Detect Combos in ActionListener

+
+ +

+ +Now that you have specified the combo steps, you want to detect them. You do that in the onAction() method that you get from the ActionListener interface. +

+ +

+Create a HashSet pressMappings to track curently pressed mappings, and a ComboMove object currentMove to track the current move. +

+ +

+We also track the cast time of a combo to determine if it has timed out (see update loop below). +

+
private HashSet<String> pressedMappings = new HashSet<String>();
+private ComboMove currentMove = null;
+private float currentMoveCastTime = 0;
+private float time = 0;
+...
+ 
+public void onAction(String name, boolean isPressed, float tpf) {
+    // Record pressed mappings
+    if (isPressed){
+        pressedMappings.add(name);
+    }else{
+        pressedMappings.remove(name);
+    }
+ 
+    // The pressed mappings have changed: Update ComboExecution objects
+    List<ComboMove> invokedMoves = new ArrayList<ComboMove>();
+    if (fireballExec.updateState(pressedMappings, time)){
+        invokedMoves.add(fireball);
+    }
+    // ... add more ComboExecs here...
+ 
+    // If any ComboMoves have been sucessfully triggered:
+    if (invokedMoves.size() > 0){
+        // identify the move with highest priority
+        float priority = 0;
+        ComboMove toExec = null;
+        for (ComboMove move : invokedMoves){
+            if (move.getPriority() > priority){
+                priority = move.getPriority();
+                toExec = move;
+            }
+        }
+        if (currentMove != null && currentMove.getPriority() > toExec.getPriority()){
+            return; // skip lower-priority moves
+        }
+ 
+        // If a ComboMove has been identified, store it in currentMove
+        currentMove = toExec;
+        currentMoveCastTime = currentMove.getCastTime();
+    }
+}
+
+ +

Execute Combos in the Update Loop

+
+ +

+ +Now that you have detected the current move, you want to execute it. You do that in the update loop. +

+
@Override
+public void simpleUpdate(float tpf){
+    time += tpf;
+    fireballExec.updateExpiration(time); 
+    // ... update more ComboExecs here....
+ 
+    if (currentMove != null){
+        currentMoveCastTime -= tpf;
+        if (currentMoveCastTime <= 0){
+            System.out.println("THIS COMBO WAS TRIGGERED: " + currentMove.getMoveName());
+            // TODO: for each combo, implement special actions here
+            currentMoveCastTime = 0;
+            currentMove = null;
+        }
+    }
+}
+

+Test currentMove.getMoveName() and proceed to call methods that implement any special actions and bonuses. This is up to you and depends individually on your game. +

+ +
+ +

Why Combos?

+
+ +

+ +Depending on the game genre, the designer can reward the players' intrinsical or extrinsical skills: + +

+
    +
  • (intrinsical:) RPGs typically calculate the success of an attack from the character's in-game training level: The player plays the role of a character whose skill level is defined in numbers. RPGs typically do not offer any Combos.
    +
  • +
  • (extrinsical:) Sport and fighter games typically choose to reward the player's “manual” skills: The success of a special move solely depends on the player's own dexterity. These games typically offer optional Combos.
    +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html new file mode 100644 index 000000000..c1fa8c5a1 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html @@ -0,0 +1,278 @@ + +

Custom Controls

+
+ +

+ +com.jme3.scene.control.Control is a customizable jME3 interface that allows you to cleanly implement Game Logic. You use Controls to control the behaviour of types of Spatials. To control global game behaviour see Application States – you can use both together. +

+ +

+To control the behaviour of types of entities: +

+
    +
  1. You define a custom control and implement its behaviour in the Control's update() method.
    +
      +
    • You can pass arguments and manipulate the spatial in any way: Modify its transformation (move, scale, rotate), play animations, check for enemies around it and react, etc.
      +
    • +
    +
  2. +
  3. Add the control to a Spatial (spatial.addControl(myControl)), and the Spatial's game state is updated automatically from now on.
    +
  4. +
  5. Create one control for each type of behavior. When you add several controls to one spatial, they will be executed in the order they were added.
    +
  6. +
+ +

+ +To implement game logic for a Spatial, you will either extend AbstractControl, or implement Control, as explained in this article. +

+ +
+ +

Usage Examples

+
+ +

+ +For example, you could write a CharacterAnimControl that animates a character accordingly while its being moved by a CharacterControl. Or you can write an AIControl that remote controls NPC behaviour. Or you could write a DestructionControl that automatically replaces a structure with an appropriate piece of debris after collision with a projectile… The possibilities are endless. :-) +

+ +

+Existing examples in the code base include: + +

+
    +
  • allows manipulation of skeletal animation, including blending an channels.
    +
  • +
  • allows you to sync the camera position with the position of a given spatial.
    +
  • +
  • displays a flat picture orthogonally, e.g. a speech bubble or informational dialog.
    +
  • +
  • subclasses (such as CharacterControl, RigidBodyControl, VehicleControl) allow you to add physical properties to any spatial. PhysicsControls tie into capabilities provided by the BulletAppState.
    +
  • +
+ +
+ +

The Control Interface

+
+ +

+ +The interface can be found under com.jme3.scene.control.Control. It has the following method signatures: + +

+
    +
  • cloneForSpatial(Spatial): Clones the Control and attaches it to a clone of the given Spatial.
    +
  • +
  • setEnabled(boolean): Enable or disable the control. If disabled, update() does nothing. Goes with accessor isEnabled();.
    +
  • +
  • There are also some internal methods that you do not call from user code: setSpatial(Spatial s), update(float tpf);, render(RenderManager rm, ViewPort vp).
    +
  • +
+ +

+ +If you want to create a Control that also extends an existing class, then create a custom extension of the Control Interface. Usage example: +

+ +

+1. Create a custom control interface + +

+
public interface MyControl extends Control { 
+    public void setSomething(int x); // add your custom methods
+}
+

+ +2. Create custom classes implementing your control interface + +

+
public class ControlledThing extends MyThing implements MyControl {
+ 
+    protected Spatial spatial;
+    protected boolean enabled = true;
+ 
+    public ControlledThing() { }
+ 
+    public ControlledThing(int x) {
+        super(x);
+    }
+ 
+    @Override
+    public void update(float tpf) {
+        if (enabled && spatial != null) {
+            // ...
+            // Write custom code to control the spatial here!
+        }
+    }
+ 
+    @Override
+    public void render(RenderManager rm, ViewPort vp) {
+        // optional, e.g. to display a debug shape
+    }
+ 
+    @Override
+    public Control cloneForSpatial(Spatial spatial) {
+        ControlledThing control = new ControlledThing(y);
+        // ...
+        spatial.setControl(control);
+        return control;
+    }
+ 
+    @Override
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+        // ...
+    }
+ 
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+ 
+    @Override
+    public void setSomething(int z) {
+        // your custom method ...
+    }
+ 
+    @Override
+    public void write(JmeExporter ex) throws IOException {
+        super.write(ex);
+        OutputCapsule oc = ex.getCapsule(this);
+        oc.write(enabled, "enabled", true);
+        oc.write(spatial, "spatial", null);
+        // write custom variables ....
+    }
+ 
+    @Override
+    public void read(JmeImporter im) throws IOException {
+        super.read(im);
+        InputCapsule ic = im.getCapsule(this);
+        enabled = ic.readBoolean("enabled", true);
+        spatial = (Spatial) ic.readSavable("spatial", null);
+        // read custom variables ....
+    }    
+}
+
+ +

AbstractControl

+
+ +

+ +This class can be found under com.jme3.scene.control.AbstractControl. +

+
    +
  • This is a default abstract class that implements the Control interface.
    +
  • +
  • It gives you access to a boolean enabled, and a Spatial spatial.
    +
  • +
  • Extend AbstractControl to create a custom Control.
    +
  • +
+ +

+ +Usage: Your custom subclass must implement the three methods controlUpdate(), controlRender(), and cloneForSpatial() as shown here: +

+
public class MyControl extends AbstractControl implements Savable, Cloneable {
+ 
+  private Thing thing; // some custom class of yours
+ 
+  public MyControl(){} // empty serialization constructor
+ 
+  public MyControl(thing) { // some custom constructor
+    super(spatial);
+    this.thing = thing;
+  }
+ 
+  @Override
+  protected void controlUpdate(float tpf){
+    if(spatial != null && thing != null) {
+      // Implement your custom control here ...
+    }
+  }
+ 
+  @Override
+  protected void controlRender(RenderManager rm, ViewPort vp){
+     // ... optionial
+  }
+ 
+  @Override
+  public Control cloneForSpatial(Spatial spatial){
+    final MyControl control = new MyControl(...);
+    spatial.setControl(control);
+    return control;
+  }
+ 
+  @Override
+  public void read(JmeImporter im) throws IOException {
+      super.read(im);
+      // im.getCapsule(this).read(...);
+  }
+ 
+  @Override
+  public void write(JmeExporter ex) throws IOException {
+      super.write(ex);
+      // ex.getCapsule(this).write(...);
+  }
+ 
+}
+
+ +

Best Practices

+
+ +

+ +Tip: You can use the getControl() accessor to get Control objects from Spatials! No need to pass around lots of object references. +

+ +

+Here an example from the monkeyzone code: +

+
public class CharacterAnimControl implements Control {
+  ...
+  public void setSpatial(Spatial spatial) {
+    ...
+    animControl      = spatial.getControl(AnimControl.class);
+    characterControl = spatial.getControl(CharacterControl.class);
+    ...
+  }
+}
+

+Tip: You can create custom Control interfaces so a set of different Controls provide the same methods and can be accessed with the interface class type. +

+
public interface ManualControl extends Control {
+    public void steerX(float value);
+    public void steerY(float value);
+    public void moveX(float value);
+    public void moveY(float value);
+    public void moveZ(float value);
+   ...
+}
+

+Then you create custom sub-Controls and implement the methods accordingly to the context: +

+
public class ManualVehicleControl   extends ManualControl {...}
+

+ and + +

+
public class ManualCharacterControl extends ManualControl {...}
+

+Then add the appropriate controls to spatials: +

+
characterSpatial.addControl(new ManualCharacterControl());
+...
+vehicleSpatial.addControl(new ManualVehicleControl());
+...
+

+Tip: Use the getControl() method on a Spatial, get a specific Control object, and activate its behaviour! +

+
ManualControl c = mySpatial.getControl(ManualControl.class);
+c.steerX(steerX);
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html new file mode 100644 index 000000000..a63222c89 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html @@ -0,0 +1,275 @@ + +

Custom Mesh Shapes

+
+ +

+ + +

+ +

+Use the Mesh class to create custom shapes that go beyond Quad, Box, Cylinder, and Sphere, even procedural shapes are possible. Thank you to KayTrance for providing the sample code! +

+ +

+In this tutorial, we (re)create a very simple rectangular mesh, and we have a look at different ways of coloring it. A flat rectangle may not look useful because it's exactly the same as a com.jme3.scene.shape.Quad. We choose this simple example in order to show you how to build any shape out of triangles – without the distractions of more complex shapes. + +

+
    +
  • Full code sample:
    +
  • +
+ +
+ +

Polygon Meshes

+
+ +

+ +Polygon meshes are made up of triangles. The corners of the triangles are vertices. So, when ever you create a new shape, you break it down into triangles. +

+ +

+Let's look at a cube. A cube is made up of 6 rectangles. Each rectangle can be broken down into two triangles. This means you need 12 triangles to create a cube mesh. You also need to know the 8 corner coordinates (vertices). The trick is that you have to specify the vertices in a certain order: Each triangle separately, counter-clockwise. +

+ +

+Sounds worse than it is – here is an example: +

+ +
+ +

Creating a Quad Mesh

+
+ +

+ +Okay, we want to create a Quad. A quad has four vertices, and is made up of two triangles. +

+ +

+The base class for creating meshes is com.jme3.scene.Mesh. +

+
Mesh m = new Mesh();
+
+ +

Vertices

+
+ +

+ +To define your own shape, determine its vertex positions in space. Store them in an array using com.jme3.math.Vector3f. For a Quad, we need four vertices: Bottom left, bottom right, top left, top right. We name the array vertices[]. +

+
Vector3f [] vertices = new Vector3f[4];
+vertices[0] = new Vector3f(0,0,0);
+vertices[1] = new Vector3f(3,0,0);
+vertices[2] = new Vector3f(0,3,0);
+vertices[3] = new Vector3f(3,3,0);
+
+ +

Texture Coordinates

+
+ +

+ +Next, define the Quad's 2D texture coordinates for each vertex, in the same order: Bottom left, bottom right, top left, top right. We name this array texCoord[] +

+
Vector2f[] texCoord = new Vector2f[4];
+texCoord[0] = new Vector2f(0,0);
+texCoord[1] = new Vector2f(1,0);
+texCoord[2] = new Vector2f(0,1);
+texCoord[3] = new Vector2f(1,1);
+
+ +

Connecting the Dots

+
+ +

+ +Next we turn the unrelated coordinates into triangles – We define the order in which the mesh is constructed. Think of these indexes as coming in groups of three. Each group of indexes describes one triangle. Note that you must specify the vertices counter-clockwise! +

+
int [] indexes = { 2,0,1, 1,3,2 };
    +
  • The 2,0,1 triangle starts at top left, continues bottom left, and ends at bottom right.
    +
  • +
  • The 1,3,2 triangle start at bottom right, continues top right, and ends at top left.
    +
  • +
+
+2\2--3
+| \  | Counter-clockwise
+|  \ |         
+0--1\1
+
+ +
+ +

Setting the Mesh Buffer

+
+ +

+ +The Mesh data is stored in a buffer. +

+
    +
  1. Using com.jme3.util.BufferUtils, we create three buffers for the three types of information we have:
    +
      +
    • vertex positions,
      +
    • +
    • texture coordinates,
      +
    • +
    • indices.
      +
    • +
    +
  2. +
  3. We assign the data to the appropriate type of buffer inside the mesh object. The three buffer types are taken from an enum in com.jme3.scene.VertexBuffer.Type.
    +
  4. +
  5. The third parameter describes the number of components of the values. Vertex postions are 3 float values, texture coordinates are 2 float values, and the indices are single ints.
    +
  6. +
+
m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
+m.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
+m.setBuffer(Type.Index,    1, BufferUtils.createIntBuffer(indexes));
+

+Our Mesh is ready! Now we want to see it. +

+ +
+ +

Using the Mesh in a Scene

+
+ +

+We create a com.jme3.scene.Geometry, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene. +

+
Geometry geom = new Geometry("OurMesh", m);
+Material mat = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
+mat.setColor("Color", ColorRGBA.Blue);
+geom.setMaterial(mat);
+rootNode.attachChild(geom);
+

+Ta-daa! +

+ +
+ +

Optional Mesh Features

+
+ +

+ +There are more vertex buffers in a Mesh than the three shown above. For an overview, see also Meshes and Models. +

+ +
+ +

Example: Vertex Colors

+
+ +

+ +Vertex coloring is a simple way of coloring meshes. Instead of just assigning one solid color, each vertex (corner) has a color assigned. The faces between the vertices are then colored with a gradient. +

+ +

+We will use the same mesh m as defined above, but with a special VertexColor material. +

+
Geometry coloredMesh = new Geometry ("ColoredMesh", m);
+Material matVC = new Material(assetManager, "Common/MatDefs/Misc/VertexColor.j3md");
+

+We create a float array color buffer. + +

+
    +
  • We assign 4 color values, RGBA, to each vertex.
    +
      +
    • To loop over the 4 color values, we use a color index
      int colorIndex = 0;
      +
    • +
    +
  • +
  • The color buffer contains four color values for each vertex.
    +
      +
    • The Quad in this example has 4 vertices.
      float[] colorArray = new float[4*4];
      +
    • +
    • Tip: If your mesh has a different number of vertices, you would write:
      float[] colorArray = new float[yourVertexCount * 4]
      +
    • +
    +
  • +
+ +

+ +We loop over the colorArray buffer to quickly set some RGBA value for each vertex. As usual, RGBA color values range from 0.0f to 1.0f. Note that the values we use here are arbitrarily chosen! It's just a quick loop to give every vertex a different RGBA value (a purplish gray, purple, a greenish gray, green, see screenshot), without writing too much code. For your own mesh, you'd assign values for the color buffer depending on which color you want your mesh to have. +

+
for(int i = 0; i < 4; i++){
+   // Red value (is increased by .2 on each next vertex here)
+   colorArray[colorIndex++]= 0.1f+(.2f*i);
+   // Green value (is reduced by .2 on each next vertex)
+   colorArray[colorIndex++]= 0.9f-(0.2f*i);
+   // Blue value (remains the same in our case)
+   colorArray[colorIndex++]= 0.5f;
+   // Alpha value (no transparency set here)
+   colorArray[colorIndex++]= 1.0f;
+}
+

+ +Next, set the color buffer. An RGBA color value contains four float components, thus the parameter 4. +

+
m.setBuffer(Type.Color, 4, colorArray);
+coloredMesh.setMaterial(matVC);
+

+Now you see a gradient color extending from each vertex. +

+ +
+ +

Example: Point Mode

+
+ +

+ +Alternatively, you can show the vertices as colored points instead of coloring the faces. +

+
Geometry coloredMesh = new Geometry ("ColoredMesh", cMesh);
+...
+m.setMode(Mesh.Mode.Points);
+m.setPointSize(10f);
+m.updateBound();
+m.setStatic();
+Geometry points = new Geometry("Points", m);
+points.setMaterial(mat);
+rootNode.attachChild(points);
+ 
+rootNode.attachChild(coloredMesh);
+

+This will result in a 10 px dot being rendered for each of the four vertices. The dot has the vertex color you specified above. The Quad's faces are not rendered at all. This can be used for a special debugging or editing mode. +

+ +
+ +

Tip: Front and Back Faces

+
+ +

+ +By default, jME3 optimizes a scene by culling all backfaces. It determines which side the front or backface of a mesh is by the order of the vertices. The frontface is the one where the vertices are specified counter-clockwise. +

+ +

+This means your mesh, as created above, is invisible when seen from “behind”. This may not be a problem and is often even intended. If you use the custom meshes to form a polyhedron, or flat wallpaper-like object, rendering the backfaces (the inside of the polyhedron) would indeed be a waste of resources. +

+ +

+In case that your use case requires the backfaces to be visible, you have two options: +

+
    +
  • If you have a very simple scene, you can just deactivate backface culling for this one mesh's material.
    + mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off));
    +
  • +
  • The recommended solution is to specify each triangle twice, the second time with the opposite order of vertices. The second, reversed triangle makes up the backface.
    + int[] indexes = { 2,0,1, 1,3,2, 2,3,1, 1,0,2 };
    +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debug-shapes.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debug-shapes.png new file mode 100644 index 000000000..998330a83 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debug-shapes.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debugging.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debugging.html new file mode 100644 index 000000000..c94938924 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debugging.html @@ -0,0 +1,179 @@ + +

Debugging

+
+ +

+ +When you deal with complex game engine features like animations or physics it is handy to get feedback from the engine how it interpreted the current state. Is the physical object's collision shape really where you think it is? Is the skeleton of the animated character moveing like you think it should? This document shows you how to activate visual debug aides. +

+ +

+What if you just want to quickly write code that loads models and brings them in their start position? You may not want to hunt for a sample model, convert it, add lights, and load materials. Instead you use “hasslefree” simple shapes a wireframe material: No model, no light source, no materials are needed to see them in the scene. +

+ +

+If you ever have problems with objects appearing in the wrong spot, with the wrong scale, or wrong orientation, simply attach debug shapes to your scene to have a point of reference in 3D space – just like a giant ruler. If your code positions the debug shapes correctly, but models remain invisible when you apply the same code to them, you know that the problem must be the model or the light or its material – and not the positioning code. +

+ +

+Here are some different debug shapes: +

+ +

+ +

+ +
+ +

Debug Shapes

+
+ +
+ +

Coordinate Axes

+
+ +

+ +The coordinate axes (com.jme3.scene.debug.Arrow) help you see the cardinal directions (X,Y,Z) from their center point. Scale the arrows to use them as a “ruler” for a certain length. +

+
private void attachCoordinateAxes(Vector3f pos){
+  Arrow arrow = new Arrow(Vector3f.UNIT_X);
+  arrow.setLineWidth(4); // make arrow thicker
+  putShape(arrow, ColorRGBA.Red).setLocalTranslation(pos);
+ 
+  Arrow arrow = new Arrow(Vector3f.UNIT_Y);
+  arrow.setLineWidth(4); // make arrow thicker
+  putShape(arrow, ColorRGBA.Green).setLocalTranslation(pos);
+ 
+  Arrow arrow = new Arrow(Vector3f.UNIT_Z);
+  arrow.setLineWidth(4); // make arrow thicker
+  putShape(arrow, ColorRGBA.Blue).setLocalTranslation(pos);
+}
+ 
+private Geometry putShape(Mesh shape, ColorRGBA color){
+  Geometry g = new Geometry("coordinate axis", shape);
+  Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+  mat.getAdditionalRenderState().setWireframe(true);
+  mat.setColor("Color", color);
+  g.setMaterial(mat);
+  rootNode.attachChild(g);
+  return g;
+}
+
+ +

Wireframe Grid

+
+ +

+ +Use a wireframe grid (com.jme3.scene.debug.Grid) as a ruler or simple floor. +

+
private void attachGrid(Vector3f pos, float size, ColorRGBA color){
+  Geometry g = new Geometry("wireframe grid", new Grid(size, size, 0.2f) );
+  Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+  mat.getAdditionalRenderState().setWireframe(true);
+  mat.setColor("Color", color);
+  g.setMaterial(mat);
+  g.center().move(pos);
+  rootNode.attachChild(g);
+  return g;
+}
+
+ +

Wireframe Cube

+
+ +

+ +Use a wireframe cube (com.jme3.scene.debug.WireBox) as a stand-in object to see whether your code scales, positions, or orients, loaded models right. +

+
public void attachWireBox(Vector3f pos, float size, ColorRGBA color){
+  Geometry g = new Geometry("wireframe cube", new WireBox(size, size, size));
+  Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+  mat.getAdditionalRenderState().setWireframe(true);
+  mat.setColor("Color", color);
+  g.setMaterial(mat);
+  g.setLocalTranslation(pos);
+  rootNode.attachChild(g);
+  return g;
+}
+
+ +

Wireframe Sphere

+
+ +

+ +Use a wireframe sphere (com.jme3.scene.debug.WireSphere) as a stand-in object to see whether your code scales, positions, or orients, loaded models right. +

+
private void attachWireSphere(Vector3f pos, float size, ColorRGBA color){
+  Geometry g = new Geometry("wireframe sphere", new WireSphere(size));
+  Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+  mat.getAdditionalRenderState().setWireframe(true);
+  mat.setColor("Color", color);
+  g.setMaterial(mat);
+  g.setLocalTranslation(pos);
+  rootNode.attachChild(g);
+  return g;
+}
+
+ +

Wireframe for Physics

+
+ +

+ +You can display a wireframe of the (usually invisible) collision shape around all physical objects. Use this for debugging when analyzing unexpected behaviour. Does not work with DETACHED physics, please switch to PARALLEL or SEQUENTIAL for debugging. +

+
physicsSpace.enableDebug(assetManager);
+
+ +

Wireframe for Animations

+
+ +

+ +Making the skeleton visible inside animated models can be handy for debugging animations. The control object is an AnimControl, player is the loaded model. +

+
     SkeletonDebugger skeletonDebug = 
+         new SkeletonDebugger("skeleton", control.getSkeleton());
+     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+     mat.setColor("Color", ColorRGBA.Green);
+     mat.getAdditionalRenderState().setDepthTest(false);
+     skeletonDebug.setMaterial(mat);
+     player.attachChild(skeletonDebug);
+
+ +

Example: Toggle Wireframe on Model

+
+ +

+ +We assume that you have loaded a model with a material mat. +

+ +

+Then you can add a switch to toggle the model's wireframe on and off, like this: + +

+
    +
  1. Create a key input trigger that switches between the two materials: E.g. we toggle when the T key is pressed:
        inputManager.addMapping("toggle wireframe", new KeyTrigger(KeyInput.KEY_T));
    +    inputManager.addListener(actionListener, "toggle wireframe");
    +
  2. +
  3. Now add the toggle action to the action listener
      private ActionListener() {
    +    @Override
    +    public void onAction(String name, boolean pressed, float tpf) {
    +      // toggle wireframe
    +      if (name.equals("toggle wireframe") && !pressed) {
    +        wireframe = !wireframe; // toggle boolean
    +        mat.getAdditionalRenderState().setWireframe(wireframe); 
    +      }
    +      // else ... other input tests.
    +    }
    +  };
    +
  4. +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/dof-blur.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/dof-blur.png new file mode 100644 index 000000000..7fabbeeca Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/dof-blur.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html new file mode 100644 index 000000000..35dbf8bef --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html @@ -0,0 +1,266 @@ + +

jME3 Effects -- Overview

+
+ +

+ +
+ +

+ +

+jME3 supports various post-rendering and particle effects. This list contains screenshots and sample code that demonstrates how to add the effect to a scene. +

+ +

+
+ +

+ +
+ +

2D Filter Effects

+
+ +
+ +

Screen Space Ambient Occlusion

+
+ +

+ + +

+ +

+ +

+ +

+ +

+ +

+ +

+ +

+ (article) +

+ +

+ +

+ +
+ +

Light Scattering

+
+ +

+ + +

+ +
+ +

Bloom

+
+ +

+ + +

+ +

+Bloom and Glow +

+ +

+ +

+ +
+ +

Toon Effect

+
+ +

+ + +

+ +

+ +

+ +
+ +

Depth of Field Blur

+
+ +

+ + +

+ +

+ +

+ +
+ +

Fog

+
+ +

+ + (temporary workaround, will be deprecated) +

+ +

+ +

+ +
+ +

Lighting and Shadows

+
+ +

+ + +

+ +

+ +

+ +

+ +

+ +

+ +

+ +

+ +

+ +

+ = Parallel-Split Shadow Mapping (PSSM) +

+ +
+ +

Water

+
+ +

+ + +

+ +

+"SeaMonkey" water + +

+
    +
  • +
  • +
+
    +
  • +
  • +
+ +

+ + +

+ +

+ + +

+
    +
  • +
  • +
+
    +
  • +
  • +
+ +

+ +
+ +

+ +

+
+ +

+ +
+ +

Special Effects

+
+ +

+ + +Particle Emitters +

+ +
+ +

Particles: Explosions, Fire

+
+ +

+ + – debris, flame, flash, shockwave, smoke, sparks +

+ +

+ +

+ +

+ +

+ +
+ +

Particles: Smoke

+
+ +

+ + +

+ +

+Particles can have any texture, e.g. fog, leaves, meteors, snowflakes, mosquitos + +

+
+ +

+See also: + +

+ + +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png new file mode 100644 index 000000000..4c9fca2d3 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html new file mode 100644 index 000000000..d3f40f720 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html @@ -0,0 +1,216 @@ + +

Physical Hinges and Joints

+
+ +

+ +The jMonkeyEngine3 has built-in support for via the com.jme3.bullet package. +

+ +

+Game Physics are not only employed to calculate collisions, but they can also simulate hinges and joints. Think of pulley chains, shaky rope bridges, swinging pendulums, or (trap)door and chest hinges. Physics are a great addition to e.g. an action or puzzle game. +

+ +

+In this example, we will create a pendulum. The joint is the (invisible) connection between the pendulum body and the hook. You will see that you can use what you learn from the simple pendulum and apply it to other joint/hinge objects (rope bridges, etc). +

+ +
+ +

Sample Code

+
+
    +
  • +
  • +
+ +
+ +

Overview of this Physics Application

+
+
    +
  1. Create a SimpleApplication with a BulletAppState
    +
      +
    • This gives us a PhysicsSpace for PhysicsControls
      +
    • +
    +
  2. +
  3. For the pendulum, we use a Spatial with a PhysicsControl, and we apply physical forces to them.
    +
      +
    • The parts of the “pendulum” are Physics Control'ed Spatials with Collision Shapes.
      +
    • +
    • We create a fixed hookNode and a dynamic pendulumNode.
      +
    • +
    +
  4. +
  5. We can “crank the handle” and rotate the joint like a hinge, or we can let loose and expose the joints freely to gravity.
    +
      +
    • For physical forces we will use the method joint.enableMotor();
      +
    • +
    +
  6. +
+ +
+ +

Creating a Fixed Node

+
+ +

+ +The hookNode is the fixed point from which the pendulum hangs. It has no mass. +

+
Node hookNode=PhysicsTestHelper.createPhysicsTestNode(assetManager, new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),0);
+hookNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,0,0f));
+ 
+rootNode.attachChild(hookNode);
+getPhysicsSpace().add(hookNode);
+

+For a rope bridge, there would be two fixed nodes where the bridge is attached to the mountainside. +

+ +
+ +

Creating a Dynamic Node

+
+ +

+ +The pendulumNode is the dynamic part of the construction. It has a mass. +

+
Node pendulumNode=PhysicsTestHelper.createPhysicsTestNode(assetManager, new BoxCollisionShape(new Vector3f( .3f, .3f, .3f)),1);
+pendulumNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,-1,0f));
+rootNode.attachChild(pendulumNode);
+getPhysicsSpace().add(pendulumNode);
+

+For a rope bridge, each set of planks would be one dynamic node. +

+ +
+ +

Understanding DOF, Joints, and Hinges

+
+ +

+ +A PhysicsHingeJoint is an invisible connection between two nodes – here between the pendulum body and the hook. Why are hinges and joints represented by the same class? Hinges and joints have something in common: They constrain the mechanical degree of freedom (DOF) of another object. +

+ +

+Consider a free falling, “unchained” object in physical 3D space: It has 6 DOFs: +

+
    +
  • It translates along 3 axes
    +
  • +
  • It rotates around 3 axes
    +
  • +
+ +

+ +Now consider some examples of objects with joints: +

+
    +
  • An individual chain link is free to spin and move around, but joined into a chain, the link's movement is restricted to stay with the surrounding links.
    +
  • +
  • A person's arm can rotate around some axes, but not around others. The shoulder joint allows one and restricts the other.
    +
  • +
  • A door hinge is one of the most restricted types of joint: It can only rotate around one axis.
    +
  • +
+ +

+ +You'll understand that, when creating any type of joint, it is important to correctly specify the DOFs that the joint restricts, and the DOFs that the joint allows. For the typical DOF of a ragDoll character's limbs, jME even offers a special joint, PhysicsConeJoint. +

+ +
+ +

Creating the Joint

+
+ +

+ +You create the PhysicsHingeJoint after you have created the nodes that are to be chained together. In the code snippet you see that the PhysicsHingeJoint constructor requires the two node objects. You also have to specify axes and pivots – they are the degrees of freedom that you just heard about. +

+
private HingeJoint joint;
+...
+  public void simpleInitApp() {
+    ...
+    // hookNode and pendulumNode are created here...
+    ...
+ 
+    joint=new HingeJoint(hookNode.getControl(RigidBodyControl.class), // A
+                     pendulumNode.getControl(RigidBodyControl.class), // B
+                     new Vector3f(0f, 0f, 0f),  // pivot point of A
+                     new Vector3f(0f,-1f, 0f),  // pivot point of B 
+                     Vector3f.UNIT_Z,           // DoF Axis of A (Z axis)
+                     Vector3f.UNIT_Z  );        // DoF Axis of B (Z axis)
+

+Specify the following parameters for each joint: +

+
    +
  • PhysicsControl A and B – the two nodes that are to be joined
    +
  • +
  • Vector3f pivot A and pivot B – coordinates of the two attachment points
    +
      +
    • The points typically lie on the surface of the PhysicsControl's Spatials, rarely in the middle.
      +
    • +
    +
  • +
  • Vector3f axisA and axisB – around which axes each node is allowed to spin.
    +
      +
    • In our example, we constrain the pendulum to swing only along the Z axis.
      +
    • +
    +
  • +
+ +

+ +Remember to add all joint objects to the physicsSpace, just like you would do with any physical objects. +

+
bulletAppState.getPhysicsSpace().add(joint);
+

+Tip: If you want the joint to be visible, attach a geometry to the dynamic node, and translate it to its start position. +

+ +
+ +

Apply Physical Forces

+
+ +

+ +You can apply forces to dynamic nodes (the ones that have a mass), and see how other joined (“chained”) objects are dragged along. +

+ +

+Alternatively, you can also apply forces to the joint itself. In a game, you may want to spin an automatic revolving door, or slam a door closed in a spooky way, or dramatically open the lid of a treasure chest. +

+ +

+The method to call on the joint is enableMotor(). +

+
joint.enableMotor(true, 1, .1f);
+joint.enableMotor(true, -1, .1f);
    +
  1. Switch the motor on by supplying true
    +
  2. +
  3. Specify the velocity with which the joint should rotate around the specified axis.
    +
      +
    • Use positive and negative numbers to change direction.
      +
    • +
    +
  4. +
  5. Specify the impulse for this motor. Heavier masses need a bigger impulse to be moved.
    +
  6. +
+ +

+ +When you disable the motor, the chained nodes are exposed to gravity again: + +

+
joint.enableMotor(false, 0, 0);
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hud.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hud.html new file mode 100644 index 000000000..3ce5dfd96 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hud.html @@ -0,0 +1,180 @@ + +

Head-Up Display (HUD)

+
+ +

+ +A HUD (Head-Up Display) is part of a game's visual user interface. It's an overlay that displays additional information as (typically) 2-dimensional text or icons on the screen, on top of the 3D scene. +

+ +

+HUDs are used to supply players with essential information about the game state. +

+
    +
  • Status: Score, minimap, points, stealth mode, …
    +
  • +
  • Resources: Ammunition, lives/health, time, …
    +
  • +
  • Vehicle instruments: Cockpit, speedometer, …
    +
  • +
  • Navigational aides: Crosshairs, cursor, hand, …
    +
  • +
+ +

+ + +

+ +

+Not all games have, or need a HUD. To avoid breaking the immersion and cluttering the screen, only use a HUD if it is the only way to convey certain information. +

+ +

+You have two options how to create HUDs. +

+
    +
  • To create full-featured user interfaces, you use Nifty GUI. (Recommended)
    +
  • +
  • If you just quickly want to display a line of text or an icon, you use the guiNode.
    +
  • +
+ +
+ +

HUD with Nifty GUI

+
+ +

+ +The recommended approach to create HUDs is using Nifty GUI. +

+
    +
  1. Lay out the GUI in one or several Nifty XML files.
    +
  2. +
  3. Write the controller classes in Java.
    +
  4. +
  5. Load the XML file with the controller object in your game's simpleInit() method.
    +
  6. +
+ +

+ +The advantage of Nifty GUI is that it is well integrated into jME and the jMonkeyPlatform, and that it offers all the features that you expect from a professional modern user interface. The only small disadvantage is that you (currently still) have to lay out the interface in XML. You can see this as an advantage too, as it enables you to edit the user interface without editing the code afterwards. +

+ +

+For HUDs, you Basically follow the same instructions as for creating a normal Nifty GUI, you just don't pause the game while the HUD is up. +

+ +
+ +

The GUI Node

+
+ +

+ +Using the GUI Node is the default approach in jme3 to create very simple, static HUDs. If you just quickly want to display a line of text, or a simple icon on the screen, use this no-frills method. If you want a more advanced HUD with effects and interaction, use Nifty GUI. +

+ +

+Next to the rootNode for the 3-dimensional scene graph, jME3 also offers a 2-dimension (orthogonal) node, the guiNode. This is how you use it for HUDs: +

+
    +
  • Create a GUI element (text or image).
    +
  • +
  • Attach the GUI element to the guiNode.
    +
  • +
  • Place the GUI element in the orthogonal render queue using setQueueBucket(Bucket.Gui).
    +
  • +
+ +

+The element appears as 2-D, static element on the screen. +

+ +

+By default, the guiNode has some scene graph statistics attached in SimpleApplication. To clear the guiNode and attach your own GUI elements, you detach all children. +

+
guiNode.detachAllChildren();
+
+ +

Displaying Pictures in the HUD

+
+ +

+ +A simple image can be displayed using com.jme3.ui.Picture. +

+
Picture pic = new Picture("HUD Picture");
+pic.setImage(assetManager, "Textures/ColoredTex/Monkey.png", true);
+pic.setWidth(settings.getWidth()/2);
+pic.setHeight(settings.getHeight()/2);
+pic.setPosition(settings.getWidth()/4, settings.getHeight()/4);
+guiNode.attachChild(pic);
+

+When you set the last boolean in setImage() to true, the alpha channel of your image will be rendered transparent/translucent. +

+ +
+ +

Displaying Text in the HUD

+
+ +

+ +You use com.jme3.font.BitmapText to display text on the screen. +

+
BitmapText hudText = new BitmapText(guiFont, false);          
+hudText.setSize(guiFont.getCharSet().getRenderedSize());      // font size
+hudText.setColor(ColorRGBA.Blue);                             // font color
+hudText.setText("You can write any string here");             // the text
+hudText.setLocalTranslation(300, hudText.getLineHeight(), 0); // position
+guiNode.attachChild(hudText);
+

+The BitmapFont object guiFont is a default font provided by SimpleApplication. Copy you own fonts as .fnt+.png files into the assets/Interface/Fonts directory and load them like this: +

+
BitmapFont myFont = assetManager.loadFont("Interface/Fonts/Console.fnt");
+hudText = new BitmapText(myFont, false);
+ +
+ +

Displaying Geometries in the HUD

+
+ +

+ +It is technically possible to attach Quads and 3D Geometries to the HUD. They show up as flat, static GUI elements. Note that if you use a lit Material, you must add a light to the guiNode. Also remember that size units are pixels in the HUD (a 2-wu cube is displayed 2 pixels wide). +

+ +
+ +

Positioning HUD Elements

+
+
    +
  • When positioning text and images in 2D, the bottom left corner of the screen is (0f,0f), and the top right corner is at (settings.getWidth(),settings.getHeight()).
    +
  • +
  • If you have several 2D elements in the GUI bucket that overlap, define their depth order by specifing a Z value. You can use pic.move(x, y, -2) or hudText.setLocalTranslation(x,y,-2).
    +
  • +
  • Size and length values in the orthogonal render queue are treated like pixels. A 20*20-wu big quad is rendered 20 pixels wide.
    +
  • +
+ +
+ +

Keeping the HUD Up-To-Date

+
+ +

+ +Use the update loop to keep the content up-to-date. +

+
public void simpleUpdate(float tpf) {
+  ...
+  hudText.setText("Score: " + score);
+  ...
+  picture.setImage(assetManager, "Interface/statechange.png", true);
+  ...
+}
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/input_handling.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/input_handling.html new file mode 100644 index 000000000..70110cb63 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/input_handling.html @@ -0,0 +1,266 @@ + +

Input Handling

+
+ +

+ +Users interact with your jME3 application with different input devices – the mouse, the keyboard, or a joystick. To respond to inputs we use the inputManager object in SimpleApplication. +

+ +

+This is how you add interaction to your game: + +

+
    +
  1. For each action, choose the trigger(s) (a key or mouse click etc)
    +
  2. +
  3. For each action, add a trigger mapping to the inputManager
    +
  4. +
  5. Create at least one listener in SimpleApplication
    +
  6. +
  7. For each action, register its mappings to a listener
    +
  8. +
  9. Implement each action in the listener
    +
  10. +
+ +
+ +

1. Choose Trigger

+
+ +

+ +Choose one or several key/mouse events for the interaction. We use KeyTrigger, MouseAxisTrigger, MouseButtonTrigger, JoyAxisTrigger and JoyButtonTrigger constants from the com.jme3.input.controls package. +

+ +

+The booleans are used to negate the axes: For inputs that have two axes (MouseAxis, JoyAxis), you have to listen to the negative (true) and positive (false) axis separately. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Trigger Code
Mouse button: Left Click MouseButtonTrigger(MouseInput.BUTTON_LEFT)
Mouse button: Right Click MouseButtonTrigger(MouseInput.BUTTON_RIGHT)
Mouse button: Middle Click MouseButtonTrigger(MouseInput.BUTTON_MIDDLE)
Mouse movement: MouseAxisTrigger(MouseInput.AXIS_X, true),
+ MouseAxisTrigger(MouseInput.AXIS_Y, true),
+ MouseAxisTrigger(MouseInput.AXIS_X, false),
+ MouseAxisTrigger(MouseInput.AXIS_Y, false)
Mouse wheel: MouseAxisTrigger(MouseInput.AXIS_WHEEL,false)
+ MouseAxisTrigger(MouseInput.AXIS_WHEEL,true)
Keyboard: Characters and Numbers etc KeyTrigger(KeyInput.KEY_X) etc
Keyboard: Spacebar KeyTrigger(KeyInput.KEY_SPACE)
Keyboard: Shift KeyTrigger(KeyInput.KEY_RSHIFT),
+ KeyTrigger(KeyInput.KEY_LSHIFT)
Keyboard: F1 etc KeyTrigger(KeyInput.KEY_F1) etc
Keyboard: Return, Enter KeyTrigger(KeyInput.KEY_RETURN),
+ KeyTrigger(KeyInput.KEY_NUMPADENTER)
Keyboard: PageUp, PageDown KeyTrigger(KeyInput.KEY_PGUP),
+ KeyTrigger(KeyInput.KEY_PGDN)
Keyboard: Delete, Backspace KeyTrigger(KeyInput.KEY_BACK),
+ KeyTrigger(KeyInput.KEY_DELETE)
Keyboard: Escape KeyTrigger(KeyInput.KEY_ESCAPE)
Keyboard: Arrows KeyTrigger(KeyInput.KEY_DOWN),
+ KeyTrigger(KeyInput.KEY_UP)
+ KeyTrigger(KeyInput.KEY_LEFT), KeyTrigger(KeyInput.KEY_RIGHT)
NumPad: Number 1 etc KeyTrigger(KeyInput.KEY_NUMPAD1) etc
Joystick: Button JoyButtonTrigger(0, JoyInput.AXIS_POV_X),
+ JoyButtonTrigger(0, JoyInput.AXIS_POV_Y) ?
Joystick: Movement JoyAxisTrigger(0, JoyInput.AXIS_POV_X, true),
+ JoyAxisTrigger(0, JoyInput.AXIS_POV_X, false),
+ JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, true),
+ JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, false)
+ +
+ +

2. Add a Trigger Mapping

+
+ +

+ +When initializing the application, add a Mapping for each Trigger. +

+ +

+Give the mapping a meaningful name. The name should reflect the action, not the key, since the keys can change. Here some examples: +

+
inputManager.addMapping("Pause Game", new KeyTrigger(KeyInput.KEY_P));
+inputManager.addMapping("Rotate",     new KeyTrigger(KeyInput.KEY_SPACE));
+

+There are cases where you may want more then one trigger for one action. For instance some users prefer the WASD keys to navigate, others prefer the arrow keys. You can define both by adding them after a comma. +

+
inputManager.addMapping("Left",  new KeyTrigger(KeyInput.KEY_A), 
+                                 new KeyTrigger(KeyInput.KEY_LEFT));
+inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D), 
+                                 new KeyTrigger(KeyInput.KEY_RIGHT));
+
+ +

3. Create Listeners

+
+ +

+ +The jME3 input manager supports two types of event listeners for inputs: +

+ +

+com.jme3.input.controls.AnalogListener +

+
    +
  • Use for continuous and gradual actions.
    +
      +
    • Examples: Walk, run, rotate, accelerate vehicle, strafe, (semi-)automatic weapon shot
      +
    • +
    +
  • +
  • JME gives you access to:
    +
      +
    • the name of the triggered action.
      +
    • +
    • a gradual value between 0-9 how long the key has been pressed.
      +
    • +
    +
  • +
+ +

+ +com.jme3.input.controls.ActionListener +

+
    +
  • Use for absolute “pressed or released?”, “on or off?” actions.
    +
      +
    • Examples: Pause/unpause, a rifle or revolver shot, jump, click to select.
      +
    • +
    +
  • +
  • JME gives you access to:
    +
      +
    • the name of the triggered action.
      +
    • +
    • a boolean whether the key is still pressed or has just been released.
      +
    • +
    +
  • +
+ +

+ +You can use one or both in the same application. Add one or both of these code snippets to your main SimpleApplication-based class to activate the listener. +

+
private ActionListener() {
+  public void onAction(String name, boolean keyPressed, float tpf) {
+     /** TODO */
+  }
+};
private AnalogListener analogListener = new AnalogListener() {
+  public void onAnalog(String name, float keyPressed, float tpf) {
+     /** TODO */
+  }
+};
+
+ +

4. Register Mappings to Listeners

+
+ +

+ +To activate the mappings, you must register them to the Listener. Write your registration code after the part where you have added the mappings to the inputManager before. +

+ +

+In this example, we register the “Pause Game” mapping to the actionListener object, because pausing a game is in “either/or” decision. +

+
inputManager.addListener(actionListener, new String[]{"Pause Game"});
+

+In this example, we register navigational mappings to the analogListener object, because walking is a continuous action. Players tend to keep the key pressed to express continuity, for example when they want to “walk on” or “accelerate”. +

+
inputManager.addListener(analogListener, new String[]{"Left", "Right"});
+

+As you see, you can add several listeners in one String array. You can call the addListener() method more than once, each time with a subset of your list, if that helps you keep you code tidy. +

+ +

+Tip: Check the string's capitalization and spelling if you think you have registered an action, but it does not work. +

+ +
+ +

5. Implement Actions

+
+ +

+ +You specify the action to be triggered where it says TODO in the Listener code snippets. +Typically you write a series of if/else conditions, testing for all the mapping names, and specifying each action. Here is one example: +

+
private AnalogListener analogListener = new AnalogListener() {
+    public void onAnalog(String name, float value, float tpf) {
+ 
+      if (name.equals("Rotate")) {         // test?
+        player.rotate(0, value*speed, 0);  // action!
+      } // else if ...
+ 
+    }
+  };
+

+It's very common that you want an action to be only triggered once, in the moment when the key is released. Examples are when the player presses an action key to open a door or pick up an item, or to flip a game state, such as pause/unpause. For these cases, use an ActionListener and test for && !keyPressed, like shown in the following example. +

+
private ActionListener() {
+    public void onAction(String name, boolean keyPressed, float tpf) {
+ 
+      if (name.equals("Pause Game") && !keyPressed) { // test?
+        isRunning = !isRunning;                       // action!
+      } // else if ...
+ 
+    }
+  };
+
+ +

Remapping Keys

+
+ +

+ +This approach of separating triggers from actions has the advantage that you can remap triggers easily. Maybe your players have different keyboard layouts, are used to “reversed” mouse navigation, or prefer different navigational keys than the ones you defined. In any case, you only need to replace the trigger parts in the inputManager.addMapping() lines with variables, and load different sets of trigger objects when the game starts. The rest of the code stays as it is. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html new file mode 100644 index 000000000..9b130e750 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html @@ -0,0 +1,338 @@ + +

Saving and Loading Materials with .j3m Files

+
+ +

+ +In the Material Definitions article you learned how to configure Materials programmatically in Java code. If you have certain commonly used Materials that never change, you can clean up the amount of Java code that clutters your init method, by moving material settings into .j3m files. Then later in your code, you only need to call one setter instead of several to apply the material. +

+ +
+ +

Writing the .j3m File

+
+
    +
  1. For every Material, create a file and give it a name that describes it: e.g. SimpleBump.j3m
    +
  2. +
  3. Place the file in your project's assets/Materials/ directory, e.g. MyGame/src/assets/Materials/SimpleBump.j3m
    +
  4. +
  5. Edit the file and add content using the following Syntax, e.g.:
    +Material shiny bumpy rock : Common/MatDefs/Light/Lighting.j3md {
    +     MaterialParameters {
    +         Shininess: 8.0
    +         NormalMap: Textures/bump_rock_normal.png
    +         UseMaterialColors : true
    +         Ambient  : 0.0 0.0 0.0 1.0
    +         Diffuse  : 1.0 1.0 1.0 1.0
    +         Specular : 0.0 0.0 0.0 1.0
    +     }
    +}
    +
    +
    +
  6. +
+ +

+ +How to this file is structured: +

+
    +
  1. Header
    +
      +
    1. Material is a fixed keyword, keep it.
      +
    2. +
    3. shiny bumpy rock is a descriptive string that you can make up. Choose a name to help you remember for what you intend to use this material.
      +
    4. +
    5. After the colon, specify on which Material definition you base this Material.
      +
    6. +
    +
  2. +
  3. Now look up the choosen Material Definition's parameters and their parameter types from the Material table. Add one line for each parameter.
    +
      +
    • For example: The series of four numbers in the example above represent RGBA color values.
      +
    • +
    +
  4. +
  5. Check the detailed syntax reference below if you are unsure.
    +
  6. +
+ +

+ +Tip: In the jMonkeyPlatform, use File>New File>Material>Empty Material File to create .j3m files. +

+ +
+ +

How to Use .j3m Materials

+
+ +

+ +This is how you use the prepared .j3m Material on a Spatial. Since you have saved the .j3m file to your project's Assets directory, the .j3m path is relative to MyGame/src/assets/…. +

+
myGeometry.setMaterial(assetManager.loadAsset("Materials/SimpleBump.j3m"));
+

+Tip: In the jMonkeyPlatform, open Windows>Palette and drag the JME Material: Set J3M snippet into your code. +

+ +
+ +

Syntax Reference for .j3m Files

+
+ +
+ +

Paths

+
+ +

+ +Make sure to get the paths to the textures (.png, .jpg) and material definitions (.j3md) right. + +

+
    +
  • The paths to the built-in .j3md files are relative to jME3's Core Data directory. Just copy the path stated in the Material table.
    + Common/MatDefs/Misc/Unshaded.j3md is resolved to jme3/src/src/core-data/Common/MatDefs/Misc/Unshaded.j3md.
    +
  • +
  • The paths to your textures are relative to your project's assets directory.
    + Textures/bump_rock_normal.png is resolved to MyGame/src/assets/Textures/bump_rock_normal.png
    +
  • +
+ +
+ +

Data Types

+
+ +

+ +All data types (except Color) are specified in com.jme3.shader.VarType. +“Color” is specified as Vector4 in J3MLoader.java. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamejME Java class.j3m file syntax
Float a float (e.g. 0.72) , no comma or parentheses
Vector2 com.jme3.math.Vector2f Two floats, no comma or parentheses
Vector3 com.jme3.math.Vector3f Three floats, no comma or parentheses
Texture2D com.jme3.texture.Texture Path to texture in assets directory, no quotation marks
Boolean (basic Java type) true or false
Int (basic Java type) Integer number, no comma or parentheses
Color com.jme3.math.ColorRGBA Four floats, no comma or parentheses
Vector4
FloatArray
Vector2Array
Vector3Array
Vector4Array
Matrix3
Matrix4
Matrix3Array
Matrix4Array
TextureBuffer
Texture3D
TextureArray
TextureCubeMap
+ +
+ +

Flip and Repeat Syntax

+
+
    +
  • A texture can be flipped using the following syntax NormalMap: Flip Textures/bump_rock_normal.png
    +
  • +
  • A texture can be set to repeat using the following syntax NormalMap: Repeat Textures/bump_rock_normal.png
    +
  • +
  • If a texture is set to both being flipped and repeated, Flip must come before Repeat
    +
  • +
+ +
+ +

Syntax for Additional Render States

+
+
    +
  • A Boolean can be “On” or “Off”
    +
  • +
  • Float is “123.0” etc
    +
  • +
  • Enum - values depend on the enum
    +
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypePurpose
Wireframe (Boolean)
FaceCull (Enum: FaceCullMode)
DepthWrite (Boolean)
DepthTest (Boolean)
Blend (Enum: BlendMode)
AlphaTestFalloff (Float)
PolyOffset (Float, Float)
ColorWrite (Boolean)
PointSprite (Boolean)
+ +
+ +

Examples

+
+ +
+ +

Example 1: Shiny

+
+
Spatial signpost = (Spatial) assetManager.loadAsset(
+    new OgreMeshKey("Models/Sign Post/Sign Post.mesh.xml", null));
+signpost.setMaterial( (Material) assetManager.loadAsset(
+    new AssetKey("Models/Sign Post/Sign Post.j3m")));
+TangentBinormalGenerator.generate(signpost);
+rootNode.attachChild(signpost);
+

+The file assets/Models/Sign Post/Sign Post.j3m contains: +

+
+Material Signpost : Common/MatDefs/Light/Lighting.j3md {
+    MaterialParameters {
+         Shininess: 4.0
+         DiffuseMap:  Models/Sign Post/Sign Post.jpg
+         NormalMap:   Models/Sign Post/Sign Post_normal.jpg
+         SpecularMap: Models/Sign Post/Sign Post_specular.jpg
+         UseMaterialColors : true
+         Ambient  : 0.5 0.5 0.5 1.0
+         Diffuse  : 1.0 1.0 1.0 1.0
+         Specular : 1.0 1.0 1.0 1.0
+    }
+}
+
+ +

+The JPG files are in the same directory, assets/Models/Sign Post/…. +

+ +
+ +

Example 2: Repeating Texture

+
+
Material mat = assetManager.loadMaterial(
+    "Textures/Terrain/Pond/Pond.j3m");
+mat.setColor("Ambient", ColorRGBA.DarkGray);
+mat.setColor("Diffuse", ColorRGBA.White);
+mat.setBoolean("UseMaterialColors", true);
+

+The file assets/Textures/Terrain/Pond/Pond.j3m contains: +

+
+Material Pong Rock : Common/MatDefs/Light/Lighting.j3md {
+     MaterialParameters {
+         Shininess: 8.0
+         DiffuseMap: Repeat Textures/Terrain/Pond/Pond.png
+         NormalMap:  Repeat Textures/Terrain/Pond/Pond_normal.png
+     }
+}
+
+ +

+The PNG files are in the same directory, assets/Textures/Terrain/Pond/ +

+ +
+ +

Example 3: Transparent

+
+ +

+ +The file assets/Models/Tree/Leaves.j3m contains: +

+
+Material Leaves : Common/MatDefs/Light/Lighting.j3md {
+
+    Transparent On
+
+    MaterialParameters {
+        DiffuseMap : Models/Tree/Leaves.png
+        UseAlpha : true
+        AlphaDiscardThreshold : 0.5
+        UseMaterialColors : true
+        Ambient : .5 .5 .5 .5
+        Diffuse : 0.7 0.7 0.7 1
+        Specular : 0 0 0 1
+        Shininess : 16
+    }
+    AdditionalRenderState {
+        Blend Alpha
+        AlphaTestFalloff 0.50
+        FaceCull Off
+    }
+}
+
+ +

+The PNG file is in the same directory, assets/Models/Tree/… +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/jme3_shaders.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/jme3_shaders.html new file mode 100644 index 000000000..b1b37b016 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/jme3_shaders.html @@ -0,0 +1,289 @@ + +

JME3 and Shaders

+
+ +

+
+ + +

+ +
+ +

Shaders Basics

+
+ +

+Shaders are sets of instructions that are executed on the GPU. They are used to take advantage of hardware acceleration available on the GPU for rendering purposes.
+ +This paper only covers Vertex and Fragment shaders because they are the only ones supported by JME3 for the moment. But be aware that there are some other types of shaders (geometry, tessellation,…).
+ +There are multiple frequently used languages that you may encounter to code shaders but as JME3 is based on OpenGL, shaders in JME use GLSL and any example in this paper will be written in GLSL.
+ +
+ + +

+ +
+ +

How Does it work?

+
+ +

+To keep it Simple: The Vertex shader is executed once for each vertex in the view, then the Fragment shader (also called the Pixel shader) is executed once for each pixel on the screen.
+ +The main purpose of the Vertex shader is to compute the screen coordinate of a vertex (where this vertex will be displayed on screen) while the main purpose of the Fragment shader is to compute the color of a pixel.
+ +This is a very simplified graphic to describe the call stack:
+ +
+ +The main program sends mesh data to the vertex shader (vertex position in object space, normals, tangents, etc..). The vertex shader computes the screen position of the vertex and sends it to the Fragment shader. The fragment shader computes the color, and the result is displayed on screen or in a texture. +
+ + +

+ +
+ +

Variables scope

+
+ +

+There are different types of scope for variables in a shader : +

+
    +
  • uniform : User defined variables that are passed by the main program to the vertex and fragment shader, these variables are global for a given execution of a shader.
    +
  • +
  • attribute : Per-vertex variables passed by the engine to the shader, like position, normal, etc (Mesh data in the graphic)
    +
  • +
  • varrying : Variables passed from the vertex shader to the fragment shader.
    +
  • +
+ +

+ +There is a large panel of variable types to be used, for more information about it I recommend reading the GLSL specification .
+ +
+ +

+ +
+ +

Spaces and Matrices

+
+ +

+To understand the coming example you must know about the different spaces in 3D computer graphics, and the matrices used to translate coordinate from one space to another.
+ +
+ +The engine passes the object space coordinates to the vertex shader. We need to compute its position in projection space. To do that we transform the object space position by the WorldViewProjectionMatrix which is a combination of the World, View, Projection matrices (who would have guessed?).
+ +
+ + +

+ +
+ +

Simple example : rendering a solid color on an object

+
+ +

+Here is the simplest application to shaders, rendering a solid color.
+ +Vertex Shader :
+ + +

+
//the global uniform World view projection matrix 
+//(more on global uniforms below)
+uniform mat4 g_WorldViewProjectionMatrix;
+//The attribute inPosition is the Object space position of the vertex
+attribute vec3 inPosition;
+ 
+void main(){
+    //Transformation of the object space coordinate to projection space
+    //coordinates.
+    //- gl_Position is the standard GLSL variable holding projection space
+    //position. It must be filled in the vertex shader
+    //- To convert position we multiply the worldViewProjectionMatrix by
+    //by the position vector. 
+    //The multiplication must be done in this order.
+    gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
+}
+

+Fragment Shader :
+ + +

+
void main(){
+    //returning the color of the pixel (here solid blue)
+    //- gl_FragColor is the standard GLSL variable that holds the pixel
+    //color. It must be filled in the Fragment Shader.
+    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+}
+

+ +For example applying this shader to a sphere would render a solid blue sphere on screen.
+ +
+ +

+ +
+ +

How to use shaders in JME3

+
+ +

+You probably heard that JME3 is “shader oriented”, but what does that mean?
+ +Usually to use shaders you must create what is called a program. This program specify the vertex shader and the fragment shader to use.
+ +JME3 encloses this in the material system. Every material in JME3 uses shaders.
+ +For example let’s have a look at the SolidColor.j3md file :
+ + +

+
MaterialDef Solid Color {
+    //This is the complete list of user defined uniforms to be used in the
+    //shaders
+    MaterialParameters {
+        Vector4 Color
+    }
+ 
+    Technique {
+        //This is where the vertex and fragment shader files are
+        //specified
+        VertexShader GLSL100:   Common/MatDefs/Misc/SolidColor.vert
+        FragmentShader GLSL100: Common/MatDefs/Misc/SolidColor.frag
+ 
+        //This is where you specify which global uniform you need for your
+        //shaders
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+    }
+    Technique FixedFunc {
+    }
+}
+

+ +For more information on JME3 material system, i suggest you read this .
+ +
+ +

+ +
+ +

JME3 Global uniforms

+
+ +

+JME3 can expose pre-computed global uniforms to your shaders. You must specify the one that are required for your shader in the WorldParameters section of the material definition file (.j3md).
+ +Note that in the shader the uniform names will be prefixed by a “g_”.
+ +In the example above, WorldViewProjectionMatrix is declared as uniform mat4 g_WorldViewProjectionMatrix in the shader.
+ +The complete list of global uniforms that can be used in JME3 can be found .
+ +
+ + +

+ +
+ +

JME3 attributes

+
+ +

+Those are different attributes that are always passed to your shader.
+ +you can find a complete list of those attribute in the Type enum of the VertexBuffer .
+ +Note that in the shader the attributes names will be prefixed by a “in”.
+ +
+ + +

+ +
+ +

Step by step

+
+
    +
  • Create a vertex shader (.vert) file
    +
  • +
  • Create a fragment shader (.frag) file
    +
  • +
  • Create a material definition (j3md) file specifying the user defined uniforms, path to the shaders and the global uniforms to use
    +
  • +
  • In your initSimpleApplication, create a material using this definition, apply it to a geometry
    +
  • +
  • That’s it!!
    +
  • +
+
    // A cube 
+    Box(Vector3f.ZERO, 1f,1f,1f);
+    Geometry cube = new Geometry("box", box);
+    Material mat = new Material(assetManager,"Path/To/My/materialDef.j3md");
+    cube.setMaterial(mat);
+    rootNode.attachChild(cube);
+

+ +
+ + +

+ +
+ +

JME3 and OpenGL 3 & 4 compatibility

+
+ +

+GLSL 1.0 to 1.2 comes with build in attributes and uniforms (ie, gl_Vertex, gl_ModelViewMatrix, etc…).
+ Those attributes are deprecated since GLSL 1.3 (opengl 3), hence JME3 global uniforms and attributes. Here is a list of deprecated attributes and their equivalent in JME3
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GLSL 1.2 attributesJME3 equivalent
gl_Vertex inPosition
gl_Normal inNormal
gl_Color inColor
gl_MultiTexCoord0 inTexCoord
gl_ModelViewMatrix g_WorldViewMatrix
gl_ProjectionMatrix g_ProjectionMatrix
gl_ModelViewProjectionMatrix g_WorldViewMatrix
gl_NormalMatrix g_NormalMatrix
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-scattering-filter.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-scattering-filter.png new file mode 100644 index 000000000..e8657b482 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-scattering-filter.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-sources.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-sources.png new file mode 100644 index 000000000..7cffb4221 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-sources.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light_and_shadow.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light_and_shadow.html new file mode 100644 index 000000000..ebd9b9418 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light_and_shadow.html @@ -0,0 +1,206 @@ + +

Light and Shadow

+
+ +

+ +Lighting means that an object is lighter on the side facing the light direction, and darker on the backside. A light source with a direction or location is required for lit Materials to be visible. Lighting does not automatically mean that objects cast a shadow on the floor or other objects: Activating shadow processing is an extra step described below. +

+ +

+ +

+ +
+ +

Light Sources

+
+ +

+ +You can add several light sources to a scene using rootNode.addLight(). All Lighting.j3md- based Materials require a light source to be visible. +

+ +

+The available light sources in com.​jme3.​light are SpotLight, PointLight, AmbientLight, and DirectionalLight. You can set the color of the light – normally, it is white. You can choose to set other colors to influence the scene's atmosphere. +

+ +

+A PointLight has a location and shines from there in all directions as far as its radius reaches, like a lamp. The light intensity decreases with increased distance from the light source. +

+
PointLight lamp_light = new PointLight();
+lamp_light.setColor(ColorRGBA.Yellow);
+lamp_light.setRadius(4f);
+lamp_light.setPosition(new Vector3f(lamp_geo.getLocalTranslation()));
+rootNode.addLight(lamp_light);
+

+A DirectionalLight has no position, only a direction. It is considered “infinitely” far away and sends out parallel beams of light. It can cast shadows. You typically use it to simulate sun light: +

+
DirectionalLight sun = new DirectionalLight();
+sun.setColor(ColorRGBA.White);
+sun.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
+rootNode.addLight(sun);
+

+An AmbientLight influences the brightness of the whole scene globally. It has no direction and no location, and does not cast any shadow. +

+
AmbientLight al = new AmbientLight();
+al.setColor(ColorRGBA.White.mult(1.3f));
+rootNode.addLight(al);
+

+A SpotLight is like a flashlight that sends a distinct beam of light. (Still work in progress, as of alpha-3.) +

+ +
+ +

Simple Lighting

+
+
    +
  • +
  • +
  • +
  • +
+ +

+ +Here we use a material based on Lighting.j3md (More info about Materials). Lighting.j3md-based materials dynamically support Shininess, and Ambient, Diffuse, and Specular Colors. +

+
Geometry teapot = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj");
+TangentBinormalGenerator.generate(teapot.getMesh(), true);
+Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
+mat.setBoolean("m_UseMaterialColors", true);
+mat.setColor("m_Ambient",  ColorRGBA.Black);
+mat.setColor("m_Diffuse",  ColorRGBA.Blue);
+mat.setColor("m_Specular", ColorRGBA.White);
+mat.setFloat("m_Shininess", 12);
+rootNode.attachChild(teapot);
+

+In this example, we use material colors instead of textures. But you can equally well use Lighting.j3md to create a Material that uses texture maps, such as the Diffuse and Normal map used here, but also Specular and Paralax Maps: +

+
    Sphere rock = new Sphere(32,32, 2f);
+    Geometry shiny_rock = new Geometry("Shiny rock", rock);
+    rock.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres
+    TangentBinormalGenerator.generate(rock);           // for lighting effect
+    Material mat_lit = new Material(
+        assetManager, "Common/MatDefs/Light/Lighting.j3md");
+    mat_lit.setTexture("m_DiffuseMap", 
+        assetManager.loadTexture("Textures/Terrain/Pond/Pond.png"));
+    mat_lit.setTexture("m_NormalMap", 
+        assetManager.loadTexture("Textures/Terrain/Pond/Pond_normal.png"));
+    mat_lit.setFloat("m_Shininess", 5f); // [0,128]
+    shiny_rock.setMaterial(mat_lit);
+    rootNode.attachChild(shiny_rock);
+

+This lighting updates live when the object or light source moves. If you shine a colored PointLight at this object, you will see a light reflection in the color of the PointLight. +

+ +

+This lighting method doesn't make the node cast a shadow onto other nodes. +

+ +
+ +

BasicShadowRenderer

+
+
    +
  • +
  • +
+ +

+ +Use the Shadow Renderer to make textured scene nodes cast and receive shadows. +

+ +

+Switch off the default shadow mode, and add a jME SceneProcessor named com.jme3.shadow.BasicShadowRenderer to the viewPort. +

+
BasicShadowRenderer bsr;
+...
+public void simpleInitApp() {
+    ...
+    rootNode.setShadowMode(ShadowMode.Off);
+    bsr = new BasicShadowRenderer(assetManager, 256);
+    bsr.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
+    viewPort.addProcessor(bsr);
+    ...
+

+For every scene node that needs shadows, individually specify the shadow behaviour: Whether it cast shadows, receive shadows, both, or neither. +

+
wall.setShadowMode(ShadowMode.CastAndReceive);
+...
+floor.setShadowMode(ShadowMode.Receive);
+...
+airplane.setShadowMode(ShadowMode.Cast);
+...
+ghost.setShadowMode(ShadowMode.Off);
+...
+
+ +

Parallel-Split Shadow Map

+
+
    +
  • +
  • +
+ +

+ +The PSSM shadow renderer can cast real-time shadows on curved surfaces. +To activate it, add a jME SceneProcessor named com.jme3.shadow.PssmShadowRenderer to the viewPort. +

+
private PssmShadowRenderer pssmRenderer;
+...
+ 
+public void simpleInitApp() {
+    ....
+    pssmRenderer = new PssmShadowRenderer(
+        assetManager,1024,4,PssmShadowRenderer.EDGE_FILTERING_PCF);
+    pssmRenderer.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
+    viewPort.addProcessor(pssmRenderer);
+

+The constructor expects the following values: +

+
    +
  • Your assetManager object
    +
  • +
  • The size of the rendered shadowmaps (512, 1024, 2048, etc…)
    +
  • +
  • The number of shadow maps rendered (the more shadow maps, the more quality, the less FPS).
    +
  • +
  • The type of filtering for shadow edge smoothing:
    +
      +
    • PSSMShadowRenderer.EDGE_FILTERING_DITHER
      +
    • +
    • PSSMShadowRenderer.EDGE_FILTERING_PCF (default).
      +
    • +
    +
  • +
+ +

+ +You can set the following properties on the pssmRenderer object: +

+
    +
  • setDirection(Vector3f) – the direction of the light
    +
  • +
  • setLambda(0.65f) – Factor to use to reduce the split size
    +
  • +
  • setShadowIntensity(0.7f) – shadow darkness (1 black, 0 invisible)
    +
  • +
  • setShadowZextend() – distance how far away from camera shadows will still be computed
    +
  • +
+ +

+ +As usual, specify the shadow behaviour for every scene node. +

+
...
+teapot.setShadowMode(ShadowMode.CastAndReceive);
+...
+soil.setShadowMode(ShadowMode.Receive);
+...
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/localization.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/localization.html new file mode 100644 index 000000000..55535be0c --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/localization.html @@ -0,0 +1,173 @@ + +

Localizing jME 3 Games

+
+ +
+ +

Scope

+
+ +

+ +Localizing an application can mean several things: + +

+
    +
  • At minimum you translate all messages and dialogs in the user interface to your target languages.
    +
  • +
  • You should also translate the “read me”, help, and other documentation.
    +
  • +
  • Also translating web content related to the application makes sure international users find out about your localized game.
    +
  • +
  • If you go the whole way of internationalization, you also “translate” metaphors in icons or symbols used.
    + E.g. For localizations to right-to-left languages, you must also adjust the whole flow of the UI (order of menus and buttons).
    +
  • +
+ +

+ +There are tools that assist you with localizing Java Swing GUIs. jME3 applications do not typically have a Swing GUI, so those tools are not of much help. Just stick to the normal Java rules about using Bundle Properties: +

+ +
+ +

Preparing the Localization

+
+ +

+ +Tip: The jMonkeyPlatform supports opening and editing Bundle.properties files. Also note the Tools > Localization menu. +

+ +

+To prepare the application for localization, you have to first identify all hard-coded messages. + +

+
    +
  1. Find every line in your jME3 game where you hard-coded message strings, e.g.
    +
    System.out.print("Hello World!");
    +UiText.setText("Score: "+score);
    +
  2. +
  3. Create one file named Bundle.properties in each directory where there are Java file that contain messages.
    +
  4. +
  5. For every hard-coded message, you add one line to the Bundle.properties file: First specify a unique key that identifies this string; then an equal sign; and the literal string itself.
    +
    greeting=Hello World!
    +score.display=Score: 
    +
    +
  6. +
  7. In the source code, replace every occurence of a hard-coded message with the appropriate Resource Bundle call to its unique key:
    ResourceBundle.getBundle("Bundle").getString("greeting"));
    +UiText.setText(ResourceBundle.getBundle("Bundle").getString("score.display")+score);
    +
  8. +
+ +

+ +The language used in the Bundle.properties files will be the default language for your game. + +

+ +
+ +

Translating the Messages

+
+ +

+ +Each additional language comes in a set of files that is marked with a (usually) two-letter suffix. Common locales are de for German, en for English, fr for French, ja for Japanese, pt for Portuguese, etc. +

+ +

+To translate the messages to another language, for example, German: + +

+
    +
  1. Make a copy of the Bundle.properties files.
    +
  2. +
  3. Name the copy Bundle_de.properties for German. Note the added suffix _de.
    +
  4. +
  5. Translate all strings (text on the right side of the equal sign) in the Bundle_de.properties to German.
    greeting=Hallo Welt!
    +score.display=Spielstand: 
    + +

    + Important: Do not modify any of the keys (text to the left of the equal sign)! +

    +
    +
  6. +
  7. To test the German localization, start the application from the command line with -Duser.language=de. Note the parameter de.
    +
  8. +
+ +

+ +Tip: In the jMonkeyPlatform, you set this VM Option in the Project properties under Run. Here you can also save individual run configuraions for each language you want to test. +

+ +

+To get the full list of language suffixes use + +

+
Locale.getISOLanguages()));
+
+ +

Which Strings Not to Translate

+
+ +

+ +Important: In the Bundle.properties file, do not include any strings that are asset paths, node or geometry names, input mappings, or material layers. +

+
    +
  • Keep material layers:
    mat.setTexture("m_ColorMap", tex);
    +
  • +
  • Keep paths:
    teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
    +
  • +
  • Keep geometry and node names:
    Geometry thing=new Geometry("A thing", mesh);
    +Node vehicle = new Node("Vehicle");
    +
  • +
  • Keep mappings:
    inputManager.addMapping("Shoot", trigger);
    +inputManager.addListener(actionListener, "Shoot");
    +
  • +
+ +

+ +Only localize messages and UI text! +

+ +
+ +

Common Localization Problems

+
+ +

+ +Typical problems include: +

+
    +
  • Localized strings will be of vastly different lengths and will totally break your UI layout. ⇒ Test every localization
    +
  • +
  • Strings with variable text or numbers don't work the same in different languages. ⇒ Either work in grammatical cases/numbers/gender for each language, or find a work-around.
    +
  • +
  • The localizer only sees the strings, without any context. E.g. does “Search History” mean “display the history of searches”, or “search through the history”? ⇒ Use clear key labels and work closely with the localizers if they require extra info.
    +
  • +
  • Broken international characters ⇒ Make sure the files are saved with the right character encoding for the language.
    +
  • +
+ +
+ +

More Documentation

+
+ +

+ + +

+ +

+ + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/logging.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/logging.html new file mode 100644 index 000000000..9a0b2efd3 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/logging.html @@ -0,0 +1,90 @@ + +

Logging and Monitoring

+
+ +
+ +

Development Log Output

+
+ +

+ +jME uses the standard Java logger from java.util.logging. +

+ +

+To write to the log: +

+
private static final Logger logger = Logger.getLogger(HelloWorld.class.getName());
+

+ +Replace HelloWorld by the name of the class where you are using this line. + +

+
logger.severe("something has failed");
+

+ +or + +

+
logger.warning("verify something...");
+

+More about . +

+ +
+ +

Switching the Logger on and off

+
+ +

+ +In the release version you will deactivate the logging output to the terminal. +

+ +

+To deactivate the default logger, you set the log level to only report severe messages: + +

+
Logger.getLogger(””).setLevel(Level.SEVERE);
+

+To reactivate it: + +

+
Logger.getLogger(””).setLevel(Level.FINE);
+
+ +

jMonkeyPlatform Log Files

+
+ +

+ +You find the jMonkeyPlatform log file in /dev/var/log/messages.log in the jMonkeyPlatform preferences folder. You can learn the location of the preferences folder in the “About” screen of the jMonkeyPlatform under the label Userdir. + +

+
    +
  • Windows: C:\Documents and Settings\YOUR_NAME\.jmonkeyplatform\”
    +
  • +
  • Linux: /home/YOUR_NAME/.jmonkeyplatform/”
    +
  • +
  • Mac OS: /Users/YOUR_NAME/Library/Application Support/jmonkeyplatform/
    +
  • +
+ +
+ +

Read Graphic Card Capabilites

+
+ +

+ +You can read the graphic card's capabilities using the com.jme3.renderer.Caps class: +

+
Collection<Caps> caps = renderer.getCaps();
+Logger.getLogger(HelloWorld.class.getName()).log(Level.INFO, “Caps: {0}” + caps.toString()); 	
+

+Replace HelloWorld by the name of the class where you are using this line. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html new file mode 100644 index 000000000..a91a3b389 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html @@ -0,0 +1,107 @@ + +

How to Use Material Definitions (.j3md)

+
+ +

+ +Typically, you create a set of custom materials, and use them throughout the game. For example, you can initialize and configure your materials objects in the initSimpleApp() method, and then load 3D models (Geometries) and use setMaterial() on them. +

+ +

+Tip: If you use one custom material very often, additionally read about storing material configurations in user-friendly j3m Material Files. +

+ +
+ +

Preparing a Material

+
+
    +
  1. Choose a Material Definition from the Materials Overview list that has the features that you need.
    +
      +
    • Tip: If you don't know, you can always start with Unshaded.j3md.
      +
    • +
    +
  2. +
  3. Look at the applicable parameters of the Material Definition and determine which ones you need to achieve the desired effect. Most parameters are optional.
    +
      +
    1. Create and save the necessary Texture files to the assets directory.
      +
        +
      • E.g. ColorMap; DiffuseMap, NormalMap, AlphaMap, etc…
        +
      • +
      +
    2. +
    3. Determine the required values to achieve the effect that you want.
      +
        +
      • E.g. Colors, floats, booleans, etc…
        +
      • +
      +
    4. +
    +
  4. +
+ +
+ +

Using a Material

+
+
    +
  1. In you Java code, create a Material object based on the .j3md file: e.g.
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    +
  2. +
  3. Configure your Material by setting the appropriate values listed in the Materials Overview table. Here are examples of the methods that set the different data types:
    +
      +
    • mat.setColor( “Color”, ColorRGBA.White );
      +
    • +
    • mat.setTexture( “ColorMap”, assetManager.loadTexture(“Interface/Logo/Monkey.png” ));
      +
    • +
    • mat.setFloat( “Shininess”, 5f);
      +
    • +
    • mat.setBoolean( “SphereMap”, true);
      +
    • +
    • mat.setVector3( “NormalScale”, new Vector3f(1f,1f,1f));
      +
    • +
    +
  4. +
  5. Use your prepared material on a Geometry:
    myGeometry.setMaterial(mat);
    +
  6. +
  7. (Optional) Adjust the texture scale:
    geometry.scaleTextureCoordinates(new Vector2f(1f, .5f));
    +
  8. +
+ +
+ +

Examples

+
+ +

+ +A simpled textured material. + +

+
Material mat = new Material(assetManager, 
+    "Common/MatDefs/Misc/Unshaded.j3md");
+mat.setTexture("ColorMap", assetManager.loadTexture(
+    "Interface/Logo/Monkey.jpg"));
+

+A textured material with a color bleeding through transparent areas. + +

+
Material mat = new Material(assetManager, 
+    "Common/MatDefs/Misc/Unshaded.j3md");
+mat.setTexture("ColorMap", assetManager.loadTexture(
+    "Textures/ColoredTex/Monkey.png"));
+mat.setColor("Color", ColorRGBA.Blue);
+

+You can test these examples within the following code snippet. It creates a box and applies the material: +

+
 Box(Vector3f.ZERO, 1, 1, 1);
+Geometry geom = new Geometry("Box", b);
+// ... insert Material definition...
+geom.setMaterial(mat);
+rootNode.attachChild(geom);
+

+Tip: You can find these and other common code snippets in the jMonkeyPlatform Code Palette. Drag and drop them into your source code. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html new file mode 100644 index 000000000..278d533e0 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html @@ -0,0 +1,303 @@ + +

Materials Overview

+
+ +

+ +This table shows you which material definitions jME supplies by default, and how to make the most of your designer's 3D models by using material parameters. +

+ +

+If you are looking for information about how to use these materials in code, look at Material Definitions and j3M Material Files. +

+ +
+ +

Table of Material Definitions

+
+ +

+ +Some parameters are “optional” because they are somewhat advanced. If you don't know what an option means, chances are that you are not using this feature in your textures – and you don't need to specify it. (E.g. YCoCg and LATC are image compression formats; Minnaert and WardIso are shader types.) +

+ +

+Also note that many other parameters are optional, even if they are not explicitly marked optional. For example, it's okay to specify solely the DiffuseMap and NormalMap when using Lighting.j3md. You are only using a subset of what is possible, but if that's what you want, you can do that. The developer should be in contact with the designer regarding what jME features individual Materials/Textures require. +

+ +
+ +

Coloring and Standard Textures

+
+ + + + + + + + + + + + + + + + +
Material Definition Usage Parameter : Type
Common/MatDefs/Misc/Unshaded.j3md Standard unlit Material. ColorMap : Texture
+ LightMap : Texture
+ Color : Color
+ VertexColor : Boolean
+ SeperateTexCoord : Boolean
+ GlowMap : Texture
+ GlowColor: Color
Common/MatDefs/Misc/Sky.j3md A solid skyblue, or use with a custom SkyDome texture.
+ See also: Sky
Texture : TextureCubeMap
+ SphereMap : Boolean
+ NormalScale : Vector3
Common/MatDefs/Terrain/Terrain.j3md Splat textures for e.g. terrains.
+ See also: Hello Terrain
Texture1 : Texture (red)
+ Texture1Scale : Float
+ Texture2 : Texture (green)
+ Texture2Scale : Float
+ Texture3 : Texture (blue)
+ Texture3Scale : Float
+ Alpha : Texture
Common/MatDefs/Misc/Particle.j3md Used with texture masks for particle effects, or for point sprites.
+ The Quadratic value scales the particle for perspective view ().
+ Does support an optional colored glow effect.
+ See also: Hello Effects
Texture : Texture
+ GlowMap : Texture
+ GlowColor : Color
+ Quadratic : Float
+ PointSprite : Boolean
+ + + + + + + + + + +
Deprecated Material Definition Usage Parameter : Type
Deprecated: use Unshaded.j3md instead
+ Common/MatDefs/Misc/SimpleTextured.j3md
Standard unlit textured Material. ColorMap : Texture
+ ShowAlpha : Boolean (optional)
+ Normalize : Boolean (optional)
+ YCoCg1) : Boolean (optional)
+ LATC2) : Boolean (optional)
Deprecated: use Unshaded.j3md instead
+ Common/MatDefs/Misc/ColoredTextured.j3md
Transparent texture with one solid color bleeding through transparent areas. ColorMap : Texture
+ Color : Color
+ +
+ +

Light and Shadow

+
+ + + + + + + + + + + + + +
Material Definition Usage Parameters
Common/MatDefs/Light/Lighting.j3md Standard lit material with Phong Lighting. Use with SpecularMap, BumpMap, NormalMaps textures, Shininess, etc.
+ Requires light source!
DiffuseMap : Texture
+ UseAlpha3) : Boolean
+ NormalMap : Texture
+ LATC4) : Boolean
+ SpecularMap : Texture
+ Shininess : Float
+ ParallaxMap : Texture
+ AlphaMap : Texture
+ AlphaDiscardThreshold: Float
+ ColorRamp : Texture
+ Glow (optional)
+ GlowMap : Texture
+ GlowColor : Color
+ Performance and quality (optional)
+ VertexLighting : Boolean
+ UseVertexColor : Boolean
+ LowQuality : Boolean
+ HighQuality : Boolean
+ Material Colors (optional)
+ UseMaterialColors : Boolean
+ Diffuse : Color
+ Ambient : Color
+ Specular : Color
+ Tangent shading (optional):
+ VTangent : Boolean
+ Minnaert5) : Boolean
+ WardIso6) : Boolean
Common/MatDefs/Terrain/TerrainLighting.j3mdSame kind of splat texture as Terrain.j3md, but with shading.
+ Requires a light source.
Color Diffuse : Color
+ Ambient : Color
+ Shininess : Float
+ Specular : Color
+ SpecularMap : Texture
+ WardIso : Boolean
+ useTriPlanarMapping : Boolean
+ Texture Splat Maps
+ DiffuseMap : Texture
+ DiffuseMap_0_scale : Float
+ NormalMap : Texture
+ DiffuseMap_1 : Texture
+ DiffuseMap_1_scale : Float
+ NormalMap_1 : Texture
+ DiffuseMap_2 : Texture
+ DiffuseMap_2_scale : Float
+ NormalMap_2 : Texture
+ DiffuseMap_3 : Texture
+ DiffuseMap_3_scale : Float
+ NormalMap_3 : Texture
+ Alpha Maps
+ AlphaMap : Texture
+ AlphaMap_1 : Texture
+ AlphaMap_2 : Texture
+ Glowing
+ GlowMap : Texture
+ GlowColor : Color
Common/MatDefs/Light/Reflection.j3md Reflective glass material with environment map (CubeMap/SphereMap).
+ Requires light source.
+ See also:
Texture : Texture
+ SphereMap: Boolean
+ +
+ +

Testing and Debugging

+
+ + + + + + + + + + + + + +
Material Definition Usage Parameters
Common/MatDefs/Misc/VertexColor.j3md Every vertex gets a solid color, colors of mesh faces are interpolated.
Common/MatDefs/Misc/ShowNormals.j3md A color gradient calculated from surface normals.
Common/MatDefs/Misc/Wireframe.j3md Transparent wireframe outline. Color : Color
+ +
+ +

Transparency

+
+ +

+ +Most Material Definitions support an alpha channel for transparency. In an RGBA color, the last float is the alpha value, whereas 0.0f = transparent, 1.0f = opaque. +

+ +

+For example: mat.setColor(“Color”, new ColorRGBA(1,0,0,0.5f)); is a half-opaque red. +

+ +

+Additionally, specify a blendmode: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionUsage
mat.getAdditionalRenderState().setBlendMode(BlendMode.Off);Opaque
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);Use this for normal transparency. Interpolates the background pixel with the current by using the current pixel's alpha. E.g. alpha-blended vegetation.
mat.getAdditionalRenderState().setBlendMode(BlendMode.Additive);Additive alpha blending adds colors in a commutative way, i.e. the result does not depend on the order of transparent layers. Adds the background pixel color with the current pixel color. E.g. particle effects that have black color as background.
mat.getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);Same as “Additive”, except first it multiplies the current pixel color by the pixel alpha. E.g. used for particle effects that have alpha as background.
mat.getAdditionalRenderState().setBlendMode(BlendMode.Color);Blends by color. Generally useless.
mat.getAdditionalRenderState().setBlendMode(BlendMode.Modulate);Multiplies the background pixel by the current pixel.
mat.getAdditionalRenderState().setBlendMode(BlendMode.ModulateX2);Same as “Modulate”, except the result is doubled.
mat.getAdditionalRenderState().setBlendMode(BlendMode.PremultAlpha);Pre-multiplied alpha blending. E.g. if the color of the object has already been multiplied by its alpha, this is used instead of “Alpha” blend mode.
mat.getAdditionalRenderState().setDepthWrite(false);Use this if you have several transparent objects obscuring one another. Disables writing of the pixel's depth value to the depth buffer.
mat.getAdditionalRenderState().setAlphaFallOff(0.5f);
+ mat.getAdditionalRenderState().setAlphaTest(true)
Enables alpha test, generally used for vegetation. Works the same way as “AlphaDiscardThreshold”.
+ +

+ +Also note the AlphaDiscardThreshold value for materials based on Lighting.j3md. The renderer does not render pixels whose transparancy is below the threshold. +

+ +
+ +

Material Options

+
+ + + + + + + + + + + + + + + + +
mat.getAdditionalRenderState().setWireframe(true);Switch to showing the (textured) Material in wireframe mode
mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
+ mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Front);
+ mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
+ mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.FrontAndBack)
Activate back- or frontface culling, both (=invisible), or off. Backface culling is activated by default as an optimization.
mat.getAdditionalRenderState().setColorWrite(false);Disable writing the color of pixels. Use this together with setDepthWrite(true) to write pixels only to the depth buffer for example.
mat.getAdditionalRenderState().setPointSprite(true);Enables point-sprite mode, so meshes with “Mode.Points” will be rendered as textured sprites. Note that gl_PointCoord must be set in the shader. Point sprites are used for hardware accelerated particle effects.
mat.getAdditionalRenderState().setPolyOffset();Enable polygon offset. Use this when you have meshes that have triangles really close to each over (e.g. ), it will shift the depth values to prevent .
+ +
+ +

Internal Use Only

+
+ +

+ +You may also come across to mentions of the following Material Definition files, but they are only used internally. +

+
+Common/MatDefs/Blur/HGaussianBlur.j3md, VGaussianBlur.j3md, RadialBlur.j3md
+Common/MatDefs/Light/LightScattering.j3md, Deferred.j3md 
+Common/MatDefs/Shadow/PreShadow.j3md, PostShadow.j3md, PostShadowPSSM.j3md
+Common/MatDefs/SSAO/normal.j3md, ssao.j3md 
+Common/MatDefs/Gui/Gui.j3md  
+Common/MatDefs/Hdr/LogLum.j3md, ToneMap.j3md
+ +
+
+
1) +YCoCg is an image compression format.
+
2) +LATC is an image compression format.
+
3) +UseAlpha specifies whether DiffuseMap uses the alpha channel
+
4) +LATC Specifies whether NormalMap is BC5/ATI2n/LATC/3Dc-compressed
+
5) +Minnaert is a shader type.
+
6) +WardIso is a shader type.
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/mesh.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/mesh.html new file mode 100644 index 000000000..2ed87e489 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/mesh.html @@ -0,0 +1,163 @@ + +

Polygon Meshes

+
+ +

+ + +

+ +

+All visible game elements in a scene, whether it is a Model or a Shape, are made up of polygon meshes. JME3 has a com.jme3.scene.Mesh class that represents all meshes. + +

+
    +
  • Meshes are made up of triangles.
    + getTriangleCount(…) and getTriangle(…)
    +
  • +
  • Each mesh has a unique ID
    + getId()
    +
  • +
  • Meshes have transformations: Location (local translation), rotation, scale.
    +
  • +
  • Meshes have a bounding volume. jME3 can detect intersections (that is, non-physical collisions) between meshes, or between meshes and 2D elements such as rays.
    + collideWith().
    +
  • +
  • Meshes are locked with setStatic() and unlocked with setDynamic().
    +
      +
    • Static Meshes cannot be modified, but are more optimized and faster (they can be precalculated).
      +
    • +
    • Dynamic Meshes can be modified live, but are not optimized and slower.
      +
    • +
    +
  • +
  • (Optional) Meshes can have a LOD (level of detail optimization) that renders more or less details depending on distance from the camera.
    +
  • +
+ +

+ +You can use default Shapes as meshes; load 3D models (i.e. meshes created in external applications); or create free-form custom meshes programmatically. +

+ +
+ +

Vertex Buffer

+
+ +

+ +The VertexBuffer contains a particular type of geometry data used by Meshes. Every VertexBuffer set on a Mesh is sent as an attribute to the vertex shader to be processed. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Vertex Buffer TypeDescription
Type.Position Position of the vertex (3 floats)
Type.Index Specifies the index buffer, must contain integer data.
Type.TexCoord Texture coordinate
Type.TexCoord2 Texture coordinate #2
Type.Normal Normal vector, normalized.
Type.Tangent Tangent vector, normalized.
Type.Binormal Binormal vector, normalized.
Type.Color Color and Alpha (4 floats)
Type.Size The size of the point when using point buffers.
Type.InterleavedData Specifies the source data for various vertex buffers when interleaving is used.
Type.BindPosePosition Inital vertex position, used with animation.
Type.BindPoseNormal Inital vertex normals, used with animation
Type.BoneWeight Bone weights, used with animation
Type.BoneIndex Bone indices, used with animation
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Mesh methodDescription
setLineWidth(1)
setPointSize(4.0f)
setBound(boundingVolume)
setStatic()Locks the mesh so you cannot modify it anymore, thus optimizing its data (faster).
setDynamic()Unlocks the mesh so you can modified it, but this will un-optimize the data (slower).
setMode(Mesh.Mode.Points) Used to set mesh modes, see below
getId()
getTriangle(int,tri)
scaleTextureCoordinates(Vector2f)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Mesh ModeDescription
Mesh.Mode.PointsShow only corner points
Mesh.Mode.LinesShow lines
Mesh.Mode.LineLoop?
Mesh.Mode.LineStrip?
Mesh.Mode.Triangles?
Mesh.Mode.TriangleStrip?
Mesh.Mode.TriangleFan?
Mesh.Mode.Hybrid?
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/motion_path.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/motion_path.html new file mode 100644 index 000000000..a7899029d --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/motion_path.html @@ -0,0 +1,36 @@ + +

Motion path

+
+ +

+ +When creating cinematics, we need a convenient way of making objects follow a path, or making smooth camera travelings. +That's where the MotionPath come in handy. +

+ +
+ +

Description

+
+ +

+The MotionPath is a control over a Spatial object. that means that it's able to update the Spatial position on each frame.
+ +It contains a list of way points that are positions in world space that determine the general shape of the path.
+ +The accurate shape is computed using a linear interpolation or a spline interpolation. +

+
    +
  • Linear interpolation result in straight segments between the way points.
    +
  • +
  • Catmull-Rom splines allow to create a very smooth path with few way points, ensure that the curve goes through each way point, with the possibility to adjust the tension of the curve. This is the interpolation you are going to use in most cases
    +
  • +
+ +

+ +more to come… +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/multiple_camera_views.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/multiple_camera_views.html new file mode 100644 index 000000000..df2f4d261 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/multiple_camera_views.html @@ -0,0 +1,137 @@ + +

Multiple Camera Views

+
+ +

+ +You can split the screen and look into the 3D scene from different camera angles at the same time. In this example, we create four views (2×2) with the same aspect ratio as the normal view, but half the size. +

+ +

+The packages used in this example are com.jme3.renderer.Camera and com.jme3.renderer.ViewPort. You can get the full sample code here: +

+ +
+ +

Set up the First View

+
+ +

+ +We use the preconfigured Camera cam and viewPort from SimpleApplication for the first view. +

+
viewPort.setBackgroundColor(ColorRGBA.Blue);
+cam.setViewPort(.5f, 1f, 0f, 0.5f); // resize the viewPort
+cam.setLocation(new Vector3f(3.3212643f, 4.484704f, 4.2812433f));
+cam.setRotation(new Quaternion (-0.07680723f, 0.92299235f, -0.2564353f, -0.27645364f));
+

+Place the main camera in the scene and rotate it in its start position. +

+ +

+We will have a detailed look at how we use setViewPort() to position and resize the default view later. +

+ +
+ +

Set up Three Additional Views

+
+ +

+ +Here is the outline for how you create the three other cams and viewPorts (.) In the code snippet, cam_n stand for cam_2 - cam_4, respectively, same for view_n. + +

+
    +
  1. Clone the first cam to reuse its settings
    +
  2. +
  3. Resize and position the cam's viewPort with setViewPort() – details below.
    +
  4. +
  5. Place the cameras in the scene and rotate them.
    +
  6. +
  7. Create a main view for each camera
    +
  8. +
  9. Reset the cameras' enabled statuses
    +
  10. +
  11. Attach the rootNode to be displayed to this view
    +
      +
    1. It doesn't have to be rootNode, but that is the most common use case
      +
    2. +
    +
  12. +
  13. You can set other optional view properties such as backgroundColor
    +
  14. +
+
Camera cam_n    = cam.clone();
+cam_n.setViewPort(...); // resize the viewPort
+cam_n.setLocation(new Vector3f(...));
+cam_n.setRotation(new Quaternion(...));
+ 
+ViewPort view_n = renderManager.createMainView("View of camera #n", cam_n);
+view_n.setClearEnabled(true);
+view_n.attachScene(rootNode);
+view_n.setBackgroundColor(ColorRGBA.Black);
+
+ +

How to resize and position the ViewPorts

+
+ +

+ +How does jme know which of the four views should appear where on the screen? +

+ +

+Imagine the view as a 1×1-sized box. By default, the settings is cam.setViewPort(0f, 1f, 0f, 1f);. This means the view takes up the whole box, from 0 to 1 left to right, and from 0 to 1 bottom to top. +

+ +

+In the , note the following four lines: +

+
cam.setViewPort(  0.5f, 1.0f, 0.0f, 0.5f);
+...
+cam_2.setViewPort(0.0f, 0.5f, 0.0f, 0.5f);
+...
+cam_3.setViewPort(0.0f, 0.5f, 0.5f, 1.0f);
+...
+cam_4.setViewPort(0.5f, 1.0f, 0.5f, 1.0f);
+

+These viewport parameters are, in this order, the left - right - bottom - top extend of a camera's box on the screen. Note that we have set a few values to 0.5f – this is where we resize each view to half its default height and width. +

+
+0.0 , 1.0       1.0 , 1.0
+       +----+----+
+       |    |    |
+       |cam3|cam4|
+       +---------+
+       |    |    |
+       |cam2|cam |
+       +----+----+
+0.0 , 0.0       1.0 , 0.0
+ +

+Example: Cam3's rect extends from bottom-left (0.0 , 0.5) to top-right (0.5 , 1.0) +

+
    +
  • The left corner is at 0, and the right corner is 0.5 on the x axis.
    +
  • +
  • The bottom of the box is at 0.5 and the top at 1.0 on the y axis.
    +
  • +
+ +
+ +

Other Layouts

+
+ +

+ +This layout shows 2×2 views. For a split screen you may want to lay out two views, one above the other, or one next to the other. +

+ +

+If you scale the views in a way so that the aspect ratio changes, the views will obviously be distorted. In these cases, create custom camera objects with the right aspect ratio (redefine the default cam). +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui.png new file mode 100644 index 000000000..ef4a09116 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html new file mode 100644 index 000000000..699a29f08 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html @@ -0,0 +1,481 @@ + +

Creating User Interfaces with Nifty GUI

+
+ +

+ +Although it is possible to embed a jME3 canvas in a Swing GUI app, a 3D game typically runs full-screen, or in a window of its own. This soon raises the question of how to add a user interface: Most games respond to the escape key by displaying buttons that allow users to switch to different screens – for example to view high scores, customize settings, or load saved games. +

+ +

+This doc introduces you to , a Java library for graphical user interfaces (GUIs). Nifty GUI (de.lessvoid.nifty package) is well integrated with jME3 via the com.jme3.niftygui package. You define the GUI layout in XML and call it from your Java code. All the JAR libraries that you need are already included in your jME3 download, so you do not need to install anything extra (Just make sure they are on the classpath). +

+ +

+There are three steps needed to add a GUI to your jME3 game: + +

+
    +
  1. Lay out the GUI
    +
      +
    • in XML, or
      +
    • +
    • in Java (work in progress)
      +
    • +
    +
  2. +
  3. Integrate the GUI into the Game
    +
      +
    • Overlay the User Interface Over the Screen, or
      +
    • +
    • Project the User Interface Onto a Texture
      +
    • +
    +
  4. +
  5. Interact with the GUI from Java
    +
  6. +
+ +

+ + +

+ +
+ +

Sample Code

+
+
    +
  • +
  • +
  • +
  • +
+ +
+ +

Laying out the GUI

+
+ +

+ +Usually, you lay out the GUI using XML, but using Java will soon be a second option. +

+ +
+ +

a) Lay out the GUI in XML

+
+ +

+ +Create an empty helloworld.xml file in the assets/Interfaces/ directory of your project. +

+ +

+You “draw” the GUI to the screen by writing XML code. +

+
    +
  • The base element is the screen.
    +
      +
    • Name the first screen id=“start”. Name any others whatever you like.
      +
    • +
    +
  • +
  • A screen contains one or more layers.
    +
  • +
  • A layer contains elements such as panels, images, text fields.
    +
  • +
  • Every element has an id to refer to it.
    +
  • +
  • Every Screen has a Java class as ScreenController.
    +
  • +
+ +
+ +

How to Use Screens and Layers

+
+ +

+ +Here's a minimal example showing an empty centered layer: +

+
<?xml version="1.0" encoding="UTF-8"?>
+<nifty>
+  <screen id="start" controller="de.lessvoid.nifty.examples.helloworld.HelloWorldStartScreen">
+    <layer id="layer" backgroundColor="#003f" childLayout="center">
+       <!-- panels and text fields go here -->
+    </layer>
+  </screen>
+</nifty>
+

+Into a layer, you add elements (panels, text, images, etc), and specify their properties: +

+ +

+Load a Panel (rectangular colored box) +

+
...
+<panel height="25%" width="35%" align="center" valign="center" backgroundColor="#f60f"
+       childLayout="center" visibleToMouse="true">
+</panel>
+...
+

+Load a Piece of Text +

+
...
+<text font="verdana-24-shadow.fnt" text="Hello World!" align="center" valign="center" />
+...
+

+ +or +

+
...
+<label text="this is my text" align="left"/>
+...
+

+Load an Image +

+
<image filename="Textures/jme-logo.png" ></image>
+

+Nifty additionally offers predefined controls – learn more from the NiftyGUI page: +

+
    +
  • +
  • +
  • +
  • +
+ +
+ +

How to Add Effects

+
+ +

+ +You can register effects to screen elements. +

+
    +
  • Respond to element events such as onStartScreen, onEndScreen, onHover, onFocus, onActive,
    +
  • +
  • Trigger effects that change movement, blending, size, color, fading, and much more.
    +
  • +
+ +

+ +Here is an example that moves a panel when the startScreen opens. You place an < effect > tag inside the element that you want to want to be affected. +

+
...
+  <panel height="25%" width="35%" ...>
+    <effect>
+      <onStartScreen name="move" mode="in" direction="top" 
+                     length="300" startDelay="0" inherit="true"/>
+    </effect>
+  </panel>
+...
+

+Playing sounds using nifty is also possible with effects as triggers. Remember to first register the sound you're going to play: +

+
...
+  <registerSound id="click" filename="Sounds/Gui/ButtonClick.ogg" />
+...
+  <label>
+    <effect>
+       <onClick name="playSound" sound="click"/>
+    </effect>
+  </label>
+...
+

+ +Learn more from the NiftyGUI page: +

+
    +
  • +
  • +
+ +
+ +

b) Lay out the GUI in Java

+
+ +

+ +The Nifty team has started creating a “Builder Pattern” based way to create Nifty GUIs. These classes can be used from within Java to create a Nifty GUI without the need for an external XML file. +

+ +
+ +

Integrating the GUI into the Game

+
+ +

+ +Define a key (for example escape) that switches the GUI on and off. +You can either overlay the running game with the GUI (you will most likely pause then game then), or even project it as a texture onto a mesh (but that makes clicking difficult). +

+ +
+ +

a) Overlaying the User Interface Over the Screen

+
+ +

+ +This code shows you how to overlay anything on the screen with the GUI. This is the most common usecase. +

+
NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(
+    assetManager, inputManager, audioRenderer, guiViewPort);
+nifty = niftyDisplay.getNifty();
+ 
+// init Nifty start screen
+nifty.fromXml("Interface/helloworld.xml", "start");
+ 
+// attach the Nifty display to the gui view port as a processor
+guiViewPort.addProcessor(niftyDisplay);
+// disable the fly cam
+flyCam.setDragToRotate(true);
+
+ +

b) Projecting the User Interface Onto a Texture

+
+ +

+ +You can project the Nifty GUI onto a texture, load the texture into a material, and assign it to a 3D mesh. Allthough this is possible the approach is rarely used since it is difficult to record clicks this way, you can only interact with this UI by keyboard. +

+
/** Create a new viewport for the GUI */
+ViewPort niftyView = renderManager.createPreView("NiftyView", new Camera(1024, 768));
+niftyView.setClearEnabled(true);
+ 
+ 
+/** Create a new NiftyJmeDisplay for the integration */
+NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(
+  assetManager,  inputManager,  audioRenderer,  niftyView);
+ 
+/** Create a new NiftyGUI object and read your XML */
+Nifty nifty = niftyDisplay.getNifty();
+nifty.fromXml("Interface/helloworld.xml", "start");
+ 
+/** We prepare a framebuffer for the texture niftytex */
+niftyView.addProcessor(niftyDisplay);
+FrameBuffer fb = new FrameBuffer(1024, 768, 0);
+fb.setDepthBuffer(Format.Depth);
+Texture2D niftytex = new Texture2D(1024, 768, Format.RGB8);
+fb.setColorTexture(niftytex);
+niftyView.setClearEnabled(true);
+niftyView.setOutputFrameBuffer(fb);
+ 
+/** This is the 3D cube we project the GUI on */
+Box(Vector3f.ZERO, 1, 1, 1);
+Geometry geom = new Geometry("Box", b);
+Material mat = new Material(assetManager, "Common/MatDefs/Misc/SimpleTextured.j3md");
+mat.setTexture("m_ColorMap", niftytex); /** Here comes the texture! */
+geom.setMaterial(mat);
+rootNode.attachChild(geom);
+

+You select buttons on this GUI with the arrow keys and then press return – Clicking them will not work. +

+ +

+Again, check the to get all the “bells and whistles”! +

+ +
+ +

Interacting with the GUI from Java

+
+ +

+ +The main purpose of the GUI is to send events back to your Java class that indicate what the users clicked, which settings they chose, which values they entered into a field, etc. In the Java class, you want to respond with an appropriate action, or store the entered settings in a file, etc. +

+ +
+ +

Connect GUI to Java Controller

+
+ +

+ +How does the XML file send a message back to your Java application? You register a ScreenController (a Java class) to every NiftyGUI screen. +

+ +

+Create a ScreenController by creating a Java class that implements the de.lessvoid.nifty.screen.ScreenController interface and its abtract methods. +

+
package my.game;
+import de.lessvoid.nifty.Nifty;
+import de.lessvoid.nifty.screen.Screen;
+import de.lessvoid.nifty.screen.ScreenController;
+ 
+public class MySettingsScreen implements ScreenController {
+ 
+    public void bind(Nifty nifty, Screen screen) { }
+ 
+    public void onStartScreen() { }
+ 
+    public void onEndScreen() {  }
+}
+

+The name and package of your custom ScreenController class (here my.game.MySettingsScreen) goes into the controller parameter of the respective screen it belongs to: +

+
<nifty>
+  <screen id="settings" controller="my.game.MySettingsScreen">
+      <!-- panel code ... -->
+  </screen>
+</nifty>
+

+Now the Java class my.game.MySettingsScreen and this GUI screen (settings) are connected. +

+ +
+ +

Make GUI and Java Interact

+
+ +

+ +You can use any of the three following approaches to interact, and you can also combine them, depending on what you want to do. +

+ +
+ +

a) GUI Calls a Void Java Method

+
+ +

+ +To respond to an interaction, add the <interact /> element to a panel and specify the Java method you want to call. In this example, we want to call sayHello() when a panel on the screen is clicked. +

+
...
+<panel id="panel" height="25%" width="35%" align="center" valign="center" 
+       backgroundColor="#f60f" childLayout="center" visibleToMouse="true">
+    <text id="text" font="aurulent-sans-17.fnt" color="#000f" 
+          text="Hello World!" align="center" valign="center" />
+    <interact onClick="sayHello(hi)"/>
+</panel>
+...
+

+Back in this screen's Java class, we specify what the sayHello() method does. As you see, you can include String arguments in the call. +

+
public class MySettingsScreen implements ScreenController {
+  ...
+  public void sayHello(String myarg) {
+     System.out.println("Nifty says "+myarg);
+  }
+ 
+  public String callThis() {
+     return "my friend";
+  }
+}
+
+ +

b) GUI Gets Return Value from Java Method

+
+ +

+ +To send a message from Java to Nifty, Nifty uses ${CALL.callThis()} to get the return value of a custom callThis() method from your Java class. +

+
...
+<panel id="panel" height="25%" width="35%" align="center" valign="center" 
+       backgroundColor="#f60f" childLayout="center" visibleToMouse="true">
+    <text id="text" font="aurulent-sans-17.fnt" color="#000f" 
+          text="Hello World, ${CALL.callThis()}!" align="center" valign="center" />
+    <interact onClick="sayHello(hi)"/>
+</panel>
+...
+

+The Java class callThis() in MySettingsScreen defines the Text that is displayed in the textfield after the words Hello World, …! +

+ +
+ +

c) Java Modifies Nifty Elements and Events

+
+ +

+ +You can also alter the appearance and functions of your nifty elements from Java. +

+ +

+Here's an example of how to change an image: +

+
NiftyImage img = nifty.getRenderEngine().createImage("Interface/Images/image.png", false);
+Element niftyElement = nifty.getCurrentScreen().findElementByName("myElement");
+niftyElement.getRenderer(ImageRenderer.class).setImage(img);
+

+To change the onClick() event of an element: +

+
Element niftyElement = nifty.getCurrentScreen().findElementByName("myElement");
+niftyElement.setInteraction(new ElementInteraction(nifty) {
+ 
+    @Override
+    public void onClick() {
+        // call java functions normally.
+        niftyController.onElementClicked();
+        super.onClick();
+    }
+ 
+    @Override
+    public boolean onClick(MouseInputEvent inputEvent) {
+        niftyController.onElementClicked();
+        return super.onClick(inputEvent);
+    }
+});
+

+For this to work, there already needs to be an < interact > tag inside your xml element: +

+
<interact onClick="doNothing()"/>
+ +

+Learn more: +

+ +
+ +

Pro Tip: Use XML Schema

+
+ +

+ +If you include the following XML schema in the first lines of your NiftyGUI XML files, your IDE will give you helpful hints and code completion. +

+
<?xml version="1.0" encoding="UTF-8"?>
+<nifty xmlns="http://nifty-gui.sourceforge.net/nifty.xsd" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="http://nifty-gui.sourceforge.net/nifty.xsd 
+                           http://nifty-gui.sourceforge.net/nifty.xsd">
+ 
+     <!-- Example: The IDE will tell you that 1 <screen></screen> element is expected here -->
+ 
+</nifty>
+
+ +

Nifty Documentation

+
+ +

+ +Learn more from the NiftyGUI page! +

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nobloomsky.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nobloomsky.png new file mode 100644 index 000000000..129e9d888 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nobloomsky.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otoglow.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otoglow.png new file mode 100644 index 000000000..094c68d63 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otoglow.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otonobloom.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otonobloom.png new file mode 100644 index 000000000..569a1f17e Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otonobloom.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle.png new file mode 100644 index 000000000..aa1812e41 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html new file mode 100644 index 000000000..832cb6802 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html @@ -0,0 +1,232 @@ + +

Particle Emmitter Settings

+
+ +

+ +You cannot create a 3D model for delicate things like fire, smoke, or explosions. Particle Emitters are quite an efficient solution to create these kinds of effects: The emitter renders a series of flat orthogonal images and manipulates them in a way that creates the illusion of a anything from a delicate smoke cloud to individual flames, etc. +

+ +

+Creating an effect involves some trial and error to get the settings just right, and it's worth exploring the expressiveness of the options described below. Tip: Use the Scene Editor in the jMonkeyPlatform to design and preview effects. +

+ +

+ +

+ +
+ +

Create an Emitter

+
+
    +
  1. Create one emitter for each effect:
    ParticleEmitter explosion = new ParticleEmitter(
    +"My explosion effect", ParticleMesh.Type.Triangle, 30);
    +
  2. +
  3. Attach the emitter to the rootNode and position it in the scene:
    rootNode.attachChild(explosion);
    +explosion.setLocalTranslation(bomb.getLocalTranslation());
    +
  4. +
  5. Trigger the effect by calling
    explosion.emitAllParticles()
    +
  6. +
  7. End the effect by calling
    explosion.killAllParticles()
    +
  8. +
+ +

+ +Choose one of the following mesh shapes +

+
    +
  • ParticleMesh.Type.Triangle
    +
  • +
  • ParticleMesh.Type.Point
    +
  • +
+ +
+ +

Configure Parameters

+
+ +

+ +Not all of these parameters are required for all kinds of effects. If you don't specify one of them, a default value will be used. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter Method Default Description
number setNumParticles() The maximum number of particles visible at the same time. Specified by user in constructor.
emission rate setParticlesPerSec() 20 Density of the effect, how many new particles are emitted per second.
+ Set to zero to control the start of the effect.
+ Set to a number for a constantly running effect.
size setStartSize(), setEndSize() 0.2f, 2f Set both to same value for constant size effect.
+ Set to different values for shrink/grow effect.
color setStartColor(), setEndColor() gray, darkgray Set both to the same color for single-colored effects (e.g. fog).
+ Set both to different colors for a gradient effect (e.g. fire).
velocity/direction setInitialVelocity() Vector3f(0,0,0) A vector specifying how fast or slow particles fly, and it which direction.
randomness setVelocityVariation() 0.2f How much the direction/speed (setInitialVelocity()) can vary.
+ 1 = Maximum variation (particles emit in random directions)
+ 0 = No variation (particles fly straight with start velocity only).
direction setFacingVelocity() false true = Flying particles pitch in the direction they're flying (e.g. missiles).
+ false = Particles keep flying rotated the way they started (e.g. debris).
direction setRandomAngle() false true = Flying particle should face at a random angle (e.g. explosion).
+ false = Flying particle flies straight.
direction setFaceNormal() Vector3f.NAN Vector3f = Flying particles face in the given direction.
+ Vector3f.NAN = Flying particles face the camera.
lifetime setLowLife() 3f Minimum time period before particles fade
lifetime setHighLife() 7f Maximum time period before particles fade
rotation setRotateSpeed() 0f 0 = Flying particles don't spin.
+ > 0 = How fast particle spins while flying.
gravity setGravity() 0.1f >0 = Particles fall “down” (e.g. debris, sparks).
+ 0.0f = Particles keep flying (e.g. flames, zero g explosion.)
+ +

+ +Build up you effect by specifying one parameter after the other. If you change several parameters at the same time, it's difficult to tell which of the values caused which outcome. +

+ +
+ +

Create an Effect Material

+
+ +

+ + +

+ +

+Use the common Particle.j3md Material Definition to specify the shape of the particles. The shape is only limited by the texture you provide and can be anything – debris, flames, smoke, mosquitoes, leaves, butterflies… be creative. +

+
    Material mat_flash = new Material(
+        assetManager, "Common/MatDefs/Misc/Particle.j3md");
+    mat_flash.setTexture("Texture", 
+        assetManager.loadTexture("Effects/Explosion/flash.png"));
+    flash.setMaterial(debris_mat);
+    flash.setImagesX(2); // columns
+    flash.setImagesY(2); // rows
+    flash.setSelectRandomImage(true);
+

+The effect texture can contain Sprite animations – a series of different pictures in equally spaced rows and columns. +

+
    +
  • Specify the number of rows and columns
    +
  • +
  • Specify whether you want to play the series in order or at random.
    +
  • +
+ +

+ +Have a look at the following default textures and you will see that you can easily create your own Sprite textures after the same fashion. +

+ +
+ +

Default Particle Textures

+
+ +

+ +The Material is used together with grayscale texture: The black parts will be transparent and the white parts will be opaque. +

+ +

+The following effect textures are available by default from test-data.jar. You can also load your own textures from your assets directory. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Texture Path Dimension Preview
Effects/Explosion/Debris.png 3*3
Effects/Explosion/flame.png 2*2
Effects/Explosion/flash.png 2*2
Effects/Explosion/roundspark.png 1*1
Effects/Explosion/shockwave.png 1*1
Effects/Explosion/smoketrail.png 1*3
Effects/Explosion/spark.png 1*1
Effects/Smoke/Smoke.png 1*15
+ +

+Tip: Use the setStartColor()/setEndColor() settings described above to colorize the textures. +

+ +
+ +

Usage Example

+
+
    ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
+    Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
+    mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
+    fire.setMaterial(mat_red);
+    fire.setImagesX(2); fire.setImagesY(2); // 2x2 texture animation
+    fire.setEndColor(  new ColorRGBA(1f, 0f, 0f, 1f));   // red
+    fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
+    fire.setInitialVelocity(new Vector3f(0, 2, 0));
+    fire.setStartSize(1.5f);
+    fire.setEndSize(0.1f);
+    fire.setGravity(0);
+    fire.setLowLife(0.5f);
+    fire.setHighLife(3f);
+    fire.setVelocityVariation(0.3f); 
+    rootNode.attachChild(fire);
+

+Browse the full source code of all here. + +

+
+ +

+See also: Effects Overview + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics-vehicle.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics-vehicle.png new file mode 100644 index 000000000..4cc958d68 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics-vehicle.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics.html new file mode 100644 index 000000000..478a1b6ea --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics.html @@ -0,0 +1,658 @@ + +

Physics: Gravity, Collisions, Forces

+
+ +

+The jMonkeyEngine3 has built-in support for via the com.jme3.bullet package. +Game Physics are used in applications that simulate mass/gravity, collisions, and friction. Think of pool billiard or car racing simulations. + +

+ +
+ +

Technical Overview

+
+ +

+ +Bullet physics runs internally at 60fps by default. This rate is not dependent on the actual framerate and it does not lock the framerate at 60fps. Instead, when the actual fps is higher than the physics framerate the system will display interpolated positions for the physics objects. When the framerate is lower than the physics framerate the physics space will be stepped multiple times per frame to make up for the missing calculations. +

+ +

+A bullet physics space can be created with a BulletAppState. The updating and syncing of the actual physics objects happens in the following way: +

+ +

+A “normal” update loop with physics looks like this: +

+
    +
  1. collision callbacks (BulletAppState.update())
    +
  2. +
  3. user update (simpleUpdate / update)
    +
  4. +
  5. physics to scenegraph syncing/applying (updateLogicalState())
    +
  6. +
  7. stepping physics (before / in parallel to Application.render())
    +
  8. +
+ +

+ +When you use physics, 1 unit (1.0f) equals 1 meter, weight is expressed in kilograms, most torque and rotation values are expressed in radians. +

+ +
+ +

Sample Code

+
+ +

+ +Full code samples are here: + +

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+ +
+ +

Physics Application

+
+ +

+ +A short overview of how to write a jME application with Physics capabilities: +

+ +

+Do the following once per application to gain access to the physicsSpace object: + +

+
    +
  1. Make you application extend com.jme3.app.SimpleApplication.
    +
  2. +
  3. Create a BulletAppState field:
    private BulletAppState bulletAppState;
    +
  4. +
  5. Initialize your bulletAppState and attach it to the state manager:
    public void simpleInitApp() {
    +    bulletAppState = new BulletAppState();
    +    stateManager.attach(bulletAppState);
    +    ...
    +
  6. +
+ +

+ +You can also access the BulletAppState via the state manager: + +

+
stateManager.getState(BulletAppState.class)
+

+For each Spatial that you want to be physical: + +

+
    +
  1. Create a CollisionShape.
    +
  2. +
  3. Create a PhysicsControl by supplying the CollisionShape and mass.
    +
      +
    • E.g. com.jme3.bullet.control.RigidBodyControl
      +
    • +
    +
  4. +
  5. Add the PhysicsControl to the Spatial.
    +
  6. +
  7. Add the PhysicsControl to the physicsSpace object.
    +
  8. +
  9. Attach the Spatial to the rootNode, as usual.
    +
  10. +
  11. (Optional) Implement the PhysicsCollisionListener interface to respond to PhysicsCollisionEvents if desired.
    +
  12. +
+ +
+ +

Collision Shapes

+
+ +

+ +Before you can create a Physics Control, you must create a Collision Shape from the com.jme3.bullet.collision.shapes package. +

+ +

+The Collision Shape is a simplified shape for which physics are easier to calculate than for the real shape of the model. This approach speeds up the simulation greatly. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Shape Purpose
BoxCollisionShape Box shaped objects such as bricks, crates, simple obstacles. Does not roll.
SphereCollisionShape Spherical objects such as balls. Can roll.
CylinderCollisionShape Tube-shaped pillars, disc-shaped wheels. Can roll on one side.
CapsuleCollisionShape A compound of a cylinder plus two spheres at the top and bottom. Rotated upright, this shape is optimal for character nodes: A cylinder-shaped body does not get stuck at corners and vertical obstacles; the rounded top and bottom do not get stuck on stair steps and ground obstacles. Is locked to stay upright, does not roll.
CompoundCollisionShape A CompoundCollisionShape allows custom combinations of box/sphere/cylinder shapes to form another more complex shape.
MeshCollisionShape A free-form mesh-accurate shape that wraps itself around a mesh.
+ Limitations: Only non-mesh collision shapes (sphere, box, cylinder, compound) can collide with mesh-accurate collision shapes. The Mesh Collision Shape only works for static obstacles, e.g. for a game level model.
GImpactCollisionShape This free-form Mesh Collision Shape can be used for moving objects. Uses . Limitations: CPU intensive, use sparingly! We recommend using HullCollisionShapes or CompoundShapes made of simple shapes if you need improved performance.
HeightFieldCollisionShape Optimized Mesh Collision Shape for static terrains. This shape is much faster than a other Free-Form Mesh Shapes. Requires heightmap data.
HullCollisionShape A collision shape that is based on a mesh but is a simplified convex version.
SimplexCollisionShape A physical point, line, triangle, or quad Collision Shape, defined by one to four points.
PlaneCollisionShape A 2D plane that can be used as flat solid floor or wall.
+ +

+ +Pick the right shape for the mesh for what you want to do: If you give a box a sphere collision shape, it will roll; if you give a ball a box collision shape, it will sit on a slope. +

+ +

+Let's look at the constructor: +

+ +
+ +

Collision Shape Code Samples

+
+ +

+ +MeshCompoundShape and MeshCollisionShape are both mesh-accurate and are intended for immobile scene objects, such as terrains, buildings, or whole shooter levels. Limitation: Only collisions of non-mesh-accurate shapes (sphere, box, etc) shapes can be detected against mesh-accurate shapes. +

+
CompoundCollisionShape myComplexShape = 
+    CollisionShapeFactory.createMeshShape((Node) myComplexGeometry );
+

+An angular, non-mesh-accurate compound shape: +

+
CompoundCollisionShape boxShape = 
+    CollisionShapeFactory.createBoxCompoundShape((Node) someBox);
+

+SphereCollisionShape, BoxCollisionShape, CapsuleCollisionShape are also not mesh-accurate, but have better performance. The can be added to anything, and collisions between them and any other shape can be detected. +

+
SphereCollisionShape sphereShape = 
+    new SphereCollisionShape(1.0f);
+
+ +

Physics Controls

+
+ +

+ +Available PhysicsControls in the com.jme3.bullet.control package are: + +

+ + + + + + + + + + + + + + + + + + + +
Physics ControlPurpose
RigidBodyControlUse for physical objects in the scene, e.g. projectiles and obstacles – things that are freely affected by physical forces, be it by collision or falling.
CharacterControlUse for characters (persons, animals) that stand upright, orthogonally to the X/Z plane. When directional forces are applied to a CharacterControl'ed Spatial, it does not tip over (as a RigidBodyControl'ed Spatial would), but it moves upright (as a walking character would).
GhostControlA GhostControl is a PhysicsControl that detects overlaps with other physical objects. A GhostControl is non-solid and moves with the Spatial it is attached to. Use this for game elements that do not have a visible solid Geometry: Aggro radius, motion detectors, photoelectric sensors, radioactive areas, life-draining ghosts, etc.
VehicleControl
+ PhysicsVehicleWheel
Implements terrestric vehicle behaviour.
RagDollControl Implements Ragdoll behaviour.
+ +

+ +Bullet Physics are available in jME3 through a several classes. You will use PhysicsControls in 99% of the time. +

+ +
+ +

Bullet Physics Controls

+
+ +

+ +PhysicsControls are the recommended way to use physics in a jME3 application. PhysicsControls are flexible and can be added to any Spatial to make it act according to physical properties. These Control classes directly extend Bullet Physics Objects. +

+ +

+Package: com.jme3.bullet.control +

+ +
+ +

Bullet Physics Objects

+
+ +

+ +Physics Objects are mostly standard Bullet classes like RigidBody, GhostObject etc., that jME3's other classes are built upon. Advanced users can use these classes to create custom physics functions. +

+ +

+Package: com.jme3.bullet.objects +

+ +
+ +

(Deprecated) Bullet Physics Nodes

+
+ +

+ +Physics Nodes have Bullet Controllers attached and wrap their methods to “simulate” the old physics nodes that were available before alpha-4. The setLocalTranslation/Rotation() info is transferred to the Bullet Objects for simplicity. Do not use Physics Nodes, use PhysicsControls instead. +

+ +

+Package: com.jme3.bullet.nodes +

+ +
+ +

Physics Controls Code Samples

+
+ +

+ +The various Physics Control constructors expect a Collision Shape (here thingShape) and a mass (a float). +

+
RigidBodyControl myControl=new RigidBodyControl( thingShape , 1.0f );
+

+To make the Physics Control visible in the scene, you must attach the Control to a Geometry (e.g. a model named myGeometry): +

+
myGeometry.addControl(myControl);
+

+This code sample creates a physical Character: +

+
// Load a normal model
+Node model = (Node) assetManager.loadModel("Models/myCharacterModel.mesh.xml");
+rootNode.attachChild(model);
+// Create a appropriate physical shape for it 
+CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
+CharacterControl character_phys = new CharacterControl(capsuleShape, 0.01f);
+// Attach physical properties to model and PhysicsSpace
+model.addControl(character_phys);    
+bulletAppState.getPhysicsSpace().add(character_phys);
+

+Tip: Spheres and Boxes will fall back to their correct default Collision Shape if you don't specify a shape in the RigidBodyControl constructor. The following creates a box with Box Collision Shape: +

+
Box(1,1,1);
+myBox.addControl(new RigidBodyControl( 1.0f ));
+bulletAppState.getPhysicsSpace().add(myBox);
+
+ +

Physics Space

+
+ +

+ +The Physics Space is an object in BulletAppState that is like a rootNode for Physics Controls. +

+
    +
  1. First specify parameters such as gravity and accuracy.
    bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0f,-1f,0f));
    +bulletAppState.getPhysicsSpace().setAccuracy(0.005f);
    +
  2. +
  3. Physics Controls must be added to the PhysicsSpace.
    bulletAppState.getPhysicsSpace().add(myPhysicsControl); ...
    +
  4. +
  5. Physics Control must be added to their Spatial.
    myModel.addControl(myPhysicsControl); ...
    +
  6. +
  7. The Spatial must be attached to the rootNode, as always.
    rootNode.attachChild(myModel); ...
    +
  8. +
  9. You remove physical objects from the scene like this:
    bulletAppState.getPhysicsSpace().remove(myPhysicsControl); 
    +myModel.removeFromParent();
    +
  10. +
+ +
+ +

Properties of Physical Objects

+
+ +

+ +On a PhysicsControl, you can set the following physical properties. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RigidBodyControl Method Property
setFriction(1f) Friction.
setMass(1f) Sets the mass. Dynamic objects have masses > 0.0f.
+ Static immobile obstacles (including buildings and terrains) have mass 0.0f.
setPhysicsLocation()Positions the object. Do not use setLocalTranslation().
setPhysicsRotation()Rotates the object. Do not use setLocalRotate().
setRestitution(0.0f) How bouncy the object is. For a rubber object set this > 0.0f. This setting has an impact on performance.
setKinematic(true) A kinematic node is not affected by gravity, but it is solid and affects other physics objects. It has a mass its position is updated from the spatials translation. You can attach joints to it.
setGravity(new Vector3f(0f,-1f,0f)) You can change the gravity of a physics object after it was added to the physics space.
setCcdMotionThreshold(0.1f) The amount of motion in 1 physics tick to trigger the continuous motion detection.
+ + + + + + + + + + + + + + + + + + + +
CharacterControl Method Property
setFallSpeed(1f) Fall speed (down)
setJumpSpeed(1f) Jump speed (up)
setMaxSlope(1.5f) How steep the slopes are that the character can still climb.
setUpAxis(1) 0 = X axis , 1 = Y axis , 2 = Z axis. E.g. for characters and vehicle, up is usually along the the Y axis.
setGravity(1f) You can change the Gravity of a physics object after it was added to the physics space
+ +
+ +

Kinematic vs Dynamic vs Static

+
+ +

+ +Physical objects… +

+
    +
  • must not overlap.
    +
  • +
  • can detect collisions and report several values about the impact.
    +
  • +
  • can respond dynamically or statically or kinematically to collisions.
    +
  • +
+ +
+ +

Dynamic

+
+ +

+ +A dynamic physics object is one that falls when in mid-air, it bounces off obstacles, and is pushed around when it collides with another physical object. It has a mass. +

+ +
+ +

Static

+
+ +

+ +You can create static physical objects without mass. They are still treated as solid objects, but they cannot be dynamically pushed around. They act as static, immobile attached physical obstacles such as terrains and building models. +

+ +
+ +

Kinematic

+
+ +

+ +Kinematic RigidBodys have a mass, but they are not affected by gravity. When non-kinematic objects collide with a kinematic object, only the non-kinematic ones are pushed away by the collision. The intesity of the kinematic's effect against other objects depends on their speed and mass: +

+ +

+Ekin = mass * speed^2 (well, approximately, bullet doesn't use Einsteins formula ;)) +

+ +

+Tip: Spatials with a kinematic RigidBodyControl can be moved programmatically, e.g. using setLocalTranslation() in the update() loop, or by an Animation Path. You can also “hang them up in mid-air” and attach other PhysicsNodes to them using hinges and joints. +

+
airhook.setKinematic(true);
+
+ +

Forces: Moving Physical Objects

+
+ +

+ +Use the following methods to move physics objects. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Motion
setAngularVelocity(new Vector3f(0f,0f,1f)) Set the current rotational speed of the object
setLinearVelocity(new Vector3f(0f,0f,1f))  Set the current linear speed of this object
setWalkDirection(new Vector3f(0f,0f,0.1f)) Make a physical character walk (characters are locked to prevent falling over and use a simple physics simulation). Use setWalkDirection(Vector3f.ZERO) to stop a directional motion.
applyCentralForce(…) Move (push) the object once with a certain moment, expressed as a Vector3f.
applyForce(…) Move (push) the object once with a certain moment, expressed as a Vector3f. Optionally, you can specify where on the object the pushing force hits.
applyContinuousForce(…) Keep moving (pushing) the object with continuous force in one direction, expressed as a Vector3f. Optionally, you can specifiy where on the object the pushing force hits. You can applyContinuousForce(false) to stop the force.
applyTorque(…) Rotate (twist) the object once around its axes, expressed as a Vector3f.
applyContinuousTorque(…) Keep rotating (twisting) the object continuously around its axes, expressed as a Vector3f. You can applyContinuousTorque(false) to stop the rotation.
applyImpulse(…) An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball.
applyTorqueImpulse(…) An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball.
clearForces()Cancels out all forces (force, torque) etc and stops the motion.
+ +

+ +Note: It is possible to position physics nodes using setLocalTranslation(), e.g. to place them in their start position in the scene. However you must be very careful not to cause an “impossible state” where one physical object overlaps with another! Within the game, you typically use the setters shown here exclusively. +

+ +

+Physics also supports the following features: + +

+ + + + + + + + + + + + + + + + + + + + + + +
Method Property
setCollisionShape(collisionShape)Changes the collision shape.
setCollideWithGroups()
+ setCollisionGroup()
+ addCollideWithGroup(COLLISION_GROUP_01)
+ removeCollideWithGroup(COLLISION_GROUP_01)
Collision Groups are integer bit masks – enums are available in CollisionObject. All physics objects are by default in COLLISION_GROUP_01. Two objects collide when the collideWithGroups set of one contains the collisionGroup of the other.
setDamping(float, float)The first value is the linear threshold and the second the angular.
setAngularFactor(1f)Set the amount of rotation that will be applied. A value of zero will cancel all rotational force outcome.
setCcdSweptSphereRadius()?
setSleepingThreshold(float,float)Sets the sleeping thresholds wich define when the object gets deactivated to save ressources. Low values keep the object active when it barely moves. The first value is the linear threshold and the second the angular.
+ +
+ +

Responding to a PhysicsCollisionEvent

+
+ +

+ +If you do not implement the PhysicsCollisionListener interface, a collisions will just mean that forces are applied automatically. If you just want “Balls rolling, bricks falling” you do not need a listener. +

+ +

+If you want to respond to a collision event with a custom action however, then you need to implement the PhysicsCollisionListener interface. Typical actions triggered by collisions include: +

+
    +
  • increasing a counter (score points)
    +
  • +
  • decreasing a counter (health points)
    +
  • +
  • triggering an effect (explosion)
    +
  • +
  • playing a sound (explosion, ouch)
    +
  • +
  • … and countless more
    +
  • +
+ +
+ +

Overriding the Collision() Method

+
+ +

+ +To respond to the PhysicsCollisionEvent you have to override the collision() method. This gives you access to the event object. Mostly you will be interested in the identity of any two nodes that collided: event.getNodeA() and event.getNodeB(). +

+ +

+After you identify the colliding nodes, specify the action to trigger when this pair collides. Note that you cannot know which one will be Node A or Node B, you have to deal with either variant. +

+
    public void collision(PhysicsCollisionEvent event) {
+        if ( event.getNodeA().getName().equals("player") ) {
+            final Node node = event.getNodeA();
+            /** ... do something with the node ... */
+        } else if ( event.getNodeB().getName().equals("player") ) {
+            final Node node = event.getNodeB();
+            /** ... do something with the node ... */
+        }
+    }
+

+

Note that after the collision() method ends, the PhysicsCollisionEvent is cleared. You must get all objects and values you need within the collision() method. +

+

+ +
+ +

Reading Details From a PhysicsCollisionEvent

+
+ +

+ +The PhysicsCollisionEvent event gives you access to detailed information about the collision. You already know the event objects can identify which nodes collided, but it even knows how hard they collided: + +

+ + + + + + + + + + + + + + + + + + + + + + +
Method Purpose
getNodeA()
+ getNodeB()
The two participants in the collision. You cannot know in advance whether some node will be recorded as A or B, you always have to consider both cases.
getAppliedImpulse() A float value representing the collision impulse
getAppliedImpulseLateral1() A float value representing the lateral collision impulse
getAppliedImpulseLateral2() A float value representing the lateral collision impulse
getCombinedFriction() A float value representing the collision friction
getCombinedRestitution() A float value representing the collision restitution (bounciness)
+ +

+ +Note that after the collision method has been called the object is not valid anymore so you should copy any data you want to keep into local variables. +

+ +
+ +

Best Practices

+
+ +

+ +Do not overuse physics nodes. Although the physics nodes are put to “sleep” when they are not moved, creating a world solely out of dynamic physics nodes will quickly bring you to the limits of your computer's capabilities. +

+ +

+You can use normal non-physical Nodes in the same scene next to physical ones. Use the non-physical ones for non-solid things for which you do not want to detect collisions (ghost, foliage, plants, effects, …). This improves performance. +

+ +

+If you get weird behaviour, such as physical nodes jittering wildy and being ejected for no apparent reason, it usually means you have created an impossible state. Verify that none of the collision shapes overlap. This can happen when you create physical nodes in positions that are too close to other nodes; or if you position a physical node using setLocalTranslation() and it touches another node's collision shape. +

+ +

+For large static meshes like shooter levels or terrain its best to divide the mesh into multiple physics objects to allow the less cpu intense broadphase to filter out most collision items. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/post-processor_water.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/post-processor_water.html new file mode 100644 index 000000000..4460df575 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/post-processor_water.html @@ -0,0 +1,266 @@ + +

Rendering Water as Post-Process Effect

+
+ +

+ +This awesome water effect is highly configurable and can render any type of water. It is is based on published on gamedev.net. Here's a video: +

+ +

+ +

+ +
+ +

The Theory

+
+ +

+ +In this article the author uses the effect in a deferred rendering process, taking advantage of the pre-computed position buffer and back buffer (a texture representing the screen’s pixels position in view space, and a texture of the rendered scene). +

+ +

+After some calculation this allows to reconstruct the position in world space for each pixel on the screen. If a pixel is under a given water height, let’s render it as a blue pixel! Blue pixel? Not exactly, we want waves, we want ripples, we want foam, we want reflection and refraction. +

+ +

+The GameDev.net article describes how those effects are achieved, but the main idea is to generate waves from a height map, create ripples from a normal map, blend in the foam texture when the water depth is below a certain height, compute the refraction color with a clever color extinction algorithm, and then, display the reflection and specular effect by computing a Fresnel term (like in standard water effect). In addition this effect, allow to blend the water shore with the ground to avoid the hard edges effect of classic water effects based on grids or quads. +

+ +
+ +

How Did We Implement it in jME3?

+
+ +

+ +jME3 default behavior is to use a forward rendering process, so there is no position buffer rendered that we can take advantage of. But while rendering the main scene to a frame buffer in the FilterPostPorcessor, we can write the hardware depth buffer to a texture, with nearly no additional cost. +

+ +

+I won’t go into the details of this, but there are several ways of reconstructing the world space position of a pixel from the depth buffer. The computational cost is higher than just fetching the position form a position buffer, but the bandwidth and the memory required is a lot lower. +

+ +

+We have the rendered scene in a texture, and we can reconstruct the position in world space of each pixel… We’re good to go! +

+ +

+See also: by Nehon +

+ +
+ +

Sample Code

+
+ +

+ +There are two test cases in the jME3 repository: + +

+
    +
  • (ocean island)
    +
  • +
+
    +
  • (calm and muddy water pond)
    +
  • +
+ +
+ +

Using the Water Filter

+
+ +

+ +In the simpleInitApp() method, you attach your scene to the rootNode, typically a terrain with a sky. Remember to add a directional light, since the water relies on the light direction vector. The WaterFilter constrcutor expects a node with the scene attached that should be reflected in the water, and vector information from the light source's direction. +

+ +

+This is how you use the water filter post-processor code in your code: +

+
private FilterPostProcessor fpp;
+private WaterFilter water;
+private Vector3f lightDir = new Vector3f(-4.9f, -1.3f, 5.9f); // same as light source
+private float initialWaterHeight = 0.8f; // choose a value for your scene
+...
+ 
+public void simpleInitApp() {
+  ...
+  fpp = new FilterPostProcessor(assetManager);
+  water = new WaterFilter(rootNode, lightDir);
+  water.setWaterHeight(initialWaterHeight);
+  fpp.addFilter(water);
+  viewPort.addProcessor(fpp);
+  ...
+}
+

+Usually you make the water reflect everything attached to the rootNode. But you can also give a custom node (a subnode of the rootNode) to the WaterFilter constructor that has only a subset of scene nodes attached. This would be a relevant optimization if you have lots of nodes that are far away from the water, or covered, and will never be reflected. +

+ +
+ +

Optional: Waves

+
+ +

+ +If you want waves, set the water height in the update loop. We reuse the initialWaterHeight variable, and repeatedly reset the waterHeight value according to time. This causes the waves. +

+
private float time = 0.0f;
+private float waterHeight = 0.0f; 
+ 
+@Override
+public void simpleUpdate(float tpf) {
+  super.simpleUpdate(tpf);
+  time += tpf;
+  waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f;
+  water.setWaterHeight(initialWaterHeight + waterHeight);
+}
+
+ +

Optional: Water Wave and Color Effects

+
+ +

+ + +

+ +

+All these effects are optional. Every setter also has a getter. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Water method exampleEffects: Waves Default
water.setWaterHeight(-6);Use this waterheight method for causing waves.0.0f
water.setMaxAmplitude(0.3f);How high the highest waves are.1.0f
water.setWaveScale(0.008f);Sets the scale factor of the waves height map. The smaller the value, the bigger the waves! 0.005f
water.setWindDirection(new Vector2f(0,1))Sets the wind direction, which is the direction where the waves moveVector2f(0.0f, -1.0f)
water.setSpeed(0.7f);How fast the waves move. Set it to 0.0f for still water.1.0f
water.setHeightTexture( (Texture2D)
+ manager.loadTexture(“Textures/waveheight.png”) )
This height map describes the shape of the waves“Common/MatDefs/Water/Textures/heightmap.jpg”
water.setNormalTexture( (Texture2D)
+ manager.loadTexture(“Textures/wavenormals.png”) )
This normal map describes the shape of the waves“Common/MatDefs/Water/Textures/gradient_map.jpg”
water.setUseRipples(false);Switches the ripples effect on or off.true
water.setNormalScale(0.5f)Sets the normal scaling factors to apply to the normal map. The higher the value, the more small ripples will be visible on the waves.1.0f
+ + + + + + + + + + + + + + + + + + + + + + +
Water method example Effects: ColorDefault
water.setLightDirection(new Vector3f(-0.37f,-0.50f,-0.78f))Usually you set this to the same as the light source's direction. Use this to set the light direction if the sun is moving.Value given to WaterFilter() constructor.
water.setLightColor(ColorRGBA.White)Usually you set this to the same as the light source's color.RGBA.White
water.setWaterColor(ColorRGBA.Brown.mult(2.0f));Sets the main water color.greenish blue
+ Vector3f(0.0f,0.5f,0.5f,1.0f)
water.setDeepWaterColor(ColorRGBA.Brown);Sets the deep water color.dark blue
+ Vector3f(0.0f, 0.0f,0.2f,1.0f)
water.setWaterTransparency(0.2f);Sets how fast colors fade out. use this to control how clear (e.g. 0.05f) or muddy (0.2f) water is. 0.1f
water.setColorExtinction(new Vector3f(10f,20f,30f));Sets At what depth the refraction color extincts. The three values are RGB (red, green, blue) in this order. Play with these parameters to “muddy” the water.Vector3f(5f,20f,30f)
+ + + + + + + + + + +
Water method example Effects: ShoreDefault
water.setShoreHardness(1.0f);Sets how soft the transition between shore and water should be. High values mean a harder transition between shore and water.0.1f
water.setUseHQShoreline(false);Renders shoreline with better quality ?true
+ + + + + + + + + + + + + + + + +
Water method example Effects: FoamDefault
water.setUseFoam(false);Switches the white foam on or offtrue
water.setFoamHardness(0.5f)Sets how much the foam will blend with the shore to avoid a hard edged water plane.1.0f
water.setFoamExistence(new Vector3f(0.5f,5f,1.0f))The three values describe what depth foam starts to fade out, at what depth it is completely invisible, at what height foam for waves appears (+ waterHeight).Vector3f(0.45f,4.35f,1.0f)
water.setFoamTexture( (Texture2D)
+ manager.loadTexture(“Textures/foam.png”) )
This foam texture will be used with WrapMode.Repeat“Common/MatDefs/Water/Textures/foam.jpg”
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Water method example Effects: LightDefault
water.setSunScale(1f);Sets how big the sun should appear in the light's specular effect on the water.3.0f
water.setUseSpecular(false)Switches specular effect on or offtrue
water.setShininess(0.8f)Sets the shininess of the water reflections0.7f
water.setUseRefraction(true)Switches the refraction effect on or off.true
water.setRefractionConstant(0.2f);The lower the value, the less reflection can be seen on water. This is a constant related to the index of refraction (IOR) used to compute the fresnel term.0.3f
water.setRefractionStrength(-0.1)This value modifies the current Fresnel term. If you want to weaken reflections use bigger value. If you want to empasize them, use a value smaller than 0.0.0f
water.setReflectionMapSize(256)Sets the size of the reflection map. The higher, the better the quality, but the slower the effect.512
+ +
+ +

Sound Effects

+
+ +

+ +You should also add audio nodes with water sounds to complete the effect. +

+
AudioNode waves = new AudioNode(assetManager, "Sound/Environment/Ocean Waves.ogg", false);
+waves.setLooping(true);
+audioRenderer.playSource(waves);
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/pssm.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/pssm.png new file mode 100644 index 000000000..5d0eb1ad5 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/pssm.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html new file mode 100644 index 000000000..40e7eb028 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html @@ -0,0 +1,199 @@ + +

Ragdoll Physics

+
+ +

+ +The jMonkeyEngine3 has built-in support for via the com.jme3.bullet package. Physics are not only responsible for handing collisions, but they also make hinges and joints possible. One special example of physical joints are ragdoll physics, shown here. +

+ +
+ +

Sample Code

+
+
    +
  • (Tip: Click to pull the ragdoll up)
    +
  • +
+ +
+ +

Preparing the Physics Game

+
+
    +
  1. Create a SimpleApplication with a BulletAppState
    +
      +
    • This gives us a PhysicsSpace for PhysicControls
      +
    • +
    +
  2. +
  3. Add a physical floor (A box collision shape with mass zero)
    +
  4. +
+ +
+ +

Creating the Ragdoll

+
+ +

+ + +

+ +

+The ragdoll is a simple dummy that we build out of cylinder collision shapes. It has 11 limbs: shoulders, a body, and hips; plus 2 arms and 2 legs are made up of two limbs each. In your game, you replace the cylinders with your own limb models. +

+ +
+ +

Limbs

+
+ +

+Since we're just creating the ragdoll for this example, all the limbs have the same shape, and we can write a simple helper method to create them. The function returns a PhysicsNode with CollisionShape with the width, height, location, and rotation (vertical or horizontal) that we specify. We choose a CapsuleCollisionShape (a cylinder with rounded top and bottom) so the limbs collide smoothly against one another. +

+
private Node createLimb(float width, float height, Vector3f location, boolean rotate) {
+        int axis = rotate ? PhysicsSpace.AXIS_X : PhysicsSpace.AXIS_Y;
+        CapsuleCollisionShape shape = new CapsuleCollisionShape(width, height, axis);
+        Node node = new Node("Limb");
+        RigidBodyControl rigidBodyControl = new RigidBodyControl(shape, 1);
+        node.setLocalTranslation(location);
+        node.addControl(rigidBodyControl);
+        return node;
+}
+

+We use this helper method to initialize the 11 limbs. Look at the screenshot above for orientation. +

+
    +
  • All cylinders have the same diameter, 0.2f.
    +
  • +
  • We make the body and shoulders longer than the other limbs, 1.0f instead of 0.5f.
    +
  • +
  • We determine the coordinates for positioning the limbs to form a person.
    +
  • +
  • The shoulders and hips are vertical cylinders, this is why we set the rotation to true.
    +
  • +
+
Node shoulders = createLimb(0.2f, 1.0f, new Vector3f( 0.00f, 1.5f, 0), true);
+Node     uArmL = createLimb(0.2f, 0.5f, new Vector3f(-0.75f, 0.8f, 0), false);
+Node     uArmR = createLimb(0.2f, 0.5f, new Vector3f( 0.75f, 0.8f, 0), false);
+Node     lArmL = createLimb(0.2f, 0.5f, new Vector3f(-0.75f,-0.2f, 0), false);
+Node     lArmR = createLimb(0.2f, 0.5f, new Vector3f( 0.75f,-0.2f, 0), false);
+Node      body = createLimb(0.2f, 1.0f, new Vector3f( 0.00f, 0.5f, 0), false);
+Node      hips = createLimb(0.2f, 0.5f, new Vector3f( 0.00f,-0.5f, 0), true);
+Node     uLegL = createLimb(0.2f, 0.5f, new Vector3f(-0.25f,-1.2f, 0), false);
+Node     uLegR = createLimb(0.2f, 0.5f, new Vector3f( 0.25f,-1.2f, 0), false);
+Node     lLegL = createLimb(0.2f, 0.5f, new Vector3f(-0.25f,-2.2f, 0), false);
+Node     lLegR = createLimb(0.2f, 0.5f, new Vector3f( 0.25f,-2.2f, 0), false);
+

+We now have the outline of a person. But if we ran the application now, the individual limbs would fall down independently of one another – the ragdoll is still lacking joints. +

+ +
+ +

Joints

+
+ +

+ +As before, we write a small helper method. This time its purpose is to quickly join two limbs A and B at the connection point that we specify. +

+
    +
  • We convert A's and B's connectionPoint vector from world coordinate space to local coordinate space.
    +
  • +
  • We use a ConeJoint, a special joint that approximates the degree of freedom that limbs typically have. The ConeJoint constructor requires the two nodes, and the two local pivot coordinates that we just determined.
    +
  • +
  • We set the joints limits to allow swinging, but not twisting.
    +
  • +
+
private PhysicsJoint join(Node A, Node B, Vector3f connectionPoint) {
+        Vector3f pivotA = A.worldToLocal(connectionPoint, new Vector3f());
+        Vector3f pivotB = B.worldToLocal(connectionPoint, new Vector3f());
+        ConeJoint joint = new ConeJoint(A.getControl(RigidBodyControl.class),
+                                        B.getControl(RigidBodyControl.class), 
+                                        pivotA, pivotB);
+        joint.setLimit(1f, 1f, 0);
+        return joint;
+}
+

+We use the helper method to connect all limbs with joints where they belong, at one end of the limb. +

+
join(body,  shoulders, new Vector3f( 0.00f,  1.4f, 0));
+join(body,       hips, new Vector3f( 0.00f, -0.5f, 0));
+ 
+join(uArmL, shoulders, new Vector3f(-0.75f,  1.4f, 0));
+join(uArmR, shoulders, new Vector3f( 0.75f,  1.4f, 0));
+join(uArmL,     lArmL, new Vector3f(-0.75f,  0.4f, 0));
+join(uArmR,     lArmR, new Vector3f( 0.75f,  0.4f, 0));
+ 
+join(uLegL,      hips, new Vector3f(-0.25f, -0.5f, 0));
+join(uLegR,      hips, new Vector3f( 0.25f, -0.5f, 0));
+join(uLegL,     lLegL, new Vector3f(-0.25f, -1.7f, 0));
+join(uLegR,     lLegR, new Vector3f( 0.25f, -1.7f, 0));
+

+Now the ragdoll is connected. If we ran the app now, the doll would collapse, but the limbs would stay together. +

+ +
+ +

Attaching Everything to the Scene

+
+ +

+ +We create one (non-physical) Node named ragDoll, and attach all other nodes to it. +

+
ragDoll.attachChild(shoulders);
+ragDoll.attachChild(body);
+ragDoll.attachChild(hips);
+ragDoll.attachChild(uArmL);
+ragDoll.attachChild(uArmR);
+ragDoll.attachChild(lArmL);
+ragDoll.attachChild(lArmR);
+ragDoll.attachChild(uLegL);
+ragDoll.attachChild(uLegR);
+ragDoll.attachChild(lLegL);
+ragDoll.attachChild(lLegR);
+

+To use the ragdoll in a scene, we attach its main node to the rootNode, and to the PhysicsSpace. +

+
rootNode.attachChild(ragDoll);
+bulletAppState.getPhysicsSpace().addAll(ragDoll);
+
+ +

Applying Forces

+
+ +

+ +To pull the doll up, you could add an input handler that triggers the following action: +

+
Vector3f upforce = new Vector3f(0, 200, 0);
+shoulders.applyContinuousForce(true, upforce);
+

+We can use the action to pick the doll up and put it back on its feet, or what ever. Read more about Forces here. +

+ +
+ +

Detecting Collisions

+
+ +

+ +Read the Responding to a PhysicsCollisionEvent chapter in the general physics documentation on how to detect collisions. +

+ +
+ +

Best Practices

+
+ +

+ +If you are seeing weird behaviour in a ragdoll – such as exploding into pieces and then reassembling – check your collision shapes. Verify you did not position the limbs too close to one another when assmebling the ragdoll. You typically see physical nodes being ejected when their collision shapes intersect, which puts physics in an impossible state. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.png new file mode 100644 index 000000000..23c67ccdb Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shadow.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shadow.png new file mode 100644 index 000000000..73f601eb6 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shadow.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shape.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shape.html new file mode 100644 index 000000000..b05e4a368 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shape.html @@ -0,0 +1,62 @@ + +

Shapes

+
+ +

+ +The simplest type of Meshes are jME's default Shapes. You can use Shapes to build complex Geometries. Shapes are created without using the AssetManager. +

+ +

+3D shapes: +

+
    +
  • com.jme3.scene.shape.Sphere – A ball or elipsoid.
    +
  • +
  • com.jme3.scene.shape.Box – A cube or cuboid.
    +
  • +
  • com.jme3.scene.shape.Cylinder – A disk or pillar.
    +
  • +
  • com.jme3.scene.shape.Dome – Half a sphere.
    +
  • +
  • com.jme3.scene.shape.Torus – An single-holed torus (“donut”).
    +
  • +
  • com.jme3.scene.shape.PQTorus – A parameterized torus, also known as PQ torus. Looks like a .
    +
  • +
+ +

+ +Non-3D shapes: +

+
    +
  • com.jme3.scene.shape.Quad – A flat 2D rectangle (has two sides)
    +
  • +
  • com.jme3.scene.shape.Line – A 1D line (has a length)
    +
  • +
  • come.jme3.math.Ray – A 1D line (has length, direction, start point, but no end)
    +
  • +
+ +
+ +

Usage

+
+ +

+ +To add a shape to the scene: +

+
    +
  1. Create the base mesh shape
    +
  2. +
  3. Wrap it into a Geometry
    +
  4. +
  5. Attach the Geometry to the rootNode to make it visible.
    +
  6. +
+
Sphere sphereMesh = new Sphere(32, 32, 10, false, true);
+Geometry sphere = new Geometry("Sky", sphereMesh);
+rootNode.attachChild(sphere);
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/simplewater.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/simplewater.png new file mode 100644 index 000000000..a5af124f4 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/simplewater.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/sky.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/sky.html new file mode 100644 index 000000000..d31525abc --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/sky.html @@ -0,0 +1,100 @@ + +

How to add a Sky to your Scene

+
+ +

+ +
+ +

+ +

+Here is an example for how you add a static horizon (a background landscape and a sky) to a scene. +Having a discernable horizon with a suitable landscape (or space, or ocean, or whatever) in the background makes scenes look more realistic than just a single-colored “sky” background. +

+ +
+ +

Adding the Sky

+
+ +

+ +Adding a sky is extremely easy using the com.jme3.util.SkyFactory. +

+
rootNode.attachChild(SkyFactory.createSky(
+            assetManager, "Textures/Sky/Bright/BrightSky.dds", false));
+

+To add a sky you need to supply: +

+
    +
  1. The assetManager object to use
    +
  2. +
  3. A cube or sphere map texture of the sky
    +
  4. +
  5. Set the boolean to true if you are using a sphere map texture. For a cube map, use false.
    + Tip: Cube map is the default. You would know if you had created a sphere map.
    +
  6. +
+ +

+ +Internally, the SkyFactory calls the following methods: +

+
    +
  1. sky.setQueueBucket(Bucket.Sky); makes certain the sky is rendered in the right order, behind everything else.
    +
  2. +
  3. sky.setCullHint(Spatial.CullHint.Never); makes certain that the sky is never culled.
    +
  4. +
  5. The SkyFactory uses the internal jME3 material definition Sky.j3md. This Material definition works with sphere and cube maps.
    +
  6. +
+ +
+ +

Creating the Textures

+
+ +

+ +As the sky texture we use the sample BrightSky.dds file from jme3test-test-data. +

+ +

+How to create a sky textures? + +

+
    +
  • There are many tools out there that generate cube and sphere maps.
    + Examples for landscape texture generators are Terragen or Bryce.
    +
  • +
  • The actual texture size does not matter, as long as you add the Sky Geometry to the Sky bucket: Everything in the sky bucket will always be infinitely far away behind everything else, and never intersect with your scene.
    + Of course the higher the resolution, the better it will look. On the other hand, if the graphic is too big, it will slow the game down.
    +
  • +
  • A box or sphere map is the simplest solution. But you can use any Node as sky, even complex sets of geometries and quads with animated clouds, blinking stars, city skylines, etc.
    +
  • +
  • JME3 supports cube maps in PNG, JPG, or (compressed) DDS format.
    +
  • +
+ +

+ +Box or Sphere? +

+
    +
  • If you have access to cube map textures, then use a SkyBox
    +
      +
    • +
    • +
    +
  • +
  • If you have access to sphere map textures – specially projected sky images that fit inside a sphere – then you use a SkySphere or SkyDome.
    +
      +
    • +
    • +
    +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/spatial.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/spatial.html new file mode 100644 index 000000000..e885df6ed --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/spatial.html @@ -0,0 +1,102 @@ + +

Spatial

+
+ +

+ +This is an introduction to the concept of of Spatials, the elements of the 3D scene graph. The scene graph is a data structure that manages all objects in your 3D world. For example it keeps track of the 3D models that you load and position. When you extend a Java class from com.jme3.app.SimpleApplication, you inherit the scene graph and rootNode. +

+ +

+The main element of the scene graph is a Spatial called rootNode. All other Spatials are attached to the rootNode in a parent-child relationship. If you think you want to understand the scene graph better, please read Scenegraph for dummies first. +

+ +
+ +

Node versus Geometry

+
+ +

+ +A Spatial is either a Node or a Geometry. +

+ +

+ + +

+ + + + + + + + + + + + + + + + + + + + + + +
Spatials
Purpose: A Spatial is an abstract data structure that stores transformations (translation, rotation, scale) of elements of the scene graph. A Spatial can be saved and loaded using the AssetManager.
com.jme3.scene.Geometry com.jme3.scene.Node
Visibility: A Geometry represents a visible 3-D object in the scene graph. A Node is an invisible “handle” for a group of objects in the scene graph.
Purpose: Use Geometries to represent an object's looks: Every Geometry contains a polygon mesh and a material, specifying its shape, color, texture, and opacity/transparency.
+ You can attach a Geometry to an Node.
Use nodes to structure and group Geometries and other Nodes. Every Node is attached to parent node, and the node can have children attached to itself. When you transform a parent node, all its children are transformed as well.
Content: Transformations, mesh, material. Transformations. No mesh, no material.
Examples: A box, a sphere, player, a building, a piece of terrain, a vehicle, missiles, NPCs, etc… The rootNode, the guiNode, an audio node, a custom grouping node, etc…
+ +

+ +Important: You never create a Spatial with Spatial s = new Spatial(); – it's abstract. Instead you create (e.g. load) a Node or Geometry object, and cast it to Spatial. You use the Spatial type in methods that accept both Nodes and Geometries as arguments. +

+ +
+ +

Mesh

+
+ +

+ +The polygon Mesh inside a Geometry can be one of three things: + +

+
    +
  • Shapes: The simplest type of Meshes are jME's default Shapes such as cubes and spheres. You can use several Shapes to build complex Geometries. Shapes are built-in and can be created without using the AssetManager.
    +
  • +
  • 3D Models: 3D models and scenes are also made up of meshes, but are more complex than Shapes. You create Models and Scenes in external 3D Mesh Editors and export them as Ogre XML or Wavefront OBJ. Use the Asset Manager to load models into a your jME3 game.
    +
  • +
  • Custom Meshes: Advanced users can create Custom Meshes programmatically.
    +
  • +
+ +
+ +

How to Access a Named Sub-Mesh

+
+ +

+ +Often after you load a scene or model, you need to access a part of it as an individual Geometry in the scene graph. Maybe you want to swap a character's weapon, or you want to play a door-opening animation. First you need to know the unique name of the sub-mesh. + +

+
    +
  1. Open the model in a 3D mesh editor, or in the jMonkeyPlatform's viewer.
    +
  2. +
  3. Find out the existing names of sub-meshes in the model.
    +
  4. +
  5. Assign unique names to sub-meshes in the model if neccessary.
    +
  6. +
+ +

+ +In the following example, the Node house is the loaded model. The sub-meshes in the Node are called its children. The String, here door 12, is the name of the mesh that you are searching. +

+
Geometry submesh = (Geometry) houseScene.getChild("door 12");
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/swing_canvas.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/swing_canvas.html new file mode 100644 index 000000000..36afdeb5f --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/swing_canvas.html @@ -0,0 +1,160 @@ + +

JME3 Canvas in a Swing GUI

+
+ +

+ +3D games are typically played full-screen, or in a window that takes over the mouse and all inputs. However it is also possible to embed a jME 3 canvas in a standard Swing application. +

+ +

+This can be useful when you create some sort of interactive 3D viewer with a user interface that is more complex than just a HUD: For instance an interactive scientific demo, a level editor, or a game character designer. + +

+
    +
  • Advantages:
    +
      +
    • You can use Swing components (frame, panels, menus, controls) in your jME3 game.
      +
    • +
    • The NetBeans GUI builder is compatible with the jMonkeyEngine; you can use it it to lay out the Swing GUI frame, and then add() the jME canvas into it. Install the GUI builder via Tools → Plugins → Available Plugins.
      +
    • +
    +
  • +
  • Disadvantages:
    +
      +
    • You cannot use SimpleApplication's default mouse capturing for camera navigation, but have to come up with a custom solution.
      +
    • +
    +
  • +
+ +

+ +Here is the full code sample, contributed by pgi. +

+ +
+ +

Extending SimpleApplication

+
+ +

+ +You start out just the same as for any jME3 game: The base application, here SwingCanvasTest, extends com.jme3.app.SimpleApplication. As usual, you use simpleInitApp() to initialize the scene, and simpleUpdate() as event loop. +

+ +

+The camera's default behaviour in SimpleApplication is to capture the mouse, which doesn't make sense in a Swing window. You have to deactivate and replace this behaviour by flyCam.setDragToRotate(true); when you initialize the application: +

+
public void simpleInitApp() {
+  // activate windowed input behaviour
+  flyCam.setDragToRotate(true);
+ 
+  // Set up inputs and load your scene as usual
+  ...
+}
+

+In short: The first thing that is different is the main() method. We don't call start() on the SwingCanvasTest object as usual. Instead we create a Runnable() that creates and opens a standard Swing jFrame. In the runnable, we also create our SwingCanvasTest game with special settings, create a Canvas for it, and add that to the jFrame. Then we call startCanvas(). +

+ +
+ +

Main() and Runnable()

+
+ +

+ +The Swing isn't thread-save and doesn't allow us to keep the jME3 canvas up-to-date. This is why we create a runnable for the jME canvas and queue it in the AWT event thread, so it can be invoked “later” in the loop, when Swing is ready with updating its own stuff. +

+ +

+In the SwingCanvasTest's main() method, create a queued runnable(). It will contain the jME canvas and the Swing frame. +

+
  public static void main(String[] args) {
+    java.awt.Runnable() {
+      public void run() {
+         // ... see below ...
+      }
+    });
+  }
+
+ +

Creating the Canvas

+
+ +

+ +Here in the run() method, we start the jME application, create its canvas, create a Swing frame, and add everything together. +

+ +

+Specify the com.jme3.system.AppSettings so jME knows the size of the Swing panel that we put it into. The application will not ask the user for display settings, you have to specify them in advance. +

+
AppSettings settings = new AppSettings(true);
+settings.setWidth(640);
+settings.setHeight(480);
+

+We create our canvas application SwingCanvasTest, and give it the settings. We manually create a canvas for this game and configure the com.jme3.system.JmeCanvasContext. The method setSystemListener() makes sure that the listener receives events relating to context creation, update, and destroy. +

+
SwingCanvasTest canvasApplication = new SwingCanvasTest();
+canvasApplication.setSettings(settings);
+canvasApplication.createCanvas(); // create canvas!
+JmeCanvasContext ctx = (JmeCanvasContext) canvasApplication.getContext();
+ctx.setSystemListener(canvasApplication);
+Dimension(640, 480);
+ctx.getCanvas().setPreferredSize(dim);
+

+Note that we have not called start() on the application, as we would usually do in the main() method. We will call startCanvas() later instead. +

+ +
+ +

Creating the Swing Frame

+
+ +

+ +Inside the run() method, you create the Swing window as you would usually do. Create an empty jFrame and add() components to it, or create a custom jFrame object in another class file (for example, by using the NetBeans GUI builder) and create an instance of it here. +Which ever you do, let's call the jFrame window. +

+
JFrame("Swing Application");
+window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+

+We create a standard JPanel inside the JFrame. Give it any Layout you wish – here we use a simple Flow Layout. Where the code sample says “Some Swing Component”, this is where you add your buttons and controls. +

+ +

+The important step is to add() the canvas component into the panel, like all the other Swing components. +

+
FlowLayout()); // a panel
+// add all your Swing components ...
+panel.add(new JButton("Some Swing Component")); 
+...
+// add the JME canvas
+panel.add(ctx.getCanvas());
+

+OK, the jFrame and the panel are ready. We add the panel into the jFrame, and pack everything together. Set the window's visibility to true make it appear. +

+
window.add(panel);
+window.pack();
+window.setVisible(true);
+

+Remember that we haven't called start() on the jME appliation yet? For the canvas, there is a special startCanvas() method that you must call now: +

+
canvasApplication.startCanvas();
+

+Clean, build, and run! +

+ +
+ +

Navigation

+
+ +

+ +Remember, to navigate in the scene, click and drag (!) the mouse, or press the WASD keys. Depending on your game you may even want to define custom inputs to handle navigation in this untypical environment. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tank_diffuse_ss.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tank_diffuse_ss.png new file mode 100644 index 000000000..ebe5aaae1 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tank_diffuse_ss.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tank_glow_map_ss.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tank_glow_map_ss.png new file mode 100644 index 000000000..4a16d83a5 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tank_glow_map_ss.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tanlglow1.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tanlglow1.png new file mode 100644 index 000000000..3c12587fb Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/tanlglow1.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/terrain.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/terrain.html new file mode 100644 index 000000000..40bb5692e --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/terrain.html @@ -0,0 +1,172 @@ + +

TerraMonkey - jME3's Terrain System

+
+ +

+ +The goal of TerraMonkey is to provide a base implementation that will be usable for 80% of people's goals, while providing tools and a good foundation for the other 20% to build off of. +

+ +
+ +

Overview

+
+ +

+ +TerraMonkey is a GeoMipMapping quad tree of terrain tiles that supports real time editing and texture splatting. That's a mouth full! Lets look at each part: +

+
    +
  • GeoMipMapping: a method of changing the level of detail (LOD) of geometry tiles based on how far away they are from the camera. Between the edges of two tiles, it will seam those edges together so you don't get gaps or holes. For an in-depth read on how it works, here is a pdf .
    +
  • +
  • Quad Tree: The entire terrain structure is made up of TerrainPatches (these hold the actual meshes) as leaves in a quad tree (TerrainQuad). TerrainQuads are subdivided by 4 until they reach minimum size, then a TerrainPatch is created, and that is where the actual geometry mesh lives. This allows for fast culling of the terrain that you can't see.
    +
  • +
  • Splatting: The ability to paint multiple textures onto your terrain. What differs here from JME2 is that this is all done in a shader, no more render passes. So it performs much faster.
    +
  • +
  • Real-time editing: TerraMonkey will be editable in JMonkeyPlatform, and you will be able to do it in real time: raising and lowering terrain.
    +
  • +
+ +
+ +

Current Features:

+
+
    +
  • Support for up to 3 splat textures.
    +
  • +
  • GeoMipMapping
    +
  • +
  • can be supplied a heightmap
    +
  • +
+ +
+ +

Planned Features:

+
+
    +
  • jMonkeyPlatform terrain editor
    +
  • +
  • Support for up to 16 splat textures.
    +
  • +
  • Hydraulic erosion and procedural texture generation
    +
  • +
  • Streaming terrain (ie. “infinite” terrain)
    +
  • +
  • Holes: caves, cliffs
    +
  • +
+ +
+ +

Geo Mip Mapping

+
+ +

+You have seen GeoMipMapping implemented in games before. This is where the farther away terrain has fewer polygons, and as you move closer, more polygons fill in. The whole terrain is divided into a grid of patches, and each one has its own LOD. The GeoMipMapping algorithm will look at each patch, and its neighbours, to determine how to render the geometry. It will seam the edges between two patches with different LOD. +This often leads to “popping” where you see the terrain switch from one LOD to another. TerraMonkey has been designed so you can swap out different LOD calculation algorithms based on what will look best for your game. +You can do this with the LodCalculator interface. +GeoMipMapping in TerraMonkey has been split into several parts: the terrain quad tree, and the LODGeomap. The geomap deals with the actual LOD and seaming algorithm. So if you want a different data structure for your terrain system, you can re-use this piece of code. +The quad tree (TerrainQuad and TerrainPatch) provide a means to organize the LODGeomaps, notify them of their neighbour's LOD change, and to update the geometry when the LOD does change. +To change the LOD it does this by changing the index buffer of the triangle strip, so the whole geometry doesn't have to be re-loaded onto the video card. +

+ +

+If you are eager, you can read up more detail how GeoMipMapping works here: +

+ +
+ +

Terrain Quad Tree

+
+ +

+TerraMonkey is a quad tree. Each node is a TerrainQuad, and each leaf is a TerrainPatch. A TerrainQuad has either 4 child TerrainQuads, or 4 child TerrainPatches. The TerrainPatch holds the actual mesh geometry. This structure is almost exactly the same as JME2's TerrainPage system. Except now each leaf has a reference to its neighbours, so it doesn't ever have to traverse the tree to get them. +

+ +
+ +

Texture Splatting

+
+ +

+ +The default material for TerraMonkey is Terrain.j3md. This material combines an alphamap with several textures to produce the final texture. +Right now there is support for only 3 textures and an alpha map. This is in place until we finish the terrain editor in JMP, and then the texture support will be 16 textures. +It is only 3 right now so you can hand-paint them in a drawing program, like Photoshop, setting each splat texture in either Red, Green, or Blue. The test case has an example texture to show you how this works. +

+ +

+Along with getting more splat texture support, we will be adding in lighting and normal mapping support. The normal mapping isn't fully planned out yet. We need to decide how we are going to handle a normal map for each texture that is passed in. That could generate some very odd effects. +Thoughts, ideas, and recommendations are appreciated! +

+ +
+ +

Code Sample

+
+ +

+First, we load our textures and the heightmap texture for the terrain +

+
// Create material from Terrain Material Definition
+matRock = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md");
+// Load alpha map (for splat textures)
+matRock.setTexture("m_Alpha", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
+// load heightmap image (for the terrain heightmap)
+Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
+ 
+// load grass texture
+Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
+grass.setWrap(WrapMode.Repeat);
+matRock.setTexture("m_Tex1", grass);
+matRock.setFloat("m_Tex1Scale", 64f);
+ 
+// load dirt texture
+Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
+dirt.setWrap(WrapMode.Repeat);
+matRock.setTexture("m_Tex2", dirt);
+matRock.setFloat("m_Tex2Scale", 32f);
+ 
+// load rock texture
+Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
+rock.setWrap(WrapMode.Repeat);
+matRock.setTexture("m_Tex3", rock);
+matRock.setFloat("m_Tex3Scale", 128f);
+

+We create the heightmap from the heightMapImage. +

+
AbstractHeightMap heightmap = null;
+heightmap = new ImageBasedHeightMap(
+    ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 1f);
+heightmap.load();
+

+ +Next we create the actual terrain. +

+
    +
  • The terrain tiles are 65×65.
    +
  • +
  • The total size of the terrain is 513×513, but it can easily be up to 1025×1025.
    +
  • +
  • It uses the heightmap to generate the height values.
    +
  • +
+
terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
+terrain.setMaterial(matRock);
+terrain.setModelBound(new BoundingBox());
+terrain.updateModelBound();
+terrain.setLocalScale(2f, 1f, 2f); // scale to make it less steep
+ 
+List<Camera> cameras = new ArrayList<Camera>();
+cameras.add(getCamera());
+TerrainLodControl control = new TerrainLodControl(terrain, cameras);
+terrain.addControl(control);
+ 
+rootNode.attachChild(terrain);
+

+PS: As an alternative to an image-based height map, you can also generate a Hill hightmap: +

+
heightmap = new HillHeightMap(1025, 1000, 50, 100, (byte) 3);
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/toon-dino.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/toon-dino.png new file mode 100644 index 000000000..fa28e4ae6 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/toon-dino.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/update_loop.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/update_loop.html new file mode 100644 index 000000000..f04428657 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/update_loop.html @@ -0,0 +1,76 @@ + +

Update Loop

+
+ +

+ +Extending your application from com.jme3.app.SimpleApplication provides you with an update loop. This is where you implement your game logic (game mechanics). +

+ +

+Examples: Here you remote-control NPCs (computer controlled characters), generate game events, and respond to user input. + +

+
    +
  1. Initialization (simpleInit())
    +
  2. +
  3. If exit is requested, then cleanup and destroy
    +
  4. +
  5. Input handling (listeners)
    +
  6. +
  7. Update game state
    +
      +
    1. +
    2. +
    3. User update (simpleUpdate() method)
      +
    4. +
    5. Entity logical update (Custom Controls)
      +
    6. +
    +
  8. +
  9. render
    +
      +
    1. +
    2. +
    3. Scene rendering
      +
    4. +
    5. User rendering (simpleRender() method)
      +
    6. +
    +
  10. +
  11. Repeat (goto 2)
    +
  12. +
+ +
+ +

Usage

+
+ +

+ +Use… +

+
    +
  • Application States to implement global game mechanics
    + Example: Physics
    +
  • +
  • Custom Controls to implement entity behavior
    + Example: Enemy AI
    +
  • +
  • simpleUpdate() to implement the rest, or for testing during development.
    +
  • +
+ + +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/vehicles.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/vehicles.html new file mode 100644 index 000000000..279e6af5e --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/vehicles.html @@ -0,0 +1,333 @@ + +

Controlling a Physical Vehicle

+
+ +

+ +For physical vehicles, jME's uses the jBullet ray-cast vehicle. In this vehicle implementation, the physical chassis 'floats' along on four non-physical vertical rays. +

+ +

+Internally, each wheel casts a ray down, and using the ray's intersection point, jBullet calculates the suspension length, and the suspension force. The suspension force is applied to the chassis, keeping it from hitting the ground. The friction force is calculated for each wheel where the ray intersects with the ground. Friction is applied as a sideways and forwards force. 1) +

+ +

+This article shows how you use this vehicle implementation in a jME3 application. +

+ +

+ +

+ +
+ +

Sample Code

+
+ +

+ +Full code samples are here: + +

+
    +
  • +
  • +
  • +
  • +
+ +
+ +

Overview of this Physics Application

+
+ +

+ +The goal is to create a physical vehicle with wheels that can be steered and that interacts (collides with) with the floor and obstacles. + +

+
    +
  1. Create a SimpleApplication with a BulletAppState
    +
      +
    • This gives us a PhysicsSpace for PhysicsNodes
      +
    • +
    +
  2. +
  3. Create a VehicleControl + CompoundCollisionShape for the physical vehicle behaviour
    +
      +
    1. Set physical properties of the vehicle, such as suspension.
      +
    2. +
    +
  4. +
  5. Create a VehicleNode for the car model
    +
      +
    1. Create a box plus 4 cylinders as wheels (using vehicle.addWheel()).
      +
    2. +
    3. Add the VehicleControl behaviour to the VehicleNode geometry.
      +
    4. +
    +
  6. +
  7. Create a RigidBodyControl and CollisionShape for the floor
    +
  8. +
  9. Map key triggers and add input listeners
    +
      +
    • Navigational commands Left, Right, Foward, Brake.
      +
    • +
    +
  10. +
  11. Define the steering actions to be triggered by the key events.
    +
      +
    • vehicle.steer()
      +
    • +
    • vehicle.accelerate()
      +
    • +
    • vehicle.brake()
      +
    • +
    +
  12. +
+ +
+ +

Creating the Vehicle Chassis

+
+ +

+ +The vehicle that we create here in the example is just a “box on wheels”, a basic vehicle shape that you can replace with a fancy car model, as demonstrated in . +

+ +

+Every physical object must have a collision shape, that we prepare first. For the vehicle, we choose a compound collision shape that is made up of a box-shaped body of the right size for the vehicle. We will add the wheels later. +

+
CompoundCollisionShape compoundShape = new CompoundCollisionShape();
+BoxCollisionShape box = new BoxCollisionShape(new Vector3f(1.2f, 0.5f, 2.4f));
+

+Best Practice: We attach the BoxCollisionShape (the vehicle body) to the CompoundCollisionShape at a Vector of (0,1,0): This shifts the effective center of mass of the BoxCollisionShape downwards to 0,-1,0 and makes a moving vehicle more stable! +

+
compoundShape.addChildShape(box, new Vector3f(0, 1, 0));
+

+Any kind of geometry can make up the visible part of the vehicle, here we use a wireframe box. We create a node that we use to group the geometry. +

+
        Node vehicleNode=new Node("vehicleNode");
+        vehicle = new VehicleControl(compoundShape, 400);
+        vehicleNode.addControl(vehicle);
+

+We initialize the Vehicle Control with the compound shape, and set its mass to a heavy value, 400f. The Vehicle Control represents the car's physical behaviour. +

+
vehicle = new VehicleControl(compoundShape, 400);
+

+Finally we add the behaviour (VehicleControl) to the visible Geometry (node). +

+
vehicleNode.addControl(vehicle);
+

+We configure the physical properties of the vehicle's suspension: Compresion, Damping, Stiffness, and MaxSuspenionForce. Picking workable values for the wheel suspension can be tricky – for background info have a look at these . For now, let's work with the following values: +

+
        float stiffness = 60.0f;//200=f1 car
+        float compValue = .3f; //(should be lower than damp)
+        float dampValue = .4f;
+        vehicle.setSuspensionCompression(compValue * 2.0f * FastMath.sqrt(stiffness));
+        vehicle.setSuspensionDamping(dampValue * 2.0f * FastMath.sqrt(stiffness));
+        vehicle.setSuspensionStiffness(stiffness);
+        vehicle.setMaxSuspensionForce(10000.0f);
+

+We now have a node vehicleNode with a visible “car” geometry, which acts like a vehicle. One thing that's missing are wheels. +

+ +
+ +

Adding the Wheels

+
+ +

+ +We create four wheel Geometries and add them to the vehicle. Our wheel geometries are simple, non-physical discs (flat Cylinders), they are just visual decorations. Note that the physical wheel behaviour (the com.jme3.bullet.objects.VehicleWheel objects) is created internally by the vehicle.addWheel() method. +

+ +

+The addWheel() method sets following properties: +

+
    +
  • Vector3f connectionPoint – Coordinate where the suspension connects to the chassis (internally, this is where the Ray is casted downwards).
    +
  • +
  • Vector3f direction – Wheel direction is typically a (0,-1,0) vector.
    +
  • +
  • Vector3f axle – Axle direction is typically a (-1,0,0) vector.
    +
  • +
  • float suspensionRestLength – Suspension rest length in world units
    +
  • +
  • float wheelRadius – Wheel radius in world units
    +
  • +
  • boolean isFrontWheel – Whether this wheel is one of the steering wheels.
    + Front wheels are the ones that rotate visibly when the vehicle turns.
    +
  • +
+ +

+ +We initialize a few variables that we will reuse when we add the four wheels. yOff, etc, are the particular wheel offsets for our small vehicle model. +

+
Vector3f wheelDirection = new Vector3f(0, -1, 0);
+Vector3f wheelAxle = new Vector3f(-1, 0, 0);
+float radius = 0.5f;
+float restLength = 0.3f;
+float yOff = 0.5f;
+float xOff = 1f;
+float zOff = 2f;
+

+We create a Cylinder mesh shape that we use to create the four visible wheel geometries. +

+
Cylinder wheelMesh = new Cylinder(16, 16, radius, radius * 0.6f, true);
+

+For each wheel, we create a Node and a Geometry. We attach the Cylinder Geometry to the Node. We rotate the wheel by 90° around the Y axis. We set a material to make it visible. Finally we add the wheel (plus its properties) to the vehicle. +

+
Node node1 = new Node("wheel 1 node");
+Geometry wheels1 = new Geometry("wheel 1", wheelMesh);
+node1.attachChild(wheels1);
+wheels1.rotate(0, FastMath.HALF_PI, 0);
+wheels1.setMaterial(mat);
+ 
+vehicle.addWheel(node1, new Vector3f(-xOff, yOff, zOff),
+                 wheelDirection, wheelAxle, restLength, radius, true);
+

+The three next wheels are created in the same fashion, only the offsets are different. Remember to set the Boolean parameter correctly to indicate whether it's a front wheel. +

+
...
+vehicle.addWheel(node2, new Vector3f(xOff, yOff, zOff),
+                wheelDirection, wheelAxle, restLength, radius, true);
+...
+vehicle.addWheel(node3, new Vector3f(-xOff, yOff, -zOff),
+                wheelDirection, wheelAxle, restLength, radius, false);
+...
+vehicle.addWheel(node4, new Vector3f(xOff, yOff, -zOff),
+                wheelDirection, wheelAxle, restLength, radius, false);
+

+Attach the wheel Nodes to the vehicle Node to group them, so they move together. +

+
vehicleNode.attachChild(node1);
+vehicleNode.attachChild(node2);
+vehicleNode.attachChild(node3);
+vehicleNode.attachChild(node4);
+

+As always, attach the vehicle Node to the rootNode to make it visible, and add the Vehicle Control to the PhysicsSpace to make the car physical. +

+
rootNode.attachChild(vehicleNode);
+getPhysicsSpace().add(vehicle);
+

+Not shown here is that we also created a Material mat. +

+ +
+ +

Steering the Vehicle

+
+ +

+ +Not shown here is the standard way how we map the input keys to actions (see full code sample). Also refer to Input Handling). +

+ +

+In the ActionListener, we implement the actions that control the vehicle's direction and speed. For the four directions (accelerate=up, brake=down, left, right), we specify how we want the vehicle to move. + +

+
    +
  • The braking action is pretty straightforward:
    + vehicle.brake(brakeForce)
    +
  • +
  • For left and right turns, we add a constant to steeringValue when the key is pressed, and subtract it when the key is released.
    + vehicle.steer(steeringValue);
    +
  • +
  • For acceleration we add a constant to accelerationValue when the key is pressed, and substract it when the key is released.
    + vehicle.accelerate(accelerationValue);
    +
  • +
  • Because we can and it's fun, we also add a turbo booster that makes the vehicle jump when you press the assigned key (spacebar).
    + vehicle.applyImpulse(jumpForce, Vector3f.ZERO);
    +
  • +
+
public void onAction(String binding, boolean value, float tpf) {
+        if (binding.equals("Lefts")) {
+            if (value) {
+                steeringValue += .5f;
+            } else {
+                steeringValue += -.5f;
+            }
+            vehicle.steer(steeringValue);
+        } else if (binding.equals("Rights")) {
+            if (value) {
+                steeringValue += -.5f;
+            } else {
+                steeringValue += .5f;
+            }
+            vehicle.steer(steeringValue);
+        } else if (binding.equals("Ups")) {
+            if (value) {
+                accelerationValue += accelerationForce;
+            } else {
+                accelerationValue -= accelerationForce;
+            }
+            vehicle.accelerate(accelerationValue);
+        } else if (binding.equals("Downs")) {
+            if (value) {
+                vehicle.brake(brakeForce);
+            } else {
+                vehicle.brake(0f);
+            }
+        } else if (binding.equals("Space")) {
+            if (value) {
+                vehicle.applyImpulse(jumpForce, Vector3f.ZERO);
+            }
+        } else if (binding.equals("Reset")) {
+            if (value) {
+                System.out.println("Reset");
+                vehicle.setPhysicsLocation(Vector3f.ZERO);
+                vehicle.setPhysicsRotation(new Matrix3f());
+                vehicle.setLinearVelocity(Vector3f.ZERO);
+                vehicle.setAngularVelocity(Vector3f.ZERO);
+                vehicle.resetSuspension();
+            } else {
+            }
+        }
+    }
+

+For your reference, this is how we initialized the constants for this example: +

+
private final float accelerationForce = 1000.0f;
+private final float brakeForce = 100.0f;
+private float steeringValue = 0;
+private float accelerationValue = 0;
+private Vector3f jumpForce = new Vector3f(0, 3000, 0);
+

+Remember, the standard input listener code that maps the actions to keys can be found in the code samples. +

+ +
+ +

Detecting Collisions

+
+ +

+ +Read the Responding to a PhysicsCollisionEvent chapter in the general physics documentation on how to detect collisions. You would do this if you want to react to collisions with custom events, such as adding points or substracting health. +

+ +
+ +

Best Practices

+
+ +

+ +This example shows a very simple but functional vehicle. For a game you would implement steering behaviour and acceleration with values that are typical for the type of vehicle that you want to simulate. Instead of a box, you load a chassis model. You can consider using an AnalogListener to respond to key events in a more sophisticated way. +

+ +

+For a more advanced example, look at . +

+ +
+
+
1) +
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/walking_character.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/walking_character.html new file mode 100644 index 000000000..4d1716279 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/walking_character.html @@ -0,0 +1,137 @@ + +

Walking Character

+
+ +

+ +Work in progress. +

+ +

+In other code samples we have seen how to create collidable landscapes and walk around in a first-person perspective, by enclosing the camera with a collision shape. +

+ +

+Many games however require a third-person perspective of the character. If you load a character model, create a PhysicsControl for it, and use forces to push it around, you may not get the desired effect: Phyical objects often fall over when pushed, and that is not what you expect of a walking character. +

+ +

+This is why jME3 offers a special CharacterControl to implement walking characters. +

+ +
+ +

Sample Code

+
+ +

+ +The full code sample can be found here: +

+
    +
  • (third-person view)
    +
  • +
  • (third-person view)
    +
  • +
  • (first-person view)
    +
  • +
+ +
+ +

Overview of this Physics Application

+
+
    +
  1. Create a SimpleApplication with a BulletAppState
    +
      +
    • This gives us a Physics Space
      +
    • +
    +
  2. +
  3. Load any physical game level model, terrain, or floor
    +
  4. +
  5. Load an animated character model
    +
  6. +
  7. Set up animation channel and controller
    +
  8. +
  9. Add a CharacterControl to the model
    +
  10. +
+ +
+ +

Creating the Character

+
+
    +
  1. Initialze physical character behaviour, including collision shape
    +
      +
    1. Create CapsuleCollisionShape of the right size for the model.
      +
        +
      • A Capsule is a cylinder with rounded top and bottom: A good collision shape for a character since it reduces the risk of getting stuck on obstacles.
        +
      • +
      +
    2. +
    3. Create a CharacterControl from the collision shape
      +
    4. +
    +
  2. +
  3. Load the visible character model, and add the physical behaviour to it
    +
      +
    1. Load an animated model (e.g. “Models/Oto/Oto.mesh.xml”).
      +
    2. +
    3. Add the CharacterControl to the character model.
      +
    4. +
    +
  4. +
  5. Make character visible and physical
    +
      +
    1. Attach the model to the rootNode to make it appear in the scene.
      +
    2. +
    3. Add the CharacterControl to the PhysicsSpace to make it physical.
      +
    4. +
    +
  6. +
+
// initialze physical character behaviour, including collision shape
+CapsuleCollisionShape capsule = new CapsuleCollisionShape(3f, 4f);
+CharacterControl character = new CharacterControl(capsule, 0.01f);
+// load the visible character model and add the physical behaviour to it
+Node model = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
+model.addControl(character);
+// Make character visible and physical
+rootNode.attachChild(model);      // make it visible
+getPhysicsSpace().add(character); // make it physical
+
+ +

Setting Up the Animation Controller

+
+ +

+ +We create two AninChannels, for example one for walking, one for shooting. The shootingChannel only controls one arm, while the walking channels controls the whole animation. +

+
AnimControl animationControl = model.getControl(AnimControl.class);
+animationControl.addListener(this);
+ 
+AnimChannel animationChannel = animationControl.createChannel();
+AnimChannel shootingChannel = animationControl.createChannel();
+ 
+shootingChannel.addBone(animationControl.getSkeleton().getBone("uparm.right"));
+shootingChannel.addBone(animationControl.getSkeleton().getBone("arm.right"));
+shootingChannel.addBone(animationControl.getSkeleton().getBone("hand.right"));
+

+The extra shooting channel exists so the character can lift an arm to shoot and walk at the same time. +

+ +
+ +

Walking

+
+ +

+Work in progress (this is being updated for the new physics and chase cam.) + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post-muddy.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post-muddy.png new file mode 100644 index 000000000..58423c3ba Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post-muddy.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post.png new file mode 100644 index 000000000..473fa70b3 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.html new file mode 100644 index 000000000..7647717e9 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.html @@ -0,0 +1,209 @@ + +

SeaMonkey - jME3 Water System

+
+ +

+ +DRAFT +

+ +

+Here is some background info for JME3's frist water implementation, nicknamed SeaMonkey: +

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
+ +

+ + +

+ +
+ +

SimpleWaterProcessor

+
+ +

+ +A JME3 scene with water uses a com.jme3.water.SimpleWaterProcessor (which implements the SceneProcessor interface). +

+ +

+To achieve a water effect, JME3 uses shaders and a special material, Common/MatDefs/Water/SimpleWater.j3md. The water surface is a quad, and we use normal map and dU/dV map texturing to simulate the waves. + +

+
    +
  1. Every frame, we render to three texture maps:
    +
      +
    • For the water surface (reflection), we take a snapshot of the environment, flip it upside down, and clip it to the visible water surface. Note that we do not actually use a “water texture” color map: The “texture” of the water is solely a distorted reflection.
      +
    • +
    • For the “wavy” distortion (refraction), we use the derivative of a normal map, a dU/dV map.
      +
    • +
    • For the fogginess of water (depth) we use a depth map from the terrains z-buffer.
      +
    • +
    +
  2. +
  3. In the shaders, we add all of the texture maps together.
    +
      +
    • For the “bumpy” displacement of the waves, we use a normal map and a du/dv map that are shifted against each other over time to create the wave effect.
      +
    • +
    • For the light reflection vectors on the water surface, we use the Fresnel formula, together with normal vectors.
      +
    • +
    • We add specular lighting.
      +
    • +
    +
  4. +
  5. (For the underwater caustics effect, we use splatted textures. – TODO)
    +
  6. +
+ +
+ +

Usage

+
+ +

+ + + +

+
    +
  1. Create a mainScene Node
    +
      +
    1. Attach the mainScene Node to the rootNode
      +
    2. +
    +
  2. +
  3. Load your scene Spatial
    +
      +
    1. Add a light source to the scene Spatial
      +
    2. +
    3. Attach the scene Spatial to the mainScene Node
      +
    4. +
    +
  4. +
  5. Load your sky Geometry
    +
      +
    1. Attach the sky Geometry to the mainScene Node
      +
    2. +
    +
  6. +
  7. Create the SimpleWaterProcessor waterProcessor
    +
      +
    1. Set the processor's ReflectionScene to the mainScene Spatial (!)
      +
    2. +
    3. Set the processor's Plane to where you want your water surface to be
      +
    4. +
    5. Set the processor's WaterDepth, DistortionScale, and WaveSpeed
      +
    6. +
    7. Attach the processor to the viewPort
      +
    8. +
    +
  8. +
  9. Create a Quad quad
    +
      +
    1. Set the quad's TextureCoordinates to specify the size of the waves
      +
    2. +
    +
  10. +
  11. Create a water Geometry from the Quad
    +
      +
    1. Set the water's translation and rotation (same Y value as Plane above!)
      +
    2. +
    3. Set the water's material to the processor's output material
      +
    4. +
    5. Attach the water Geometry to the rootNode. (Not to the mainScene!)
      +
    6. +
    +
  12. +
+ +
+ +

Sample Code

+
+ +

+ +The sample code can be found in jme3/src/jme3test/water/TestSimpleWater.java and jme3/src/jme3test/water/TestSceneWater.java. +

+ +

+Here is the most important part of the code: +

+
// we create a water processor
+SimpleWaterProcessor waterProcessor = new SimpleWaterProcessor(assetManager);
+waterProcessor.setReflectionScene(mainScene);
+ 
+// we set the water plane
+Vector3f waterLocation=new Vector3f(0,-6,0);
+waterProcessor.setPlane(new Plane(Vector3f.UNIT_Y, waterLocation.dot(Vector3f.UNIT_Y)));
+viewPort.addProcessor(waterProcessor);
+ 
+// we set wave properties
+waterProcessor.setWaterDepth(40);         // transparency of water
+waterProcessor.setDistortionScale(0.05f); // strength of waves
+waterProcessor.setWaveSpeed(0.05f);       // speed of waves
+ 
+// we define the wave size by setting the size of the texture coordinates
+Quad quad = new Quad(400,400);
+quad.scaleTextureCoordinates(new Vector2f(6f,6f));
+ 
+// we create the water geometry from the quad
+Geometry water=new Geometry("water", quad);
+water.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
+water.setLocalTranslation(-200, -6, 250);
+water.setShadowMode(ShadowMode.Receive);
+water.setMaterial(waterProcessor.getMaterial());
+rootNode.attachChild(water);
+
+ +

Settings

+
+ +

+ +You can lower the render size to gain higher performance: + +

+
waterProcessor.setRenderSize(128,128);
+

+The deeper the water, the more transparent. (?) + +

+
waterProcessor.setWaterDepth(40);
+

+A higher distortion scale makes bigger waves. + +

+
waterProcessor.setDistortionScale(0.05f);
+

+A lower wave speed makes calmer water. + +

+
waterProcessor.setWaveSpeed(0.05f);
+

+If your scene does not have a lightsource, you can set the light direction for the water: + +

+
waterProcessor.setLightDirection( new Vector3f(0.55f, -0.82f, 0.15f));
+

+Instead of creating a quad and specifying a plane, you can get a default waterplane from the processor: + +

+
Geometry waterPlane = waterProcessor.createWaterGeometry(10, 10);
+waterPlane.setLocalTranslation(-5, 0, 5);
+waterPlane.setMaterial(waterProcessor.getMaterial());
+

+You can offer a switch to set the water Material to a static texture – for users with slow PCs. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.png new file mode 100644 index 000000000..887f0d715 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-animation.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-animation.png new file mode 100644 index 000000000..93b7a036b Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-animation.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-assets-models.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-assets-models.png new file mode 100644 index 000000000..30e718add Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-assets-models.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-effect-fire.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-effect-fire.png new file mode 100644 index 000000000..24096dc49 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-effect-fire.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-materials.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-materials.png new file mode 100644 index 000000000..42e24b721 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-materials.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-physics.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-physics.png new file mode 100644 index 000000000..7b02a3744 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-physics.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-picking.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-picking.png new file mode 100644 index 000000000..3c2c6ebeb Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-picking.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-scene.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-scene.png new file mode 100644 index 000000000..7eaf67bde Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-scene.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-terrain.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-terrain.png new file mode 100644 index 000000000..e42e21b9d Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-terrain.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_animation.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_animation.html new file mode 100644 index 000000000..3308f8ac9 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_animation.html @@ -0,0 +1,319 @@ + +

Getting Started with JME3 (7) - Hello Animation

+
+ +

+ +Previous: Hello Material, +Next: Hello Picking +

+ +

+
+ +This tutorial shows how to add an animation controller and channels, and how to respond to user input by triggering an animation in a loaded model. +
+ +

+ +

+ +

+ +
+ +

Sample Code

+
+
package jme3test.helloworld;
+ 
+import com.jme3.animation.AnimChannel;
+import com.jme3.animation.AnimControl;
+import com.jme3.animation.AnimEventListener;
+import com.jme3.animation.LoopMode;
+import com.jme3.app.SimpleApplication;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.light.DirectionalLight;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Node;
+ 
+/** Sample 7 - how to load an OgreXML model and play an animation, 
+ * using channels, a controller, and an AnimEventListener. */
+public class HelloAnimation extends SimpleApplication
+  implements AnimEventListener {
+ 
+  private AnimChannel channel;
+  private AnimControl control;
+  Node player;
+ 
+  public static void main(String[] args) {
+    HelloAnimation app = new HelloAnimation();
+    app.start();
+  }
+ 
+  @Override
+  public void simpleInitApp() {
+    viewPort.setBackgroundColor(ColorRGBA.LightGray);
+    initKeys();
+ 
+    DirectionalLight dl = new DirectionalLight();
+    dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());
+    rootNode.addLight(dl);
+ 
+    player = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
+    player.setLocalScale(0.5f);
+    rootNode.attachChild(player);
+ 
+    control = player.getControl(AnimControl.class);
+    control.addListener(this);
+    channel = control.createChannel();
+    channel.setAnim("stand");
+  }
+ 
+  public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
+    if (animName.equals("Walk")) {
+      channel.setAnim("stand", 0.50f);
+      channel.setLoopMode(LoopMode.DontLoop);
+      channel.setSpeed(1f);
+    }
+  }
+ 
+  public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
+    // unused
+  }
+ 
+  /** Custom Keybinding: Map named actions to inputs. */
+  private void initKeys() {
+    inputManager.addMapping("Walk", new KeyTrigger(KeyInput.KEY_SPACE));
+    inputManager.addListener(actionListener, "Walk");
+  }
+ 
+  private ActionListener() {
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Walk") && !keyPressed) {
+        if (!channel.getAnimationName().equals("Walk")) {
+          channel.setAnim("Walk", 0.50f);
+          channel.setLoopMode(LoopMode.Loop);
+        }
+      }
+    }
+  };
+ 
+}
+
+ +

Creating and Loading Animated Models

+
+ +

+ +You create animated models with a tool such as Blender. Take some time and learn how to create your own models in these . For now, download and use a free model, such as the one included here as an example (, ). +

+ +

+
+ +

+ +

+Loading an animated model is pretty straight-forward, just as you have learned in the previous chapters. Animated Ogre models come as a set of files: The model is in Oto.mesh.xml, and the animation details are in Oto.skeleton.xml (plus materials and textures). Check that all files of the model are indeed in the right Model subdirectory. +

+
    /* Displaying the model requires a light source */
+    DirectionalLight dl = new DirectionalLight();
+    dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());
+    rootNode.addLight(dl);
+ 
+    /* load and attach the model as usual */
+    player = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
+    player.setLocalScale(0.5f); // resize
+    rootNode.attachChild(player);
+

+Don't forget to add a light source to make the material visible. +

+ +
+ +

Animation Controler and Channel

+
+ +

+ +After you load the animated model, you register it to the Animation Controller. +

+
    +
  • The controller object gives you access to the available animation sequences.
    +
  • +
  • The controller can have several channels, each channel can run one animation sequence at a time.
    +
  • +
  • To run several sequences, you create several channels, and set them each to their animation.
    +
  • +
+
    /* Load the animation controls, listen to animation events, 
+     * create an animation channel, and bring the model in its default position.  */
+    control = player.getControl(AnimControl.class);
+    control.addListener(this);
+    channel = control.createChannel();
+    channel.setAnim("stand");
+
+ +

Responding to Animation Events

+
+ +

+ +Add implements AnimEventListener to the class declaration. This interface gives you access to events that notify you when a sequence is done, or when you change from one sequence to another, so you can respond to it. In this example, you reset the character to a standing position after a Walk cycle is done. +

+
  public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
+    if (animName.equals("Walk")) {
+      channel.setAnim("stand", 0.50f);
+      channel.setLoopMode(LoopMode.DontLoop);
+      channel.setSpeed(1f);
+    }
+  }
+ 
+  public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
+    // unused
+  }
+
+ +

Trigger Animations After User Input

+
+ +

+ +There are ambient animations like animals or trees that you may want to trigger in the main event loop. In other cases, animations are triggered by user interaction, such as key input. You want to play the Walk animation when the player presses a certain key (here the spacebar), at the same time as the avatar performs the walk action and changes its location. + +

+
    +
  1. Initialize a new input controller (in simpleInitApp()).
    +
      +
    • Don't forget to call the initKey() convenience method from simpleInitApp().
      +
    • +
    +
  2. +
  3. Add a key mapping with the name the action you want to trigger.
    +
      +
    • Here for example, you map Walk to the Spacebar key.
      +
    • +
    +
  4. +
  5. Add an input listener for the Walk action.
    +
  6. +
+
  private void initKeys() {
+    inputManager.addMapping("Walk", new KeyTrigger(KeyInput.KEY_SPACE));
+    inputManager.addListener(actionListener, "Walk");
+  }
+

+To use the input controller, you need to implement the actionLister: +Test for each action by name, and set the channel to the corresponding animation to run. + +

+
    +
  • The second parameter of setAnim() is the blendTime (?).
    +
  • +
  • LoopMode can be Loop (repeat), Cycle (?), and DontLoop (only once).
    +
  • +
  • If needed, use channel.setTime() to set the speed of this animation.
    +
  • +
+
  private ActionListener() {
+    public void onAction(String name, boolean keyPressed, float tpf) {
+        if (name.equals("Walk") && !keyPressed) {
+            if (!channel.getAnimationName().equals("Walk")){
+                channel.setAnim("Walk", 0.50f);
+                channel.setLoopMode(LoopMode.Cycle);
+            }
+        } 
+    }
+  };
+
+ +

Exercises

+
+ +
+ +

Two Animations

+
+ +

+ +Make the a mouse click trigger another animation sequence! + +

+
    +
  1. Create a second channel in the controller
    +
  2. +
  3. Create a new key trigger mapping and action (see: Hello Input)
    +
  4. +
  5. Tip: Do you want to find out what animation sequences are available in the model? Use:
    for (System.out.println(anim); }
    +
  6. +
+ +
+ +

Revealing the Skeleton (1)

+
+ +

+ +Open the skeleton.xml file in a text editor of your choice. +

+ +

+You don't have to be able to read or write these xml files (Blender does that for you) – but it is good to know what the xml files are there for and how skeletons work. “There's no magic to it!” +

+
    +
  • Note how the bones are numbered and named. All names of animated models follow a naming scheme.
    +
  • +
  • Note the bone hierarchy that specifies how the bones are connected.
    +
  • +
  • Note the list of animations: Each animation has a name, and several tracks. Each track tells individual bones how and when to transform. These animation steps are called keyframes.
    +
  • +
+ +
+ +

Revealing the Skeleton (2)

+
+ +

+ +Add the following code snippet to simpleInitApp() to make the bones (that you just read about) visible! +

+
     SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
+     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+     mat.setColor("Color", ColorRGBA.Green);
+     mat.getAdditionalRenderState().setDepthTest(false);
+     skeletonDebug.setMaterial(mat);
+     player.attachChild(skeletonDebug);
+

+Can you identify individual bones in the skeleton? +

+ +
+ +

Conclusion

+
+ +

+ +Now you can load animated models, identify stored animations, and trigger by using onAnimCycleDone() and onAnimChange(). You also learned that you can play several animations simultaneously, by starting each in a channel of its own. This could be useful if you ever want to animate the lower and upper part of the characters body independently, for example the legs run, and the arms use a weapon. +

+ +

+Now that your character can walk, wouldn't it be cool if it could also pick up things, or aim a weapon at things, or open doors? Time to learn more about picking! + +

+
+ +

+See also: + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_asset.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_asset.html new file mode 100644 index 000000000..ca3b18f6a --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_asset.html @@ -0,0 +1,444 @@ + +

Getting Started with JME3 (3) - Hello Assets

+
+ +

+ +Previous: Hello Node, +Next: Hello Main Event Loop +

+ +

+In this Tutorial we will learn to load 3-D models and text into the scene graph, using the jME asset manager. You also learn how to arrive at the correct paths, and which file formats to use. +

+ +

+ +

+ +

+

To use the example assets in a new jMonkeyPlatform project, right-click your project, select “Properties”, go to “Libraries”, press “Add Library” and add the “jme3-test-data” library. +

+

+ +
+ +

Code Sample

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.font.BitmapText;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.Box;
+ 
+/** Sample 3 - how to load an OBJ model, and OgreXML model, 
+ * a material/texture, or text. */
+public class HelloAssets extends SimpleApplication {
+ 
+    public static void main(String[] args) {
+        HelloAssets app = new HelloAssets();
+        app.start();
+    }
+ 
+    @Override
+    public void simpleInitApp() {
+ 
+        Spatial teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
+        Material mat_default = new Material( 
+            assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
+        teapot.setMaterial(mat_default);
+        rootNode.attachChild(teapot);
+ 
+        // Create a wall with a simple texture from test_data
+        Box(Vector3f.ZERO, 2.5f,2.5f,1.0f);
+        Spatial wall = new Geometry("Box", box );
+        Material mat_brick = new Material( 
+            assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat_brick.setTexture("ColorMap", 
+            assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));
+        wall.setMaterial(mat_brick);
+        wall.setLocalTranslation(2.0f,-2.5f,0.0f);
+        rootNode.attachChild(wall);
+ 
+        // Display a line of text with a default font
+        guiNode.detachAllChildren();
+        guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
+        BitmapText helloText = new BitmapText(guiFont, false);
+        helloText.setSize(guiFont.getCharSet().getRenderedSize());
+        helloText.setText("Hello World");
+        helloText.setLocalTranslation(300, helloText.getLineHeight(), 0);
+        guiNode.attachChild(helloText);
+ 
+        // Load a model from test_data (OgreXML + material + texture)
+        Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
+        ninja.scale(0.05f, 0.05f, 0.05f);
+        ninja.rotate(0.0f, -3.0f, 0.0f);
+        ninja.setLocalTranslation(0.0f, -5.0f, -2.0f);
+        rootNode.attachChild(ninja);
+        // You must add a light to make the model visible
+        DirectionalLight sun = new DirectionalLight();
+        sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
+        rootNode.addLight(sun);
+ 
+    }
+}
+

+Build and run the code sample. You should see a green Ninja with a colorful teapot standing behind a wall. The text on the screen should say “Hello World”. +

+ +
+ +

The Asset Manager

+
+ +

+ +JME3 comes with a handy asset manager that helps you keep your assets structured. Project assets are media files such as models, materials, textures, scenes, shaders, sounds, and fonts. The asset manager maintains a root that contains the classpath, so it can load any file from the current classpath (the top level of your project directory). +

+ +

+Additionally, the assetManager can be configured to add any path to the assets root, so assets can be loaded from directories you specify. In a jMonkeyPlatform project, jME3 seaches for models in the assets directory of your project. This is our recommended directory structure for storing assets: +

+
+assets/Interface/
+assets/MatDefs/
+assets/Materials/
+assets/Models/
+assets/Scenes/
+assets/Shaders/
+assets/Sounds/
+assets/Textures/
+build.xml
+src/...
+dist/...
+
+ +

+These are just the most common examples, you can name the directories inside the assets directory how you like. +

+ +
+ +

Loading Textures

+
+ +

+ +Place the textures in a subdirectory of assets/Textures/. Load the texture into the material before you set the Material. The following code sample is from the simpleInitApp() method: +

+
        // Create a wall with a simple texture from test_data
+        Box(Vector3f.ZERO, 2.5f,2.5f,1.0f);
+        Spatial wall = new Geometry("Box", box );
+        Material mat_brick = new Material( 
+            assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat_brick.setTexture("ColorMap", 
+            assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));
+        wall.setMaterial(mat_brick);
+        wall.setLocalTranslation(2.0f,-2.5f,0.0f);
+        rootNode.attachChild(wall);
+

+In most cases, you use default material descriptions such as “SimpleTextured.j3md”, as we do in this example. Advanced users can create custom Materials. +

+ +
+ +

Loading Text and Fonts

+
+ +

+ +This example displays “Hello Text” in the default font at the bottom edge of the window. You attach text to the guiNode, a special node for flat (orthogonal) display elements. You can clear existing text in the guiNode by detaching all its children. +The following code sample goes into the simpleInitApp() method. +

+
        // Display a line of text with a default font
+        guiNode.detachAllChildren();
+        guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
+        BitmapText helloText = new BitmapText(guiFont, false);
+        helloText.setSize(guiFont.getCharSet().getRenderedSize());
+        helloText.setText("Hello World");
+        helloText.setLocalTranslation(300, helloText.getLineHeight(), 0);
+        guiNode.attachChild(helloText);
+
+ +

Loading an Ogre XML Model

+
+ +

+ +Export your model in OgreXML format (.mesh.xml, .scene, .material, .skeleton.xml) and place it in a subdirectory of assets/Models/. The following code sample goes into the simpleInitApp() method. +

+
        // Load a model from test_data (OgreXML + material + texture)
+        Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
+        ninja.scale(0.05f, 0.05f, 0.05f);
+        ninja.rotate(0.0f, -3.0f, 0.0f);
+        ninja.setLocalTranslation(0.0f, -5.0f, -2.0f);
+        rootNode.attachChild(ninja);
+        // You must add a light to make the model visible
+        DirectionalLight sun = new DirectionalLight();
+        sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
+        rootNode.addLight(sun);
+

+If you use the build script created by the jMonkeyPlatform then, by default, the original OgreXML files will not be included in your distributed game. You will get an error message when trying to load them. +

+
com.jme3.asset.DesktopAssetManager loadAsset
+WARNING: Cannot locate resource: Scenes/town/main.scene
+com.jme3.app.Application handleError
+SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
+java.lang.NullPointerException
+
+ +

+For the release build, you should work with .j3o files only. Use the jMonkeyPlatform's context menu action to convert OgreXML models to .j3o format. +

+ +
+ +

Loading Assets From Custom Paths

+
+ +

+ +What if your game relies on user supplied model files, that will not be included in your distribution? If a file is not located in the default location, you can register a custom Locator and load it from any path. +

+ +

+Here is a usage example of a ZipLocator that is registered to a file town.zip in the top level of your project directory: +

+
    assetManager.registerLocator("town.zip", ZipLocator.class.getName());
+    Spatial scene = assetManager.loadModel("main.scene");
+    rootNode.attachChild(scene);
+

+Here is a HttpZipLocator that can download zipped models: +

+
    assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/wildhouse.zip", 
+                                 HttpZipLocator.class.getName());
+    Spatial scene = assetManager.loadModel("main.scene");
+    rootNode.attachChild(scene);
+

+JME3 offers ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, and UrlLocator (see com.jme3.asset.plugins). +

+ +
+ +

Creating Models and Scenes

+
+ +

+ +To create 3D models and scenes, you need a 3D Mesh Editor such as Blender, with an OgreXML Exporter plugin. Create your models with . +You can use the jMonkeyPlatform to load models and create scenes from them. +

+ +

+Export your models as Ogre XML meshes with materials. +

+
    +
  1. Open the menu File > Export > OgreXML Exporter to open the exporter dialog.
    +
  2. +
  3. In the Export Materials field: Give the material the same name as the model. For example, the model something.mesh.xml goes with something.material, plus (optionally) something.skeleton.xml and some JPG files.
    +
  4. +
  5. In the Export Meshes field: Select a subdirectory of your assets/Models/ directory. E.g. assets/Models/something/.
    +
  6. +
  7. Activate the following exporter settings:
    +
      +
    • Copy Textures: YES
      +
    • +
    • Rendering Materials: YES
      +
    • +
    • Flip Axis: YES
      +
    • +
    • Require Materials: YES
      +
    • +
    • Skeleton name follows mesh: YES
      +
    • +
    +
  8. +
  9. Click export.
    +
  10. +
+ +

+ +File Format: JME 3 can load Ogre XML models, materials, and scenes, as well as Wavefront OBJ+MTL models. For the game release, you should optimize model loading by converting all models to JME3's .j3o format. We recommend creating your project in the jMonkeyPlatform, it contains an integrated .j3o converter. + +

+
    +
  1. Open your JME3 Project in the jMonkeyplatform.
    +
  2. +
  3. Right-click a .mesh.xml file in the Projects (or Favorites) window, and choose “convert to JME3 binary”.
    +
  4. +
  5. The .j3o file appears next to the .mesh.xml file with the same name.
    +
  6. +
  7. If you use the build script generated by the jMonkeyPlatform, mesh.xml files and obj files will be excluded from the executable JAR. If you get a runtime exception, make sure you have converted all models to .j3o.
    +
  8. +
+ +
+ +

Loading Models and Scenes

+
+ + + + + + + + + + + + + +
Task? Solution!
Load a model with materials Use the asset managers loadModel() method and attach the Spatial to the rootNode.
Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml");
+rootNode.attachChild(elephant);
Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.j3o");
+rootNode.attachChild(elephant);
Load a model without materials If you have a model without materials, you have to add a default material to make it visible.
Spatial teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
+Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
+teapot.setMaterial(mat);
+rootNode.attachChild(teapot);
Load a scene You load scenes just like you load models:
Spatial scene = assetManager.loadModel("Scenes/house/main.scene");
+rootNode.attachChild(scene);
+ +
+ +

Excercise - How to Load Assets

+
+ +

+ +As an exercise, let's try different ways of loading a scene. You can load a scene directly, or from a zip file: + +

+
    +
  1. sample scene.
    +
  2. +
  3. (Optional:) Unzip the town.zip to see the structure of the contained Ogre dotScene: You'll get a directory named town. It contains XML and texture files, and file called main.scene. (This is just for your information, you do not need to do anything with it.)
    +
  4. +
  5. Place the town.zip file in the top level directory of your JME3 project, like so:
    jMonkeyProjects/MyGameProject/assets/
    +jMonkeyProjects/MyGameProject/build.xml
    +jMonkeyProjects/MyGameProject/src/
    +jMonkeyProjects/MyGameProject/town.zip
    +...
    +
    +
    +
  6. +
+ +

+ +Use the following method to load models from a zip file: + +

+
    +
  1. Make sure town.zip is in the project directory.
    +
  2. +
  3. We register a zip file locator to the project directory. The loadModel() method now searches this zip directly for the files to load.
    + (That is, do not write town.zip/main.scene or similar.)
    +
  4. +
  5. Add the following code under simpleInitApp() {
        assetManager.registerLocator("town.zip", ZipLocator.class.getName());
    +    Spatial gameLevel = assetManager.loadModel("main.scene");
    +    gameLevel.setLocalTranslation(0, -5.2f, 0);
    +    gameLevel.setLocalScale(2);
    +    rootNode.attachChild(gameLevel);
    +
  6. +
  7. Clean, build and run the project. You should see the Ninja+wall+teapot standing in a town.
    +
  8. +
+ +

+ +If you register new locators, make sure you do not get any file name conflicts: Give each scene a unique name. +

+ +

+Earlier in this tutorial, you loaded scenes and models from the asset directory. This is the most common way you will be loading scenes and models. Here is the typical procedure: + +

+
    +
  1. Remove the code from the previous exercise.
    +
  2. +
  3. Move the unzipped town/ directory into the assets/Scenes/ directory of your project.
    +
  4. +
  5. Add the following code under simpleInitApp() {
        Spatial gameLevel = assetManager.loadModel("Scenes/town/main.scene");
    +    gameLevel.setLocalTranslation(0, -5.2f, 0);
    +    gameLevel.setLocalScale(2);
    +    rootNode.attachChild(gameLevel);
    +
  6. +
  7. Note that the path starts relative to the assets/… directory.
    +
  8. +
  9. Clean, build and run the project. Again, you should see the Ninja+wall+teapot standing in a town.
    +
  10. +
+ +

+ +Here is a third method you must know. Loading a scene/model from a .j3o file: + +

+
    +
  1. Remove the code from the previous exercise.
    +
  2. +
  3. If you haven't already, open the jMonkeyPlatform and open the project that contains the Hello Asset class.
    +
  4. +
  5. In the projects window, browse to the assets/Scenes/town directory.
    +
  6. +
  7. Right-click the main.scene and convert the scene to binary: The jMoneyPlatform generates a main.j3o file.
    +
  8. +
  9. Add the following code under simpleInitApp() {
        Spatial gameLevel = assetManager.loadModel("Scenes/town/main.j3o");
    +    gameLevel.setLocalTranslation(0, -5.2f, 0);
    +    gameLevel.setLocalScale(2);
    +    rootNode.attachChild(gameLevel);
    +
  10. +
  11. Again, note that the path starts relative to the assets/… directory.
    +
  12. +
  13. Clean, Build and run the project. Again, you should see the Ninja+wall+teapot standing in a town.
    +
  14. +
+ +

+ +What is the difference between loading Scenes/town/main.j3o and Scenes/town/main.scene? +

+
    +
  • You can work with *.scene and .xml files during the development phase: When your designer pushes updated files to the asset directory, you can quickly review the latest version in your development environment.
    +
  • +
  • Create and load *.j3o files for QA and release builds: .j3o is a binary format for jME3 applications, and .j3o files will be automatically included in the distributable JAR file. When you do QA test builds or are ready to release, use the jMonkeyPlatform to convert all .scene and .xml files to .j3o files, and load these.
    +
  • +
+ +
+ +

Conclusion

+
+ +

+ +Now you know how to populate the scenegraph with static shapes and models, and how to build scenes. You have learned how to load assets using the assetManager and you have seen that the paths start relative to your project directory. Another important thing you have learned is to convert models to .j3o format for the JAR builds. +

+ +

+Let's add some action to the scene and continue with the main event loop. + +

+
+ +

+See also: +

+
    +
  • +
  • +
  • +
  • +
  • If you want to learn how to load sounds, see Hello Audio
    +
  • +
  • If you want to learn more about loading textures and materials, see Hello Material
    +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_audio.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_audio.html new file mode 100644 index 000000000..59181dd55 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_audio.html @@ -0,0 +1,285 @@ + +

Hello Audio

+
+ +

+ +Previous: Hello Terrain, +Next: Hello Effects +

+ +

+ +This tutorial explains how to add 3D sound to a game, and how to trigger when sounds are to be played. We will use an Audio Listener, an Audio Renderer, two Audio Nodes, and an Action Listener. +

+ +
+ +

Sample Code

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.audio.AudioNode;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.MouseButtonTrigger;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+ 
+/** Sample 11 - playing 3D audio. */
+public class HelloAudio extends SimpleApplication {
+ 
+  private AudioNode audio_gun;
+  private AudioNode audio_nature;
+  private Geometry player;
+ 
+  public static void main(String[] args) {
+    HelloAudio app = new HelloAudio();
+    app.start();
+  }
+ 
+  @Override
+  public void simpleInitApp() {
+    flyCam.setMoveSpeed(40);
+ 
+    /** just a blue box floating in space */
+    Box(Vector3f.ZERO, 1, 1, 1);
+    player = new Geometry("Player", box1);
+    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mat1.setColor("Color", ColorRGBA.Blue);
+    player.setMaterial(mat1);
+    rootNode.attachChild(player);
+ 
+    /** custom init methods, see below */
+    initKeys();
+    initAudio();
+  }
+ 
+  /** We create two audio nodes. */
+  private void initAudio() {
+    /* gun shot sound is to be triggered by a mouse click. */
+    audio_gun = new AudioNode(assetManager, "Sound/Effects/Gun.wav", false);
+    audio_gun.setLooping(false);
+    // Volume goes from 0.1f to 1.0f. At 0 it's muted.
+    audio_gun.setVolume(0.2f);
+ 
+    /* nature sound - keeps playing in a loop. */
+    audio_nature = new AudioNode(assetManager, "Sound/Environment/Nature.ogg", false);
+    audio_nature.setLooping(true);
+    audio_nature.setPositional(true);
+    audio_nature.setLocalTranslation(Vector3f.ZERO.clone());
+    // Volume goes from 0.1f to 1.0f. At 0 it's muted.
+    audio_nature.setVolume(0.3f);
+    audioRenderer.playSource(audio_nature); // play continuously!
+  }
+ 
+  /** Declaring the "Shoot" action, and
+   *  mapping it to a trigger (mouse click). */
+  private void initKeys() {
+    inputManager.addMapping("Shoot", new MouseButtonTrigger(0));
+    inputManager.addListener(actionListener, "Shoot");
+  }
+ 
+  /** Defining the "Shoot" action: Play a gun sound. */
+  private ActionListener() {
+    @Override
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Shoot") && !keyPressed) {
+        audioRenderer.playSource(audio_gun); // play once!
+      }
+    }
+  };
+ 
+  /** Move the listener with the a camera - for 3D audio. */
+  @Override
+  public void simpleUpdate(float tpf) {
+    listener.setLocation(cam.getLocation());
+    listener.setRotation(cam.getRotation());
+  }
+ 
+}
+

+When you run the sample, you should see a blue cube, and hear nature ambient sounds. When you click you hear a loud shot. +

+ +
+ +

Understanding the Code Sample

+
+ +

+ +In the game's initSampleApp() method, we create a simple blue cube geometry called player and attach it to the scene – it's just sample content so you see something when running the audio sample. +

+ +

+From initSampleApp(), we initialize the game by calling the two custom methods initKeys() and initAudio(). You could call the lines of code in these two methods directly from initSampleApp(); we simply moved them into extra methods to keep the code more readable. +

+ +

+Let's look at initKeys(): As we learned in previous tutorials, we use jme's inputManager to respond to user input. We add a mapping for a left mouse button click, and we name this new action Shoot. +

+
/** Declaring the "Shoot" action and mapping to a trigger. */
+  private void initKeys() {
+    // click to shoot
+    inputManager.addMapping("Shoot", new MouseButtonTrigger(0));
+    inputManager.addListener(actionListener, "Shoot");
+  }
+

+Setting up the ActionListener should also be familiar from previous tutorials. We declare that, when the trigger (the mouse button) is pressed and released, we want to play a gun sound. +

+
  /** Defining the "Shoot" action: play a sound. */
+  private ActionListener() {
+    @Override
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Shoot") && !keyPressed) {
+        audioRenderer.playSource(audio_gun);
+      }
+    }
+  };
+

+Next we have a closer look at initAudio() to learn how to use the AudioRenderer and AudioNodes. +

+ +
+ +

AudioNodes

+
+ +

+ +Using audio is quite simple. Save your audio files into your assets/Sound directory. jME3 supports both Ogg Vorbis (.ogg) and Wave (.wav) files. +

+ +

+For each sound you create an audio node. A sound node can be used like any node in the jME scene graph. We create one node for a gunshot sound, and one for a nature sound. +

+
  private AudioNode audio_gun;
+  private AudioNode audio_nature;
+

+Look at initAudio(): Here we initialize the sound objects and set some parameters. +

+
    audio_gun = new AudioNode(assetManager, "Sound/Effects/Gun.wav", false);
+    audio_nature = new AudioNode(assetManager, "Sound/Environment/Nature.ogg", true);
+ +

+These two lines create new sound nodes from the given audio files in the assetManager. The Boolean parameter specifies whether you want to stream the sound or not. The nature sound is quite long, so we set this to true because we want to stream it. +

+ +

+In the next lines we specify that we want the gunshot sound to play only once (do not loop) and we specify its volume on a scale of 0.1 to 1.0. At 0, it is muted. +

+
    audio_gun.setLooping(false);
+    audio_gun.setVolume(0.4f);
+

+The nature sound is different: We want it to loop continuously as background sound. We also make it a positional sound and give the node an explicit translation (Vector3f.ZERO stands for 0.0f,0.0f,0.0f). Since jME supports 3D audio, you will be able to hear this sound coming from a particular direction. +

+
    audio_nature.setLooping(true);
+    audio_nature.setPositional(true);
+    audio_nature.setLocalTranslation(new Vector3f.ZERO.clone());
+    audio_nature.setVolume(0.3f);
+  }
+
+ +

Triggering Audio

+
+ +

+ +The two sounds are used differently: +

+
    +
  • The gunshot is situational. We want to play it only once, right when it is triggered.
    +
      +
    • This is why we made it setLooping(false)
      +
    • +
    +
  • +
  • The nature sound is a background noise. We want it to start playing and loop on as long as the game runs.
    +
      +
    • This is why we made it setLooping(true)
      +
    • +
    +
  • +
+ +

+ +So every sound knows whether it loops or not. The actual play command is the same for both files: +

+
    audioRenderer.playSource(audio_nature);
+...
+    audioRenderer.playSource(audio_gun);
+

+The only difference is where they are called: +

+
    +
  • We start playing the background nature sound right after we have created it, in the initAudio() method.
    +
  • +
  • The gunshot sound, however, is triggered situationally, as part of the Shoot input action that we defined.
    +
  • +
+ +
+ +

3D Audio Listener

+
+ +

+ +To keep up the 3D audio effect, jME needs to know the position of the sound source, and the position of the audio listener. The listener is a built-in object in a SimpleApplication and it is not related to an ActonListener. +

+ +

+I order to make the most of 3D audio, we use the simpleUpdate() method to move the listener with the camera. +

+
   public void simpleUpdate(float tpf) {
+    listener.setLocation(cam.getLocation());
+    listener.setRotation(cam.getRotation());
+  }
+
+ +

Global or Positional?

+
+ +

+ +In this example, we defined the nature sound as coming from a certain position, but not the gunshot sound. This means the gunshot can be heard everywhere with the same volume. + +

+
    +
  • In a game with moving enemies you maight want to make the audio_gun node positional, and move it to the location of the shooting enemy before playing it – this way a player with stereo speakers could hear from which direction the gunshot is coming.
    +
  • +
  • Similarly, you may have game levels where you want one background sound to play globally, in this case, you would not make the audio_nature a positional sound.
    +
  • +
+ +

+ +In short, you must choose in every situation whether you want a sound to be global or positional. +

+ +
+ +

Conclusion

+
+ +

+ +You now know how to add two types of sound to your game: global sounds and positional sounds. You can play sounds in two ways: Either as loop or just once. You also learned to use sound files that are in either .ogg or .wav format. +

+ +

+Tip: jME's Audio implementation also supports more advanced effects such as reverberation and the Doppler effect. Find out more about these from the sample code included in the jme3test directory. +

+ +

+Want some fire and explosions to go with your sounds? Read on to learn more about effects. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_collision.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_collision.html new file mode 100644 index 000000000..5edf29b25 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_collision.html @@ -0,0 +1,489 @@ + +

Getting Started with JME3 (9) - Hello Collision

+
+ +

+ +Previous: Hello Picking, +Next: Hello Audio +

+ +

+This tutorial demonstrates how you load a scene model and give it solid walls and floors for a character to walk around. +

+ +

+We will use a PhysicsNode for the static collidable scene, and a PhysicsCharacterNode for the mobile first-person character. We will also adapt the default first-person camera to work with physics-controlled navigation. +

+ +

+The solution shown here can be used for first-person shooters, mazes, and similar games. +

+ +

+ +

+ +
+ +

Sample Code

+
+ +

+ +If you don't have it yet, sample scene. +

+
jMonkeyProjects$ ls -1 BasicGame
+assets/
+build.xml
+town.zip
+src/
+ +

+Place town.zip in the root directory of your JME3 project. +

+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.asset.plugins.ZipLocator;
+import com.jme3.bullet.BulletAppState;
+import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
+import com.jme3.bullet.collision.shapes.CollisionShape;
+import com.jme3.bullet.control.CharacterControl;
+import com.jme3.bullet.control.RigidBodyControl;
+import com.jme3.bullet.util.CollisionShapeFactory;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.light.AmbientLight;
+import com.jme3.light.DirectionalLight;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+ 
+/**
+ * Example 9 - How to make walls and floors solid.
+ * This version uses Physics and a custom Action Listener.
+ * @author normen, with edits by Zathras
+ */
+public class HelloCollision extends SimpleApplication
+  implements ActionListener {
+ 
+  private Spatial sceneModel;
+  private BulletAppState bulletAppState;
+  private RigidBodyControl landscape;
+  private CharacterControl player;
+  private Vector3f walkDirection = new Vector3f();
+  private boolean left = false, right = false, up = false, down = false;
+ 
+  public static void main(String[] args) {
+    HelloCollision app = new HelloCollision();
+    app.start();
+  }
+ 
+  public void simpleInitApp() {
+    /** Set up Physics */
+    bulletAppState = new BulletAppState();
+    stateManager.attach(bulletAppState);
+ 
+    // We re-use the flyby camera for rotation, while positioning is handled by physics
+    viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f));
+    flyCam.setMoveSpeed(100);
+    setUpKeys();
+    setUpLight();
+ 
+    // We load the scene from the zip file and adjust its size.
+    assetManager.registerLocator("town.zip", ZipLocator.class.getName());
+    sceneModel = assetManager.loadModel("main.scene");
+    sceneModel.setLocalScale(2f);
+ 
+    // We set up collision detection for the scene by creating a
+    // compound collision shape and a static physics node with mass zero.
+    CollisionShape sceneShape =
+      CollisionShapeFactory.createMeshShape((Node) sceneModel);
+    landscape = new RigidBodyControl(sceneShape, 0);
+    sceneModel.addControl(landscape);
+ 
+    // We set up collision detection for the player by creating
+    // a capsule collision shape and a physics character node.
+    // The physics character node offers extra settings for
+    // size, stepheight, jumping, falling, and gravity.
+    // We also put the player in its starting position.
+    CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
+    player = new CharacterControl(capsuleShape, 0.05f);
+    player.setJumpSpeed(20);
+    player.setFallSpeed(30);
+    player.setGravity(30);
+    player.setPhysicsLocation(new Vector3f(0, 10, 0));
+ 
+    // We attach the scene and the player to the rootnode and the physics space,
+    // to make them appear in the game world.
+    rootNode.attachChild(sceneModel);
+    bulletAppState.getPhysicsSpace().add(landscape);
+    bulletAppState.getPhysicsSpace().add(player);
+  }
+ 
+    private void setUpLight() {
+        // We add light so we see the scene
+        AmbientLight al = new AmbientLight();
+        al.setColor(ColorRGBA.White.mult(1.3f));
+        rootNode.addLight(al);
+ 
+        DirectionalLight dl = new DirectionalLight();
+        dl.setColor(ColorRGBA.White); 
+        dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
+        rootNode.addLight(dl);
+    }
+ 
+  /** We over-write some navigational key mappings here, so we can
+   * add physics-controlled walking and jumping: */
+  private void setUpKeys() {
+    inputManager.addMapping("Lefts",  new KeyTrigger(KeyInput.KEY_A));
+    inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D));
+    inputManager.addMapping("Ups",    new KeyTrigger(KeyInput.KEY_W));
+    inputManager.addMapping("Downs",  new KeyTrigger(KeyInput.KEY_S));
+    inputManager.addMapping("Jumps",  new KeyTrigger(KeyInput.KEY_SPACE));
+    inputManager.addListener(this, "Lefts");
+    inputManager.addListener(this, "Rights");
+    inputManager.addListener(this, "Ups");
+    inputManager.addListener(this, "Downs");
+    inputManager.addListener(this, "Jumps");
+  }
+ 
+  /** These are our custom actions triggered by key presses.
+   * We do not walk yet, we just keep track of the direction the user pressed. */
+  public void onAction(String binding, boolean value, float tpf) {
+    if (binding.equals("Lefts")) {
+      if (value) { left = true; }  else { left = false; }
+    } else if (binding.equals("Rights")) {
+      if (value) { right = true; } else { right = false; }
+    } else if (binding.equals("Ups")) {
+      if (value) { up = true; }    else { up = false; }
+    } else if (binding.equals("Downs")) {
+      if (value) { down = true; }  else { down = false; }
+    } else if (binding.equals("Jumps")) {
+      player.jump();
+    }
+  }
+ 
+  /**
+   * This is the main event loop--walking happens here.
+   * We check in which direction the player is walking by interpreting
+   * the camera direction forward (camDir) and to the side (camLeft).
+   * The setWalkDirection() command is what lets a physics-controlled player walk.
+   * We also make sure here that the camera moves with player.
+   */
+  @Override
+  public void simpleUpdate(float tpf) {
+    Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
+    Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
+    walkDirection.set(0, 0, 0);
+    if (left)  { walkDirection.addLocal(camLeft); }
+    if (right) { walkDirection.addLocal(camLeft.negate()); }
+    if (up)    { walkDirection.addLocal(camDir); }
+    if (down)  { walkDirection.addLocal(camDir.negate()); }
+    player.setWalkDirection(walkDirection);
+    cam.setLocation(player.getPhysicsLocation());
+  }
+}
+

+Run the sample. You should see a town square with houses and a monument. Use the WASD keys and the mouse to navigate around in first person view. Run forward and jump by pressing W and Space. Note how you step over the sidewalk, and up the steps to the monument. You can walk in the alleys between the houses, but the walls are solid. Don't walk over the edge of the world! :-) +

+ +
+ +

Understanding the Code

+
+ +

+ +Let's start with the class declaration: +

+
extends SimpleApplication implements ActionListener
+

+SimpleApplication is the base class for all jME3 games. We also have this class implement the ActionListener interface because we want to customize the navigational inputs later. +

+
  private Spatial sceneModel;
+  private BulletAppState bulletAppState;
+  private RigidBodyControl landscape;
+  private CharacterControl player;
+  private Vector3f walkDirection = new Vector3f();
+  private boolean left = false, right = false, up = false, down = false;
+

+We initialize a few private fields: +

+
    +
  • The BulletAppState gives this SimpleApplication access to physics features (such as collision detection) supplied by jME3's jBullet integration
    +
  • +
  • The Spatial sceneModel is a normal OgreXML model loaded as a Spatial.
    +
  • +
  • You use the model as the game's landscape by adding a RigidBodyControl to it.
    +
  • +
  • The (invisible) first-person player is represented by a CharacterControl object.
    +
  • +
  • The fields walkDirection and the four Booleans are used for physics-controlled navigation.
    +
  • +
+ +

+ +Let's have a look at all the details: +

+ +
+ +

Initializing the Game

+
+ +

+ +As usual, you initialize the game in the simpleInitApp() method. +

+
    viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f));
+    flyCam.setMoveSpeed(100);
+    setUpKeys();
+    setUpLight();
+

+We switch the background color from balck to light blue, since this is a scene with a sky. +You repurpose the default flyCam camera as first-person camera and set its speed. +The auxiliary method setUpLights() adds light sources. +The auxiliary method setUpKeys() configures input mappings–we will look at it later. +

+ +
+ +

The Physics-Controlled Scene

+
+ +

+ +The first thing you do in every physics game is create a BulletAppState object. It gives you access to jME3's jBullet integration which handles physical forces and collisions. +

+
    bulletAppState = new BulletAppState();
+    stateManager.attach(bulletAppState);
+

+For the scene, you load the sceneModel from a zip file, and adjust the size. +

+
    assetManager.registerLocator("town.zip", ZipLocator.class.getName());
+    sceneModel = assetManager.loadModel("main.scene");
+    sceneModel.setLocalScale(2f);
+

+The file town.zip is included as a sample model in the JME3 sources – you can . (Optionally, use any OgreXML scene of your own.) For this sample, place the zip file in the application's top level directory (that is, next to src/, assets/, build.xml). +

+
    CollisionShape sceneShape =
+      CollisionShapeFactory.createMeshShape((Node) sceneModel);
+    landscape = new RigidBodyControl(sceneShape, 0);
+    sceneModel.addControl(landscape);
+

+To use collision detection, you want to add a RigidBodyControl to the sceneModel Spatial. The RigidBodyControl for a complex model takes two arguments: A Collision Shape, and the object's mass. + +

+
    +
  • JME3 offers a CollisionShapeFactory that precalculates a mesh-accurate collision shape for a Spatial. We choose to generate a CompoundCollisionShape, which has MeshCollisionShapes as its children. Note: This type of collision shape is optimal for immobile objects, such as terrain, houses, and whole shooter levels.
    +
  • +
  • You set the mass to zero since a scene is static and its mass irrevelant.
    +
  • +
+ +

+ +Add the control to the Spatial to make give it physical properties. Attach the sceneModel to the rootNode to make it visible. +

+
    rootNode.attachChild(sceneModel);
+

+Tip: Remember to always add a light source so you can see the scene. +

+ +
+ +

The Physics-Controlled Player

+
+ +

+ +Next you set up collision detection for the first-person player. +

+
    CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
+

+Again, you create a CollisionShape: This time we choose a CapsuleCollisionShape, a cylinder with a rounded top and bottom. Note: This shape is optimal for a person: It's tall and the roundness helps to get stuck less often on obstacles. +

+
    +
  • Supply the CapsuleCollisionShape constructor with the desired size of the bounding capsule to fit the shape of your character. In this example the character is 2*1.5f units wide, and 6f units tall.
    +
  • +
  • The final integer argument specifies the orientation of the cylinder: 1 is the Y-axis, which fits an upright person. For many animals and vehicles you would use 0 or 2.
    +
  • +
+
    player = new CharacterControl(capsuleShape, 0.05f);
+

+Now you use the CollisionShape to create a CharacterControl that represents the player. The last argument of the CharacterControl constructor (here .05f) is the size of a step that the character should be able to surmount. +

+
    player.setJumpSpeed(20);
+    player.setFallSpeed(30);
+    player.setGravity(30);
+

+Apart from step height and character size, the CharacterControl lets you configure jumping, falling, and gravity speeds. Adjust the values to fit your game situation. +

+
    player.setPhysicsLocation(new Vector3f(0, 10, 0));
+

+Finally we put the player in its starting position and update its state – remember to use setPhysicsLocation() instead of setLocalTranslation(). since you are dealing with a physical object. +

+ +
+ +

Activating the PhysicsSpace

+
+ +

+ +As in every JME3 application, you must attach the scene and the player to the rootNode to make them appear in the game world. +

+
    rootNode.attachChild(landscape);
+    rootNode.attachChild(player);
+

+Remember that for physical games, you must also add all solid objects (usually the characters and the scene) to the PhysicsSpace! +

+
    bulletAppState.getPhysicsSpace().add(landscape);
+    bulletAppState.getPhysicsSpace().add(player);
+
+ +

Navigation

+
+ +

+ +The default camera controller cam is a third-person camera. JME3 also offers a first-person controller, flyCam, which we use here to handle camera rotation. +

+ +

+However we must redefine how walking is handled for physics-controlled objects: When you navigate a physical node, you do not specify a target location, but a walk direction. The physics space calculates how far the character can actually go in the desired direction – or whether it will be stoped by an obstacle. +

+ +

+This is why we must re-define the flyCam's navigational key mappings to use setWalkDirection() instead of setLocalTranslation(). Here are the steps: +

+ +
+ +

1. inputManager

+
+ +

+ +Configure the familiar WASD inputs for walking, and Space for jumping. +

+
    inputManager.addMapping("Lefts",  new KeyTrigger(KeyInput.KEY_A));
+    inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D));
+    inputManager.addMapping("Ups",    new KeyTrigger(KeyInput.KEY_W));
+    inputManager.addMapping("Downs",  new KeyTrigger(KeyInput.KEY_S));
+    inputManager.addMapping("Jumps",  new KeyTrigger(KeyInput.KEY_SPACE));
+    inputManager.addListener(this, "Lefts");
+    inputManager.addListener(this, "Rights");
+    inputManager.addListener(this, "Ups");
+    inputManager.addListener(this, "Downs");
+    inputManager.addListener(this, "Jumps");
+

+In the code sample above, this block of code was moved into an auxiliary method setupKeys() that is called from simpleInitApp()–this is just to keep the code more readable. +

+ +
+ +

2. onAction()

+
+ +

+ +Remember that we declared this class an ActionListener so we could customize the flyCam. The ActionListener interface requires us to implement the onAction() method: You re-define the actions triggered by navigation key presses to work with physics. +

+
  public void onAction(String binding, boolean value, float tpf) {
+    if (binding.equals("Lefts")) {
+      if (value) { left = true; }  else { left = false; }
+    } else if (binding.equals("Rights")) {
+      if (value) { right = true; } else { right = false; }
+    } else if (binding.equals("Ups")) {
+      if (value) { up = true; }    else { up = false; }
+    } else if (binding.equals("Downs")) {
+      if (value) { down = true; }  else { down = false; }
+    } else if (binding.equals("Jumps")) {
+      player.jump();
+    }
+  }
+

+Every time the user presses one of the WASD keys, you keep track of the direction the user wants to go – by storing this info in four directional Booleans. We will use them soon. +

+ +

+Note that no actual walking happens here – not yet! +

+ +

+The only movement that you do not have to implement yourself is the jumping action. The call player.jump() is a special method that handles a correct jumping motion for your PhysicsCharacterNode. +

+ +
+ +

3. setWalkDirection()

+
+ +

+ +In onAction() you have determined in which direction the user wants to go in terms of “forward” or “left”. +Now you need poll the current rotation of the camera to find to which vectors “forward” and “left” correspond in the coordinate system. +This last and most important code snippet goes into the main event loop, simpleUpdate(). +

+
    Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
+    Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
+    walkDirection.set(0, 0, 0);
+    if (left)  { walkDirection.addLocal(camLeft); }
+    if (right) { walkDirection.addLocal(camLeft.negate()); }
+    if (up)    { walkDirection.addLocal(camDir); }
+    if (down)  { walkDirection.addLocal(camDir.negate()); }
+

+Reset the variable walkDirection to zero. Then add to it all latest motion vectors that you polled from the camera. It is posible for a character to move forward and to the left simultaneously. +

+
player.setWalkDirection(walkDirection);
+

+This one line does the “walking” magic: Always use setWalkDirection() to make a physics-controlled object move continuously, and the physics engine automatically handles collision detection for you! +

+ +

+Important: Do not use setLocalTranslation() to walk the player around. You may get it stuck by overlapping with another physical object. You can put the player in a start position with setPhysicalLocation() if you make sure to place it a bit above the floor and away from obstacles. +

+ +

+Lastly, do not forget to make the first-person camera object move along with the physics-controlled player node: +

+
    cam.setLocation(player.getPhysicsLocation());
+

+That's it! +

+ +
+ +

Conclusion

+
+ +

+ +You have learned how to load a “solid” physical scene model and walk around in it with a first-person perspective. +You had JME3 calculate the CollisionShapes, and you represented collidables as PhysicsNodes that you registered to the Physics Space. +You also made certain to use player.setWalkDirection(walkDirection) to move physical characters around. +

+ +

+To learn more about different ways of loading models and scene have a look at Hello Asset,Scene Explorer and Scene Composer +

+ +

+There are also other possible solutions for this task that do not require physics. +Have a look at (and SphereMotionAllowedListener.java). +To learn more about complex physics scenes where several mobile physical objects bump into each other, read Hello Physics. +

+ +

+Do you want to hear your player say “ouch!” when he bumps into a wall? Continue with learning how to add sound to your game. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_effects.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_effects.html new file mode 100644 index 000000000..c48e42b91 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_effects.html @@ -0,0 +1,330 @@ + +

Getting Started with JME3 (12) - Hello Effects

+
+ +

+ +Previous: Hello Audio, +Next: Hello Physics +

+ +

+ +

+ +

+When you see one of the following in a game, then a particle system is likely behind it: +

+
    +
  • Fire, flames, sparks;
    +
  • +
  • Rain, snow, waterfalls, leaves;
    +
  • +
  • Explosions, debris, shockwaves;
    +
  • +
  • Dust, fog, clouds, smoke;
    +
  • +
  • Insects swarms, meteor showers;
    +
  • +
  • Magic spells.
    +
  • +
+ +

+ +These things typically cannot be modeled by meshes. +In very simple terms: +

+
    +
  • The difference between an explosion and a dust cloud is the speed of the effect.
    +
  • +
  • The difference between flames and a waterfall is the direction and the color of the effect.
    +
  • +
+ +

+ +Particle effects can be animated (e.g. sparks, drops) and static (strands of grass, hair). Non-particle effects include bloom/glow, and motion blur/afterimage. In this tutorial we will look at animated particles (com.jme3.effect). +

+ +
+ +

Sample Code

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.effect.ParticleEmitter;
+import com.jme3.effect.ParticleMesh;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+ 
+/** Sample 11 - how to create fire, water, and explosion effects. */
+public class HelloEffects extends SimpleApplication {
+ 
+  public static void main(String[] args) {
+    HelloEffects app = new HelloEffects();
+    app.start();
+  }
+ 
+  @Override
+  public void simpleInitApp() {
+ 
+    ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
+    Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
+    mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
+    fire.setMaterial(mat_red);
+    fire.setImagesX(2); fire.setImagesY(2); // 2x2 texture animation
+    fire.setEndColor(  new ColorRGBA(1f, 0f, 0f, 1f));   // red
+    fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
+    fire.setInitialVelocity(new Vector3f(0, 2, 0));
+    fire.setStartSize(1.5f);
+    fire.setEndSize(0.1f);
+    fire.setGravity(0);
+    fire.setLowLife(0.5f);
+    fire.setHighLife(3f);
+    fire.setVelocityVariation(0.3f); 
+    rootNode.attachChild(fire);
+ 
+    ParticleEmitter debris = new ParticleEmitter("Debris", ParticleMesh.Type.Triangle, 10);
+    Material debris_mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
+    debris_mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/Debris.png"));
+    debris.setMaterial(debris_mat);
+    debris.setImagesX(3); debris.setImagesY(3); // 3x3 texture animation
+    debris.setRotateSpeed(4);
+    debris.setSelectRandomImage(true);
+    debris.setInitialVelocity(new Vector3f(0, 4, 0));
+    debris.setStartColor(new ColorRGBA(1f, 1f, 1f, 1f));
+    debris.setGravity(6f);
+    debris.setVelocityVariation(.60f);
+    rootNode.attachChild(debris);
+    debris.emitAllParticles();
+ 
+  }
+}
+

+You should see an explosion that sends debris flying, and a fire. + +

+ +
+ +

Texture Animation and Variation

+
+ +

+ + +

+ +

+Start by choosing a material texture for your effect. If you provide the emitter with a set of textures (see image), it can use them either for variation (random order), or as animation steps (fixed order). +

+ +

+Setting emitter textures works just as you have already learned in previous chapters. This time we use the Particle.j3md default material. In the following example, we have a closer look at the Debris effect. +

+
    ...
+    Material debris_mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
+    debris_mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/Debris.png"));
+    debris.setMaterial(debris_mat);
+    debris.setImagesX(3); // columns
+    debris.setImagesY(3); // rows
+    debris.setSelectRandomImage(true);
+    ...
    +
  1. Load the texture in the emitter's material.
    +
  2. +
  3. Tell the Emitter into how many animation steps (x*y) the texture is divided. 1×1 is default.
    +
  4. +
  5. Optionally, tell the Emitter whether the animation steps are to be at random, or in order.
    +
  6. +
+ +

+ +As you see in the debris example, texture animations improve effects because each “flame” or “piece of debris” looks different. Also think of electric or magic effects, where you can create very interesting animations by using an ordered morphing series of lightning bolts; or flying leaves or snow flakes, for instance. +

+ +
+ +

Default Particle Textures

+
+ +

+ +The following effect textures are some of the example textures included in test-data.jar. + +

+ + + + + + + + + + + + + + + + + + + +
Texture Path Dimension Preview
Effects/Explosion/Debris.png 3*3
Effects/Explosion/flame.png 2*2
Effects/Explosion/shockwave.png 1*1
Effects/Explosion/smoketrail.png 1*3
Effects/Smoke/Smoke.png 1*15
+ +

+ +Copy them into you assets/Effects directory to use them. +

+ +
+ +

Creating Custom Textures

+
+ +

+ +For your game, you will likely create custom textures. Look at the fire example again. +

+
    ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
+    Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
+    mat_red.setTexture("m_Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
+    fire.setMaterial(mat_red);
+    fire.setImagesX(2); // columns 
+    fire.setImagesY(2); // rows
+    fire.setEndColor(  new ColorRGBA(1f, 0f, 0f, 1f));   // red
+    fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
+

+ +

+
    +
  • Black parts of the image will be rendered transparent.
    +
  • +
  • White/gray parts of the image are transparent and will be colored.
    +
  • +
  • You set the color (here, a gradient from yellow to red) in the code.
    +
  • +
  • By default the animation will be played in order (?) and loop.
    +
  • +
+ +

+ +Create a grayscale texture in a graphic editor, and save it to your assets/Effects directory. If you split up one image file into x*y animation steps, make sure each animation step is of equal size–just as you see in the examples here. +

+ +
+ +

Emitter Parameters

+
+ +

+ +A particle system is always centered around an emitter. +

+ +

+Use the setShape() method to change the EmitterShape: +

+
    +
  • EmitterPointShape(Vector3f.ZERO) – default shape
    +
  • +
  • EmitterSphereShape(Vector3f.ZERO,2f)
    +
  • +
  • EmitterBoxShape(new Vector3f(-1f,-1f,-1f),new Vector3f(1f,1f,1f))
    +
  • +
+ +

+Example: emitter.setShape(new EmitterPointShape(Vector3f.ZERO)); +

+ +

+You create different effects by changing the emitter parameters: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter Method (default value) Description
number setNumParticles() The maximum number of particles visible at the same time. Value is specified by user in constructor.
velocity setInitialVelocity() (Vector3f.ZERO) You must specify a vector how fast particles should move and it which start direction.
direction setVelocityVariation() (0.2f)
+ setFacingVelocity() (false)
+ setRandomAngle() (false)
+ setFaceNormal() (Vector3f.NAN)
+ setRotateSpeed() (0f)
Optional accessors that control in which direction particles face when flying.
lifetime setLowLife() (3f)
+ setHighLife() (7f)
Minimum and maximum time period before particles fade.
emission rate setParticlesPerSec() (20) How many new particles are emitted per second.
color setStartColor()
+ setEndColor() (gray)
Set to two different colors for gradient effects, or to same color.
size setStartSize() (0.2f)
+ setEndSize() (2f)
Set to two different values for shrink/grow effect, or to same size.
gravity setGravity() (0.1f) Whether particles falls down eventually. Set to 0f for zero-g effects.
+ +

+ +You can find details about effect parameters in the user guide. +Add and modify one paramter at a time, and try different values until you get the effect you want. Tip: Use the jMonkeyPlatform SceneComposer to preview effects settings (instructions: TODO). +

+ +
+ +

Exercise

+
+ +

+ +Can you “invert” the campfire into a small waterfall? +

+
    +
  • Change the Red and Yellow color to Cyan and Blue…
    +
  • +
  • Invert the velocity vector (direction) by using a negative number…
    +
  • +
  • Swap start and end size…
    +
  • +
  • Activate gravity by setting it to 1…
    +
  • +
+ +
+ +

Conclusion

+
+ +

+ +You have learned that many different effects can be created by changing the parameters and textures of one general emitter object. +

+ +

+Now we move on to the next exciting chapter – the simulation of . Let's shoot some cannon balls at a brick wall! + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_input_system.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_input_system.html new file mode 100644 index 000000000..6710fb541 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_input_system.html @@ -0,0 +1,353 @@ + +

Getting Started with JME3 (5) - Hello Input System

+
+ +

+ +Previous: Hello Event Loop, +Next: Hello Material +

+ +

+ +By default, SimpleApplication sets up an input system that allows you to steer the camera with the WASD keys, the arrow keys, and the mouse. You can use it as a flying first-person camera right away. But what if you need a third-person camera, or you want keys to trigger special game actions? +

+ +

+Every game has its custom keybindings, and this tutorial explains how you define them. We first define the key presses and mouse events, and then we define the actions they should trigger. +

+ +
+ +

Sample Code

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.material.Material;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.math.ColorRGBA;
+import com.jme3.input.KeyInput;
+import com.jme3.input.MouseInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.AnalogListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.input.controls.MouseButtonTrigger;
+ 
+/** Sample 5 - how to map keys and mousebuttons to actions */
+public class HelloInput extends SimpleApplication {
+ 
+  public static void main(String[] args) {
+    HelloInput app = new HelloInput();
+    app.start();
+  }
+  protected Geometry player;
+  Boolean isRunning=true;
+ 
+  @Override
+  public void simpleInitApp() {
+    Box(Vector3f.ZERO, 1, 1, 1);
+    player = new Geometry("Player", b);
+    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mat.setColor("Color", ColorRGBA.Blue);
+    player.setMaterial(mat);
+    rootNode.attachChild(player);
+    initKeys(); // load my custom keybinding
+  }
+ 
+  /** Custom Keybinding: Map named actions to inputs. */
+  private void initKeys() {
+    // You can map one or several inputs to one named action
+    inputManager.addMapping("Pause",  new KeyTrigger(KeyInput.KEY_P));
+    inputManager.addMapping("Left",   new KeyTrigger(KeyInput.KEY_J));
+    inputManager.addMapping("Right",  new KeyTrigger(KeyInput.KEY_K));
+    inputManager.addMapping("Rotate", new KeyTrigger(KeyInput.KEY_SPACE),
+                                      new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
+    // Add the names to the action listener.
+    inputManager.addListener(actionListener, new String[]{"Pause"});
+    inputManager.addListener(analogListener, new String[]{"Left", "Right", "Rotate"});
+ 
+  }
+ 
+  private ActionListener() {
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Pause") && !keyPressed) {
+        isRunning = !isRunning;
+      }
+    }
+  };
+ 
+  private AnalogListener analogListener = new AnalogListener() {
+    public void onAnalog(String name, float value, float tpf) {
+      if (isRunning) {
+        if (name.equals("Rotate")) {
+          player.rotate(0, value*speed, 0);
+        }
+        if (name.equals("Right")) {
+          Vector3f v = player.getLocalTranslation();
+          player.setLocalTranslation(v.x + value*speed, v.y, v.z);
+        }
+        if (name.equals("Left")) {
+          Vector3f v = player.getLocalTranslation();
+          player.setLocalTranslation(v.x - value*speed, v.y, v.z);
+        }
+      } else {
+        System.out.println("Press P to unpause.");
+      }
+    }
+  };
+}
+

+Build and run the example. +

+
    +
  • Press the Spacebar or click to rotate the cube.
    +
  • +
  • Press the J and K keys to move the cube.
    +
  • +
  • Press P to pause and unpause the game. While paused, the game should not respond to any input, other than P.
    +
  • +
+ +
+ +

Defining Mappings and Triggers

+
+ +

+ +First you register each mapping name with its trigger(s). Remember the following: + +

+
    +
  • The trigger can be a key press or mouse action.
    +
  • +
  • The mapping name is a string that you can choose.
    + The name should describe the action, not the trigger.
    +
  • +
  • One named mapping can have several triggers.
    + The “Rotate” action can be triggered by a click and by pressing the spacebar.
    +
  • +
+ +

+ +Have a look at the code: +

+
    +
  1. You register the mapping named “Rotate” to the Spacebar trigger
    + new KeyTrigger(KeyInput.KEY_SPACE)).
    +
  2. +
  3. In the same line, you also register “Rotate” to the mouse button trigger
    + new MouseButtonTrigger(MouseInput.BUTTON_LEFT)
    +
  4. +
  5. You map the Pause, Left, Right mappings to the P, J, K keys, respectively.
    +
  6. +
  7. You register the (on/off) pause action to the ActionListener
    +
  8. +
  9. You register the (gradual) movement actions to the AnalogListener
    +
  10. +
+
    // You can map one or several inputs to one named action
+    inputManager.addMapping("Pause",  new KeyTrigger(KeyInput.KEY_P));
+    inputManager.addMapping("Left",   new KeyTrigger(KeyInput.KEY_J));
+    inputManager.addMapping("Right",  new KeyTrigger(KeyInput.KEY_K));
+    inputManager.addMapping("Rotate", new KeyTrigger(KeyInput.KEY_SPACE),
+                                      new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
+    // Add the names to the action listener.
+    inputManager.addListener(actionListener, new String[]{"Pause"});
+    inputManager.addListener(analogListener, new String[]{"Left", "Right", "Rotate"});
+

+This code usually goes into the simpleInitApp() method. But since we will likely add many keybindings, we extract these lines and wrap them in an auxiliary method, initKeys(). The initKeys() method is not part of the Input Controls interface – so you can name it whatever you like. Just don't forget to call your method from the initSimpleApp() method. +

+ +
+ +

Implementing the Actions

+
+ +

+ +Now you have mapped action names to input triggers. Now you specify the actions themselves. +

+ +

+The two important methods here are the ActionListener with its onAction() method, and the AnalogListener with its onAnalog() method. In these two methods, you test for each named mapping, and call the game action you want to trigger. +

+ +

+In this example, we set the following mappings: + +

+
    +
  1. The Rotate mapping triggers the action player.rotate(0, value, 0).
    +
  2. +
  3. The Left and Right mappings increase and decrease the player's x coordinate.
    +
  4. +
  5. The Pause mapping flips a boolean isRunning.
    +
  6. +
  7. We also want to check the boolean isRunning before any action (other than unpausing) is executed.
    +
  8. +
+
  private ActionListener() {
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Pause") && !keyPressed) {
+        isRunning = !isRunning;
+      }
+    }
+  };
+ 
+  private AnalogListener analogListener = new AnalogListener() {
+    public void onAnalog(String name, float value, float tpf) {
+      if (isRunning) {
+        if (name.equals("Rotate")) {
+          player.rotate(0, value*speed, 0);
+        }
+        if (name.equals("Right")) {
+          Vector3f v = player.getLocalTranslation();
+          player.setLocalTranslation(v.x + value*speed, v.y, v.z);
+        }
+        if (name.equals("Left")) {
+          Vector3f v = player.getLocalTranslation();
+          player.setLocalTranslation(v.x - value*speed, v.y, v.z);
+        }
+      } else {
+        System.out.println("Press P to unpause.");
+      }
+    }
+  };
+

+It's okay to use only one of the two Listeners, and not implement the other one, if you are not using this type of interaction. In the following, we have a closer look how to decide which of the two listeners is best suited for which situation. +

+ +
+ +

Analog, Pressed, or Released?

+
+ +

+ +Technically, every input can be an “Analog” or a “on-off Action”. Here is how you find out which listener is the right one for which type of input. +

+ +

+Mappings registered to the AnalogListener are triggered repeatedly and gradually. +

+
    +
  • Parameters:
    +
      +
    1. JME gives you access to the name of the triggered action.
      +
    2. +
    3. JME gives you access to a gradual value between 0-9 how long the key has been pressed.
      +
    4. +
    +
  • +
  • Example: Navigational events (e.g. Left, Right, Rotate, Run, Strafe), situations where you interact continuously.
    +
  • +
+ +

+ +Mappings registered to the ActionListener are treated in an absolute way – “Pressed or released? On or off?” +

+
    +
  • Parameters:
    +
      +
    1. JME gives you access to the name of the triggered action.
      +
    2. +
    3. JME gives you access to a boolean whether the key is pressed or not.
      +
    4. +
    +
  • +
  • Example: Pause button, shooting, selecting, jumping, one-time click interactions.
    +
  • +
+ +

+ +Tip: It's very common that you want an action to be only triggered once, in the moment when the key is released. For instance when opening a door, flipping a boolean state, or picking up an item. To achieve that, you use an ActionListener and test for … && !keyPressed. For an example, look at the Pause button code. +

+
      if (name.equals("Pause") && !keyPressed) {
+        isRunning = !isRunning;
+      }
+
+ +

Table of Triggers

+
+ +

+ +You can find the list of input constants in the files src/core/com/jme3/input/KeyInput.java, JoyInput.java, and MouseInput.java. Here is an overview of the most common triggers constants: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Trigger Code
Mouse button: Left Click MouseButtonTrigger(MouseInput.BUTTON_LEFT)
Mouse button: Right Click MouseButtonTrigger(MouseInput.BUTTON_RIGHT)
Keyboard: Characters and Numbers KeyTrigger(KeyInput.KEY_X)
Keyboard: Spacebar KeyTrigger(KeyInput.KEY_SPACE)
Keyboard: Return, Enter KeyTrigger(KeyInput.KEY_RETURN), KeyTrigger(KeyInput.KEY_NUMPADENTER)
Keyboard: Escape KeyTrigger(KeyInput.KEY_ESCAPE)
Keyboard: Arrows KeyTrigger(KeyInput.KEY_UP), KeyTrigger(KeyInput.KEY_DOWN)
+ KeyTrigger(KeyInput.KEY_LEFT), KeyTrigger(KeyInput.KEY_RIGHT)
+ +

+ +Tip: If you don't recall an input constant during development, you benefit from an IDE's code completion functionality: Place the caret after e.g. KeyInput.| and trigger code completion to select possible input identifiers. +

+ +
+ +

Exercises

+
+
    +
  1. Add mappings for moving the player (box) up and down with the H and L keys.
    +
  2. +
  3. Modify the mappings so that you can also trigger the up an down motion with the mouse scroll wheel.
    +
      +
    • Tip: Use new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true)
      +
    • +
    +
  4. +
  5. In which situation would it be better to use variables for the MouseInput/KeyInput definitions?
    int usersPauseKey = KeyInput.KEY_P; 
    +...
    +inputManager.addMapping("Pause",  new KeyTrigger(usersPauseKey));
    +
  6. +
+ +
+ +

Conclusion

+
+ +

+ +You now how to add custom interactions to your game: You know now that you first have to define the key mappings, and then the actions for each mapping. You have learned to respond to mouse events and to the keyboard. You understand the difference between “analog” (gradually repeated) and “digital” (on/off) inputs. +

+ +

+Now you can already write a little interactive game! But wouldn't it be cooler if these old boxes were a bit more fancy? Let's continue with learning about materials. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_main_event_loop.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_main_event_loop.html new file mode 100644 index 000000000..f539b72ec --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_main_event_loop.html @@ -0,0 +1,160 @@ + +

Getting Started with JME3 (4) - Hello Event Loop

+
+ +

+ +
+ +Previous: Hello Assets, +Next: Hello Input System +
+ +
+ +Now that you know how to load assets such as 3-D models, you want them to implement the actual gameplay. The event loop of your game is where the action happens. +

+ +
+ +

Code Sample

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+ 
+/** Sample 4 - how to trigger repeating actions from the main event loop.
+ * In this example, we make the player character rotate. */
+public class HelloLoop extends SimpleApplication {
+ 
+    public static void main(String[] args){
+        HelloLoop app = new HelloLoop();
+        app.start();
+    }
+ 
+    protected Geometry player;
+ 
+    @Override
+    public void simpleInitApp() {
+ 
+        Box(Vector3f.ZERO, 1, 1, 1);
+        player = new Geometry("blue cube", b);
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setColor("Color", ColorRGBA.Blue);
+        player.setMaterial(mat);
+        rootNode.attachChild(player);
+    }
+ 
+    /* This is the main event loop */
+    @Override
+    public void simpleUpdate(float tpf) {
+        // make the player rotate
+        player.rotate(0, 2*tpf, 0); 
+    }
+}
+

+Build and run the file: You see a constantly rotating cube. +

+ +
+ +

Understanding the Code

+
+ +

+ +Compared to our previous code samples you note that the player Geometry is now a class field. This is because we want the main event loop to be able to access and transform this Geometry. As you can see, we initialize the player object in the simpleInitApp() method. +

+ +

+
+ +Now have a closer look at the simpleUpdate() method, this is the main event loop. +

+
    +
  • The player.rotate(0, 2*tpf, 0); line changes the rotation of the player object.
    +
  • +
  • We use the tpf variable (“time per frame”) to time this action depending on the current frames per second rate. This means the cube rotates with the same speed on fast machines, and the game remains playable.
    +
  • +
+ +
+ +

The Event Loop

+
+ +

+ +A rotating object is just a simple example. In the event loop, you can update score and health points, check for collisions, make enemies calculate their next move, roll the dice whether a trap has been set off, play random ambient sounds, and much more. +

+ +

+
+ +

+
    +
  • The event loop starts after the simpleInitApp() method has set up the scenegraph and state variables.
    +
  • +
  • JME executes everything in the simpleUpdate() method repeatedly, as fast as possible.
    +
      +
    1. Use the loop to poll the game state and initiate actions.
      +
    2. +
    3. Use the loop to trigger reactions and update the game state.
      +
    4. +
    5. Use it wisely, because having too many calls in the loop also slows down the game.
      +
    6. +
    +
  • +
+ +
+ +

Exercises

+
+ +

+ +Here are some fun things to try: +

+
    +
  1. What happens if you give the rotate() method negative numbers?
    +
  2. +
  3. Can you create two models next to each other, and make one rotate twice as fast as the other? (use the tpf)
    +
  4. +
  5. Can you make a cube that pulsates? (grows and shrinks)
    +
  6. +
  7. Can you make a rolling cube? (spin around the x axis, and translate along the z axis)
    +
  8. +
+ +

+ +Look back at the Hello Node tutorial if you do not remember the transformation methods for scaling, translating, and rotating. +

+ +
+ +

Conclusion

+
+ +

+ +Now you are listening to the update loop, “the heart beat” of the game, and you can add all kinds of action to it. +

+ +

+The next thing the game needs is some interaction! Continue learning how to respond to user input. +

+
+ +

+See also: Advanced jME3 developers additionally use Application States and Custom Controls to implement more complex mechanics in their game loops. You will come across these topics later when you proceed to advanced documentation. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_material.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_material.html new file mode 100644 index 000000000..7631f46ea --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_material.html @@ -0,0 +1,402 @@ + +

Getting Started with JME3 (6) - Hello Materials

+
+ +

+ +Previous: Hello Input System, +Next: Hello Animation +

+ +

+When we speak of Materials, we mean everything that influences what the surface of a 3D model looks like: The color, texture, and material (shininess, opacity/transparency). Simple Coloring is covered in Hello Node. Loading models that come with materials is covered in Hello Asset. Here we focus on using and creating . +

+ +

+ +

+ +
+ +

Sample Code

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.material.RenderState.BlendMode;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.scene.shape.Sphere;
+import com.jme3.texture.Texture;
+import com.jme3.util.TangentBinormalGenerator;
+ 
+/** Sample 6 - how to give an object's surface a material and texture.
+ * How to make objects transparent, or let colors "leak" through partially
+ * transparent textures. How to make bumpy and shiny surfaces.  */
+public class HelloMaterial extends SimpleApplication {
+ 
+  public static void main(String[] args) {
+    HelloMaterial app = new HelloMaterial();
+    app.start();
+  }
+ 
+  @Override
+  public void simpleInitApp() {
+ 
+    /** A simple textured cube -- in good MIP map quality. */
+    Box(new Vector3f(-3f,1.1f,0f), 1f,1f,1f);
+    Geometry cube = new Geometry("My Textured Box", boxshape1);
+    Material mat_stl = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    Texture tex_ml = assetManager.loadTexture("Interface/Logo/Monkey.jpg");
+    mat_stl.setTexture("ColorMap", tex_ml);
+    cube.setMaterial(mat_stl);
+    rootNode.attachChild(cube);
+ 
+    /** A translucent/transparent texture, similar to a window frame. */
+    Box(new Vector3f(0f,0f,0f), 1f,1f,0.01f);
+    Geometry window_frame = new Geometry("window frame", boxshape3);
+    Material mat_tt = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mat_tt.setTexture("ColorMap", 
+        assetManager.loadTexture("Textures/ColoredTex/Monkey.png"));
+    mat_tt.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
+    window_frame.setMaterial(mat_tt);
+    rootNode.attachChild(window_frame);
+ 
+    /** A cube with base color "leaking" through a partially transparent texture */
+    Box(new Vector3f(3f,-1f,0f), 1f,1f,1f);
+    Geometry cube_leak = new Geometry("Leak-through color cube", boxshape4);
+    Material mat_tl = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mat_tl.setTexture("ColorMap", 
+        assetManager.loadTexture("Textures/ColoredTex/Monkey.png"));
+    mat_tl.setColor("Color", new ColorRGBA(1f,0f,1f, 1f)); // purple
+    cube_leak.setMaterial(mat_tl);
+    rootNode.attachChild(cube_leak);
+ 
+    /** A bumpy rock with a shiny light effect */
+    Sphere rock = new Sphere(32,32, 2f);
+    Geometry shiny_rock = new Geometry("Shiny rock", rock);
+    rock.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres
+    TangentBinormalGenerator.generate(rock);           // for lighting effect
+    Material mat_lit = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
+    mat_lit.setTexture("DiffuseMap", 
+        assetManager.loadTexture("Textures/Terrain/Pond/Pond.png"));
+    mat_lit.setTexture("NormalMap", 
+        assetManager.loadTexture("Textures/Terrain/Pond/Pond_normal.png"));
+    mat_lit.setFloat("Shininess", 5f); // [0,128]
+    shiny_rock.setMaterial(mat_lit);
+    shiny_rock.setLocalTranslation(0,2,-2); // Move it a bit
+    shiny_rock.rotate(1.6f, 0, 0);          // Rotate it a bit
+    rootNode.attachChild(shiny_rock);
+    /** Must add a light to make the lit object visible! */
+    DirectionalLight sun = new DirectionalLight();
+    sun.setDirection(new Vector3f(1,0,-2).normalizeLocal());
+    sun.setColor(ColorRGBA.White);
+    rootNode.addLight(sun);
+ 
+  }
+}
+

+You should see +

+
    +
  • Left – A cube with a brown monkey texture.
    +
  • +
  • Middle – A translucent monkey picture in front of a shiny rock.
    +
  • +
  • Right – A cube with a purple monkey texture.
    +
  • +
+ +

+Move around with the WASD keys to have a closer look at the translucency, and the rock's bumpiness. +

+ +
+ +

Simple Unshaded Texture

+
+ +

+ +Typically you want to give objects in your scene textures: It can be rock, grass, brick, wood, water, metal, paper… A texture is a normal image file in JPG or PNG format. In this example, we create a box with a simple unshaded Monkey texture as material. +

+
    /** A simple textured cube. */
+    Box(new Vector3f(-3f,1.1f,0f), 1f,1f,1f);
+    Geometry cube = new Geometry("My Textured Box", boxshape1);
+    Material mat_stl = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    Texture tex_ml = assetManager.loadTexture("Interface/Logo/Monkey.jpg");
+    mat_stl.setTexture("ColorMap", tex_ml);
+    cube.setMaterial(mat_stl);
+    rootNode.attachChild(cube);
+

+Here is what we did: +

+
    +
  1. Create a Geometry from a mesh. This geometry is a cube.
    +
  2. +
  3. Create a Material based on jME3's default Unshaded.j3md material definition.
    +
  4. +
  5. Create a texture from the Monkey.jpg file and load it into the material.
    + The ColorMap is the material layer where textures go.
    +
  6. +
  7. Apply the material to the cube and attach the cube to the rootnode.
    +
  8. +
+ +
+ +

Transparent Unshaded Texture

+
+ +

+ +Monkey.png is the same texture as Monkey.jpg, but with an added alpha channel. The alpha channel allows you to specify which areas of the texture you want to be translucent: Black areas remain opaque, gray areas become translucent, and white areas become transparent. In combination with setting the texture blend mode to BlendMode.Alpha, this results in a partially translucent/transparent texture! +

+
    /** A translucent/transparent texture. */
+    Box(new Vector3f(0f,0f,0f), 1f,1f,0.01f);
+    Geometry seethrough = new Geometry("see-through box", boxshape3);
+    Material mat_tt = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mat_tt.setTexture("ColorMap", 
+        assetManager.loadTexture("Textures/ColoredTex/Monkey.png"));
+    mat_tt.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); // activate transparency
+    seethrough.setMaterial(mat_tt);
+    rootNode.attachChild(seethrough);
+

+What we did it the same as before, with only one added step for the transparency. +

+
    +
  1. Create a Geometry from a mesh. This Geometry is flat upright box.
    +
  2. +
  3. Create a Material based on jME3's default Unshaded.j3md material definition.
    +
  4. +
  5. Create a texture from the Monkey.png file and load it into the material.
    + The ColorMap is the material layer where textures go. The PNG file must have an alpha layer.
    +
  6. +
  7. Activate transparency in the material by setting the blend mode to Alpha!
    +
  8. +
  9. Apply the material to the cube and attach the cube to the rootnode.
    +
  10. +
+ +

+ +Tip: Learn more about creating PNG images with an alpha layer in the help system of your graphic editor. +

+ +
+ +

Shininess and Bumpiness

+
+ +

+ +But textures are not all. Have a look at the shiny bumpy sphere again – you cannot get such a nice material with just a texture. We will have a quick look at some advanced jme features here – lit materials: +

+ +

+In a lit material, the standard texture layer is refered to as Diffuse Map, any material can have it. A lit material can additionally have lighting effects such as Shininess used together with the Specular Map layer, and even a realistically bumpy or cracked surface with help of the Normal Map layer. +

+ +

+Let's have a look at the part of the code example where you create the shiny bumpy rock. +

+
    +
  1. Create a Geometry from a mesh. This Geometrx is a normal smooth sphere.
        Sphere rock = new Sphere(32,32, 2f);
    +    Geometry shiny_rock = new Geometry("Shiny rock", rock);
    +
      +
    1. (Only for Spheres) Change the sphere's TextureMode to make the square texture project better onto the sphere.
          rock.setTextureMode(Sphere.TextureMode.Projected); 
      +
    2. +
    3. You generate TangentBinormals to enable rendering the bumpiness (stored in the NormalMap) of the texture.
          TangentBinormalGenerator.generate(rock);
      +
    4. +
    +
  2. +
  3. Create a material based on the Lighting.j3md default material.
        Material mat_lit = new Material(assetManager, 
    +        "Common/MatDefs/Light/Lighting.j3md");
    +
      +
    1. Set a standard rocky texture in the DiffuseMap layer.
      +
          mat_lit.setTexture("DiffuseMap", 
      +        assetManager.loadTexture("Textures/Terrain/Pond/Pond.png"));
      +
    2. +
    3. Set the NormalMap layer that contains the bumpiness. The NormalMap was generated for this particular DiffuseMap with a special tool (e.g. Blender).
          mat_lit.setTexture("NormalMap", 
      +        assetManager.loadTexture("Textures/Terrain/Pond/Pond_normal.png"));
      +
    4. +
    5. Set the material's Shininess to a value between 0 and 127.
          mat_lit.setFloat("Shininess", 5f); // [0,128]
      +
    6. +
    +
  4. +
  5. Assign your newly created material to the rock.
        shiny_rock.setMaterial(mat_lit);
    +
  6. +
  7. Let's move and rotate the geometry a bit to position it better.
        shiny_rock.setLocalTranslation(0,2,-2); // Move it a bit
    +    shiny_rock.rotate(1.6f, 0, 0);          // Rotate it a bit
    +    rootNode.attachChild(shiny_rock);
    +
  8. +
  9. Note that any lighting material requires a light source.
    +
  10. +
+ +
+ +

Default Material Definitions

+
+ +

+ +As you have seen, the following default materials can always be found in jme/core-data/Common. + +

+ + + + + + + + + + +
Default Definition Usage Parameters
Common/MatDefs/Misc/Unshaded.j3md Textured: Use with mat.setTexture() and TextureKey.
+ Colored: Use with mat.setColor() and RGBAColor.
ColorMap : Texture.
Common/MatDefs/Light/Lighting.j3md Use with shiny Textures, Bump- and NormalMaps textures.
+ Requires a light source.
Ambient, Diffuse, Specular : Color
+ DiffuseMap, NormalMap, SpecularMap : Texture
+ Shininess : Float
+ +

+ +In a real game, you will create your custom Materials based these existing ones – as you have just seen in the example with the shiny rock. +

+ +
+ +

Exercises

+
+ +
+ +

Exercise 1: Custom Materials

+
+ +

+ +Look at the purple leak-through sample above again. It takes four lines to create and set the Material. +

+
    +
  • Note how it loads the Unshaded.j3md Material definition.
    +
  • +
  • Note how it sets to Color parameter to purple (new ColorRGBA(1f,0f,1f,1f)).
    +
  • +
  • Note how it sets the ColorMap to a texture path.
    +
  • +
+ +

+If you want to use one custom material for several models, you can store it in a .j3m file, and save a few lines of code every time. Here is an example: +

+ +

+Create a file assets/Materials/LeakThrough.j3m with the following content: + +

+
Material Leak Through : Common/MatDefs/Misc/Unshaded.j3md {
+     MaterialParameters {
+         Color : 1 0 1 1
+         ColorMap : Textures/ColoredTex/Monkey.png
+     }
+}
+
    +
  • Note that Material is a keyword.
    +
  • +
  • Note that Leak Through is a name that you can choose.
    +
  • +
  • Note how it sets the same three properties, Color, ColorMap, and Unshaded.j3md.
    +
  • +
+ +

+Using this new custom material LeakThrough.j3m only takes one line. +

+
    +
  1. In the code sample, comment out the three lines with mat_tl in them.
    +
  2. +
  3. Below them, add the following line:
    cube_leak.setMaterial((Material) assetManager.loadAsset( "Materials/LeakThrough.j3m"));
    +
  4. +
  5. Run the app. The result is the same.
    +
  6. +
+ +

+ +You have replaced the three lines of an on-the-fly material definition with one line that loads a custom material from a file. This method is very handy if you use the same material often. +

+ +
+ +

Exercise 2: Bumpiness and Shininess

+
+ +

+ +Go back to the bumpy rock sample above: +

+
    +
  1. Comment out the DiffuseMap line, and run the app. (Uncomment it again.)
    +
  2. +
  3. Comment out the NormalMap line, and run the app. (Uncomment it again.)
    +
      +
    • Compare: Which property of the rock is lost in either case?
      +
    • +
    +
  4. +
  5. Change the value of Shininess to values like 0, 63, 127.
    +
      +
    • What aspect of the Shininess changes?
      +
    • +
    +
  6. +
+ +
+ +

Conclusion

+
+ +

+ +You have learned how to create a Material, specify its properties, and use it on a Geometry. You know how to load an image file (.png, .jpg) as texture into a material. You know to save texture files in a subfolder of your project's assets/Textures/ directory. +

+ +

+You have also learned that a material can be stored in a .j3m file. The file references a built-in Material Definition and specifies values for properties of that MaterialDefinition. You know to save your custom .j3m files in your project's assets/Materials/ directory. +

+ +

+Now that you know how to load models and how to assign good-looking materials to them, let's have a look at how to animate models in the next chapter, Hello Animation. + +

+
+ +

+See also +

+
    +
  • +
  • +
  • +
  • +
  • forum thread
    +
  • +
  • (PDF)
    +
  • +
  • +
  • +
  • +
  • +
  • (Not done with JME3, this is just to show the fantastic range of Material parameters in the hands of an expert, until we have a JME3 demo for it.)
    +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_node.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_node.html new file mode 100644 index 000000000..366303f20 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_node.html @@ -0,0 +1,316 @@ + +

Getting Started with JME3 (2) - Hello Node

+
+ +

+ +Previous: Hello SimpleApplication, +Next: Hello Assets. +

+ +

+When creating a 3D game, you start out with creating a scene and some objects. You place the objects (player tokens, obstacles, etc) in the scene, and move, resize, rotate, color, and animate them. +

+ +

+In this Tutorial we will have a look at a simple 3D scene. You will learn that the 3D world is represented in a scene graph, and why the rootNode is important. You will learn how to create simple objects and how to transform them – move, scale, rotate. You will understand the difference between the two types of Spatials in the scene graph, Node and Geometry. For a visual introduction to the scene graph check out our Scene Graph for Dummies presentation. +

+ +
+ +

Code Sample

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.material.Material;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.math.ColorRGBA;
+import com.jme3.scene.Node;
+ 
+/** Sample 2 - How to use nodes as handles to manipulate objects in the scene graph.
+ * You can rotate, translate, and scale objects by manipulating their parent nodes.
+ * The Root Node is special: Only what is attached to the Root Node appears in the scene. */
+public class HelloNode extends SimpleApplication {
+ 
+    public static void main(String[] args){
+        HelloNode app = new HelloNode();
+        app.start();
+    }
+ 
+    @Override
+    public void simpleInitApp() {
+ 
+        // create a blue box at coordinates (1,-1,1)
+        Box( new Vector3f(1,-1,1), 1,1,1);
+        Geometry blue = new Geometry("Box", box1);
+        Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat1.setColor("Color", ColorRGBA.Blue);
+        blue.setMaterial(mat1);
+ 
+        // create a red box straight above the blue one at (1,3,1)
+        Box( new Vector3f(1,3,1), 1,1,1);
+        Geometry red = new Geometry("Box", box2);
+        Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat2.setColor("Color", ColorRGBA.Red);
+        red.setMaterial(mat2);
+ 
+        // create a pivot node at (0,0,0) and attach it to root
+        Node pivot = new Node("pivot");
+        rootNode.attachChild(pivot);
+ 
+        // attach the two boxes to the *pivot* node!
+        pivot.attachChild(blue);
+        pivot.attachChild(red);
+        // rotate pivot node: Both boxes have rotated!
+        pivot.rotate( 0.4f , 0.4f , 0.0f );
+ 
+    }
+}
+

+Build and run the code sample. You should see two colored boxes tilted at the same angle. +

+ +
+ +

Understanding the Terminology

+
+ +

+ +In this tutorial, you will learn some new terms: + +

+
    +
  1. The scene graph represents your 3D world.
    +
  2. +
  3. Objects in the scene graph (such as the boxes in this example) are called Spatials.
    +
      +
    • A Spatial is a collection of information about an object: its location, rotation, and scale.
      +
    • +
    • A Spatial can be loaded, transformed, and saved.
      +
    • +
    +
  4. +
  5. There are two types of Spatials, Nodes and Geometries.
    +
  6. +
  7. To add a Spatial to the scene graph, you attach the Spatial to the rootNode.
    +
  8. +
  9. Everything attached to the rootNode is part of the scene graph.
    +
  10. +
+ +
+ +

Understanding the Code

+
+ +

+ +So what exactly happens in this code snippet? Note that we are using the simpleInitApp() method that was introduced in the first tutorial. + +

+
    +
  1. We create a box Geometry.
    +
      +
    • The box Geometry's extends are (1,1,1), that makes it 2x2x2 world units big.
      +
    • +
    • We place the box at (1,-1,1)
      +
    • +
    • We give it a solid blue material.
              Box( new Vector3f(1,-1,1), 1,1,1);
      +        Geometry blue = new Geometry("Box", box1);
      +        Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
      +        mat1.setColor("Color", ColorRGBA.Blue);
      +        blue.setMaterial(mat1);
      +
    • +
    +
  2. +
  3. We create a second box Geometry.
    +
      +
    • This box Geometry is also 2x2x2 world units big.
      +
    • +
    • We place the second box at (1,3,1). This is straight above the blue box, with a gap of 2 world units inbetween.
      +
    • +
    • We give it a solid red material
              Box( new Vector3f(1,3,1), 1,1,1);
      +        Geometry red = new Geometry("Box", box2);
      +        Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
      +        mat2.setColor("Color", ColorRGBA.Red);
      +        red.setMaterial(mat2);
      +
    • +
    +
  4. +
  5. We create a Node.
    +
      +
    • By default the Node is placed at (0,0,0).
      +
    • +
    • We attach the Node to the rootNode.
      +
    • +
    • An attached Node has no visible appearance in the scene.
              Node pivot = new Node("pivot");
      +        rootNode.attachChild(pivot);
      +
    • +
    +
  6. +
  7. Note that we have not attached the two boxes to anything yet!
    +
      +
    • If we ran the application now, the scenegraph would appear empty.
      +
    • +
    +
  8. +
  9. We attach the two boxes to the node.
    +
      +
    • If we ran the app now, we would see two boxes: one straight above the other.
              pivot.attachChild(blue);
      +        pivot.attachChild(red); 
      +
    • +
    +
  10. +
  11. Now, we rotate the node.
    +
      +
    • When we run the application now, we see two boxes on top of each other – but both are tilted at the same angle.
              pivot.rotate( 0.4f , 0.4f , 0.0f );
      +
    • +
    +
  12. +
+ +

+ +What has happened? We have attached two box Geometries to a Node. Then we used the Node as a handle to grab the two boxes and transform (rotate) both, in one step. This is a common task and you will use this method a lot in your games when you move game characters around. +

+ +
+ +

Definition: Geometry vs Node

+
+ +

+ +You work with two types of Spatials in your scenegraph: Nodes and Geometries. Here is the difference: + +

+ + + + + + + + + + + + + +
Geometry Node
Visibility: A visible 3-D object. An invisible “handle”.
Purpose: A Geometry stores an object's looks. A Node groups Geometries and other Nodes together.
Examples: A box, a sphere, player, a building, a piece of terrain, a vehicle, missiles, NPCs, etc… The default rootNode, the guiNode (for on-screen text); a floor node, a custom vehicle-with-passengers node, an audio node, etc…
+ +
+ +

FAQ: How to Populate the Scenegraph?

+
+ + + + + + + + + + + + + + + + + + + +
Task? Solution!
Create a Spatial Create a shape and give it a Material. For instance a box shape:
Box(Vector3f.ZERO, 1, 1, 1);
+Geometry thing = new Geometry("thing", mesh);
+Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
+thing.setMaterial(mat);
Make an object appear in the scene Attach the Spatial to the rootNode, or to any node that is attached to the rootNode.
rootNode.attachChild(thing);
Remove objects from the scene Detach the Spatial from the rootNode, and from any node that is attached to the rootNode.
rootNode.detachChild(thing);
rootNode.detachAllChildren();
Find a Spatial in the scene by the object's name or ID Look at the node's children.
Spatial thing = rootNode.getChild("thing");
Spatial twentythird = rootNode.getChild(22);
Specify what should be loaded at the start Everything you initialize and attach to the rootNode in the simpleInitApp() method is part of the scene at the start of the game.
+ +
+ +

How to Transform Objects?

+
+ +

+ +There are three types of 3D transformation: Translation (moving), Scaling (resizing), and Rotation (turning). + +

+ + + + + + + + + + + + + +
Task? Solution! X Y Z
Position and move objects Translation: Specify the new location in three dimensions: right/left, up/down, forward/backward.
+ Example 1. To move an object to specific coordinates, such as (0,40.2f,-2), use:
thing.setLocalTranslation( new Vector3f( 0.0f, 40.2f, -2.0f ) );
+

+
+ Example 2: To move an object by a certain amount, e.g. higher up (y=40.2f) and further back (z=-2.0f): +

+
thing.move( 0.0f, 40.2f, -2.0f );
right/leftup/downforeward/ backward
Resize objects Scaling: To resize a Spatial, specify the scale factor in each dimension: length, height, width. A value between 0.0f and 1.0f will shrink the object; a value bigger than 1.0f will make it grow; and 1.0f will keep this dimension the same. Using the same value for each dimension scales an object proportionally, using different values stretches it.
+ Example: Make it 10 times longer, one tenth of the height, same width:
thing.setLocalScale( 10.0f, 0.1f, 1.0f  );
thing.scale( 10.0f, 0.1f, 1.0f );
lengthheightwidth
Turn objects Rotation: 3-D rotation is a bit tricky (learn details here). In short: You can rotate around three axes, pitch, yaw, and roll.
+ Important: You do not specify the rotation in degrees from 0° to 360°, but in radians from 0.0f to 6.28f (FastMath.PI*2) !
+ Example: To roll an object 180° around the z axis:
thing.rotate( 0f , 0f , FastMath.PI );
+

+ Tip: If your game idea calls for a serious amount of rotations, it is worth looking into quaternions, a data structure that can combine and store rotations efficiently. +

+
thing.setLocalRotation( new Quaternion(). fromAngleAxis(FastMath.PI/2, new Vector3f(1,0,0)));
pitchyawroll
+ +
+ +

How to Troubleshoot Nodes?

+
+ +

+ +If you get unexpected results, check whether you made the following common mistakes: + +

+ + + + + + + + + + + + + +
Problem? Solution!
Created Geometry does not appear in scene Have you attached it to (a node that is attached to) the rootNode?
+ Does it have a Material?
+ What is its translation (positition)? Is it covered up by another Geometry?
Spatial rotates wrong Did you use radian values, and not degrees?
+ Did you rotate the intended pivot node?
+ Did you rotate around the right axis?
Geometry has an unexpected Material Did you reuse a Material from another Geometry and have inadvertently changed its properties?
+ +
+ +

Conclusion

+
+ +

+ +You have learned that the 3D world is a Scene Graph of Spatials: Visible Geometries and invisible Nodes. You can transform Spatials, or attach them to nodes and transform the nodes. +

+ +

+Since standard shapes like spheres and boxes get old fast, continue with the next chapter where you learn to load assets, such as 3-D models. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_physics.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_physics.html new file mode 100644 index 000000000..26546be11 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_physics.html @@ -0,0 +1,595 @@ + +

Getting Started with JME3 (13) - Hello Physics

+
+ +

+ +Previous: Hello Effects, +Next: JME 3 documentation +

+ +

+For the simulation of physical forces, jME3 integrates the library. The most common use cases for physics in 3D games are: + +

+
    +
  • Driving vehicles with suspensions, tyre friction, ramp jumping, drifting – example: car racers
    +
  • +
  • Rolling and bouncing balls – example: pong, pool billiard, bowling
    +
  • +
  • Sliding and falling boxes – example: Breakout, Arkanoid
    +
  • +
  • Exposing objects to forces and gravity – example: spaceships or zero-g flight
    +
  • +
  • Animating ragdolls – example: “realistic” character simulations
    +
  • +
  • … and much more: swinging pendulums, flexible chains…
    +
  • +
+ +

+ +All that can be done in JME3. Let's have a look at a Physics simulation in this example where we shoot cannon balls at a wall. +

+ +

+ +

+ +
+ +

Sample Code

+
+ +

+ +Thanks to double1984 for contributing this fun sample! +

+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.asset.TextureKey;
+import com.jme3.bullet.BulletAppState;
+import com.jme3.bullet.control.RigidBodyControl;
+import com.jme3.font.BitmapText;
+import com.jme3.input.MouseInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.MouseButtonTrigger;
+import com.jme3.material.Material;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.queue.RenderQueue.ShadowMode;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.scene.shape.Sphere;
+import com.jme3.scene.shape.Sphere.TextureMode;
+import com.jme3.shadow.BasicShadowRenderer;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Texture.WrapMode;
+ 
+/**
+ * Example 12 - how to give objects physical properties so they bounce and fall.
+ * @author base code by double1984, updated by zathras
+ */
+public class HelloPhysics extends SimpleApplication {
+ 
+  public static void main(String args[]) {
+    HelloPhysics app = new HelloPhysics();
+    app.start();
+  }
+ 
+  /** Prepare the Physics Application State (jBullet) */
+  private BulletAppState bulletAppState;
+ 
+  /** Activate custom rendering of shadows */
+  BasicShadowRenderer bsr;
+ 
+  /** Prepare Materials */
+  Material wall_mat;
+  Material stone_mat;
+  Material floor_mat;
+ 
+  /** Prepare geometries and physical nodes for bricks and cannon balls. */
+  private RigidBodyControl    brick_phy;
+  private static final Box    box;
+  private RigidBodyControl    ball_phy;
+  private static final Sphere sphere;
+  private RigidBodyControl    floor_phy;
+  private static final Box    floor;
+ 
+  /** dimensions used for bricks and wall */
+  private static final float brickLength = 0.48f;
+  private static final float brickWidth  = 0.24f;
+  private static final float brickHeight = 0.12f;
+ 
+  static {
+    /** Initialize the cannon ball geometry */
+    sphere = new Sphere(32, 32, 0.4f, true, false);
+    sphere.setTextureMode(TextureMode.Projected);
+    /** Initialize the brick geometry */
+    box = new Box(Vector3f.ZERO, brickLength, brickHeight, brickWidth);
+    box.scaleTextureCoordinates(new Vector2f(1f, .5f));
+    /** Initialize the floor geometry */
+    floor = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
+    floor.scaleTextureCoordinates(new Vector2f(3, 6));
+  }
+ 
+  @Override
+  public void simpleInitApp() {
+    /** Set up Physics Game */
+    bulletAppState = new BulletAppState();
+    stateManager.attach(bulletAppState);
+    /** Configure cam to look at scene */
+    cam.setLocation(new Vector3f(0, 6f, 6f));
+    cam.lookAt(Vector3f.ZERO, new Vector3f(0, 1, 0));
+    cam.setFrustumFar(15);
+    /** Add InputManager action: Left click triggers shooting. */
+    inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
+    inputManager.addListener(actionListener, "shoot");
+    /** Initialize the scene, materials, and physics space */
+    initMaterials();
+    initWall();
+    initFloor();
+    initCrossHairs();
+    initShadows();
+  }
+ 
+  /**
+   * Every time the shoot action is triggered, a new cannon ball is produced.
+   * The ball is set up to fly from the camera position in the camera direction.
+   */
+  private ActionListener() {
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("shoot") && !keyPressed) {
+        makeCannonBall();
+      }
+    }
+  };
+ 
+  /** Initialize the materials used in this scene. */
+  public void initMaterials() {
+    wall_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");
+    key.setGenerateMips(true);
+    Texture tex = assetManager.loadTexture(key);
+    wall_mat.setTexture("ColorMap", tex);
+ 
+    stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
+    key2.setGenerateMips(true);
+    Texture tex2 = assetManager.loadTexture(key2);
+    stone_mat.setTexture("ColorMap", tex2);
+ 
+    floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.png");
+    key3.setGenerateMips(true);
+    Texture tex3 = assetManager.loadTexture(key3);
+    tex3.setWrap(WrapMode.Repeat);
+    floor_mat.setTexture("ColorMap", tex3);
+  }
+ 
+  /** Make a solid floor and add it to the scene. */
+  public void initFloor() {
+    Geometry floor_geo = new Geometry("Floor", floor);
+    floor_geo.setMaterial(floor_mat);
+    floor_geo.setShadowMode(ShadowMode.Receive);
+    floor_geo.setLocalTranslation(0, -0.1f, 0);
+    this.rootNode.attachChild(floor_geo);
+    /* Make the floor physical with mass 0.0f! */
+    floor_phy = new RigidBodyControl(0.0f);
+    floor_geo.addControl(floor_phy);
+    bulletAppState.getPhysicsSpace().add(floor_phy);
+  }
+ 
+  /** This loop builds a wall out of individual bricks. */
+  public void initWall() {
+    float startpt = brickLength / 4;
+    float height = 0;
+    for (int j = 0; j < 15; j++) {
+      for (int i = 0; i < 4; i++) {
+        Vector3f vt =
+         new Vector3f(i * brickLength * 2 + startpt, brickHeight + height, 0);
+        makeBrick(vt);
+      }
+      startpt = -startpt;
+      height += 2 * brickHeight;
+    }
+  }
+ 
+  /** Activate shadow casting and light direction */
+  private void initShadows() {
+    bsr = new BasicShadowRenderer(assetManager, 256);
+    bsr.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
+    viewPort.addProcessor(bsr);
+    // Default mode is Off -- Every node declares own shadow mode!
+    rootNode.setShadowMode(ShadowMode.Off);
+  }
+ 
+  /** This method creates one individual physical brick. */
+  public void makeBrick(Vector3f loc) {
+    /** Create a brick geometry and attach to scene graph. */
+    Geometry brick_geo = new Geometry("brick", box);
+    brick_geo.setMaterial(wall_mat);
+    rootNode.attachChild(brick_geo);
+    /** Position the brick geometry and activate shadows */
+    brick_geo.setLocalTranslation(loc);
+    brick_geo.setShadowMode(ShadowMode.CastAndReceive);
+    /** Make brick physical with a mass > 0.0f. */
+    brick_phy = new RigidBodyControl(2f);
+    /** Add physical brick to physics space. */
+    brick_geo.addControl(brick_phy);
+    bulletAppState.getPhysicsSpace().add(brick_phy);
+  }
+ 
+  /** This method creates one individual physical cannon ball.
+   * By defaul, the ball is accelerated and flies
+   * from the camera position in the camera direction.*/
+  public void makeCannonBall() {
+    /** Create a cannon ball geometry and attach to scene graph. */
+    Geometry ball_geo = new Geometry("cannon ball", sphere);
+    ball_geo.setMaterial(stone_mat);
+    rootNode.attachChild(ball_geo);
+    /** Position the cannon ball and activate shadows */
+    ball_geo.setLocalTranslation(cam.getLocation());
+    ball_geo.setShadowMode(ShadowMode.CastAndReceive);
+    /** Make the ball physcial with a mass > 0.0f */
+    ball_phy = new RigidBodyControl(1f);
+    /** Add physical ball to physics space. */
+    ball_geo.addControl(ball_phy);
+    bulletAppState.getPhysicsSpace().add(ball_phy);
+    /** Accelerate the physcial ball to shoot it. */
+    ball_phy.setLinearVelocity(cam.getDirection().mult(25));
+  }
+ 
+  /** A plus sign used as crosshairs to help the player with aiming.*/
+  protected void initCrossHairs() {
+    guiNode.detachAllChildren();
+    guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
+    BitmapText ch = new BitmapText(guiFont, false);
+    ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
+    ch.setText("+");        // fake crosshairs :)
+    ch.setLocalTranslation( // center
+      settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
+      settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
+    guiNode.attachChild(ch);
+  }
+}
+

+You should see a brick wall that is casting a shadow on a floor. Click to shoot cannon balls. Watch the bricks fall and bounce off one another! +

+ +
+ +

A Basic Physics Application

+
+ +

+ +In the previous tutorials, we were using Geometries (boxes, spheres, and models) that we placed in the scene. Geometries can float in mid-air and even overlap – they are not affected by “gravity” and have no physical mass. This tutorial shows how to add physical properties to Geometries. +

+ +

+As always, we start with a standard com.jme3.app.SimpleApplication. To activate physics, we create a com.jme3.bullet.BulletAppState, and and attach it to the SimpleApplication's application state manager. +

+
public class HelloPhysics extends SimpleApplication {
+  private BulletAppState bulletAppState;
+ 
+  public void simpleInitApp() {
+    bulletAppState = new BulletAppState();
+    stateManager.attach(bulletAppState);
+  }
+}
+

+The BulletAppState gives the game access to a Physics Space. The Physics Space allows us to use com.jme3.bullet.control.PhysicsControls that add physical properties to Nodes. +

+ +
+ +

Creating Bricks and Cannon Balls

+
+ +
+ +

Geometries

+
+ +

+ +In this “shoot at the wall” example, we use Geometries such as cannon balls and bricks. A geometry just describes the shape and look of an object. +

+
  /** Prepare geometries and physical nodes for bricks and cannon balls. */
+  private static final Box    box;
+  private static final Sphere sphere;
+  private static final Box    floor;
+ 
+  /** dimensions used for bricks and wall */
+  private static final float brickLength = 0.48f;
+  private static final float brickWidth  = 0.24f;
+  private static final float brickHeight = 0.12f;
+ 
+  static {
+    /** Initialize the cannon ball geometry */
+    sphere = new Sphere(32, 32, 0.4f, true, false);
+    sphere.setTextureMode(TextureMode.Projected);
+    /** Initialize the brick geometry */
+    box = new Box(Vector3f.ZERO, brickLength, brickHeight, brickWidth);
+    box.scaleTextureCoordinates(new Vector2f(1f, .5f));
+    /** Initialize the floor geometry */
+    floor = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
+    floor.scaleTextureCoordinates(new Vector2f(3, 6));
+  }
+
+ +

RigidBodyControl: Brick

+
+ +

+ +For each Geometry that we want to have physcial properties, we add a RigidBodyControl. +

+
  private RigidBodyControl brick_phy;
+

+The makeBrick(loc) methods creates a physics node brickNode at a location loc. Our brick shall have +

+
    +
  • a visible Geometry brick_geo
    +
  • +
  • physical properties brick_phy
    +
      +
    • a mass of 2.0f.
      +
    • +
    +
  • +
+
  public void makeBrick(Vector3f loc) {
+    /** Create a brick geometry and attach to scene graph. */
+    Geometry brick_geo = new Geometry("brick", box);
+    brick_geo.setMaterial(wall_mat);
+    rootNode.attachChild(brick_geo);
+    /** Position the brick geometry and activate shadows */
+    brick_geo.setLocalTranslation(loc);
+    brick_geo.setShadowMode(ShadowMode.CastAndReceive);
+    /** Make brick physical with a mass > 0.0f. */
+    brick_phy = new RigidBodyControl(2f);
+    /** Add physical brick to physics space. */
+    brick_geo.addControl(brick_phy);
+    bulletAppState.getPhysicsSpace().add(brick_phy);
+  }
+

+This code sample does the following: +

+
    +
  1. We use a box shape as brick, and give it a brick-colored material.
    +
  2. +
  3. We attach the brick to the rootNode and position it at the position loc in the scene graph.
    +
  4. +
  5. (Optionally, we activate a “Cast and Receive” shadow mode for each brick.)
    +
  6. +
  7. We create a RigidBodyControl for the brick, add it to the brick Geometry, and register it to the PhysicsSpace.
    +
  8. +
+ +
+ +

RigidBodyControl: Cannonball

+
+ +

+ +You will notice that the cannon ball is created in the same way: +

+ +

+The makeCannonBall() methods creates a physics node cannonballNode. The cannon ball shall have +

+
    +
  • a visible Geometry ball_geo
    +
  • +
  • physical properties ball_phy
    +
      +
    • a mass of 1.0f.
      +
    • +
    +
  • +
+
  public void makeCannonBall() {
+    /** Create a cannon ball geometry and attach to scene graph. */
+    Geometry ball_geo = new Geometry("cannon ball", sphere);
+    ball_geo.setMaterial(stone_mat);
+    rootNode.attachChild(ball_geo);
+    /** Position the cannon ball and activate shadows */
+    ball_geo.setLocalTranslation(cam.getLocation());
+    ball_geo.setShadowMode(ShadowMode.CastAndReceive);
+    /** Make the ball physcial with a mass > 0.0f */
+    ball_phy = new RigidBodyControl(1f);
+    /** Add physical ball to physics space. */
+    ball_geo.addControl(ball_phy);
+    bulletAppState.getPhysicsSpace().add(ball_phy);
+    /** Accelerate the physcial ball to shoot it. */
+    ball_phy.setLinearVelocity(cam.getDirection().mult(25));
+  }
+

+This code sample does the following: +

+
    +
  1. We use a sphere shape as cannonball, and give it a stone material.
    +
  2. +
  3. We attach the ball to the rootNode and position it where the camera is.
    +
  4. +
  5. (Optionally, we activate a “Cast and Receive” shadow mode for the ball.)
    +
  6. +
  7. We create a RigidBodyControl for the ball, add it to the ball Geometry, and register it to the PhysicsSpace.
    +
  8. +
  9. Since are are shooting cannon balls here, we accelerate the ball in the direction the camera is looking, with a speed of 25f.
    +
  10. +
+ +
+ +

RigidBodyControl: Floor

+
+ +

+ +The (static) floor has one important difference compared to the (dynamic) bricks and cannonballs: A mass of zero. +

+ +

+As before, we write a custom initFloor() method that creates a flat box with a rock texture that we use as floor. The floor shall have: +

+
    +
  • a visible Geometry floor_geo
    +
  • +
  • physical properties floor_phy
    +
      +
    • A mass of 0.0f!
      +
    • +
    +
  • +
+
  private RigidBodyControl    floor_phy;
+  ...
+  public void initFloor() {
+    Box(Vector3f.ZERO, 10f, 0.1f, 5f);
+    floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
+    floor_geo = new Geometry("floor", floorBox);
+    floor_geo.setMaterial(floor_mat);
+    floor_geo.setShadowMode(ShadowMode.Receive);
+    floor_geo.setLocalTranslation(0, -0.1f, 0);
+    this.rootNode.attachChild(floor_geo);
+    /* Make the floor physical with mass 0.0f! */
+    floor_phy = new RigidBodyControl(0.0f);
+    floor_geo.addControl(floor_phy);
+    bulletAppState.getPhysicsSpace().add(floor_phy);
+ 
+

+This code sample does the following: +

+
    +
  1. We use a box shape as floor, and give it a floor material.
    +
  2. +
  3. We attach the floor to the rootNode and position it a bit below the origin – to prevent overlap with other physical nodes.
    +
  4. +
  5. (Optionally, we activate a “Receive” shadow mode for the floor. The floor does not cast any shadows, this saves computing time.)
    +
  6. +
  7. Static objects such as floors are mass-less and are not affected by gravity! Therefor we create a RigidBodyControl with a mass of 0.0f.
    +
  8. +
  9. We add the RigidBodyControl to the floor Geometry, and register it to the PhysicsSpace.
    +
  10. +
+ +
+ +

Creating the Scene

+
+ +

+ +Let's have a quick look at the remaining custom helper methods: initMaterial(), initShadows(), initCrossHairs(), and initWall(). + +

+
    +
  • initMaterial() – This method initializes all the materials we use in this demo.
    +
  • +
  • initShadows() – (Optional) We deactivate the rootNode's default ShadowMode and use a JME SceneProcessor called BasicShadowRenderer from the com.jme3.shadow package. For every relevant scene node (floor, cannon balls, bricks) we specify individually what shadow behaviour we want, Cast, Receive, or both.
    +
  • +
  • initWall() – A double loop that generates a wall by positioning brick objects: 15 rows high with 4 bricks per row. It's important to space the bricks so the do not overlap.
    +
  • +
  • initCrossHairs() – This method simply displays a plus sign that we use as crosshairs for aiming. Note that screen elements such as crosshairs are attached to the guiNode, not the rootNode.
    +
  • +
+ +

+ +These methods are each called once from the simpleInitApp() method at the start of the game. As you see, you write any number of custom methods to set up your game's scene. +

+ +
+ +

The Cannon Ball Shooting Action

+
+ +

+ +In the initSimpleApp() we add an input mapping that triggers a shoot action when the left mouse button is pressed. +

+
    public void simpleInitApp() {
+    ...
+        inputManager.addMapping("shoot", new MouseButtonTrigger(0));
+        inputManager.addListener(actionListener, "shoot");
+    ...
+    }
+

+ + +The action of shooting a new cannon ball is defined as follows: +

+
    private ActionListener() {
+        public void onAction(String name, boolean keyPressed, float tpf) {
+            if (name.equals("shoot") && !keyPressed) {
+                makeCannonBall();
+            }
+        }
+    };
+

+In the moment the cannonball appears in the scene, it flies off with the velocity (and in the direction) that we have specified using setLinearVelocity() inside makeCannonBall(). The newly created cannon ball flies off, hits the wall, and exerts a physical force that shifts the individual bricks. +

+ +
+ +

Movement of the physics enabled Spatial

+
+ +

+The location of the spatial is defined by the RigidBodyControl, move that to move the spatial or if its a non-world-object set the RigidBodyControl to kinematic mode to have it move along with the spatial. This will make the RigidBody be unaffected by the physics but it will effect the physics objects around it based on its location and amount of movement that is applied. Note that a kinematic RigidBody needs to have a mass! +

+ +
+ +

Excercises

+
+ +

+ +Exercise 1 +

+ +

+What happens if you give a static node such as the floor a mass of more than 0.0f? +

+ +

+Exercise 2 +

+ +

+Popular AAA games use a clever mix of physics, animation and prerendered graphics to give you the illusion of a real, “physical” world. Look at your favorite games and try to spot where and how the game designers trick you into believing that the whole scene is physical. – For example, a building “breaking” into 4-8 parts when falling apart is most likely being replaced by dynamic physics nodes only after it has been destroyed… Now that you start to implement game physics yourself, look behind the curtain. +

+ +
+ +

Conclusion

+
+ +

+ +Using physics everywhere in a game sounds like a cool idea, but it is easily overused. Although the physics nodes are put to “sleep” when they are not moved, creating a world solely out of dynamic physics nodes will quickly bring you to the limits of your computer's capabilities. +

+ +

+You have learned how to add a PhysicsSpace to an application by attaching a BulletAppState. You know how to create PhysicsNodes from a geometry, a collision shape, and a mass value. You have learned that physical objects are not only attached to the rootNode but also registered to the PhysicsSpace. You are aware that overusing physics has a huge performance impact. +

+ +

+Additionally you have learned how to add shadows to a scene. + +

+
+ +

+This is the last beginner tutorial for now. Now you are ready to start combining what you learned to create a game of your own! + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_picking.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_picking.html new file mode 100644 index 000000000..e158a627c --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_picking.html @@ -0,0 +1,452 @@ + +

Getting Started with JME3 (8) - Hello Picking

+
+ +

+ +Previous: Hello Animation, +Next: Hello Collision +

+ +

+Common interactions in games include shooting, picking up objects, and opening doors. +

+ +

+From an implementation point of view, these apparently different interactions are very similar: The user first aims and selects a target in the 3D scene, and then triggers an action on it. We call that picking. +

+ +

+You can pick something by either pressing a key on the keyboard, or by clicking with the mouse. In either case, you identify the target by aiming a ray –a straight line– into the scene. This method to implement picking is called ray casting (not the same as ray tracing). +

+ +

+ +

+ +

+This tutorial relies on what you have learned in the Hello Input tutorial. +

+ +
+ +

Sample Code

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.collision.CollisionResult;
+import com.jme3.collision.CollisionResults;
+import com.jme3.font.BitmapText;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.input.controls.MouseButtonTrigger;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Ray;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Node;
+import com.jme3.scene.shape.Box;
+import com.jme3.scene.shape.Sphere;
+ 
+/** Sample 8 - how to let the user pick (select) objects in the scene 
+ * using the mouse or key presses. Can be used for shooting, opening doors, etc. */
+public class HelloPicking extends SimpleApplication {
+ 
+  public static void main(String[] args) {
+    HelloPicking app = new HelloPicking();
+    app.start();
+  }
+ 
+  Node shootables;
+  Geometry mark;
+ 
+  @Override
+  public void simpleInitApp() {
+    initCrossHairs(); // a "+" in the middle of the screen to help aiming
+    initKeys();       // load custom key mappings
+    initMark();       // a red sphere to mark the hit
+ 
+    /** create four colored boxes and a floor to shoot at: */
+    shootables = new Node("Shootables");
+    rootNode.attachChild(shootables);
+    shootables.attachChild(makeCube("a Dragon",    -2f, 0f, 1f));
+    shootables.attachChild(makeCube("a tin can",    1f,-2f, 0f));
+    shootables.attachChild(makeCube("the Sheriff",  0f, 1f,-2f));
+    shootables.attachChild(makeCube("the Deputy",   1f, 0f,-4f));
+    shootables.attachChild(makeFloor());
+  }
+ 
+  /** Declaring the "Shoot" action and mapping to its triggers. */
+  private void initKeys() {
+    inputManager.addMapping("Shoot",
+      new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar
+      new MouseButtonTrigger(0));         // trigger 2: left-button click
+    inputManager.addListener(actionListener, "Shoot");
+  }
+ 
+  /** Defining the "Shoot" action: Determine what was hit and how to respond. */
+  private ActionListener() {
+    @Override
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Shoot") && !keyPressed) {
+        // 1. Reset results list.
+        CollisionResults results = new CollisionResults();
+        // 2. Aim the ray from cam loc to cam direction.
+        Ray ray = new Ray(cam.getLocation(), cam.getDirection());
+        // 3. Collect intersections between Ray and Shootables in results list.
+        shootables.collideWith(ray, results);
+        // 4. Print the results. 
+        System.out.println("----- Collisions? " + results.size() + "-----");
+        for (int i = 0; i < results.size(); i++) {
+          // For each hit, we know distance, impact point, name of geometry.
+          float dist = results.getCollision(i).getDistance();
+          Vector3f pt = results.getCollision(i).getContactPoint();
+          String hit = results.getCollision(i).getGeometry().getName();
+          System.out.println("* Collision #" + i);
+          System.out.println("  You shot " + hit + " at " + pt + ", " + dist + " wu away.");
+        }
+        // 5. Use the results (we mark the hit object)
+        if (results.size() > 0){
+          // The closest collision point is what was truly hit:
+          CollisionResult closest = results.getClosestCollision();
+          // Let's interact - we mark the hit with a red dot.
+          mark.setLocalTranslation(closest.getContactPoint());
+          rootNode.attachChild(mark);
+        } else {
+        // No hits? Then remove the red mark.
+          rootNode.detachChild(mark);
+        }
+      }
+    }
+  };
+ 
+  /** A cube object for target practice */
+  protected Geometry makeCube(String name, float x, float y, float z) {
+    Box(new Vector3f(x, y, z), 1, 1, 1);
+    Geometry cube = new Geometry(name, box);
+    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mat1.setColor("Color", ColorRGBA.randomColor());
+    cube.setMaterial(mat1);
+    return cube;
+  }
+ 
+  /** A floor to show that the "shot" can go through several objects. */
+  protected Geometry makeFloor() {
+    Box(new Vector3f(0,-4,-5), 15,.2f,15);
+    Geometry floor = new Geometry("the Floor", box);
+    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mat1.setColor("Color", ColorRGBA.Gray);
+    floor.setMaterial(mat1);
+    return floor;
+  }
+ 
+  /** A red ball that marks the last spot that was "hit" by the "shot". */
+  protected void initMark() {
+    Sphere sphere = new Sphere(30, 30, 0.2f);
+    mark = new Geometry("BOOM!", sphere);
+    Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+    mark_mat.setColor("Color", ColorRGBA.Red);
+    mark.setMaterial(mark_mat);
+  }
+ 
+  /** A centred plus sign to help the player aim. */
+  protected void initCrossHairs() {
+    guiNode.detachAllChildren();
+    guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
+    BitmapText ch = new BitmapText(guiFont, false);
+    ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
+    ch.setText("+"); // crosshairs
+    ch.setLocalTranslation( // center
+      settings.getWidth()/2 - guiFont.getCharSet().getRenderedSize()/3*2,
+      settings.getHeight()/2 + ch.getLineHeight()/2, 0);
+    guiNode.attachChild(ch);
+  }
+}
+

+You should see four colored cubes floating over a gray floor, and cross-hairs. Aim the cross-hairs and click, or press the spacebar to shoot. The last hit will be marked with a red dot. +

+ +

+Keep an eye on the application's output stream, it will give you more details: The name of the mesh that was hit, the coordinates of the hit, and the distance. +

+ +
+ +

Understanding the Helper Methods

+
+ +

+ +The methods makeCube(), makeFloor(), initMark(), and initCrossHairs, are custom helper methods. We call them from simpleInitApp() to initialize the scenegraph with sample content. + +

+
    +
  1. makeCube() creates simple colored boxes for “target practice”.
    +
  2. +
  3. makeFloor() creates a gray floor node for “target practice”.
    +
  4. +
  5. initMark() creates a red sphere (“mark”). We will use it later to mark the spot that was hit.
    +
      +
    • Note that the mark is not attached and therefor not visible at the start.
      +
    • +
    +
  6. +
  7. initCrossHairs() creates simple cross-hairs by printing a ”+” sign in the middle of the screen.
    +
      +
    • Note that the cross-hairs are attached to the guiNode, not to the rootNode.
      +
    • +
    +
  8. +
+ +

+ +In this example, we attached all “shootable” objects to one custom node, Shootables. This is an optimization so the engine only has to calculate intersections with objects we are actually interested in. The Shootables node is attached to the rootNode as usual. +

+ +
+ +

Understanding Ray Casting for Hit Testing

+
+ +

+ +Our goal is to determine which box the user “shot” (picked). In general, we want to determine which mesh the user has selected by aiming the cross-hairs at it. Mathematically, we draw a line from the camera and see whether it intersects with objects in the 3D scene. This line is called a ray. +

+ +

+Here is our simple ray casting algorithm for picking objects: + +

+
    +
  1. Reset the results list.
    +
  2. +
  3. Cast a ray from cam location into the cam direction.
    +
  4. +
  5. Collect all intersections between the ray and Shootable nodes in the results list.
    +
  6. +
  7. Use the results list to determine what was hit:
    +
      +
    1. For each hit, JME reports its distance from the camera, impact point, and the name of the mesh.
      +
    2. +
    3. Sort the results by distance.
      +
    4. +
    5. Take the closest result, it is the mesh that was hit.
      +
    6. +
    +
  8. +
+ +
+ +

Implementing Hit Testing

+
+ +
+ +

Loading the scene

+
+ +

+ +First initialize some shootable nodes and attach them to the scene. You will use the mark object later. +

+
  Node shootables;
+  Geometry mark;
+ 
+  @Override
+  public void simpleInitApp() {
+    initCrossHairs();
+    initKeys();
+    initMark(); 
+    shootables = new Node("Shootables");
+    rootNode.attachChild(shootables);
+    shootables.attachChild(makeCube("a Dragon",    -2f, 0f, 1f));
+    shootables.attachChild(makeCube("a tin can",    1f,-2f, 0f));
+    shootables.attachChild(makeCube("the Sheriff",  0f, 1f,-2f));
+    shootables.attachChild(makeCube("the Deputy",   1f, 0f, -4));
+    shootables.attachChild(makeFloor());
+  }
+
+ +

Setting Up the Input Listener

+
+ +

+ +Next you declare the shooting action. It can be triggered either by clicking, or by pressing the space bar. The initKeys() method is called from simpleInitApp() to set up these input mappings. +

+
  /** Declaring the "Shoot" action and its triggers. */
+  private void initKeys() {
+    inputManager.addMapping("Shoot",      // Declare...
+      new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar, or
+      new MouseButtonTrigger(0));         // trigger 2: left-button click
+    inputManager.addListener(actionListener, "Shoot"); // ... and add.
+  }
+
+ +

Defining the Picking Action

+
+ +

+ +Next we implement the ActionListener that responds to the Shoot trigger with an action. The action follows the ray casting algorithm described above: + +

+
    +
  1. For every click or press of the spacebar, the Shoot action is triggered.
    +
  2. +
  3. The action casts a ray forward and determines intersections with shootable objects (= ray casting).
    +
  4. +
  5. For any target that has been hit, it prints name, distance, and coordinates of the hit.
    +
  6. +
  7. Finally it attaches a red mark to the closest result, to highlight the spot that was actually hit.
    +
  8. +
  9. When nothing was hit, the results list is empty, and the red mark is removed.
    +
  10. +
+ +

+ +Note how it prints a lot of output to show you which hits were registered. +

+
  /** Defining the "Shoot" action: Determine what was hit and how to respond. */
+  private ActionListener() {
+    @Override
+    public void onAction(String name, boolean keyPressed, float tpf) {
+      if (name.equals("Shoot") && !keyPressed) {
+        // 1. Reset results list.
+        CollisionResults results = new CollisionResults();
+        // 2. Aim the ray from cam loc to cam direction.
+        Ray ray = new Ray(cam.getLocation(), cam.getDirection());
+        // 3. Collect intersections between Ray and Shootables in results list.
+        shootables.collideWith(ray, results);
+        // 4. Print results.
+        System.out.println("----- Collisions? " + results.size() + "-----");
+        for (int i = 0; i < results.size(); i++) {
+          // For each hit, we know distance, impact point, name of geometry.
+          float dist = results.getCollision(i).getDistance();
+          Vector3f pt = results.getCollision(i).getContactPoint();
+          String hit = results.getCollision(i).getGeometry().getName();
+          System.out.println("* Collision #" + i);
+          System.out.println("  You shot " + hit + " at " + pt + ", " + dist + " wu away.");
+        }
+        // 5. Use the results (we mark the hit object)
+        if (results.size() > 0){
+          // The closest collision point is what was truly hit:
+          CollisionResult closest = results.getClosestCollision();
+          mark.setLocalTranslation(closest.getContactPoint());
+          // Let's interact - we mark the hit with a red dot.
+          rootNode.attachChild(mark);
+        } else {
+        // No hits? Then remove the red mark.
+          rootNode.detachChild(mark);
+        }
+      }
+    }
+  };
+

+Tip: Notice how you use the provided method results.getClosestCollision().getContactPoint() to determine the closest hit's location. If your game includes a “weapon” or “spell” that can hit multiple targets, you would instead loop over the list of results, and interact with each of them. +

+ +
+ +

Exercises

+
+ +

+ +After a hit was registered, the closest object is identified as target, and marked with a red dot. +Modify the code sample to solve these exercises: +

+ +
+ +

Magic Spell

+
+ +

+ +Change the color of the closest clicked target!
+ Here are some tips: +

+
    +
  1. Go to the line where the closest target is indentified, and add you changes after that.
    +
  2. +
  3. To change an object's color, you must first know its node. Identify the node by identifying the target's name.
    +
      +
    • Use rootNode.getChild(closest.getGeometry().getName())
      +
    • +
    +
  4. +
  5. Create a new color material and set the node's Material to this color.
    +
      +
    • Look inside the makeCube() method for an example of how to set random colors.
      +
    • +
    +
  6. +
+ +
+ +

Shoot at a Character

+
+ +

+ +Shooting boxes isn't very exciting – can you add code that loads and positions a model in the scene, and shoot at it? +

+
    +
  • Tip: You can use Spatial golem = assetManager.loadModel(“Models/Oto/Oto.mesh.xml”); from the engine's jme3-test-data.jar.
    +
  • +
+ +
+ +

Pick up into Inventory

+
+ +

+ +Change the code as follows to simulate the player picking up objects into the inventory: When you click once, the closest target is identified and detached from the scene. When you click a second time, the target is reattached at the location that you have clicked. Here are some tips: +

+
    +
  1. Create an inventory node to store the detached nodes.
    +
  2. +
  3. The inventory node is not attached to the rootNode.
    +
  4. +
  5. You can make the inventory visible by attaching the inventory node to the guiNode.
    +
  6. +
+ +
+ +

Conclusion

+
+ +

+ +You have learned how to use ray casting to solve the task of determining what object a user selected on the screen. You learned that this can be used for a variety of interactions, such as shooting, opening, picking up and dropping items, pressing a button or lever, etc. +

+ +

+Use your imagination from here: +

+
    +
  • In your game, the click can trigger any action on the identified object: Detach it and put it into the inventory, attach something to it, trigger an animation or effect, open a door or crate, – etc.
    +
  • +
  • In your game, you could replace the red mark with a particle emitter, add an explosion effect, play a sound, calculate the new score after each hit depending on what was hit – etc.
    +
  • +
+ +

+ +Now, wouldn't it be nice if those targets and the floor were solid objects and you could walk among them? Let's continue with Collision Detection. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_simpleapplication.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_simpleapplication.html new file mode 100644 index 000000000..3be6dafa9 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_simpleapplication.html @@ -0,0 +1,247 @@ + +

Getting Started with JME3 (1) - Hello SimpleApplication

+
+ +

+ +Previous: Installing JME3, +Next: Hello Node +
+ +

+ +

+This tutorial assumes that you have already downloaded and set up jMonkeyEngine3 in an IDE of your choice, and are able to run the bundled samples. +

+ +

+You are ready to create your first jMonkeyEngine3 game! You can generally use the tutorials in this introductory series with any integrated development environment (IDE), such as the jMonkeyPlatform, NetBeans, Eclipse, or run them straight from the commandline. +

+ +
+ +

Writing a SimpleApplication

+
+ +

+ +Create a jme3test.helloworld package and a file HelloJME3.java in it. +

+ +

+In NetBeans, you would right-click the Source Packages node +

+
    +
  • Select New… > Java Class to create a new file.
    +
  • +
  • Enter a class name: HelloJME3
    +
  • +
  • Enter a package: jme3test.helloworld
    +
  • +
  • Click Finish.
    +
  • +
+ +
+ +

Sample Code

+
+ +

+ +Replace the contents of the HelloJME3.java file with the following code: +

+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.material.Material;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.math.ColorRGBA;
+ 
+/** Sample 1 - how to get started with the most simple JME 3 application.
+ * Display a blue 3D cube and view from all sides by
+ * moving the mouse and pressing the WASD keys. */
+public class HelloJME3 extends SimpleApplication {
+ 
+    public static void main(String[] args){
+        HelloJME3 app = new HelloJME3();
+        app.start();
+    }
+ 
+    @Override
+    public void simpleInitApp() {
+        Box(Vector3f.ZERO, 1, 1, 1);
+        Geometry geom = new Geometry("Box", b);
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setColor("Color", ColorRGBA.Blue);
+        geom.setMaterial(mat);
+        rootNode.attachChild(geom);
+    }
+}
+

+ +Build and run the HelloJME3 class. If a jme settings dialog pops up, confirm the default settings. + +

+
    +
  1. You should see a simple window displaying a 3-D cube.
    +
  2. +
  3. Use the WASD keys and the mouse to navigate around.
    +
  4. +
  5. Press Escape to close the application.
    +
  6. +
+ +

+ +Congratulations, it works! How did we do that? +

+ +
+ +

Understanding the Code

+
+ +

+ +Here some basic rules that are valid for all JME3 games: +

+ +
+ +

Starting the Game

+
+ +

+ +Note that the HelloJME3.java class extends com.jme3.app.SimpleApplication, which is a subclass of com.jme3.app.Application. Every JME3 game is an instance of com.jme3.app.Application (directly, or indirectly). +

+ +

+To run a JME3 game, you first instantiate your Application-based class, and then call its start() method: +

+
HelloJME3 app = new HelloJME3(); 
+app.start();
+

+Usually, you do that from your Java application's main method. +

+ +

+Tip: Advanced Java developers may want to make a copy of SimpleApplication and use it as a template for a custom application class. +

+ +
+ +

Initializing the Scene

+
+ +

+ +This simple “game” consists of nothing but a cube. Here is how we create it, position it, give it a color, and attach it to the scene. (We will have a closer look at the details later.) +

+
    public void simpleInitApp() {
+        Box(Vector3f.ZERO, 1, 1, 1); // create cube shape
+        Geometry geom = new Geometry("Box", b);  // create cube geometry from the shape
+        Material mat = new Material(assetManager, 
+         "Common/MatDefs/Misc/Unshaded.j3md"); // create a simple material
+        mat.setColor("Color", ColorRGBA.Blue); // set color of material
+        geom.setMaterial(mat);                   // set the cube's material
+        rootNode.attachChild(geom);              // attach the cube to the scene
+    }
+

+The simpleInitApp() method is automatically called once at the beginning of every JME3 game. In this method you create or load game objects before the game starts! Here is the usual process: + +

+
    +
  1. Initialize game objects:
    +
      +
    • Create or load all objects, and position them.
      +
    • +
    • To make a geometry (like the box) appear in the scene, attach it to the rootNode.
      +
    • +
    • Examples: Load player, terrain, sky, enemies, obstacles, and place them in their start positions.
      +
    • +
    +
  2. +
  3. Initialize game variables
    +
      +
    • Game variables track the game state. Set them to their start values.
      +
    • +
    • Examples: Here you set the score to 0, and health to 100%, and so on.
      +
    • +
    +
  4. +
  5. Initialize navigation
    +
      +
    • The following key bindings are pre-configured by default:
      +
        +
      • W,A,S,D keys – Move around
        +
      • +
      • Mouse and arrow keys – Turn the camera
        +
      • +
      • Escape key - Quit game
        +
      • +
      +
    • +
    +
  6. +
+ +

+ +The important part is: The JME3 Application has a rootNode object. Your game automatically inherits the rootNode. Everything attached to the rootNode appears in the scene. Or in other words: An object that has been created, but is not attached to the rootNode, remains invisible. +

+ +
+ +

Conclusion

+
+ +

+ +These few lines of code do nothing but display a static object in 3-D, but they already allow you to navigate around in 3D. You have learned that a SimpleApplication is a good starting point because it provides you with: + +

+
    +
  • a simpleInitApp() method to initialize the game objects
    +
  • +
  • a rootNode where you attach geometries to make them appear in the scene
    +
  • +
  • useful default navigation settings
    +
  • +
+ +

+ +In a real game, you will want to: + +

+
    +
  1. Inititialize the game world,
    +
  2. +
  3. Trigger actions in the event loop,
    +
  4. +
  5. Respond to user input.
    +
  6. +
+ +

+ +In the following tutorials you will learn how these tasks are accomplished with the jMonkeyEngine 3! +

+ +

+Continue with the Hello Node tutorial, where we will first show you more details about how to initialize the game world, also known as the scene graph. + +

+
+ +

+See also: SimpleApplication from the commandline + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html new file mode 100644 index 000000000..9b7caff0d --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html @@ -0,0 +1,515 @@ + +

Hello Terrain

+
+ +

+ +Previous: Hello Collision, +Next: Hello Audio +

+ +

+One way to create a 3D landscape is to sculpt a huge terrain model. This will give you a lot of artistic freedom – but rendering such a huge model can be quite slow. jME supports heightmaps to solve this common performance issue of terrains. +

+ +

+This tutorial explains how to create terrains from heightmaps and how to use splat textures to make the terrain look good. +

+ +

+ +

+ +
+ +

Sample Code

+
+
package jme3test.helloworld;
+ 
+import com.jme3.app.SimpleApplication;
+import com.jme3.material.Material;
+import com.jme3.renderer.Camera;
+import com.jme3.terrain.geomipmap.TerrainLodControl;
+import com.jme3.terrain.heightmap.AbstractHeightMap;
+import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.heightmap.HillHeightMap; // is used in example 2
+import com.jme3.terrain.heightmap.ImageBasedHeightMap;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Texture.WrapMode;
+import java.util.ArrayList;
+import java.util.List;
+import jme3tools.converters.ImageToAwt;
+ 
+public class HelloTerrain extends SimpleApplication {
+ 
+  private TerrainQuad terrain;
+  Material mat_terrain;
+ 
+  public static void main(String[] args) {
+    HelloTerrain app = new HelloTerrain();
+    app.start();
+  }
+ 
+  @Override
+  public void simpleInitApp() {
+    flyCam.setMoveSpeed(50);
+ 
+    /** 1. Create terrain material and load four textures into it. */
+    mat_terrain = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md");
+ 
+    /** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */
+    mat_terrain.setTexture("m_Alpha", 
+               assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
+ 
+    /** 1.2) Add GRASS texture into the red layer (m_Tex1). */
+    Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
+    grass.setWrap(WrapMode.Repeat);
+    mat_terrain.setTexture("m_Tex1", grass);
+    mat_terrain.setFloat("m_Tex1Scale", 64f);
+ 
+    /** 1.3) Add DIRT texture into the green layer (m_Tex2) */
+    Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
+    dirt.setWrap(WrapMode.Repeat);
+    mat_terrain.setTexture("m_Tex2", dirt);
+    mat_terrain.setFloat("m_Tex2Scale", 32f);
+ 
+    /** 1.4) Add ROAD texture into the blue layer (m_Tex3) */
+    Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
+    rock.setWrap(WrapMode.Repeat);
+    mat_terrain.setTexture("m_Tex3", rock);
+    mat_terrain.setFloat("m_Tex3Scale", 128f);
+ 
+    /** 2. Create the height map */
+    final Texture heightMapImage = 
+        assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
+    final AbstractHeightMap heightmap =
+        new ImageBasedHeightMap(
+            ImageToAwt.convert(
+                heightMapImage.getImage(), false, true, 0));
+    heightmap.load();
+ 
+    /** 3. We have prepared material and heightmap. Now we create the actual terrain:
+     * 3.1) We create a TerrainQuad and name it "my terrain".
+     * 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65.
+     * 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513.
+     * 3.4) As LOD step scale we supply Vector3f(1,1,1).
+     * 3.5) At last, we supply the prepared heightmap itself.
+     */
+    terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap());
+ 
+    /** 4. We give the terrain its material, position & scale it, and attach it. */
+    terrain.setMaterial(mat_terrain);
+    terrain.setLocalTranslation(0, -100, 0);
+    terrain.setLocalScale(2f, 1f, 2f);
+    rootNode.attachChild(terrain);
+ 
+    /** 5. The LOD (level of detail) depends on were the camera is: */
+    List<Camera> cameras = new ArrayList<Camera>();
+    cameras.add(getCamera());
+    TerrainLodControl control = new TerrainLodControl(terrain, cameras);
+    terrain.addControl(control);
+ 
+  }
+}
+

+When you run this sample you should see a landscape with dirt mountains, grass plains, plus some winding roads in between. +

+ +
+ +

What is a Heightmap?

+
+ +

+ +Heightmaps are an efficient way of representing the shape of a hilly landscape. Picture a heightmap as a float array containing height values between 0f and 255f. Here is a very simple example of a heightmap with 25 height values. +

+ +

+ +

+ +

+Important things to note: +

+
    +
  • Low values (e.g. 0 or 50) are valeys.
    +
  • +
  • High values (e.g. 200, 255) are hills.
    +
  • +
  • We only specified a few points, and the engine interpolates the rest. Interpolation is more efficient than creating a model with several millions of vertices.
    +
  • +
+ +

+ +Now when looking at Java data types to hold an array of floats between 0 and 255, the Image class comes to mind. Storing a terrain's height values as a grayscale image has one big advantage: The outcome is a very userfriendly, almost topographical, representation of a landscape: +

+
    +
  • Low values (e.g. 0 or 50) are dark gray – these are valleys.
    +
  • +
  • High values (e.g. 200, 255) are light grays – these are hills.
    +
  • +
+ +

+ +Look at the next screenshot: In the top left you see the 128×128 grayscale image (heightmap) that was used as a base to generate the depicted terrain. To make the hilly shape better visible, the mountain tops are colored white, valleys brown, and the areas inbetween green: +

+ +

+} +

+ +

+In a real game, you will want to use more complex and smoother terrains than the simple heightmaps shown here. Heightmaps typically have square sizes of 512×512 or 1024×1024, and contain hundred thousands to 1 million height values. No matter which size, the concept is the same as described here. +

+ +
+ +

Looking at the Heightmap Code

+
+ +

+ + +

+ +

+The first step is always to create the heightmap. You can create it yourself in any standard graphic application. Make sure it has the following properties: +

+
    +
  • The size must be square and a power of two
    +
      +
    • Examples: 128×128, 256×256, 512×512, 1024×1024
      +
    • +
    +
  • +
  • Color mode: 255 grayscales.
    +
      +
    • If you supply a color image, it will be converted to grayscale (with possibly weird results).
      +
    • +
    +
  • +
  • Save it as a normal .jpg or .png file
    +
  • +
+ +

+ +The file mountains512.png that you see here is a typical example of a heightmap. +

+ +

+Here is how you create the heightmap object in your jME code: +

+
    +
  1. Create a Texture object
    +
  2. +
  3. Load your prepared heightmap texture into the texture object
    +
  4. +
  5. Create an AbstractHeightmap object from an ImageBasedHeightMap.
    + ImageBasedHeightMap expects the following parameters:
    +
      +
    1. An ImageToAwt.convert()ed image file
      +
    2. +
    3. A boolean whether you are using 16 bit – here false.
      +
    4. +
    5. A boolean whether you are using an alphamap – here true.
      +
    6. +
    +
  6. +
  7. Load the heightmap.
    +
  8. +
+
    final Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
+    final AbstractHeightMap heightmap =
+        new ImageBasedHeightMap(
+            ImageToAwt.convert(
+                heightMapImage.getImage(), false, true, 0));
+    heightmap.load();
+
+ +

What is Texture Splatting?

+
+ +

+ +Texture splatting allows you create a custom textured material and “paint” on it. This is very useful for terrains: As you see in the example here, you can paint a grass texture into the valleys, a dirt texture onto the mountains, and free-form roads inbetween. +

+ +

+How is it done? We have three texture layers to paint on, m_Tex1, m_Tex2 and m_Tex3 (these names are found by opening the Terrain.j3md file, under the Material Parameters section; they may be changed) . before we start we have to make a few decisions: + +

+
    +
  1. You choose three textures. For example grass.jpg, dirt.jpg, and road.jpg.
    +
  2. +
  3. You will “paint” three texture layers with three colors: Red, blue and, green. We arbitrarily chose that…
    +
      +
    1. … everything red will be grass – this goes into layer m_Tex1
      +
    2. +
    3. … everything green will be dirt – this goes into layer m_Tex2
      +
    4. +
    5. … everything blue will be roads – this goes into layer m_Tex3
      +
    6. +
    +
  4. +
+ +

+ +Now we start painting the texture: + +

+
    +
  1. Make a copy of your terrains heightmap, mountains512.png, so you know the shape of the landscape.
    +
  2. +
  3. Name the copy alphamap.png.
    +
  4. +
  5. Open alphamap.png in a graphic editor and switch the image mode to color image.
    +
      +
    1. Paint the black valleys in the image red – this will be the grass.
      +
    2. +
    3. Paint the white hills in shades of green – this will be the dirt of the mountains.
      +
    4. +
    5. Paint blue lines where you want roads to cross the landscape.
      +
    6. +
    +
  6. +
  7. The end result should look similar to this:
    +
  8. +
+ +

+ + +

+ +

+Note: In the future, the jMonkeyPlatform will take over some of these steps so you don't have to worry about the details. +

+ +
+ +

Looking at the Texturing Code

+
+ +

+ +As usual, we create a Material object. We base it on the Material Definition Terrain.j3md that is included in the jME3 framework. +

+
Material mat_terrain = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md");
+

+Now we load four textures into this material. The first one, m_Alpha, is the alphamap that we just created. +

+
mat_terrain.setTexture("m_Alpha", 
+    assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
+

+Three other textures are the layers that we have previously decided to paint: grass, dirt, and road. We create texture objects and load the three textures as usual. Note how we assign them to their respective texture layers (m_Tex1, m_Tex2, and m_Tex3) inside the Material! +

+
    /** 1.2) Add GRASS texture into the red layer (m_Tex1). */
+    Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
+    grass.setWrap(WrapMode.Repeat);
+    mat_terrain.setTexture("m_Tex1", grass);
+    mat_terrain.setFloat("m_Tex1Scale", 64f);
+ 
+    /** 1.3) Add DIRT texture into the green layer (m_Tex2) */
+    Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
+    dirt.setWrap(WrapMode.Repeat);
+    mat_terrain.setTexture("m_Tex2", dirt);
+    mat_terrain.setFloat("m_Tex2Scale", 32f);
+ 
+    /** 1.4) Add ROAD texture into the blue layer (m_Tex3) */
+    Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
+    rock.setWrap(WrapMode.Repeat);
+    mat_terrain.setTexture("m_Tex3", rock);
+    mat_terrain.setFloat("m_Tex3Scale", 128f);
+

+The individual texture scales (e.g. mat_terrain.setFloat(“m_Tex3Scale”, 128f);) depend on the size of the textures you use. You can tell you picked a too small scale if, for example, your road tiles appear like tiny grains of sand, or to big if the blades of grass look like twigs. +

+ +

+We use setWrap(WrapMode.Repeat) to make the small texture fill the wide area. If the repetition is too visible, try adjusting the Tex*Scale value. +

+ +

+Later, after we have created the actual terrain object, we must not forgot to set the material on it: +

+
terrain.setMaterial(mat_terrain);
+
+ +

Looking at the Terrain Generation Code

+
+ +

+ +Internally, the generated terrain mesh is broken down into tiles and blocks. This is an optimization for culling. You do not need to worry about tiles and blocks too much, just use recommended values for now. +

+ +

+Let's assume we want to generate a small 512×512 terrain. We already have created the heightmap object. Here are the steps that we perform everytime we create a new terrain. +

+ +

+We create a TerrainQuad with the following arguments: +

+
    +
  1. Name: E.g. my terrain.
    +
  2. +
  3. Tile size: We want to create terrain tiles of size 64×64, so we supply 64+1 = 65.
    +
      +
    • In general, 64 is a good value for terrain tiles.
      +
    • +
    +
  4. +
  5. Block size: Since we prepared a heightmap of size 512×512, we supply 512+1 = 513.
    +
      +
    • If the the block size is double the heightmap size (1024+1=1025), you get a stretched out, wider, flatter terrain.
      +
    • +
    • If the the block size is half the heightmap size (256+1=257), you get a smaller, more detailed terrain.
      +
    • +
    +
  6. +
  7. Finally, we supply the 512×512 heightmap object that we have previously created.
    +
  8. +
+ +

+ +Here's the code: + +

+
terrain = new TerrainQuad(
+  "my terrain",               // name
+  65,                         // tile size
+  513,                        // block size
+  heightmap.getHeightMap());  // heightmap
+
+ +

+Don't forget to attach the terrain to the rootNode. You can scale and translate the terrain just like any other Spatial. +

+ +
+ +

Looking at the Level of Detail Code

+
+ +

+ +jME3 includes an optimization that adjusts the level of detail of the rendered terrain depending on how close or far the camera is. +

+
    List<Camera> cameras = new ArrayList<Camera>();
+    cameras.add(getCamera());
+    TerrainLodControl control = new TerrainLodControl(terrain, cameras);
+    terrain.addControl(control);
+

+Close parts of the terrain are rendered in full detail. Terrain parts that are further away are not clearly visible anyway, and jME improves performance by rendering them less detailed. This way you can afford to load huge terrains with no penalty caused by invisible details. +

+ +
+ +

Exercises

+
+ +
+ +

Exercise 1: Texture Layers

+
+ +

+ +What happens if you swap two layers, for example m_Tex1 and m_Tex2? + +

+
...
+mat_terrain.setTexture("m_Tex2", grass);
+...
+mat_terrain.setTexture("m_Tex1", dirt);
+

+It's easier to swap layers in the code than to change the color in the alphamap. +

+ +
+ +

Exercise 2: Randomized Terrains

+
+ +

+ +These two lines generate the hightmap from a user defined image: + +

+
Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
+    heightmap = new ImageBasedHeightMap(
+      ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 1f);
+

+ +You can also let jME create a random landscape. + +

+
    +
  1. What result do you get when you replace the two heightmap lines by the following lines and run the sample?
    +
  2. +
+
HillHeightMap heightmap = null;
+ 
+try {
+    heightmap = new HillHeightMap(513, 1000, 50, 100, (byte) 3);
+} catch (Exception ex) {
+    ex.printStackTrace();
+}
    +
  1. Change one value at a time and the run the sample again. Note the differences. Can you find out which of the values has which effect on the generated terrain?
    +
      +
    • Which value controls the size?
      +
        +
      • What happens if the size is not a square number +1 ?
        +
      • +
      +
    • +
    • Which value controls the number of hills generated?
      +
    • +
    • Which values control the minimum and maximum radius of the hills?
      +
        +
      • What happens if the minimum is bigger than the maximum?
        +
      • +
      +
    • +
    • Which value controls the flattening of the hills?
      +
        +
      • What happens if this value is 1 ?
        +
      • +
      +
    • +
    +
  2. +
+ +

+ +Tip: You can keep using the splatted texture from the sample code above. Just don't be surprised that the textures do not automatically adjust to the randomized landscape. +

+ +
+ +

Conclusion

+
+ +

+ +You have learned how to create terrains that are more efficient as loading a giant model. You are now also able to texture a terrain. +

+ +

+In the next chapter, you will learn how to add sounds to your game. + +

+
+ +

+See also: Terrain Collision +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/build_jme3_sources_with_netbeans.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/build_jme3_sources_with_netbeans.html new file mode 100644 index 000000000..b17b13eaf --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/build_jme3_sources_with_netbeans.html @@ -0,0 +1,275 @@ + +

Setting up JME3 in Netbeans 6.x

+
+ +

+ +You are welcome to try out the new jME3, and contribute patches and features! This document shows how to download, set up, build, and run the latest development version from the sources. (As of Early 2010, we are in pre-alpha.) +

+ +

+
+ +

+ +

+Note: In the following, always replace ”~” with the path to your home directory. +

+ +
+ +

Downloading the Sources

+
+ +

+ +Check out the sources form the repository. (The following NetBeans instructions are equivalent to executing cd ~/NetBeansProjects; svn checkout on the commandline.) + +

+
    +
  1. In NetBeans go to Team > Subversion > Checkout
    +
      +
    1. Repository URL:
      +
    2. +
    3. You can leave user/pw blank for anonymous access.
      +
    4. +
    +
  2. +
  3. Click Next
    +
      +
    1. Repository Folders: “branches/jme3”
      +
    2. +
    3. Local Folder: ~/NetBeansProjects
      +
    4. +
    +
  4. +
  5. Click Finish and wait.
    +
  6. +
+ +

+ +The jme3 project opens in the Project window. +

+ +

+Look into the Libraries node and confirm that the project depends on the following libraries in the classpath: +

+
+jME3-natives-joal.jar	lwjgl.jar       gluegen-rt.jar
+jME3-jogl-natives.jar   jbullet.jar	stack-alloc.jar
+jME3-lwjgl-natives.jar	jinput.jar	swing-layout-1.0.4.jar
+j-ogg-oggd.jar	        joal.jar	vecmath.jar
+j-ogg-vorbisd.jar       jogl.jar        asm-all-3.1.jar
+
+ +

+If you should see any red exclamation marks on packages, look at the Troubleshooting section below. +

+ +
+ +

Optional: Setting up JOAL and JOGL

+
+ +

+ +This steps configures two optional libraries: JOAL for Audio, and JOGL as back-up option for older GPUs. (This step is recommended, but you can skip it if you know what are are doing.) + +

+
    +
  1. Open the jme3's project properties from the Projects window, and go to the Run category.
    +
  2. +
  3. Under VM Options, enter the following, depending on your operating system. (Replace 32 with 64 if applicable.)
    +
      +
    • Windows: -Djava.library.path=“lib/jogl/win32/:lib/joal/win32/”
      +
    • +
    • Linux: -Djava.library.path=“lib/jogl/linux32/:lib/joal/linux32/”
      +
    • +
    • Mac OS: -Djava.library.path=“lib/jogl/macosx_universal/:lib/joal/macosx/”
      +
    • +
    +
  4. +
+ +

+ +It is possible to configure one univerversal java library path - this is useful if you ever need to build a platform-independent JAR of your project: +

+
    +
  • -Djava.library.path=“lib/jogl/win32/:lib/joal/win32/:lib/jogl/linux32/:lib/joal/linux32/:lib/jogl/macosx_universal/:lib/joal/macosx/”
    +
  • +
  • -Djava.library.path=“lib/jogl/win64/:lib/joal/win64/:lib/jogl/linux64/:lib/joal/linux64/:lib/jogl/macosx_universal/:lib/joal/macosx/”
    +
  • +
+ +

+ +Important: When copying from the wiki, make certain to use normal quotation marks, not the curly ones. +

+ +
+ +

Optional: Setting up Android Support

+
+ +

+ +Work in progress … +

+ +

+A jme3 application can either be deployed to the desktop (as Java Swing application) and web browser (as JNLP/WebStart or Applet), or to an Android phone. While the former is the default, switching to Android deployment can be done in a few steps. + +

+
    +
  1. Open Project Properties, go to Sources category.
    +
  2. +
  3. At Source Packages Folders, click “Add Folder”.
    +
      +
    • Add src/jme3_android
      +
    • +
    • Remove src/jme3_desktop
      +
    • +
    • Remove src/jme3_desktop_fx
      +
    • +
    +
  4. +
  5. build.xml…
    +
  6. +
+ +
+ +

Build and Run

+
+ +

+ +That's it! +

+
    +
  1. Right-click the jme3 project node and “Clean and Build” the project.
    +
  2. +
  3. In the Projects window, browse to the src/jme3_test folder.
    +
  4. +
  5. Right-click the file jme3_test/model/TestBox.java and choose “Run” to run a sample.
    +
      +
    1. In the sample application, use the mouse and the AWSD keys to move around the test object.
      +
    2. +
    3. Press escape to quit the sample application.
      +
    4. +
    +
  6. +
+ +

+ +Sample code for cool features is in the src/jme3_test folder. A sample game can be found in jme3_games/jme3game/cubefield/CubeField.java. +

+ +

+Tips: +

+
    +
  • To run runnable classes from the Projects window, right-click and choose Run.
    +
  • +
  • To run any runnable class that is open in the editor, press shift-F6.
    +
  • +
+ +
+ +

Optional: Javadoc Popups and Source Navigation in NetBeans

+
+ +

+ +If you are working on the jme3 sources: +

+
    +
  1. In the Projects window, right-click the jme3 project and choose Generate Javadoc. Wait.
    +
  2. +
  3. Confirm in the Files window that the javadoc has been created in ~/NetBeansProjects/jme3/dist/javadoc
    +
  4. +
  5. In the editor, place the caret in a jme class and press ctrl-space to view javadoc.
    +
  6. +
+ +

+ +If you are working on a game project that depends on jme3: +

+
    +
  1. First follow the previous tip. (In the future, we may offer jme javadoc as download instead.)
    +
  2. +
  3. In your game project, right-click the Libraries node and choose “Properties”.
    +
  4. +
  5. In the Library properties, select jme3.jar and click the Edit button.
    +
      +
    1. For the Javadoc field, browse to ~/NetBeansProjects/jme3/dist/javadoc. Check “as relative path” and click select.
      +
    2. +
    3. For the Sources field, browse to ~/NetBeansProjects/jme3/src. Check “as relative path” and click select.
      +
    4. +
    5. Click OK.
      +
    6. +
    +
  6. +
  7. In the editor, place the caret in a jme class and press ctrl-space to view javadoc. Ctrl-click any jme3 method to jump to its definition in the sources.
    +
  8. +
+ +

+ +This tip works for any third-party JAR library that you use. (You may have to download the javadoc/sources from their home page separately). +

+ +
+ +

Troubleshooting

+
+ +

+ +Cannot Find Symbol SwingWorker compile errors, and red exclamation marks on some package icons? SwingWorker is part of JDK6 but not JDK5. If you get this error, you have two options to fix it: +

+
    +
  • Make sure you have JDK6 installed, and switch the jme3 project to JDK6.
    +
      +
    1. In NetBeans, register the JDK6 in the “Tools > Java Platform” manager.
      +
    2. +
    3. Open the jme3 Project Properties, and switch the JDK settings in the “Sources” and “Libraries” sections to JDK6.
      +
    4. +
    5. Clean and Build.
      +
    6. +
    +
  • +
  • Alternatively, if you must stay with JDK5:
    +
      +
    1. Temporarily remove the directory jme3_tools/deploy.
      +
    2. +
    3. Clean and Build.
      +
    4. +
    +
  • +
+ +

+ +
+ +

+
+ +

+ +
+ +

+ +

+Sources used: , +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/bullet_multithreading.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/bullet_multithreading.html new file mode 100644 index 000000000..c22e13fb2 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/bullet_multithreading.html @@ -0,0 +1,138 @@ + +

Multithreading Bullet Physics in jme3

+
+ +
+ +

Introduction

+
+ +

+With computers having multiple cores nowadays, it seems feasible to let the physics run on a separate thread. However, there are some implications and plain multithreading is not always the solution for problems but bring on new ones. +

+ +

+Multithreading is misunderstood by many programmers nowadays. The secret is not to have separate detached logical loops going on in parallel and have them communicate about their state (Like one thread AI, one Sound, one Graphics) but to have a normal “loop” for logic and then just multithread within that loop when its appropriate. Each for loop in the main loop might be a chance for MT'ing, this scales way better to multiple cores and does not break up code logic. So ideally, the physics system makes use of multiple cores itself and is still included in a “normal” update order. Since bullet is not (yet) multithreaded or GPU accelerated the jME3 implementation allows some ways to run the physics on a separate thread. These are described here. +

+ +
+ +

How is it handled in jme3 and bullet?

+
+ +

+ +A SimpleApplication with a BulletAppState allows setting the threading type via +

+
setThreadingType(ThreadingType type);
+ +

+ where ThreadingType can be either SEQUENTIAL, PARALLEL or DETACHED. +

+ +

+In the simpleInitApp() method: +

+
bulletAppState = new BulletAppState();
+bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
+stateManager.attach(bulletAppState);
+
+ +

SEQUENTIAL

+
+ +

+This does everything sequentially on one thread, updating the scene, updating physics and then rendering the scene. +

+ +
+ +

Good about this way:

+
+
    +
  1. Seamless for user, no syncing problems
    +
  2. +
+ +
+ +

Bad about this way:

+
+
    +
  1. no multithreading (only one core is used)
    +
  2. +
+ +
+ +

PARALLEL

+
+ +

+ +This solution comes close to the “one loop /w parallel computations” way I described before. Here the physics update happens in parallel to rendering, after the users changes have been made in the update() call. This way the loop logic is still maintained: the user can set and change values in physics and scenegraph objects before render() and physicsUpdate() are called in parallel. +This is the “standard” form of multithreading since it will produce less problems for users. +

+ +
+ +

Good about this way:

+
+
    +
  1. Seamless for user, no syncing problems
    +
  2. +
+ +
+ +

Bad about this way:

+
+
    +
  1. render and physics thread will have to wait for each other, lowering the multithreading efficiency
    +
  2. +
  3. user update(), updateGeometric() and updateLogic() takes away cpu cycles for rendering and physics, not just render time
    +
  4. +
+ +
+ +

DETACHED

+
+ +

+This mode lets the physics update loop run completely separate on another thread and the location/rotation of the single physics objects (via the MotionState) is atomized. This way the scenegraph loop can safely get and set these values. However all physics parameters have still to be changed from the physics thread and adding/removing of objects has to happen via the physics thread. +The updatePhysics() method is called by a separate thread and you have to care for yourself that you access the physics parameters of a PhysicsNode from the physics thread and the “rest” of the parameters via the opengl thread. +

+ +
+ +

Good about this way:

+
+
    +
  1. Because only the single objects are atomized, the scenegraph and physics update loops will seldom block each other as they're probably working in different “areas” of the scenegraph most of the time. This means maximum thread efficiency.
    +
  2. +
+ +
+ +

Bad about this way:

+
+
    +
  1. Because only the single objects are atomized, the state of the physics objects that is applied to the jme objects is not assured to be from the same physics step for all objects. But still many users of bullet handle it this way and in effect its not noticeable.
    +
  2. +
  3. User has to care about what to modify from what thread
    +
  4. +
+ +
+ +

Future of jme3/bullet

+
+ +

+In the future, I hope that when I have integrated the native bullet version with OpenCL support etc. the PARALLEL solution or even the SEQUENTIAL solution becomes the standard way of doing things as the boost in performance from the graphics card should beat the boost from using another CPU by far. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/dolphin-mesh.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/dolphin-mesh.png new file mode 100644 index 000000000..532af5bdf Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/dolphin-mesh.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/api_feature_mapping.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/api_feature_mapping.html new file mode 100644 index 000000000..c85dbd836 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/api_feature_mapping.html @@ -0,0 +1,269 @@ + +

JME 3 - API / Feature Mapping

+
+ +

+ +This page provides a quick answer to the questions “I want my game to do X, where do I find that in jME 3 ??” +

+ +

+Knowing exactly what you are looking for allows you to search more efficiently, find documentation more quickly, and ask clearer questions on the . This intermediate page assumes that you already went through the beginner tutorials. Feel free to add APIs, tutorials and javadoc links that helped you understand and use a feature! +

+ +
+ +

Applications and SceneGraph

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
How do I…? Use this JME 3 Feature! Learn more here…
Start with a preconfigured game com.jme3.app.SimpleApplication Hello SimpleApplication
Make an object appear in the scene Attach nodes and geometries to the rootNode: rootNode.attach(geo);
+ com.jme3.scene.Node, com.jme3.scene.Geometry
The Scene Graph
+ Hello Asset
+ Hello Node
Use third-person view Use default camera cam
+ com.jme3.renderer.Camera
ChaseCam WIP
Use first-person view Use camera flyCam
+ com.jme3.input.FlyByCamera
Hello Collision
Only draw outline of the scene Use a wireframe material, e.g. for debugging. Debugging
Change the background color Call viewPort.setBackgroundColor(ColorRGBA.Blue); N/A
Customize the applicaton class Extend com.jme3.app.SimpleApplication (or com.jme3.app.Application) and set Application Settings SimpleApplication 
+ AppSettings
Force or disable cullingrootNode.setCullHint(CullHint.Never);N/A
Disable the loggerLogger.getLogger(””).setLevel(Level.SEVERE);
+ java.util.logging.*
Logging
+ +
+ +

Creation and Manipulation of Objects

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
How do I…? Use this JME 3 Feature! Learn more here…
Make simple shapes like cubes, spheres com.jme3.scene.Geometry, com.jme3.scene.shape.* Hello Node, Shape
+ , ,
Create a 3-D model Create the model in a 3-D mesh editor (for example Blender) and export it as Ogre XML mesh. , ,
+ 3D Models
Load a 3-D model Import asset as Ogre XML mesh.
+ jMonkeyPlatform: Converting Ogre to j3o binary format speeds up model loading.
+ AssetManager, com.jme3.scene.plugins.ogre.*, com.jme3.scene.Geometry
Hello Asset
+ jMonkeyPlatform j3o converter
+ ,
Move or turn or resize an object Use transformations: geo.setLocalTranslation(), geo.rotate(), geo.scale()
+ geo.updateGeometricState();
Hello Node
+ Spatial
Concatenate transformations (e.g. rotations around several axes in one step) com.jme3.math.Quaternion, slerp()
+ com.jme3.math.Transform, interpolateTransforms()
rotate, rotate_about_a_point, quaternion, math_for_dummies
Make an object move by itself Change the geo's translation in the update phase of the main loop. Or remote-control the motion using cinematics.
+ com.jme3.scene.Geometry, setLocalTranslation(), setWalkDirection() for physical objects.
Hello Loop
+ Update Loop
+ Custom Controls
+ Cinematics
+ ,
Manipulate the color or shininess of an object Materials, AssetManager Hello Material
+ Materials Overview
+ ,
Manipulate the surface of an object (wood vs stone vs metal etc) Textures, AssetManager. Hello Material
+ Materials Overview
+
+
Make objects cast a shadow com.jme3.shadow.BasicShadowRenderer, com.jme3.light.DirectionalLight
+ setShadowMode()
Light and Shadow
+ ,
Render transparent objects (glass, window panes, water, tree leaves) Assign a transparent texture to the Material and set material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); Hello Material
+ Materials Overview
Force or disable Backface culling com.jme3.material.RenderState.FaceCullMode: Back, Front, FrontAndBack, Off
+ e.g. material.getAdditionalRenderState(). setFaceCullMode(FaceCullMode.FrontAndBack);
N/A
Make procedural or custom shapes com.jme3.scene.Mesh Custom Meshes
Keep my models, textures, sound files in order Put all assets in subdirectories of a project directory named assets and use the assetManager to load them. Hello Asset, Asset Manager
Identify Named Sub-Mesh in ModelGeometry result = spatial.getName().startsWith(name);Spatial
+ +
+ +

Actions, Interactions, Physics

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
How do I…? Use this JME 3 Feature! Learn more here…
Implement the game logic and game mechanics Use Controls to define behaviours of types of Spatials. Use Application States to implement global behaviours. Use the simpleUpdate() loop for the remaining tests and interactions. Use Cinematics to remote-control objects in scenes. Hello Loop
+ Update Loop
+ Custom Controls
+ Application States
+ Cinematics
Let players interact by pressing keyboard keys com.jme3.input.KeyInput, com.jme3.input.binding.BindingListener Hello Input
+ Input Handling
Let players interact by clicking, e.g. picking up objects, opening doors, shooting Intersect a Ray from the player with the Bounding Volume of the target: com.jme3.bounding.*, com.jme3.math.Ray, com.jme3.collision.CollisionResults. Hello Picking
+ Collision and Intersection
+
Animate objects and characters Create an animated OgreMesh model with Bones in a 3-D editor (e.g. Blender).
+ com.jme3.animation.*
Hello Animation
+ Animation
+ ,
Keep players walking on floors of scenes Collision detection – raycasting or physics. Hello Collision
+ Physics
Prevent players from walking through walls in scenes Collision detection using physics and bounding volumes.
+ com.jme3.bullet.*, CapsuleCollisionShape / CompoundCollisionShape, PhysicsCharacterNode / PhysicsNode
+ geo.setModelBound(); geo.updateModelBound();
Hello Collision
+ Physics
Let balls, cars, etc bounce off obstacles and roll on floors Use physics nodes and bounding volumes: com.jme3.bounding.*, com.jme3.bullet.collisions, com.jme3.bullet.nodes.PhysicsNode etc
+ geo.setModelBound(); geo.updateModelBound();
Hello Physics
+ Physics
+ ,
Steer cars, motorcycles, etc Use physics characters and vehicles: com.jme3.bullet.*, PhysicsCharacterNode, PhysicsVehicleNode Vehicles
+ ,
+ (Press HUJK keys to steer, spacebar to jump.)
Let an object swing like a pendulum or chain links Use physics joints: com.jme3.bullet.joints.PhysicsHingeJoint Hinges and Joints
+
+ (Press HK keys to turn, spacebar to swing.)
+ +
+ +

GUI Display

+
+ + + + + + + + + + + + + +
How do I…? Use this JME 3 Feature! Learn more here…
Get rid of default debug display (fps etc) in SimpleApplication guiNode.detachAllChildren(); N/A
Display text (score, health), flat mini-maps or status icons Attach a picture to the orthogonal guiNode to create a heads-up display ().
+ com.jme3.font.*, com.jme3.ui.Picture. guiNode.attachChild()
HUD
+ ,
Display buttons to let the player switch between the game/settings/score screens Nifty GUI Nifty GUI
+
+ +
+ +

Environment Effects: Sound, Landscape

+
+ + + + + + + + + + + + + + + + + + + +
How do I…? Use this JME 3 Feature! Learn more here…
Play sounds and noises AudioRenderer, Listener, and AudioNode from com.jme3.audio.* Hello Audio
+ Audio
+
Simulate fire, flames, smoke, explosions, swarms, dust, magic spells Use particle emitters: com.jme3.effect.EmitterSphereShape, com.jme3.effect.ParticleEmitter Hello Effects
+ Particle Emitters
+ Bloom and Glow
+ Effects Overview
+ ,
Simulate water, waves, reflections com.jme3.water.* Water
+ Post-Processor Water
+
Generate a terrain com.jme3.terrain.* Hello Terrain
+ Terrain
+
Simulate a sky rootNode.attachChild(SkyFactory.createSky( assetManager, “Textures/Sky/Bright/BrightSky.dds”, false));
+ skyGeo.setQueueBucket(Bucket.Sky)
Sky
+
+ +
+ +

Back-End Properties

+
+ + + + + + + + + + +
How do I…? Use this JME 3 Feature! Learn more here…
Check graphic card capabilitiescom.jme3.renderer.Caps
+ Collection<Caps> caps = renderer.getCaps();
+ Logger.getLogger(HelloJME3.class.getName()).log(Level.INFO, “Caps: {0}” + caps.toString());
N/A
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/appsettings.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/appsettings.html new file mode 100644 index 000000000..741a78d35 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/appsettings.html @@ -0,0 +1,106 @@ + +

jME3 Application Display Settings

+
+ +

+ +Every class that extends jme3.app.Application (or jme3.app.SimpleApplication) has properties that can be configured by customizing a com.jme3.system.AppSettings object. Configure the settings before you call app.start() on the application object. If you change display settings during runtime, call app.restart() to make them take effect. +

+ +

+Note: Other runtime settings are covered in SimpleApplication. +

+ +
+ +

Code Sample

+
+
AppSettings settings = new AppSettings(true);
+settings.setRenderer(AppSettings.LWJGL_OPENGL3);
+Application app = new Application();
+app.setSettings(settings);
+app.start();
+

+Set the boolean in the AppSettings contructor to true if you want to keep the default settings for everything that you do not specify. Set this parameter to false if you want to specify each property yourself (you'll get an exception if you missed one). +

+ +

+Use app.setShowSettings(false); to disable the default settings-window at startup. +

+ +
+ +

Properties

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDscriptionDefault
setRenderer(AppSettings.LWJGL_OPENGL2)
+ setRenderer(AppSettings.LWJGL_OPENGL3)
Switch Video RendererOpenGL 2
setAudioRenderer(AppSettings.LWJGL_OPENAL)
+ setAudioRenderer(AppSettings.LWJGL_JOAL)
Switch Audio RendererOpenAL
setBitsPerPixel(8)Set color depth.
+ 1 = black and white, 2 bit = gray,
+ 4 = 16 colors, 8 = 256 colors, 24 or 32 = “truecolor”.
24
setFrequency(60)The screen frequency (refresh rate of the graphics card), usually 60 or 75 fps.60 fps
setFramerate(60)How often per second the engine should try to refresh the frame. For the release, usually 60 fps. Can be lower (59-30) for FX-intensive games. Do not set to a higher value than the screen frequency.-1 (auto)
setFullscreen(true)Set this to true to make the display fill the whole screen; you need to provide a key that calls app.stop() to exit the fullscreen view gracefully (default: escape).
+ Set it to false to play the game in a normal window of its own.
False (windowed)
setHeight(480), setWidth(640)
+ setResolution(640,480)
Two equivalent ways of setting the display resolution.640×480 pixels
setSamples(4)Set multisampling to 0 to switch antialiasing off (harder edges, faster.)
+ Set multisampling to 2 or 4 to activate antialising (softer edges, may be slower.)
+ Depending on your graphic card, you may be able to go set multisampling to 8, 16, or 32 samples.
0
setVSync(true)Set vertical syncing to true to time the frame buffer to coincide with the refresh interval of the screen: Prevents page tearing, but slower; recommened for release.
+ Set to false to deactivate vertical syncing (faster, but possible page tearing artifacts); can be deactivated during development.
false
useInput(false)Respond to user input by mouse and keyboard. Can be deactivated for use cases where you only display a 3D scene on the canvas without any interaction.true
useJoysticks(true)Activate optional joystick supportfalse
setSettingsDialogImage(”/path/in/assets.png”)A custom image to display when the settings dialog is shown.”/com/jme3/app/Monkey.png”
setTitle(“My Game”)This string will be visible in the titlebar, unless the window is fullscreen.“jMonkey Engine 3.0”
+ +
+ +

Methods

+
+ +

+ +An AppSettings object also supports the following methods: +

+
    +
  • Use settings.save(outstream) and settings.load(instream) to save and load your settings via standard java.io serialization.
    +
  • +
  • Use newSettings.copyFrom(oldSettings) to copy a settings object.
    +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/best_practices.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/best_practices.html new file mode 100644 index 000000000..ba2e81ec7 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/best_practices.html @@ -0,0 +1,505 @@ + +

Best Practices For jME3 Developers

+
+ +

+ +A collection of recommendations and expert tips. Feel free to add your own! +

+ +

+If you are a beginner, you should first game developement. We cannot cover all general tips here. +

+ +
+ +

Requirements Gathering

+
+ +

+ +As a quick overview, answer yourself the following questions: + +

+
    +
  • Motivation
    +
      +
    • Sum up your game idea in one sentence. If you can't, it's too complicated.
      +
    • +
    • Who's the target group? Why would they choose your game over the million others that exist?
      +
    • +
    +
  • +
  • Game type
    +
      +
    • Point of view (camera)? What character(s) does the player control (if any)?
      +
    • +
    • Time- or turn-based?
      +
    • +
    • Genre, setting, background story? (If applicable)
      +
    • +
    +
  • +
  • Gameplay
    +
      +
    • What is the start state, what is the end state?
      +
    • +
    • What resources does the player manage? E.g. speed, gold, health, “points”
      +
    • +
    • How does the player interact? Rules, challenges, game mechanics
      +
    • +
    • What state is considered winning, and what losing?
      +
    • +
    +
  • +
  • Media assets
    +
      +
    • Which media will you need? How will you get this content?
      + models, terrains; materials, textures; audio, sound, music; video; spoken/written dialog; levels, quests, stories; AI scripts
      +
    • +
    +
  • +
  • Interface
    +
      +
    • Can you achieve a high degree of input control? Even minor navigation and interaction glitches make the game unsolvable.
      +
    • +
    • Clearly reflect status and changes in game states. E.g. health/damage.
      +
    • +
    • Clearly reward good moves and discourage bad ones.
      +
    • +
    +
  • +
+ +
+ +

Planning Development Milestones

+
+
    +
  1. Pre-Alpha
    +
      +
    1. Lay out the overall application flow using mock-ups or stock art. E.g. switching between intro screen / options screen / game screen.
      +
    2. +
    3. Get one typical level working. E.g. if it's a “Jump'n'Run”, jumping and running must work before you can call it an Alpha.
      +
    4. +
    +
  2. +
  3. Alpha
    +
      +
    1. Run internal tests, debug, optimize (issue tracker).
      +
    2. +
    3. Replace all mock-ups with first drafts of real media and levels.
      +
    4. +
    5. Feature Freeze: Avoid a bottomless pit of side effects causing new issues.
      +
    6. +
    +
  4. +
  5. Beta
    +
      +
    1. Have external people review and “beta test” it (issue tracker).
      +
    2. +
    3. Even out the kinks in the code – don't add any more new features.
      +
    4. +
    5. Fill in all final content.
      +
    6. +
    +
  6. +
  7. Release Candidate
    +
      +
    1. Last chance to find a horrible bug.
      +
    2. +
    +
  8. +
  9. Final Release
    +
  10. +
+ +

+ +How you actually name or number these milestones is up to you. People use the words “milestone”, Greek letters, versions, numbers, or combinations thereof. +

+ +

+Every milestone has a development phase and a test phase. Here are some best practices: +

+ +
+ +

Development Phase

+
+ +
+ +

Where to Start?

+
+ +

+ +You have a list of features that you want in game, but which one do you implement first? You will keep adding features to a project that grows more and more complex, how can you minimize the amount of rewriting required? + +

+
    +
  1. Start with implementing the most complex game feature first – the one that imposes most constraints on the structure of your project (for instance, networking.)
    +
  2. +
  3. Make sure the game's high-level frame (screen switching, networking, physics, loading/saving) is sound and solid before you implement low-level details of gameplay.
    +
  4. +
  5. Only add one larger feature at a time. If there are complex interactions (such as “networking + physics”), start with a small test case (“one cube”) and work your way up, don't start with a whole scene.
    +
  6. +
  7. Test for side-effects on existing code before you add the next feature.
    +
  8. +
+ +

+ +Acknowledge whether you want a feature because it is necessary for gameplay, or simply because “everyone else has it”. Successful high-performance games are the ones where someone made smart decisions what to keep and what to drop. +

+
    +
  • Example: Everybody wants “full physics, AI, post-rendering effects, and multi-player networking”… Make certain you truly understand what that requires (e.g. client-server synchonization)! Your goal should be to bring out the essence of your game idea, don't water down gameplay but attempting to make it “do everything, but better”.
    +
  • +
+ +
+ +

Extend SimpleApplication

+
+ +

+ +Typically developers create a custom class off of jME3's SimpleApplication. For a racing game you would create a different base game class than for a space game or shooter. + +

+
    +
  1. Create a generic game class for your custom game:
    +
      +
    1. Create a jME3-based project with all necessary JARs on the classpath.
      +
    2. +
    3. Create a class in this package that extends SimpleApplication, name it something like my.company.MyBaseGame.java.
      +
    4. +
    5. Implement all generic features that the game type needs in the MyBaseGame class. For example methods for loading and saving scenes, physics, networking and multi-player logon screen, switching to settings screen, etc.
      +
    6. +
    7. Include generic assets (company logo, reusable GUI elements in your company style, etc) in the MyBaseGame's assets directory.
      +
    8. +
    +
  2. +
  3. Create your actual game, e.g. a shooter:
    +
      +
    1. Create another jME3-based project, and a new package for the game itself, e.g. my.company.zombieshooter.MyGame.java.
      +
    2. +
    3. Add MyBaseGame.jar to the classpath of MyGame.java.
      +
    4. +
    5. Make MyGame.java's main class extend MyBaseGame.
      +
    6. +
    7. The specific assets (scenes, models) of this game go into MyGame's own assets folder.
      +
    8. +
    9. Now implement this game's mechanics and levels – without having to worry about logon&settings screens and all the other features that you already dealt with in MyBaseGame.
      +
    10. +
    +
  4. +
+ +
+ +

Controls and AppStates -- The Smart Way to Implement Game Logic

+
+ +

+ +As your jME3-based application grows more advanced, you may find yourself putting more and more tests in the simpleUpdate() loop, and passing around lots of object references. Don't implement game behaviour by copying and pasting boilerplate code! It is a best practice to move game behaviour into classes of their own. In jME3 these classes are Controls and AppStates. + +

+
    +
  • Use Controls to implement the behaviour of types of game entities. A character control that defines how this type of Spatials moves, an animation control that plays animations in this type of Spatial's model, etc.
    +
  • +
  • Use AppStates to implement global game behaviour: A physics manager, a custom artificial intelligence manager, etc.
    +
  • +
  • Use the simpleUpdate() loop for the remaining “one-off” tests and interactions.
    +
  • +
+ +

+ +Both classes automatically hook into the main update loop. Instead of remote controlling game entities via simpleUpdate(), you define the desired behaviour in the update methods of custom Controls and AppStates. You then add Controls to Spatials, and AppStates to the application, and jME3 will automatically trigger the update methods. This cleans up your simpleUpdate() loop code considerably. +

+ +

+Learn more about Custom Controls and Application States. +

+ +
+ +

Optimize Application Performance

+
+ +

+ +Optimization +

+ +
+ +

Use an Assets Folder

+
+ +

+ +Put your assets into subfolders of your project's assets directory. This is the default path where the assetManager looks for files. +

+
+jMonkeyProjects/Pong/assets/    # Store assets here
+jMonkeyProjects/Pong/build/     # jMP generates built classes here *
+jMonkeyProjects/Pong/build.xml  # Customize Ant build script here
+jMonkeyProjects/Pong/nbproject/ # jMP stores default build.xml and meta data *
+jMonkeyProjects/Pong/dist/      # jMP generates executables here *
+jMonkeyProjects/Pong/src/       # Store Java sources here
+jMonkeyProjects/Pong/test/      # Store test classes here (optional)
+(*) managed by jMonkeyPlatform, don't edit
+
+
    +
  • Agree on a file and directory naming scheme with the designers.
    +
      +
    • Are there assets (models, sound files, …) that will be used interchangeably? Then name or number them in a way so that the developer can swap the assets by swapping part of the path string.
      +
    • +
    • Decide on naming standards for naming interactive parts of models (e.g. arms/legs in an animation).
      +
    • +
    +
  • +
  • Structure the subfolders of assets in any way that suits the project – but stick with one system.
    +
      +
    • Either keep all Textures together with their Ogre meshes in the Model directory.
      +
    • +
    • Or keep the Ogre meshes with their Textures in the Textures directory. (Recommended.)
      +
    • +
    +
  • +
  • Place reusable Textures and Materials (the ones that you set programmatically) into the Textures and Materials directory, respectively.
    +
  • +
  • If different types of assets (materials, textures, models) belong together, create a parallel subdirectory structure for them: Textures/vehicles/car/, Materials/vehicles/car/, Models/vehicles/car/
    +
  • +
+ +

+ +Here is an example of a commonly used directory structure: +

+
+jMonkeyProjects/Pong/assets/Interface/ # .font, .jpg, .png, .xml
+jMonkeyProjects/Pong/assets/MatDefs/   # .j3md
+jMonkeyProjects/Pong/assets/Materials/ # .j3m
+jMonkeyProjects/Pong/assets/Models/    # .j3o
+jMonkeyProjects/Pong/assets/Scenes/    # .j3o
+jMonkeyProjects/Pong/assets/Shaders/   # .vert, .frag
+jMonkeyProjects/Pong/assets/Sounds/    # .ogg, .wav
+jMonkeyProjects/Pong/assets/Textures/  # .mesh.xml+.material, .mtl+.obj, .jpg, .png
+
+ +

+See also: Asset Packs +

+ +
+ +

Don't Mess With Geometric State

+
+ +

+ +Here are some tips especially for users who already know jME2. Automatic handling of the Geometric State has improved in jME3, and it is now a best practice to not mess with it. + +

+
    +
  • Do not call updateGeometricState() on anything but the root node!
    +
  • +
  • Do not override or mess with updateGeometricState() at all.
    +
  • +
  • Do not use getLocalTranslation().set() to move a spatial, always use setLocalTranslation().
    +
  • +
+ +
+ +

Maintain Internal Documentation

+
+ +

+ +It's unlikely you will be willing to fully document every class you write. You should at minimum javadoc all crucial methods/parameters in a meaningful way. + +

+
    +
  • Answer three questions for every crucial method/parameter:
    +
      +
    • What is this?
      +
    • +
    • How does it solve its task? (e.g. algorithm used)
      +
    • +
    • In which situation do I want to use this?
      +
    • +
    +
  • +
  • Write down limits (e.g. min/max values) and defaults while you still remember.
    +
  • +
  • Is this optional or required? What are the alternatives?
    +
  • +
  • Treat javadoc as messages to your future self. “genNextVal() generates the next value” and ”@param float factor A factor influencing the result” do not count as documentation.
    +
  • +
+ +
+ +

Use Version Control

+
+ +

+ +Whether you work in a team or alone, keeping a version controlled repository of your code will help you roll-back buggy changes or recover that code that you or someone deleted and now is needed. +

+
    +
  • Treat commit messages as messages to your future self. “Made some changes” is not a commit message.
    +
  • +
  • The jMonkeyPlatform supports Subversion, Mercurial, and CVS.
    +
      +
    • If you don't know which to choose, Subversion is a good choice for starters.
      +
    • +
    • You can get free project hosting space from various open-source dev portals like , , or . support private projects.
      +
    • +
    +
  • +
+ +
+ +

Convert Models to .j3o Format

+
+ +

+ +From the beta on, convert all Ogre mesh models and scenes to the binary .j3o format. Use the jMonkeyPlatform for the conversion, and save the .j3o files into the Models directory. + +

+
    +
  • .j3o is an optimized format to store part of a jME3 scenegraph.
    + It can contain an individual model or a whole scene. Optionally (using the jMonkeyEngine SceneComposer) you can include the model's physical properties, materials, lights, particle emitters, and audio nodes.
    +
  • +
  • If you kept the Ogre mesh together with the textures in the Textures directory during the conversion, the paths are recorded in a way so that you can move the .j3o to another directory, and it will still find its textures.
    +
  • +
  • The default Ant build script copies .j3o / .j3m files and other assets into the distributable JAR automatically.
    +
  • +
  • Important: Other model files however (.mesh.xml, .material, .obj, .mat) are not bundled automatically. You will get a runtime error that a resource was not found if you try to run the JAR with code referring to these files.
    +
  • +
+ +
+ +

Debugging and Test Phase

+
+ +
+ +

Test

+
+ +

+ +Unit Tests (Java Assertions) have a different status in 3D graphics development than in other types of software. You cannot write any assertions that automatically test whether the rendered image looks correct, or whether interactions are intuitive. Still you should create simple test cases for separate game features such as loaders, content generators, effects. Run them now and then to see whether they still work as intended – or whether they are affected by side effects. Keep the test classes in a test directory in the project, but don't include them in the distribution. +

+ +

+Quality Assurance (QA) means maintaining a clear list of steps that must always work, and checking them. There can be bugs in software, but tasks such as installing and de-installing, saving and loading, starting/pausing/quitting the game, must work, no excuse. After every milestone, you go through the list again, on every supported operating system, and systematically look for regressions or bugs. +

+ +

+Alpha and Beta Testing means that you ask someone to try to install and run your game. It should be a real user situation, where they are left to figure it out by themselves (you only can include the usual read-me and help docs). Provide the testers with an easy method to report back descriptions of their problems, e.g. why they gave up. Evaluate whether these problems are exceptions or must be fixed for the game to be playable. +

+ +
+ +

Debug

+
+ +

+ +A Java Debugger is included in the jMonkeyPlatform. It allows you to set a break point in your code near the point where an exception happens. Then you step through the execution line by line and watch object and variable states to detect where the bug starts. +

+ +

+Use the Logger to print status messages during the development and debugging phase, instead of System.out.println(). +

+ +
+ +

Enhance Performance

+
+ +

+ +A Java Profiler can be added to the jMonkeyPlatform via Tools → Plugins → Available. The profiler presents statistics on the lifecycle of methods and objects. Performance problems may be caused by just a few methods that take long, or are called too often. If object creation and garbage collection counts keep increasing, you are looking at a memory leak. +

+ +
+ +

Release Phase

+
+ +

+ +Pre-Release To-Do List + +

+
    +
  • Verify that all assets are up-to-date and converted to .j3o.
    +
  • +
  • Switch off fine logging output.
    +
  • +
  • Prepare a web page
    +
  • +
  • Prepare a readme.txt file, installation guide, or handbook – if applicable.
    +
  • +
  • Prepare promotional art: Cool screenshots (in thumbnail, square, vertical, horizontal, and fullscreen formats) and video clips. Include name, contact info, slogan, etc.
    +
  • +
  • Get a certificate if it is required for your distribution method (see below).
    +
  • +
  • Specify a classification rating.
    +
  • +
  • +
  • +
+ +

+ +Distributable Executable +

+ +

+Do you release your game as WebStart, Desktop JAR, or Applet? Each has its pros and cons. + +

+ + + + + + + + + + + + + + + + +
DistributionProsCons
Desktop Launcher
+ (.EXE, .app, .jar+.sh)
This is the standard way of distributing desktop applications. The jMonkeyPlatform can be configured to automatically create zipped launchers for each operating system. Your company does not need a certificate.You need to offer three separate, platform-dependent downloads.
Desktop Application
+ (.JAR)
Platform independent desktop application. Your company does not need a certificate.User must have Java configured to run JARs when they are opened; or user must know how to run JARs from command line; or you must provide a custom JAR wrapper.
Web Start
+ (.JNLP)
The user accesses a URL, saves the game as one executable file. Easy process, no installer required. You can allow the game to be played offline.Users need network connection to install the game. Downloading bigger games takes a while as opposed to running them from a CD. Your company must have a trusted certificate.
Browser Applet
+ (.HTML+.JAR)
Easy to access and play game via most web browsers. Userfriendly solution for quick small games.Game only runs in the browser. Game or settings cannot be saved to disk. Your company must have a trusted certificate. Some restrictions in default camera navigation (jME cannot capture mouse.)
+ +

+ +Which ever method you choose, a Java-Application works on the three main operating systems: Windows, Mac OS, Linux. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/coordinate-system.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/coordinate-system.png new file mode 100644 index 000000000..f52ed092f Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/coordinate-system.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/file_types.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/file_types.html new file mode 100644 index 000000000..1f9721ce4 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/file_types.html @@ -0,0 +1,56 @@ + +

jMonkeyEngine3 Supported File Types

+
+ +
+ +

jMonkeyEngine3 File Formats

+
+ + + + + + + + + + + + + +
SuffixUsageLearn more
.j3oBinary 3D model or scene. From the Beta release of your game on, you should convert all models to .j3o format. During alpha and earlier development phases (when models still change a lot) you can alternatively load OgreXML/OBJ models directly.Model Loader and Viewer
.j3mA custom Material. You create these Material objects to store Material configurations for your 3D models.Materials Overview Material Editing
.j3mdA Material definition. These are templates for advanced shader-based Materials. Each custom .j3m Material is based on a .j3md Material Definition. Materials Overview
+ +
+ +

Supported External File Types

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
File SuffixDescription
.mesh.xml, .meshxml, .sceneOgre Mesh XML for 3D models, Ogre DotScene for 3D scenes
.OBJ, .MTLWavefront, 3D model format
.JPG, .PNG, .GIF2D Images, textures
.DDS, .HDR, .PFM, .TGATextures
.fontBitmap fonts
.WAV, .OGGWave and OGG Vorbis audio
.OGVOgg Theora video
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/headlessserver.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/headlessserver.html new file mode 100644 index 000000000..699a7291f --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/headlessserver.html @@ -0,0 +1,76 @@ + +

jME3 Headless Server

+
+ +

+ +When adding multiplayer to your game, you may find that your server needs to know about game state (e.g. where are players, objects? Was that a direct hit? etc.) You can code all this up yourself, but there's an easier way. +

+ +

+It's very easy to change your current (client) game to function as a server as well. +

+ +
+ +

Client Code

+
+ +

+ +First, let's take a look at the default way of creating a new game (in its simplest form): +

+
public static void main(String[] args) {
+  Application app = new Main();
+  app.start();
+}
+
+ +

Headless Server Code

+
+ +

+ +Now, with a simple change you can start your game in Headless mode. This means that all input and audio/visual output will be ignored. That's a good thing for a server. +

+
import com.jme3.system.JmeContext;
+import com.jme3.system.JmeContext.Type;
+ 
+public static void main(String[] args) {
+  Application app = new Main();
+  app.start(JmeContext.Type.Headless);
+}
+

+

Although all input/output is ignored, the server does keep game state and does call the simpleUpdate() as expected. +

+

+ +
+ +

Next steps

+
+ +

+ +Okay, so you can now start your game in a headless 'server mode', where to go from here? + +

+
    +
  • Parse String[] args from the main-method to enable server mode on demand (e.g. start your server like java -jar mygame.jar –server.
    +
  • +
  • Integrate SpiderMonkey, to provide game updates to the server over a network.
    +
  • +
  • Only execute code that's needed. (E.g. place all rendering code inside an if (servermode)-block) (or if (!servermode) for the client).
    +
  • +
  • Add decent logging so your server actually makes sense.
    +
  • +
+ + +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/my_first_game.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/my_first_game.html new file mode 100644 index 000000000..0151b624b --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/my_first_game.html @@ -0,0 +1,135 @@ + +

My First Game - Tutorial Series (Draft)

+
+ +

+ +DRAFT! +

+ +
+ +

Outline

+
+ +

+ +Goal: Concisely show how to write simple game, in context, from end to end. +

+
    +
  • Top-down overview of the finished game and its parts.
    +
  • +
  • Bottom-up tutorial series.
    +
      +
    1. Analysis phase – What questions do I answer myself before I can start implementing?
      +
    2. +
    3. Development phase – What is the work process like? (With code samples)
      +
        +
      • Best practices for project structure (asset directories, packages, classes)
        +
      • +
      • Best practices for common functionalities (input, settings, GUI, formats)
        +
      • +
      • including debugging, profiling, QA testing
        +
      • +
      +
    4. +
    5. Release phase – When do I consider my game complete?
      +
    6. +
    +
  • +
+ +
+ +

User Suggested Topics

+
+
    +
  1. Create and load a scene/terrain
    +
      +
    • Creation: Refer to Blender tutorials until we have our own terrain/scene editor
      +
    • +
    +
  2. +
  3. Create, load and animate models
    +
      +
    • Creation: Refer to Blender tutorials
      +
    • +
    +
  4. +
  5. Basic camera navigation (first-person/third-person view)
    +
  6. +
  7. User input (character moves, attacks)
    +
  8. +
  9. Collision (physics: floor/walls/obstacles)
    +
  10. +
  11. Mouse interaction (shooting/picking up)
    +
  12. +
  13. Basic enemy AI
    +
      +
    • Mainly show how to integrate a simple interactive decision process
      +
    • +
    +
  14. +
  15. Enhancements: Effects, scores, settings, audio, GUI, HUD
    +
      +
    • Show very briefly what is possible and how to integrate L0l
      +
    • +
    +
  16. +
+ +

+ +See also: for jme2 +

+ +
+ +

Tutorial Deliverables

+
+
    +
  1. Playable finished game executable available for download.
    +
  2. +
  3. Finished sources (build script, libraries, assets) available for download.
    +
  4. +
  5. Tutorial series describing the evolution of the project.
    +
  6. +
  7. Snapshots of sources at different stages of development (to go with tutorials).
    +
  8. +
  9. Illustrations and screenshots (to go with tutorials)
    +
  10. +
+
+ +

+ +Draft +

+
+ +
+ +

Taking a Look At the Finished JME3 Game

+
+ +

+ +… +

+ +
+ +

Developing your First JME3 Game

+
+ +

+ +Best Practices +

+ +

+… +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/optimization.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/optimization.html new file mode 100644 index 000000000..2594ba2a2 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/optimization.html @@ -0,0 +1,54 @@ + +

Optimization reference

+
+ +

+ +This page is intended as a reference collection of optimization tricks that can be used to speed up JME3 applications. +

+ +
+ +

Maintain low Geometry count

+
+ +

+ +The more Geometry objects are added to the scene, the harder it gets to handle them in a speedy fashion. +The reson for this is, that for every object a render command must be done, here is a bottleneck betwenn the CPU and the Graficcard. +

+ +

+Possible optimization techniques +

+
    +
  • Use GeometryBatchFactory.optimize(node) to merge the meshes of the geometries contained in the given node into fewer batches (based on common Material used).
    +
  • +
+ +

+ +Side-effects +

+
    +
  • Using GeometryBatchFactory merges individual Geometries into a single mesh. Thereby it becomes hard to apply specific Materials or to remove a single Geometry. Therefore it should be used for static Geometry only that does not require frequent changes or individual materials/texturing.
    +
  • +
  • Using Texture atlases might be a way to provide a limited individual texturing.
    +
  • +
+ +
+ +

Avoid creating new objects

+
+ +

+ +When you use math operations like vectorA.mult(vectorB); new objects are created that have to be garbage collected when you don't use them anymore. Check your math operations for opportunities to use the local version of the math operations, e.g. vectorA.multLocal(vectorB). This way the result is stored in vectorA and no new object needs to be created. +

+ + +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/scene-graph.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/scene-graph.png new file mode 100644 index 000000000..2fa05d56f Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/scene-graph.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/simpleapplication.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/simpleapplication.html new file mode 100644 index 000000000..0708c3d14 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/simpleapplication.html @@ -0,0 +1,267 @@ + +

Application and SimpleApplication

+
+ +

+ +The base classes of the jMonkeyEngine3 are com.jme3.app.Application and its subclass com.jme3.app.SimpleApplication. SimpleApplication extends Application, and offers everything that Application offers, plus pre-configured features such as a scene graph and a flyby cam. +

+ +

+Your game class typically extends com.jme3.app.SimpleApplication. You call app.start() and app.stop() on your game instance to start or quit the application. The following code sample shows the typical base structure of a jME3 game: +

+
import com.jme3.app.SimpleApplication;
+ 
+public class HelloWorld extends SimpleApplication {
+ 
+    public static void main(String[] args){
+        HelloWorld app = new HelloWorld();
+        app.start(); 
+    }
+ 
+    @Override
+    public void simpleInitApp() {
+       /* Initialize your game scene here */
+    }
+ 
+    @Override
+    public void simpleUpdate(float tpf) {
+       /* Interact with game events here in the main loop */
+    }
+}
+

+Let's have a look at what the base classes have to offer. +

+ +
+ +

Application Class

+
+ +

+ +The com.jme3.app.Application class represents an instance of a real-time 3D rendering jME3 application. A com.jme3.app.Application provides all the tools that are commonly used in jME3 applications. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Class field or methodPurpose
contextThe application context contains renderer, AppSettings, timer, etc. The context object is not usually directly accessed by users.
getRenderManager()
+ getRenderer();
Low-level and high-level rendering interface.
getStateManager()The Application state manager is used to activate physics.
viewPortThe view object for the default camera.
guiViewPortThe view object for the orthogonal GUI view. Used internally for HUDs.
settings
+ setSettings()
The AppSettings let you specify the display width and height (by default 640×480), color bit depth, z-buffer bits, anti-aliasing samples, and update frequency, video and audio renderer, asset manager.
timerInternal update loop timer. Users have access to the tpf float variable in the simpleUpdate() loop to time actions.
camThe default camera with perspective projection, 45° field of view, near plane = 1 wu, far plane = 1000 wu.
assetManager
+ getAssetManager()
An object that manages paths for loading models, textures, materials, sounds, etc. By default the AssetManager paths are relative to your projects root directory.
getAudioRenderer()
+ getListener()
The audio system.
keyInput
+ mouseInput
+ joyInput
Default input contexts for keyboard, mouse, and joystick
getInputManager()Use the inputManager to configure your custom inputs.
inputEnabledSet this boolean whether the system should listen for user inputs (or instead just play a non-interactive scene).
setPauseOnLostFocus()Set this boolean whether the game should pause when ever the window loses focus.
pausedSet this boolean during runtime to pause/unpause a game.
start()
+ start(jMEContextType)
Call this method to start a jME3 game. By default this opens a new jME3 window, initializes the scene, and starts the event loop. Can optionally accept com.​jme3.​system.​JmeContext.Type.* as argument to run headless or embedded. (See below.)
restart()Reloads the AppSettings into the current application context.
stop()Stops the running jME3 game and closes the jME3 window.
+ +

+ +The jME Context Type (com.​jme3.​system.​JmeContext.Type.*) is one of the following: +

+
    +
  • Display – jME application runs in a window of its own. This is the Default.
    +
  • +
  • Canvas – jME application is embedded in a Swing Canvas)
    +
  • +
  • Headless – jME application runs its event loop without calculating any view and without opening any window. Can be used for a Headless Server application.
    +
  • +
  • OffscreenSurface – jME application view is not shown, but calculated and cached as bitmap (back buffer).
    +
  • +
+ +

+You can switch Context Types when starting the application, for example: app.start(JmeContext.Type.Headless); +

+ +

+See also: AppSettings +

+ +
+ +

SimpleApplication Class

+
+ +

+ +The com.jme3.app.SimpleApplication class extends the com.jme3.app.Application class to provide default functionality like a first-person (fly-by) camera, and a scenegraph with a rootNode that is updated and rendered regularly. +

+ +

+By default, a SimpleApplication displays statistics (such as frames per second) on-screen, using the com.jme3.app.StatsView class. You deactivate the statistics view by calling getGuiNode().detachAllChildren();. +

+ +

+Some input keys are pre-configured by default: You quit the application by pressing the Escape key, and you can control the camera using the mouse, the arrow keys, and WASD keys. (More details below.) +

+ +

+Additional to what Application offers, SimpleApplication offers: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SimpleApplication FeaturePurpose
getRootNode()
+ rootNode
The root node of the scene graph. A Spatial that you attach to the rootNode appears in the 3D scene.
getGuiNode()
+ guiNode
Attach flat GUI elements (such as HUD images and text) to this orthogonal GUI node.
loadStatsView()Call this method to print live statistic information to the screen, such as current frames-per-second and triangles/vertices counts. You deactivate this statistics view by calling getGuiNode().detachAllChildren();.
getFlyByCamera()
+ flyCam
The default fly-by camera object, controlled by the WASD and arrow keys.
setShowSettings(true)Whether the user should be presented with a splashscreen and display settings dialog when starting the game. Set this boolean before calling start() on the SimpleApplication.
simpleInitApp()Override this method to initialize the game scene. Here you load and create objects, attach Spatials to the rootNode, and bring everything in its starts position.
simpleUpdate(float tpf)Override this method to have access to the main event loop. Use this loop to poll the current game state and respond to changes, or to initiate state changes and to generate encounters. For advanced info how to hook into the update loop, see also Application States and Custom Controls.
simpleRender()Optionally, override this method to do advanced modifications to the frameBuffer and scene graph.
+ +
+ +

Input Defaults

+
+ +

+ +The following default actions are available for a running game: + +

+ + + + + + + + + + + + + +
KeyAction
KEY_ESCAPEQuits the game by calling app.stop()
KEY_CPrints camera position, rotation, and direction
KEY_MPrints memory usage stats
+ +

+ +If useInput() is true, the default Flyby Cam is active. Then the following so-called “WASD” inputs are additionally available: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Camera MotionKey or Mouse Input
Move ForwardKEY_W
Move Left (Strafe)KEY_A
Move BackwardKEY_S
Move Right (Strafe)KEY_D
Move Vertical UpwardKEY_Q
Move Vertical DownwardKEY_Z
Rotate LeftKEY_LEFT, or move mouse horizontally left (-x)
Rotate RightKEY_RIGHT, or move mouse horizontally right (+x)
Rotate UpKEY_UP, or move mouse vertically forward (+y)
Rotate DownKEY_DOWN, or move mouse vertically backward (-y)
Zoom InScroll mouse wheel backward
Zoom OutScroll mouse wheel forward
Rotate dragHold left mouse button and move
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/terrain_collision.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/terrain_collision.html new file mode 100644 index 000000000..096b54f42 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/intermediate/terrain_collision.html @@ -0,0 +1,302 @@ + +

Terrain Collision

+
+ +

+ +*Work in progress* +

+ +

+This page will extend (not the Java keyword!) the Hello_Terrain tutorial in a few small ways in order to show you a quick way to create a Collision Shape out of the map we have generated. A Collision Shape allows a player (who is also a Collision Shape in this tutorial) to collide with the map, i.e. clip, walk on, stand on, etc. in order to create the type of world and interactivity most gamers are familiar with in FPS or MMOs. + +

+
+ about +
+ +
+ +

Sample Code

+
+
package mygame;
+ 
+import jme3tools.converters.ImageToAwt;
+import com.jme3.app.SimpleBulletApplication;
+import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
+import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
+import com.jme3.bullet.nodes.PhysicsCharacterNode;
+import com.jme3.bullet.nodes.PhysicsNode;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.material.Material;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.Camera;
+import com.jme3.terrain.geomipmap.TerrainLodControl;
+import com.jme3.terrain.heightmap.AbstractHeightMap;
+import com.jme3.terrain.heightmap.ImageBasedHeightMap;
+import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Texture.WrapMode;
+import java.util.ArrayList;
+import java.util.List;
+ 
+public class Main extends SimpleBulletApplication {
+ 
+    private TerrainQuad terrain;
+    PhysicsCharacterNode player;
+    Boolean left = false, right = false, up = false, down = false;
+    private Vector3f walkDirection = new Vector3f();
+ 
+    public static void main(String[] args) {
+        Main app = new Main();
+        app.start();
+    }
+ 
+    @Override
+    public void simpleInitApp() {
+        setupKeys();
+        setupPlayer();
+ 
+        Material terrain_mat;
+        PhysicsNode landscape;
+ 
+        /** 1. Create terrain material and load four textures into it. */
+        terrain_mat = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md");
+ 
+        /** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */
+        terrain_mat.setTexture("m_Alpha", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
+ 
+        /** 1.2) Add GRASS texture into the red layer (m_Tex1). */
+        Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
+        grass.setWrap(WrapMode.Repeat);
+        terrain_mat.setTexture("m_Tex1", grass);
+        terrain_mat.setFloat("m_Tex1Scale", 64f);
+ 
+        /** 1.3) Add DIRT texture into the green layer (m_Tex2) */
+        Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
+        dirt.setWrap(WrapMode.Repeat);
+        terrain_mat.setTexture("m_Tex2", dirt);
+        terrain_mat.setFloat("m_Tex2Scale", 32f);
+ 
+        /** 1.4) Add ROAD texture into the blue layer (m_Tex3) */
+        Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
+        rock.setWrap(WrapMode.Repeat);
+        terrain_mat.setTexture("m_Tex3", rock);
+        terrain_mat.setFloat("m_Tex3Scale", 128f);
+ 
+        /** 2. Create the height map */
+        AbstractHeightMap heightmap = null;
+        Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
+        heightmap = new ImageBasedHeightMap(
+                ImageToAwt.convert(heightMapImage.getImage(), false, true, 0));
+        heightmap.load();
+ 
+        /** 3. We have prepared material and heightmap. Now we create the actual terrain:
+         * 3.1) We create a TerrainQuad and name it "my terrain".
+         * 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65.
+         * 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513.
+         * 3.4) At last, we supply the prepared heightmap itself.*/
+        terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap());
+ 
+        HeightfieldCollisionShape sceneShape = new HeightfieldCollisionShape(heightmap.getHeightMap());
+        landscape = new PhysicsNode(terrain, sceneShape, 0);
+ 
+ 
+        /** 4. The LOD (level of detail) depends on were the camera is: */
+        List<Camera> cameras = new ArrayList<Camera>();
+        cameras.add(getCamera());
+        TerrainLodControl control = new TerrainLodControl(terrain, cameras);
+        terrain.addControl(control);
+ 
+        /** 5. We give the terrain its material, position & scale it, and attach it. */
+        terrain.setMaterial(terrain_mat);
+        landscape.setLocalTranslation(0, -100, 0);
+        rootNode.attachChild(landscape);
+        getPhysicsSpace().add(landscape);
+    }
+ 
+    @Override
+    public void simpleUpdate(float tpf) {
+        Vector3f camDir = cam.getDirection().clone().multLocal(0.2f);
+        Vector3f camLeft = cam.getLeft().clone().multLocal(0.1f);
+        walkDirection.set(0, 0, 0);
+        if (left) {
+            walkDirection.addLocal(camLeft);
+        }
+        if (right) {
+            walkDirection.addLocal(camLeft.negate());
+        }
+        if (up) {
+            walkDirection.addLocal(camDir);
+            walkDirection.y = 0;
+        }
+        if (down) {
+            walkDirection.addLocal(camDir.negate());
+            walkDirection.y = 0;
+        }
+        player.setWalkDirection(walkDirection);
+        cam.setLocation(player.getLocalTranslation());
+    }
+ 
+    public void setupPlayer() {
+        player = new PhysicsCharacterNode(new CapsuleCollisionShape(1.2f, 3f, 1), .05f);
+        player.setJumpSpeed(20);    //10 default
+        player.setFallSpeed(30);    //30 default
+        player.setGravity(30);      //30 default
+        player.setLocalTranslation(new Vector3f(0f, 250f, 150f));
+        rootNode.attachChild(player);
+        getPhysicsSpace().add(player);
+    }
+ 
+    private void setupKeys() {
+        inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A));
+        inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D));
+        inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_W));
+        inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_S));
+        inputManager.addMapping("Jumps", new KeyTrigger(KeyInput.KEY_SPACE));
+        inputManager.addListener(actionListener, new String[]{"Lefts", "Rights", "Ups",
+                    "Downs", "Jumps"});
+    }
+    private ActionListener() {
+ 
+        public void onAction(String binding, boolean value, float tpf) {
+            if (binding.equals("Lefts")) {
+                if (value && player.onGround()) {
+                    left = true;
+                } else {
+                    left = false;
+                }
+            } else if (binding.equals("Rights")) {
+                if (value && player.onGround()) {
+                    right = true;
+                } else {
+                    right = false;
+                }
+            } else if (binding.equals("Ups")) {
+                if (value && player.onGround()) {
+                    up = true;
+                } else {
+                    up = false;
+                }
+            } else if (binding.equals("Downs")) {
+                if (value && player.onGround()) {
+                    down = true;
+                } else {
+                    down = false;
+                }
+            } else if (binding.equals("Jumps") && player.onGround()) {
+                player.jump();
+            }
+        }
+    };
+}
+
+ +

What's Going On?

+
+ +

+To try this code, go into a New Project → JME3 → BasicGame using the default settings (if you haven't already made a default project before) the name should be BasicGame and the package would be called myGame, then just paste this over the entire preconstructed main.java text. Then Add the jme3-test-data library which is available through your library list. This should compile and run from there. +

+ +
+ +

Explaining the Code

+
+ +

+I will only briefly describe the sections that are covered in the original Hello_Terrain. Most detail will be given to the additives. +

+ +

+Imports are to bring in the appropriate class definitions. +

+
private TerrainQuad terrain;
+

+ +Holds our map. + +

+
PhysicsCharacterNode player;
+

+ +Creates our character in the style of FPS that many gamers are familiar with. + +

+
Boolean left = false, right = false, up = false, down = false;
+

+ +Variables for creating fluid movement. + +

+
private Vector3f walkDirection = new Vector3f();
+

+ +The direction we determine from combinations of the booleans. +

+ +

+ +The main function is standard. +In simpleInit we run setupKeys() first and create the common WASD and SPACEBAR to jump. + +

+
inputManager.addListener(actionListener, new String[]{"Lefts", "Rights", "Ups", "Downs", "Jumps"})
+ +

+ +This line indicates our actionListener function and what to do when each command (the string names) is sent. +

+ +

+The onAction function basically sets the booleans true based on which directions we're pressing or makes us jump. +The simpleUpdate function constants changed our direction based on the boolean (ie the directions) we're pressing. +

+ +

+The real collisioning happens in these parts; + +

+
player = new PhysicsCharacterNode(new CapsuleCollisionShape(1.2f, 3f, 1), .05f);
+rootNode.attachChild(player);
+getPhysicsSpace().add(player);
+
+HeightfieldCollisionShape sceneShape = new HeightfieldCollisionShape(heightmap.getHeightMap());
+landscape = new PhysicsNode(terrain, sceneShape, 0);
+
+landscape.setLocalTranslation(0, -100, 0);
+rootNode.attachChild(landscape);
+getPhysicsSpace().add(landscape);
+ +

+The first chunk makes our player into a collision shape that's a capsule, kinda like a human right? And then attaches it to the rootNode and gets it's physics (important!). +The second chunk feeds the heightmap we made into a heightfield collision shape generator to create the collidable shape of the land mass. +The third chunk sets our land and it's collision down some, attaches em to root, and gets the physics. +

+ +
+ +

Conclusion

+
+ +

+You should spawn high up in the area and fall down to the map, giving you a few seconds to survey the domain. Then walk around and see how you like the lay of the land. + +

+
+ +

+See also: + +

+ + +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/math.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/math.html new file mode 100644 index 000000000..a3f79ed90 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/math.html @@ -0,0 +1,1055 @@ + +

Introduction to Mathematical Functionality

+
+ +

+ +It's a fact of life, math is hard. Unfortunately, 3D graphics require a fair bit of knowledge about the subject. Fortunately, jME is able to hide the majority of the details away from the user. Vectors are the fundamental type in the 3D environment, and it is used extensively. Matrices are also a basic necessity of 3D for representing linear systems. Quaternions are perhaps the most complicated of the basic types and are used for rotation in jME. +

+ +

+I'll discuss how these are used in the system for the core functionality. Including Transforming, Visibility Determination, Collision Detection, and the Coordinate System. Note, that these are low level details. Further chapters will discuss how to use these various systems from a high level perspective. +

+ +

+To get a visual introduction to math in jME3 for the absolute beginner, check out our Math for Dummies introduction class. +

+ +
+ +

Coordinate System

+
+ +
+ +

Definition

+
+ +

+ +A coordinate system consists of an origin (single point in space) and three coordinate axes that are each unit length and mutually perpendicular. The axes can be written as the column of a Matrix, R = [U1|U2|U3]. In fact, this is exactly how CameraNode works. The coordinate system defined by Camera is stored in a Matrix. +

+ +

+jME uses a Right-Handed coordinate system (as OpenGL does). +

+ +

+The definition of a coordinate system is defined in jME by the properties sent to Camera. There are no error checks to insure that: 1) the coordinate system is right-handed and 2) The axes are mutually perpendicular. Therefore, if the user sets the axes incorrectly, they are going to experience very odd rendering artifacts (random culling, etc). +

+ +

+ +

+ +
+ +

Transformations

+
+ +

+ +Transformations define an operation that converts points from one coordinate system to another. This includes translation, rotation and scaling. In jME, local transforms are used to represent the positioning of objects relative to a parent coordinate system. While, world transforms are used to represent the positioning of objects in a global coordinate system. +

+ +
+ +

Visibility Determination

+
+ +

+ +Visibility Determination concerns itself with minimizing the amount of data that is sent to the graphics card for rendering. Specifically, we do not want to send data that will not be seen. Data not sent to the graphics card is said to be culled. The primary focus of this section is Frustum Culling based on the Camera's view frustum. In essence, this frustum creates six standard view planes. The BoundingVolume of an object is tested against the frustum planes to determine if it is contained in the frustum. If at any point the object's bounding is outside of the plane, it is tossed out and no longer processed for rendering. This also includes any children that it managed, allowing fast culling of large sections of the scene. +

+ +
+ +

Fundamental Types

+
+ +
+ +

ColorRGBA

+
+ +
+ +

Definition

+
+ +

+ +ColorRGBA defines a color value in the jME library. The color value is made of three components, red, green and blue. A fourth component defines the alpha value (transparent) of the color. Every value is set between [0, 1]. Anything less than 0 will be clamped to 0 and anything greater than 1 will be clamped to 1. +

+ +

+Note: If you would like to “convert” an ordinary RGB value (0-255) to the format used here (0-1), simply multiply it with: 1/255. +

+ +
+ +

jME Class

+
+ +

+ +ColorRGBA defines a few static color values for ease of use. That is, rather than: +

+
ColorRGBA red = new ColorRGBA(1,0,0,1);
+object.setSomeColor(red);
+

+you can simply say: + +

+
object.setSomeColor(ColorRGBA.red)
+

+ColorRGBA will also handle interpolation between two colors. Given a second color and a value between 0 and 1, a the owning ColorRGBA object will have its color values altered to this new interpolated color. +

+ +
+ +

Matrix

+
+ +

+ +See
+ +and +

+ +
+ +

Definition

+
+ +

+ +A Matrix is typically used as a linear transformation to map vectors to vectors. That is: Y = MX where X is a Vector and M is a Matrix applying any or all transformations (scale, rotate, translate). +

+ +

+There are a few special matrices: +

+ +

+zero matrix is the Matrix with all zero entries. +

+ + + + + + + + + + +
000
000
000
+ +

+ +The Identity Matrix is the matrix with 1 on the diagonal entries and 0 for all other entries. +

+ + + + + + + + + + +
100
010
001
+ +

+ +A Matrix is invertible if there is a matrix M-1 where MM-1 = M-1 = I. +

+ +

+ +The transpose of a matrix M = [mij] is MT = [mji]. This causes the rows of M to become the columns of MT. +

+ + + + + + + + + + +
111 123
222123
333 123
+ +

+ +A Matrix is symmetric if M = MT. +

+ + + + + + + + + + +
XAB
AXC
BCX
+ +

+Where X, A, B, and C equal numbers +

+ +

+jME includes two types of Matrix classes: Matrix3f and Matrix4f. Matrix3f is a 3×3 matrix and is the most commonly used (able to handle scaling and rotating), while Matrix4f is a 4×4 matrix that can also handle translation. +

+ +
+ +

Transformations

+
+ +

+ +Multiplying a vector with a Matrix allows the vector to be transformed. Either rotating, scaling or translating that vector. +

+ +
+ +

Scaling

+
+ +

+ +If a diagonal Matrix, defined by D = [dij] and dij = 0 for i != j, has all positive entries it is a scaling matrix. If di is greater than 1 then the resulting vector will grow, while if di is less than 1 it will shrink. +

+ +
+ +

Rotation

+
+ +

+ +A rotation matrix requires that the transpose and inverse are the same matrix (R-1 = RT). The rotation matrix R can then be calculated as: R = I + (sin(angle)) S + (1 - cos(angle)S2 where S is: + +

+ + + + + + + + + + +
0u2-u1
-u20u0
u1-u00
+ +
+ +

Translation

+
+ +

+ +Translation requires a 4×4 matrix, where the vector (x,y,z) is mapped to (x,y,z,1) for multiplication. The Translation Matrix is then defined as: + +

+ + + + + + + +
MT
ST1
+ +

+ +where M is the 3×3 matrix (containing any rotation/scale information), T is the translation vector and ST is the transpose Vector of T. 1 is just a constant. +

+ +
+ +

jME Class

+
+ +

+ +Both Matrix3f and Matrix4f store their values as floats and are publicly available as (m00, m01, m02, …, mNN) where N is either 2 or 3. +

+ +

+Most methods are straight forward, and I will leave documentation to the Javadoc. +

+ +
+ +

Vector

+
+ +

+ +See
+ +and +

+ +
+ +

Definition

+
+ +

+ +Vectors are used to represent a multitude of things in jME, points in space, vertices in a triangle mesh, normals, etc. These classes (Vector3f in particular) are probably the most used class in jME. +

+ +

+A Vector is defined by an n-tuple of real numbers. V = <V1, V2,…, Vn>. +

+ +

+We have two Vectors (2f and 3f) meaning we have tuples of 2 float values or 3 float values. +

+ +
+ +

Operations

+
+ +
+ +

Multiplication by Scalar

+
+ +

+ +A Vector can be multiplied by a scalar value to produce a second Vector with the same proportions as the first. aV = Va = <aV1, aV2,…,aVn> +

+ +
+ +

Addition and Subtraction

+
+ +

+ +Adding or subtracting two Vectors occurs component-wise. That is the first component is added (subtracted) with the first component of the second Vector and so on. +

+ +

+P + Q = <P1+Q1, P2+Q2, …, Pn+Qn> +

+ +
+ +

Magnitude

+
+ +

+ +The magnitude defines the length of a Vector. A Vector of magnitude 1 is unit length. +

+ +

+For example, if V = (x, y, z), the magnitude is the square root of (x2 + y2 + z2). +

+ +

+A Vector can be normalized or made unit length by multiplying the Vector by (1/magnitude). +

+ +
+ +

Dot Products

+
+ +

+ +The dot product of two vectors is defined as: +P dot Q = PxQx + PyQy + PzQz +

+ +

+Using the dot product allows us to determine how closely two Vectors are pointing to the same point. If the dot product is negative they are facing in relatively opposite directions, while postive tells us they are pointing in the relative same direction. +

+ +

+If the dot product is 0 then the two Vectors are orthogonal or 90 degrees off. +

+ +
+ +

Cross Product

+
+ +

+ +The Cross Product of two Vectors returns a third Vector that is prependicular to the two Vectors. This is very useful for calculating surface normals. +

+ +

+P X Q = <PyQz - PzQy, PzQx - PxQz, PxQy - PyQx> +

+ +
+ +

jME Class

+
+ +

+ +Vector3f and Vector2f store their values (x, y, z) and (x, y) respectively as floats. Most methods are straight forward, and I will leave documentation to the Javadoc. +

+ +
+ +

Quaternion

+
+ +

+ +See +

+ +
+ +

Definition

+
+ +

+ +Quaternions define a subset of a hypercomplex number system. Quaternions are defined by (i2 = j2 = k2 = ijk = -1). jME makes use of Quaternions because they allow for compact representations of rotations, or correspondingly, orientations, in 3D space. With only four float values, we can represent an object's orientation, where a rotation matrix would require nine. They also require fewer arithmetic operations for concatenation. +

+ +

+Additional benefits of the Quaternion is reducing the chance of Gimbal Lock and allowing for easily interpolation between two rotations (spherical linear interpolation or slerp). +

+ +

+While Quaternions are quite difficult to fully understand, there are an exceeding number of convenience methods to allow you to use them without having to understand the math behind it. Basically, these methods involve nothing more than setting the Quaternion's x,y,z,w values using other means of representing rotations. The Quaternion is then contained in Spatial as its local rotation component. +

+ +

+Quaternion q has the form +

+ +

+q = <w,x,y,z> = w + xi + yj + zk +

+ +

+or alternatively, it can be written as: +

+ +

+q = s + v, where s represents the scalar part corresponding to the w-component of q, and v represents the vector part of the (x, y, z) components of q. +

+ +

+Multiplication of Quaternions uses the distributive law and adheres to the following rules with multiplying the imaginary components (i, j, k): +

+ +

+i2 = j2 = k2 = -1
+ +ij = -ji = k
+ +jk = -kj = i
+ +ki = -ik = j +

+ +

+However, Quaternion multiplication is not commutative, so we have to pay attention to order. +

+ +

+q1q2 = s1s2 - v1 dot v2 + s1v2 + s2v1 + v1 X v2 +

+ +

+Quaternions also have conjugates where the conjugate of q is (s - v) +

+ +

+These basic operations allow us to convert various rotation representations to Quaternions. +

+ +
+ +

Angle Axis

+
+ +

+ +You might wish to represent your rotations as Angle Axis pairs. That is, you define a axis of rotation and the angle with which to rotate about this axis. Quaternion defines a method fromAngleAxis (and fromAngleNormalAxis) to create a Quaternion from this pair. This is acutally used quite a bit in jME demos to continually rotate objects. You can also obtain a Angle Axis rotation from an existing Quaternion using toAngleAxis. +

+ +
+ +

Example - Rotate a Spatial Using fromAngleAxis

+
+
//rotate about the Y-Axis by approximately 1 pi
+Vector3f axis = Vector3f.UNIT_Y; 
+// UNIT_Y equals (0,1,0) and does not require to create a new object
+float angle = 3.14f;
+s.getLocalRotation().fromAngleAxis(angle, axis);
+
+ +

Three Angles

+
+ +

+ +You can also represent a rotation by defining three angles. The angles represent the rotation about the individual axes. Passing in a three-element array of floats defines the angles where the first element is X, second Y and third is Z. The method provided by Quaternion is fromAngles and can also fill an array using toAngles +

+ +
+ +

Example - Rotate a Spatial Using fromAngles

+
+
//rotate 1 radian on the x, 3 on the y and 0 on z
+float[] angles = {1, 3, 0};
+s.getLocalRotation().fromAngles(angles);
+
+ +

Three Axes

+
+ +

+ +If you have three axes that define your rotation, where the axes define the left axis, up axis and directional axis respectively) you can make use of fromAxes to generate the Quaternion. It should be noted that this will generate a new Matrix object that is then garbage collected, thus, this method should not be used if it will be called many times. Again, toAxes will populate a Vector3f array. +

+ +
+ +

Example - Rotate a Spatial Using fromAxes

+
+
//rotate a spatial to face up ~45 degrees
+Vector3f[] axes = new Vector3f[3];
+axes[0] = new Vector3f(-1, 0, 0); //left
+axes[1] = new Vector3f(0, 0.5f, 0.5f); //up
+axes[2] = new Vector3f(0, 0.5f, 0.5f); //dir
+ 
+s.getLocalRotation().fromAxes(axes);
+
+ +

Rotation Matrix

+
+ +

+ +Commonly you might find yourself with a Matrix defining a rotation. In fact, it's very common to contain a rotation in a Matrix create a Quaternion, rotate the Quaternion, and then get the Matrix back. Quaternion contains a fromRotationMatrix method that will create the appropriate Quaternion based on the give Matrix. The toRotationMatrix will populate a given Matrix. +

+ +
+ +

Example - Rotate a Spatial Using a Rotation Matrix

+
+
 
+Matrix3f mat = new Matrix3f();
+mat.setColumn(0, new Vector3f(1,0,0));
+mat.setColumn(1, new Vector3f(0,-1,0));
+mat.setColumn(2, new Vector3f(0,0,1));
+ 
+s.getLocalRotation().fromRotationMatrix(mat);
+

+As you can see there are many ways to build a Quaternion. This allows you to work with rotations in a way that is conceptually easier to picture, but still build Quaternions for internal representation. +

+ +
+ +

Slerp

+
+ +

+ +One of the biggest advantages to using Quaternions is allowing interpolation between two rotations. That is, if you have an initial Quaternion representing the original orientation of an object, and you have a final Quaternion representing the orientation you want the object to face, you can do this very smoothly with slerp. Simply supply the time, where time is [0, 1] and 0 is the initial rotation and 1 is the final rotation. +

+ +
+ +

Example - Use Slerp to Rotate Between two Quaternions

+
+
Quaternion q1;
+Quaternion q2;
+ 
+//the rotation half-way between these two
+Quaternion q3 = q1.slerp(q2, 0.5f);
+
+ +

Multiplication

+
+ +

+ +You can concatenate (add) rotations: This means you turn the object first around one axis, then around the other, in one step. +

+
Quaternion myRotation = pitch90.mult(roll45); /* pitch and roll */
+

+To rotate a Vector3f around its origin by the Quaternion amount, use the multLocal method of the Quaternion: +

+
Quaternion myRotation = pitch90;
+Vector3f myVector = new Vector3f(0,0,-1);
+myRotation.multLocal(myVector);
+
+ +

Utility Classes

+
+ +

+ +Along with the base Math classes, jME provides a number of Math classes to make development easier (and, hopefully, faster). Most of these classes find uses throughout the jME system internally. They can also prove beneficial to users as well. +

+ +
+ +

Fast Math

+
+ +

+ +See +

+ +
+ +

Definition

+
+ +

+ +FastMath provides a number of convience methods, and where possible faster versions (although this can be at the sake of accuracy). +

+ +
+ +

Usage

+
+ +

+ +FastMath provides a number of constants that can help with general math equations. One important attribute is USE_FAST_TRIG if you set this to true, a look-up table will be used for trig functions rather than Java's standard Math library. This provides significant speed increases, but might suffer from accuracy so care should be taken. +

+ +

+There are five major categories of functions that FastMath provides. +

+ +
+ +

Trig Functions

+
+
    +
  • cos and acos - provide and values (make use of the look-up table if USE_FAST_TRIG is true)
    +
  • +
  • sin and asin - provide and values (make use of the look-up table if USE_FAST_TRIG is true)
    +
  • +
  • tan and atan - provide and values
    +
  • +
+ +
+ +

Numerical Methods

+
+
    +
  • ceil - provides the ceiling (smallest value that is greater than or equal to a given value and an integer)of a value.
    +
  • +
  • floor - provides the floor (largest value that is less than or equal to a given value and an integer) of a value.
    +
  • +
  • exp - provides the (e) raised to the provided value.
    +
  • +
  • sqr - provides the square of a value (i.e. value * value).
    +
  • +
  • pow - provides the first given number raised to the second.
    +
  • +
  • isPowerOfTwo - provides a boolean if a value is a power of two or not (e.g. 32, 64, 4).
    +
  • +
  • abs - provides the of a given number.
    +
  • +
  • sign - provides the sign of a value (1 if positive, -1 if negative, 0 if 0).
    +
  • +
  • log - provides the of a value.
    +
  • +
  • sqrt - provides the of a value.
    +
  • +
  • invSqrt - provides the inverse of a value (1 / sqrt(value).
    +
  • +
+ +
+ +

Linear Algebra

+
+
    +
  • LERP - calculate the of two points given a time between 0 and 1.
    +
  • +
  • determinant - calculates the of a 4×4 matrix.
    +
  • +
+ +
+ +

Geometric Functions

+
+
    +
  • counterClockwise - given three points (defining a triangle), the winding is determined. 1 if counter-clockwise, -1 if clockwise and 0 if the points define a line.
    +
  • +
  • pointInsideTriangle - calculates if a point is inside a triangle.
    +
  • +
  • sphericalToCartesian - converts a point from to .
    +
  • +
  • cartesianToSpherical - converts a point from to .
    +
  • +
+ +
+ +

Misc.

+
+
    +
  • newRandomFloat - obtains a random float.
    +
  • +
+ +
+ +

Line

+
+ +

+ +See +

+ +
+ +

Definition

+
+ +

+ +A line is a straight one-dimensional figure having no thickness and extending infinitely in both directions. A line is defined by two points A and B with the line passing through both. +

+ +
+ +

Usage

+
+ +

+ +jME defines a Line class that is defined by an origin and direction. In reality, this Line class is typically used as a line segment. Where the line is finite and contained between these two points. +

+ +

+random provides a means of generate a random point that falls on the line between the origin and direction points. +

+ +
+ +

Example 1 - Find a Random Point on a Line

+
+
Line(new Vector3f(0,1,0), new Vector3f(3,2,1));
+Vector3f randomPoint = l.random();
+
+ +

Plane

+
+ +

+ +See +

+ +
+ +

Definition

+
+ +

+ +A plane is defined by the equation N . (X - X0) = 0 where N = (a, b, c) and passes through the point X0 = (x0, y0, z0). X defines another point on this plane (x, y, z). +

+ +

+N . (X - X0) = 0 can be described as (N . X) + (N . -X0) = 0 +

+ +

+or +

+ +

+(ax + by + cz) + (-ax0-by0-cz0) = 0 +

+ +

+where (-ax0-by0-cz0) = d +

+ +

+Where d is the negative value of a point in the plane times the unit vector describing the orientation of the plane. +

+ +

+This gives us the general equation: (ax + by + cz + d = 0) +

+ +
+ +

Usage in jME

+
+ +

+ +jME defines the Plane as ax + by + cz = -d. Therefore, during creation of the plane, the normal of the plane (a,b,c) and the constant d is supplied. +

+ +

+The most common usage of Plane is Camera frustum planes. Therefore, the primary purpose of Plane is to determine if a point is on the positive side, negative side, or intersecting a plane. +

+ +

+Plane defines the constants: + +

+
    +
  • NEGATIVE_SIDE - represents a point on the opposite side to which the normal points.
    +
  • +
  • NO_SIDE - represents a point that lays on the plane itself.
    +
  • +
  • POSITIVE_SIDE - represents a point on the side to which the normal points.
    +
  • +
+ +

+ +These values are returned on a call to whichSide. +

+ +
+ +

Example 1 - Determining if a Point is On the Positive Side of a Plane

+
+
Vector3f normal = new Vector3f(0,1,0);
+float constant = new Vector3f(1,1,1).dot(normal);
+Plane testPlane = new Plane(normal, constant);
+ 
+int side = testPlane.whichSide(new Vector3f(2,1,0);
+ 
+if(side == Plane.NO_SIDE) {
+   System.out.println("This point lies on the plane");
+}
+
+ +

Example 2 - For the Layperson

+
+ +

+ +Using the standard constructor Plane(Vector3f normal, float constant), here is what you need to do to create a plane, and then use it to check which side of the plane a point is on. +

+
package test;
+ 
+import java.util.logging.Logger;
+ 
+import com.jme.math.*;
+ 
+/**
+ *@author Nick Wiggill
+ */
+ 
+public class TestPlanes
+{
+  public static final Logger logger = Logger.getLogger(LevelGraphBuilder.class.getName());
+ 
+  public static void main(Exception
+  {
+    //***Outline.
+    //This example shows how to construct a plane representation using
+    //com.jme.math.Plane.
+    //We will create a very simple, easily-imagined 3D plane. It will
+    //be perpendicular to the x axis (it's facing). It's "centre" (if
+    //such a thing exists in an infinite plane) will be positioned 1
+    //unit along the positive x axis.
+ 
+    //***Step 1.
+    //The vector that represents the normal to the plane, in 3D space.
+    //Imagine a vector coming out of the origin in this direction.
+    //There is no displacement yet (see Step 2, below).
+    Vector3f normal = new Vector3f(5f,0,0);
+ 
+    //***Step 2.
+    //This is our displacement vector. The plane remains facing in the
+    //direction we've specified using the normal above, but now we are
+    //are actually giving it a position other than the origin.
+    //We will use this displacement to define the variable "constant"
+    //needed to construct the plane. (see step 3)
+    Vector3f displacement = Vector3f.UNIT_X;
+    //or
+    //Vector3f displacement = new Vector3f(1f, 0, 0);
+ 
+    //***Step 3.
+    //Here we generate the constant needed to define any plane. This
+    //is semi-arcane, don't let it worry you. All you need to
+    //do is use this same formula every time.
+    float constant = displacement.dot(normal);
+ 
+    //***Step 4.
+    //Finally, construct the plane using the data you have assembled.
+    Plane plane = new Plane(normal, constant);
+ 
+    //***Some tests.
+    logger.info("Plane info: "+plane.toString()); //trace our plane's information
+ 
+    Vector3f p1  = new Vector3f(1.1f,0,0); //beyond the plane (further from origin than plane)
+    Vector3f p2  = new Vector3f(0.9f,0,0); //before the plane (closer to origin than plane)
+    Vector3f p3  = new Vector3f(1f,0,0); //on the plane
+ 
+    logger.info("p1 position relative to plane is "+plane.whichSide(p1)); //outputs NEGATIVE
+    logger.info("p2 position relative to plane is "+plane.whichSide(p2)); //outputs POSITIVE
+    logger.info("p3 position relative to plane is "+plane.whichSide(p3)); //outputs NONE
+  }
+}
+
+ +

Ray

+
+ +

+ +See +

+ +
+ +

Definition

+
+ +

+ +Ray defines a line that starts at a point A and continues in a direction through B into infinity. +

+ +

+This Ray is used extensively in jME for Picking. A Ray is cast from a point in screen space into the scene. Intersections are found and returned. To create a ray supply the object with two points, where the first point is the origin. +

+ +
+ +

Example 1 - Create a Ray That Represents Where the Camera is Looking

+
+
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
+
+ +

Rectangle

+
+ +

+ +See +

+ +
+ +

Definition

+
+ +

+ +Rectangle defines a finite plane within three dimensional space that is specified via three points (A, B, C). These three points define a triangle with the forth point defining the rectangle ( (B + C) - A ). +

+ +
+ +

jME Usage

+
+ +

+ +Rectangle is a straight forward data class that simply maintains values that defines a Rectangle in 3D space. One interesting use is the random method that will create a random point on the Rectangle. The Particle System makes use of this to define an area that generates Particles. +

+ +
+ +

Example 1 : Define a Rectangle and Get a Point From It

+
+
Vector3f v1 = new Vector3f(1,0,0);
+Vector3f v2 = new Vector3f(1,1,0);
+Vector3f v3 = new Vector3f(0,1,0);
+Rectangle(v1, v2, v3);
+Vector3f point = r.random();
+
+ +

Triangle

+
+ +

+ +See +

+ +
+ +

Definition

+
+ +

+ +A triangle is a 3-sided polygon. Every triangle has three sides and three angles, some of which may be the same. If the triangle is a right triangle (one angle being 90 degrees), the side opposite the 90 degree angle is the hypotenuse, while the other two sides are the legs. All triangles are and . +

+ +
+ +

Usage

+
+ +

+ +jME's Triangle class is a simple data class. It contains three Vector3f objects that represent the three points of the triangle. These can be retrieved via the get method. The get method, obtains the point based on the index provided. Similarly, the values can be set via the set method. +

+ +
+ +

Example 1 - Creating a Triangle

+
+
//the three points that make up the triangle
+Vector3f p1 = new Vector3f(0,1,0);
+Vector3f p2 = new Vector3f(1,1,0);
+Vector3f p3 = new Vector3f(0,1,1);
+Triangle t = new Triangle(p1, p2, p3);
+
+ +

Tips and Tricks

+
+ +
+ +

How do I get height/width of a spatial?

+
+ +

+ +Cast the spatial to com.jme3.bounding.BoundingBox to be able to use getExtent(). + +

+
Vector3f extent = ((BoundingBox) spatial.getWorldBound()).getExtent(new Vector3f());
+float x = ( (BoundingBox)spatial.getWorldBound()).getXExtent();
+float y = ( (BoundingBox)spatial.getWorldBound()).getYExtent();
+float z = ( (BoundingBox)spatial.getWorldBound()).getZExtent();
+
+ +

How do I position the center of a Geomtry?

+
+
geo.center().move(pos);
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/terminology.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/terminology.html new file mode 100644 index 000000000..3825b9973 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/terminology.html @@ -0,0 +1,577 @@ + +

3D Game Development Terminology

+
+ +

+ +Before you start, make certain you are familiar with the following concepts and terminology. +

+ +
+ +

3D Graphics and Audio

+
+ +

+ +OpenGL is the Open Graphics Library, a platform-independent specification for rendering 2D/3D computer graphics. For Java, there are two implementations of OpenGL-based renderers: +

+
    +
  1. Lightweight Java Game Library (LWJGL)
    +
  2. +
  3. Java OpenGL (JOGL)
    +
  4. +
+ +

+ +OpenAL is the Open Audio Library, a platform-independent 3D audio API. +

+ +
+ +

Context, Display, Renderer

+
+ +

+ +The jME Context makes settings, renderer, timer, input and event listeners, display system, accessible to a JME game. +

+
    +
  • The jME Display System is what draws the custom JME window (instead of Java Swing).
    +
  • +
  • The input system is what lets you respond to user input via mouse, keyboard, and joystick.
    +
  • +
  • The renderer is what does all the work of calculating how to draw the 3D scenegraph to the 2D screen.
    +
      +
    • The Shader is a programmable part of the rendering pipeline. The jME3 game engine uses it to offer advanced customizable materials.
      +
    • +
    +
  • +
+ +
+ +

Geometry

+
+ +
+ +

Coordinates

+
+ +

+ +Coordinates represent a location in a coordinate system, relative to the origin (0,0,0). m. In 3D space, you need to specify three coordinate values to locate a point: x,y,z. +As opposed to a vector (which looks similar), a coordinate does not have a “direction”. +

+ +

+ +

+ +
+ +

The Origin

+
+ +

+ +The origin is the central point in the 3D world. It's at the coordinates (0,0,0). +

+ +

+Code sample: Vector3f origin = new Vector3f( Vector3f.ZERO ); +

+ +
+ +

Vectors

+
+ +

+ +A vector has a length and a direction. It is used like an arrow pointing at a point in 3D space. A vector starts at the origin (0,0,0), and ends at the target coordinate (x,y,z). Backwards directions are expressed with negative values. +

+ +

+Code sample: Vector3f v = new Vector3f( 17 , -4 , 0 ); +

+ +
+ +

Unit Vectors

+
+ +

+ +A unit vector is a basic vector with a length of 1 world unit. Since its length is fixed (and it thus can only point at one location anyway), the only interesting thing about this vector is its direction. +

+
    +
  • Vector3f.UNIT_X = ( 1, 0, 0) = right
    +
  • +
  • Vector3f.UNIT_Y = ( 0, 1, 0) = up
    +
  • +
  • Vector3f.UNIT_Z = ( 0, 0, 1) = forwards
    +
  • +
  • Vector3f.UNIT_XYZ = 1 wu diagonal right-up-forewards
    +
  • +
+ +
+ +

Normalized Vectors

+
+ +

+ +A normalized vector is a custom unit vector. A normalized vector is not the same as a (surface) normal vector. +

+ +

+When you normalize a vector, it still has the same direction, but you lose the information where the vector originally pointed. +

+ +

+For instance, you normalize vectors before calculating angles. +

+ +
+ +

Surface Normals

+
+ +

+ +A surface normal is a vector that is perpendicular to a plane. +You calculate the Surface Normal by calculating the cross product. +

+ +
+ +

Cross Product

+
+ +

+ +The cross product is a calculation that you use to find a perpendicular vector (an orthogonal, a “right angle” at 90°). +

+ +

+In 3D space, speaking of an orthogonal only makes sense with respect to a plane. You need two vectors to uniquely define a plane. The cross product of the two vectors, v1 × v2, is a new vector that is perpendicular to this plane. A vector perpendicular to a plane is a called Surface Normal. +

+ +

+Example: The x unit vector and the y unit vector together define the x/y plane. The vector perpendicular to them is the z axis. JME can calculate that this equation is true:
+ +( Vector3f.UNIT_X.cross( Vector3f.UNIT_Y ) ).equals( Vector3f.UNIT_Z ) == true +

+ +
+ +

Polygon, Mesh, Vertex

+
+ +

+ + +

+ +

+Most visible objects in a 3D scene are made up of polygon meshes – characters, terrains, buildings, etc. A mesh is a grid-like structure that represents a complex shape. The advantage of a mesh is that it is mathematically simple enough to render in real time, and detailed enough to be recognizable. +

+ +

+Every shape is reduced to a number of connected polygons, usually triangles; even round surfaces such as spheres are reduced to a grid of triangles. The polygons' corner points are called vertices. Every vertex is positioned at a coordinate, all vertices together describe the outline of the shape. +

+ +

+You create 3D meshes in tools called mesh editors, e.g in Blender. +

+ +

+Learn more about 3D maths here. +

+ +
+ +

Materials: Color, Lighting/Shading

+
+ +

+ +What we call “color” is merely part of an object's light reflection. The onlooker's brain uses shading and reflecting properties to infer an object's shape and material. Factors like these make all the difference between chalk vs milk, skin vs paper, water vs plastic, etc! () +

+ +
+ +

Color

+
+ +
+ +

Ambient color

+
+
    +
  • The uniform base color of the mesh – what it looks like when not influenced by any light source.
    +
  • +
  • Usually similar to the Diffuse color.
    +
  • +
  • This is the minimum color you need for an object to be visible.
    +
  • +
+ +
+ +

Diffuse color

+
+
    +
  • The base color of the mesh plus shattered light and shadows that are caused by a light source.
    +
  • +
  • Usually similar to the Ambient color.
    +
  • +
+ +
+ +

Light Sources

+
+ +
+ +

Emissive color

+
+
    +
  • The color of light emitted by a light source or glowing material.
    +
  • +
  • Only glowing materials such as lights have an emissive color, normal objects don't have this property.
    +
  • +
  • Often white (sun light).
    +
  • +
+ +
+ +

Reflections

+
+ +
+ +

Shininess

+
+
    +
  • Degree of shininess of a surface (0-128).
    +
  • +
  • Shiny objects have small, clearly outlined specular highlights. (E.g. glass, water, silver)
    +
  • +
  • Normal objects have wide, blurry specular highlights. (E.g. metal, plastic, stone, polished materials)
    +
  • +
  • Uneven objects are not shiny and have no specular highlights. (E.g. cloth, paper, wood, snow)
    +
  • +
+ +
+ +

Specular Color

+
+
    +
  • If the material is shiny, then the Specular Color is the color of the reflected highlights.
    +
  • +
  • Usually the same as the emissive color of the light source (e.g. white).
    +
  • +
  • You can use colors to achieve special specular effects, such as metallic or iridescent reflections.
    +
  • +
  • Non-shiny objects don't use a specular color.
    +
  • +
+ +

+ + +

+ +
+ +

Materials: Textures

+
+ +

+ +Textures are part of Materials. In the simplest case, an object could have just one texture, the Color Map, loaded from one image file. When you think back of old computer games you'll remember this looks quite plain. +

+ +

+The more information you (the game designer) provide additionally to the Color Map, the higher the degree of detail and realism. Whether you want photo-realistic rendering or “toon” rendering (Cel Shading), everything depends on the quality of your materials and texture maps. Modern 3D graphics use several layers of information to describe one material, each layer is a Texture Map. +

+ +
+ +

Texture Maps

+
+ +
+ +

Color Map

+
+ +

+ + +

+
    +
  • A simple image file (or a procedural texture).
    +
  • +
  • The image can have alpha channels for transparency.
    +
  • +
  • A color map is the minimum texture you need. All other texture maps are optional improvements.
    +
  • +
+ +
+ +

Diffuse Map

+
+ +

+ + +

+
    +
  • The Diffuse Map specifies the intensity of color.
    +
  • +
  • Its basically the same as a Color Map but its called Diffuse Map in a lighting environment, as it defines the color the object “diffuses”.
    +
  • +
+ +
+ +

Bump Map

+
+ +

+ +Bump maps are used to describe detailed shapes that would be too hard or simply too inefficient to sculpt in a mesh editor. You use Normal Maps to model cracks in walls, rust, skin texture, or a canvas weave. You use Height Maps to model whole terrains with valleys and mountains. +

+ +

+ +

+ +
+ +

Height Map

+
+
    +
  • A height map is a grayscale image looking similar to a terrain map used in topography. Brighter grays represent higher areas and darker grays lower areas.
    +
  • +
  • A heightmap can represent 256 height levels and is mostly used to roughly outline terrains.
    +
  • +
  • You can draw a heightmap by hand in any image editor.
    +
  • +
+ +
+ +

Normal Map

+
+ +

+ + +

+
    +
  • A well-done Normal Map makes a shape more detailed–without the need to add costly polygons to the mesh. It contains shading information that makes the object appear smoother and more fine-grained.
    +
  • +
  • The Normal Map is displayed looking like a false-color version of the Color Map–but it is never used for coloring, instead, each RGB value encodes transformation data. This displacement data is represented by Surface Normals of the slopes, hence the name.
    +
  • +
  • It's hard to draw normal maps by hand. Generally you use software tools to calculate them off 3D models.
    +
  • +
+ +
+ +

Specular Map

+
+ +

+ + +

+
    +
  • A Specular Map further improves the realism of an object's surface: It contains extra information about shininess and makes the shape appear more realistically illumated.
    +
  • +
  • Start out with a gray value that corresponds to the average shininess/dullness of this material. Then add ligher grays for smoother, shinier, more reflective areas; and darker grays for duller, rougher, worn-out areas. The resulting image file looks similar to a grayscale version of the Color Map.
    +
  • +
  • You can use colors in a specular map to create certain reflective effects (iridiscence, metallic).
    +
  • +
+ +
+ +

Seamless Tiled Textures

+
+ +

+ + +

+ +

+This is a very simple, commonly used type of texture. When texturing a wide area (e.g. walls, floors), you don't create one huge texture, instead you tile a small texture repeatedly to fill the area. +

+ +

+A seamless texture is an image file that has been designed so that it can be used as tiles: The right edge matches the left edge, and the top edge matches the bottom edge. The onlooker cannot easily tell where one starts and the next one ends, thus creating an illusion of a huge texture. The downside is that the tiling becomes painfully obvious when the area is viewed from a distance. Also you cannot use it on more complex models such as characters. +

+ +
+ +

UV Maps

+
+ +

+ + +

+ +

+Creating a texture for a cube is easy – but what about a character with a face and extremities? For more complex objects, you design the texture in the same ways as a sewing pattern: One image file contains the outline of the front, back, and side of the object, next to one another. Specific areas of the flat texture (UV coordinates) map onto certain areas of your 3D model (XYZ coordinates), hence the name UV map. +

+ +

+Getting the seams and mappings right is crucial: You will have to use a graphic tool like Blender to create UV Maps. It's worth the while to learn this, UV mapped models look a lot more professional. +

+ +
+ +

Environment Maps

+
+ +

+ + +Environment Maps are used to create the impression of reflections and refractions. You create a Cube Map to represent your environment, similar to a skybox. (Sphere Maps are possible, but often look too distorted.) You give the Cube Map a set of images showing a “360° view” of the completed scene. The renderer uses this as base to texture the reflective surface. +

+ +

+Of course these reflections are static and not “real”, e.g. the player will not see his avatar's face reflected, etc… But they cause the desired “glass/mirror/water” effect, and are fast enough to render in real usecases, it's better than nothing. +

+ +
+ +

MIP Map Texture

+
+ +

+ +You provide the texture in two or three resolutions to be stored in one file (MIP = “multum in parvo” = “many in one”). Depending on how close (or far) the camera is, the engine automatically renders a more (or less) detailed texture for the object. Thus objects look smooth from close up, but don't waste resources with unspottable details when far away. Good for everything, but requires more time to create and more space to store textures. +

+ +
+ +

Procedural Textures

+
+ +

+ +A procedural texture is generated from repeating one small image, plus some pseudo-random, gradient variations (Perlin noise). Procedural textures look more natural than static rectangular textures, for instance, they look less distorted on spheres. On big meshes, their repetitiveness is much less noticable than tiled seamless textures. Procedural textures are ideal for irregular large-area textures like grass, soil, rock, rust, and walls. See also: +

+ +

+ +

+ +

+See also: , +

+ +
+ +

Animation

+
+ +

+ +In 3D games, Skeletal Animation is used for animated characters, but in principle the skeleton approach can be extended to any 3D mesh (for example, an opening crate's hinge can be considered a joint). +

+ +

+Unless you animate a 3D cartoon, realism of animated characters is generally a problem: Movement can look alien-like mechanical or broken, the character appears hollow, or as if floating. Professional game designers invest a lot of effort to make characters animate in a natural way (including motion capturing). +

+ +
+ +

Rigging and Skinning

+
+ +

+ + +

+ +

+An animated character has an armature: An internal skeleton (Bones) and an external surface (Skin). The Skin is the visible outside of the character and it includes clothing. The Bones are not visible and are used to interpolate (calculate) the morphing steps of the skin. +

+ +

+JME3, the game engine, only loads and plays your recorded animations. You must use a tool (such as Blender) to set up (rig, skin, and animate) a character. + +

+
    +
  1. Rigging: The Construction of a character's skeleton.
    +
      +
    • Create as few Bones as possible to decrease complexity.
      +
    • +
    • Bones are connected in a parent-child hierarchy: Moving one bone can pull another bone with it (e.g. arm pulls hand).
      +
    • +
    • Bones follow a certain naming scheme so the 3D engines know what's what.
      +
    • +
    +
  2. +
  3. Skinning: The association of individual bones with the corresponding skin sections.
    +
      +
    • Each Bone is connected to a part of the Skin. Animating the (invisible) Bone pulls the (visible) Skin with it.
      + E.g. the thigh Bone is connected to the upper leg Skin.
      +
    • +
    • One part of the Skin can be affected by more than one bone (e.g. knee, elbow).
      +
    • +
    • The connection between bones and skin sections is gradual: You assign weights how much each skin polygon is affected by any bone's motion.
      + E.g. when the thigh bone moves, the leg is fully affected, the hips joints less so, and the head not at all.
      +
    • +
    +
  4. +
  5. Keyframe Animation: A keyframe is one recorded snapshot of a motion sequence.
    +
      +
    • A series of keyframes makes up one animation.
      +
    • +
    • Each model can have several animations. Each animation has a name to identify it (e.g. “walk”, “attack”, “jump”).
      +
    • +
    • You specify in your game code which keyframe animation to load, and when to play it.
      +
    • +
    +
  6. +
+ +
+ +

Kinematics

+
+
    +
  • Forward kinematics: “Given the angles of all the character's joints, what is the position of the character's hand?”
    +
  • +
  • Inverse kinematics: “Given the position of the character's hand, what are the angles of all the character's joints?”
    +
  • +
+ +
+ +

Controller and Channel

+
+ +

+ +In the JME3 application, you register animated models to the Animation Controller. The controller object gives you access to the available animation sequences. The controller has several channels, each channels can run one animation sequence at a time. To run several sequences, you create several channels, and run them in parallel. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/the_scene_graph.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/the_scene_graph.html new file mode 100644 index 000000000..ce9d9ab37 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/the_scene_graph.html @@ -0,0 +1,132 @@ + +

The Scene Graph and Other jME3 Terminology

+
+ +

+ +Before you start making games, make sure you understand general 3D Gaming terminology. +

+ +

+Second, if you are a beginner, we recommend our Scene Graph for Dummies presentation for a visual introduction to the concept of a scene graph. +

+ +

+Then continue learning about jME3 concepts here. +

+ +
+ +

Coordinate System

+
+ +

+ + +

+ +

+The jMonkeyEngine uses a right-handed coordinate system, just as OpenGL does. +

+ +

+The coordinate system consists of: + +

+
    +
  • The origin, a single point in space.
    +
      +
    • This point is always at coordinate (0,0,0)
      +
    • +
    +
  • +
  • Three coordinate axes that are mutually perpendicular, and meet in the origin.
    +
      +
    • The X axis is “right/left”
      +
    • +
    • The Y axis is “up/down”
      +
    • +
    • The Z axis is “towards you/away from you”
      +
    • +
    +
  • +
+ +

+ +Every point in 3D space is defined by its (x,y,z) coordinates. The data type for vectors is com.jme3.math.Vector3f. +

+ +

+For your orientation, the default camera's location is (0.0f,0.0f,10.0f), and it is looking in the direction described by the unit vector (0.0f, 0.0f, -1.0f). This means your point of view is on the positive side of the Z axis, looking towards the origin, down the Z axis. +

+ +

+The unit of meassurement is world unit (wu). Typically, 1 wu is considered to be one meter. All scales, vectors and points are relative to this coordinate system. +

+ +
+ +

Scene Graph and RootNode

+
+ +

+ +The scene graph represents your 3D world. Objects in the jME3 scene graph are called Spatials. Everything attached to the rootNode is part of the scene graph. Attaching a Spatial to the rootNode (or other nodes) adds the Spatial to the scene; detaching removes it. +

+ +

+ +

+ +
+ +

Spatials: Node vs Geometry

+
+ +

+ +A Spatial can be transformed, loaded and saved. There are two types of Spatials, Nodes and Geometries. + +

+ + + + + + + + + + + + + + + + + + + + + + +
Spatial
Purpose: A Spatial is an abstract data structure that stores transformations (translation, rotation, scale).
Geometry Node
Visibility: A visible 3-D object. An invisible “handle” for a group of objects.
Purpose: Represents the “look” of an object: Shape, color, texture, opacity/transparency. Groups Geometries and other Nodes together: You transform a Node to affect all attached Nodes.
Content: Transformations, mesh, material. Transformations. No mesh, no material.
Examples: A box, a sphere, player, a building, a piece of terrain, a vehicle, missiles, NPCs, etc… The rootNode, the guiNode, an audio node, a custom grouping node, etc.
+ +
+ +

How to Use This Knowledge?

+
+ +

+ +Before you start creating your game, you should have completed the Hello World tutorial series. It shows how to load and create Spatials, how to lay out a scene by attaching and transforming Spatials, and how to add interaction and effects to a game. +

+ +

+The intermediate and advanced documentation gives you more details on how to put all the parts together to create an awesome Java 3D game! + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/webstart.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/webstart.html new file mode 100644 index 000000000..3f5729c81 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/webstart.html @@ -0,0 +1,84 @@ + +

+When running under WebStart, jMonkeyEngine may not have permission to extract the native libraries to the current directory. To avoid this problem, you can instruct WebStart to load the native libraries itself using the JNLP file, and then instruct jME3 not to try to do so itself. +

+ +

Simple way

+
+ +

+ +You can import the LWJGL JNLP extension directly into your extension, however be aware that your application will break whenever they update their jars. Simply add this line to your JNLP: +

+
<extension name="lwjgl" href="http://lwjgl.org/webstart/2.7.1/extension.jnlp" />
+
+ +

Reliable way

+
+ +
+ +
Native jars
+
+ +

+ +You can download the LWJGL native jars from their site, or to ensure you're using the exact same version as bundled with your jME3 release, make your own: +

+
+mkdir tmp
+cd tmp
+jar xfv ../jME3-lwjgl-natives.jar
+cd native
+for i in *; do
+  cd $i
+  jar cfv ../../native_$i.jar .
+  cd ..
+done
+
+ +

+Remember to sign all the jar files and move them into the right place from the tmp directory. +

+ +
+ +
JNLP file
+
+ +

+ +Add the following to your JNLP file: +

+
  <resources os="Windows">
+    <j2se version="1.4+"/>
+    <nativelib href="native_windows.jar"/>
+  </resources>
+  <resources os="Linux">
+    <j2se version="1.4+"/>
+    <nativelib href="native_linux.jar"/>
+  </resources>
+  <resources os="Mac OS X">
+    <j2se version="1.4+"/>
+    <nativelib href="native_macosx.jar"/>
+  </resources>
+  <resources os="SunOS" arch="x86">
+    <j2se version="1.4+"/>
+    <nativelib href="native_solaris.jar"/>
+  </resources>
+
+ +
Set low-permissions mode
+
+ +

+ +In your main() method, if running under WebStart, tell jME3 it is running in a low-permission environment so that it doesn't try to load the natives itself: +

+
  public static void main(String[] args)
+  {
+      if (System.getProperty("javawebstart.version") != null) {
+        JmeSystem.setLowPermissions(true);
+      }
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/application_deployment.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/application_deployment.html new file mode 100644 index 000000000..99ef1b3c1 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/application_deployment.html @@ -0,0 +1,312 @@ + +

jMonkeyPlatform: Application Deployment

+
+ +

+ +After you have written and tested your game, you want to brand it and distribute it to your users. If you use the build script provided by the jMonkeyPlatform's BaseGame, you have the following deployment options: + +

+
    +
  • Desktop application (.JAR)
    +
  • +
  • WebStart from URL (.JNLP + .JAR)
    +
  • +
  • Applet in browser page (.JNLP + .JAR)
    +
  • +
  • Android Mobile phone (work in progress)
    +
  • +
+ +
+ +

Requirements

+
+ +

+ +Since JAR files are platform independent, your customers can play your jMonkeyEngine application on Windows, Mac OS, or Linux. The only requirement is that the user has the free Java 5 or 6 Runtime (or browser plugin) installed. For more information see . +

+ +
+ +

Branding

+
+
    +
  1. Open your game project in the jMonkeyPlatform's Projects window.
    +
  2. +
  3. Right-click the project and open the Properties
    +
  4. +
  5. Open the properties → Application section. Here you do your branding:
    +
      +
    1. Title: the game's name
      +
    2. +
    3. Vendor: your name
      +
    4. +
    5. Description: why your game is the coolest ever ;)
      +
    6. +
    7. Homepage: Your web URL
      +
    8. +
    9. Splashscreen: Browse to a picture that will be shown while the game loads.
      +
    10. +
    +
  6. +
  7. Click OK.
    +
  8. +
  9. Clean and Build.
    +
  10. +
+ +
+ +

Creating the Distributable

+
+ +

+ +When you run the build script provided by the jMonkeyPlatform, it automatically compiles your classes, libraries, and assets. It creates a dist directory in your project directory which contains the executable JAR and a directory with libraries. +

+ +

+In the simplest case, you zip up the dist directory and distribute it to your customers. Companies often have additional tools to create executables and installers. +

+ +

+Here are your deployment options in detail: + +

+ +
+ +

Desktop Application (JAR)

+
+ +

+ +The JAR file is the most common deployment method for Java desktop applications. The user downloads the executable JAR file to his machine and runs it to start the game. + +

+
    +
  1. Right-click your project and open the Project Properties.
    +
  2. +
  3. In the Application>Web Start category, make sure the box “Enable Web Start” is not checked. Click OK.
    +
  4. +
  5. Right-click your project and Clean and Build.
    +
  6. +
  7. If the build succeeds you see a line similar to
    + Building jar: /home/joe/jMonkeyPlatform/MySuperTestGame/dist/MySuperTestGame.jar
    + this means the executable JAR has been generated successfully in your project directory.
    +
  8. +
  9. Zip up the dist directory and distribute it to your users. Make sure to keep the lib directory in it!
    +
  10. +
+ +

+ +Most operating systems execute a JAR when users double-click on it, but you can also create a launcher. +

+ +
+ +

Desktop Executables

+
+ +

+ +jMonkeyPlatform allows you to create launchers for different desktop platforms, like an .exe file for Windows systems, an Application for MaxOSX and a launcher for Linux systems. + +

+
    +
  1. Right-click your project and open the Project Properties.
    +
  2. +
  3. In the Application>Desktop category, select the checkboxes for the platforms you want to distribute to.
    +
  4. +
  5. Click OK.
    +
  6. +
+ +

+ +When you build your project, zip files for each selected platform will be created in the dist folder that contain all that is needed to run your application on that platform. +

+ +
+ +

Web Start (JNLP)

+
+ +

+ +Web Start allows your users to start your application by simply clicking a link that you provide, for example in a button on your web page. The browser downloads the JAR file and then automatically runs your game in an extra window. The only requirement is that the user's browser has the Java plugin installed. This is a very user-friendly way for your customers to play your game without any extra steps to install it. Optionally, you can set it up so the file is saved to their desktop and can be restarted later, so they do not need to be online to play. + +

+
    +
  1. Right-click your project and open the Project Properties.
    +
      +
    1. In the Application>Web Start category, check the box to Enable Web Start.
      +
    2. +
    3. Check the box to make the application self-signed. :!:
      +
    4. +
    5. Optionally, check the box to allow offline use.
      +
    6. +
    7. Make sure Application Descriptor is activated. Click OK.
      +
    8. +
    +
  2. +
  3. Right-click your project and Clean and Build. The dist directory is generated.
    +
  4. +
  5. Upload the contents of the dist directory to a public http server
    +
  6. +
  7. Either edit the sample launch.html file, or simply add a standard link (A HREF) pointing to your .jnlp file to one of your web pages.
    +
  8. +
  9. Tell your users to open your page in a webbrowser, and click the link to webstart the application.
    +
  10. +
+ +

+ +Look at the sample launch.html, you can have any custom content around the link. Keep a copy of your launcher file because the jMonkeyPlatform will always regenerate its default launch.html. +

+ +

+Also, see this on creating WebStarts. + +

+ +
+ +

Browser Applet

+
+ +

+ +A browser Applet is a Java application that runs in the web browser while the user is visiting your web page. The only requirement is that the user's browser has the Java plugin installed. There is no installation step, the user can play right away in the browser. The user will not be able to save the game to his harddrive, nor can he play offline. +

+ +

+These instrcutions assume that you have already written a game that you want to turn into an Applet. As opposed to other jME3 games, Applets cannot capture the mouse for navigation, so the camera will be switched to dragToRotate mode. The jMonkeyPlatform and the included build script already contain what you need. +

+ +
+ +

To Turn a Project Into an Applet

+
+
    +
  1. Right-click your project and open the Project Properties.
    +
      +
    1. In the Application>Applet category, check the box to enable Applet creation.
      +
    2. +
    3. Change the applet width and height as you want it.
      +
    4. +
    5. Click OK.
      +
    6. +
    +
  2. +
  3. Right-click your project and Clean and Build.
    +
  4. +
+ +

+ +The dist/Applet directory now contains all the files necessary for the game to run as Applet. To test the Applet-based game, run the project in the jMonkeyPlatform. +

+ +
+ +

To Deploy the Game as Applet

+
+
    +
  1. Edit the dist/Applet/run-applet.html file in anyway you like. Just keep the Applet code.
    +
  2. +
  3. Upload the contents of the dist/Applet directory to a public http server.
    +
  4. +
  5. Access the run-applet.html file using a webbrowser
    +
  6. +
  7. Click the link to web-start your application.
    +
  8. +
+ +
+ +

To Troubleshoot Applets

+
+
    +
  • Open the Java console for error messages.
    +
  • +
  • Depending on your settings, the browser caches the applet, the html page, and/or the jnlp file, even after you have cleaned and built the project. Make sure to empty the browser cache.
    +
  • +
+ +
+ +

Android

+
+ +

+ +TODO +

+ +
+ +

Tip: Switching Build Configurations

+
+ +

+ +The jMonkeyPlatform has a Run Configuration menu in the toolbar. Use it to save your various sets of Project Property configuations, and switch between them. + +

+
    +
  1. Click the Set Project Configuration popup in the toolbar and choose Customize.
    +
  2. +
  3. The Project Properties Run section opens. Under Configuration, click New.
    +
  4. +
  5. Name the saved configuration, for instance “my webstart” vs “my desktop app”, or “development” vs “deployment”. Click OK.
    +
  6. +
  7. Make sure the new config is selected in the Set Project Configuration popup above the editor.
    +
  8. +
  9. Make changes to the Project Properties as described above.
    +
  10. +
+ +

+ +Now you can use the Set Project Configuration popup menu to switch between your run/build configurations. +

+ +
+ +

Tip: Reducing Distribution Size

+
+ +

+ +There may be several parts of the full jMonkeyEngine library that you do not even use in your application. You should leave out the corresponding libraries from your distribution. +

+ +

+To remove unused libraries: +

+
    +
  1. Right-click your project and select “Properties”
    +
  2. +
  3. Select “Libraries” on the left
    +
  4. +
  5. Select the “jme3-libraries” entry and press “remove”.
    + This library package contains all libraries for jME3 and is quite large.
    +
  6. +
  7. Press the “Add Library” button
    +
  8. +
  9. Select the “jme3-libraries-lwjgl-minimum” or “jme3-libraries-jogl-minimum” library (depening on which renderer you use).
    +
  10. +
  11. Add other jME3 libraries in the same way depending which features you use (jme3-libraries-gui, jme3-libraries-physics, jme3-libraries-video etc.)
    +
  12. +
  13. Click OK.
    +
  14. +
  15. Clean, Build and Run the project and make sure you have not missed anything.
    +
  16. +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/applymaterial.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/applymaterial.jpg new file mode 100644 index 000000000..e9cb8e25f Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/applymaterial.jpg differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/asset_packs.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/asset_packs.html new file mode 100644 index 000000000..c6be2c805 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/asset_packs.html @@ -0,0 +1,186 @@ + +

jMonkeyPlatform AssetPacks

+
+ +

+AssetPacks are a way to package jME3 compatible assets like models, textures, sounds and whole scenes into a package that contains publisher info, license info, descriptions etc. for all of the assets. An AssetPack basically consists of an assetpack.xml file that describes the content and an assets folder that contains the content. The integrated browser in jMP allows you to add the assets of installed AssetPacks to any project you are doing. +

+ +
+ +

The AssetPack Browser

+
+ +

+ +

+ +

+The AssetPack browser in jMP makes browsing the installed AssetPacks easy. Browse categories, search for tags and find the right asset for your project. When you have found it, you can add it with one click to your current scene. The AssetPack manager will automagically copy all needed textures, sounds etc. to your projects assets folder. +

+ +

+You can also browse a selection of online assetpacks that are available on jMonkeyEngine.org for download and install them to your jMonkeyPlatforms AssetPack browser. +

+ +

+The AssetPack browser uses a predefined directory to store the AssetPacks which is also used for new AssetPack projects. You can see and change the folder path in the AssetPack preferences (jMonkeyPlatform→Settings). +

+ +
+ +

Using the browser

+
+ +

+To preview a model from the browser, right-click it and select “Preview Asset” +

+ +

+To add a model from the AssetPack browser to a scene do the following: +

+
    +
  1. Create a new scene (j3o) file or use an existing one
    +
  2. +
  3. Open it in the SceneComposer by right-clicking it and selecting “Edit in SceneComposer”
    +
  4. +
  5. Select the root node of the scene (or another node you want to add the model to)
    +
  6. +
  7. Right-click a model in the AssetBrowser and select “Add to SceneComposer”
    +
  8. +
+ +

+The model will be added to your scene and all needed texture files will be copied to your projects assets folder. +

+ +
+ +

AssetPack Projects

+
+ +

+ +AssetPack projects are a way to create your own AssetPacks, either for personal use or for publishing. With this project type in jMonkeyPlatform you can create a library of assets on your computer that you can use in any of your projects via the AssetPack browser. +Editing of asset and project info, adding of new assets and setting their properties, everything you need to create and publish your AssetPacks is there. + +

+
    +
  1. Select “File → New Project”
    +
  2. +
  3. Select “AssetPack Project”
    +
  4. +
  5. Fill in the project info and press “finish”
    +
  6. +
+ +

+ +You can access and change the project properties by right-clicking the project and selecting “Properties”. + +

+ +
+ +

Adding Assets

+
+ +

+ +

+ +

+To add new assets to your AssetPack do the following: +

+
    +
  1. Right-Click the “Assets” node of the AssetPack project
    +
  2. +
  3. Select “Add Asset..”
    +
  4. +
  5. Specify the info about your asset and press Next
    +
  6. +
  7. Press the “add files” button and select all files belonging to your asset
    +
  8. +
  9. Select the “main” checkbox for the main model file if your asset is a model file
    +
  10. +
  11. Change the asset paths and types if needed and press “finish”
    +
  12. +
+ +

+ +The global asset type can be “model”, “scene”, “texture”, “sound”, “shader” or “other” +

+ +

+With the “model” or “scene” types, the AssetPack browser will try to load and add a model file from the selected assets when the user selects “Add to SceneComposer”. Specify the “load this model with material” flag for the model file that should be loaded via the AssetManager, you can also specify multiple mesh or scene files to be loaded. All texture and other needed files will be copied to the users project folder. +

+ +

+On the “Add Files” page you define the path of the files in the AssetPack. The importer tries to generate a proper path from the info entered on the first page. Note that for j3o binary models, the texture paths have to be exactly like they were during conversion. The given paths will also be used when copying the data to the users “assets” folder. +

+ +

+With the “add files” button you can open a file browser to select files from your harddisk that will be copied into the assets/ folder of the AssetPack project. With the “add existing” button you can add a file thats already in your AssetPack assets folder to a new asset item. This way you can reuse e.g. textures for asset items or make items for an existing collection of asset files that you copied to the projects assets folder. +

+ +

+ +

+ +

+You can specify a specific material to be used for the single mesh/scene files, just select it in the dropdown below the mesh or scene file. If you don't select a material file here, the first found material file is used or none if none is found. +

+ +

+If the material file is an Ogre material file (.material) it will be used for loading an Ogre scene or mesh file. If it is a jMonkeyEngine3 material file (.j3m), it will be applied to the mesh regardless of model type. Note that for j3o models you don't need material files as the material is stored inside the j3o file. +

+ +

+In your AssetPack Project, if you right-click your asset and select “preview asset” you should be able to see your model. If you do, it should work for the user as well. +

+ +

+You can change the single assets properties in the properties window after you have added them. Just select an asset and open the properties window (Windows→Properties). +

+ +

+Supported formats for models are: +

+
    +
  1. OgreXML
    +
  2. +
  3. Wavefront OBJ
    +
  4. +
  5. jMonkeyEngine3 j3o
    +
  6. +
+ +
+ +

AssetPack Publishing

+
+ +

+ +

+ +

+You can publish your AssetPacks either as a zip file or directly to jmonkeyengine.org, using your website user name and login. This means other jMonkeyPlatform users can download your AssetPacks and install them to their local database right off the AssetPack online packages browser. +

+ +

+To make sure you can upload, you have to be registered on jmonkeyengine.org and have to enter your login info in the AssetPack preferences (jMonkeyPlatform→Settings). + +

+
    +
  1. Right-Click your AssetPack project and select “Publish AssetPack..”
    +
  2. +
  3. Check the description etc. settings and press “Next”
    +
  4. +
  5. Select the checkbox for online and/or local publishing and press “finish”
    +
  6. +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/code_editor.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/code_editor.html new file mode 100644 index 000000000..03a900f79 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/code_editor.html @@ -0,0 +1,252 @@ + +

jMonkeyPlatform: Code Editor and Palette

+
+ +

+ +The Source Code Editor is the central part of the jMonkeyPlatform. This documentation shows you how to make the most of the jMonkeyPlatform's assistive features. +

+ +

+Note: Since the jMonkeyPlatform is based on the NetBeans Platform framework, you can learn about certain jMonkeyPlatform features by reading the corresponding NetBeans IDE tutorials (in the “see also links”). +

+ +
+ +

Code Completion and Code Generation

+
+ +

+ +While typing Java code in the source code editor, you will see popups that help you to write more quickly by completing keywords, and generating code snippets. Additionally, they will let you see the javadoc for the classes you are working with. +

+ +

+ +

+ +

+Code Completion +

+
    +
  • Complete keyword / method / variable: Ctrl-Space (Alternatively use Ctrl-\)
    +
      +
    • Customize Code Completion options: Tools > Options > Editor > Code Completion
      +
    • +
    +
  • +
  • Show expected parameters of this method in a tooltip: Ctrl-P
    +
  • +
  • Complete any string (even non-Java) that has been used before: (Shift-)Ctrl-K
    +
  • +
+ +

+ +Code Generation +

+
    +
  • Auto-fix import statements: Ctrl-Shift-I
    +
  • +
  • Auto-generate getters/setters, try/catch, equals/hashCode: Alt-Insert
    +
      +
    • Customize code completion: Choose Tools > Options > Editor > Code Completion
      +
    • +
    +
  • +
  • Auto-generate common code snippets such as loops, declarations, println, by typing the template name + TabKey
    +
      +
    • Customize code templates: Choose Tools > Options > Editor > Code Templates
      +
    • +
    +
  • +
  • Rename, move, or introduce methods, fields, and variables, without breaking the project: Refactoring menu
    +
  • +
+ +
+ +

Semantic and Syntactic Coloring

+
+ +

+ + +

+ +

+The text color in the editor gives you important hints how the compiler will interpret what you typed, even before you compiled it. +

+ +

+Examples: +

+
    +
  • Java keywords are blue, variables and fields are green, parameters are orange.
    +
  • +
  • Strikethrough means deprecated method or field.
    +
  • +
  • Gray underline means unused variable or method.
    +
  • +
  • Place the caret in a method or variable and all its ocurrences are marked tan.
    +
  • +
  • Place the caret in a method's return type to highlight all exit points
    +
  • +
  • and many more…
    +
  • +
+ +

+ +To customize Colors and indentation: +

+
    +
  • Tools > Options > Editor > Formatting.
    +
  • +
  • Tools > Options > Fonts and Colors.
    +
  • +
+ +
+ +

Editor Hints and Quick Fixes (a.k.a. Lightbulbs)

+
+ +

+ +Editor hints and quick fixes show as lightbulbs along the left edge of the editor. They point out warnings and errors, and often propose useful solutions! + +

+
    +
  • Execute a quick fix: Place the caret in the line next to the lightbulb and press Alt-Enter (or click the lightbulb)
    +
      +
    • Customize hints: Choose Tools > Options > Editor > Hints.
      +
    • +
    +
  • +
+ +
+ +

Javadoc

+
+
    +
  • Place the caret above a method or a class that has no Javadoc, type /** and press Enter: The editor generates skeleton code for a Javadoc comment.
    +
  • +
  • Right-click the project in the Projects window and choose Generate Javadoc.
    +
  • +
  • Right-click a file and choose Tools > Analyze Javadoc
    +
  • +
+ +

+ +To display a javadoc popup in the editor, place the caret in a line and press Ctrl-Space (Alternatively use Ctrl-\). + +

+
    +
  • If the javadoc popup doesn't work, make certain that
    +
      +
    • You have the Java JDK documentation installed and set up: Tools > Java Platforms
      +
    • +
    • You downloaded and set up javadoc for third-party libraries: Project properties > Libraries > Edit
      +
    • +
    +
  • +
+ +
+ +

Navigating the jME3 Source

+
+ +

+ +When the JavaDoc does not deliver enough information, you can have a look at the source of every method or object of jME3 that you use. Just right-click the variable or method, select “Navigate > Go to source..” and an editor will open showing you the source file of jME3. +

+ +
+ +

Palette

+
+ +

+ + +

+ +

+Choose Windows > Palette to open the context-sensitive Palette. The jMonkeyPlatform provides you with jme3 code snippets here that you can drag and drop into your source files. +

+
    +
  • Examples: Node and Model creation code snippets.
    +
  • +
+ +

+ +Tip: Choose Tools > Add to Palette… from the menu to add your own code snippets to the Palette. (not available yet in alpha build) +

+ +
+ +

Keyboard Shortcuts

+
+ +

+ +Keyboard Shortcuts save you time when when you need to repeat common actions such as Build&Run or navigation to files. +

+
    +
  • Go to File: Alt-Shift-O
    +
  • +
  • Go to Type: Ctrl-O
    +
  • +
  • Open in Projects / Files / Favorites window: Ctrl-Shift-1 / 2 / 3
    +
  • +
  • Build&Run Project / File: F6 / Shift-F6
    +
  • +
  • Switch to Editor / Projects / Files / Navigator: Ctrl-0 / 1 / 3 / 7
    +
  • +
  • Indent code: Ctrl-Shift-F
    +
  • +
+ +

+ +By default, jMonkeyEngine uses the same as the NetBeans IDE, but you can also switch to an Eclipse Keymap, or create your own set. +

+
    +
  • Customize keyboard shortcuts: Tools > Options > Keymap
    +
  • +
+ +
+ +

Tips and Tricks

+
+
    +
  • To browse the physical file structure of your project, use the Files window: Ctrl-2
    +
  • +
  • To open a file that is not part of a Java project, add it to the Favorites window: Ctrl-3
    +
  • +
  • If you cannot find a particular menu item or option panel, use the IDE Search box in the top right! Ctrl-i
    +
  • +
  • If a code block, class, or javadoc is quite long and you don't want to scroll over it, click the +/- signs to collapse (fold) the code block temporarily.
    +
  • +
  • Press F1 for Help
    +
  • +
+
+ +

+See also + +

+
    +
  • +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/debugging_profiling_testing.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/debugging_profiling_testing.html new file mode 100644 index 000000000..d0c6c6cde --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/debugging_profiling_testing.html @@ -0,0 +1,236 @@ + +

jMonkeyPlatform: Debugging, Profiling, Testing

+
+ +

+ +Debugging, testing and profiling are important parts of the development cycle. This documentation shows you how to make the most of the jMonkeyPlatform's assistive features. +

+ +

+
+ +

+ +

+Note: Since the jMonkeyPlatform is based on the NetBeans Platform framework, you can learn about certain jMonkeyPlatform features by reading the corresponding NetBeans IDE tutorials (in the “see also links”). +

+ +
+ +

Testing

+
+ +

+ +The jMonkeyPlatform supports the JUnit testing framework. It is a good practice to write tests (assertions) for each of your classes. Each test makes certain this “unit” (e.g. method) meets its design and behaves as intended. Run your tests after each major change and you immediately see if you broke something. +

+ +
+ +

Creating Tests

+
+
    +
  1. Right-click in a java file in the Projects window and choose Tools > Create JUnit Tests.
    +
  2. +
  3. Click OK. The jMonkeyPlatform creates a JUnit test skeleton in the Test Package directory.
    +
  4. +
  5. The body of each generated test method is provided solely as a guide. In their place, you need to write your actual test cases!
    +
  6. +
  7. You can use tests such as assertTrue(), assertFalse(), assertEquals(), or assert().
    +
      +
    • Here is an example for assertions that test an addition method: assert( add(1, 1) == 2); assert( add(2,-5) == -3); …
      +
    • +
    +
  8. +
  9. “Optimally”, you should write a test case for every method (100% coverage).
    +
  10. +
+ +

+ +
+ +Tip: Use the Navigate menu to jump from a test to its tested class, and back. +

+ +
+ +

Running Tests

+
+
    +
  1. Right-click the class in the Projects window and Choose Test File, or right-click the project and select Test to run all tests.
    +
  2. +
  3. Check the Test window to see successful test (green) and test failures (red).
    +
  4. +
  5. If a test fails that has succeeded before, you know that your latest changes broke something!
    +
  6. +
+ +

+ +Using unit tests regularly allows you to detect side-effects on classes that you thought were unaffected by a code change. +

+ +

+
+ +See also: +

+
    +
  • +
  • +
  • +
  • +
+ +
+ +

Debugging

+
+ +

+ +In the jMonkeyPlatform, you have access to a debugger to examine your application for errors such as deadlocks and NullPointerExeptions. You can set breakpoints, watch variables, and execute your code line-by-line to identify the source of a problem. + +

+
    +
  1. First, you set breakpoints and/or watches before the problematic lines of code where you suspect the bug.
    +
      +
    • If you want to watch a variable's value: Right-click on a variable and select New Watch from the context menu.
      +
    • +
    • If you want to step through the execution line by line: Right-click on a line and choose Toggle Line Breakpoint; a pink box appears as a mark.
      +
    • +
    +
  2. +
  3. Choose “Debug > Debug Main Project” to start a debugger session for the whole project. Or, right-click in a file and select Debug File to debug only one file.
    +
  4. +
  5. The application starts running normally. If you have set a breakpoint, the execution stops. Debugger windows open and print debugger output.
    +
  6. +
  7. You can do many things now to track down a bug:
    +
      +
    • Inspect the values of local variables.
      +
    • +
    • Use the Step buttons in the top to step into, out of, and over expressions while you watch the execution.
      +
    • +
    • Navigate through your application's call stack. Right-click on threads to suspend or resume them.
      +
    • +
    • Choose Debug > Evaluate Expression from the menu to evaluate an expression.
      +
    • +
    • Move the mouse pointer over a variable to inspect its value in a tooltip.
      +
    • +
    • Inspect the classes loaded on the heap and the percentage and number of object instances. Right-click a class in the Loaded Classes window and choose Show in Instances view (JDK6 only).
      +
    • +
    • And more…
      +
    • +
    +
  8. +
  9. To stop debugging, choose Debug > End Debugger Session from the menu.
    +
  10. +
+ +
+ +

Profiling

+
+ +

+ +The profiler tool is used to monitor thread states, CPU performance, and memory usage of your jme3 application. It helps you detect memory leaks and bottlenecks in your game while it's running. +
+ + +

+ +
+ +

Installing the Profiler

+
+ +

+ +If you do not see a Profiler menu in the jMonkeyPlatform, you need to download the Profiler plugin first. +

+
    +
  1. Open the Tools > Plugins menu, and got to the “Available plugins” tab
    +
  2. +
  3. Find the “Java Profiler” plugin (“Java SE” category) and check the Install box.
    +
  4. +
  5. Click the install button and follow the instructions.
    +
  6. +
  7. When you start the profiler for the first time, you are prompted to run a calibration once. Click OK in the “Profiler integration” dialog to complete the installation process.
    +
  8. +
+ +
+ +

Monitoring and Analyzing

+
+
    +
  1. Choose Profile Project from the Profile menu.
    +
  2. +
  3. Select one of three tasks:
    +
      +
    • Monitor Application – Collect high-level information about properties of the target JVM, including thread activity and memory allocations.
      +
    • +
    • Analyze CPU Performance – Collect detailed data on application performance, including the time to execute methods and the number of times the method is invoked.
      +
    • +
    • Analyze Memory Usage – Collect detailed data on object allocation and garbage collection.
      +
    • +
    +
  4. +
  5. Click Run. Your application starts and runs normally.
    +
  6. +
  7. Use the Profiling window to track and collect live profiling results while you application is running.
    +
  8. +
+ +
+ +

Comparing Snapshots

+
+ +

+ +Click the Take Snapshot button to capture the profiling data for later! +

+
    +
  • You can store and view snapshots in the Profiling window.
    +
  • +
  • Choose Compare Snapshots from the profiler window to compare two selected snapshots
    +
  • +
+ +
+ +

Using Profiling Points

+
+ +

+ +Profiling points are similar to debugger breakpoints: You place them directly in the source code and they can trigger profiling behaviour when hit. +

+
    +
  • Open a class in the browser, right-click in a line, and select Profiling > Insert Profiling Point to add a profiling point here.
    +
  • +
  • Use Profiling points if you need a trigger to reset profiling results, take a snapshot or heap dump, record the timestamp or execution time of a code fragment, stop and start a load generator script (requires the load generator plugin).
    +
  • +
  • Open the Profiling Points window to view, modify and delete the Profiling Points in your projects.
    +
  • +
+ +

+ +
+ +See also: +

+
    +
  • +
  • +
  • +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/default_build_script.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/default_build_script.html new file mode 100644 index 000000000..6691de58f --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/default_build_script.html @@ -0,0 +1,93 @@ + +

Default Build Script

+
+ +

+ +If you use jME3 together with the jMonkeyPlatform (recommended) then you benefit from the provided build script. Every new project comes with a default Ant script. The toolbar buttons and clean/build/run actions in the jMonkeyPlatform are already pre-configured. +

+ +
+ +

Default Targets

+
+ +

+ +The build script includes targets for the following tasks: + +

+
    +
  • clean – deletes the built classes and executables in the dist directory.
    +
  • +
  • jar – compiles the classes, builds the executable JAR in the dist directory, copies libraries.
    +
  • +
  • run – runs the executable JAR.
    +
  • +
  • javadoc – compiles javadoc from your java files into html files.
    +
  • +
  • debug – used by the jMonkeyPlatform Debugger plugin.
    +
  • +
  • test – Used by the jMonkeyPlatform JUnit Test plugin.
    +
  • +
+ +

+ +Usage on the command line: + +

+
ant clean
+ant jar
+ant run
+ +

+Recommended Usage: Use the menu items or toolbar buttons in the jMonkeyPlatform to trigger clean, build, and run actions. +

+ +
+ +

Browsing the Build Script

+
+ +

+ +To see the build script and the predefined tasks +

+
    +
  1. Open your project in the jMonkeyPlatform if it isn't already open (File > Open Project…)
    +
  2. +
  3. Open the Files window (Window > Files)
    +
  4. +
  5. Open the project node. You see build.xml listed.
    +
      +
    1. Double-click build.xml to see how the jme3-specify build targets were defined. You typically do not need to edit the existing ones, but you can.
      +
    2. +
    3. Click the triangle next to build.xml to see all targets.
      +
        +
      1. Double-click a target in the Files window, or the Navigator, to see how the target was defined.
        + You will notice that the file nbproject/build-impl.xml opens. It contains very generic targets that you typically will never need to edit. Note that build.xml includes build-impl.xml!
        +
      2. +
      +
    4. +
    +
  6. +
+ +
+ +

Adding Custom Targets

+
+ +

+ +The build script is a non-proprietary Apache Ant script. It will work out-of-the-box, but if necessary, you can extend and customize it. +

+ +

+Read the comments in build.xml, they explain how to override targets, or extend them, to customize the build process without breaking the existing functionality. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/extension_library.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/extension_library.html new file mode 100644 index 000000000..582882f55 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/extension_library.html @@ -0,0 +1,79 @@ + +

Creating an extension library plugin

+
+ +

+This page describes how you can wrap any jar library into a plugin that a jMP user can download, install and then use the contained library in his own game projects. +

+ +

+
+ +Creating the plugin project (in jMP): +

+
    +
  • Create a new Module Suite (or use an existing one)
    +
  • +
  • Open the suite, right-click the “Modules” folder and select “Add new..”
    +
  • +
  • For “Project Name” enter an all-lowercase name without spaces like my-library
    +
  • +
  • Make sure the “Project Location” is inside the module suite folder and press “Next”
    +
  • +
  • Enter the base java package for your plugin in “Code Name Base” like com.mycompany.plugins.mylibrary
    +
  • +
  • Enter a “Module Display Name” for your plugin like “My Library”
    +
  • +
  • Check the “Generate XML Layer” checkbox
    +
  • +
  • Press Finish
    +
  • +
+ +

+ +Adding the library: +

+
    +
  • Right click the Module Project and select “New→Other”
    +
  • +
  • Under “Module Development” select the “Java SE Library Descriptor” template and press “Next”
    +
  • +
  • If you dont have the external library registered in jMP yet, click “Manage Libraries” and do the following:
    +
      +
    • Click “New Library”, enter a name for the library and press OK
      +
    • +
    • In the “Classpath” tab, press “Add JAR/Folder” and select the jar file(s) needed for the library
      +
    • +
    • In the “JavaDoc” tab, press “Add ZIP/Folder” and add the javadoc for the library (zipped or folder)
      +
    • +
    • In the “Sources” tab you can add a folder or jar file containing the source files of the library if available
      +
    • +
    • Press OK
      +
    • +
    +
  • +
  • Select the external library from the list and press “Next”
    +
  • +
  • Enter a name for the Library (used as filename for the description file)
    +
  • +
  • Enter a display name for the Library (This is the name the user later sees in his library list)
    +
  • +
  • Press OK
    +
  • +
+ +

+ +You will notice a new file “MyLibrary.xml” is created in the plugins base package and linked to in the layer.xml file. This is basically it, you can configure a version number, license file (should be placed in Module root folder) and more via the Module Properties. +

+ +

+
+ +After you are done, you can contribute the plugin in the jMP contribution update center. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/general.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/general.html new file mode 100644 index 000000000..10973b1c4 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/general.html @@ -0,0 +1,22 @@ + +

Creating plugin components

+
+ +

+For the most common extensions like Windows, File Types, Libraries etc. there exist templates that you can add to your plugin. + +

+
    +
  1. Right-click your Module Project and select New→Other
    +
  2. +
  3. Select “Module Development” to the left
    +
  4. +
+ +

+ +You will see a list of components you can add to your project. A wizard will guide you through the creation of the component. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/model_loader.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/model_loader.html new file mode 100644 index 000000000..a8018fb62 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/model_loader.html @@ -0,0 +1,41 @@ + +

Creating a model importer

+
+ +

+ +TODO + +

+
    +
  1. Create plugin
    +
  2. +
  3. Add importer jar file (wrap jar file)
    +
  4. +
  5. Add filetype (Template)
    +
  6. +
  7. Change DataObject to extend SpatialAssetDataObject
    +
  8. +
  9. Implement loadAsset method in DataObject (if necessary)
    +
  10. +
  11. Create AssetManagerConfiguratorSee also:
    +
  12. +
+ +

+ + +

+
+
+ Task + + + + +
Assigned to:normen
+
+
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/scene.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/scene.html new file mode 100644 index 000000000..74282c8ac --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/scene.html @@ -0,0 +1,213 @@ + +

The Scene

+
+ +

+ +To reduce system overhead the jMonkeyPlatform Core supplies one scene/jme3 application that is shared between plugins. Furthermore there's the “SceneExplorer” that shows a visual representation of the scenegraph and its objects properties across plugins. +

+ +

+
+ +Note: All info due to change until jMP is stable! +

+ +
+ +

How to access the Scene

+
+ +

+ +There are several ways for your plugin to interact with the Scene: +

+
    +
  • It listens for selected spatials / objects and offers options for those
    +
  • +
  • It requests the whole scene for itself and loads/arranges the content in it (e.g. a terrain editor or model animation plugin).
    +
  • +
+ +
+ +
Notes
+
+
    +
  • Although the scene can be accessed at any time via SceneApplication.getApplication() it is not recommended to modify the scene like that. Other plugins might be accessing the scene and updates will not be properly recognized.
    +
  • +
  • Remember the scene runs on the render thread and most everything you do in the plugin (button events etc.) runs on the AWT thread, always encapsulate calls to either side correctly via Callables/Runnables or register as an AppState to the SceneApplication to have an update() call by the render thread.
    +
  • +
  • It became a standard in jMP to start the name of methods that execute directly on the OpenGL thread with “do” e.g “doMoveSpatial”, this makes identifying threading issues easier.
    +
  • +
  • The AssetManager of jme3 is threadsafe and can be used from any thread to load assets
    +
  • +
+ +
+ +

Listening for Node selection

+
+ +

+ +In jMP, all objects are wrapped into NetBeans “Nodes” (different thing than jme Nodes!). Such nodes can have properties and icons and can be displayed and selected in the jMP UI. The SceneExplorer shows a tree of Nodes that wrap the Spatials of the current scene and allows manipulating their properties on selection. A jME “Spatial” is wrapped by a “JmeSpatial” node, for example. One advantage of these Nodes is that one can manipulate properties of Spatials directly from the AWT thread. +

+ +

+
+ +To listen to the current selection, implement org.openide.util.LookupListener and register like this: +

+
private final Result<JmeSpatial> result;
+ 
+//method to register the listener;
+private void registerListener(){
+    result = Utilities.actionsGlobalContext().lookupResult(JmeSpatial.class);
+    result.addLookupListener(this);
+}
+ 
+//implements org.openide.util.LookupListener (called from AWT thread)
+public void resultChanged(LookupEvent ev) {
+    Collection<JmeSpatial> items = (Collection<JmeSpatial>) result.allInstances();
+    for (JmeSpatial jmeSpatial : items) {
+        //Using the JmeSpatials properties you can modify the spatial directly from the AWT thread:
+        spatial.getPropertySets()[0].setValue("Local Translation", Vector3f.ZERO);
+        return;
+    }
+}
+

+You can also access the “real” spatial but since its part of the scenegraph you will have to modify it on that thread: +

+
//retrieve the "real" spatial class from the JmeNode
+for (JmeSpatial jmeSpatial : items) {
+    //the spatial is stored inside the JmeSpatials "Lookup", a general container for Objects
+    final Spatial realSpatial = jmeSpatial.getLookup().lookup(Spatial.class);
+    //use a Callable to execute on the render thread:
+    SceneApplication.getApplication().enqueue(new Callable() {
+        public Exception {
+            realSpatial.setLocalTranslation(Vector3f.ZERO);
+            return null;
+        }
+    });
+    return;
+}
+
+ +

Requesting the Scene

+
+ +

+ +If your plugin wants to use the scene by itself, it first has to implement SceneListener and register at the scene and then send a SceneRequest to the SceneApplication. When the SceneRequest has been approved and the current Scene has been closed, the SceneListener (your class) is called with its own SceneRequest as a parameter. When another plugin sends a SceneRequest it is also reported to you and its a hint that your RootNode has been removed from the Scene and you are no longer in control of it. You could also hook into the SceneRequests of other plugins to see if/when they are activated to display add-on plugins for that plugin. +

+ +

+
+ +The SceneRequest object has to contain several things. A thing that you must supply is a jme “Node” wrapped into a “JmeNode” object. This is your rootNode that you use to display and build your scene. As soon as you control the scene, you will have to control the camera etc. yourself. +

+
com.jme3.scene.Node rootNode = new com.jme3.scene.Node("MyRootNode");
+ 
+private void registerSceneListener(){
+    SceneApplication.getApplication().addSceneListener(this);
+}
+ 
+private void requestScene(){
+    //create a jmeNode from the rootNode using the NodeUtility
+    JmeNode jmeNode = NodeUtility.createNode(rootNode);
+    //create the scene request
+    SceneRequest request=new SceneRequest(this, jmeNode, assetManager);
+    //request the scene
+    SceneApplication.getApplication().requestScene(request);
+}
+ 
+//implements SceneListener (called from render thread)
+public void sceneRequested(SceneRequest request){
+    //check if its our request
+    if (request.getRequester() == this) {
+        //we now own the scene
+    }
+}
+ 
+public boolean sceneClose(SceneRequest request) {
+    if (request.getRequester() == this) {
+        //we have to close the scene, if we cannot, return false
+        if(isNotSaved()){
+            return false;
+        }
+    }
+    return true;
+}
+
+ +

Undo/Redo support

+
+ +

+jMP has a global undo/redo queue that activates the undo/redo buttons. To use it in your TopComponent, add the following method: + +

+
@Override 
+public UndoRedo getUndoRedo() { 
+return Lookup.getDefault().lookup(SceneUndoRedoManager.class); 
+}
+

+To add a undo/redo event that modifies objects on the Scenegraph, theres a special version of AbstractUndoableEdit which executes the undo/redo calls on the scene thread. Simply implement that class and add it to the queue like this: + +

+
Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { 
+ 
+@Override 
+public void sceneUndo() { 
+    //undo stuff in scene here
+} 
+ 
+@Override 
+public void sceneRedo() { 
+    //redo stuff in scene here
+} 
+ 
+@Override 
+public void awtUndo() { 
+    //undo stuff on awt thread here (updating of visual nodes etc, called post scene edit)
+} 
+ 
+@Override 
+public void awtRedo() { 
+    //redo stuff on awt thread here
+} 
+});
+

+Note: Its important that you use the method addEdit(Object source, UndoableEdit edit); +

+ +
+ +

Handy things in jMonkeyPlatform Core

+
+
    +
  • com.jme3.gde.core.scene.controller
    +
      +
    • AbstractCameraController → A basic camera control for plugins, used by SimpleSceneComposer and “View Model”
      +
    • +
    • SceneToolController → A basic controller for having selection, cursor etc. displayed in the scene, used by SimpleSceneComposer
      +
    • +
    +
  • +
  • com.jme3.gde.core.scene
    +
      +
    • OffViewPanel → A panel that renders a 3d scene in a preview and displays it in a lightweight swing panel
      +
    • +
    +
  • +
  • com.jme3.gde.core.util
    +
      +
    • DataObjectSaveNode → Allows enabling the save all button by using any file and implementing the SvaeCookie yourself.
      +
    • +
    +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/sceneexplorer.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/sceneexplorer.html new file mode 100644 index 000000000..69cc7da93 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/sceneexplorer.html @@ -0,0 +1,294 @@ + +

The SceneExplorer

+
+ +
+ +

Adding Node types to SceneExplorer

+
+ +

+ +If your plugin brings in its own SceneGraph objects you can still have them work like any other SceneExplorer item, including its special properties. +

+ +

+
+ +You will have to create your own class that extends org.openide.nodes.Node and implement the interface com.jme3.gde.core.sceneexplorer.nodes.SceneExplorerNode. Then you register that class by adding +

+
@org.openide.util.lookup.ServiceProvider(service=com.jme3.gde.core.sceneexplorer.nodes.SceneExplorerNode.class)
+ +

+ above the “public class MyClass” line in your class. Thats all, your Spatial type will automatically be used and displayed in the SceneExplorer. +

+ +

+
+ +Theres also AbstractSceneExplorerNode which brings some other useful features you might want to include like automatic creation of properly threaded properties etc. JmeSpatial for example bases on it. A simple SceneExplorerNode example for an object extending Spatial would be JmeGeometry (see below). +

+ +

+The SceneExplorerNode can be used for Spatial and Control type objects. +

+ +
+ +

Spatial Example

+
+
@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class)
+public class JmeGeometry extends JmeSpatial {
+ 
+    private static Image smallImage =
+            ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/geometry.gif");
+    private Geometry geom;
+ 
+    public JmeGeometry() {
+    }
+ 
+    public JmeGeometry(Geometry spatial, SceneExplorerChildren children) {
+        super(spatial, children);
+        getLookupContents().add(spatial);
+        this.geom = spatial;
+        setName(spatial.getName());
+    }
+ 
+    @Override
+    public Image getIcon(int type) {
+        return smallImage;
+    }
+ 
+    @Override
+    public Image getOpenedIcon(int type) {
+        return smallImage;
+    }
+ 
+    @Override
+    protected Sheet createSheet() {
+        Sheet sheet = super.createSheet();
+        Sheet.Set set = Sheet.createPropertiesSet();
+        set.setDisplayName("Geometry");
+        set.setName(Geometry.class.getName());
+        Geometry obj = geom;//getLookup().lookup(Geometry.class);
+        if (obj == null) {
+            return sheet;
+        }
+ 
+        set.put(makeProperty(obj, int.class, "getLodLevel", "setLodLevel", "Lod Level"));
+        set.put(makeProperty(obj, Material.class, "getMaterial", "setMaterial", "Material"));
+        set.put(makeProperty(obj, Mesh.class, "getMesh", "Mesh"));
+ 
+        sheet.put(set);
+        return sheet;
+ 
+    }
+ 
+    public Class getExplorerObjectClass() {
+        return Geometry.class;
+    }
+ 
+    public Class getExplorerNodeClass() {
+        return JmeGeometry.class;
+    }
+ 
+    public org.openide.nodes.Node[] createNodes(Object key2, boolean readOnly) {
+        SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key);
+        children.setReadOnly(readOnly);
+        return new org.openide.nodes.Node[]{new JmeGeometry((Geometry) key, children).setReadOnly(readOnly)};
+    }
+}
+
+ +

Control Example

+
+
@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class)
+public class JmeGhostControl extends AbstractSceneExplorerNode {
+ 
+    private static Image smallImage =
+            ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/ghostcontrol.gif");
+    private GhostControl geom;
+ 
+    public JmeGhostControl() {
+    }
+ 
+    public JmeGhostControl(GhostControl spatial, DataObject dataObject) {
+        super(dataObject);
+        getLookupContents().add(this);
+        getLookupContents().add(spatial);
+        this.geom = spatial;
+        setName("GhostControl");
+    }
+ 
+    @Override
+    public Image getIcon(int type) {
+        return smallImage;
+    }
+ 
+    @Override
+    public Image getOpenedIcon(int type) {
+        return smallImage;
+    }
+ 
+    protected SystemAction[] createActions() {
+        return new SystemAction[]{
+                    //                    SystemAction.get(CopyAction.class),
+                    //                    SystemAction.get(CutAction.class),
+                    //                    SystemAction.get(PasteAction.class),
+                    SystemAction.get(DeleteAction.class)
+                };
+    }
+ 
+    @Override
+    public boolean canDestroy() {
+        return !readOnly;
+    }
+ 
+    @Override
+    public void destroy() throws IOException {
+        super.destroy();
+        final Spatial spat=getParentNode().getLookup().lookup(Spatial.class);
+        try {
+            SceneApplication.getApplication().enqueue(new Callable<Void>() {
+ 
+                public Exception {
+                    spat.removeControl(geom);
+                    return null;
+                }
+            }).get();
+            ((AbstractSceneExplorerNode)getParentNode()).refresh(true);
+        } catch (InterruptedException ex) {
+            Exceptions.printStackTrace(ex);
+        } catch (ExecutionException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+ 
+    @Override
+    protected Sheet createSheet() {
+        Sheet sheet = super.createSheet();
+        Sheet.Set set = Sheet.createPropertiesSet();
+        set.setDisplayName("GhostControl");
+        set.setName(GhostControl.class.getName());
+        GhostControl obj = geom;//getLookup().lookup(Spatial.class);
+        if (obj == null) {
+            return sheet;
+        }
+ 
+        set.put(makeProperty(obj, Vector3f.class, "getPhysicsLocation", "setPhysicsLocation", "Physics Location"));
+        set.put(makeProperty(obj, Quaternion.class, "getPhysicsRotation", "setPhysicsRotation", "Physics Rotation"));
+ 
+        set.put(makeProperty(obj, CollisionShape.class, "getCollisionShape", "setCollisionShape", "Collision Shape"));
+        set.put(makeProperty(obj, int.class, "getCollisionGroup", "setCollisionGroup", "Collision Group"));
+        set.put(makeProperty(obj, int.class, "getCollideWithGroups", "setCollideWithGroups", "Collide With Groups"));
+ 
+        sheet.put(set);
+        return sheet;
+ 
+    }
+ 
+    public Class getExplorerObjectClass() {
+        return GhostControl.class;
+    }
+ 
+    public Class getExplorerNodeClass() {
+        return JmeGhostControl.class;
+    }
+ 
+    public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) {
+        return new org.openide.nodes.Node[]{new JmeGhostControl((GhostControl) key, key2).setReadOnly(cookie)};
+    }
+}
+
+ +

Adding items to the add and tools menus

+
+ +

+For adding Spatials, Contols and for general tools theres premade abstract classes that you can use to extend the options. Undo/Redo is handled by the abstract class. +

+ +

+

Note that the classes you create are singletons which are used across multiple nodes and you should not store any data in local variables! +

+

+ +

+To add a new Tool, use the AbstractToolAction: +

+
@org.openide.util.lookup.ServiceProvider(service = ToolAction.class)
+public class GenerateTangentsTool extends AbstractToolAction {
+ 
+    public GenerateTangentsTool() {
+        name = "Generate Tangents";
+    }
+ 
+    @Override
+    protected boolean doApplyTool(AbstractSceneExplorerNode rootNode) {
+        Geometry geom = rootNode.getLookup().lookup(Geometry.class);
+        Mesh mesh = geom.getMesh();
+        if (mesh != null) {
+            TangentBinormalGenerator.generate(mesh);
+        }
+        return true;
+    }
+ 
+    @Override
+    protected void doUndoTool(AbstractSceneExplorerNode rootNode) {
+        Geometry geom = rootNode.getLookup().lookup(Geometry.class);
+        Mesh mesh = geom.getMesh();
+        if (mesh != null) {
+            mesh.clearBuffer(Type.Tangent);
+        }
+    }
+ 
+    public Class<?> getNodeClass() {
+        return JmeGeometry.class;
+    }
+ 
+}
+

+For a new Spatial or Control, use AbstractNewSpatialAction +

+
@org.openide.util.lookup.ServiceProvider(service = NewSpatialAction.class)
+public class NewSpecialSpatialAction extends AbstractNewSpatialAction {
+ 
+    public NewSpecialSpatialAction() {
+        name = "Spatial";
+    }
+ 
+    @Override
+    protected Spatial doCreateSpatial(Node parent) {
+        Spatial spatial=new Node();
+        return spatial;
+    }
+}
+

+ + +or AbstractNewControlAction: +

+
@org.openide.util.lookup.ServiceProvider(service = NewControlAction.class)
+public class NewRigidBodyAction extends AbstractNewControlAction {
+ 
+    public NewRigidBodyAction() {
+        name = "Static RigidBody";
+    }
+ 
+    @Override
+    protected Control doCreateControl(Spatial spatial) {
+        RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
+        if (control != null) {
+            spatial.removeControl(control);
+        }
+        Node parent = spatial.getParent();
+        spatial.removeFromParent();
+        control = new RigidBodyControl(0);
+        if (parent != null) {
+            parent.attachChild(spatial);
+        }
+        return control;
+    }
+}
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/setup.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/setup.html new file mode 100644 index 000000000..18b46f15f --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/development/setup.html @@ -0,0 +1,118 @@ + +

Creating a jMP plugin

+
+ +

+Note that the creation of a Module Suite is only necessary if you want to upload your plugin to the contribution update center. + +

+ +
+ +

Using jMP for development (preferred)

+
+
    +
  • Install the “Netbeans Plugin Development”, “NetBeans API Documentation” and “GUI Builder” plugins via Tools→Plugins
    +
  • +
  • Create a new “Module Suite” project (can be any name, this will be your local “collection” of plugins that you create)
    +
  • +
  • Open the suite, right-click the “Modules” folder and select “Add new..”
    +
  • +
  • For “Project Name” enter an all-lowercase name without spaces like my-library
    +
  • +
  • Make sure the “Project Location” is inside the module suite folder and press “Next”
    +
  • +
  • Enter the base java package for your plugin in “Code Name Base” like com.mycompany.plugins.mylibrary
    +
  • +
  • Enter a “Module Display Name” for your plugin like “My Library”
    +
  • +
  • Check the “Generate XML Layer” checkbox
    +
  • +
  • Press Finish
    +
  • +
  • To use core jMP or jME3 functions, add “jMonkeyPlatfom Core” and “jMonkeyPlatform Core jME3” via “Module Properties→Library→Add Dependency”
    +
  • +
  • Write your plugin
    +
  • +
+ +
+ +

Using NetBeans for development

+
+
    +
  • Download the jMP source from svn, then open and compile the project
    +
  • +
  • Create a new “Module Suite” project (can be any name, this will be your local “collection” of plugins that you create)
    +
  • +
  • In the Suites Properties, under “Libraries”, press “Add Project” and select the jMP project folder.
    +
  • +
  • Open the suite, right-click the “Modules” folder and select “Add new..”
    +
  • +
  • For “Project Name” enter an all-lowercase name for your plugin without spaces like my-library
    +
  • +
  • Make sure the “Project Location” is inside the module suite folder and press “Next”
    +
  • +
  • Enter the base java package for your plugin in “Code Name Base” like com.mycompany.plugins.mylibrary
    +
  • +
  • Enter a “Module Display Name” for your plugin like “My Library”
    +
  • +
  • Check the “Generate XML Layer” checkbox
    +
  • +
  • Press Finish
    +
  • +
  • To use core jMP or jME3 functions, add “jMonkeyPlatfom Core” and “jMonkeyPlatform Core jME3” via “Module Properties→Library→Add Dependency”
    +
  • +
  • Write your plugin
    +
  • +
+ +
+ +

jMP Contributions Update Center

+
+ +

+If you want your plugin to appear in the “jMP Contributions Update Center” so users can download, install and update it easily via the plugin manager, you can host your plugin in the contributions update center svn repository. The contributions update center is based on a googlecode project for contributed plugins which will be automatically compiled, version-labeled and added to the contributions update center like the core jMP plugins. +

+ +

+
+ +To add your plugin to the repository, do the following: +

+
    +
  • Make sure the plugin is part of a “Module Suite” and that its located in the folder of the suite (this saves you from problems with the svn and local version not being configured the same)
    +
  • +
  • In “Module Properties→Sources” set the “Source Level” to 1.5 if possible (jMP is compatible to Java 1.5)
    +
  • +
  • In “Module Properties→API Versioning” set a specification version for your plugin (like 0.8.1)
    +
  • +
  • Set the “implementation version” to “0” and select “append implementation versions automatically”
    +
  • +
  • Ask the managers or developers for access to the gc project
    +
  • +
  • Commit only the module project to trunk:
    +
      +
    • Right click the Plugin Project and select “Versioning → Import into Subversion Repository”
      +
    • +
    • Enter in the URL field
      +
    • +
    • Enter your googlecode username and password and press “Next”
      +
    • +
    • Check that the “Repository Folder” is trunk/mypluginfolder and enter an import message
      +
    • +
    • Press “Finish”
      +
    • +
    +
  • +
+ +

+ +And thats it, from now on each time you commit changes to your module it will be built and added to the contributions center automatically and the version number will be extended by the svn revision number (e.g. 0.8.1.1234) + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-2.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-2.png new file mode 100644 index 000000000..d15f07472 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-2.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-3.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-3.png new file mode 100644 index 000000000..5accbc2ce Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-3.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-4.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-4.png new file mode 100644 index 000000000..dfb9e4dd7 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-4.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-5.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-5.png new file mode 100644 index 000000000..b53a41eab Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-docu-5.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-sceneexplorer-add.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-sceneexplorer-add.jpg new file mode 100644 index 000000000..3884c1c27 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/jmonkeyplatform-sceneexplorer-add.jpg differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/material-editor.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/material-editor.png new file mode 100644 index 000000000..850d6fb29 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/material-editor.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/material_editing.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/material_editing.html new file mode 100644 index 000000000..cbcaae7e0 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/material_editing.html @@ -0,0 +1,108 @@ + +

The Material Editor

+
+ +
+ +

Materials

+
+ +

+ +The jMonkeyEngine uses a special Material format, which comes in .j3m files. You use .j3m files to store sets of material properties that you use repeatedly. This enables you write one short line of code that simply loads the presets from a custom j3m file. Without a .j3m file you need to write several lines of material property setters every time when you want to use a non-default material. + +

+ +
+ +

Creating .j3m Materials

+
+ +

+ +

+ +

+To create new .j3m files, +

+
    +
  1. Right-click the assets/Materials directory and choose New… > Other.
    +
  2. +
  3. In the New File Wizard, choose Material > Empty Material File, and click Next.
    +
  4. +
  5. Give the file a name, for example mat_wall for a wall material.
    +
  6. +
  7. A new file mat_wall.j3m is created in the Materials directory and opens in the Material Editor.
    +
  8. +
+ +

+ +You can edit the source of the material, or use the user-friendly visual editor to set the properties of the material. Set the properties to the same values as you would otherwise specify with setters on a Material object in Java code: +

+
Material mat_wall = new Material(
+    assetManager, "Common/MatDefs/Light/Lighting.j3md");
+mat_wall.setTexture("DiffuseMap", 
+    assetManager.loadTexture("Textures/wall.png"));
+mat_wall.setTexture("NormalMap", 
+    assetManager.loadTexture("Textures/wall-normals.png"));
+mat_wall.setFloat("Shininess", 5f);
+

+The source code of the j3m file is always accessible and can be modified in the “source” tab of the editor. +

+ +
+ +

Using .j3m Materials

+
+ +

+ +

+ +

+When the material is ready and saved into your projects assets directory, you can assign the .j3m to a Geometry. +

+ +

+In the jMonkeyPlatform +

+
    +
  1. Open the SceneExplorer window
    +
  2. +
  3. Select the .j3o file in the Project window to view it in the SceneExplorer
    +
  4. +
  5. In the SceneExplorer, click the geometry to which you want to assign the material.
    +
  6. +
  7. Open the Properties window
    +
  8. +
  9. Assign the .j3m material to the .j3o in the Properties>Geometry>Material section
    +
  10. +
  11. Save the j3o and load it into you game.
    +
  12. +
+ +

+ +Or in your Java code +

+
    +
  • Use a loader and a setter to assign the material to a Geometry
    +
  • +
+
mywall.setMaterial(assetManager.loadAsset( "Materials/mat_wall.j3m"));

+ +

+See also +

+ + +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html new file mode 100644 index 000000000..9ff4db286 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html @@ -0,0 +1,169 @@ + +

jMonkeyPlatform: Importing and Viewing Models

+
+ +

+ +JMonkeyPlatform imports models from your project and stores them in the assets folder. The imported models are converted to a jME3 compatible binary format called .j3o. Double-click .j3o files in the jMonkeyPlatform to display them in the SceneViewer, or load them in-game using the AssetManager. +

+ +

+Presently, is the preferred modelling tool for jME3 as it is also Open-Source Software and an exporter for OgreXML files exists. Note that the OgreXML exporter is not yet compatible with Blender 2.5alpha! +

+ +

+Also, see this on importing models. +

+ +
+ +

Installing the OgreXML Exporter in Blender

+
+ +

+ +jMonkeyPlatform includes a tool to install the correct exporter tools in Blender to export OgreXML files. To install the exporter, do the following: + +

+
    +
  1. Select “Tools”→“OgreXML”→“Install Blender OgreXML” in the jMonkeyPlatform Menu
    +
  2. +
  3. If you are presented a filechooser, select the folder where your blender scripts reside
    +
  4. +
  5. Press “Install” in the window that opens
    +
  6. +
+ +
+ +

Importing and Viewing a Model

+
+ +
+ +

Using the Model Importer Tool

+
+ +

+jMonkeyPlatform includes a model importer tool that allows you to preview and import supported models into your jMonkeyEngine3 project. +

+ +

+ + + +

+
    +
  1. Select the project you want to import your model to
    +
  2. +
  3. Click the “Import Model” button in the toolbar
    +
  4. +
  5. Click “open model..” and select the main model file
    +
  6. +
  7. Check the preview and file list and press “Next”
    +
  8. +
  9. Check and change the import path if necessary
    +
  10. +
  11. If you want to copy the original model files as well, check the checkbox
    +
  12. +
  13. Press “finish”
    +
  14. +
+ +

+ +The model is converted to j3o and all necessary files are copied to the project assets folder. If you have specified the corresponding option, all original model files will also be copied to your assets folder. +

+ +
+ +

Using the model files directly

+
+ +

+ + +

+
    +
  1. Create a separate folder for each model in the assets folder of your project.
    +
  2. +
  3. Export the model from Blender as OgreXML into its subfolder in the asset folder of your project,
    +
  4. +
  5. Make sure that the OgreXML material file has the same name as the exported mesh or scene file!
    +
  6. +
  7. In the Projects Explorer Assets node, select the model that you want to import.
    +
  8. +
  9. Double-click the model or right-click and select “Convert to JME binary” from the context-menu.
    +
  10. +
  11. In the Projects Explorer Assets node you should see your model j3o file.
    +
  12. +
  13. Double-click it to view it in the SceneViewer.
    +
  14. +
  15. Click on the lightbulb to turn on the light if you cannot see your model
    +
  16. +
+ +

+ +Note: It is important that you copy the model file and its textures to the correct assets folder before creating the j3o file because the paths for textures (and possibly other things) will be stored as absolute (to the assets folder root) when you convert that model. This means the texture location should not change after the import. +

+ +
+ +

Working With a Model

+
+
    +
  • Open Windows>SceneExplorer to view sub-nodes of the model
    +
  • +
  • Open Windows>Properties to view the properties of the model's nodes.
    +
  • +
  • Click the cube button in the SceneViewer to toggle between Wireframe mode and Textured mode.
    +
  • +
  • Click the lightbulb to view Materials that require a light source
    +
  • +
+ +
+ +

Notes About Model Assets

+
+ +

+ +The original OgreXML .mesh.xml, .scene, .material and .skeleton.xml model files will not be included in the distribution assets.jar file of your distributed game, they are only available in the assets folder so you are able to recreate the .j3o file from the original if you ever come to change it in blender and have to export it again. +

+ +
+ +

About the SceneViewer and SceneExplorer window

+
+ +

+ +The SceneViewer and SceneExplorer windows are shared among plugins to save system resources. This means that you will have to keep an eye on what plugin is using the scene right now and what you are actually modifying in these windows. +

+ +

+Most plugins will deliver their own UI elements to modify the scene so the SceneExplorer is more of a global tool. The simple SceneComposer however heavily relies on its functions as other plugins might too in the future. +

+ +
+ +

About the projects AssetManager

+
+ +

+Each jMP project has its own internal AssetManager that has the projects assets folder registered as a FileLocator. When the project is run, the assets folder is compressed into a jar file and added to the projects main jar classpath. This way the editors in jMP and the running game have the same asset folder structure. +

+ +

+You might wonder why jMP requires you to copy the model that is to be converted to j3o into the assets folder before. The Model Import Tool also copies the model and associated files to the project directory before converting. To load the model it needs to be in a folder (or jar etc..) that belongs to the projects AssetManager root. To load a model from some other folder of the filesystem, that folder would have to be added to the AssetManager root. If every folder that contains a model was in the root of the AssetManager, all textures named “hull.jpg” for example would be the same for the AssetManager and it would only deliver the texture of the first model folder that was added. +

+ +

+To have a valid jME3 object, the paths to textures and other assets belonging to the model have to be read with the correct, final path that can then be stored in the j3o object. The j3o object will use those paths when it is loaded with the AssetManager and it requires the AssetManager to deliver the assets on those paths, this is why the folder structure while converting has to be the same as when loading. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/netbeans_code_completion.png b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/netbeans_code_completion.png new file mode 100644 index 000000000..f6bd6b60e Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/netbeans_code_completion.png differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/project_creation.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/project_creation.html new file mode 100644 index 000000000..5fd06ec58 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/project_creation.html @@ -0,0 +1,259 @@ + +

jMonkeyPlatform: Creating Projects

+
+ +

+ +The jMonkeyPlatform makes it easy to get started with developing 3-D games based on the jMonkeyEngine. +

+ +
+ +

Creating a New jMonkeyEngine Project

+
+
    +
  1. Choose File > New Project from the main menu.
    +
  2. +
  3. In the New Project Wizard, select the template JME3 > Basic Game
    +
  4. +
  5. Click next to specify a project name, and the path where to store your new project.
    +
  6. +
  7. Click Finish. A skeleton application is created and opens in the Project Explorer.
    +
      +
    • This basic jme3 application is based on the SimpleApplication class to allow an easy start with jme3.
      +
    • +
    • You can click the run button to run it: You will see a jMonkey cube.
      +
    • +
    +
  8. +
+ +
+ +

Project Structure

+
+ +

+ + +

+ +

+Let's have a look at the abstract project structure in the Project Explorer (ctrl-1). + +

+
    +
  • Project Assets node: These directories have been created for you to store your games assets, such as fonts, materials, models, shaders, sounds, and textures. For a newly created project, these directories are empty.
    +
  • +
  • Source Packages node: This is where you manage your packages and classes. For a newly created project, it contains one package and one class, Main.java. Double click Main.java to open it in the editor.
    +
  • +
  • Libraries node: An overview of all libraies on your game's classpath. The classpath is already set-up for the jme3 framework (including LWJGL, JOGG, JOAL, JOGL, etc).
    +
  • +
+ +
+ +

Directory Structure

+
+ +

+ +Now let's have a look at the project's file structure in the File Explorer (ctrl-2). This explorer shows the physical directory structure on your hard drive. + +

+
    +
  • assets – This directory corresponds to the Project Assets node. It is needed for the assetManager. This is the recommended internal structure:
    +
      +
    • assets/Interface
      +
    • +
    • assets/MatDefs
      +
    • +
    • assets/Materials
      +
    • +
    • assets/Models
      +
    • +
    • assets/Scenes
      +
    • +
    • assets/Shaders
      +
    • +
    • assets/Sounds
      +
    • +
    • assets/Textures
      +
    • +
    +
  • +
  • src – This directory corresponds to the Source Packages node. Your sources code goes here.
    +
  • +
  • nbproject – This is meta data used by the jMonkeyPlatform (don't edit).
    +
  • +
  • build.xml – This is an Ant build script that is hooked up to the clean/build/run/test actions in the jMonkeyPlatform. It loads a default build script, and allows you to further customize the build process. The Ant script also assures that you are able to clean/build/run/test your application outside of the jMonkeyPlatform – e.g. from the command line.
    +
  • +
  • build – This directory contains the compiled classes. (Will be generated by the jMonkeyPlatform when you build the project.)
    +
  • +
  • dist – This directory contains the executable JAR files. (Will be generated by the jMonkeyPlatform when you build the project.)
    +
  • +
  • test – The jMonkeyPlatform will store JUnit tests here if you create any. (Optional.)
    +
  • +
+ +
+ +

Working With Your Game Project

+
+ +
+ +

Project Configuration

+
+ +

+ +Right-Click the project to open the Project properties. +

+
    +
  • In the Run section, specify the main class of your project.
    +
  • +
  • In the Run section, you can optionally configure JVM options and command line parameters.
    +
  • +
  • In the Application section, specify the game title (by default the game will be named BasicGame).
    +
  • +
  • In the Application section, specify the vendor name (your name), a short description, your project's homepage, and a splash screen.
    +
  • +
+ +
+ +

Adding external jar libraries

+
+ +

+ +Add the library to the global library list: +

+
    +
  • Select Tools→Libraries in the main menu.
    +
  • +
  • Click “New Library”, enter a name for the library and press OK
    +
  • +
  • In the “Classpath” tab, press “Add JAR/Folder” and select the jar file(s) needed for the library
    +
  • +
  • In the “JavaDoc” tab, press “Add ZIP/Folder” and select the javadoc for the library (zipped or folder)
    +
  • +
  • In the “Sources” tab you can select a folder or jar file containing the source files of the library if available
    +
  • +
  • Press OK
    +
  • +
  • Right-Click your project
    +
  • +
+ +

+ +Add the library to a project: +

+
    +
  • Right-Click your project and select “Properties”
    +
  • +
  • Select “Libaries” on the left and then press “Add Library”
    +
  • +
  • Select the library from the list and press OK
    +
  • +
+ +

+ +Thats it, your project can now use the external library. +

+ +
+ +

Development Process

+
+
    +
  • Creating new files and packages: Select the Source Packages node (or any of its subnodes), and press ctrl-N (File>New File): Use the New File wizard to create new Java classes, Java packages, Java beans, Swing forms, Junit files, JME3 Materials and Models, and many more.
    +
  • +
  • Editing files: Open the Projects Explorer and double-click a Java file from the Source Packages to open it in the Editor. The jMonkeyPlatform Editor assists you in many ways, including Syntactic and semantic code coloring, code completion, and javadoc. (More...)
    +
  • +
  • Adding Assets:
    +
      +
    • You can import models, scenes, and materials as assets into your project.
      +
    • +
    • To add sound files and images, use your operating system's file explorer and copy the files into your project's asset directory.
      +
    • +
    +
  • +
  • ToDo List: The tasks window automatically lists all lines containing errors and warnings, and all lines that you have marked with comment keywords such as FIXME, @todo, TODO.
    +
  • +
  • Integrated tools: Debugging, Testing, Profiling.
    +
  • +
+ +
+ +

Clean, Build and Run Cycle

+
+ +

+ + + +

+
    +
  • Right-Click the project and use the context-menu to clean all generated classes and JARs.
    +
  • +
  • Right-Click individual files with a main method to build and run them. (Shift-F6)
    +
  • +
  • Press the Run button (green arrow in the toolbar) to build and run the project. (F6)
    +
  • +
+ +

+ +More than one project open? The toolbar buttons and the F-keys are bound to the main project, which is shown in bold in the Project Explorer. Right-click a project and select Set As Main Project to make it respond to the toolbar buttons and F-keys. +

+ +

+Worried About Proprietary Lock-in? You are never locked into the jMonkeyPlatform: At any time, you can change into your project directory on the command line, and clean, build, and run your project, using non-proprietary Apache Ant commands: +

+
ant clean; ant jar; ant run;
+ +
+ +

Application Deployment

+
+
    +
  • You can deploy your game as desktop application (JAR), browser applet, WebStart (JNLP), or on the Android platform. (More...)
    +
  • +
+ +
+ +

Running Sample Projects

+
+
    +
  1. Choose File > New Project from the main menu.
    +
  2. +
  3. In the New Project Wizard, select JME3 > JME3 Tests
    +
  4. +
  5. Click next to pick a path where to store the JME3Tests project.
    +
  6. +
  7. Click Finish. The sample project opens.
    +
  8. +
  9. Right-click the JME3Tests project and choose Run.
    +
      +
    • Use the TestChooser to try out the included jMonkeyEngine demos!
      +
    • +
    +
  10. +
  11. Open the Source Packages node of the sample's project.
    +
      +
    • Browse a demo's source code to learn how a feature is implemented.
      +
    • +
    • Feel free to modify the code samples and experiment! If you break something, you can always recreate the packaged samples from the JME3 Tests template.
      +
    • +
    +
  12. +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/scene_composer.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/scene_composer.html new file mode 100644 index 000000000..2535fb0e9 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/scene_composer.html @@ -0,0 +1,198 @@ + +

Scene Composer

+
+ +

+ +SceneComposer allows you to edit scenes stored in j3o files and add content or modify existing content. Please note that the Scene Composer and Explorer are a work in progress and will provide more powerful functions in the future. Also other plugins will allow creation of more specific game type scenes in jMP. +

+ +

+Most buttons in the SceneComposer have tooltips that appear when you hover the mouse over the button for a short while. +

+ +
+ +

Mouse/Cursor Controls

+
+
    +
  • Left-click and drag to rotate the camera around the cam center
    +
  • +
  • Right-click and drag to move the cam center
    +
  • +
  • Scoll the mouse wheel to zoom in/out the cam center
    +
  • +
  • Left-click a geometry to select it
    +
  • +
  • Right-click a geometry to place the cursor
    +
  • +
+ +

+ +In the SceneComposer toolbar are buttons to snap the camera to the cursor, snap the cursor to the selection and etc. +

+ +
+ +

Creating a scene file

+
+ +

+ +jMP stores the scene in a j3o file, this binary file contains the whole scenegraph including all settings for spatials, materials, physics, effects etc. Textures are not stored in the j3o file but as absolute locators to the textures. +

+ +

+To create a blank scene file do the following: +

+
    +
  1. Right click the “Scenes” folder in your Project Assets and select “New→Other”
    +
  2. +
  3. Select “Scene” to the left then select “Empty jME3 Scene” and press “Next”
    +
  4. +
  5. Enter a file name for your scene like “MyScene” and press “OK”
    +
  6. +
+ +
+ +

Loading the scene

+
+ +

+ + +

+ +

+To open a scene +

+
    +
  1. In the Project Explorer, right-click the *.j3o file of the scene
    +
  2. +
  3. Choose “Open in SceneComposer”
    +
  4. +
+ +

+ +Now the SceneComposer window opens at the bottom and displays the scene in the SceneViewer. The SceneExplorer displays the contained scene graph as a tree and when selecting a node, you can edit the properties of the corresponding scene graph object in the Properties window. +

+ +

+For now, you only see the cursor in the SceneViewer and a single node (the root node of the scene) in the SceneExplorer. +

+ +
+ +

Adding light to the scene

+
+
    +
  1. Select the root node in the SceneExplorer
    +
  2. +
  3. Select “Directional Light” in the SceneComposer window
    +
  4. +
  5. Press the ”+” button in the SceneComposer window
    +
  6. +
+ +

+ +A directional light has been added to your scene, you can see it in the SceneExplorer. +

+ +
+ +

Adding effects etc. to the scene

+
+ +

+ +You can add a variety of special objects with the SceneComposer, including lights, effects, audio etc. + +

+
    +
  1. Select root Node in the SceneExplorer
    +
  2. +
  3. Select the object type in the list displayed in the SceneComposer window
    +
  4. +
  5. Press the ”+ cursor” button in the SceneComposer window
    +
  6. +
+ +
+ +

Adding Models to the scene

+
+ +

+ + +

+ +

+You can directly import 3d models to your scene so that they will be part of your scene file. To be able to import for example an OgreXML file, first export it from your 3D editor to a separate folder in the assets folder of your project (e.g. assets/Models/MyModel/). + +

+
    +
  1. Place the SceneComposer cursor where you want the model to be
    +
  2. +
  3. Select the parent Node for the model in the SceneExplorer
    +
  4. +
  5. In the Project Explorer right-click the model file you want to import
    +
  6. +
  7. Choose “Add to SceneComposer”
    +
  8. +
+ +

+ +Note that when importing a model the texture paths are stored absolute, so the folder you import the model from will later only be a textures folder because the original model file is not included in the release. +

+ +

+Also note that when adding models this way, changes in the original model file will not be reflected in the scene file as its a complete copy of the original file. If you change the original model, delete the models node from the scene and import it again. +

+ +
+ +

Linking Models to the scene

+
+ +

+ +You can also link models/objects into your scene, this way they are reloaded dynamically from the other/original file. + +

+
    +
  1. Place the SceneComposer cursor where you want the model to be
    +
  2. +
  3. Select the parent Node for the model in the SceneExplorer
    +
  4. +
  5. In the Project Explorer right-click the model file you want to link
    +
  6. +
  7. Choose “Link in SceneComposer”
    +
  8. +
+ +

+ +Note that when linking objects this way, you cannot edit them as part of the scene. To change the model you have to change the original j3o file. +

+ +

+Also note that although it its possible to directly link external model files (OgreXML, OBJ etc.), this is not recommended. Convert the original file to a j3o file by right-clicking it and selecting “Convert to jME Binary” before linking it. This is required because the original model files are not included in the release version of the application. +

+ +
+ +

Saving the Scene

+
+
    +
  1. When a scene has been changed, press the “save” button in the main toolbar or press [Ctrl-S] / [Apple-S] to save it.
    +
  2. +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/scene_explorer.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/scene_explorer.html new file mode 100644 index 000000000..f6fbe0a89 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/scene_explorer.html @@ -0,0 +1,65 @@ + +

jMonkeyPlatform: Scene Explorer

+
+ +
+ +

About the SceneExplorer window

+
+ +

+The SceneExplorer gives you a structural overview of the currently edited scene and is active among all plugins +

+ +

+Most plugins will deliver their own UI elements to modify the scene so the SceneExplorer is more of a global tool. The simple SceneComposer however heavily relies on its functions as other plugins might too in the future. + +

+ +
+ +

Using the SceneExplorer

+
+ +

+ + +The SceneExplorer displays Nodes in a tree that represents the tree of Spatials in your scene. Spatial controls, lights and geometry meshes are also displayed in the tree. +

+ +
+ +

Editing Objects in the scene

+
+
    +
  1. Select a node in the SceneExplorer window (Open via Window→SceneExplorer if not open)
    +
  2. +
  3. Edit the node in the Properties window (Open via Window→Properties if not open)
    +
  4. +
  5. You can rename a Spatial by right clicking it or by slowly double-clicking the node
    +
  6. +
+ +
+ +

Reorganizing Objects in the scene

+
+
    +
  1. You can cut, copy and paste Nodes in the SceneExplorer with the normal keyboard commands or the right-click menu of the Nodes
    +
  2. +
  3. You can move single object within the SceneExplorer tree by dragging&dropping them
    +
  4. +
+ +
+ +

Adding Objects to the scene

+
+ +

+ +Right-click a Spatial or Node in the SceneExplorer to add other Spatials like ParticleEmitters or Lights, you can also add UserData to a Spatial that can be read during runtime. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/terrain_editor.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/terrain_editor.html new file mode 100644 index 000000000..aaca522b8 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/terrain_editor.html @@ -0,0 +1,162 @@ + +

Overview

+
+ +

+The terrain lets you create, modify, and paint terrain. +

+ +
+ +

Controls

+
+ +

+Terrain controls are the same as the Scene Composer, you rotate the camera with the left mouse button and pan the camera with the right mouse button. Until you select one of the terrain tools in the toolbar, then the controls change for that tool. Then left mouse button will use that tool: painting, raising/lowering terrain, etc. The right mouse button might do something, depending on the tool. +

+ +
+ +

Creating Terrain

+
+ +

+To create terrain, first select a node (probably your root node) in your scene. Then click the add terrain button. +This will pop up the Create Terrain wizard that will walk you through the steps for creating terrain. Make sure you decide now how large you want your terrain to be and how detailed you want the textures to be as you cannot change it later on! +

+ +
+ +
Step 1: Terrain Size
+
+ +

+Here you determine the size of your terrain, the total size and the patch size. You should probably leave the patch size alone. But the total size should be defined; this is how big your terrain is. +

+ +
+ +
Step 2: Heightmap
+
+ +

+Here you can select a heightmap generation technique to give you a default/random look of the terrain. You can also select a heightmap image to pre-define how your terrain looks. +By default, it will give you a flat terrain. +

+ +
+ +
Step 3: Alpha Image Detail
+
+ +

+This step determines how large the alpha blend images are for your terrain. The smaller the alpha image, the less detailed you can paint the terrain. Play around with this to see how big you need it to be. Remember that terrain does not have to be that detailed, and is often covered by vegetation, rocks, and other items. So having a really detailed texture is not always necessary. +

+ +
+ +

Modifying Terrain

+
+ +

+Right now there are two terrain modification tools: raise and lower terrain. +There are two sliders that affect how these tools operate: +

+
    +
  • Radius: how big the brush is
    +
  • +
  • Weight/Height: how much impact the brush has
    +
  • +
+ +

+ +Once a tool is selected, you will see the tool marker (now an ugly wire sphere) on the map where your mouse is. Click and drag on the terrain to see the tool change the height of the terrain. +

+ +
+ +

Painting Terrain

+
+ +

+Your terrain comes with one diffuse default texture, and you can have up to 12 total diffuse textures. It also allows you to add normal maps to each texture layer. +All of the textures can be controlled in the Texture Layer table by clicking on the textures. +

+ +

+There are two sliders that affect how the paint tool operates: +

+
    +
  • Radius: how big the brush is
    +
  • +
  • Weight/Height: how much impact the brush has
    +
  • +
+ +
+ +
Adding a new texture layer
+
+ +
+ +
Changing the diffuse texture
+
+ +
+ +
Adding a normal map to the texture layer
+
+ +
+ +
Removing a normal map from the texture layer
+
+ +
+ +
Changing the texture scale
+
+ +

+The field in the table to the right of the diffuse and normal textures for your texture layer is the scale. Changing that value changes the scale of the texture. +You will notice that the scale changes when you switch between Tri-Planar and normal texture mapping. Tri-planar mapping does not use the texture coordinates of the geometry, but real world coordinates. And because of this, in order for the texture to look the same when you switch between the two texture mapping methods, the terrain editor will automatically convert the scales for you. +Essentially if your scale in normal texture coordinates is 16, then for tri-planar gets converted like this: 1/terrainSize/16 +

+ +
+ +
Tri-planar texture mapping
+
+ +

+Tri-planar texture mapping is recommended if you have lots of near-vertical terrain. With normal texture mapping the textures can look stretched because it is rendered on the one plane: X-Z. Tri-planar mapping renders the textures on three planes: X-Z, X-Y, Z-Y; and blends them together based on what plane the normal of the triangle is facing most on. +This makes the terrain look much better, but it does have a performance hit! +Here is an article on tri-planar mapping: +

+ +
+ +
Total texture count
+
+ +

+Terrain will support a maximum of 12 diffuse texture. And a combined total of 13 diffuse and normal maps. +Most video cards are limited to 16 texture units (textures), and 3 are used behind the scenes of the terrain material for alpha blending of the textures, so you are left with a maximum of 13 textures. +

+ +
+ +

Generating Terrain Entropies for LOD

+
+ +

+If you are using the recommended PerspectiveLodCalculator for calculating LOD levels of the terrain, then you will want to pre-generate the entropy levels for the terrain. This is a slow process. If they are not pre-generated, the LOD control will generate them for you, but this will lag the user when they load the scene, and the terrain will flicker. +Use the 'Generate Entropies' button to pre-generate the entropies for the terrain, they will be saved with it. +Note that whenever you modify the height of the terrain, you should re-generate the entropies. Of course, don't do this every time, but maybe just before you are ready to send the map out for testing. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/troubleshooting.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/troubleshooting.html new file mode 100644 index 000000000..dbf88e722 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/troubleshooting.html @@ -0,0 +1,17 @@ + +

Troubleshooting jMonkeyEngine3 SDK

+
+ +
+ +

Specifying the JDK location

+
+ +

+If jMonkeyPlatform cannot find a valid JDK although you have it installed you have to specify the location manually. +To do that edit the file jmonkeyplatform.conf in the etc directory of your jMonkeyPlatform installation location. Mac users have to right-click the application and select “Show package contents” and then navigate to Contents/Resources/jmonkeyplatform. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/use_own_jme.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/use_own_jme.html new file mode 100644 index 000000000..4f34f14da --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/use_own_jme.html @@ -0,0 +1,38 @@ + +

How to integrate your own jME3 compile in jMP projects

+
+
    +
  1. +
  2. +
  3. Make your changes
    +
  4. +
  5. Compile jme3 project
    +
  6. +
  7. Go to Tools → Libraries
    +
  8. +
  9. Press “New Library”
    +
  10. +
  11. Name it “jme3-modified”
    +
  12. +
  13. Press “Add Jar/Folder”
    +
  14. +
  15. Select jMonkeyEngine3.jar from the dist dir of the compiled jme3 version
    +
  16. +
  17. Add the src folder of the jme3 project in the “sources” tab
    +
  18. +
  19. Optionally javadoc in the “javadoc” tab
    +
  20. +
  21. Press “OK”
    +
  22. +
  23. Right-click your project and select “Properties”
    +
  24. +
  25. Select “Libraries” to the left
    +
  26. +
  27. Remove the “jme3” library
    +
  28. +
  29. Press “Add Library” and select the “jme3-modified” library
    +
  30. +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/vehicle_creator.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/vehicle_creator.html new file mode 100644 index 000000000..f9aae1914 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/vehicle_creator.html @@ -0,0 +1,53 @@ + +

Vehicle Creator

+
+ +

+ +Best results when car is facing in z direction (towards you) +

+ +

+Usage: +

+
    +
  1. Select a j3o that contains a vehicle model and press the vehicle button (or right-click → edit vehicle)
    +
  2. +
  3. The VehicleCreator automatically adds a PhysicsVehicleControl to the rootNode of the model if there is none
    +
  4. +
  5. Select the Geometry or Node that contains the chassis in the SceneExplorer and press “create hull shape from selected”
    +
  6. +
  7. Select a Geometry that contains a wheel and press “make selected spatial wheel”, select the “front wheel” checkboxes for front wheels
    +
  8. +
  9. Do so for all wheels
    +
  10. +
+ +

+ +New wheels will get the current suspension settings, you can edit single wheels via the SceneExplorer (update VehicleControl if wheels dont show up) or apply settings created with the settings generator to wheel groups. +

+ +

+Press the “test vehicle” button to drive the vehicle, use WASD to control, Enter to reset. +

+ +

+Known Issues: Dont save while testing the vehicle, you will save the location and acceleration info in the j3o. +

+ +

+Code Example to load vehicle: + +

+
//load vehicle and access VehicleControl
+Spatial car=assetManager.loadModel("Models/MyCar.j3o");
+VehicleControl control=car.getControl(VehicleControl.class);
+rootNode.attachChild(car);
+physicsSpace.add(control);
+ 
+//then use the control to control the vehicle:
+control.setPhysicsLocation(new Vector3f(10,2,10));
+control.accelerate(100);
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/version_control.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/version_control.html new file mode 100644 index 000000000..1da736cba --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/sdk/version_control.html @@ -0,0 +1,214 @@ + +

jMonkeyPlatform: Version Control

+
+ +

+ +Whether you work in a development team or alone: File versioning is a handy method to keep your code consistent, compare files line-by-line, and even roll back unwanted changes. This documentation shows you how to make the most of the jMonkeyPlatform's integrated version control features for Subversion, Mercurial, and CVS. +

+ +

+
+ +

+ +

+Note: Since the jMonkeyPlatform is based on the NetBeans Platform framework, you can learn about certain jMonkeyPlatform features by reading the corresponding NetBeans IDE tutorials (in the “see also links”). +

+ +
+ +

Version Control Systems

+
+ +

+ +The jMonkeyPlatform supports various Version Control Systems such as Subversion, Mercurial, and CVS. No matter which of them you use, they all share a common user interface. +

+ +

+You can use file versioning alone or in a team. The advantages are that you can keep track of changes (who did it, when, and why), you can compare versions line-by-line, you can revert changes to files and lines, merge multiple changes to one file, and you can even undelete files. +

+ +
+ +

Creating a Repository (Upload)

+
+ +

+ +Requirements: +

+
    +
  • You must have a project that you want to version.
    +
  • +
  • You must have version control software installed (Subversion, Mercurial, or CVS) and have initialized a repository.
    +
      +
    • Tip: For Subversion, the init command looks like this example: svnadmin create /home/joe/mysvnrepo
      +
    • +
    +
  • +
  • The computer where the repository is to be hosted must be available in your network, or you will only be able to use your repo locally.
    +
      +
    • Tip: Hosts such as SourceForge, GoogleCode, dev.java.net offer free version control services for open-source projects.
      +
    • +
    +
  • +
+ +

+ +Now you create a repository to store your project's files. + +

+
    +
  1. In the jMonkeyPlatform, right-click the project in the Projects window and choose Versioning > Import Into CVS/Subversion Repository (or initialize Mercurial Project, respectively).
    +
      +
    • Tip: If you haven't evaluated yet which system to choose, start with Subversion for now.
      +
    • +
    +
  2. +
  3. Go through the wizard and fill in the fields to set up the repository.
    +
  4. +
+ +
+ +

Checking Out a Repository (Download)

+
+ +

+ +You and your team mates check out (download) the repository to their individual workstations. + +

+
    +
  1. Go to the Team menu and choose Subversion > Checkout (or CVS/Mercurial>Checkout respectively)
    +
  2. +
  3. Fill in your repo data into the wizard and click Finish.
    +
      +
    • A typical repository URL looks like this example:
      +
    • +
    • If you want to be able to submit changes, you must have a username and password to this repository. Otherwise leave these fields blank.
      +
    • +
    +
  4. +
  5. The repository is downloaded and stored in the location you chose.
    +
  6. +
  7. Use the File > Open Project menu to open the checkout as project and start working.
    +
      +
    • If the checkout is not recognized you need to choose File > New Project from Existing Sources
      +
    • +
    +
  8. +
+ +

+ +
+ +Of course you can also check out existing repositories and access code from other open-source projects (e.g. SourceForge, GoogleCode, dev.java.net). +

+ +
+ +

Updating and Committing Changes (Send and Receive)

+
+ +

+ +Receiving the latest changes from the team's repository is referred to as updating. Sending your changes to the team's repository is refered to as commiting. + +

+
    +
  1. Before making changes, right-click the project and select Subversion > Update to make sure you have the latest revision.
    +
      +
    • Get in the habit of updating regularly, always before you edit a version controlled file. It will spare you much grief.
      +
    • +
    +
  2. +
  3. After making changes to the project, make certain your change did not break anything.
    +
      +
    1. Update, build, run, test.
      +
    2. +
    3. Look at the red/green/blue marks in the editor to review what you have deleted/added/changed. Click the marks to review all differences in a file.
      +
    4. +
    5. Choose Subversion > Show Changes to see all files that were recently changed – by you and other team members.
      +
    6. +
    7. Update again in case your team mates made changes while you were reviewing.
      +
    8. +
    +
  4. +
  5. If there are no conflicts and you want to commit your changes, choose Subversion > Commit from the menu.
    +
  6. +
  7. Write a commit message describing what you changed.
    +
      +
    • Remember, you are writing “a message to your future self”. Never write redundant stuff like “I changed something”.
      +
    • +
    +
  8. +
+ +
+ +

Comparing and Reverting Changes

+
+
    +
  • If you and another committer edited the same line, there is a conflict, and the jMonkeyPlatform will show an error message.
    +
      +
    • Right-click a file Choose Subversion > Resolve Conflict
      +
        +
      1. Compare the conflicting versions. Press the buttons to accept or reject each change individually.
        +
      2. +
      3. After the resolver shows green, save the resolution.
        +
      4. +
      5. Build and test the resolution, update, and commit.
        +
      6. +
      +
    • +
    +
  • +
  • Right-click a file and choose Subversion > Search History.
    +
      +
    • You can inspect a file's history and see who changed what, why, and when.
      +
    • +
    • You can roll back a file to a historic version if necessary.
      +
    • +
    +
  • +
  • In general, you can choose Subversion > Diff for any file to see two versions of a file next to each other.
    +
  • +
+ +
+ +

No Version Control? Local History!

+
+ +

+ +If you do not use any version control, you can still track changes in projects to a certain degree. + +

+
    +
  • Right-click a file or directory and choose Local History to show or revert changes, or undelete files.
    +
  • +
  • You can also select any two files in the Project window and choose Tools > Diff to compare them.
    +
  • +
  • Local History only works for files edited in jMonkeyPlatform Projects (It does not work for other files, e.g. in the Favorites window.)
    +
  • +
+ +

+
+ +See also: + +

+
    +
  • +
  • +
+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey.html new file mode 100644 index 000000000..416c7e37e --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey.html @@ -0,0 +1,114 @@ + +

SpiderMonkey

+
+ +

+SpiderMonkey is a high performance Java networking engine, aiming to provide game developers a stable and efficient networking system. It's also perfectly capable of doing anything other than game networking. SpiderMonkey is part of jME3 and can be found in the src/networking directory. +

+ +

+Author: Lars 'Levia' Wesselius
+ +License:
+ +Blog:
+ +Forum:
+ +
+ +

+ +

+A tutorial trail can be found below, and below that all different aspects of SpiderMonkey are explained. These tutorials are to be updated upon SVN HEAD, so if new features are added in SVN, you should tutorials arriving of them soon. + +

+ +
+ +

Tutorial trail

+ + +

Explanation of SpiderMonkey's inner workings

+
+ +
+ +

Connection protocols

+
+ +

+SpiderMonkey supports both TCP and UDP, and is also extendable to provide others. Possible future protocols may be RUDP, UDP Lite, and SCTP. SCTP will be added in Java 7, and will therefore probably added to SpiderMonkey after it's released. Please note that the language level of SpiderMonkey is 1.5, so it will definitely not be part of the standard API for a few years. +

+ +
+ +

Clients

+
+ +

+SpiderMonkey creates two connections by default. A TCP connection for a reliable connection, and an UDP 'connection' 1) for fast message handling. A problem arises here: these two connections mean that even though there are two connections, there's only one client to represent both the connections. In SpiderMonkey you don't have to worry about that. The server has a client manager which deals with this problem. Upon connecting, clients have to send a ClientRegistration message to link their TCP and UDP connections together. Upon receiving those two messages, server combines the clients into one, and provides this client to you. This means you can call both TCP and UDP methods on the client. If you still want to receive the 'local' client of a connection, you can do so by calling the appropriate messages in the Server class. + +

+ +
+ +

Serializing

+
+ +

+Serializing is an aspect that received a lot of attention. I wanted it to be simple for people to register their own messages, but also be able to register serializers for their own object types. The system works by registering classes to serializers. Generally, a serializer does not exist without a class it can serialize - simply because it doesn't have to: Why have a serializer when there's nothing to serialize. A lot of work has been put into making it as efficient as possible. What can be left out, is left out, and what can optimized, is optimized. +

+ +
+ +
Field serializer
+
+ +

+The default serializer requires some explanation. This serializer serializes all classes that have no (registered) serializer. The field serializer works by saving all fields internally, so it can access them on serialization faster. The fields are taken, and their types are checked. They are put through a serializer again (which serializer depends, of course, on the data type). Then they are ready to be written to the buffer. As you can tell, this is quite a simple serializer, and should be used if your message don't require extra attention. See this tutorial if you want to know how to register your own messages or serializers. + +

+ +
+ +

Service system

+
+ +

+The service system is in fact a tiny system. It's meant to solve a small, but annoying problem. Imagine you have SpiderMonkey as your networking library, and other people have made extra's for it. Excellent, of course, but they may all require different initialization! Perhaps you have to instantiate one yourself by using new, or maybe another works by calling a factory method; the service system exists to avoid that problem. All extras should use this system. Please see the service tutorial on how to use this system. + +

+ +
+ +

Compression

+
+ +

+By default SpiderMonkey supports compressing messages. It's been made to where you have complete freedom over what messages you wish to compress. See this tutorial on how to use these special messages. + +

+ +
+
+
1) +UDP is connectionless
+
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/compression.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/compression.html new file mode 100644 index 000000000..ef06e3f7f --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/compression.html @@ -0,0 +1,37 @@ + +

Compression

+
+ +

+Now this is going to be a real simply tutorial but still I wanted this in a separate article. Why you may ask? Simply because it's a feature that requires some explanation, since it has some caveats that I'll discuss. Also, I'll cover writing your own compression message. +

+ +

+First off - there are two compression types in SpiderMonkey, they are GZip and Zip. Could've added more, but didn't want to have a dependency for just a compression method. Both are used by wrapping your message in the appropriate compression message: + +

+
MyMessage msg = new MyMessage();
+client.send(new GZIPCompressedMessage(msg));
+// or
+client.send(new ZIPCompressedMessage(msg));
+

+ +Really simple, but ZIP requires some explanation. The ZIPCompressedMessage class also has two extra methods; setLevel(int) and getLevel(). These methods are for setting the compression level, where 1 is best compression but slowest, and where 9 is weakest compression but fastest. Please note that 9 is not the so called 'store' ZIP method, which simply stores file in the ZIP, instead of compressing it. This 'store' feature is not in SpiderMonkey since otherwise it would not have been called compression. +

+ +
+ +

Writing your own

+
+ +

+ +Now of course I'd love to see more compression methods in SpiderMonkey, so I'll discuss how to write your own. Let's just take GZIPCompressedMessage as example, since that one is the most straightforward. What I've done, is I've just created a GZIPCompressedMessage which extends CompressedMessage. It does not contain any extra messages, so the GZIPCompressedMessage class is practically 'empty'. The magic happens at the serializer, which is called the GZIPSerializer (you can read about writing your own serializer here). Then I just registered the GZIPSerializer to GZIPCompressedMessage and presto - you're done. Don't forget that in the Serializer you need to use writeClassAndObject first and then compress that data, and for read you'd need to use readClassAndObject after you've uncompressed (inflated) the message. For this to be clear, it may be useful to read . +

+ +

+That's that! Next tutorial we're going to discuss how to use the Service system. +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/connection.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/connection.html new file mode 100644 index 000000000..a17c7a8bd --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/connection.html @@ -0,0 +1,101 @@ + +

Connecting

+
+ +

+This very first tutorial is going to teach you how to open a server and a client, and connect them to eachother. I'll also discuss how connection registration works. Since this is a very simple process in SpiderMonkey, this tutorial will be quite short. +

+ +
+ +

Simple connections

+
+ +

+Creating a server is as simple as doing this: + +

+
Server myServer = new Server(4040, 5050);
+myServer.start();
+

+This initializes and starts a server on TCP port 4040 and UDP port 5050. Now it's time to connect a client: +

+
Client client = new Client("localhost", 4040, 5050);
+client.start();
+

+This initializes and starts a client, and it will immediately connect to localhost, TCP port 4040, and UDP port 5050. In the log, you'll get to see this: +

+
+Sep 16, 2010 11:52:16 AM com.jme3.network.connection.TCPConnection bind
+INFO: [Server#1][TCP] Bound to 0.0.0.0/0.0.0.0:4040
+Sep 16, 2010 11:52:16 AM com.jme3.network.connection.UDPConnection bind
+INFO: [Server#1][UDP] Bound to 0.0.0.0/0.0.0.0:5050
+Sep 16, 2010 11:52:16 AM com.jme3.network.connection.Server start
+INFO: [Server#1][???] Started server.
+Sep 16, 2010 11:52:16 AM com.jme3.network.connection.TCPConnection connect
+INFO: [Client#1][TCP] Connecting to localhost/127.0.0.1:4040
+Sep 16, 2010 11:52:16 AM com.jme3.network.connection.UDPConnection connect
+INFO: [Client#1][UDP] Set target to localhost/127.0.0.1:5050
+Sep 16, 2010 11:52:16 AM com.jme3.network.connection.TCPConnection accept
+INFO: [Server#1][TCP] A client connected with address /127.0.0.1
+Sep 16, 2010 11:52:16 AM com.jme3.network.connection.TCPConnection connect
+INFO: [Client#1][TCP] Connection succeeded.
+
+ +

+ +As you can see, this is a combined log of the client and server. Even though it looks like only a connection has been made, the Client registration has already happened at this point as well. Client registration is necessary so you can call TCP and UDP methods on only one Client instance on the server. You don't have to worry about client registration, since SpiderMonkey does this automatically on connection. + +

+ +
+ +

Connector filters

+
+ +

+You can also filter connections (or connectors as I call them) in SpiderMonkey. You can do this by implementing the ConnectorFilter interface: +

+
public class MyConnectorFilter implements ConnectorFilter {
+   public String filterConnector(InetSocketAddress address) {
+      if (address.isLoopbackAddress()) return "I don't like locals!";
+      return null;
+   }  
+}
+

+ +Return null for no filtering, or a String with the reason if you want to filter this person. +

+ +
+ +

Discover hosts

+
+ +

+SpiderMonkey Clients are also able to discover hosts running in the LAN. This is also a very simple process, and can be done as follows: + +

+
Client client = new Client();
+List<InetAddress> foundHosts = client.discoverHosts(5050, 5000);
+

+ +This starts the host discovery on port 5050, and listens for servers for 5 seconds. Typically, servers respond pretty fast so a few seconds should be enough. To do something with these hosts it's as simple as doing: + +

+
for (InetAddress host : foundHosts) {
+    client.connect(host.getCanonicalHostName(), 4040, 5050);
+}
+client.start();
+

+ +Do note that this would connect to every host found, so this does not work properly, but the idea is that you can configure it the way you want it. Don't forget to start() the client. +

+ +

+This concludes the first tutorial. In the next tutorial, it's time to send and listen for messages! + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/sending_and_receiving_messages.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/sending_and_receiving_messages.html new file mode 100644 index 000000000..910f6e19d --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/sending_and_receiving_messages.html @@ -0,0 +1,65 @@ + +

Sending and receiving messages

+
+ +

+In this tutorial I'm going to cover sending and receiving messages. I'll also explain how to write your own messages. This tutorial assumes you already have a working server-client connection. +

+ +

+Let's start by creating our own message. Later on we'll send this across the network. + +

+
@Serializable()
+public class HelloMessage extends Message {
+   public String hello = "Hello!";
+}
+

+ +This is probably the smallest and simplest message you'll find. This is simply the process of creating a class, extending Message, and adding your fields to it. Also you need the @Serializable annotation, but we'll get to that later. Even though you don't have to extend Message, you generally should since then SpiderMonkey can add client and connection information on receiving. You can also send separate data, but we'll not go into that here - you should just send Messages. +

+ +

+Now let's send this message across the network. We'll send it from the client to the server. + +

+
Serializer.registerClass(HelloMessage.class);
+server.addMessageListener(this, HelloMessage.class);
+client.addMessageListener(this, HelloMessage.class);
+client.send(new HelloMessage());
+

+ +First we've registered the class to the Serializer. This needs to happen on both the client and server, I'll explain why in the next tutorial. Then we add the message listeners for both the server and client, this makes sure we're notified when messages are received. Then we send the message. The message is by default reliable, and so it will be sent over TCP. Now we'll handle it on the server: + +

+
public void messageReceived(Message message) {
+   // This message is of type HelloMessage, so we don't have to check.
+   HelloMessage helloMessage = (HelloMessage)message;
+   System.out.println(helloMessage.hello);
+   helloMessage.hello = "Hi!";
+   message.getClient().send(helloMessage);
+}
+

+ +This simply receives the message, and changes the Hello! to Hi! and sends it back to the client. The client, can of course handle this message however it wants to. +

+ +
+ +

Serializable annotation

+
+ +

+The Serializable annotation is used to determine which serializer you want to use for your message, and which ID you want to register to it. If you specify no ID and no serializer, a ID will be assigned, and the default serializer will be used. The problem with specifying no ID is that you have to have the same order of registration on both the client and server, otherwise serializing will go wrong. It's therefore advisable that you use the id field, if you want to register classes in a different order. +

+ +

+The default serializer is, of course, FieldSerializer, which'll do just fine for just about any message you can throw at it. However, if you wish to serialize your message yourself, all you must do is write your own serializer, and then pass the class to the serializer field in the annotation. For example, this Serializable annotation sets ID to four, and serializer to CustomSerializer (which doesn't exist, mind you). +

+
@Serializable(id=4, serializer=CustomSerializer.class)
+

+That was it! The next tutorial explains how the Serializer system works, and how you can register your own serializers! +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/serializing.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/serializing.html new file mode 100644 index 000000000..142d317f8 --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/serializing.html @@ -0,0 +1,89 @@ + +

Serialization system

+
+ +

+In this lesson you'll learn about a pretty advanced system of SpiderMonkey. Why so early, you may ask; it's because it is an important aspect of SpiderMonkey, that you need to understand to effectively network your games. +

+ +

+Let's start with a general explanation of how the serialization system works. SpiderMonkey's Serializer class is the entry point for everything serializing. Serializing is the act of translating an object into bytes, so it can be transferred over the network. SpiderMonkey does this by having Serializer classes (they extend Serializer itself), and having some static methods available in the Serializer class. A serializer does not exist without a class it can serialize - this means that Serializers need to be registered with a class. For example, the String type is registered to the StringSerializer class. Without the String type being registered, there'd be no instance of StringSerializer. So! Let's get down to business! + +

+ +
+ +

Writing your own serializer

+
+ +

+There is going to be a situation where you need to serialize something yourself, whether you like it or not. We're going through how you're going to do, by writing a entirely new Serializer - please note that this Serializer is not necessary in SpiderMonkey, since SpiderMonkey can serialize Serializable, and InetAddress4 implements Serializable (though it does save a LOT of bytes by doing it yourself). The field that makes an InetAddress4 an InetAddress4 is the IP address, so that's what we're going to serialize. Let's start by going through the basics of extending the Serializer class: + +

+
public class Inet4AddressSerializer extends Serializer {
+   public IOException
+      return null;
+   }
+ 
+   public void writeObject(ByteBuffer buffer, IOException {
+      InetAddress)object;
+   }
+}
+

+ +As you can see, you have to extend Serializer and implement the methods T readObject(ByteBuffer, Class) and writeObject(ByteBuffer, Object). These are the methods that actually do the job. Obviously, writeObject is used when sending, and readObject is used when reading. The next part is just Java coding - you just kind of have to know the API of those objects you're serializing to convert into bytes. This one's really simple though ;) +

+
public class Inet4AddressSerializer extends Serializer {
+   @Override
+   public <T> T readObject(ByteBuffer data, Class<T> c) throws IOException {
+       byte[] address = new byte[4];
+       data.get(address);
+       return (T)Inet4Address.getByAddress(address);
+   }
+ 
+   @Override
+   public void writeObject(ByteBuffer buffer, IOException {
+       Inet4Address address = (Inet4Address)object;
+       buffer.put(address.getAddress());
+   }
+}
+

+ +So now you've got this serializer, and you don't know what to do with it. Well, you need to register it to a class, and what other class would you want to register it to, than Inet4Address? + +

+
+Serializer.registerClass(Inet4Address.class, new Inet4AddressSerializer());
+
+ +

+ +And now you can use the Inet4Address anywhere in a Message! Now we'll test this Serializer, and see if we can get the IP on the other side: +

+
public class AddressMessage extends Message {
+  public Inet4Address addr;
+  public AddressMessage(Inet4Address addr) { this.addr = addr; }
+}
+...
+client.send(new AddressMessage(Inet4Address.getByName("google.com")));
+

+ +Results in a message being received, which prints out as: + +

+
+/66.102.13.106
+
+ +

+ +And there you go, that's the end of this tutorial! +

+ +

+Next tutorial you'll learn about a simple, but powerful feature - compression. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/services.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/services.html new file mode 100644 index 000000000..e6b745afa --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/services.html @@ -0,0 +1,48 @@ + +

Service system

+
+ +

+The service system is meant to create a common way of using plugins. It is a tiny system, on Server and Client level. In this tutorial I'll tell you how to use services, and how to create your own. +

+ +
+ +

Creating services

+
+ +

+Creating services is really easy - you just have to implement the Service interface. Make sure you don't do anything time consuming since the developer may not be expecting it. Services can choose to support Server, Client, or both. To implement this, use the appropriate constructors: + +

+
public class MyExampleService implements Service {
+   public MyExampleService(Server server) {
+      // By adding the constructor with the Server as argument, this service
+      //  now supports servers.
+   }
+ 
+   public MyExampleService(Client client) {
+      // Same goes for client. I could just leave this constructor out, and
+      //  SpiderMonkey would determine this service does not support client mode.
+   }
+}
+
+ +

Using services

+
+ +

+The Server and Client class both have a method called getService(). It retrieves a service based on class name, and instantiates it if necessary. From there you can use the service. +

+ +

+The Service system is not a terribly powerful system, neither does it do safety checks and service management - it just provides a way to commonly manage extensions. +

+ +

+That's it! Next tutorial we're going to have a look at how to use the streaming API. + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/streaming.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/streaming.html new file mode 100644 index 000000000..0bd3d1d4a --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/spidermonkey/tutorial/streaming.html @@ -0,0 +1,54 @@ + +

Streaming service

+
+ +

+The streaming service is meant for situations where you want to transfer files, or other types of data to clients. In this tutorial we'll discuss how it works, and how to use it. +

+ +

+Let's start off with how it works; streaming service uses messages to transfer data. This is done so it doesn't block other messages from being sent, while transferring. First a message is sent the describes the stream. The peer can now choose whether to accept or reject the stream. When the peer accepts, the data will be sent. You have to handle this data yourself. At the end of the stream you get the same message as when the stream was offered, to indicate the end of the stream. +

+ +

+Let's transfer a file to a client: + +

+
StreamingService sService = client.getService(StreamingService.class);
+sService.addStreamListener(this);
+ 
+sService = server.getService(StreamingService.class);
+Client receiver = server.getConnectors().get(0); // Note that you can't use 'client' here, since it's not a connector.
+sService.offerStream(receiver, new StreamMessage(), new FileInputStream("test.txt")); // StreamMessage used here as start and end message, but can be anything to describe the stream on the other end.
+

+ +As you can see, this system uses the Service system. First, we get the client's StreamingService, and register ourselves as a listener. Then we get the server's version of the StreamingService, from which you can stream things. Then we get a connector client (the first one), and send the file via an InputStream. +

+ +

+Now to receive this stuff is simple; + +

+
public boolean streamOffered(StreamMessage message) {
+   // Here you'd normally check the message what this stream is all about, and 
+   // base your acception criteria on that.
+   fileStream = new FileOutputStream("test.txt");
+   return true; // Sure, we'll just accept this message.
+}
+ 
+public void streamDataReceived(StreamDataMessage message) {
+   fileStream.write(message.getData());
+}
+ 
+public void streamCompleted(StreamMessage message) {
+   fileStream.flush();
+   fileStream.close();
+}
+

+ +That was all; simple right? + +

+ +
+

view online version

\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wiki-map.xml b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wiki-map.xml new file mode 100644 index 000000000..65c6084ef --- /dev/null +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wiki-map.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackbrowser-300x166.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackbrowser-300x166.jpg new file mode 100644 index 000000000..7b4eb1292 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackbrowser-300x166.jpg differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackdownload-263x300.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackdownload-263x300.jpg new file mode 100644 index 000000000..1e5cc2648 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackdownload-263x300.jpg differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackimport-300x222.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackimport-300x222.jpg new file mode 100644 index 000000000..e2411f2aa Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackimport-300x222.jpg differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackimport2-300x179.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackimport2-300x179.jpg new file mode 100644 index 000000000..275f75f78 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/10/assetpackimport2-300x179.jpg differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/11/jmonkeyplatform002-300x218.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/11/jmonkeyplatform002-300x218.jpg new file mode 100644 index 000000000..5fa59cf08 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/11/jmonkeyplatform002-300x218.jpg differ diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/11/jmonkeyplatform003-300x117.jpg b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/11/jmonkeyplatform003-300x117.jpg new file mode 100644 index 000000000..827cd4909 Binary files /dev/null and b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/wp-uploads/2010/11/jmonkeyplatform003-300x117.jpg differ diff --git a/sdk/jme3-core/javahelp/wiki_help.properties b/sdk/jme3-core/javahelp/wiki_help.properties new file mode 100644 index 000000000..26ee5f93e --- /dev/null +++ b/sdk/jme3-core/javahelp/wiki_help.properties @@ -0,0 +1,99 @@ +javahelp_path = com/jme3/gde/core/docs/ +wiki_url = http://jmonkeyengine.org/wiki/doku.php/ +wiki_pages = sdk:project_creation,\ +sdk:application_deployment,\ +sdk:asset_packs,\ +sdk:code_editor,\ +sdk:debugging_profiling_testing,\ +sdk:default_build_script,\ +sdk:material_editing,\ +sdk:model_loader_and_viewer,\ +sdk:project_creation,\ +sdk:scene_composer,\ +sdk:scene_explorer,\ +sdk:terrain_editor,\ +sdk:troubleshooting,\ +sdk:use_own_jme,\ +sdk:vehicle_creator,\ +sdk:version_control,\ +sdk:development:extension_library,\ +sdk:development:general,\ +sdk:development:model_loader,\ +sdk:development:scene,\ +sdk:development:sceneexplorer,\ +sdk:development:setup,\ +spidermonkey:tutorial:compression,\ +spidermonkey:tutorial:connection,\ +spidermonkey:tutorial:sending_and_receiving_messages,\ +spidermonkey:tutorial:serializing,\ +spidermonkey:tutorial:services,\ +spidermonkey:tutorial:streaming,\ +jme3:build_jme3_sources_with_netbeans,\ +jme3:bullet_multithreading,\ +jme3:math,\ +jme3:terminology,\ +jme3:the_scene_graph,\ +jme3:webstart,\ +jme3:intermediate:api_feature_mapping,\ +jme3:intermediate:appsettings,\ +jme3:intermediate:best_practices,\ +jme3:intermediate:file_types,\ +jme3:intermediate:headlessserver,\ +jme3:intermediate:my_first_game,\ +jme3:intermediate:optimization,\ +jme3:intermediate:simpleapplication,\ +jme3:intermediate:terrain_collision,\ +jme3:advanced:3d_models,\ +jme3:advanced:animation,\ +jme3:advanced:application_states,\ +jme3:advanced:asset_manager,\ +jme3:advanced:audio,\ +jme3:advanced:bloom_and_glow,\ +jme3:advanced:camera,\ +jme3:advanced:cinematics,\ +jme3:advanced:collision_and_intersection,\ +jme3:advanced:combo_moves,\ +jme3:advanced:custom_controls,\ +jme3:advanced:custom_meshes,\ +jme3:advanced:debugging,\ +jme3:advanced:effects_overview,\ +jme3:advanced:hinges_and_joints,\ +jme3:advanced:hud,\ +jme3:advanced:input_handling,\ +jme3:advanced:j3m_material_files,\ +jme3:advanced:jme3_shaders,\ +jme3:advanced:light_and_shadow,\ +jme3:advanced:localization,\ +jme3:advanced:logging,\ +jme3:advanced:material_definitions,\ +jme3:advanced:materials_overview,\ +jme3:advanced:mesh,\ +jme3:advanced:motion_path,\ +jme3:advanced:multiple_camera_views,\ +jme3:advanced:nifty_gui,\ +jme3:advanced:particle_emitters,\ +jme3:advanced:physics,\ +jme3:advanced:post-processor_water,\ +jme3:advanced:ragdoll,\ +jme3:advanced:shape,\ +jme3:advanced:sky,\ +jme3:advanced:spatial,\ +jme3:advanced:swing_canvas,\ +jme3:advanced:terrain,\ +jme3:advanced:update_loop,\ +jme3:advanced:vehicles,\ +jme3:advanced:walking_character,\ +jme3:advanced:water,\ +jme3:beginner:hello_simpleapplication,\ +jme3:beginner:hello_node,\ +jme3:beginner:hello_asset,\ +jme3:beginner:hello_main_event_loop,\ +jme3:beginner:hello_input_system,\ +jme3:beginner:hello_material,\ +jme3:beginner:hello_animation,\ +jme3:beginner:hello_picking,\ +jme3:beginner:hello_collision,\ +jme3:beginner:hello_terrain,\ +jme3:beginner:hello_audio,\ +jme3:beginner:hello_effects,\ +jme3:beginner:hello_physics \ No newline at end of file diff --git a/sdk/jme3-core/manifest.mf b/sdk/jme3-core/manifest.mf new file mode 100644 index 000000000..91daa7f95 --- /dev/null +++ b/sdk/jme3-core/manifest.mf @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.core/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Install: com/jme3/gde/core/Installer.class +OpenIDE-Module-Layer: com/jme3/gde/core/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/core/Bundle.properties +OpenIDE-Module-Requires: org.netbeans.api.javahelp.Help + diff --git a/sdk/jme3-core/nbproject/build-impl.xml b/sdk/jme3-core/nbproject/build-impl.xml new file mode 100644 index 000000000..ade01000b --- /dev/null +++ b/sdk/jme3-core/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/nbproject/genfiles.properties b/sdk/jme3-core/nbproject/genfiles.properties new file mode 100644 index 000000000..37cb768ae --- /dev/null +++ b/sdk/jme3-core/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=464e557f +build.xml.script.CRC32=41c1873f +build.xml.stylesheet.CRC32=79c3b980@1.31.1.7 +# 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=464e557f +nbproject/build-impl.xml.script.CRC32=21022eaf +nbproject/build-impl.xml.stylesheet.CRC32=261c4bef@1.31.1.7 diff --git a/sdk/jme3-core/nbproject/platform.properties b/sdk/jme3-core/nbproject/platform.properties new file mode 100644 index 000000000..a5e1957da --- /dev/null +++ b/sdk/jme3-core/nbproject/platform.properties @@ -0,0 +1,21 @@ +cluster.path=\ + ${nbplatform.active.dir}/harness:\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/java:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + org.netbeans.modules.apisupport.harness,\ + org.netbeans.modules.apisupport.tc.cobertura,\ + org.netbeans.modules.editor.highlights,\ + org.netbeans.modules.gsf,\ + org.netbeans.modules.gsf.api,\ + org.netbeans.modules.gsfpath.api,\ + org.netbeans.modules.hibernate,\ + org.netbeans.modules.hibernatelib,\ + org.netbeans.modules.hudson.ant,\ + org.netbeans.modules.hudson.maven,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.websvc.saas.codegen.java,\ + org.openide.compat,\ + org.openide.util.enumerations +nbplatform.active=default diff --git a/sdk/jme3-core/nbproject/project.properties b/sdk/jme3-core/nbproject/project.properties new file mode 100644 index 000000000..78700583a --- /dev/null +++ b/sdk/jme3-core/nbproject/project.properties @@ -0,0 +1,9 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +javahelp.hs=core-hs.xml +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +project.license=jme +spec.version.base=0.12.0 diff --git a/sdk/jme3-core/nbproject/project.xml b/sdk/jme3-core/nbproject/project.xml new file mode 100644 index 000000000..782a2ecf1 --- /dev/null +++ b/sdk/jme3-core/nbproject/project.xml @@ -0,0 +1,263 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.core + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.6 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.5 + + + + com.jme3.gde.core.updatecenters + + 0.6 + + + + org.netbeans.api.progress + + + + 1 + 1.16.1.1 + + + + org.netbeans.libs.javacapi + + + + 0.11.1.1 + + + + org.netbeans.modules.autoupdate.services + + 1.16.1 + + + + org.netbeans.modules.editor.lib2 + + + + 1 + 1.18.1.2 + + + + org.netbeans.modules.java.j2seproject + + + + 1 + + + + + org.netbeans.modules.java.source + + + + 0.52.2.8.8.2 + + + + org.netbeans.modules.project.ant + + + + 1 + 1.37 + + + + org.netbeans.modules.project.libraries + + + + 1 + 1.25.1 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.28.1 + + + + org.netbeans.modules.projectuiapi + + + + 1 + 1.40.1.6 + + + + org.netbeans.modules.settings + + + + 1 + 1.22.1.1 + + + + org.netbeans.spi.palette + + + + 1 + 1.20.1 + + + + org.openide.actions + + + + 6.12.1.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.explorer + + + + 6.22.2.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.io + + + + 1.20.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.modules + + + + 7.13.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.text + + + + 6.27.1 + + + + org.openide.util + + + + 7.31.1.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.30.1 + + + + + com.jme3.gde.core + com.jme3.gde.core.assets + com.jme3.gde.core.assets.actions + com.jme3.gde.core.assets.nodes + com.jme3.gde.core.codeless + com.jme3.gde.core.j2seproject + com.jme3.gde.core.properties + com.jme3.gde.core.scene + com.jme3.gde.core.scene.controller + com.jme3.gde.core.scene.processors + com.jme3.gde.core.sceneexplorer + com.jme3.gde.core.sceneexplorer.nodes + com.jme3.gde.core.sceneexplorer.nodes.actions + com.jme3.gde.core.sceneexplorer.nodes.actions.impl + com.jme3.gde.core.sceneexplorer.nodes.properties + com.jme3.gde.core.sceneviewer + com.jme3.gde.core.undoredo + com.jme3.gde.core.util + + + + diff --git a/sdk/jme3-core/nbproject/suite.properties b/sdk/jme3-core/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-core/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-core/src/META-INF/services/org.netbeans.spi.project.ProjectFactory b/sdk/jme3-core/src/META-INF/services/org.netbeans.spi.project.ProjectFactory new file mode 100644 index 000000000..b95e1cebe --- /dev/null +++ b/sdk/jme3-core/src/META-INF/services/org.netbeans.spi.project.ProjectFactory @@ -0,0 +1 @@ +com.jme3.gde.core.codeless.CodelessProjectFactory diff --git a/sdk/jme3-core/src/META-INF/services/org.openide.awt.UndoRedo b/sdk/jme3-core/src/META-INF/services/org.openide.awt.UndoRedo new file mode 100644 index 000000000..a374f9122 --- /dev/null +++ b/sdk/jme3-core/src/META-INF/services/org.openide.awt.UndoRedo @@ -0,0 +1 @@ +com.jme3.gde.core.undoredo.SceneUndoRedoManager diff --git a/sdk/jme3-core/src/com/jme3/asset/Desktop.cfg b/sdk/jme3-core/src/com/jme3/asset/Desktop.cfg new file mode 100644 index 000000000..55bacc779 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/asset/Desktop.cfg @@ -0,0 +1,20 @@ +LOCATOR / com.jme3.asset.plugins.ClasspathLocator + +LOADER com.jme3.texture.plugins.AWTLoader : jpg, bmp, gif, png, jpeg +LOADER com.jme3.audio.plugins.WAVLoader : wav +LOADER com.jme3.audio.plugins.OGGLoader : ogg +LOADER com.jme3.material.plugins.J3MLoader : j3m +LOADER com.jme3.material.plugins.J3MLoader : j3md +LOADER com.jme3.font.plugins.BitmapFontLoader : fnt +LOADER com.jme3.texture.plugins.DDSLoader : dds +LOADER com.jme3.texture.plugins.PFMLoader : pfm +LOADER com.jme3.texture.plugins.HDRLoader : hdr +LOADER com.jme3.texture.plugins.TGALoader : tga +LOADER com.jme3.export.binary.BinaryImporter : j3o +LOADER com.jme3.scene.plugins.OBJLoader : obj +LOADER com.jme3.scene.plugins.MTLLoader : mtl +LOADER com.jme3.scene.plugins.ogre.MeshLoader : meshxml, mesh.xml +LOADER com.jme3.scene.plugins.ogre.SkeletonLoader : skeletonxml, skeleton.xml +LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material +LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene +LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, glsl, glsllib \ No newline at end of file diff --git a/sdk/jme3-core/src/com/jme3/gde/core/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/Bundle.properties new file mode 100644 index 000000000..4187126a0 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/Bundle.properties @@ -0,0 +1,8 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides the core functions of jMonkeyPlatform. +OpenIDE-Module-Name=jMonkeyPlatform Core +OpenIDE-Module-Short-Description=The jMonkeyPlatform Core Plugin +Services/MIMEResolver/JMEBinaryModelResolver.xml=JMEBinaryModel Files +Menu/Help/jmewiki.url=Browse Help online +Menu/Help/help-main.xml=Browse Help locally diff --git a/sdk/jme3-core/src/com/jme3/gde/core/Installer.java b/sdk/jme3-core/src/com/jme3/gde/core/Installer.java new file mode 100644 index 000000000..34a4c58d9 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/Installer.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.gde.core.scene.SceneApplication; +import java.io.File; +import javax.swing.JPopupMenu; +import org.openide.modules.ModuleInstall; +import org.openide.util.Utilities; + +/** + * Manages a module's lifecycle. Remember that an installer is optional and + * often not needed at all. + */ +public class Installer extends ModuleInstall { + + @Override + public boolean closing() { + SceneApplication.getApplication().stop(); + return true; + } + + @Override + public void restored() { + //start scene app + SceneApplication.getApplication(); + } + + static { + //set default projects directory +// File userDir = new File(System.getProperty("user.home")); +// File myProjectsDir = new File(userDir, "jMonkeyProjects"); + javax.swing.JFileChooser fr = new javax.swing.JFileChooser(); + javax.swing.filechooser.FileSystemView fw = fr.getFileSystemView(); + File myProjectsDir = new File(fw.getDefaultDirectory().getPath() + File.separator + "jMonkeyProjects"); + + if (!myProjectsDir.exists()) { + myProjectsDir.mkdirs(); + } + System.setProperty("netbeans.projects.dir", myProjectsDir.getAbsolutePath()); + + //set extraction dir for platform natives + if (Utilities.isMac()) { + String jmpDir = System.getProperty("user.home") + "/Library/Application Support/jmonkeyplatform/"; + File file = new File(jmpDir); + file.mkdirs(); + com.jme3.system.Natives.setExtractionDir(jmpDir); + } else { + String jmpDir = System.getProperty("user.home") + File.separator + ".jmonkeyplatform" + File.separator; + File file = new File(jmpDir); + file.mkdirs(); + com.jme3.system.Natives.setExtractionDir(jmpDir); + } + + //avoid problems with lightweight popups + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/JMEBinaryModelResolver.xml b/sdk/jme3-core/src/com/jme3/gde/core/JMEBinaryModelResolver.xml new file mode 100644 index 000000000..7f3e33c7b --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/JMEBinaryModelResolver.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/SceneExplorerTopComponentSettings.xml b/sdk/jme3-core/src/com/jme3/gde/core/SceneExplorerTopComponentSettings.xml new file mode 100644 index 000000000..f18c5ec09 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/SceneExplorerTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/SceneExplorerTopComponentWstcref.xml b/sdk/jme3-core/src/com/jme3/gde/core/SceneExplorerTopComponentWstcref.xml new file mode 100644 index 000000000..96ec3b9e3 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/SceneExplorerTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/SceneViewerTopComponentSettings.xml b/sdk/jme3-core/src/com/jme3/gde/core/SceneViewerTopComponentSettings.xml new file mode 100644 index 000000000..7ba546b5c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/SceneViewerTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/SceneViewerTopComponentWstcref.xml b/sdk/jme3-core/src/com/jme3/gde/core/SceneViewerTopComponentWstcref.xml new file mode 100644 index 000000000..0fcb4e171 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/SceneViewerTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetData.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetData.java new file mode 100644 index 000000000..4282b0759 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetData.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import com.jme3.asset.AssetKey; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; +import org.openide.filesystems.FileAlreadyLockedException; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class AssetData extends Properties { + + private AssetDataObject file; + private String extension = "jmpdata"; + + public AssetData(AssetDataObject file) { + this.file = file; + } + + public AssetData(AssetDataObject file, String extension) { + this.file = file; + this.extension = extension; + } + + public AssetKey getAssetKey() { + return file.getAssetKey(); + } + + public Object loadAsset() { + return file.loadAsset(); + } + + public void saveAsset() throws IOException { + file.saveAsset(); + } + + @Override + public synchronized String getProperty(String key) { + return super.getProperty(key); + } + + @Override + public synchronized String getProperty(String key, String defaultValue) { +// loadProperties(); + return super.getProperty(key, defaultValue); + } + + @Override + public synchronized Object setProperty(String key, String value) { + Object obj= super.setProperty(key, value); +// try { +// saveProperties(); +// } catch (FileAlreadyLockedException ex) { +// Exceptions.printStackTrace(ex); +// } catch (IOException ex) { +// Exceptions.printStackTrace(ex); +// } + return obj; + } + + public void loadProperties() { + clear(); + FileObject myFile = FileUtil.findBrother(file.getPrimaryFile(), extension); + if (myFile == null) { + return; + } + InputStream in = null; + try { + in = myFile.getInputStream(); + try { + load(in); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } catch (FileNotFoundException ex) { + Exceptions.printStackTrace(ex); + } finally { + try { + in.close(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } + + public void saveProperties() throws FileAlreadyLockedException, IOException { + OutputStream out = null; + FileLock lock = null; + try { + FileObject pFile = file.getPrimaryFile(); + FileObject myFile = FileUtil.findBrother(pFile, extension); + if (myFile == null) { + myFile = FileUtil.createData(pFile.getParent(), pFile.getName() + "." + extension); + } + lock = myFile.lock(); + out = myFile.getOutputStream(lock); + store(out, ""); + } finally { + if (out != null) { + out.close(); + } + if (lock != null) { + lock.releaseLock(); + } + } + } + + public void setExtension(String extension) { + this.extension = extension; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetDataObject.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetDataObject.java new file mode 100644 index 000000000..c55676a08 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetDataObject.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import com.jme3.asset.AssetKey; +import com.jme3.export.Savable; +import com.jme3.export.binary.BinaryExporter; +import com.jme3.gde.core.scene.SceneApplication; +import java.io.IOException; +import java.io.OutputStream; +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; +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.awt.StatusDisplayer; +import org.openide.cookies.SaveCookie; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataNode; +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.AbstractLookup; +import org.openide.util.lookup.InstanceContent; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; + +/** + * + * @author normenhansen + */ +public class AssetDataObject extends MultiDataObject { + + protected final Lookup lookup; + protected final InstanceContent lookupContents = new InstanceContent(); + protected SaveCookie saveCookie = new SaveCookie() { + + public void save() throws IOException { + //TODO: On OpenGL thread? -- safest way.. with get()? + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + saveAsset(); + return null; + } + }); + } + }; + protected DataNode dataNode; + protected Savable savable; + protected String saveExtension; + + public AssetDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + lookup = new ProxyLookup(getCookieSet().getLookup(), new AbstractLookup(getLookupContents()), Lookups.fixed(new AssetData(this))); + setSaveCookie(saveCookie); + findAssetManager(); + } + + protected void findAssetManager() { + FileObject file = getPrimaryFile(); + ProjectManager pm = ProjectManager.getDefault(); + while (file != null) { + if (file.isFolder() && pm.isProject(file)) { + try { + Project project = ProjectManager.getDefault().findProject(file); + if (project != null) { + ProjectAssetManager mgr = project.getLookup().lookup(ProjectAssetManager.class); + if (mgr != null) { + getLookupContents().add(mgr); + return; + } + } + } catch (IOException ex) { + } catch (IllegalArgumentException ex) { + } + } + file = file.getParent(); + } + } + + @Override + protected Node createNodeDelegate() { + DataNode node = new DataNode(this, Children.LEAF, getLookup()); + node.setIconBaseWithExtension("com/jme3/gde/core/assets/jme-logo.png"); + return node; + } + + @Override + public void setModified(boolean modif) { + super.setModified(modif); + if (modif && saveCookie != null) { + getCookieSet().assign(SaveCookie.class, saveCookie); + } else { + getCookieSet().assign(SaveCookie.class); + } + } + + @Override + public Lookup getLookup() { + return lookup; + } + + public InstanceContent getLookupContents() { + return lookupContents; + } + + public void setSaveCookie(SaveCookie cookie) { + this.saveCookie = cookie; + getCookieSet().assign(SaveCookie.class, saveCookie); + setModified(false); + } + + //TODO: make save as j3o + public Savable loadAsset() { + if (isModified() && savable != null) { + return savable; + } + ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class); + if (mgr == null) { + return null; + } + String assetKey = mgr.getRelativeAssetPath(getPrimaryFile().getPath()); + FileLock lock = null; + try { + lock = getPrimaryFile().lock(); + Savable spatial = (Savable) mgr.loadAsset(new AssetKey(assetKey)); + savable = spatial; + lock.releaseLock(); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } finally { + if (lock != null) { + lock.releaseLock(); + } + } + return savable; + } + + public void saveAsset() throws IOException { + if (savable == null) { + Logger.getLogger(AssetDataObject.class.getName()).log(Level.WARNING, "Trying to save asset that has not been loaded before or does not support saving!"); + return; + } + final Savable savable = this.savable; + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Saving File.."); + progressHandle.start(); + BinaryExporter exp = BinaryExporter.getInstance(); + FileLock lock = null; + OutputStream out = null; + try { + if (saveExtension == null) { + out = getPrimaryFile().getOutputStream(); + } else { + FileObject outFileObject = getPrimaryFile().getParent().getFileObject(getPrimaryFile().getName(), saveExtension); + if (outFileObject == null) { + outFileObject = getPrimaryFile().getParent().createData(getPrimaryFile().getName(), saveExtension); + } + out = outFileObject.getOutputStream(); + } + exp.save(savable, out); + } finally { + if (lock != null) { + lock.releaseLock(); + } + if (out != null) { + out.close(); + } + } + progressHandle.finish(); + StatusDisplayer.getDefault().setStatusText(getPrimaryFile().getNameExt() + " saved."); + setModified(false); + } + + public AssetKey getAssetKey() { + ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class); + if (mgr == null) { + return null; + } + String assetKey = mgr.getRelativeAssetPath(getPrimaryFile().getPath()); + return new AssetKey(assetKey); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetManagerConfigurator.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetManagerConfigurator.java new file mode 100644 index 000000000..1c7feed90 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetManagerConfigurator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import com.jme3.asset.AssetManager; + +/** + * This class can be used by plugins to configure the AssetManager used for projects + * @author normenhansen + */ +public interface AssetManagerConfigurator { + + public void prepareManager(AssetManager manager); + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetsLookupProvider.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetsLookupProvider.java new file mode 100644 index 000000000..5f6161feb --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/AssetsLookupProvider.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import com.jme3.gde.core.j2seproject.ProjectExtensionManager; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; +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.modules.java.j2seproject.J2SEProject; +import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator; +import org.netbeans.spi.project.LookupProvider; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.netbeans.spi.project.support.ant.EditableProperties; +import org.netbeans.spi.project.ui.ProjectOpenedHook; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.Mutex; +import org.openide.util.MutexException; +import org.openide.util.lookup.Lookups; + +/** + * + * @author normenhansen + */ +public class AssetsLookupProvider implements LookupProvider { + + private Project project; + public static final String[] keyList = new String[]{ + "assets.jar.name", + "assets.folder.name", + "assets.excludes", + "assets.compress" + }; + private String extensionName = "assets"; + private String extensionVersion = "v1.0"; + private String extensionTargets = + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n"; + private String[] extensionDependencies = new String[]{"-do-init", "-init-assets"}; + private ProjectExtensionManager manager = new ProjectExtensionManager(extensionName, extensionVersion, extensionTargets, extensionDependencies); + + public Lookup createAdditionalLookup(Lookup lookup) { + Project prj = lookup.lookup(Project.class); + project = prj; + FileObject assetsProperties = prj.getProjectDirectory().getFileObject("nbproject/assets.properties"); + if (assetsProperties == null) { + assetsProperties = prj.getProjectDirectory().getFileObject("nbproject/project.properties"); + } else { + Logger.getLogger(AssetsLookupProvider.class.getName()).log(Level.WARNING, "Project is using old assets.properties file"); + } + if (assetsProperties != null && assetsProperties.isValid()) { + FileLock lock = null; + try { + lock = assetsProperties.lock(); + InputStream in = assetsProperties.getInputStream(); + Properties properties = new Properties(); + properties.load(in); + in.close(); + String assetsFolderName = properties.getProperty("assets.folder.name", "assets"); + if (prj.getProjectDirectory().getFileObject(assetsFolderName) != null) { + Logger.getLogger(AssetsLookupProvider.class.getName()).log(Level.INFO, "Valid jMP project, extending with ProjectAssetManager"); + return Lookups.fixed(new ProjectAssetManager(prj, assetsFolderName), openedHook); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } finally { + if (lock != null) { + lock.releaseLock(); + } + } + } + + return Lookups.fixed(); + } + private ProjectOpenedHook openedHook = 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); + } + } + } + }; + + public static EditableProperties getProperties(Project project) { + EditableProperties props = new EditableProperties(true); + if (!(project instanceof J2SEProject)) { + return props; + } + FileObject projDir = project.getProjectDirectory(); + //old properties files + FileObject oldProperties = projDir.getFileObject("nbproject/assets.properties"); + if (oldProperties != null) { + Logger.getLogger(AssetsLookupProvider.class.getName()).log(Level.INFO, "Deleting old project assets.properties"); + try { + props.load(oldProperties.getInputStream()); + store(props, project); + oldProperties.delete(); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } else { + load(props, project); +// if (props.getProperty("assets.folder.name") == null) { +// props.setProperty("assets.jar.name", "assets.jar"); +// props.setProperty("assets.folder.name", "assets"); +// props.setProperty("assets.excludes", "**/*.mesh\\.xml,**/*.skeleton\\.xml,**/*.scene,**/*.material,**/*.obj,**/*.mtl,**/*.j3odata"); +// props.setProperty("assets.compress", "true"); +// try { +// store(props, project); +// } catch (IOException ex) { +// Exceptions.printStackTrace(ex); +// } +// } + } + return props; + } + + public static void load(EditableProperties ep, Project project) { + J2SEPropertyEvaluator eval = project.getLookup().lookup(J2SEPropertyEvaluator.class); + if (eval == null) { + return; + } + for (int i = 0; i < keyList.length; i++) { + String string = keyList[i]; + String value = eval.evaluator().getProperty(string); + if (value != null) { + ep.setProperty(string, value); + } + //TODO: create defaults! + } + } + + public static void store(final EditableProperties storeProps, Project project) throws IOException { + final FileObject projPropsFO = project.getProjectDirectory().getFileObject(AntProjectHelper.PROJECT_PROPERTIES_PATH); + final EditableProperties ep = new EditableProperties(true); +// final EditableProperties pep = new EditableProperties(true); +// final FileObject privPropsFO = project.getProjectDirectory().getFileObject(AntProjectHelper.PRIVATE_PROPERTIES_PATH); + + try { + final InputStream is = projPropsFO.getInputStream(); +// final InputStream pis = privPropsFO.getInputStream(); + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { + + @Override + public Void run() throws Exception { + try { + ep.load(is); + } finally { + if (is != null) { + is.close(); + } + } +// try { +// pep.load(pis); +// } finally { +// if (pis != null) { +// pis.close(); +// } +// } + putProperties(storeProps, ep); + OutputStream os = null; + FileLock lock = null; + try { + lock = projPropsFO.lock(); + os = projPropsFO.getOutputStream(lock); + ep.store(os); + } finally { + if (lock != null) { + lock.releaseLock(); + } + if (os != null) { + os.close(); + } + } +// try { +// lock = privPropsFO.lock(); +// os = privPropsFO.getOutputStream(lock); +// pep.store(os); +// } finally { +// if (lock != null) { +// lock.releaseLock(); +// } +// if (os != null) { +// os.close(); +// } +// } + return null; + } + }); + } catch (MutexException mux) { + throw (IOException) mux.getException(); + } + + } + + public static void putProperties(EditableProperties from, EditableProperties to) { + for (int i = 0; i < keyList.length; i++) { + String string = keyList[i]; + String value = from.getProperty(string); + if (value != null) { + to.put(string, value); + } + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/BinaryModelDataObject.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/BinaryModelDataObject.java new file mode 100644 index 000000000..f5607b9b6 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/BinaryModelDataObject.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; + +public class BinaryModelDataObject extends SpatialAssetDataObject { + + public BinaryModelDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + getLookup().lookup(AssetData.class).setExtension(BinaryModelFileLoader.INFO_EXTENSION); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/BinaryModelFileLoader.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/BinaryModelFileLoader.java new file mode 100644 index 000000000..86bc016b9 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/BinaryModelFileLoader.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.ExtensionList; +import org.openide.loaders.FileEntry; +import org.openide.loaders.MultiDataObject; +import org.openide.loaders.MultiFileLoader; + +/** + * + * @author normenhansen + */ +public class BinaryModelFileLoader extends MultiFileLoader { + + public static final String PROP_EXTENSIONS = "extensions"; // NOI18N + public static final String INFO_EXTENSION = "j3odata"; + public static final String FILE_EXTENSION = "j3o"; + public static final String MIME_TYPE = "application/jme3model"; + private static final long serialVersionUID = -4579746482156153693L; + + public BinaryModelFileLoader() { + super("com.jme3.gde.core.assets.BinaryModelDataObject"); + } + + @Override + protected String actionsContext() { + return "Loaders/application/jme3model/Actions"; + } + + protected MultiDataObject createMultiObject(FileObject primaryFile) + throws DataObjectExistsException, IOException { + return new BinaryModelDataObject(primaryFile, this); + } + + @Override + protected void initialize() { + super.initialize(); + getExtensions(); + } + + /** For a given file find the primary file. + * @param fo the file to find the primary file for + * @return the primary file for this file or null + * if this file is not recognized by this loader. + */ + protected FileObject findPrimaryFile(FileObject fo) { + // never recognize folders. + if (fo.isFolder()) { + return null; + } + String ext = fo.getExt(); + if (ext.equalsIgnoreCase(INFO_EXTENSION)) { + FileObject info = FileUtil.findBrother(fo, FILE_EXTENSION); + if (info != null) { + return info; + } else { + return null; + } + } + if (getExtensions().isRegistered(fo)) { + return fo; + } + return null; + } + + /** Create the primary file entry. Primary files are the j3o files. + * @param primaryFile primary file recognized by this loader + * @return primary entry for that file + */ + protected MultiDataObject.Entry createPrimaryEntry( + MultiDataObject obj, FileObject primaryFile) { + return new FileEntry(obj, primaryFile); + } + + /** Create a secondary file entry. + * Secondary files are properties files, which should also be retained (so, not a + * FileEntry.Numb object) + * @param secondaryFile secondary file to create entry for + * @return the entry + */ + protected MultiDataObject.Entry createSecondaryEntry( + MultiDataObject obj, FileObject secondaryFile) { + return new FileEntry(obj, secondaryFile); + } + + /** @return The list of extensions this loader recognizes. */ + public ExtensionList getExtensions() { + ExtensionList extensions = (ExtensionList) getProperty(PROP_EXTENSIONS); + if (extensions == null) { + extensions = new ExtensionList(); + extensions.addExtension(FILE_EXTENSION); + extensions.addExtension(INFO_EXTENSION); + extensions.addMimeType(MIME_TYPE); + putProperty(PROP_EXTENSIONS, extensions, false); + } + return extensions; + } + + /** Sets the extension list for this data loader. + * @param ext new list of extensions. + */ + public void setExtensions(ExtensionList ext) { + putProperty(PROP_EXTENSIONS, ext, true); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/assets/Bundle.properties new file mode 100644 index 000000000..1ae61dc8c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/Bundle.properties @@ -0,0 +1,2 @@ +LBL_JMEBinaryModel_loader_name=JMEBinaryModel Files +TextureBrowser.title=Texture Browser diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/ProjectAssetManager.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/ProjectAssetManager.java new file mode 100644 index 000000000..936e6a31c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/ProjectAssetManager.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import com.jme3.asset.AssetManager; +import com.jme3.asset.DesktopAssetManager; +import java.io.File; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.project.Project; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.XMLFileSystem; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; + +/** + * + * @author normenhansen + */ +public class ProjectAssetManager extends DesktopAssetManager { + + private Project project; + private List folderName = new LinkedList(); + + public ProjectAssetManager(Project prj, String folderName) { + this(prj); + addFileLocator(folderName); + } + + public ProjectAssetManager(Project prj) { + super(true); + if (prj == null) { + this.project = new DummyProject(this); + folderName.add("assets"); + } else { + this.project = prj; + } + AssetManager manager = getManager(); + for (AssetManagerConfigurator di : Lookup.getDefault().lookupAll(AssetManagerConfigurator.class)) { + di.prepareManager(manager); + } + } + + public ProjectAssetManager() { + this(null); + } + + public void addFileLocator(String relativePath) { + String string = project.getProjectDirectory().getPath() + "/" + relativePath + "/"; + Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Add locator:{0}", string); + registerLocator(string, + "com.jme3.asset.plugins.FileLocator"); + folderName.add(relativePath); + } + + public Project getProject() { + return project; + } + + public String getRelativeAssetPath(String absolutePath) { + String prefix = project.getProjectDirectory().getFileObject(getFolderName() + "/").getPath(); + int idx = absolutePath.indexOf(prefix); + if (idx == 0) { + return absolutePath.substring(prefix.length() + 1); + } + return absolutePath; + } + + @Deprecated + public AssetManager getManager() { + return this; + } + + public String[] getMaterials() { + FileObject assetsFolder = project.getProjectDirectory().getFileObject(getFolderName() + "/"); + if (assetsFolder == null) { + return new String[]{}; + } + Enumeration assets = (Enumeration) assetsFolder.getChildren(true); + ArrayList list = new ArrayList(); + while (assets.hasMoreElements()) { + FileObject asset = assets.nextElement(); + if (asset.hasExt("j3m")) { + list.add(getRelativeAssetPath(asset.getPath())); + } + } + return list.toArray(new String[list.size()]); + } + + public String[] getSounds() { + FileObject assetsFolder = project.getProjectDirectory().getFileObject(getFolderName() + "/"); + if (assetsFolder == null) { + return new String[]{}; + } + Enumeration assets = (Enumeration) assetsFolder.getChildren(true); + ArrayList list = new ArrayList(); + while (assets.hasMoreElements()) { + FileObject asset = assets.nextElement(); + if (asset.hasExt("wav") || asset.hasExt("ogg")) { + list.add(getRelativeAssetPath(asset.getPath())); + } + } + return list.toArray(new String[list.size()]); + } + + public String[] getTextures() { + FileObject assetsFolder = project.getProjectDirectory().getFileObject(getFolderName() + "/"); + if (assetsFolder == null) { + return new String[]{}; + } + Enumeration assets = (Enumeration) assetsFolder.getChildren(true); + ArrayList list = new ArrayList(); + while (assets.hasMoreElements()) { + FileObject asset = assets.nextElement(); + if (asset.hasExt("jpg") || asset.hasExt("jpeg") || asset.hasExt("gif") || asset.hasExt("png") || asset.hasExt("dds") || asset.hasExt("pfm") || asset.hasExt("hdr") || asset.hasExt("tga")) { + list.add(getRelativeAssetPath(asset.getPath())); + } + } + return list.toArray(new String[list.size()]); + } + + public String[] getMatDefs() { + FileObject assetsFolder = project.getProjectDirectory().getFileObject(getFolderName() + "/"); + if (assetsFolder == null) { + return new String[]{}; + } + Enumeration assets = (Enumeration) assetsFolder.getChildren(true); + ArrayList list = new ArrayList(); + while (assets.hasMoreElements()) { + FileObject asset = assets.nextElement(); + if (asset.hasExt("j3md")) { + list.add(getRelativeAssetPath(asset.getPath())); + } + } + return list.toArray(new String[list.size()]); + } + + /** + * @return the folderName + */ + public String getFolderName() { + return folderName.get(0); + } + + /** + * @return the folderName + */ + public String getAssetFolderName() { + return project.getProjectDirectory().getPath() + "/" + getFolderName(); + } + + public FileObject getAssetFolder(){ + return project.getProjectDirectory().getFileObject(getFolderName()); + } + + public String getAbsoluteAssetPath(String path) { + for (Iterator it = folderName.iterator(); it.hasNext();) { + String string = project.getProjectDirectory().getPath() + "/" + it.next() + "/" + path; + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Check {0}", string); + File file = new File(string); + if (file.exists()) { + return file.getAbsolutePath(); + } + } + return null; + } + + /** + * @param folderName the folderName to set + */ + public void setFolderName(String folderName) { + if (folderName.length() > 0) { + this.folderName.remove(0); + } + this.folderName.add(0, folderName); + } + + /** + * For situations with no Project + */ + private class DummyProject implements Project { + + ProjectAssetManager pm; + FileObject folder; + XMLFileSystem fileSystem = new XMLFileSystem(); + + public DummyProject(ProjectAssetManager pm, FileObject folder) { + this.folder = folder; + this.pm = pm; + } + + public DummyProject(ProjectAssetManager pm) { + this.pm = pm; + } + + public Lookup getLookup() { + return Lookups.fixed(this, pm); + } + + public FileObject getProjectDirectory() { + if (folder != null) { + return folder; + } + return fileSystem.getRoot(); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/ProjectAssetsNodeFactory.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/ProjectAssetsNodeFactory.java new file mode 100644 index 000000000..7495cf19e --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/ProjectAssetsNodeFactory.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import com.jme3.gde.core.assets.nodes.ProjectAssetsNode; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ui.support.NodeFactory; +import org.netbeans.spi.project.ui.support.NodeFactorySupport; +import org.netbeans.spi.project.ui.support.NodeList; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class ProjectAssetsNodeFactory implements NodeFactory { + + private Project proj; + + public NodeList createNodes(Project project) { + + this.proj = project; + + DataObject assetsFolder; + try { + //return a new node for the project view if theres an assets folder: + ProjectAssetManager item = project.getLookup().lookup(ProjectAssetManager.class); + if (item != null) { + assetsFolder = DataObject.find(project.getProjectDirectory().getFileObject(item.getFolderName())); + Node node = assetsFolder.getNodeDelegate(); +// return NodeFactorySupport.fixedNodeList(node); + try { + ProjectAssetsNode nd = new ProjectAssetsNode(item, proj, node); + return NodeFactorySupport.fixedNodeList(nd); + } catch (DataObjectNotFoundException ex) { + Exceptions.printStackTrace(ex); + } + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + + //If our item isn't in the lookup, + //then return an empty list of nodes: + return NodeFactorySupport.fixedNodeList(); + + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/SpatialAssetDataObject.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/SpatialAssetDataObject.java new file mode 100644 index 000000000..99c85475d --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/SpatialAssetDataObject.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2009-2010 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.assets; + +import com.jme3.asset.ModelKey; +import com.jme3.scene.Spatial; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class SpatialAssetDataObject extends AssetDataObject { + + public SpatialAssetDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + saveExtension = "j3o"; + } + + @Override + public ModelKey getAssetKey() { + ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class); + if (mgr == null) { + return null; + } + String assetKey = mgr.getRelativeAssetPath(getPrimaryFile().getPath()); + return new ModelKey(assetKey); + } + + @Override + public Spatial loadAsset() { + if (isModified() && savable != null) { + return (Spatial) savable; + } + ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class); + if (mgr == null) { + return null; + } + String assetKey = mgr.getRelativeAssetPath(getPrimaryFile().getPath()); + FileLock lock = null; + try { + lock = getPrimaryFile().lock(); + mgr.deleteFromCache(new ModelKey(assetKey)); + Spatial spatial = mgr.loadModel(assetKey); + savable = spatial; + lock.releaseLock(); + return spatial; + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } finally { + if (lock != null) { + lock.releaseLock(); + } + } + return null; + } + + public void saveAsset() throws IOException { + super.saveAsset(); + ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class); + if (mgr == null) { + return; + } + FileObject outFile = null; + if (saveExtension == null) { + outFile = getPrimaryFile(); + } else { + outFile = getPrimaryFile().getParent().getFileObject(getPrimaryFile().getName(), saveExtension); + if (outFile == null) { + //ERROR + Logger.getLogger(SpatialAssetDataObject.class.getName()).log(Level.SEVERE, "Could not locate saved file."); + return; + } + } + try { + DataObject targetModel = DataObject.find(outFile); + AssetData properties = targetModel.getLookup().lookup(AssetData.class); + if (properties != null) { + properties.loadProperties(); + properties.setProperty("ORIGINAL_PATH", mgr.getRelativeAssetPath(outFile.getPath())); + properties.saveProperties(); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/Bundle.properties new file mode 100644 index 000000000..ea55ca32e --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/Bundle.properties @@ -0,0 +1,2 @@ +CTL_ConvertModel=Convert to j3o Binary +CTL_OpenModel=View Model diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/Computer_File_057.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/Computer_File_057.gif new file mode 100644 index 000000000..3604be77b Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/Computer_File_057.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/ConvertModel.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/ConvertModel.java new file mode 100644 index 000000000..23df3a0d5 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/ConvertModel.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009-2010 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.assets.actions; + +import com.jme3.gde.core.assets.BinaryModelDataObject; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.util.List; +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; +import org.openide.util.Exceptions; + +public final class ConvertModel implements ActionListener { + + private final List context; + + public ConvertModel(List context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + Runnable run = new Runnable() { + + public void run() { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Converting Model"); + progressHandle.start(); + for (SpatialAssetDataObject spatialAssetDataObject : context) { + if (!(spatialAssetDataObject instanceof BinaryModelDataObject)) { + try { + spatialAssetDataObject.loadAsset(); + spatialAssetDataObject.saveAsset(); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error converting " + spatialAssetDataObject.getName() + "\n" + ex.toString(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + } + } + progressHandle.finish(); + } + }; + new Thread(run).start(); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/OpenModel.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/OpenModel.java new file mode 100644 index 000000000..a66a460b4 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/OpenModel.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2009-2010 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.assets.actions; + +import com.jme3.asset.DesktopAssetManager; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +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.scene.Node; +import com.jme3.scene.Spatial; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +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 { + + private final SpatialAssetDataObject context; + + public OpenModel(SpatialAssetDataObject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final ProjectAssetManager manager = context.getLookup().lookup(ProjectAssetManager.class); + if (manager == null) { + return; + } + Runnable call = new Runnable() { + + public void run() { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening Model"); + progressHandle.start(); + try { + ((DesktopAssetManager) manager.getManager()).clearCache(); + + final Spatial asset = (Spatial) context.loadAsset(); + + if (asset != null) { + Node node = null; + if (asset instanceof Node) { + node = (Node) asset; + } else { + node = new Node("RootNode"); + node.attachChild(asset); + } + JmeNode jmeNode = NodeUtility.createNode(node); + SceneApplication app = SceneApplication.getApplication(); + SceneRequest request = new SceneRequest(app, jmeNode, manager); + request.setWindowTitle("SceneViewer - View Model"); + app.requestScene(request); + } else { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error opening " + context.getPrimaryFile().getNameExt(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + }catch(Exception e){ + e.printStackTrace(); + }finally { + progressHandle.finish(); + } + } + }; + new Thread(call).start(); + + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/jme-logo.png b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/jme-logo.png new file mode 100644 index 000000000..bdc220ce9 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/jme-logo.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/jme-logo24.png b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/jme-logo24.png new file mode 100644 index 000000000..2c413459f Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/actions/jme-logo24.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/jme-logo.png b/sdk/jme3-core/src/com/jme3/gde/core/assets/jme-logo.png new file mode 100644 index 000000000..f67785a6e Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/jme-logo.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/AssetChildren.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/AssetChildren.java new file mode 100644 index 000000000..35c3ad594 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/AssetChildren.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009-2010 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.assets.nodes; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import java.util.ArrayList; +import java.util.List; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; + +/** + * + * @author normenhansen + */ +public class AssetChildren extends FilterNode.Children { + + private ProjectAssetManager manager; + + public AssetChildren(ProjectAssetManager manager, Node owner) { + super(owner); + this.manager = manager; + } + + @Override + protected Node copyNode(Node original) { + return new AssetNode(manager, original); + } + + @Override + protected Node[] createNodes(Node object) { + List result = new ArrayList(); + + for (Node node : super.createNodes(object)) { + if (accept(node)) { + result.add(node); + } + } + + return result.toArray(new Node[0]); + } + + private boolean accept(Node node) { + // ... + DataObject obj = node.getLookup().lookup(DataObject.class); + if (obj != null) { + FileObject file = obj.getPrimaryFile(); + if(FileUtil.toFile(file).isHidden()){ //file.getName().startsWith(".")|| + return false; + } + + } + return true; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/AssetNode.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/AssetNode.java new file mode 100644 index 000000000..27719bd1b --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/AssetNode.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009-2010 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.assets.nodes; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.AssetDataObject; +import org.openide.loaders.DataObject; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.util.Lookup; +import org.openide.util.lookup.ProxyLookup; + +/** + * + * @author normenhansen + */ +public class AssetNode extends FilterNode { + + private Node node; + + public AssetNode(ProjectAssetManager manager, Node node) { + super(node, new AssetChildren(manager, node), createLookupProxy(manager, node)); + this.node = node; + enableDelegation(DELEGATE_GET_ACTIONS); + enableDelegation(DELEGATE_GET_CONTEXT_ACTIONS); + } + + public static Lookup createLookupProxy(ProjectAssetManager manager, Node node) { + DataObject obj = node.getLookup().lookup(DataObject.class); + if (obj instanceof AssetDataObject && obj.getLookup().lookup(ProjectAssetManager.class) == null) { + ((AssetDataObject) obj).getLookupContents().add(manager); + } + return new ProxyLookup( + new Lookup[]{ + node.getLookup() + /*,Lookups.fixed(manager)*/ + }); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/ProjectAssetsNode.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/ProjectAssetsNode.java new file mode 100644 index 000000000..6fd6091e0 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/ProjectAssetsNode.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009-2010 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.assets.nodes; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.AssetDataObject; +import java.awt.Image; +import org.netbeans.api.project.Project; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; + +/** + * + * @author normenhansen + */ +public class ProjectAssetsNode extends FilterNode { + + private static Image smallImage = + ImageUtilities.loadImage("/com/jme3/gde/core/assets/nodes/icons/assets.gif"); + + public ProjectAssetsNode(ProjectAssetManager manager, Project proj, Node node) throws DataObjectNotFoundException { + super(node, new AssetChildren(manager, node), createLookupProxy(manager, node)); + enableDelegation(DELEGATE_GET_ACTIONS); + enableDelegation(DELEGATE_GET_CONTEXT_ACTIONS); + setDisplayName("Project Assets"); + } + + public static Lookup createLookupProxy(ProjectAssetManager manager, Node node) { + DataObject obj = node.getLookup().lookup(DataObject.class); + if (obj instanceof AssetDataObject && obj.getLookup().lookup(ProjectAssetManager.class) == null) { + ((AssetDataObject) obj).getLookupContents().add(manager); + } + return new ProxyLookup( + new Lookup[]{ + node.getLookup() + /*,Lookups.fixed(manager)*/ + }); + } + + public Image getIcon(int type) { + return smallImage; + } + + public Image getOpenedIcon(int type) { + return smallImage; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/SaveNode.java b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/SaveNode.java new file mode 100644 index 000000000..04b1a9c6c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/SaveNode.java @@ -0,0 +1,68 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.core.assets.nodes; + +import java.io.IOException; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Confirmation; +import org.openide.cookies.SaveCookie; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; + +/** + * + * @author normenhansen + */ +public class SaveNode extends AbstractNode { + + SaveCookie impl; + + public SaveNode() { + super(Children.LEAF); + impl = new SaveCookieImpl(); + } + + public SaveNode(SaveCookie impl) { + super(Children.LEAF); + this.impl = impl; + } + + public void fire(boolean modified) { + if (modified) { + //If the text is modified, + //we implement SaveCookie, + //and add the implementation to the cookieset: + getCookieSet().assign(SaveCookie.class, impl); + } else { + //Otherwise, we make no assignment + //and the SaveCookie is not made available: + getCookieSet().assign(SaveCookie.class); + } + } + + private class SaveCookieImpl implements SaveCookie { + + public void save() throws IOException { + + Confirmation msg = new NotifyDescriptor.Confirmation("This plugin can not save!", + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.QUESTION_MESSAGE); + + Object result = DialogDisplayer.getDefault().notify(msg); + + //When user clicks "Yes", indicating they really want to save, + //we need to disable the Save button and Save menu item, + //so that it will only be usable when the next change is made + //to the text field: + if (NotifyDescriptor.YES_OPTION.equals(result)) { + fire(false); + //Implement your save functionality here. + } + + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/assets.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/assets.gif new file mode 100644 index 000000000..941730bab Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/assets.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/font.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/font.gif new file mode 100644 index 000000000..3747a103e Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/font.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/gui.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/gui.gif new file mode 100644 index 000000000..421d54335 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/gui.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/image.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/image.gif new file mode 100644 index 000000000..638f48ff0 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/image.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/material.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/material.gif new file mode 100644 index 000000000..7f524523f Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/material.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/model.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/model.gif new file mode 100644 index 000000000..eeab8ff3a Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/model.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/scene.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/scene.gif new file mode 100644 index 000000000..95ca42aba Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/scene.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/sound.gif b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/sound.gif new file mode 100644 index 000000000..6b7af790a Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/assets/nodes/icons/sound.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProject.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProject.java new file mode 100644 index 000000000..f9ae4446e --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProject.java @@ -0,0 +1,233 @@ + +package com.jme3.gde.core.codeless; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectInformation; +import org.netbeans.spi.project.ActionProvider; +import org.netbeans.spi.project.DeleteOperationImplementation; +import org.netbeans.spi.project.CopyOperationImplementation; +import org.netbeans.spi.project.ProjectState; +import org.netbeans.spi.project.ui.LogicalViewProvider; +import org.netbeans.spi.project.ui.support.DefaultProjectOperations; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; + +class CodelessProject implements Project { + + private final FileObject projectDir; + LogicalViewProvider logicalView = new CodelessProjectLogicalView(this); + private final ProjectState state; + private Lookup lkp; + private ProjectAssetManager projectAssetManager; + + public CodelessProject(FileObject projectDir, ProjectState state) { + this.projectDir = projectDir; + this.state = state; + Properties properties=getProperties(); + String assetsFolder=properties.getProperty("assets.folder.name","assets"); + projectAssetManager = new ProjectAssetManager(this, assetsFolder); + } + + @Override + public FileObject getProjectDirectory() { + return projectDir; + } + +// public FileObject getConfigFolder(boolean create) { +// FileObject result = +// projectDir.getFileObject(CodelessProjectFactory.PROJECT_DIR); +// if (result == null && create) { +// try { +// result = projectDir.createFolder(CodelessProjectFactory.PROJECT_DIR); +// } catch (IOException ioe) { +// Exceptions.printStackTrace(ioe); +// } +// } +// return result; +// } + + public FileObject getConfigFile(boolean create){ + FileObject folder=projectDir;//getConfigFolder(create); + FileObject file=folder.getFileObject(CodelessProjectFactory.CONFIG_NAME); + if(file==null){ + try { + return folder.createData(CodelessProjectFactory.CONFIG_NAME); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + return file; + } + + public FileObject getAssetsFolder() { + Properties properties=getProperties(); + String assetsFolder=properties.getProperty("assets.folder.name","assets"); + FileObject result = + projectDir.getFileObject(assetsFolder); + return result; + } + + private Properties getProperties(){ + Properties properties=new Properties(); + try { + properties.load(getConfigFile(true).getInputStream()); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + return properties; + } + + private void saveProperties(Properties prop){ + try { + prop.store(getConfigFile(true).getOutputStream(), "jMonkeyPlatform Properties"); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + public Lookup getLookup() { + if (lkp == null) { + lkp = Lookups.fixed(new Object[]{ + this, //project spec requires a project be in its own lookup + state, //allow outside code to mark the project as needing saving + new ActionProviderImpl(), //Provides standard actions like Build and Clean + new DemoDeleteOperation(), + new DemoCopyOperation(this), + new Info(), //Project information implementation + logicalView, //Logical view of project implementation + }); + } + return lkp; + } + + public ProjectAssetManager getProjectAssetManager() { + return projectAssetManager; + } + + private final class ActionProviderImpl implements ActionProvider { + + private String[] supported = new String[]{ + ActionProvider.COMMAND_DELETE, + ActionProvider.COMMAND_COPY, + }; + + @Override + public String[] getSupportedActions() { + return supported; + } + + @Override + public void invokeAction(String string, Lookup lookup) throws IllegalArgumentException { + if (string.equalsIgnoreCase(ActionProvider.COMMAND_DELETE)) { + DefaultProjectOperations.performDefaultDeleteOperation(CodelessProject.this); + } + if (string.equalsIgnoreCase(ActionProvider.COMMAND_COPY)) { + DefaultProjectOperations.performDefaultCopyOperation(CodelessProject.this); + } + } + + @Override + public boolean isActionEnabled(String command, Lookup lookup) throws IllegalArgumentException { + if ((command.equals(ActionProvider.COMMAND_DELETE))) { + return true; + } else if ((command.equals(ActionProvider.COMMAND_COPY))) { + return true; + } else { + throw new IllegalArgumentException(command); + } + } + } + + private final class DemoDeleteOperation implements DeleteOperationImplementation { + + public void notifyDeleting() throws IOException { + } + + public void notifyDeleted() throws IOException { + } + + public List getMetadataFiles() { + List dataFiles = new ArrayList(); + return dataFiles; + } + + public List getDataFiles() { + List dataFiles = new ArrayList(); + return dataFiles; + } + } + + private final class DemoCopyOperation implements CopyOperationImplementation { + + private final CodelessProject project; + private final FileObject projectDir; + + public DemoCopyOperation(CodelessProject project) { + this.project = project; + this.projectDir = project.getProjectDirectory(); + } + + public List getMetadataFiles() { + return Collections.EMPTY_LIST; + } + + public List getDataFiles() { + return Collections.EMPTY_LIST; + } + + public void notifyCopying() throws IOException { + } + + public void notifyCopied(Project arg0, File arg1, String arg2) throws IOException { + } + } + + /** Implementation of project system's ProjectInformation class */ + private final class Info implements ProjectInformation { + + @Override + public Icon getIcon() { + return new ImageIcon(ImageUtilities.loadImage( + "com/jme3/gde/core/sceneviewer/jme-logo.png")); + } + + @Override + public String getName() { + return getProjectDirectory().getName(); + } + + @Override + public String getDisplayName() { + return getName(); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener pcl) { + //do nothing, won't change + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener pcl) { + //do nothing, won't change + } + + @Override + public Project getProject() { + return CodelessProject.this; + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProjectFactory.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProjectFactory.java new file mode 100644 index 000000000..67840c10b --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProjectFactory.java @@ -0,0 +1,40 @@ + +package com.jme3.gde.core.codeless; + +import java.io.IOException; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ProjectFactory; +import org.netbeans.spi.project.ProjectState; +import org.openide.filesystems.FileObject; + +public class CodelessProjectFactory implements ProjectFactory { + + public static final String CONFIG_NAME="assets.jmp"; + + //Specifies when a project is a project, i.e. properties file exists + @Override + public boolean isProject(FileObject projectDirectory) { + if(projectDirectory.getFileObject(CONFIG_NAME)!=null){ + return true; + } + return false; + } + + //Specifies when the project will be opened, i.e., + //if the project exists: + @Override + public Project loadProject(FileObject dir, ProjectState state) throws IOException { + return isProject(dir) ? new CodelessProject(dir, state) : null; + } + + @Override + public void saveProject(final Project project) throws IOException, ClassCastException { + FileObject projectRoot = project.getProjectDirectory(); + if (projectRoot.getFileObject(CONFIG_NAME) == null) { + throw new IOException("Project Settings " + projectRoot.getPath() + + " deleted," + + " cannot save project"); + } + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProjectLogicalView.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProjectLogicalView.java new file mode 100644 index 000000000..2f1bc1bb5 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/CodelessProjectLogicalView.java @@ -0,0 +1,143 @@ +package com.jme3.gde.core.codeless; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.nodes.ProjectAssetsNode; +import java.awt.Image; +import java.util.LinkedList; +import java.util.List; +import javax.swing.Action; +import org.netbeans.spi.project.ui.LogicalViewProvider; +import org.netbeans.spi.project.ui.support.CommonProjectActions; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataFolder; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; + +class CodelessProjectLogicalView implements LogicalViewProvider { + + private final CodelessProject project; + + public CodelessProjectLogicalView(CodelessProject project) { + this.project = project; + } + + @Override + public org.openide.nodes.Node createLogicalView() { + + try { + return new ProjectNode(project); + } catch (DataObjectNotFoundException donfe) { + Exceptions.printStackTrace(donfe); + //Fallback—the directory couldn't be created - + //read-only filesystem or something evil happened + return new AbstractNode(Children.LEAF); + } + } + + /** This is the node you actually see in the project tab for the project */ + private static final class ProjectNode extends AbstractNode { + + private InstanceContent instanceContent; + final CodelessProject project; + + public ProjectNode(CodelessProject project) throws DataObjectNotFoundException { + super(new ProjectChildren(project), new ProjectLookup(new InstanceContent())); + this.project = project; + instanceContent = ((ProjectLookup) getLookup()).getInstanceContent(); + instanceContent.add(project); + instanceContent.add(project.getProjectAssetManager()); + } + + @Override + public Action[] getActions(boolean arg0) { + Action[] nodeActions = new Action[7]; +// nodeActions[0] = CommonProjectActions.newFileAction(); + nodeActions[1] = CommonProjectActions.copyProjectAction(); + nodeActions[2] = CommonProjectActions.deleteProjectAction(); + nodeActions[5] = CommonProjectActions.setAsMainProjectAction(); + nodeActions[6] = CommonProjectActions.closeProjectAction(); + return nodeActions; + } + + @Override + public Image getIcon(int type) { + return ImageUtilities.loadImage("com/jme3/gde/core/sceneviewer/jme-logo.png"); + } + + @Override + public Image getOpenedIcon(int type) { + return getIcon(type); + } + + @Override + public String getDisplayName() { + return project.getProjectDirectory().getName(); + } + } + + public static final class ProjectLookup extends AbstractLookup { + + private static final long serialVersionUID = 1214314412L; + private InstanceContent instanceContent; + + public ProjectLookup(InstanceContent instanceContent) { + super(instanceContent); + this.instanceContent = instanceContent; + instanceContent.add(this); + } + + public InstanceContent getInstanceContent() { + return instanceContent; + } + } + + private static final class ProjectChildren extends Children.Keys { + + CodelessProject project; + Node node; + + public ProjectChildren(CodelessProject project) { + this.project = project; + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(createKeys()); + } + + protected List createKeys() { + LinkedList ret = new LinkedList(); + ret.add(new Object()); + return ret; + } + + @Override + protected Node[] createNodes(Object key) { + if (node == null) { + try { + ProjectAssetManager manager = project.getProjectAssetManager(); + FileObject assets = project.getAssetsFolder(); + node = new ProjectAssetsNode(manager, project, DataFolder.find(assets).getNodeDelegate()); + } catch (DataObjectNotFoundException ex) { + Exceptions.printStackTrace(ex); + node = new AbstractNode(Children.LEAF); + node.setDisplayName("error"); + } + } + return new Node[]{node}; + } + } + + @Override + public Node findPath(Node root, Object target) { + //leave unimplemented for now + return null; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/Bundle.properties new file mode 100644 index 000000000..728fff274 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/Bundle.properties @@ -0,0 +1,15 @@ +CTL_Codeless_Project=Asset-Only Project +CodelessProjectWizardVisualPanel1.jLabel2.text=Assets Folder: +CodelessProjectWizardVisualPanel1.jTextField1.text=path to project +CodelessProjectWizardVisualPanel1.jButton1.text=.. +CodelessProjectWizardVisualPanel1.jLabel3.text=Enter the root folder of your project: +CodelessProjectWizardVisualPanel1.jLabel1.text=Project Folder: +CodelessProjectWizardVisualPanel1.jPanel1.border.title=Information +CodelessProjectWizardVisualPanel1.jTextField2.text=path to assets +CodelessProjectWizardVisualPanel1.jButton2.text=.. +CodelessProjectWizardVisualPanel1.jLabel4.text=Enter the assets folder relative to the project folder: +CodelessProjectWizardVisualPanel1.jLabel5.text=A settings folder will be created in your project directory. +CodelessProjectWizardVisualPanel1.jLabel6.text=This importer will create a project that only manages the +CodelessProjectWizardVisualPanel1.jLabel7.text=external projects assets. No code or libraries will be imported. +CodelessProjectWizardVisualPanel2.jLabel1.text=TODO-No checks for now! +CodelessProjectWizardVisualPanel1.jLabel8.text=The assets folder should be in your games AssetManager root. diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardAction.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardAction.java new file mode 100644 index 000000000..28366fafc --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardAction.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2009-2010 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.codeless.wizard; + +import com.jme3.gde.core.codeless.CodelessProjectFactory; +import java.awt.Component; +import java.awt.Dialog; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.MessageFormat; +import java.util.Properties; +import javax.swing.JComponent; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.api.project.ui.OpenProjects; +import org.openide.DialogDisplayer; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CallableSystemAction; + +// An example action demonstrating how the wizard could be called from within +// your code. You can copy-paste the code below wherever you need. +public final class CodelessProjectWizardAction extends CallableSystemAction { + + private WizardDescriptor.Panel[] panels; + + public void performAction() { + WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle("Import External Project Assets"); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + if (!cancelled) { + createProjectSettings(wizardDescriptor); + } + } + + private void createProjectSettings(WizardDescriptor wizardDescriptor) { + String projectFolder = (String) wizardDescriptor.getProperty("PROJECT_FOLDER"); + String assetsFolder = (String) wizardDescriptor.getProperty("ASSETS_FOLDER"); + FileObject project = FileUtil.toFileObject(new File(projectFolder)); + try { + FileObject properties = project.createData(CodelessProjectFactory.CONFIG_NAME); + Properties propertiesObj = new Properties(); + FileLock lock=properties.lock(); + InputStream in=properties.getInputStream(); + propertiesObj.load(in); + in.close(); + propertiesObj.setProperty("assets.folder.name", assetsFolder); + OutputStream out=properties.getOutputStream(lock); + propertiesObj.store(out, "assets properties"); + out.close(); + lock.releaseLock(); + + Project theProject = ProjectManager.getDefault().findProject(project); + if(theProject!=null){ + Project[] array = new Project[1]; + array[0] = theProject; + OpenProjects.getDefault().open(array, false); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new CodelessProjectWizardWizardPanel1(), + new CodelessProjectWizardWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } + + public String getName() { + return "External Project Assets.."; + } + + @Override + public String iconResource() { + return null; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel1.form b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel1.form new file mode 100644 index 000000000..a0b3209bf --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel1.form @@ -0,0 +1,247 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel1.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel1.java new file mode 100644 index 000000000..4d964d15f --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel1.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2009-2010 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.codeless.wizard; + +import java.awt.event.ActionListener; +import java.io.File; +import javax.swing.JPanel; +import org.openide.filesystems.FileChooserBuilder; + +public final class CodelessProjectWizardVisualPanel1 extends JPanel { + + /** Creates new form CodelessProjectWizardVisualPanel1 */ + public CodelessProjectWizardVisualPanel1() { + initComponents(); + } + + @Override + public String getName() { + return "Specify Folders"; + } + + public String getProjectPath(){ + return jTextField1.getText(); + } + + public String getAssetsPath(){ + return jTextField2.getText(); + } + + public void setListener(ActionListener listener){ + jTextField1.addActionListener(listener); + jTextField2.addActionListener(listener); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jLabel5 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jLabel7 = new javax.swing.JLabel(); + jLabel8 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel2 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + jToolBar2 = new javax.swing.JToolBar(); + jLabel2 = new javax.swing.JLabel(); + jPanel3 = new javax.swing.JPanel(); + jTextField2 = new javax.swing.JTextField(); + jButton2 = new javax.swing.JButton(); + jLabel4 = new javax.swing.JLabel(); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jPanel1.border.title"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel5.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel6.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel7.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel8.text")); // NOI18N + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel6) + .addComponent(jLabel7) + .addComponent(jLabel5) + .addComponent(jLabel8)) + .addContainerGap(22, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel7) + .addGap(18, 18, 18) + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 23, Short.MAX_VALUE) + .addComponent(jLabel8) + .addContainerGap()) + ); + + jLabel3.setFont(new java.awt.Font("Lucida Grande", 0, 12)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel3.text")); // NOI18N + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel1.text")); // NOI18N + jToolBar1.add(jLabel1); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel2); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jTextField1.text")); // NOI18N + jToolBar1.add(jTextField1); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar1.add(jButton1); + + jToolBar2.setFloatable(false); + jToolBar2.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel2.text")); // NOI18N + jToolBar2.add(jLabel2); + + jPanel3.setPreferredSize(new java.awt.Dimension(100, 0)); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar2.add(jPanel3); + + jTextField2.setText(org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jTextField2.text")); // NOI18N + jToolBar2.add(jTextField2); + + org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + jToolBar2.add(jButton2); + + jLabel4.setFont(new java.awt.Font("Lucida Grande", 0, 12)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel1.class, "CodelessProjectWizardVisualPanel1.jLabel4.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 447, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jToolBar1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE) + .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 44, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + FileChooserBuilder builder = new FileChooserBuilder(System.getProperty("user.home")); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Project Folder"); + File file = builder.showOpenDialog(); + if (file != null) { + jTextField1.setText(file.getPath()); + } + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + File path=new File(jTextField1.getText()); + if(path.isDirectory()){ + FileChooserBuilder builder = new FileChooserBuilder(path.getAbsolutePath()); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Assets Folder"); + File file = builder.showOpenDialog(); + if (file != null) { + try { + jTextField2.setText(file.getAbsolutePath().substring(path.getAbsolutePath().length(), file.getAbsolutePath().length())); + } catch (Exception e) { + } + } + } + }//GEN-LAST:event_jButton2ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToolBar jToolBar2; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel2.form b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel2.form new file mode 100644 index 000000000..48fae529e --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel2.form @@ -0,0 +1,45 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel2.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel2.java new file mode 100644 index 000000000..b7eba26eb --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardVisualPanel2.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009-2010 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.codeless.wizard; + +import javax.swing.JPanel; + +public final class CodelessProjectWizardVisualPanel2 extends JPanel { + + /** Creates new form CodelessProjectWizardVisualPanel2 */ + public CodelessProjectWizardVisualPanel2() { + initComponents(); + } + + @Override + public String getName() { + return "Check Project Settings"; + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CodelessProjectWizardVisualPanel2.class, "CodelessProjectWizardVisualPanel2.jLabel1.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() + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addContainerGap(264, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardWizardPanel1.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardWizardPanel1.java new file mode 100644 index 000000000..a057ab4b7 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardWizardPanel1.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2009-2010 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.codeless.wizard; + +import java.awt.Component; +import java.awt.event.ActionListener; +import java.io.File; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.awt.StatusDisplayer; +import org.openide.util.HelpCtx; + +public class CodelessProjectWizardWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private CodelessProjectWizardVisualPanel1 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. + public CodelessProjectWizardVisualPanel1 getComponent() { + if (component == null) { + component = new CodelessProjectWizardVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + public boolean isValid() { +// StatusDisplayer.getDefault().setStatusText("Check: "+component.getProjectPath()); +// if (new File(component.getProjectPath()).isDirectory() +// && new File(component.getProjectPath()+File.separator+component.getAssetsPath()).isDirectory()) { + return true; +// } +// return false; + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + ActionListener listener=((WizardDescriptor)settings).getButtonListener(); + getComponent().setListener(listener); + } + + public void storeSettings(Object settings) { + ((WizardDescriptor) settings).putProperty("PROJECT_FOLDER", component.getProjectPath()); + ((WizardDescriptor) settings).putProperty("ASSETS_FOLDER", component.getAssetsPath()); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardWizardPanel2.java b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardWizardPanel2.java new file mode 100644 index 000000000..1d14a321a --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/codeless/wizard/CodelessProjectWizardWizardPanel2.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2009-2010 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.codeless.wizard; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class CodelessProjectWizardWizardPanel2 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private Component 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. + public Component getComponent() { + if (component == null) { + component = new CodelessProjectWizardVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + } + + public void storeSettings(Object settings) { + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/core-helpset.xml b/sdk/jme3-core/src/com/jme3/gde/core/core-helpset.xml new file mode 100644 index 000000000..cca1a889b --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/core-helpset.xml @@ -0,0 +1,7 @@ + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/errorreport/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/Bundle.properties new file mode 100644 index 000000000..1b5fcaff1 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/Bundle.properties @@ -0,0 +1 @@ +CTL_RendererInfoAction=Check Graphics Capabilities diff --git a/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfo.form b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfo.form new file mode 100644 index 000000000..44d3ca13f --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfo.form @@ -0,0 +1,64 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfo.java b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfo.java new file mode 100644 index 000000000..111a51718 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfo.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * RendererInfo.java + * + * Created on 27.02.2011, 06:17:27 + */ +package com.jme3.gde.core.errorreport; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.renderer.Caps; +import com.jme3.renderer.Renderer; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class RendererInfo extends javax.swing.JDialog { + + /** Creates new form RendererInfo */ + public RendererInfo(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); + updateInfo(); + } + + private void updateInfo() { + try { + jTextArea1.setText(SceneApplication.getApplication().enqueue(new Callable() { + + public String call() throws Exception { + String out = ""; + Renderer renderer = SceneApplication.getApplication().getRenderer(); + EnumSet caps = renderer.getCaps(); + out = out + "Graphics Capabilities\n"; + out = out + "---------------------\n"; + for (Iterator it = caps.iterator(); it.hasNext();) { + Caps caps1 = it.next(); + out = out + caps1.name() + "\n"; + } + return out; + } + }).get()); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane2 = new javax.swing.JScrollPane(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jTextArea1.setColumns(20); + jTextArea1.setEditable(false); + jTextArea1.setFont(new java.awt.Font("Courier", 0, 13)); + jTextArea1.setRows(5); + jTextArea1.setDisabledTextColor(new java.awt.Color(0, 0, 0)); + jScrollPane1.setViewportView(jTextArea1); + + jScrollPane2.setViewportView(jScrollPane1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JTextArea jTextArea1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfoAction.java b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfoAction.java new file mode 100644 index 000000000..8868da619 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/errorreport/RendererInfoAction.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2009-2010 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.errorreport; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JFrame; + +public final class RendererInfoAction implements ActionListener { + + RendererInfo info; + + public void actionPerformed(ActionEvent e) { + if (info == null) { + info = new RendererInfo(new JFrame(), false); + } + info.setLocationRelativeTo(null); + info.setVisible(true); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/help-main.xml b/sdk/jme3-core/src/com/jme3/gde/core/help-main.xml new file mode 100644 index 000000000..dfd2a7781 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/help-main.xml @@ -0,0 +1,49 @@ + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionManager.java b/sdk/jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionManager.java new file mode 100644 index 000000000..558f97fc8 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionManager.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2009-2010 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.j2seproject; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.net.URL; +import java.util.Properties; +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.ant.AntBuildExtender; +import org.netbeans.api.project.libraries.LibraryManager; +import org.netbeans.modules.java.j2seproject.J2SEProject; +import org.netbeans.modules.java.j2seproject.J2SEProjectUtil; +import org.netbeans.modules.java.j2seproject.api.J2SEProjectConfigurations; +import org.netbeans.spi.project.support.ant.EditableProperties; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; + +/** + * A ProjectExtensionManager allows extending jMonkeyPlatform projects with ant tasks. + * @author normenhansen + */ +public class ProjectExtensionManager { + + private String extensionName; + private String extensionVersion; + private String extensionTargets; + private String[] extensionDependencies; + private String antTaskLibrary; + + /** + * Allows extending ant based projects + * @param extensionName Name of the extension + * @param extensionVersion Version of the extension (impl file is recreated when this changes) + * @param extensionTargets String that contains the whole target part of the xxx-impl.xml + * @param extensionDependencies String array with targets and dependencies, has to be multiple of two. First item target, second item dependency third target etc. + * @param antTaskLibrary Name of a library that is added to the project for loading in the ant task, accessible via ${libs.MyLibraryName.classpath}. + */ + public ProjectExtensionManager(String extensionName, String extensionVersion, String extensionTargets, String[] extensionDependencies, String antTaskLibrary) { + this.extensionName = extensionName; + this.extensionVersion = extensionVersion; + this.extensionTargets = extensionTargets; + this.extensionDependencies = extensionDependencies; + } + + public ProjectExtensionManager(String extensionName, String extensionVersion, String extensionTargets, String[] extensionDependencies) { + this.extensionName = extensionName; + this.extensionVersion = extensionVersion; + this.extensionTargets = extensionTargets; + this.extensionDependencies = extensionDependencies; + } + + public ProjectExtensionManager(String extensionName, String extensionVersion, String[] extensionDependencies) { + this.extensionName = extensionName; + this.extensionVersion = extensionVersion; + this.extensionDependencies = extensionDependencies; + } + + public ProjectExtensionManager(String extensionName, String extensionVersion, String extensionTargets) { + this.extensionName = extensionName; + this.extensionVersion = extensionVersion; + this.extensionTargets = extensionTargets; + } + + public ProjectExtensionManager(String extensionName, String extensionVersion) { + this.extensionName = extensionName; + this.extensionVersion = extensionVersion; + } + + /** + * Checks if the extension exists and creates it if not + * @param proj + */ + public void checkExtension(Project proj) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Checking extension.."); + if (!(proj instanceof J2SEProject)) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.WARNING, "Trying to load Assets Properties from non-asset project"); + return; + } + + FileObject projDir = proj.getProjectDirectory(); + final FileObject buildXmlFO = J2SEProjectUtil.getBuildXml((J2SEProject) proj); + if (buildXmlFO == null) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.WARNING, "The project build script does not exist, the project cannot be extended by jMP."); + return; + } + FileObject assetsBuildFile = getImplFile(projDir, true); + AntBuildExtender extender = proj.getLookup().lookup(AntBuildExtender.class); + if (extender != null) { + assert assetsBuildFile != null; + if (extender.getExtension(extensionName) == null) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Creating extension {0}", extensionName); + AntBuildExtender.Extension ext = extender.addExtension(extensionName, assetsBuildFile); + if (extensionDependencies != null) { + for (int i = 0; i < extensionDependencies.length; i += 2) { + String target = extensionDependencies[i]; + String extension = extensionDependencies[i + 1]; + ext.addDependency(target, extension); + } + } + try { + ProjectManager.getDefault().saveProject(proj); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + addAntTaskLibrary(proj, antTaskLibrary); + } + } else { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.WARNING, "Trying to include assets build snippet in project type that doesn't support AntBuildExtender API contract."); + } + } + + private FileObject getImplFile(FileObject projDir, boolean create) { + FileObject assetsImpl = projDir.getFileObject("nbproject/" + extensionName + "-impl.xml"); + if (assetsImpl == null) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "No {0}-impl.xml found", extensionName); + if (create) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Creating {0}-impl.xml", extensionName); + assetsImpl = createImplFile(projDir); + } + } else { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Found {0}-impl.xml", extensionName); + try { + if (create && !assetsImpl.asLines().get(1).startsWith("")) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Updating {0}-impl.xml", extensionName); + assetsImpl.delete(); + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Deleted {0}-impl.xml", extensionName); + assetsImpl = createImplFile(projDir); + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Recreated {0}-impl.xml", extensionName); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + return assetsImpl; + } + + private FileObject createImplFile(FileObject projDir) { + FileLock lock = null; + FileObject file = null; + try { + file = projDir.getFileObject("nbproject").createData(extensionName + "-impl.xml"); + lock = file.lock(); + OutputStreamWriter out = new OutputStreamWriter(file.getOutputStream(lock)); + out.write("\n"); + out.write("\n"); + out.write("\n"); + if (extensionTargets != null) { + out.write(extensionTargets); + } + out.write("\n"); + out.close(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } finally { + if (lock != null) { + lock.releaseLock(); + } + } + return file; + } + + /** + * Removes the extension including all files and libraries + * @param proj + */ + public void removeExtension(Project proj) { + if (!(proj instanceof J2SEProject)) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.WARNING, "Trying to load Assets Properties from non-asset project"); + return; + } + + FileObject projDir = proj.getProjectDirectory(); + final FileObject buildXmlFO = J2SEProjectUtil.getBuildXml((J2SEProject) proj); + if (buildXmlFO == null) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.WARNING, "The project build script does not exist, the project cannot be extended by jMP."); + return; + } + AntBuildExtender extender = proj.getLookup().lookup(AntBuildExtender.class); + if (extender != null) { + if (extender.getExtension(extensionName) != null) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Removing extension {0}", extensionName); + extender.removeExtension(extensionName); + try { + FileObject assetsBuildFile = getImplFile(projDir, false); + if (assetsBuildFile != null) { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Deleting {0}", assetsBuildFile.getNameExt()); + assetsBuildFile.delete(); + } + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.INFO, "Saving project {0}", proj.getProjectDirectory().getName()); + ProjectManager.getDefault().saveProject(proj); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + removeAntTaskLibrary(proj, antTaskLibrary); + } + } else { + Logger.getLogger(ProjectExtensionManager.class.getName()).log(Level.WARNING, "Trying to include assets build snippet in project type that doesn't support AntBuildExtender API contract."); + } + } + + private void addAntTaskLibrary(Project proj, String name) { + if (name == null) { + return; + } + try { + AntBuildExtender extender = proj.getLookup().lookup(AntBuildExtender.class); + if (extender != null) { + LibraryManager.getDefault(); + extender.addLibrary(LibraryManager.getDefault().getLibrary(name)); + ProjectManager.getDefault().saveProject(proj); + } + + } catch (Exception e) { + Exceptions.printStackTrace(e); + } + } + + private void removeAntTaskLibrary(Project proj, String name) { + if (name == null) { + return; + } + try { + AntBuildExtender extender = proj.getLookup().lookup(AntBuildExtender.class); + if (extender != null) { + LibraryManager.getDefault(); + extender.removeLibrary(LibraryManager.getDefault().getLibrary(name)); + ProjectManager.getDefault().saveProject(proj); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** + * Sets the name of a library that will be added for loading with the ant task. + * If set to null no library is added (default). + * @param antTaskLibrary + */ + public void setAntTaskLibrary(String antTaskLibrary) { + this.antTaskLibrary = antTaskLibrary; + } + + /** + * Loads ant targets from a file in the classpath + * @param path + */ + public void loadTargets(String path) { + try { + LineNumberReader in = new LineNumberReader(new InputStreamReader(new URL(path).openStream())); + StringWriter out = new StringWriter(); + String line = in.readLine(); + while (line != null) { + out.write(line + "\n"); + line = in.readLine(); + } + in.close(); + out.close(); + extensionTargets = out.toString(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + + } + + /** + * Adds a run configuration (works direct, no removing) + * @param project + * @param name + * @param properties + */ + public void addRunConfiguration(Project project, String name, Properties properties) { + try { + J2SEProjectConfigurations.createConfigurationFiles(project, name, properties, null); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** + * Adds a run configuration (works direct, no removing) + * @param project + * @param name File name of the configuration + * @param label Label in the dropdown box + * @param runTarget Target for "run" + * @param debugTarget Target for "debug" + */ + public void addRunConfiguration(Project project, String name, String label, String runTarget, String debugTarget) { + try { + EditableProperties properties = new EditableProperties(true); + properties.setProperty("$label", label); + properties.setProperty("$target.run", runTarget); + properties.setProperty("$target.debug", debugTarget); + J2SEProjectConfigurations.createConfigurationFiles(project, name, properties, null); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** + * Adds a run configuration (works direct, no removing) + * @param project + * @param name File name of the configuration + * @param label Label in the dropdown box + * @param runTarget Target for "run" + */ + public void addRunConfiguration(Project project, String name, String label, String runTarget) { + try { + EditableProperties properties = new EditableProperties(true); + properties.setProperty("$label", label); + properties.setProperty("$target.run", runTarget); + J2SEProjectConfigurations.createConfigurationFiles(project, name, properties, null); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void setExtensionDependencies(String[] extensionDependencies) { + this.extensionDependencies = extensionDependencies; + } + + public void setExtensionTargets(String extensionTargets) { + this.extensionTargets = extensionTargets; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionProperties.java b/sdk/jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionProperties.java new file mode 100644 index 000000000..17425b280 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/j2seproject/ProjectExtensionProperties.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2009-2010 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.j2seproject; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.modules.java.j2seproject.J2SEProject; +import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.netbeans.spi.project.support.ant.EditableProperties; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.util.Mutex; +import org.openide.util.MutexException; + +/** + * Allows accessing a defined set of properties of a jMonkeyPlatform project + * @author normenhansen + */ +public class ProjectExtensionProperties { + + private String[] keyList; + private Project project; + private EditableProperties properties; + + /** + * Allows accessing a defined set of properties of a jMonkeyPlatform project + * @param project The project to which the properties are stored + * @param keyList A list of all property keys this list should use + */ + public ProjectExtensionProperties(Project project, String[] keyList) { + this.project = project; + this.keyList = keyList; + properties = new EditableProperties(true); + if (project instanceof J2SEProject) { + load(); + } + } + + public EditableProperties getProperties() { + return properties; + } + + public String getProperty(String key){ + return properties.getProperty(key); + } + + public void setProperty(String key, String value){ + if(value==null){ + properties.remove(key); + }else{ + properties.setProperty(key, value); + } + } + + public void load() { + properties.clear(); + J2SEPropertyEvaluator eval = project.getLookup().lookup(J2SEPropertyEvaluator.class); + if (eval == null) { + return; + } + for (int i = 0; i < keyList.length; i++) { + String string = keyList[i]; + String value = eval.evaluator().getProperty(string); + if (value != null) { + properties.setProperty(string, value); + } + } + } + + public void store() throws IOException { + final FileObject projPropsFO = project.getProjectDirectory().getFileObject(AntProjectHelper.PROJECT_PROPERTIES_PATH); + if (projPropsFO == null) { + return; + } + final EditableProperties ep = new EditableProperties(true); + + try { + final InputStream is = projPropsFO.getInputStream(); + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { + + @Override + public Void run() throws Exception { + try { + ep.load(is); + } finally { + if (is != null) { + is.close(); + } + } + putProperties(properties, ep); + OutputStream os = null; + FileLock lock = null; + try { + lock = projPropsFO.lock(); + os = projPropsFO.getOutputStream(lock); + ep.store(os); + } finally { + if (lock != null) { + lock.releaseLock(); + } + if (os != null) { + os.close(); + } + } + return null; + } + }); + } catch (MutexException mux) { + throw (IOException) mux.getException(); + } + + } + + private void putProperties(EditableProperties from, EditableProperties to) { + for (int i = 0; i < keyList.length; i++) { + String string = keyList[i]; + String value = from.getProperty(string); + if (value == null || "".equals(value)) { + to.remove(string); + } else { + to.put(string, value); + } + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/jmewiki.url b/sdk/jme3-core/src/com/jme3/gde/core/jmewiki.url new file mode 100644 index 000000000..15dcd6bb3 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/jmewiki.url @@ -0,0 +1 @@ +http://jmonkeyengine.org/wiki/doku.php/jme3 \ No newline at end of file diff --git a/sdk/jme3-core/src/com/jme3/gde/core/layer.xml b/sdk/jme3-core/src/com/jme3/gde/core/layer.xml new file mode 100644 index 000000000..329c7ca5e --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/layer.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/outputWstcref.xml b/sdk/jme3-core/src/com/jme3/gde/core/outputWstcref.xml new file mode 100644 index 000000000..ae60a2793 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/outputWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/projectTabLogical_tcWstcref.xml b/sdk/jme3-core/src/com/jme3/gde/core/projectTabLogical_tcWstcref.xml new file mode 100644 index 000000000..c3a940999 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/projectTabLogical_tcWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanel.form b/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanel.form new file mode 100644 index 000000000..d6e6c4734 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanel.form @@ -0,0 +1,134 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanel.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanel.java new file mode 100644 index 000000000..17d2ddebe --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanel.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * ProjectAssetsPropertiesPanel.java + * + * Created on 25.04.2010, 00:25:08 + */ +package com.jme3.gde.core.properties; + +import com.jme3.gde.core.assets.AssetsLookupProvider; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.support.ant.EditableProperties; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; + +/** + * + * @author normenhansen + */ +public class AssetsPropertiesPanel extends javax.swing.JPanel implements ActionListener { + + private Project project; + + /** Creates new form ProjectAssetsPropertiesPanel */ + public AssetsPropertiesPanel(Project propertiesFile) { + initComponents(); + this.project = propertiesFile; + loadSettings(); + HelpCtx.setHelpIDString(this, "sdk.application_deployment"); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jCheckBox1 = new javax.swing.JCheckBox(); + jLabel3 = new javax.swing.JLabel(); + jTextField3 = new javax.swing.JTextField(); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(AssetsPropertiesPanel.class, "AssetsPropertiesPanel.jLabel1.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(AssetsPropertiesPanel.class, "AssetsPropertiesPanel.jTextField1.text")); // NOI18N + + jLabel2.setText(org.openide.util.NbBundle.getMessage(AssetsPropertiesPanel.class, "AssetsPropertiesPanel.jLabel2.text")); // NOI18N + + jTextField2.setText(org.openide.util.NbBundle.getMessage(AssetsPropertiesPanel.class, "AssetsPropertiesPanel.jTextField2.text")); // NOI18N + + jCheckBox1.setText(org.openide.util.NbBundle.getMessage(AssetsPropertiesPanel.class, "AssetsPropertiesPanel.jCheckBox1.text")); // NOI18N + + jLabel3.setText(org.openide.util.NbBundle.getMessage(AssetsPropertiesPanel.class, "AssetsPropertiesPanel.jLabel3.text")); // NOI18N + + jTextField3.setText(org.openide.util.NbBundle.getMessage(AssetsPropertiesPanel.class, "AssetsPropertiesPanel.jTextField3.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) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addGap(46, 46, 46) + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addGap(26, 26, 26) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField3, javax.swing.GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE)) + .addComponent(jCheckBox1)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(26, 26, 26) + .addComponent(jLabel1)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(14, 14, 14) + .addComponent(jLabel2)) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(14, 14, 14) + .addComponent(jLabel3)) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(10, 10, 10) + .addComponent(jCheckBox1) + .addContainerGap(164, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + private javax.swing.JTextField jTextField3; + // End of variables declaration//GEN-END:variables + + public void actionPerformed(ActionEvent e) { + e.getActionCommand(); + saveSettings(); + } + + private void loadSettings() { + EditableProperties properties = AssetsLookupProvider.getProperties(project); + if (properties == null) { + Logger.getLogger(AssetsPropertiesPanel.class.getName()).log(Level.WARNING, "Could not obtain properties!"); + return; + } + jTextField1.setText(properties.getProperty("assets.jar.name")); + jTextField2.setText(properties.getProperty("assets.excludes")); + jTextField3.setText(properties.getProperty("assets.folder.name")); + if ("true".equals(properties.getProperty("assets.compress"))) { + jCheckBox1.setSelected(true); + } else { + jCheckBox1.setSelected(false); + } + } + + private void saveSettings() { + EditableProperties properties = AssetsLookupProvider.getProperties(project); + if (properties == null) { + Logger.getLogger(AssetsPropertiesPanel.class.getName()).log(Level.WARNING, "Could not obtain properties!"); + return; + } + //TODO: lock problems? properties that are loaded are not set -> assets.folder.name + + properties.setProperty("assets.jar.name", jTextField1.getText()); + properties.setProperty("assets.excludes", jTextField2.getText()); + properties.setProperty("assets.folder.name", jTextField3.getText()); + if (jCheckBox1.isSelected()) { + properties.setProperty("assets.compress", "true"); + } else { + properties.setProperty("assets.compress", "false"); + } + try { + AssetsLookupProvider.store(properties, project); + } catch (IOException ex) { + Logger.getLogger(AssetsPropertiesPanel.class.getName()).log(Level.WARNING, "Could not store properties!"); + Exceptions.printStackTrace(ex); + } + + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanelProvider.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanelProvider.java new file mode 100644 index 000000000..7fd019289 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/AssetsPropertiesPanelProvider.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +/** + * + * @author normenhansen + */ +import java.util.ResourceBundle; +import javax.swing.JComponent; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; +import org.netbeans.spi.project.ui.support.ProjectCustomizer.Category; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; + +public class AssetsPropertiesPanelProvider implements ProjectCustomizer.CompositeCategoryProvider { + + @ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-java-j2seproject", category="BuildCategory", position = 90) + public static AssetsPropertiesPanelProvider createAssetsPanel() { + return new AssetsPropertiesPanelProvider(); + } + private Project project; + + private AssetsPropertiesPanelProvider() { + } + + @Override + public Category createCategory(Lookup lkp) { + ResourceBundle bundle = NbBundle.getBundle(AssetsPropertiesPanelProvider.class); + ProjectCustomizer.Category toReturn = null; + project = lkp.lookup(Project.class); + if (project == null) { + return toReturn; + } + toReturn = ProjectCustomizer.Category.create( + "assets", + bundle.getString("LBL_Config_assets"), + null); + return toReturn; + } + + @Override + public JComponent createComponent(Category category, Lookup lkp) { + String nm = category.getName(); + AssetsPropertiesPanel panel = new AssetsPropertiesPanel(project); + category.setStoreListener(panel); + return panel; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/properties/Bundle.properties new file mode 100644 index 000000000..66a842887 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/Bundle.properties @@ -0,0 +1,38 @@ +# Copyright (c) 2009-2010 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. + +LBL_Config_assets=Assets +AssetsPropertiesPanel.jLabel2.text=Assets JAR Excludes: +AssetsPropertiesPanel.jTextField1.text=jTextField1 +AssetsPropertiesPanel.jLabel1.text=Assets JAR Name: +AssetsPropertiesPanel.jTextField2.text=jTextField2 +AssetsPropertiesPanel.jCheckBox1.text=Compress Assets JAR +AssetsPropertiesPanel.jLabel3.text=Assets Folder Location: +AssetsPropertiesPanel.jTextField3.text=jTextField3 diff --git a/sdk/jme3-core/src/com/jme3/gde/core/propertiesWstcref.xml b/sdk/jme3-core/src/com/jme3/gde/core/propertiesWstcref.xml new file mode 100644 index 000000000..a706bb6e2 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/propertiesWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java new file mode 100644 index 000000000..d6e838ec3 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009-2010 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.scene; + +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.SimpleFormatter; +import org.openide.windows.IOProvider; +import org.openide.windows.InputOutput; + +/** + * + * @author normenhansen + */ +public class ApplicationLogHandler extends Handler { + + InputOutput io = IOProvider.getDefault().getIO("Application", true); + Formatter formatter = new SimpleFormatter(); + + public ApplicationLogHandler() { + } + + @Override + public void publish(LogRecord record) { + if (record.getLevel().equals(Level.SEVERE)) { + io.getErr().println(formatter.formatMessage(record)); + } + else if (record.getLevel().equals(Level.WARNING)) { + io.getErr().println(formatter.formatMessage(record)); + } + else { + io.getOut().println(formatter.formatMessage(record)); + } + } + + @Override + public void flush() { +// throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void close() throws SecurityException { + io.getOut().close(); + io.getErr().close(); +// throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/OffScenePanel.form b/sdk/jme3-core/src/com/jme3/gde/core/scene/OffScenePanel.form new file mode 100644 index 000000000..309b4c532 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/OffScenePanel.form @@ -0,0 +1,32 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/OffScenePanel.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/OffScenePanel.java new file mode 100644 index 000000000..8180664b8 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/OffScenePanel.java @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * ScenePanel.java + * + * Created on 06.11.2010, 02:25:02 + */ +package com.jme3.gde.core.scene; + +import com.jme3.light.PointLight; +import com.jme3.math.ColorRGBA; +import com.jme3.math.FastMath; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.post.SceneProcessor; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Image.Format; +import com.jme3.util.BufferUtils; +import com.jme3.util.Screenshots; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.nio.ByteBuffer; +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author normenhansen + */ +public class OffScenePanel extends javax.swing.JPanel implements SceneProcessor { + + private int width = 640, height = 480; + private ByteBuffer cpuBuf; +// private byte[] cpuArray; + private Node rootNode = new Node("Root Node"); + private FrameBuffer offBuffer; + private ViewPort viewPort; + private Camera camera; + private RenderManager rm; + //AWT image + private final Object imageLock = new Object(); + private BufferedImage image; + private AffineTransform tx = AffineTransform.getScaleInstance(1, -1); + private AffineTransformOp op; + //camera + protected Quaternion rot = new Quaternion(); + protected Vector3f vector = new Vector3f(); + protected Vector3f focus = new Vector3f(); + protected PointLight light; + + public OffScenePanel() { + this(640, 480); + } + + /** Creates new form ScenePanel */ + public OffScenePanel(int width, int height) { + this.width = width; + this.height = height; + initComponents(); + } + + public void resizeGLView(final int x, final int y) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + width = x; + height = y; + if (viewPort != null) { + synchronized (imageLock) { + setupOffBuffer(); + } + } + return null; + } + }); + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + Dimension dim = new Dimension(x, y); + setPreferredSize(dim); + validate(); + } + }); + } + + public void startPreview() { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + setupOffView(); + setupOffBuffer(); + setupScene(); + return null; + } + }); + } + + public void stopPreview() { + //TODO add your handling code here: + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + SceneApplication.getApplication().getRenderManager().removePreView(viewPort); + return null; + } + }); + Logger.getLogger(OffScenePanel.class.getName()).log(Level.INFO, "Component hidden"); + } + + private void setupScene() { + //setup framebuffer's cam + camera.setFrustumPerspective(45f, 1f, 1f, 1000f); + camera.setLocation(new Vector3f(5f, 5f, 5f)); + camera.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y); + + // setup framebuffer's scene + light = new PointLight(); + light.setPosition(camera.getLocation()); + light.setColor(ColorRGBA.White); + rootNode.addLight(light); + // attach the scene to the viewport to be rendered + viewPort.attachScene(rootNode); + } + + private void setupOffBuffer() { + image = new BufferedImage(width, height, + BufferedImage.TYPE_4BYTE_ABGR); + cpuBuf = BufferUtils.createByteBuffer(width * height * 4); +// cpuArray = new byte[width * height * 4]; + offBuffer = new FrameBuffer(width, height, 0); + //setup framebuffer to use texture + offBuffer.setDepthBuffer(Format.Depth); + offBuffer.setColorBuffer(Format.RGBA8); + //set viewport to render to offscreen framebuffer + viewPort.setOutputFrameBuffer(offBuffer); + camera.resize(width, height, false); + } + + private void setupOffView() { + camera = new Camera(width, height); + // create a pre-view. a view that is rendered before the main view + viewPort = SceneApplication.getApplication().getRenderManager().createPreView("Offscreen View", camera); + viewPort.setBackgroundColor(ColorRGBA.DarkGray); + viewPort.setClearEnabled(true); + viewPort.addProcessor(this); + } + + public void initialize(RenderManager rm, ViewPort vp) { + this.rm = rm; + } + + public void reshape(ViewPort vp, int i, int i1) { + } + + public boolean isInitialized() { + return true; + } + + public void preFrame(float f) { + light.setPosition(camera.getLocation()); + rootNode.updateLogicalState(f); + rootNode.updateGeometricState(); + } + + public void postQueue(RenderQueue rq) { + } + + public void postFrame(FrameBuffer fb) { +// cpuBuf.clear(); + SceneApplication.getApplication().getRenderer().readFrameBuffer(offBuffer, cpuBuf); +// +// // copy native memory to java memory +// cpuBuf.clear(); +// cpuBuf.get(cpuArray); +// cpuBuf.clear(); +// +// // flip the components the way AWT likes them +// for (int i = 0; i < width * height * 4; i += 4) { +// byte b = cpuArray[i + 0]; +// byte g = cpuArray[i + 1]; +// byte r = cpuArray[i + 2]; +// byte a = cpuArray[i + 3]; +// +// cpuArray[i + 0] = a; +// cpuArray[i + 1] = b; +// cpuArray[i + 2] = g; +// cpuArray[i + 3] = r; +// } + + synchronized (imageLock) { + Screenshots.convertScreenShot(cpuBuf, image); +// WritableRaster wr = image.getRaster(); +// DataBufferByte db = (DataBufferByte) wr.getDataBuffer(); +// System.arraycopy(cpuArray, 0, db.getData(), 0, cpuArray.length); + } + repaint(); + } + + public void cleanup() { + } + + @Override + public void paintComponent(Graphics gfx) { + super.paintComponent(gfx); + Graphics2D g2d = (Graphics2D) gfx; + synchronized (imageLock) { + if (image != null) { + tx.translate(0, -image.getHeight()); + if (op == null) { + op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + } + g2d.drawImage(image, null, 0, 0); + } + } + } + + public Node getRootNode() { + return rootNode; + } + + public Camera getCamera() { + return camera; + } + + public ViewPort getViewPort() { + return viewPort; + } + + /** + * threadsafe attach to root node + * @param spat + */ + public void attach(final Spatial spat) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + rootNode.attachChild(spat); + return null; + } + }); + } + + /** + * threadsafe detach from root node + * @param spat + */ + public void detach(final Spatial spat) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + rootNode.detachChild(spat); + return null; + } + }); + } + + public void setCamFocus(final Vector3f focus) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doSetCamFocus(focus); + return null; + } + }); + + } + + public void doSetCamFocus(final Vector3f focus_) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + focus.set(focus_); + camera.setLocation(focus_.add(vector, camera.getLocation())); + return null; + } + }); + } + + /* + * methods to move camera (threadsafe) + */ + public void rotateCamera(final Vector3f axis, final float amount_) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + float amount = amount_; + if (axis.equals(camera.getLeft())) { + float elevation = -FastMath.asin(camera.getDirection().y); + amount = Math.min(Math.max(elevation + amount, + -FastMath.HALF_PI), FastMath.HALF_PI) + - elevation; + } + rot.fromAngleAxis(amount, axis); + camera.getLocation().subtract(focus, vector); + rot.mult(vector, vector); + focus.add(vector, camera.getLocation()); + + Quaternion curRot = camera.getRotation().clone(); + camera.setRotation(rot.mult(curRot)); + return null; + } + }); + } + + public void panCamera(final float left, final float up) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + camera.getLeft().mult(left, vector); + vector.scaleAdd(up, camera.getUp(), vector); + vector.multLocal(camera.getLocation().distance(focus)); + camera.setLocation(camera.getLocation().add(vector)); + focus.addLocal(vector); + return null; + } + }); + } + + public void moveCamera(final float forward) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + camera.getDirection().mult(forward, vector); + camera.setLocation(camera.getLocation().add(vector)); + return null; + } + }); + } + + public void zoomCamera(final float amount_) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + float amount = amount_; + amount = camera.getLocation().distance(focus) * amount; + float dist = camera.getLocation().distance(focus); + amount = dist - Math.max(0f, dist - amount); + Vector3f loc = camera.getLocation().clone(); + loc.scaleAdd(amount, camera.getDirection(), loc); + camera.setLocation(loc); + return null; + } + }); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + addComponentListener(new java.awt.event.ComponentAdapter() { + public void componentHidden(java.awt.event.ComponentEvent evt) { + OffScenePanel.this.componentHidden(evt); + } + }); + addContainerListener(new java.awt.event.ContainerAdapter() { + public void componentRemoved(java.awt.event.ContainerEvent evt) { + OffScenePanel.this.componentRemoved(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void componentHidden(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_componentHidden +// removePreView(); + }//GEN-LAST:event_componentHidden + + private void componentRemoved(java.awt.event.ContainerEvent evt) {//GEN-FIRST:event_componentRemoved + // TODO add your handling code here: +// removePreView(); + }//GEN-LAST:event_componentRemoved + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/PreviewRequest.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/PreviewRequest.java new file mode 100644 index 000000000..36fc2fb36 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/PreviewRequest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009-2010 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.scene; + +import com.jme3.scene.Spatial; +import java.awt.image.BufferedImage; + +/** + * + * @author normenhansen + */ +public class PreviewRequest { + private Object requester; + private Spatial spatial; + private BufferedImage image; + + public PreviewRequest(Object requester, Spatial spatial) { + this.requester = requester; + this.spatial = spatial; + } + + /** + * @return the requester + */ + public Object getRequester() { + return requester; + } + + /** + * @return the spatial + */ + public Spatial getSpatial() { + return spatial; + } + + /** + * @return the image + */ + public BufferedImage getImage() { + return image; + } + + /** + * @param image the image to set + */ + public void setImage(BufferedImage image) { + this.image = image; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java new file mode 100644 index 000000000..65bae7921 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2009-2010 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.scene; + +import com.jme3.app.Application; +import com.jme3.app.StatsView; +import com.jme3.font.BitmapFont; +import com.jme3.font.BitmapText; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.scene.processors.WireProcessor; +import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.input.FlyByCamera; +import com.jme3.input.MouseInput; +import com.jme3.input.controls.MouseAxisTrigger; +import com.jme3.input.controls.MouseButtonTrigger; +import com.jme3.light.PointLight; +import com.jme3.material.RenderState; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue.Bucket; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.Spatial.CullHint; +import com.jme3.system.AppSettings; +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressHandleFactory; +import org.netbeans.spi.project.LookupProvider; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Message; +import org.openide.awt.StatusDisplayer; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; +import org.openide.util.lookup.Lookups; + +/** + * + * @author normenhansen + */ +public class SceneApplication extends Application implements LookupProvider, LookupListener { + + private PointLight camLight; + private static SceneApplication application; + + public static SceneApplication getApplication() { + if (application == null) { + application = new SceneApplication(); + } + return application; + } + protected Node rootNode = new Node("Root Node"); + protected Node guiNode = new Node("Gui Node"); + private Node statsGuiNode = new Node("Stats Gui Node"); + protected Node toolsNode = new Node("Tools Node"); + private SceneCameraController camController; + //preview variables + protected float secondCounter = 0.0f; + protected BitmapText fpsText; + protected StatsView statsView; + protected FlyByCamera flyCam; + protected boolean showSettings = true; + private SceneRequest currentSceneRequest; + private ConcurrentLinkedQueue listeners = new ConcurrentLinkedQueue(); + private ScenePreviewProcessor previewProcessor; + private Lookup.Result nodeSelectionResult; + private ApplicationLogHandler logHandler = new ApplicationLogHandler(); + private WireProcessor wireProcessor; + private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening SceneViewer.."); + private boolean sceneActive = true; + private String lastError = ""; + private boolean started = false; + + public SceneApplication() { + progressHandle.start(7); + try { + AppSettings newSetting = new AppSettings(true); + newSetting.setFrameRate(30); + setSettings(newSetting); + + Logger.getLogger("com.jme3").addHandler(logHandler); + + setPauseOnLostFocus(false); + + //add listener for project selection + nodeSelectionResult = Utilities.actionsGlobalContext().lookupResult(JmeSpatial.class); + nodeSelectionResult.addLookupListener(this); + + createCanvas(); + getContext().setAutoFlushFrames(true); + getContext().setSystemListener(this); + progressHandle.progress("initialize Base Application", 1); + } catch (Exception e) { + getProgressHandle().finish(); + SceneViewerTopComponent.showOpenGLError(e.toString()); + } catch (Error e) { + getProgressHandle().finish(); + SceneViewerTopComponent.showOpenGLError(e.toString()); + } + } + + private void loadFPSText() { + BitmapFont font = assetManager.loadFont("Interface/Fonts/Default.fnt"); + + fpsText = new BitmapText(font, false); + fpsText.setSize(font.getCharSet().getRenderedSize()); + fpsText.setLocalTranslation(0, fpsText.getLineHeight(), 0); + fpsText.setText("Frames per second"); + statsGuiNode.attachChild(fpsText); + } + + public void loadStatsView() { + statsView = new StatsView("Statistics View", assetManager, renderer.getStatistics()); + // move it up so it appears above fps text + statsView.setLocalTranslation(0, fpsText.getLineHeight(), 0); + statsGuiNode.attachChild(statsView); +// guiNode.attachChild(statsGuiNode); + } + + @Override + public void initialize() { + try { + super.initialize(); + getProgressHandle().progress("Setup Camera Controller", 2); + //create camera controler + camController = new SceneCameraController(cam, inputManager); + //create preview view + getProgressHandle().progress("Setup Preview Scene", 3); + + previewProcessor = new ScenePreviewProcessor(); + previewProcessor.setupPreviewView(); + + // enable depth test and back-face culling for performance + renderer.applyRenderState(RenderState.DEFAULT); + + getProgressHandle().progress("Prepare Camera", 4); + camLight = new PointLight(); + camLight.setColor(ColorRGBA.White); + + getProgressHandle().progress("Prepare Stats View", 5); + guiNode.setQueueBucket(Bucket.Gui); + guiNode.setCullHint(CullHint.Never); + loadFPSText(); + loadStatsView(); + getProgressHandle().progress("Attach Scene to Viewport", 6); + viewPort.attachScene(rootNode); + viewPort.attachScene(toolsNode); + guiViewPort.attachScene(guiNode); + cam.setLocation(new Vector3f(0, 0, 10)); + + getProgressHandle().progress("Create", 6); + wireProcessor = new WireProcessor(assetManager); + getProgressHandle().finish(); + + inputManager.addMapping("MouseAxisX", new MouseAxisTrigger(MouseInput.AXIS_X, false)); + inputManager.addMapping("MouseAxisY", new MouseAxisTrigger(MouseInput.AXIS_Y, false)); + inputManager.addMapping("MouseAxisX-", new MouseAxisTrigger(MouseInput.AXIS_X, true)); + inputManager.addMapping("MouseAxisY-", new MouseAxisTrigger(MouseInput.AXIS_Y, true)); + inputManager.addMapping("MouseWheel", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false)); + inputManager.addMapping("MouseWheel-", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true)); + inputManager.addMapping("MouseButtonLeft", new MouseButtonTrigger(0)); + inputManager.addMapping("MouseButtonMiddle", new MouseButtonTrigger(2)); + inputManager.addMapping("MouseButtonRight", new MouseButtonTrigger(1)); + started = true; + } catch (Exception e) { + getProgressHandle().finish(); + SceneViewerTopComponent.showOpenGLError(e.toString()); + } catch (Error e) { + getProgressHandle().finish(); + SceneViewerTopComponent.showOpenGLError(e.toString()); + } + } + + @Override + public void update() { + if (speed == 0) { + return; + } + try { + super.update(); + float tpf = timer.getTimePerFrame(); + camLight.setPosition(cam.getLocation()); + secondCounter += tpf; + int fps = (int) timer.getFrameRate(); + if (secondCounter >= 1.0f) { + fpsText.setText("Frames per second: " + fps); + secondCounter = 0.0f; + } + getStateManager().update(tpf); + rootNode.updateLogicalState(tpf); + guiNode.updateLogicalState(tpf); + toolsNode.updateLogicalState(tpf); + rootNode.updateGeometricState(); + guiNode.updateGeometricState(); + toolsNode.updateGeometricState(); + getStateManager().render(renderManager); + renderManager.render(tpf); + getStateManager().postRender(); + } catch (Exception e) { + handleError(e.getMessage(), e); + } catch (Error e) { + handleError(e.getMessage(), e); + } + } + + @Override + public Future enqueue(Callable callable) { + if (sceneActive) { + return super.enqueue(callable); + } else { + try { + final V value = callable.call(); + return new Future() { + + public boolean cancel(boolean mayInterruptIfRunning) { + return true; + } + + public boolean isCancelled() { + return false; + } + + public boolean isDone() { + return true; + } + + public V get() throws InterruptedException, ExecutionException { + return value; + } + + public V get(long timeout, TimeUnit unit) { + return value; + } + }; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + } + + //TODO: Lookup for Application + public Lookup createAdditionalLookup(Lookup baseContext) { + return Lookups.fixed(getApplication()); + } + + /** + * updates node selection + * @param ev + */ + public void resultChanged(LookupEvent ev) { + Collection collection = nodeSelectionResult.allInstances(); + for (Iterator it = collection.iterator(); it.hasNext();) { + Object object = it.next(); + if (object instanceof JmeSpatial) { + return; + } + } + } + + //TODO: replace with Lookup functionality + public void addSceneListener(SceneListener listener) { + listeners.add(listener); + } + + public void removeSceneListener(SceneListener listener) { + listeners.remove(listener); + } + + private void notifySceneListeners() { + for (Iterator it = listeners.iterator(); it.hasNext();) { + SceneListener sceneViewerListener = it.next(); + sceneViewerListener.sceneRequested(currentSceneRequest); + } + } + + private boolean notifySceneListeners(SceneRequest closed) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + SceneListener sceneViewerListener = it.next(); + if (!sceneViewerListener.sceneClose(closed)) { + return false; + } + } + return true; + } + + public void notifySceneListeners(PreviewRequest request) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + SceneListener sceneViewerListener = it.next(); + sceneViewerListener.previewRequested(request); + } + } + + public void createPreview(final PreviewRequest request) { + previewProcessor.addRequest(request); + } + + /** + * method to display the node tree of a plugin (threadsafe) + * @param tree + */ + public void requestScene(final SceneRequest request) { + enqueue(new Callable() { + + public Object call() throws Exception { + if (!closeCurrentScene()) { + return null; + } + if (request.getManager() != null) { + assetManager = request.getManager().getManager(); + } + if (request.getRequester() instanceof SceneApplication) { + camController.enable(); + } else { + camController.disable(); + } + currentSceneRequest = request; + if (request.getDataObject() != null) { + setSelectedNode(request.getDataObject().getNodeDelegate()); + } + setHelpContext(request.getHelpCtx()); + getCurrentSceneRequest().setDisplayed(true); + Spatial model = request.getRootNode(); + if (model == null) { + StatusDisplayer.getDefault().setStatusText("could not load Spatial from request: " + getCurrentSceneRequest().getWindowTitle()); + return null; + } + rootNode.attachChild(model); + if (request.getToolNode() != null) { + toolsNode.attachChild(request.getToolNode()); + } + notifySceneListeners(); + setWindowTitle(request.getWindowTitle()); + return null; + } + }); + } + + /** + * method to close a scene displayed by a scene request (threadsafe) + * @param tree + */ + public void closeScene(final SceneRequest request) { + enqueue(new Callable() { + + public Object call() throws Exception { + if (request == currentSceneRequest) { + if (closeCurrentScene()) { + if (request.getRequester() instanceof SceneApplication) { + camController.disable(); + } + currentSceneRequest = null; + setWindowTitle("SceneViewer"); + } + } + return null; + } + }); + } + + private boolean closeCurrentScene() { + return closeCurrentScene(false); + } + + private boolean closeCurrentScene(boolean force) { + if (currentSceneRequest != null) { + if (!notifySceneListeners(currentSceneRequest)) { + if (!force) { + return false; + } + } + currentSceneRequest.setDisplayed(false); + } + toolsNode.detachAllChildren(); + rootNode.detachAllChildren(); + setSelectedNode(null); + setHelpContext(null); + resetCam(); + currentSceneRequest = null; + lastError = ""; + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + SceneUndoRedoManager manager = Lookup.getDefault().lookup(SceneUndoRedoManager.class); + if (manager != null) { + manager.discardAllEdits(); + } + } + }); + return true; + } + + private void resetCam() { + cam.setLocation(new Vector3f(0, 0, 10)); + cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y); + } + + private void setWindowTitle(final String string) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + SceneViewerTopComponent.findInstance().setDisplayName(string); + SceneViewerTopComponent.findInstance().requestActive(); + } + }); + } + + public void setSelectedNode(final org.openide.nodes.Node node) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (node == null) { + SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{}); + } else { + SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{node}); + } + } + }); + } + + public void setHelpContext(final HelpCtx helpContext) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (helpContext == null) { + SceneViewerTopComponent.findInstance().setHelpContext(new HelpCtx("com.jme3.gde.core.sceneviewer")); + } else { + SceneViewerTopComponent.findInstance().setHelpContext(helpContext); + } + } + }); + } + + public void enableCamLight(final boolean enabled) { + enqueue(new Callable() { + + public Object call() throws Exception { + if (enabled) { + rootNode.removeLight(camLight); + rootNode.addLight(camLight); + } else { + rootNode.removeLight(camLight); + } + return null; + } + }); + } + + public void enableStats(final boolean enabled) { + enqueue(new Callable() { + + public Object call() throws Exception { + if (enabled) { + guiNode.attachChild(statsGuiNode); + } else { + guiNode.detachChild(statsGuiNode); + } + return null; + } + }); + } + + public void enableWireFrame(final boolean selected) { + enqueue(new Callable() { + + public Object call() throws Exception { + if (selected) { + viewPort.addProcessor(wireProcessor); + } else { + viewPort.removeProcessor(wireProcessor); + } + return null; + } + }); + } + + /** + * @return the currentSceneRequest + */ + public SceneRequest getCurrentSceneRequest() { + return currentSceneRequest; + } + + /** + * @return the sceneActive + */ + public boolean isSceneActive() { + return sceneActive; + } + + /** + * @param sceneActive the sceneActive to set + */ + public void setSceneActive(boolean sceneActive) { + this.sceneActive = sceneActive; + } + + @Override + public void handleError(String msg, Throwable t) { + progressHandle.finish(); + if (!started) { + SceneViewerTopComponent.showOpenGLError(msg); + Exceptions.printStackTrace(t); + } else { + if (lastError != null && !lastError.equals(msg)) { + Message mesg = new NotifyDescriptor.Message( + "Error in scene!\n" + + "(" + t + ")", + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notifyLater(mesg); + Exceptions.printStackTrace(t); + lastError = msg; + } + } + } + + public RenderManager getRenderManager() { + return renderManager; + } + + public ViewPort getViewPort() { + return viewPort; + } + + public ViewPort getGuiViewPort() { + return guiViewPort; + } + + public Node getGuiNode() { + return guiNode; + } + + public ProgressHandle getProgressHandle() { + return progressHandle; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneCameraController.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneCameraController.java new file mode 100644 index 000000000..1d045c863 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneCameraController.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009-2010 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.scene; + +import com.jme3.gde.core.scene.controller.AbstractCameraController; +import com.jme3.input.InputManager; +import com.jme3.renderer.Camera; + +/** + * + * @author normenhansen + */ +public class SceneCameraController extends AbstractCameraController { + + public SceneCameraController(Camera cam, InputManager inputManager) { + super(cam,inputManager); + } + + @Override + protected void checkClick(int button) { + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneListener.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneListener.java new file mode 100644 index 000000000..dadc19346 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneListener.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009-2010 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.scene; + +/** + * To be replaced with Lookup functionality + * @author normenhansen + */ +public interface SceneListener { + + public void sceneRequested(SceneRequest request); + + public boolean sceneClose(SceneRequest request); + + public void previewRequested(PreviewRequest request); + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/ScenePreviewProcessor.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/ScenePreviewProcessor.java new file mode 100644 index 000000000..8f7e822ed --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/ScenePreviewProcessor.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2009-2010 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.scene; + +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.light.PointLight; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import com.jme3.post.SceneProcessor; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.scene.Node; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Image.Format; +import com.jme3.util.BufferUtils; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import java.awt.image.WritableRaster; +import java.nio.ByteBuffer; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * + * @author normenhansen + */ +public class ScenePreviewProcessor implements SceneProcessor { + + private static final int width = 120, height = 120; + private final ByteBuffer cpuBuf = BufferUtils.createByteBuffer(width * height * 4); + private final byte[] cpuArray = new byte[width * height * 4]; + protected Node previewNode = new Node("Preview Node"); + protected JmeSpatial previewSpat = null; + private FrameBuffer offBuffer; + private ViewPort offView; + private Camera offCamera; + private ConcurrentLinkedQueue previewQueue = new ConcurrentLinkedQueue(); + private PreviewRequest currentPreviewRequest; + private RenderManager rm; + + public void addRequest(PreviewRequest request) { + previewQueue.add(request); + } + + private void update(float tpf) { + previewNode.updateLogicalState(tpf); + previewNode.updateGeometricState(); + } + + public void setupPreviewView() { + offCamera = new Camera(width, height); + + // create a pre-view. a view that is rendered before the main view + offView = SceneApplication.getApplication().getRenderManager().createPreView("Offscreen View", offCamera); + offView.setBackgroundColor(ColorRGBA.DarkGray); + offView.setClearEnabled(true); + + offView.addProcessor(this); + + // create offscreen framebuffer + offBuffer = new FrameBuffer(width, height, 0); + + //setup framebuffer's cam + offCamera.setFrustumPerspective(45f, 1f, 1f, 1000f); + offCamera.setLocation(new Vector3f(5f, 5f, 5f)); + offCamera.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y); + + //setup framebuffer to use texture + offBuffer.setDepthBuffer(Format.Depth); + offBuffer.setColorBuffer(Format.RGBA8); + + //set viewport to render to offscreen framebuffer + offView.setOutputFrameBuffer(offBuffer); + + // setup framebuffer's scene + PointLight light = new PointLight(); + light.setPosition(offCamera.getLocation()); + light.setColor(ColorRGBA.White); + previewNode.addLight(light); + + // attach the scene to the viewport to be rendered + offView.attachScene(previewNode); + } + + public void initialize(RenderManager rm, ViewPort vp) { + this.rm = rm; + } + + public void reshape(ViewPort vp, int i, int i1) { + } + + public boolean isInitialized() { + return true; + } + + public void preFrame(float f) { + currentPreviewRequest = previewQueue.poll(); + if (currentPreviewRequest != null) { + previewNode.attachChild(currentPreviewRequest.getSpatial()); + } + update(f); + } + + public void postQueue(RenderQueue rq) { + } + + public void postFrame(FrameBuffer fb) { + if (currentPreviewRequest != null) { + cpuBuf.clear(); + SceneApplication.getApplication().getRenderer().readFrameBuffer(offBuffer, cpuBuf); + + // copy native memory to java memory + cpuBuf.clear(); + cpuBuf.get(cpuArray); + cpuBuf.clear(); + + // flip the components the way AWT likes them + for (int i = 0; i < width * height * 4; i += 4) { + byte b = cpuArray[i + 0]; + byte g = cpuArray[i + 1]; + byte r = cpuArray[i + 2]; + byte a = cpuArray[i + 3]; + + cpuArray[i + 0] = a; + cpuArray[i + 1] = b; + cpuArray[i + 2] = g; + cpuArray[i + 3] = r; + } + + BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_4BYTE_ABGR); + WritableRaster wr = image.getRaster(); + DataBufferByte db = (DataBufferByte) wr.getDataBuffer(); + System.arraycopy(cpuArray, 0, db.getData(), 0, cpuArray.length); + + currentPreviewRequest.setImage(image); + previewNode.detachAllChildren(); + SceneApplication.getApplication().notifySceneListeners(currentPreviewRequest); + currentPreviewRequest = null; + } + } + + public void cleanup() { + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java new file mode 100644 index 000000000..048a27faf --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2009-2010 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.scene; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility; +import org.openide.loaders.DataObject; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; + +/** + * + * @author normenhansen + */ +public class SceneRequest { + + private String windowTitle = ""; + private Object requester; + private JmeNode jmeNode; + private com.jme3.scene.Spatial rootNode; + private com.jme3.scene.Node toolNode; + private ProjectAssetManager manager; + private boolean displayed = false; + private DataObject dataObject; + private HelpCtx helpCtx; + + public SceneRequest(Object requester, JmeNode rootNode, ProjectAssetManager manager) { + this.requester = requester; + this.jmeNode = rootNode; + this.rootNode = rootNode.getLookup().lookup(com.jme3.scene.Node.class); + this.manager = manager; + } + + public SceneRequest(Object requester, com.jme3.scene.Spatial rootNode, ProjectAssetManager manager) { + this.requester = requester; + this.rootNode = rootNode; + if (rootNode instanceof com.jme3.scene.Node) { + this.jmeNode = NodeUtility.createNode((com.jme3.scene.Node) rootNode, true); + } + this.manager = manager; + } + + /** + * returns the lookup of the root node + * @return + */ + public Lookup getLookup() { + if (jmeNode != null) { + return jmeNode.getLookup(); + } else { + return Lookups.singleton(new Object()); + } + } + + /** + * @return the windowTitle + */ + public String getWindowTitle() { + return windowTitle; + } + + /** + * @param windowTitle the windowTitle to set in the SceneViewer window + */ + public void setWindowTitle(String windowTitle) { + this.windowTitle = windowTitle; + } + + /** + * @return the requester + */ + public Object getRequester() { + return requester; + } + + /** + * @return the rootNode + */ + public JmeNode getJmeNode() { + return jmeNode; + } + + public com.jme3.scene.Spatial getRootNode() { + return rootNode; + } + + /** + * @return the displayed status + */ + public boolean isDisplayed() { + return displayed; + } + + /** + * @param displayed the displayed to set + */ + public void setDisplayed(boolean displayed) { + this.displayed = displayed; + } + + /** + * @return the projectassetmanager (deprecated, use lookup) + */ + @Deprecated + public ProjectAssetManager getManager() { + return manager; + } + + /** + * @return the toolScene + */ + public com.jme3.scene.Node getToolNode() { + return toolNode; + } + + /** + * Add an additional Node that is not displayed in the SceneExplorer and can be + * used for displaying in-world tools, templates, previews etc. + * @param toolScene the toolScene to set + */ + public void setToolNode(com.jme3.scene.Node toolNode) { + this.toolNode = toolNode; + } + + public DataObject getDataObject() { + return dataObject; + } + + /** + * sets the DataObject associated with this scene + * @param dataObject + */ + public void setDataObject(DataObject dataObject) { + this.dataObject = dataObject; + } + + public HelpCtx getHelpCtx() { + return helpCtx; + } + + /** + * Set the help context for the SceneViewer window + * @param helpCtx + */ + public void setHelpCtx(HelpCtx helpCtx) { + this.helpCtx = helpCtx; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java new file mode 100644 index 000000000..e5118a474 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2009-2010 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.scene.controller; + +import com.jme3.app.Application; +import com.jme3.app.state.AbstractAppState; +import com.jme3.app.state.AppStateManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.input.InputManager; +import com.jme3.input.RawInputListener; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.AnalogListener; +import com.jme3.input.event.JoyAxisEvent; +import com.jme3.input.event.JoyButtonEvent; +import com.jme3.input.event.KeyInputEvent; +import com.jme3.input.event.MouseButtonEvent; +import com.jme3.input.event.MouseMotionEvent; +import com.jme3.math.FastMath; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import java.util.concurrent.Callable; + +/** + * + * @author normenhansen + */ +public abstract class AbstractCameraController extends AbstractAppState implements ActionListener, AnalogListener, RawInputListener{ + + protected boolean leftMouse, rightMouse, middleMouse; + protected float deltaX, deltaY, deltaZ, deltaWheel; + protected int mouseX = 0; + protected int mouseY = 0; + protected Quaternion rot = new Quaternion(); + protected Vector3f vector = new Vector3f(0,0,5); + protected Vector3f focus = new Vector3f(); + protected Camera cam; + protected InputManager inputManager; + protected Object master; + protected boolean moved = false; + protected boolean movedR = false; + protected boolean checkClick = false; + protected boolean checkClickR = false; + + public AbstractCameraController(Camera cam, InputManager inputManager) { + this.cam = cam; + this.inputManager=inputManager; + } + + public void setMaster(Object component) { + this.master = component; + } + + public void enable() { + inputManager.addRawInputListener(this); + inputManager.addListener(this, "MouseAxisX", "MouseAxisY", "MouseAxisX-", "MouseAxisY-", "MouseWheel", "MouseWheel-", "MouseButtonLeft", "MouseButtonMiddle", "MouseButtonRight"); + SceneApplication.getApplication().getStateManager().attach(this); + } + + public void disable() { + inputManager.removeRawInputListener(this); + inputManager.removeListener(this); + SceneApplication.getApplication().getStateManager().detach(this); + } + + public void setCamFocus(final Vector3f focus) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doSetCamFocus(focus); + return null; + } + }); + + } + + public void doSetCamFocus(Vector3f focus) { + cam.setLocation(cam.getLocation().add(focus.subtract(this.focus))); + this.focus.set(focus); + } + + /* + * methods to move camera + */ + protected void rotateCamera(Vector3f axis, float amount) { + if (axis.equals(cam.getLeft())) { + float elevation = -FastMath.asin(cam.getDirection().y); + amount = Math.min(Math.max(elevation + amount, + -FastMath.HALF_PI), FastMath.HALF_PI) + - elevation; + } + rot.fromAngleAxis(amount, axis); + cam.getLocation().subtract(focus, vector); + rot.mult(vector, vector); + focus.add(vector, cam.getLocation()); + + Quaternion curRot = cam.getRotation().clone(); + cam.setRotation(rot.mult(curRot)); + } + + protected void panCamera(float left, float up) { + cam.getLeft().mult(left, vector); + vector.scaleAdd(up, cam.getUp(), vector); + vector.multLocal(cam.getLocation().distance(focus)); + cam.setLocation(cam.getLocation().add(vector)); + focus.addLocal(vector); + } + + protected void moveCamera(float forward) { + cam.getDirection().mult(forward, vector); + cam.setLocation(cam.getLocation().add(vector)); + } + + protected void zoomCamera(float amount) { + amount = cam.getLocation().distance(focus) * amount; + float dist = cam.getLocation().distance(focus); + amount = dist - Math.max(0f, dist - amount); + Vector3f loc = cam.getLocation().clone(); + loc.scaleAdd(amount, cam.getDirection(), loc); + cam.setLocation(loc); + } + + public void onAction(String string, boolean bln, float f) { + if ("MouseButtonLeft".equals(string)) { + if (bln) { + leftMouse = true; + moved = false; + } else { + leftMouse = false; + if (!moved) { + checkClick = true; + } + } + } + if ("MouseButtonRight".equals(string)) { + if (bln) { + rightMouse = true; + movedR = false; + } else { + rightMouse = false; + if (!movedR) { + checkClickR = true; + } + } + } + } + + public void onAnalog(String string, float f1, float f) { + if ("MouseAxisX".equals(string)) { + moved = true; + movedR = true; + if (leftMouse) { + rotateCamera(Vector3f.UNIT_Y, -f1 * 2.5f); + } + if (rightMouse) { + panCamera(f1 * 2.5f, 0); + } + } else if ("MouseAxisY".equals(string)) { + moved = true; + movedR = true; + if (leftMouse) { + rotateCamera(cam.getLeft(), -f1 * 2.5f); + } + if (rightMouse) { + panCamera(0, -f1 * 2.5f); + } + } else if ("MouseAxisX-".equals(string)) { + moved = true; + movedR = true; + if (leftMouse) { + rotateCamera(Vector3f.UNIT_Y, f1 * 2.5f); + } + if (rightMouse) { + panCamera(-f1 * 2.5f, 0); + } + } else if ("MouseAxisY-".equals(string)) { + moved = true; + movedR = true; + if (leftMouse) { + rotateCamera(cam.getLeft(), f1 * 2.5f); + } + if (rightMouse) { + panCamera(0, f1 * 2.5f); + } + } else if ("MouseWheel".equals(string)) { + zoomCamera(.1f); + } else if ("MouseWheel-".equals(string)) { + zoomCamera(-.1f); + } + } + + public void onJoyAxisEvent(JoyAxisEvent jae) { + } + + public void onJoyButtonEvent(JoyButtonEvent jbe) { + } + + public void onMouseMotionEvent(MouseMotionEvent mme) { + mouseX = mme.getX(); + mouseY = mme.getY(); + } + + public void onMouseButtonEvent(MouseButtonEvent mbe) { + } + + public void onKeyEvent(KeyInputEvent kie) { + } + + /**APPSTATE**/ + private boolean appInit = false; + public void initialize(AppStateManager asm, Application aplctn) { + appInit = true; + } + + public boolean isInitialized() { + return appInit; + } + + public void stateAttached(AppStateManager asm) { + } + + public void stateDetached(AppStateManager asm) { + } + + public void update(float f) { + if (checkClick) { + checkClick(0); + checkClick = false; + } + if (checkClickR) { + checkClick(1); + checkClickR = false; + } + } + + protected abstract void checkClick(int button); + + public void render(RenderManager rm) { + } + + public void postRender() { + } + + public void cleanup() { + } + + public void beginInput() { + } + + public void endInput() { + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java new file mode 100644 index 000000000..8f49171ca --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java @@ -0,0 +1,331 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.core.scene.controller; + +import com.jme3.app.Application; +import com.jme3.app.state.AppState; +import com.jme3.app.state.AppStateManager; +import com.jme3.asset.AssetManager; +import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingVolume; +import com.jme3.bullet.collision.PhysicsCollisionObject; +import com.jme3.bullet.control.CharacterControl; +import com.jme3.bullet.control.PhysicsControl; +import com.jme3.bullet.control.GhostControl; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.bullet.control.VehicleControl; +import com.jme3.bullet.util.DebugShapeFactory; +import com.jme3.gde.core.scene.SceneApplication; +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.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.debug.Arrow; +import com.jme3.scene.debug.Grid; +import com.jme3.scene.debug.WireBox; +import java.util.concurrent.Callable; + +/** + * This class can be used or extended by other plugins to display + * standard tools in the tools scene e.g. a cursor etc. + * @author normenhansen + */ +public class SceneToolController implements AppState { + + protected Node toolsNode; + protected boolean showSelection = false; + protected boolean showGrid = false; + protected Node cursor; + protected Geometry grid; + protected Spatial selected; + protected Spatial selectionShape; + protected AssetManager manager; + + public SceneToolController(AssetManager manager) { + this.toolsNode = new Node("ToolsNode"); + initTools(); + SceneApplication.getApplication().getStateManager().attach(this); + } + + public SceneToolController(Node toolsNode, AssetManager manager) { + this.toolsNode = toolsNode; + this.manager = manager; + initTools(); + SceneApplication.getApplication().getStateManager().attach(this); + } + + protected void initTools() { + Material redMat = new Material(manager, "Common/MatDefs/Misc/WireColor.j3md"); + redMat.setColor("Color", ColorRGBA.Red); + Material greenMat = new Material(manager, "Common/MatDefs/Misc/WireColor.j3md"); + greenMat.setColor("Color", ColorRGBA.Green); + Material blueMat = new Material(manager, "Common/MatDefs/Misc/WireColor.j3md"); + blueMat.setColor("Color", ColorRGBA.Blue); + Material grayMat = new Material(manager, "Common/MatDefs/Misc/WireColor.j3md"); + grayMat.setColor("Color", ColorRGBA.Gray); + + //cursor + if (cursor == null) { + cursor = new Node(); + } + cursor.detachAllChildren(); + Geometry cursorArrowX = new Geometry("cursorArrowX", new Arrow(Vector3f.UNIT_X)); + Geometry cursorArrowY = new Geometry("cursorArrowY", new Arrow(Vector3f.UNIT_Y)); + Geometry cursorArrowZ = new Geometry("cursorArrowZ", new Arrow(Vector3f.UNIT_Z)); + cursorArrowX.setMaterial(redMat); + cursorArrowY.setMaterial(greenMat); + cursorArrowZ.setMaterial(blueMat); + cursor.attachChild(cursorArrowX); + cursor.attachChild(cursorArrowY); + cursor.attachChild(cursorArrowZ); + toolsNode.attachChild(cursor); + + //grid + grid = new Geometry("grid", new Grid(20, 20, 1.0f)); + grid.setMaterial(grayMat); + grid.setLocalTranslation(-10, 0, -10); + } + + public void updateSelection(final Spatial spat) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doUpdateSelection(spat); + return null; + } + }); + } + + public void doUpdateSelection(Spatial spat) { + if (showSelection && spat != null) { + if (selected != spat) { + if (selectionShape != null) { + detachSelectionShape(); + } + attachSelectionShape(spat); + } else { + if (selectionShape == null) { + attachSelectionShape(spat); + } + } + } else { + if (selectionShape != null) { + detachSelectionShape(); + } + } + selected = spat; + } + + public void setCursorLocation(final Vector3f location) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doSetCursorLocation(location); + return null; + } + }); + } + + public void doSetCursorLocation(Vector3f location) { + cursor.setLocalTranslation(location); + } + + public void snapCursorToSelection() { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doSnapCursorToSelection(); + return null; + } + }); + } + + public void doSnapCursorToSelection() { + if (selected != null) { + cursor.setLocalTranslation(selected.getWorldTranslation()); + } + } + + protected void attachSelectionShape(Spatial spat) { + if (selectionShape != null) { + selectionShape.removeFromParent(); + selectionShape = null; + } + if (spat instanceof Geometry) { + attachGeometrySelection((Geometry) spat); + } else if (spat.getControl(PhysicsControl.class) != null) { + attachPhysicsSelection(spat); + } else { + attachBoxSelection(spat); + } + } + + protected void attachGeometrySelection(Geometry geom) { + Mesh mesh = geom.getMesh(); + if (mesh == null) { + return; + } + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/WireColor.j3md"); + mat.setColor("Color", ColorRGBA.Blue); + Geometry selectionGeometry = new Geometry("selection_geometry_sceneviewer", mesh); + selectionGeometry.setMaterial(mat); + selectionGeometry.setLocalTransform(geom.getWorldTransform()); + toolsNode.attachChild(selectionGeometry); + selectionShape = selectionGeometry; + } + + protected void attachBoxSelection(Spatial geom) { + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/WireColor.j3md"); + mat.setColor("Color", ColorRGBA.Blue); + BoundingVolume bound = geom.getWorldBound(); + if (bound instanceof BoundingBox) { + BoundingBox bbox = (BoundingBox) bound; + Vector3f extent = new Vector3f(); + bbox.getExtent(extent); + WireBox wireBox=new WireBox(); + wireBox.fromBoundingBox(bbox); + Geometry selectionGeometry = new Geometry("selection_geometry_sceneviewer", wireBox); + selectionGeometry.setMaterial(mat); + selectionGeometry.setLocalTransform(geom.getWorldTransform()); + toolsNode.attachChild(selectionGeometry); + selectionShape = selectionGeometry; + } + } + + protected void attachPhysicsSelection(Spatial geom) { + PhysicsCollisionObject control = geom.getControl(RigidBodyControl.class); + if (control == null) { + control = geom.getControl(VehicleControl.class); + } + if (control == null) { + control = geom.getControl(GhostControl.class); + } + if (control == null) { + control = geom.getControl(CharacterControl.class); + } + if (control == null) { + return; + } + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/WireColor.j3md"); + mat.setColor("Color", ColorRGBA.Blue); + Spatial selectionGeometry = DebugShapeFactory.getDebugShape(control.getCollisionShape()); + if (selectionGeometry != null) { + selectionGeometry.setMaterial(mat); + selectionGeometry.setLocalTransform(geom.getWorldTransform()); + toolsNode.attachChild(selectionGeometry); + selectionShape = selectionGeometry; + } + } + + protected void detachSelectionShape() { + if (selectionShape != null) { + selectionShape.removeFromParent(); + selectionShape = null; + } + } + + public void cleanup() { + detachSelectionShape(); + cursor.removeFromParent(); + grid.removeFromParent(); + SceneApplication.getApplication().getStateManager().detach(this); + } + + //TODO: multithreading! + public Vector3f getCursorLocation() { + return cursor.getLocalTranslation(); + } + + public void setShowSelection(final boolean showSelection) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doSetShowSelection(showSelection); + return null; + } + }); + } + + public void doSetShowSelection(boolean showSelection) { + this.showSelection = showSelection; + if (showSelection && selected != null && selectionShape == null) { + attachSelectionShape(selected); + } else if (!showSelection && selectionShape != null) { + detachSelectionShape(); + } + } + + public void setShowGrid(final boolean showGrid) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doSetShowGrid(showGrid); + return null; + } + }); + } + + public void doSetShowGrid(boolean showGrid) { + this.showGrid = showGrid; + if (showGrid) { + toolsNode.attachChild(grid); + } else { + toolsNode.detachChild(grid); + } + } + + /** + * @return the toolsNode + */ + public Node getToolsNode() { + return toolsNode; + } + + public void initialize(AppStateManager asm, Application aplctn) { +// throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean isInitialized() { + return true; +// throw new UnsupportedOperationException("Not supported yet."); + } + + public void setActive(boolean bln) { +// throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean isActive() { + return true; +// throw new UnsupportedOperationException("Not supported yet."); + } + + public void stateAttached(AppStateManager asm) { +// throw new UnsupportedOperationException("Not supported yet."); + } + + public void stateDetached(AppStateManager asm) { +// throw new UnsupportedOperationException("Not supported yet."); + } + + public void update(float f) { + if (selected == null || selectionShape == null) { + return; + } + selectionShape.setLocalTranslation(selected.getWorldTranslation()); + selectionShape.setLocalRotation(selected.getWorldRotation()); + } + + public void render(RenderManager rm) { +// throw new UnsupportedOperationException("Not supported yet."); + } + + public void postRender() { +// throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/processors/WireProcessor.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/processors/WireProcessor.java new file mode 100644 index 000000000..d137954a7 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/processors/WireProcessor.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009-2010 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.scene.processors; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.SceneProcessor; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.texture.FrameBuffer; + +/** + * + * @author tomas + */ +public class WireProcessor implements SceneProcessor { + + RenderManager renderManager; + Material wireMaterial; + + public WireProcessor(AssetManager manager) { + wireMaterial = new Material(manager, "/Common/MatDefs/Misc/WireColor.j3md"); + wireMaterial.setColor("Color", ColorRGBA.Blue); + } + + public void initialize(RenderManager rm, ViewPort vp) { + renderManager = rm; + } + + public void reshape(ViewPort vp, int w, int h) { + // do nothing + } + + public boolean isInitialized() { + return renderManager != null; + } + + public void preFrame(float tpf) { + } + + public void postQueue(RenderQueue rq) { + renderManager.setForcedMaterial(wireMaterial); + } + + public void postFrame(FrameBuffer out) { + renderManager.setForcedMaterial(null); + } + + public void cleanup() { + renderManager.setForcedMaterial(null); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/processors/wire_color.j3md b/sdk/jme3-core/src/com/jme3/gde/core/scene/processors/wire_color.j3md new file mode 100644 index 000000000..0e980a9d0 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/processors/wire_color.j3md @@ -0,0 +1,31 @@ +MaterialDef Wire Color { + + MaterialParameters { + Vector4 Color + } + + Technique { + VertexShader GLSL100: solid_color.vert + FragmentShader GLSL100: solid_color.frag + + RenderState { + FaceCull Off + Blend Alpha + AlphaTestFalloff 0.01 + Wireframe On + } + + WorldParameters { + WorldViewProjectionMatrix + } + } + + Technique FixedFunc { + RenderState { + FaceCull Off + Blend Alpha + AlphaTestFalloff 0.01 + } + } + +} \ No newline at end of file diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/Bundle.properties new file mode 100644 index 000000000..4bf848d6a --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/Bundle.properties @@ -0,0 +1,4 @@ +CTL_SceneExplorerAction=SceneExplorer +CTL_SceneExplorerTopComponent=SceneExplorer Window +HINT_SceneExplorerTopComponent=This is a SceneExplorer window +SceneExplorerTopComponent.jButton1.text=update diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form new file mode 100644 index 000000000..2801b7a9e --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.form @@ -0,0 +1,64 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java new file mode 100644 index 000000000..8d9a619ab --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/SceneExplorerTopComponent.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2009-2010 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; + +import com.jme3.gde.core.scene.PreviewRequest; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneListener; +import com.jme3.gde.core.scene.SceneRequest; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import java.util.Collection; +import java.util.Iterator; +import java.util.logging.Logger; +import org.openide.util.Lookup.Result; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.actions.CopyAction; +import org.openide.actions.CutAction; +import org.openide.actions.DeleteAction; +import org.openide.actions.PasteAction; +import org.openide.awt.UndoRedo; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; +import org.openide.explorer.view.BeanTreeView; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; +import org.openide.util.actions.SystemAction; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.core.sceneexplorer//SceneExplorer//EN", +autostore = false) +public final class SceneExplorerTopComponent extends TopComponent implements ExplorerManager.Provider, SceneListener, LookupListener { + + private static SceneExplorerTopComponent instance; + /** path to the icon used by the component and its open action */ + static final String ICON_PATH = "com/jme3/gde/core/sceneexplorer/jme-logo.png"; + private static final String PREFERRED_ID = "SceneExplorerTopComponent"; + private SceneRequest request; + private final Result nodeSelectionResult; + private AbstractSceneExplorerNode selectedSpatial; + + public SceneExplorerTopComponent() { + initComponents(); + initActions(); + setName(NbBundle.getMessage(SceneExplorerTopComponent.class, "CTL_SceneExplorerTopComponent")); + setToolTipText(NbBundle.getMessage(SceneExplorerTopComponent.class, "HINT_SceneExplorerTopComponent")); + setIcon(ImageUtilities.loadImage(ICON_PATH, true)); + associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap())); + nodeSelectionResult = Utilities.actionsGlobalContext().lookupResult(AbstractSceneExplorerNode.class); + nodeSelectionResult.addLookupListener(this); + } + + private void initActions() { + CutAction cut = SystemAction.get(CutAction.class); + getActionMap().put(cut.getActionMapKey(), ExplorerUtils.actionCut(explorerManager)); + CopyAction copy = SystemAction.get(CopyAction.class); + getActionMap().put(copy.getActionMapKey(), ExplorerUtils.actionCopy(explorerManager)); + PasteAction paste = SystemAction.get(PasteAction.class); + getActionMap().put(paste.getActionMapKey(), ExplorerUtils.actionPaste(explorerManager)); + DeleteAction delete = SystemAction.get(DeleteAction.class); + getActionMap().put(delete.getActionMapKey(), ExplorerUtils.actionDelete(explorerManager, true)); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + explorerScrollPane = new BeanTreeView(); + jToolBar1 = new javax.swing.JToolBar(); + jButton1 = new javax.swing.JButton(); + + jToolBar1.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(SceneExplorerTopComponent.class, "SceneExplorerTopComponent.jButton1.text")); // NOI18N + jButton1.setFocusable(false); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar1.add(jButton1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addComponent(explorerScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(explorerScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + if (selectedSpatial == null) { + return; + } + selectedSpatial.refresh(false); + }//GEN-LAST:event_jButton1ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane explorerScrollPane; + private javax.swing.JButton jButton1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables + + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized SceneExplorerTopComponent getDefault() { + if (instance == null) { + instance = new SceneExplorerTopComponent(); + } + return instance; + } + + /** + * Obtain the SceneExplorerTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized SceneExplorerTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(SceneExplorerTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof SceneExplorerTopComponent) { + return (SceneExplorerTopComponent) win; + } + Logger.getLogger(SceneExplorerTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public HelpCtx getHelpCtx() { + HelpCtx ctx = new HelpCtx("sdk.scene_explorer"); + //this call is for single components: + //HelpCtx.setHelpIDString(this, "com.jme3.gde.core.sceneviewer"); + return ctx; + } + + @Override + public void componentOpened() { + SceneApplication.getApplication().addSceneListener(this); + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + SceneApplication.getApplication().addSceneListener(this); + // TODO add custom code on component closing + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + @Override + public UndoRedo getUndoRedo() { + return Lookup.getDefault().lookup(UndoRedo.class); + } + + private transient ExplorerManager explorerManager = new ExplorerManager(); + + public ExplorerManager getExplorerManager() { + return explorerManager; + } + + public void resultChanged(LookupEvent ev) { + Collection collection = nodeSelectionResult.allInstances(); + for (Iterator it = collection.iterator(); it.hasNext();) { + Object object = it.next(); + if (object instanceof AbstractSceneExplorerNode) { + selectedSpatial = (AbstractSceneExplorerNode) object; + return; + } + } + selectedSpatial = null; + } + + public void sceneRequested(SceneRequest request) { + this.request = request; + JmeNode node = request.getJmeNode(); + if (node != null) { + explorerManager.setRootContext(node); + explorerManager.getRootContext().setDisplayName(node.getName()); + } + } + + public boolean sceneClose(SceneRequest request) { + this.request = null; + explorerManager.setRootContext(Node.EMPTY); + return true; + } + + public void previewRequested(PreviewRequest request) { + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/jme-logo.png b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/jme-logo.png new file mode 100644 index 000000000..8e98b2f51 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/jme-logo.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/jme-logo24.png b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/jme-logo24.png new file mode 100644 index 000000000..dada2ba22 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/jme-logo24.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java new file mode 100644 index 000000000..d86977c8b --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AbstractSceneExplorerNode.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2009-2010 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.gde.core.sceneexplorer.nodes.properties.SceneExplorerProperty; +import com.jme3.gde.core.sceneexplorer.nodes.properties.ScenePropertyChangeListener; +import org.openide.loaders.DataObject; +import org.openide.nodes.AbstractNode; +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.InstanceContent; +import org.openide.util.lookup.ProxyLookup; + +/** + * + * @author normenhansen + */ +public abstract class AbstractSceneExplorerNode extends AbstractNode implements SceneExplorerNode, ScenePropertyChangeListener { + + protected Children jmeChildren; + protected final InstanceContent lookupContents; + protected boolean readOnly = false; + protected DataObject dataObject; + + public AbstractSceneExplorerNode() { + super(Children.LEAF, new SceneExplorerLookup(new InstanceContent())); + lookupContents = ((SceneExplorerLookup) getLookup()).getInstanceContent(); + } + + public AbstractSceneExplorerNode(Children children, DataObject dataObject) { + super(children, new ProxyLookup(dataObject.getLookup(), new SceneExplorerLookup(new InstanceContent()))); + this.dataObject = dataObject; + lookupContents = getLookup().lookup(SceneExplorerLookup.class).getInstanceContent(); + } + + public AbstractSceneExplorerNode(DataObject dataObject) { + super(Children.LEAF, new ProxyLookup(dataObject != null ? dataObject.getLookup() : Lookup.EMPTY, new SceneExplorerLookup(new InstanceContent()))); + this.dataObject = dataObject; + lookupContents = getLookup().lookup(SceneExplorerLookup.class).getInstanceContent(); + } + + public AbstractSceneExplorerNode(Children children) { + //TODO: OMG! + super(children, children instanceof SceneExplorerChildren + ? (((SceneExplorerChildren) children).getDataObject() != null + ? new ProxyLookup(((SceneExplorerChildren) children).getDataObject().getLookup(), new SceneExplorerLookup(new InstanceContent())) + : new SceneExplorerLookup(new InstanceContent())) + : new SceneExplorerLookup(new InstanceContent())); + this.jmeChildren = children; + lookupContents = getLookup().lookup(SceneExplorerLookup.class).getInstanceContent(); + if (children instanceof SceneExplorerChildren) { + this.dataObject = ((SceneExplorerChildren) children).getDataObject(); + } + } + + public InstanceContent getLookupContents() { + return lookupContents; + } + + public AbstractSceneExplorerNode addToLookup(Object obj) { + lookupContents.add(obj); + return this; + } + + protected void fireSave(boolean modified) { + if (dataObject != null) { + dataObject.setModified(true); + } + } + + /** + * returns the PropertySet with the given name (mostly Class.name) + * @param name + * @return The PropertySet or null if no PropertySet by that name exists + */ + public PropertySet getPropertySet(String name) { + for (int i = 0; i < getPropertySets().length; i++) { + PropertySet propertySet = getPropertySets()[i]; + if (propertySet.getName().equals(name)) { + return propertySet; + } + } + return null; + } + + /** + * @param saveCookie the saveCookie to set + */ + public AbstractSceneExplorerNode setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + return this; + } + + //TODO: refresh does not work + public void refresh(boolean immediate) { + if (jmeChildren instanceof SceneExplorerChildren) { + ((SceneExplorerChildren) jmeChildren).refreshChildren(immediate); + } + } + + public void refreshProperties() { + setSheet(createSheet()); + } + + protected Property makeProperty(Object obj, Class returntype, String method, String name) { + Property prop = null; + try { + prop = new SceneExplorerProperty(getExplorerObjectClass().cast(obj), returntype, method, null); + prop.setName(name); + } catch (NoSuchMethodException ex) { + Exceptions.printStackTrace(ex); + } + return prop; + } + + protected Property makeProperty(Object obj, Class returntype, String method, String setter, String name) { + Property prop = null; + try { + if (readOnly) { + prop = new SceneExplorerProperty(getExplorerObjectClass().cast(obj), returntype, method, null); + } else { + prop = new SceneExplorerProperty(getExplorerObjectClass().cast(obj), returntype, method, setter, this); + } + prop.setName(name); + + } catch (NoSuchMethodException ex) { + Exceptions.printStackTrace(ex); + } + return prop; + } + + public void propertyChange(final String name, final Object before, final Object after) { + fireSave(true); + firePropertyChange(name, before, after); + } + + public Class getExplorerNodeClass() { + return this.getClass(); + } + + public abstract Class getExplorerObjectClass(); + + public Node[] createNodes(Object key, DataObject dataObject, boolean readOnly) { + return new Node[]{Node.EMPTY}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AssetLinkChildren.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AssetLinkChildren.java new file mode 100644 index 000000000..e41eb8306 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/AssetLinkChildren.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2009-2010 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.asset.ModelKey; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.scene.AssetLinkNode; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class AssetLinkChildren extends SceneExplorerChildren { + + public AssetLinkChildren(AssetLinkNode spatial) { + super(spatial); + } + + public void refreshChildren(boolean immediate) { + setKeys(createKeys()); + refresh(); + } + + protected List createKeys() { + try { + return SceneApplication.getApplication().enqueue(new Callable>() { + + public List call() throws Exception { + List keys = new LinkedList(); + if (spatial instanceof AssetLinkNode) { + keys.addAll(((AssetLinkNode)spatial).getAssetLoaderKeys()); + return keys; + } + return keys; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + public void setReadOnly(boolean cookie) { + this.readOnly = cookie; + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(createKeys()); + } + + @Override + protected Node[] createNodes(Object key) { + if (key instanceof ModelKey) { + ModelKey assetKey = (ModelKey)key; + return new Node[]{new JmeAssetLinkChild(assetKey, (AssetLinkNode)spatial)}; + } + return null; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/ClipboardSpatial.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/ClipboardSpatial.java new file mode 100644 index 000000000..e4e5e5bae --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/ClipboardSpatial.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2009-2010 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.export.binary.BinaryExporter; +import com.jme3.export.binary.BinaryImporter; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.scene.Spatial; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class ClipboardSpatial implements Transferable, ClipboardOwner { + + private byte[] data; + + public ClipboardSpatial(Spatial spat){ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + BinaryExporter.getInstance().save(spat, out); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + data= out.toByteArray(); + } + + public ClipboardSpatial(byte[] spatial) { + data = spatial; + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{new DataFlavor(Spatial.class, "Spatial")}; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return new DataFlavor(Spatial.class, "Spatial").equals(flavor); + } + + public Object getTransferData(DataFlavor flavor) throws + UnsupportedFlavorException { + if (!isDataFlavorSupported(flavor)) { + return null; +// throw new UnsupportedFlavorException(flavor); + } + return createSpatial(); + } + + public void lostOwnership(java.awt.datatransfer.Clipboard clip, + java.awt.datatransfer.Transferable tr) { + return; + } + + public Spatial createSpatial(){ + try { + BinaryImporter importer=BinaryImporter.getInstance(); + //TODO: unsafe.. + importer.setAssetManager(SceneApplication.getApplication().getCurrentSceneRequest().getManager().getManager()); + return (Spatial)importer.load(data); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAmbientLight.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAmbientLight.java new file mode 100644 index 000000000..385b47cfa --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAmbientLight.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009-2010 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.light.AmbientLight; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import org.openide.cookies.SaveCookie; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeAmbientLight extends JmeLight{ + AmbientLight AmbientLight; + + public JmeAmbientLight() { + } + + public JmeAmbientLight(Spatial spatial, AmbientLight AmbientLight) { + super(spatial, AmbientLight); + this.AmbientLight = AmbientLight; + lookupContents.add(AmbientLight); + setName("AmbientLight"); + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("AmbientLight"); + set.setName(AmbientLight.class.getName()); + AmbientLight obj = AmbientLight;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return AmbientLight.class; + } + + public Class getExplorerNodeClass() { + return JmeAmbientLight.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, SaveCookie cookie) { + return null; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAnimControl.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAnimControl.java new file mode 100644 index 000000000..a8cbe9c33 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAnimControl.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2009-2010 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.animation.AnimControl; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.properties.AnimationProperty; +import com.jme3.scene.Spatial; +import java.awt.Image; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.loaders.DataObject; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeAnimControl extends AbstractSceneExplorerNode{ + + private AnimControl animControl; + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/animationcontrol.gif"); + + public JmeAnimControl() { + } + + public JmeAnimControl(AnimControl animControl) { + super(Children.LEAF); + this.animControl = animControl; + lookupContents.add(this); + lookupContents.add(animControl); + setName("AnimControl"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = Sheet.createDefault(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("AnimControl"); + set.setName(AnimControl.class.getName()); + if (animControl == null) { + return sheet; + } + + set.put(new AnimationProperty(animControl)); + + sheet.put(set); + return sheet; + + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return !readOnly; + } + + @Override + public void destroy() throws IOException { + super.destroy(); + final Spatial spat=getParentNode().getLookup().lookup(Spatial.class); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spat.removeControl(animControl); + return null; + } + }).get(); + ((AbstractSceneExplorerNode)getParentNode()).refresh(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public Class getExplorerObjectClass() { + return AnimControl.class; + } + + public Class getExplorerNodeClass() { + return JmeAnimControl.class; + } + + @Override + public Node[] createNodes(Object key, DataObject key2, boolean cookie) { + return new Node[]{new JmeAnimControl((AnimControl)key)}; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAssetLinkChild.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAssetLinkChild.java new file mode 100644 index 000000000..8ed161fe3 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAssetLinkChild.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2009-2010 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.asset.AssetKey; +import com.jme3.asset.ModelKey; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.scene.AssetLinkNode; +import com.jme3.scene.Spatial; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.util.Exceptions; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +public class JmeAssetLinkChild extends AbstractNode { + + private ModelKey key; + private AssetLinkNode linkNode; + + public JmeAssetLinkChild(ModelKey key, AssetLinkNode linkNode) { + super(Children.LEAF); + this.key = key; + this.linkNode = linkNode; + this.setName(key.getName()); + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return true; + } + + @Override + public void destroy() throws IOException { + super.destroy(); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + linkNode.detachLinkedChild(key); + return null; + } + }).get(); + JmeSpatial node = ((JmeSpatial) getParentNode()); + if (node != null) { + node.refresh(false); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAssetLinkNode.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAssetLinkNode.java new file mode 100644 index 000000000..33cf11919 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAssetLinkNode.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2009-2010 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.scene.AssetLinkNode; +import java.awt.Image; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.ImageUtilities; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeAssetLinkNode extends JmeNode { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/linknode.gif"); + private AssetLinkNode geom; + + public JmeAssetLinkNode() { + } + + public JmeAssetLinkNode(AssetLinkNode spatial, SceneExplorerChildren children) { + super(spatial, new AssetLinkChildren(spatial)); + getLookupContents().add(spatial); + this.geom = spatial; + setName(spatial.getName()); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("AssetLinkNode"); + set.setName(AssetLinkNode.class.getName()); + AssetLinkNode obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return AssetLinkNode.class; + } + + public Class getExplorerNodeClass() { + return JmeAssetLinkNode.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmeAssetLinkNode((AssetLinkNode) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAudioNode.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAudioNode.java new file mode 100644 index 000000000..984d02521 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeAudioNode.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2009-2010 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.audio.AudioNode; +import com.jme3.audio.AudioNode.Status; +import com.jme3.audio.Filter; +import com.jme3.gde.core.sceneexplorer.nodes.properties.AudioDataProperty; +import com.jme3.math.Vector3f; +import java.awt.Image; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.ImageUtilities; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeAudioNode extends JmeNode { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/audionode.gif"); + private AudioNode node; + + public JmeAudioNode() { + } + + public JmeAudioNode(AudioNode spatial, SceneExplorerChildren children) { + super(spatial, children); + getLookupContents().add(spatial); + this.node = spatial; + setName(spatial.getName()); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("AudioNode"); + set.setName(AudioNode.class.getName()); + AudioNode obj = node;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(new AudioDataProperty(obj)); + set.put(makeProperty(obj, Vector3f.class, "getDirection", "setDirection", "Direction")); + set.put(makeProperty(obj, boolean.class, "isDirectional", "setDirectional", "Directional")); + set.put(makeProperty(obj, float.class, "getInnerAngle", "setInnerAngle", "Inner Angle")); + set.put(makeProperty(obj, float.class, "getOuterAngle", "setOuterAngle", "Outer Angle")); + set.put(makeProperty(obj, Filter.class, "getDryFilter", "setDryFilter", "Dry Filter")); + set.put(makeProperty(obj, boolean.class, "isLooping", "setLooping", "Looping")); + set.put(makeProperty(obj, float.class, "getMaxDistance", "setMaxDistance", "Max Distance")); + + set.put(makeProperty(obj, float.class, "getPitch", "setPitch", "Audio Pitch")); + set.put(makeProperty(obj, boolean.class, "isPositional", "setPositional", "Positional")); + + set.put(makeProperty(obj, boolean.class, "isReverbEnabled", "setReverbEnabled", "Reverb")); + set.put(makeProperty(obj, Filter.class, "getReverbFilter", "setReverbFilter", "Reverb Filter")); + set.put(makeProperty(obj, float.class, "getRefDistance", "setRefDistance", "Ref Distance")); + set.put(makeProperty(obj, float.class, "getTimeOffset", "setTimeOffset", "Time Offset")); + + set.put(makeProperty(obj, Status.class, "getStatus", "setStatus", "Status")); + + set.put(makeProperty(obj, float.class, "getVolume", "setVolume", "Volume")); + set.put(makeProperty(obj, Vector3f.class, "getVelocity", "setVelocity", "Velocity")); + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return AudioNode.class; + } + + public Class getExplorerNodeClass() { + return JmeAudioNode.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmeAudioNode((AudioNode) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeBitmapText.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeBitmapText.java new file mode 100644 index 000000000..a89a06a55 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeBitmapText.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2009-2010 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.font.BitmapFont; +import com.jme3.font.BitmapText; +import com.jme3.math.ColorRGBA; +import java.awt.Image; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.ImageUtilities; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeBitmapText extends JmeNode { + + private static Image smallImage = + ImageUtilities.loadImage("/com/jme3/gde/core/sceneexplorer/nodes/icons/bitmaptext.gif"); + private BitmapText geom; + + public JmeBitmapText() { + } + + public JmeBitmapText(BitmapText spatial, SceneExplorerChildren children) { + super(spatial, children); + getLookupContents().add(spatial); + this.geom = spatial; + setName(spatial.getName()); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("BitmapText"); + set.setName(BitmapText.class.getName()); + BitmapText obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, String.class, "getText", "setText", "Text")); + set.put(makeProperty(obj, ColorRGBA.class, "getColor", "setColor", "Color")); + set.put(makeProperty(obj, BitmapFont.class, "getFont", "Font")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return BitmapText.class; + } + + public Class getExplorerNodeClass() { + return JmeBitmapText.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmeBitmapText((BitmapText) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeCharacterControl.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeCharacterControl.java new file mode 100644 index 000000000..b55c844b9 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeCharacterControl.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2009-2010 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.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.control.CharacterControl; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.math.Matrix3f; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.awt.Image; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeCharacterControl extends AbstractSceneExplorerNode { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/player.gif"); + private CharacterControl geom; + + public JmeCharacterControl() { + } + + public JmeCharacterControl(CharacterControl spatial, DataObject dataObject) { + super(dataObject); + getLookupContents().add(this); + getLookupContents().add(spatial); + this.geom = spatial; + setName("CharacterControl"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return !readOnly; + } + + @Override + public void destroy() throws IOException { + super.destroy(); + final Spatial spat=getParentNode().getLookup().lookup(Spatial.class); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spat.removeControl(geom); + return null; + } + }).get(); + ((AbstractSceneExplorerNode)getParentNode()).refresh(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("CharacterControl"); + set.setName(CharacterControl.class.getName()); + CharacterControl obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, Vector3f.class, "getPhysicsLocation", "setPhysicsLocation", "Physics Location")); + + set.put(makeProperty(obj, CollisionShape.class, "getCollisionShape", "setCollisionShape", "Collision Shape")); + set.put(makeProperty(obj, int.class, "getCollisionGroup", "setCollisionGroup", "Collision Group")); + set.put(makeProperty(obj, int.class, "getCollideWithGroups", "setCollideWithGroups", "Collide With Groups")); + + set.put(makeProperty(obj, int.class, "getUpAxis", "setUpAxis", "Up Axis")); + set.put(makeProperty(obj, float.class, "getFallSpeed", "setFallSpeed", "Fall Speed")); + set.put(makeProperty(obj, float.class, "getJumpSpeed", "setJumpSpeed", "Jump Speed")); + set.put(makeProperty(obj, float.class, "getGravity", "setGravity", "Gravity")); + set.put(makeProperty(obj, float.class, "getMaxSlope", "setMaxSlope", "Max Slope")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return CharacterControl.class; + } + + public Class getExplorerNodeClass() { + return JmeCharacterControl.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + return new org.openide.nodes.Node[]{new JmeCharacterControl((CharacterControl) key, key2).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeDirectionalLight.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeDirectionalLight.java new file mode 100644 index 000000000..e5f3478d9 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeDirectionalLight.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009-2010 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.light.DirectionalLight; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import org.openide.cookies.SaveCookie; +import org.openide.nodes.Sheet; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeDirectionalLight extends JmeLight{ + protected DirectionalLight directionalLight; + + public JmeDirectionalLight() { + } + + public JmeDirectionalLight(Spatial spatial, DirectionalLight directionalLight) { + super(spatial, directionalLight); + this.directionalLight = directionalLight; + lookupContents.add(directionalLight); + setName("DirectionalLight"); + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("DirectionalLight"); + set.setName(DirectionalLight.class.getName()); + DirectionalLight obj = directionalLight; + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, Vector3f.class, "getDirection", "setDirection", "Direction")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return DirectionalLight.class; + } + + public Class getExplorerNodeClass() { + return JmeDirectionalLight.class; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java new file mode 100644 index 000000000..7ab8e98ad --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGeometry.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2009-2010 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.material.Material; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import java.awt.Image; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.ImageUtilities; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeGeometry extends JmeSpatial { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/geometry.gif"); + private Geometry geom; + + public JmeGeometry() { + } + + public JmeGeometry(Geometry spatial, SceneExplorerChildren children) { + super(spatial, children); + getLookupContents().add(spatial); + this.geom = spatial; + setName(spatial.getName()); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("Geometry"); + set.setName(Geometry.class.getName()); + Geometry obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, int.class, "getLodLevel", "setLodLevel", "Lod Level")); + set.put(makeProperty(obj, Material.class, "getMaterial", "setMaterial", "Material")); + set.put(makeProperty(obj, Mesh.class, "getMesh", "Mesh")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return Geometry.class; + } + + public Class getExplorerNodeClass() { + return JmeGeometry.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmeGeometry((Geometry) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGhostControl.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGhostControl.java new file mode 100644 index 000000000..5dd92d586 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeGhostControl.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2009-2010 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.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.control.GhostControl; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.awt.Image; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeGhostControl extends AbstractSceneExplorerNode { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/ghostcontrol.gif"); + private GhostControl geom; + + public JmeGhostControl() { + } + + public JmeGhostControl(GhostControl spatial, DataObject dataObject) { + super(dataObject); + getLookupContents().add(this); + getLookupContents().add(spatial); + this.geom = spatial; + setName("GhostControl"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return !readOnly; + } + + @Override + public void destroy() throws IOException { + super.destroy(); + final Spatial spat=getParentNode().getLookup().lookup(Spatial.class); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spat.removeControl(geom); + return null; + } + }).get(); + ((AbstractSceneExplorerNode)getParentNode()).refresh(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("GhostControl"); + set.setName(GhostControl.class.getName()); + GhostControl obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, Vector3f.class, "getPhysicsLocation", "setPhysicsLocation", "Physics Location")); + set.put(makeProperty(obj, Quaternion.class, "getPhysicsRotation", "setPhysicsRotation", "Physics Rotation")); + + set.put(makeProperty(obj, CollisionShape.class, "getCollisionShape", "setCollisionShape", "Collision Shape")); + set.put(makeProperty(obj, int.class, "getCollisionGroup", "setCollisionGroup", "Collision Group")); + set.put(makeProperty(obj, int.class, "getCollideWithGroups", "setCollideWithGroups", "Collide With Groups")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return GhostControl.class; + } + + public Class getExplorerNodeClass() { + return JmeGhostControl.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + return new org.openide.nodes.Node[]{new JmeGhostControl((GhostControl) key, key2).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeLight.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeLight.java new file mode 100644 index 000000000..707b90eb8 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeLight.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2009-2010 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.gde.core.scene.SceneApplication; +import com.jme3.light.Light; +import com.jme3.math.ColorRGBA; +import com.jme3.scene.Spatial; +import java.awt.Image; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.cookies.SaveCookie; +import org.openide.loaders.DataObject; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeLight extends AbstractSceneExplorerNode{ + + private Spatial spatial; + private Light light; + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/light.gif"); + + public JmeLight() { + } + + public JmeLight(Spatial spatial, Light light) { + super(Children.LEAF); + this.spatial = spatial; + this.light = light; + lookupContents.add(light); + lookupContents.add(this); + setName("Light"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = Sheet.createDefault(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("Light"); + set.setName(Light.class.getName()); + Light obj = light; + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, ColorRGBA.class, "getColor", "setColor", "Color")); + set.put(makeProperty(obj, float.class, "getLastDistance", "setLastDistance", "Last Distance")); + + sheet.put(set); + return sheet; + + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return true; + } + + @Override + public void destroy() throws IOException { + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spatial.removeLight(light); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public Class getExplorerObjectClass() { + return Light.class; + } + + public Class getExplorerNodeClass() { + return JmeLight.class; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMesh.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMesh.java new file mode 100644 index 000000000..04ac479df --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeMesh.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2009-2010 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.gde.core.scene.SceneApplication; +import com.jme3.light.Light; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import java.awt.Image; +import java.beans.PropertyChangeEvent; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.cookies.SaveCookie; +import org.openide.loaders.DataObject; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeMesh extends AbstractSceneExplorerNode{ + + private Geometry geom; + private Mesh mesh; + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/mesh.gif"); + + public JmeMesh() { + } + + public JmeMesh(Geometry geom, Mesh mesh) { + super(Children.LEAF); + this.geom = geom; + this.mesh = mesh; + lookupContents.add(geom); + lookupContents.add(mesh); + lookupContents.add(this); + setName("Mesh"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = Sheet.createDefault(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("Mesh"); + set.setName(Light.class.getName()); + Mesh obj = mesh; + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, int.class, "getId", "setId", "Id")); + set.put(makeProperty(obj, Mesh.Mode.class, "getMode", "setMode", "Mode")); + set.put(makeProperty(obj, float.class, "getPointSize", "setPointSize", "Point Size")); + + sheet.put(set); + return sheet; + + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return true; + } + + @Override + public void destroy() throws IOException { + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { +// spatial.removeLight(light); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public Class getExplorerObjectClass() { + return Mesh.class; + } + + public Class getExplorerNodeClass() { + return JmeMesh.class; + } + + public void propertyChange(PropertyChangeEvent evt) { + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeNode.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeNode.java new file mode 100644 index 000000000..e5942c8bf --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeNode.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2009-2010 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.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AddControlAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AddLightAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AddSpatialAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AddUserDataAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.UseToolAction; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import java.awt.Image; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import javax.swing.Action; +import org.openide.actions.CopyAction; +import org.openide.actions.CutAction; +import org.openide.actions.DeleteAction; +import org.openide.actions.PasteAction; +import org.openide.actions.RenameAction; +import org.openide.awt.Actions; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; +import org.openide.util.datatransfer.PasteType; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service = SceneExplorerNode.class) +public class JmeNode extends JmeSpatial { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/node.gif"); + private Node node; + + public JmeNode() { + } + + public JmeNode(Node spatial, SceneExplorerChildren children) { + super(spatial, children); + getLookupContents().add(spatial); + this.node = spatial; + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("Node"); + set.setName(Node.class.getName()); + Node obj = node;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + sheet.put(set); + return sheet; + + } + + @Override + public PasteType getDropType(final Transferable t, int action, int index) { + Object data = null; + try { + data = t.getTransferData(SPATIAL_FLAVOR); + } catch (Exception ex) { +// Exceptions.printStackTrace(ex); + } + if (data == null) { + return null; + } + if (data instanceof ClipboardSpatial) { + final Spatial spat = ((ClipboardSpatial) data).createSpatial(); + return new PasteType() { + + @Override + public Transferable paste() throws IOException { + try { + fireSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + node.attachChild(spat); + return null; + } + }).get(); + refresh(false); + return t; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + }; + } + return null; + } + + @Override + protected void createPasteTypes(Transferable t, List s) { + super.createPasteTypes(t, s); + PasteType paste = getDropType(t, DnDConstants.ACTION_COPY_OR_MOVE, -1); + if (null != paste) { + s.add(paste); + } + } + + @Override + public Action[] getActions(boolean context) { +// return super.getActions(context); + if (((SceneExplorerChildren) jmeChildren).readOnly) { + return new Action[]{ + SystemAction.get(CopyAction.class),}; + } else { + return new Action[]{ + new AddSpatialAction(this), + new AddControlAction(this), + new AddLightAction(this), + Actions.alwaysEnabled(new AddUserDataAction(this), "Add User Data", "", false), + new UseToolAction(this), + SystemAction.get(RenameAction.class), + SystemAction.get(CopyAction.class), + SystemAction.get(CutAction.class), + SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + } + + public Class getExplorerObjectClass() { + return Node.class; + } + + public Class getExplorerNodeClass() { + return JmeNode.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children = new SceneExplorerChildren((com.jme3.scene.Spatial) key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmeNode((Node) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java new file mode 100644 index 000000000..dbf3d3c1d --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeParticleEmitter.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2009-2010 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.effect.EmitterShape; +import com.jme3.effect.ParticleEmitter; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import java.awt.Image; +import org.openide.loaders.DataObject; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.openide.util.ImageUtilities; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeParticleEmitter extends JmeGeometry{ + + public JmeParticleEmitter() { + } + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/particleemitter.gif"); + private ParticleEmitter geom; + + public JmeParticleEmitter(ParticleEmitter spatial, SceneExplorerChildren children) { + super(spatial, children); + getLookupContents().add(spatial); + this.geom = spatial; + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("ParticleEmitter"); + set.setName(ParticleEmitter.class.getName()); + ParticleEmitter obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, boolean.class, "isEnabled", "setEnabled", "Enabled")); + set.put(makeProperty(obj, EmitterShape.class, "getShape", "setShape", "Emitter Shape")); + set.put(makeProperty(obj, int.class, "getNumVisibleParticles", "setNumParticles", "Num Particles")); + set.put(makeProperty(obj, float.class, "getParticlesPerSec", "setParticlesPerSec", "Particles Per Sec")); + set.put(makeProperty(obj, ColorRGBA.class, "getStartColor", "setStartColor", "Start Color")); + set.put(makeProperty(obj, ColorRGBA.class, "getEndColor", "setEndColor", "End Color")); + set.put(makeProperty(obj, float.class, "getStartSize", "setStartSize", "Start Size")); + set.put(makeProperty(obj, float.class, "getEndSize", "setEndSize", "End Size")); + set.put(makeProperty(obj, float.class, "getHighLife", "setHighLife", "High Life")); + set.put(makeProperty(obj, float.class, "getLowLife", "setLowLife", "Low Life")); + set.put(makeProperty(obj, float.class, "getGravity", "setGravity", "Gravity")); + set.put(makeProperty(obj, Vector3f.class, "getInitialVelocity", "setInitialVelocity", "Initial Velocity")); + set.put(makeProperty(obj, Vector3f.class, "getFaceNormal", "setFaceNormal", "Face Normal")); + set.put(makeProperty(obj, float.class, "getVelocityVariation", "setVelocityVariation", "Velocity Variation")); + set.put(makeProperty(obj, boolean.class, "isFacingVelocity", "setFacingVelocity", "Facing Velocity")); + set.put(makeProperty(obj, boolean.class, "isRandomAngle", "setRandomAngle", "Random Angle")); + set.put(makeProperty(obj, boolean.class, "isInWorldSpace", "setInWorldSpace", "World Space")); + set.put(makeProperty(obj, float.class, "getRotateSpeed", "setRotateSpeed", "Rotate Speed")); + set.put(makeProperty(obj, boolean.class, "isSelectRandomImage", "setSelectRandomImage", "Select Random Image")); + set.put(makeProperty(obj, int.class, "getImagesX", "setImagesX", "Images X")); + set.put(makeProperty(obj, int.class, "getImagesY", "setImagesY", "Images Y")); + +// set.put(makeProperty(obj, EmitterShape.class, "getShape", "setShape", "shape")); + + + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return ParticleEmitter.class; + } + + public Class getExplorerNodeClass() { + return JmeParticleEmitter.class; + } + + public Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new Node[]{new JmeParticleEmitter((ParticleEmitter) key, children).setReadOnly(cookie)}; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmePicture.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmePicture.java new file mode 100644 index 000000000..1f1d96526 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmePicture.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2009-2010 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.ui.Picture; +import java.awt.Image; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.ImageUtilities; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmePicture extends JmeGeometry { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/picture.gif"); + private Picture geom; + + public JmePicture() { + } + + public JmePicture(Picture spatial, SceneExplorerChildren children) { + super(spatial, children); + getLookupContents().add(spatial); + this.geom = spatial; + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("Picture"); + set.setName(Picture.class.getName()); + Picture obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + +// set.put(makeProperty(obj, String.class, "getText", "setText", "text")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return Picture.class; + } + + public Class getExplorerNodeClass() { + return JmePicture.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmePicture((Picture) key, children).setReadOnly(cookie)}; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmePointLight.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmePointLight.java new file mode 100644 index 000000000..f00a2d9b4 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmePointLight.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009-2010 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.light.PointLight; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import org.openide.cookies.SaveCookie; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmePointLight extends JmeLight{ + PointLight pointLight; + + public JmePointLight() { + } + + public JmePointLight(Spatial spatial, PointLight pointLight) { + super(spatial, pointLight); + this.pointLight = pointLight; + lookupContents.add(pointLight); + setName("PointLight"); + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("PointLight"); + set.setName(PointLight.class.getName()); + PointLight obj = pointLight;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, Vector3f.class, "getPosition", "setPosition", "Position")); + set.put(makeProperty(obj, float.class, "getRadius", "setRadius", "Radius")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return PointLight.class; + } + + public Class getExplorerNodeClass() { + return JmePointLight.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, SaveCookie cookie) { + return null; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeRigidBodyControl.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeRigidBodyControl.java new file mode 100644 index 000000000..ce5a1d982 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeRigidBodyControl.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2009-2010 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.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.awt.Image; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeRigidBodyControl extends AbstractSceneExplorerNode { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/physicscontrol.gif"); + private RigidBodyControl geom; + + public JmeRigidBodyControl() { + } + + public JmeRigidBodyControl(RigidBodyControl spatial, DataObject dataObject) { + super(dataObject); + getLookupContents().add(spatial); + getLookupContents().add(this); + this.geom = spatial; + setName("PhysicsControl"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return !readOnly; + } + + @Override + public void destroy() throws IOException { + super.destroy(); + final Spatial spat=getParentNode().getLookup().lookup(Spatial.class); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spat.removeControl(geom); + return null; + } + }).get(); + ((AbstractSceneExplorerNode)getParentNode()).refresh(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("RigidBodyControl"); + set.setName(RigidBodyControl.class.getName()); + RigidBodyControl obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, Vector3f.class, "getPhysicsLocation", "setPhysicsLocation", "Physics Location")); + set.put(makeProperty(obj, Quaternion.class, "getPhysicsRotation", "setPhysicsRotation", "Physics Rotation")); + + set.put(makeProperty(obj, CollisionShape.class, "getCollisionShape", "setCollisionShape", "Collision Shape")); + set.put(makeProperty(obj, int.class, "getCollisionGroup", "setCollisionGroup", "Collision Group")); + set.put(makeProperty(obj, int.class, "getCollideWithGroups", "setCollideWithGroups", "Collide With Groups")); + + set.put(makeProperty(obj, float.class, "getFriction", "setFriction", "Friction")); + set.put(makeProperty(obj, float.class, "getMass", "setMass", "Mass")); + set.put(makeProperty(obj, boolean.class, "isKinematic", "setKinematic", "Kinematic")); + set.put(makeProperty(obj, Vector3f.class, "getGravity", "setGravity", "Gravity")); + set.put(makeProperty(obj, float.class, "getLinearDamping", "setLinearDamping", "Linear Damping")); + set.put(makeProperty(obj, float.class, "getAngularDamping", "setAngularDamping", "Angular Damping")); + set.put(makeProperty(obj, float.class, "getRestitution", "setRestitution", "Restitution")); + + set.put(makeProperty(obj, float.class, "getLinearSleepingThreshold", "setLinearSleepingThreshold", "Linear Sleeping Threshold")); + set.put(makeProperty(obj, float.class, "getAngularSleepingThreshold", "setAngularSleepingThreshold", "Angular Sleeping Threshold")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return RigidBodyControl.class; + } + + public Class getExplorerNodeClass() { + return JmeRigidBodyControl.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + return new org.openide.nodes.Node[]{new JmeRigidBodyControl((RigidBodyControl) key, key2).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java new file mode 100644 index 000000000..a52eaddd5 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2009-2010 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.bounding.BoundingVolume; +import com.jme3.export.binary.BinaryExporter; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AddControlAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AddLightAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AddUserDataAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.UseToolAction; +import com.jme3.gde.core.sceneexplorer.nodes.properties.UserDataProperty; +import com.jme3.light.LightList; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.renderer.queue.RenderQueue.ShadowMode; +import com.jme3.scene.Spatial; +import com.jme3.scene.Spatial.CullHint; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import javax.swing.Action; +import org.openide.actions.CopyAction; +import org.openide.actions.CutAction; +import org.openide.actions.DeleteAction; +import org.openide.actions.PasteAction; +import org.openide.actions.RenameAction; +import org.openide.awt.Actions; +import org.openide.loaders.DataObject; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service = SceneExplorerNode.class) +public class JmeSpatial extends AbstractSceneExplorerNode { + + private Spatial spatial; + protected final DataFlavor SPATIAL_FLAVOR = new DataFlavor(ClipboardSpatial.class, "Spatial"); + + public JmeSpatial() { + } + + public JmeSpatial(Spatial spatial, SceneExplorerChildren factory) { + super(factory); + this.jmeChildren = factory; + this.spatial = spatial; + getLookupContents().add(spatial); + getLookupContents().add(this); + super.setName(spatial.getName()); + } + + public JmeSpatial getChild(Spatial spat) { + if (spat == null) { + return null; + } + if (getLookup().lookup(spat.getClass()) == spat) { + return this; + } + + Node[] children = getChildren().getNodes(); + for (int i = 0; i < children.length; i++) { + Node node = children[i]; + if (node instanceof JmeSpatial) { + JmeSpatial jmeSpatial = (JmeSpatial) node; + JmeSpatial found = jmeSpatial.getChild(spat); + if (found != null) { + return found; + } + } + } + return null; + } + +// protected SystemAction[] createActions() { +// return new SystemAction[]{ +// SystemAction.get(RenameAction.class), +// SystemAction.get(CopyAction.class), +// SystemAction.get(CutAction.class), +// SystemAction.get(PasteAction.class), +// SystemAction.get(DeleteAction.class) +// }; +// } + + @Override + public Action[] getActions(boolean context) { +// return super.getActions(context); + if (((SceneExplorerChildren) jmeChildren).readOnly) { + return new Action[]{ + SystemAction.get(CopyAction.class),}; + } else { + return new Action[]{ + new AddControlAction(this), + new AddLightAction(this), + Actions.alwaysEnabled(new AddUserDataAction(this), "Add User Data", "", false), + new UseToolAction(this), + SystemAction.get(RenameAction.class), + SystemAction.get(CopyAction.class), + SystemAction.get(CutAction.class), + SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + } + + @Override + public boolean canCopy() { + return !((SceneExplorerChildren) jmeChildren).readOnly; + } + + @Override + public boolean canCut() { + return !((SceneExplorerChildren) jmeChildren).readOnly; + } + + @Override + public boolean canDestroy() { + return !((SceneExplorerChildren) jmeChildren).readOnly; + } + + @Override + public boolean canRename() { + return !((SceneExplorerChildren) jmeChildren).readOnly; + } + + @Override + public void setName(final String s) { + super.setName(s); + try { +// fireSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spatial.setName(s); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + public void destroy() throws IOException { + try { + fireSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spatial.removeFromParent(); + return null; + } + }).get(); + //TODO: not a good cast + JmeNode node = ((JmeNode) getParentNode()); + if (node != null) { + node.refresh(false); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + public Transferable clipboardCopy() throws IOException { + Transferable trans = new Transferable() { + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{SPATIAL_FLAVOR}; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + if (SPATIAL_FLAVOR.equals(flavor)) { + return true; + } + return false; + } + + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if (SPATIAL_FLAVOR.equals(flavor)) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BinaryExporter.getInstance().save(spatial, out); + + return new ClipboardSpatial(out.toByteArray()); + } else { + throw new UnsupportedFlavorException(flavor); + } + } + }; + return trans; + } + + @Override + public Transferable clipboardCut() throws IOException { + fireSave(true); + Transferable trans = new Transferable() { + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{SPATIAL_FLAVOR}; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + if (SPATIAL_FLAVOR.equals(flavor)) { + return true; + } + return false; + } + + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if (SPATIAL_FLAVOR.equals(flavor)) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spatial.removeFromParent(); + return null; + } + }).get(); + //TODO: not a good cast + JmeNode node = ((JmeNode) getParentNode()); + if (node != null) { + node.refresh(false); + } +// return spatial; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BinaryExporter.getInstance().save(spatial, out); +// + return new ClipboardSpatial(out.toByteArray()); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } else { + throw new UnsupportedFlavorException(flavor); + } + } + }; + return trans; + } + + @Override + protected Sheet createSheet() { + Sheet sheet = Sheet.createDefault(); + + //TODO: multithreading.. but we only read + Collection dataKeys = spatial.getUserDataKeys(); + if (dataKeys.size() > 0) { + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("User Data"); + set.setName(Spatial.class.getName() + "_UserData"); + for (Iterator it = dataKeys.iterator(); it.hasNext();) { + String string = it.next(); + UserDataProperty prop = new UserDataProperty(spatial, string); + prop.addPropertyChangeListener(this); + set.put(prop); + } + sheet.put(set); + } + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("Spatial"); + set.setName(Spatial.class.getName()); + Spatial obj = spatial;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } +// set.put(makeProperty(obj, String.class, "getName", "setName", "name")); + + set.put(makeProperty(obj, int.class, "getVertexCount", "Vertexes")); + set.put(makeProperty(obj, int.class, "getTriangleCount", "Triangles")); + +// set.put(makeProperty(obj, Transform.class,"getWorldTransform","world transform")); + set.put(makeProperty(obj, Vector3f.class, "getWorldTranslation", "World Translation")); + set.put(makeProperty(obj, Quaternion.class, "getWorldRotation", "World Rotation")); + set.put(makeProperty(obj, Vector3f.class, "getWorldScale", "World Scale")); + + set.put(makeProperty(obj, Vector3f.class, "getLocalTranslation", "setLocalTranslation", "Local Translation")); + set.put(makeProperty(obj, Quaternion.class, "getLocalRotation", "setLocalRotation", "Local Rotation")); + set.put(makeProperty(obj, Vector3f.class, "getLocalScale", "setLocalScale", "Local Scale")); + + set.put(makeProperty(obj, BoundingVolume.class, "getWorldBound", "World Bound")); + + set.put(makeProperty(obj, CullHint.class, "getCullHint", "setCullHint", "Cull Hint")); + set.put(makeProperty(obj, CullHint.class, "getLocalCullHint", "Local Cull Hint")); + set.put(makeProperty(obj, ShadowMode.class, "getShadowMode", "setShadowMode", "Shadow Mode")); + set.put(makeProperty(obj, ShadowMode.class, "getLocalShadowMode", "Local Shadow Mode")); + set.put(makeProperty(obj, LightList.class, "getWorldLightList", "World Light List")); + + set.put(makeProperty(obj, RenderQueue.Bucket.class, "getQueueBucket", "setQueueBucket", "Queue Bucket")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return Spatial.class; + } + + public Class getExplorerNodeClass() { + return JmeSpatial.class; + } + + public Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children = new SceneExplorerChildren((com.jme3.scene.Spatial) key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new Node[]{new JmeSpatial((Spatial) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTerrainQuad.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTerrainQuad.java new file mode 100644 index 000000000..3d137f663 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTerrainQuad.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2009-2010 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.terrain.geomipmap.TerrainQuad; +import java.awt.Image; +import org.openide.loaders.DataObject; +import org.openide.nodes.Sheet; +import org.openide.util.ImageUtilities; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeTerrainQuad extends JmeNode { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/terrain.png"); + private TerrainQuad geom; + + public JmeTerrainQuad() { + } + + public JmeTerrainQuad(TerrainQuad spatial, SceneExplorerChildren children) { + super(spatial, children); + getLookupContents().add(spatial); + this.geom = spatial; + setName(spatial.getName()); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("TerrainQuad"); + set.setName(TerrainQuad.class.getName()); + TerrainQuad obj = geom;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, int.class, "getMaxLod", "Max Lod")); + set.put(makeProperty(obj, short.class, "getQuadrant", "setQuadrant", "Quadrant")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return TerrainQuad.class; + } + + public Class getExplorerNodeClass() { + return JmeTerrainQuad.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmeTerrainQuad((TerrainQuad) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeVehicleControl.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeVehicleControl.java new file mode 100644 index 000000000..deee9e2e7 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeVehicleControl.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2009-2010 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.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.control.VehicleControl; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.awt.Image; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.loaders.DataObject; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeVehicleControl extends AbstractSceneExplorerNode { + + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/vehicle.png"); + private VehicleControl vehicle; + + public JmeVehicleControl() { + } + + public JmeVehicleControl(VehicleControl vehicle, Children children) { + super(children); + getLookupContents().add(vehicle); + getLookupContents().add(this); + this.vehicle = vehicle; + setName("VehicleControl"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return !readOnly; + } + + @Override + public void destroy() throws IOException { + super.destroy(); + final Spatial spat=getParentNode().getLookup().lookup(Spatial.class); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + spat.removeControl(vehicle); + return null; + } + }).get(); + ((AbstractSceneExplorerNode)getParentNode()).refresh(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("VehicleControl"); + set.setName(VehicleControl.class.getName()); + VehicleControl obj = vehicle;//getLookup().lookup(Spatial.class); + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, Vector3f.class, "getPhysicsLocation", "setPhysicsLocation", "Physics Location")); + set.put(makeProperty(obj, Quaternion.class, "getPhysicsRotation", "setPhysicsRotation", "Physics Rotation")); + + set.put(makeProperty(obj, CollisionShape.class, "getCollisionShape", "setCollisionShape", "Collision Shape")); + set.put(makeProperty(obj, int.class, "getCollisionGroup", "setCollisionGroup", "Collision Group")); + set.put(makeProperty(obj, int.class, "getCollideWithGroups", "setCollideWithGroups", "Collide With Groups")); + + set.put(makeProperty(obj, float.class, "getFriction", "setFriction", "Friction")); + set.put(makeProperty(obj, float.class, "getMass", "setMass", "Mass")); + set.put(makeProperty(obj, boolean.class, "isKinematic", "setKinematic", "Kinematic")); + set.put(makeProperty(obj, Vector3f.class, "getGravity", "setGravity", "Gravity")); + set.put(makeProperty(obj, float.class, "getLinearDamping", "setLinearDamping", "Linear Damping")); + set.put(makeProperty(obj, float.class, "getAngularDamping", "setAngularDamping", "Angular Damping")); + set.put(makeProperty(obj, float.class, "getRestitution", "setRestitution", "Restitution")); + + set.put(makeProperty(obj, float.class, "getLinearSleepingThreshold", "setLinearSleepingThreshold", "Linear Sleeping Threshold")); + set.put(makeProperty(obj, float.class, "getAngularSleepingThreshold", "setAngularSleepingThreshold", "Angular Sleeping Threshold")); + + set.put(makeProperty(obj, float.class, "getFrictionSlip", "setFrictionSlip", "Friction Slip")); + set.put(makeProperty(obj, float.class, "getMaxSuspensionTravelCm", "setMaxSuspensionTravelCm", "Max Suspension Travel Cm")); + set.put(makeProperty(obj, float.class, "getMaxSuspensionForce", "setMaxSuspensionForce", "Max Suspension Force")); + set.put(makeProperty(obj, float.class, "getSuspensionCompression", "setSuspensionCompression", "Suspension Compression")); + set.put(makeProperty(obj, float.class, "getSuspensionDamping", "setSuspensionDamping", "Suspension Damping")); + set.put(makeProperty(obj, float.class, "getSuspensionStiffness", "setSuspensionStiffness", "Suspension Stiffness")); + + sheet.put(set); + return sheet; + + } + + public Class getExplorerObjectClass() { + return VehicleControl.class; + } + + public Class getExplorerNodeClass() { + return JmeVehicleControl.class; + } + + public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) { + PhysicsVehicleChildren children = new PhysicsVehicleChildren((VehicleControl) key); + children.setReadOnly(cookie); + children.setDataObject(key2); + return new org.openide.nodes.Node[]{new JmeVehicleControl((VehicleControl) key, children).setReadOnly(cookie)}; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeVehicleWheel.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeVehicleWheel.java new file mode 100644 index 000000000..ea0bea3d2 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeVehicleWheel.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2009-2010 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.bullet.control.VehicleControl; +import com.jme3.bullet.objects.VehicleWheel; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.light.Light; +import com.jme3.math.Vector3f; +import java.awt.Image; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.actions.DeleteAction; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class) +public class JmeVehicleWheel extends AbstractSceneExplorerNode{ + + private VehicleWheel wheel; + private VehicleControl vehicle; + private static Image smallImage = + ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/physicswheel.gif"); + + public JmeVehicleWheel() { + } + + public JmeVehicleWheel(VehicleControl vehicle, VehicleWheel wheel) { + super(Children.LEAF); + this.vehicle=vehicle; + this.wheel = wheel; + getLookupContents().add(wheel); + getLookupContents().add(this); + setName("Wheel"); + } + + @Override + public Image getIcon(int type) { + return smallImage; + } + + @Override + public Image getOpenedIcon(int type) { + return smallImage; + } + + @Override + protected Sheet createSheet() { + //TODO: multithreading.. + Sheet sheet = Sheet.createDefault(); + Sheet.Set set = Sheet.createPropertiesSet(); + set.setDisplayName("VehicleWheel"); + set.setName(Light.class.getName()); + VehicleWheel obj = wheel; + if (obj == null) { + return sheet; + } + + set.put(makeProperty(obj, Vector3f.class, "getLocation", "Location")); + set.put(makeProperty(obj, Vector3f.class, "getAxle", "Axis")); + set.put(makeProperty(obj, Vector3f.class, "getDirection", "Direction")); + set.put(makeProperty(obj, boolean.class, "isFrontWheel", "setFrontWheel", "Front Wheel")); + set.put(makeProperty(obj, float.class, "getFrictionSlip", "setFrictionSlip", "Friction Slip")); + set.put(makeProperty(obj, float.class, "getMaxSuspensionForce", "setMaxSuspensionForce", "Max Suspension Force")); + set.put(makeProperty(obj, float.class, "getMaxSuspensionTravelCm", "setMaxSuspensionTravelCm", "Max Suspension Travel")); + set.put(makeProperty(obj, float.class, "getRadius", "setRadius", "Radius")); + set.put(makeProperty(obj, float.class, "getRestLength", "setRestLength", "Rest Length")); + set.put(makeProperty(obj, float.class, "getRollInfluence", "setRollInfluence", "Roll Influence")); + set.put(makeProperty(obj, float.class, "getSuspensionStiffness", "setSuspensionStiffness", "Suspension Stiffness")); + set.put(makeProperty(obj, float.class, "getWheelsDampingCompression", "setWheelsDampingCompression", "Damping Compression")); + set.put(makeProperty(obj, float.class, "getWheelsDampingRelaxation", "setWheelsDampingRelaxation", "Damping Relaxation")); + + sheet.put(set); + return sheet; + + } + + protected SystemAction[] createActions() { + return new SystemAction[]{ + // SystemAction.get(CopyAction.class), + // SystemAction.get(CutAction.class), + // SystemAction.get(PasteAction.class), + SystemAction.get(DeleteAction.class) + }; + } + + @Override + public boolean canDestroy() { + return true; + } + + @Override + public void destroy() throws IOException { + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + for (int i= 0; i < vehicle.getNumWheels(); i++) { + if(vehicle.getWheel(i)==wheel){ + vehicle.removeWheel(i); + return null; + } + } + return null; + } + }).get(); + ((AbstractSceneExplorerNode)getParentNode()).refresh(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public Class getExplorerObjectClass() { + return VehicleWheel.class; + } + + public Class getExplorerNodeClass() { + return JmeVehicleWheel.class; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/LightSpatialPair.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/LightSpatialPair.java new file mode 100644 index 000000000..85925f985 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/LightSpatialPair.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009-2010 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.light.Light; +import com.jme3.scene.Spatial; + +/** + * + * @author normenhansen + */ +public class LightSpatialPair { + private Light light; + private Spatial spatial; + + public LightSpatialPair(Light light, Spatial spatial) { + this.light = light; + this.spatial = spatial; + } + + /** + * @return the light + */ + public Light getLight() { + return light; + } + + /** + * @return the spatial + */ + public Spatial getSpatial() { + return spatial; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/MeshGeometryPair.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/MeshGeometryPair.java new file mode 100644 index 000000000..8c14a3f4b --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/MeshGeometryPair.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009-2010 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.light.Light; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; + +/** + * + * @author normenhansen + */ +public class MeshGeometryPair { + private Mesh mesh; + private Geometry spatial; + + public MeshGeometryPair(Mesh light, Geometry spatial) { + this.mesh = light; + this.spatial = spatial; + } + + /** + * @return the light + */ + public Mesh getMesh() { + return mesh; + } + + /** + * @return the spatial + */ + public Geometry getGeometry() { + return spatial; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/NodeUtility.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/NodeUtility.java new file mode 100644 index 000000000..cdc94c738 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/NodeUtility.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009-2010 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.scene.Node; +import org.openide.loaders.DataObject; + +/** + * + * @author normenhansen + */ +public class NodeUtility { + + public static JmeNode createNode(Node node) { + SceneExplorerChildren factory = new SceneExplorerChildren(node); + factory.setReadOnly(true); + JmeNode jmeNode = new JmeNode(node, factory); + return jmeNode; + } + + public static JmeNode createNode(Node node, boolean readOnly) { + SceneExplorerChildren factory = new SceneExplorerChildren(node); + factory.setReadOnly(readOnly); + JmeNode jmeNode = new JmeNode(node, factory); + return jmeNode; + } + + public static JmeNode createNode(Node node, DataObject dataObject) { + SceneExplorerChildren factory = new SceneExplorerChildren(node); + factory.setDataObject(dataObject); + factory.setReadOnly(true); + JmeNode jmeNode = new JmeNode(node, factory); + return jmeNode; + } + + public static JmeNode createNode(Node node, DataObject dataObject, boolean readOnly) { + SceneExplorerChildren factory = new SceneExplorerChildren(node); + factory.setDataObject(dataObject); + factory.setReadOnly(readOnly); + JmeNode jmeNode = new JmeNode(node, factory); + return jmeNode; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/PhysicsVehicleChildren.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/PhysicsVehicleChildren.java new file mode 100644 index 000000000..4b13b06fd --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/PhysicsVehicleChildren.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2009-2010 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.bullet.control.VehicleControl; +import com.jme3.bullet.objects.VehicleWheel; +import com.jme3.gde.core.scene.SceneApplication; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class PhysicsVehicleChildren extends SceneExplorerChildren { + + VehicleControl control; + + public PhysicsVehicleChildren(VehicleControl control) { + this.control = control; + } + + public void refreshChildren(boolean immediate) { + setKeys(createKeys()); + refresh(); + } + + protected List createKeys() { + try { + return SceneApplication.getApplication().enqueue(new Callable>() { + + public List call() throws Exception { + List keys = new LinkedList(); + for (int i = 0; i < control.getNumWheels(); i++) { + keys.add(control.getWheel(i)); + } + return keys; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + public void setReadOnly(boolean cookie) { + this.readOnly = cookie; + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(createKeys()); + } + + @Override + protected Node[] createNodes(Object key) { + if (key instanceof VehicleWheel) { + VehicleWheel assetKey = (VehicleWheel) key; + return new Node[]{new JmeVehicleWheel(control, assetKey)}; + } + return null; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerChildren.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerChildren.java new file mode 100644 index 000000000..08607abcb --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerChildren.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2009-2010 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.effect.ParticleEmitter; +import com.jme3.font.BitmapText; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.light.AmbientLight; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.light.LightList; +import com.jme3.light.PointLight; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; +import com.jme3.ui.Picture; +import java.util.HashMap; +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 org.openide.loaders.DataObject; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +public class SceneExplorerChildren extends Children.Keys { + + protected Spatial spatial; + protected boolean readOnly = true; + protected HashMap map = new HashMap(); + private DataObject dataObject; + + public SceneExplorerChildren() { + } + + public SceneExplorerChildren(Spatial spatial) { + this.spatial = spatial; + } + + 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 createKeys() { + try { + return SceneApplication.getApplication().enqueue(new Callable>() { + + public List call() throws Exception { + List keys = new LinkedList(); + if (spatial != null && spatial instanceof com.jme3.scene.Node) { + keys.addAll(((com.jme3.scene.Node) spatial).getChildren()); +// return keys; + } + if (spatial instanceof Geometry) { + Geometry geom = (Geometry) spatial; + Mesh mesh = geom.getMesh(); + if (mesh != null) { + keys.add(new MeshGeometryPair(mesh, geom)); + } + } + LightList lights = spatial.getLocalLightList(); + for (int i = 0; i < lights.size(); i++) { + Light light = lights.get(i); + if (light != null) { + keys.add(new LightSpatialPair(light, spatial)); + } + } + for (int i = 0; i < spatial.getNumControls(); i++) { + Control control = spatial.getControl(i); + keys.add(control); + } + return keys; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + @Override + protected Node[] createNodes(Object key) { + for (SceneExplorerNode di : Lookup.getDefault().lookupAll(SceneExplorerNode.class)) { + if (di.getExplorerObjectClass().getName().equals(key.getClass().getName())) { + Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Found {0}", di.getExplorerNodeClass()); + Node[] ret = di.createNodes(key, dataObject, readOnly); + if (ret != null) { + return ret; + } + } + } + + //TODO: go down in class hierarchy if class was not found, for now old checks are fallback + if (key instanceof Spatial) { + SceneExplorerChildren children = new SceneExplorerChildren((Spatial) key); + children.setReadOnly(readOnly); + children.setDataObject(dataObject); + if (key instanceof com.jme3.audio.AudioNode) { + return new Node[]{new JmeAudioNode((com.jme3.audio.AudioNode) key, children).setReadOnly(readOnly)}; + } + if (key instanceof com.jme3.scene.Node) { + return new Node[]{new JmeNode((com.jme3.scene.Node) key, children).setReadOnly(readOnly)}; + } + if (key instanceof BitmapText) { + return new Node[]{new JmeBitmapText((BitmapText) key, children).setReadOnly(readOnly)}; + } + if (key instanceof Picture) { + return new Node[]{new JmePicture((Picture) key, children).setReadOnly(readOnly)}; + } + if (key instanceof ParticleEmitter) { + return new Node[]{new JmeParticleEmitter((ParticleEmitter) key, children).setReadOnly(readOnly)}; + } + if (key instanceof com.jme3.scene.Geometry) { + return new Node[]{new JmeGeometry((Geometry) key, children).setReadOnly(readOnly)}; + } + return new Node[]{new JmeSpatial((Spatial) key, children).setReadOnly(readOnly)}; + } else if (key instanceof LightSpatialPair) { + LightSpatialPair pair = (LightSpatialPair) key; + if (pair.getLight() instanceof PointLight) { + return new Node[]{new JmePointLight(pair.getSpatial(), (PointLight) pair.getLight()).setReadOnly(readOnly)}; + } + if (pair.getLight() instanceof DirectionalLight) { + return new Node[]{new JmeDirectionalLight(pair.getSpatial(), (DirectionalLight) pair.getLight()).setReadOnly(readOnly)}; + } + if (pair.getLight() instanceof AmbientLight) { + return new Node[]{new JmeAmbientLight(pair.getSpatial(), (AmbientLight) pair.getLight()).setReadOnly(readOnly)}; + } + return new Node[]{new JmeLight(pair.getSpatial(), pair.getLight()).setReadOnly(readOnly)}; + } else if (key instanceof MeshGeometryPair) { + MeshGeometryPair pair = (MeshGeometryPair) key; + return new Node[]{new JmeMesh(pair.getGeometry(), pair.getMesh()).setReadOnly(readOnly)}; + } + return new Node[]{Node.EMPTY}; + } + + public DataObject getDataObject() { + return dataObject; + } + + public void setDataObject(DataObject dataObject) { + this.dataObject = dataObject; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerLookup.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerLookup.java new file mode 100644 index 000000000..482bff9d1 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerLookup.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009-2010 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 org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; + +/** + * + * @author normenhansen + */ +public class SceneExplorerLookup extends AbstractLookup{ + private static final long serialVersionUID = 1212314412L; + private InstanceContent instanceContent; + + public SceneExplorerLookup(InstanceContent instanceContent) { + super(instanceContent); + this.instanceContent = instanceContent; + instanceContent.add(this); + } + + public InstanceContent getInstanceContent() { + return instanceContent; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerNode.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerNode.java new file mode 100644 index 000000000..24b74d4d3 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/SceneExplorerNode.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2009-2010 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 org.openide.loaders.DataObject; +import org.openide.nodes.Node; + +/** + * + * @author normenhansen + */ +public interface SceneExplorerNode { + + public Class getExplorerNodeClass(); + + public Class getExplorerObjectClass(); + + public abstract Node[] createNodes(Object key, DataObject dataObject, boolean readOnly); + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractNewControlAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractNewControlAction.java new file mode 100644 index 000000000..af5c5b247 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractNewControlAction.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; +import java.awt.event.ActionEvent; +import java.util.concurrent.Callable; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +public abstract class AbstractNewControlAction implements NewControlAction { + + protected String name = "*"; + + protected abstract Control doCreateControl(Spatial spatial); + + protected Action makeAction(final JmeSpatial rootNode, final DataObject dataObject) { + final Spatial spatial = rootNode.getLookup().lookup(Spatial.class); + return new AbstractAction(name) { + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + final Control attachControl = doCreateControl(spatial); + if (spatial != null && attachControl != null) { + spatial.addControl(attachControl); + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + spatial.removeControl(attachControl); + } + + @Override + public void sceneRedo() throws CannotRedoException { + spatial.addControl(attachControl); + } + + @Override + public void awtRedo() { + dataObject.setModified(true); + rootNode.refresh(true); + } + + @Override + public void awtUndo() { + dataObject.setModified(true); + rootNode.refresh(true); + } + }); + setModified(); + } + return null; + } + }); + } + + protected void setModified() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + dataObject.setModified(true); + rootNode.refresh(true); + } + }); + } + }; + } + + public Action getAction(JmeSpatial rootNode, DataObject dataObject) { + return makeAction(rootNode, dataObject); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractNewSpatialAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractNewSpatialAction.java new file mode 100644 index 000000000..1bff08c67 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractNewSpatialAction.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import java.awt.event.ActionEvent; +import java.util.concurrent.Callable; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +public abstract class AbstractNewSpatialAction implements NewSpatialAction { + + protected String name = "*"; + + protected abstract Spatial doCreateSpatial(Node parent); + + protected Action makeAction(final JmeNode rootNode, final DataObject dataObject) { + final Node node = rootNode.getLookup().lookup(Node.class); + return new AbstractAction(name) { + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + final Spatial attachSpatial = doCreateSpatial(node); + if (node != null && attachSpatial != null) { + node.attachChild(attachSpatial); + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + attachSpatial.removeFromParent(); + } + + @Override + public void sceneRedo() throws CannotRedoException { + node.attachChild(attachSpatial); + } + + @Override + public void awtRedo() { + dataObject.setModified(true); + rootNode.refresh(true); + } + + @Override + public void awtUndo() { + dataObject.setModified(true); + rootNode.refresh(true); + } + }); + setModified(); + } + return null; + } + }); + } + + protected void setModified() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + dataObject.setModified(true); + rootNode.refresh(true); + } + }); + } + }; + } + + public Action getAction(JmeNode rootNode, DataObject dataObject) { + return makeAction(rootNode, dataObject); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractToolAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractToolAction.java new file mode 100644 index 000000000..6ea95a34f --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractToolAction.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import java.awt.event.ActionEvent; +import java.util.concurrent.Callable; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +public abstract class AbstractToolAction implements ToolAction { + + protected String name = "*"; + + protected Action makeAction(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { + return new AbstractAction(name) { + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + if (doApplyTool(rootNode)) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + doUndoTool(rootNode); + setModified(); + } + + @Override + public void sceneRedo() throws CannotRedoException { + doApplyTool(rootNode); + setModified(); + } + + @Override + public void awtRedo() { + dataObject.setModified(true); + rootNode.refresh(true); + } + + @Override + public void awtUndo() { + dataObject.setModified(true); + rootNode.refresh(true); + } + }); + setModified(); + } + return null; + } + }); + } + + protected void setModified() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + dataObject.setModified(true); + rootNode.refresh(true); + } + }); + } + }; + } + + protected abstract boolean doApplyTool(AbstractSceneExplorerNode rootNode); + + protected abstract void doUndoTool(AbstractSceneExplorerNode rootNode); + +// protected abstract void doAwtUndo(); +// protected abstract void doAwtRedo(); + public Action getAction(AbstractSceneExplorerNode rootNode, DataObject dataObject) { + return makeAction(rootNode, dataObject); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddControlAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddControlAction.java new file mode 100644 index 000000000..ffd2f57b8 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddControlAction.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.scene.Node; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; +import org.openide.util.actions.Presenter; + +/** + * + * @author normenhansen + */ +public class AddControlAction extends AbstractAction implements Presenter.Popup { + + protected JmeSpatial jmeSpatial; + protected Node node; + protected DataObject dataObject; + + public AddControlAction(JmeSpatial node) { + this.jmeSpatial = node; + this.node = node.getLookup().lookup(Node.class); + this.dataObject = node.getLookup().lookup(DataObject.class); + } + + public void actionPerformed(ActionEvent e) { + } + + public JMenuItem getPopupPresenter() { + JMenu result = new JMenu("Add Control.."); + for (NewControlAction di : Lookup.getDefault().lookupAll(NewControlAction.class)) { + result.add(new JMenuItem(di.getAction(jmeSpatial, dataObject))); + } + return result; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddLightAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddLightAction.java new file mode 100644 index 000000000..16e658966 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddLightAction.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.light.AmbientLight; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.light.PointLight; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.awt.event.ActionEvent; +import java.util.concurrent.Callable; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; +import org.openide.util.actions.Presenter; + +/** + * + * @author normenhansen + */ +public class AddLightAction extends AbstractAction implements Presenter.Popup { + + protected JmeSpatial jmeNode; + protected Spatial node; + protected DataObject dataObject; + + public AddLightAction(JmeSpatial node) { + this.jmeNode = node; + this.node = node.getLookup().lookup(Spatial.class); + this.dataObject = node.getLookup().lookup(DataObject.class); + } + + public void actionPerformed(ActionEvent e) { + } + + public JMenuItem getPopupPresenter() { + JMenu result = new JMenu("Add Light.."); + result.add(new JMenuItem(new AddAmbientAction())); + result.add(new JMenuItem(new AddDirectionalAction())); + result.add(new JMenuItem(new AddPointAction())); + return result; + } + + private class AddAmbientAction extends AbstractAction { + + public AddAmbientAction() { + putValue(NAME, "Ambient Light"); + } + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + AmbientLight light = new AmbientLight(); + light.setColor(ColorRGBA.White); + node.addLight(light); + addLightUndo(node, light); + setModified(); + return null; + } + }); + } + } + + private class AddDirectionalAction extends AbstractAction { + + public AddDirectionalAction() { + putValue(NAME, "Directional Light"); + } + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + DirectionalLight light = new DirectionalLight(); + light.setDirection(new Vector3f(-1, -1, -1).normalizeLocal()); + light.setColor(ColorRGBA.White); + node.addLight(light); + addLightUndo(node, light); + setModified(); + return null; + } + }); + } + } + + private class AddPointAction extends AbstractAction { + + public AddPointAction() { + putValue(NAME, "Point Light"); + } + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + PointLight light = new PointLight(); + light.setColor(ColorRGBA.White); + addLightUndo(node, light); + setModified(); + return null; + } + }); + } + } + + private void addLightUndo(final Spatial undoParent, final Light undoLight) { + //add undo + if (undoParent != null && undoLight != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + undoParent.removeLight(undoLight); + } + + @Override + public void sceneRedo() throws CannotRedoException { + undoParent.addLight(undoLight); + } + + @Override + public void awtRedo() { + dataObject.setModified(true); + jmeNode.refresh(true); + } + + @Override + public void awtUndo() { + dataObject.setModified(true); + jmeNode.refresh(true); + } + }); + } + } + + private void setModified() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + dataObject.setModified(true); + jmeNode.refresh(true); + } + }); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddSpatialAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddSpatialAction.java new file mode 100644 index 000000000..ff707e627 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddSpatialAction.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.audio.AudioNode; +import com.jme3.effect.EmitterSphereShape; +import com.jme3.effect.ParticleEmitter; +import com.jme3.effect.ParticleMesh; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.material.Material; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import java.awt.event.ActionEvent; +import java.util.concurrent.Callable; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; +import org.openide.util.actions.Presenter; + +/** + * + * @author normenhansen + */ +public class AddSpatialAction extends AbstractAction implements Presenter.Popup { + + protected JmeNode jmeNode; + protected Node node; + protected DataObject dataObject; + + public AddSpatialAction(JmeNode node) { + this.jmeNode = node; + this.node = node.getLookup().lookup(Node.class); + this.dataObject = node.getLookup().lookup(DataObject.class); + } + + public void actionPerformed(ActionEvent e) { + } + + public JMenuItem getPopupPresenter() { + JMenu result = new JMenu("Add Spatial.."); + result.add(new JMenuItem(new AddNodeAction())); + result.add(new JMenuItem(new AddEmitterAction())); + result.add(new JMenuItem(new AddAudioNodeAction())); + for (NewSpatialAction di : Lookup.getDefault().lookupAll(NewSpatialAction.class)) { + result.add(new JMenuItem(di.getAction(jmeNode, dataObject))); + } + return result; + } + + private class AddNodeAction extends AbstractAction { + + public AddNodeAction() { + putValue(NAME, "Node"); + } + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + Node newItem = new Node("Node"); + node.attachChild(newItem); + addSpatialUndo(node, newItem); + setModified(); + return null; + } + }); + } + } + + private class AddEmitterAction extends AbstractAction { + + public AddEmitterAction() { + putValue(NAME, "Particle Emitter"); + } + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + ParticleEmitter emit = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 200); + emit.setShape(new EmitterSphereShape(Vector3f.ZERO, 1f)); + emit.setGravity(0); + emit.setLowLife(5); + emit.setHighLife(10); + emit.setInitialVelocity(new Vector3f(0, 0, 0)); + emit.setImagesX(15); + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/Particle.j3md"); + emit.setMaterial(mat); + node.attachChild(emit); + addSpatialUndo(node, emit); + setModified(); + return null; + } + }); + } + } + + private class AddAudioNodeAction extends AbstractAction { + + public AddAudioNodeAction() { + putValue(NAME, "Audio Node"); + } + + public void actionPerformed(ActionEvent e) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + AudioNode newItem = new AudioNode(); + newItem.setName("AudioNode"); + node.attachChild(newItem); + addSpatialUndo(node, newItem); + setModified(); + return null; + } + }); + } + } + + private void addSpatialUndo(final Node undoParent, final Spatial undoSpatial) { + //add undo + if (undoParent != null && undoSpatial != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + undoSpatial.removeFromParent(); + } + + @Override + public void sceneRedo() throws CannotRedoException { + undoParent.attachChild(undoSpatial); + } + + @Override + public void awtRedo() { + dataObject.setModified(true); + jmeNode.refresh(true); + } + + @Override + public void awtUndo() { + dataObject.setModified(true); + jmeNode.refresh(true); + } + }); + } + } + + private void setModified() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + dataObject.setModified(true); + jmeNode.refresh(true); + } + }); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddUserDataAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddUserDataAction.java new file mode 100644 index 000000000..1b096c472 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddUserDataAction.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import javax.swing.JFrame; + +public final class AddUserDataAction implements ActionListener { + + private final JmeSpatial context; + private UserDataDialog dialog; + + public AddUserDataAction(JmeSpatial context) { + this.context = context; + dialog=new UserDataDialog(new JFrame(), true, context); + } + + public void actionPerformed(ActionEvent ev) { + dialog.setLocationRelativeTo(null); + dialog.setVisible(true); +// for (JmeSpatial jmeSpatial : context) { + // TODO use jmeSpatial +// } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/Bundle.properties new file mode 100644 index 000000000..2a3ddc099 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/Bundle.properties @@ -0,0 +1,7 @@ +CTL_EditUserDataAction=Edit User Data.. +UserDataDialog.jTextField1.text= +UserDataDialog.jButton1.text=OK +UserDataDialog.jButton2.text=Cancel +UserDataDialog.jLabel1.text=Name: +UserDataDialog.jTextField2.text= +UserDataDialog.jLabel2.text=Data: diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/NewControlAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/NewControlAction.java new file mode 100644 index 000000000..4dc0c80c9 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/NewControlAction.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import javax.swing.Action; +import org.openide.loaders.DataObject; + +/** + * + * @author normenhansen + */ +public interface NewControlAction { + public Action getAction(JmeSpatial spatial, DataObject dataObject); +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/NewSpatialAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/NewSpatialAction.java new file mode 100644 index 000000000..9d89a75a3 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/NewSpatialAction.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import javax.swing.Action; +import org.openide.loaders.DataObject; + +/** + * + * @author normenhansen + */ +public interface NewSpatialAction { + public Action getAction(JmeNode rootNode, DataObject dataObject); +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/ToolAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/ToolAction.java new file mode 100644 index 000000000..0994457ea --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/ToolAction.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import javax.swing.Action; +import org.openide.loaders.DataObject; + +/** + * + * @author normenhansen + */ +public interface ToolAction { + public Class getNodeClass(); + public Action getAction(AbstractSceneExplorerNode object, DataObject dataObject); +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UseToolAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UseToolAction.java new file mode 100644 index 000000000..67faae673 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UseToolAction.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009-2010 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.actions; + +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.scene.Spatial; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; +import org.openide.util.actions.Presenter; + +/** + * + * @author normenhansen + */ +public class UseToolAction extends AbstractAction implements Presenter.Popup { + + protected AbstractSceneExplorerNode exNode; + protected DataObject dataObject; + + public UseToolAction(AbstractSceneExplorerNode node) { + this.exNode = node; + this.dataObject = node.getLookup().lookup(DataObject.class); + } + + public void actionPerformed(ActionEvent e) { + } + + public JMenuItem getPopupPresenter() { + JMenu result = new JMenu("Tools.."); + for (ToolAction di : Lookup.getDefault().lookupAll(ToolAction.class)) { + if(exNode.getClass().isAssignableFrom(di.getNodeClass())){ + result.add(new JMenuItem(di.getAction(exNode, dataObject))); + } + } + return result; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form new file mode 100644 index 000000000..022c23cbc --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form @@ -0,0 +1,144 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java new file mode 100644 index 000000000..5cbfb689c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * UserDataDialog.java + * + * Created on 29.01.2011, 18:35:53 + */ +package com.jme3.gde.core.sceneexplorer.nodes.actions; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.scene.Spatial; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.loaders.DataObject; + +/** + * + * @author normenhansen + */ +public class UserDataDialog extends javax.swing.JDialog { + + JmeSpatial spat; + + /** Creates new form UserDataDialog */ + public UserDataDialog(java.awt.Frame parent, boolean modal, JmeSpatial spat) { + super(parent, modal); + this.spat = spat; + initComponents(); + } + + private void updateSpatial() { + final String format = (String) jComboBox1.getSelectedItem(); + final String data = jTextField1.getText(); + final String name = jTextField2.getText(); + if (name.trim().length() == 0) { + return; + } + final Spatial spatial = spat.getLookup().lookup(Spatial.class); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + if (format.equals("String")) { + spatial.setUserData(name, data); + } else if (format.equals("Int")) { + spatial.setUserData(name, Integer.parseInt(data)); + } else if (format.equals("Float")) { + spatial.setUserData(name, Float.parseFloat(data)); + } else if (format.equals("Boolean")) { + spatial.setUserData(name, Boolean.parseBoolean(data)); + } else if (format.equals("Long")) { + spatial.setUserData(name, Long.parseLong(data)); + } + return null; + } + }).get(); + } catch (InterruptedException ex) { + } catch (ExecutionException ex) { + } + spat.refreshProperties(); + spat.getLookup().lookup(DataObject.class).setModified(true); + setVisible(false); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jComboBox1 = new javax.swing.JComboBox(); + jTextField1 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + jLabel1 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "String", "Int", "Float", "Boolean", "Long" })); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jTextField1.text")); // NOI18N + jTextField1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jTextField1ActionPerformed(evt); + } + }); + + jButton1.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jLabel1.text")); // NOI18N + + jTextField2.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jTextField2.text")); // NOI18N + + jLabel2.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jLabel2.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 187, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addGap(18, 18, 18) + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 186, Short.MAX_VALUE))) + .addGap(18, 18, 18) + .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(20, 20, 20)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1) + .addComponent(jButton2)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed + updateSpatial(); + }//GEN-LAST:event_jTextField1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + setVisible(false); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + updateSpatial(); + }//GEN-LAST:event_jButton1ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JComboBox jComboBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/GenerateTangentsTool.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/GenerateTangentsTool.java new file mode 100644 index 000000000..fdbd362bc --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/GenerateTangentsTool.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2009-2010 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.actions.impl; + +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.sceneexplorer.nodes.JmeGeometry; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractToolAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.ToolAction; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.VertexBuffer.Type; +import com.jme3.util.TangentBinormalGenerator; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service = ToolAction.class) +public class GenerateTangentsTool extends AbstractToolAction { + + public GenerateTangentsTool() { + name = "Generate Tangents"; + } + + @Override + protected boolean doApplyTool(AbstractSceneExplorerNode rootNode) { + Geometry geom = rootNode.getLookup().lookup(Geometry.class); + Mesh mesh = geom.getMesh(); + if (mesh != null) { + TangentBinormalGenerator.generate(mesh); + } + return true; + } + + @Override + protected void doUndoTool(AbstractSceneExplorerNode rootNode) { + Geometry geom = rootNode.getLookup().lookup(Geometry.class); + Mesh mesh = geom.getMesh(); + if (mesh != null) { + mesh.clearBuffer(Type.Tangent); + } + } + + public Class getNodeClass() { + return JmeGeometry.class; + } + +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewCharacterAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewCharacterAction.java new file mode 100644 index 000000000..068be89c6 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewCharacterAction.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009-2010 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.actions.impl; + +import com.jme3.bullet.collision.shapes.CapsuleCollisionShape; +import com.jme3.bullet.control.CharacterControl; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractNewControlAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.NewControlAction; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service = NewControlAction.class) +public class NewCharacterAction extends AbstractNewControlAction { + + public NewCharacterAction() { + name = "Character"; + } + + @Override + protected Control doCreateControl(Spatial spatial) { + CharacterControl control = spatial.getControl(CharacterControl.class); + if (control != null) { + spatial.removeControl(control); + } + Node parent = spatial.getParent(); + spatial.removeFromParent(); + control = new CharacterControl(new CapsuleCollisionShape(0.6f, 1.8f), 0.03f); + if (parent != null) { + parent.attachChild(spatial); + } + return control; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewRigidBodyAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewRigidBodyAction.java new file mode 100644 index 000000000..0dfcc4883 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewRigidBodyAction.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009-2010 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.actions.impl; + +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractNewControlAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.NewControlAction; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service = NewControlAction.class) +public class NewRigidBodyAction extends AbstractNewControlAction { + + public NewRigidBodyAction() { + name = "Static RigidBody"; + } + + @Override + protected Control doCreateControl(Spatial spatial) { + RigidBodyControl control = spatial.getControl(RigidBodyControl.class); + if (control != null) { + spatial.removeControl(control); + } + Node parent = spatial.getParent(); + spatial.removeFromParent(); + control = new RigidBodyControl(0); + if (parent != null) { + parent.attachChild(spatial); + } + return control; + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/animationcontrol.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/animationcontrol.gif new file mode 100644 index 000000000..228cfe3ec Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/animationcontrol.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/audionode.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/audionode.gif new file mode 100644 index 000000000..6b7af790a Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/audionode.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/bitmaptext.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/bitmaptext.gif new file mode 100644 index 000000000..3747a103e Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/bitmaptext.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/charactercontrol.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/charactercontrol.gif new file mode 100644 index 000000000..44752ae55 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/charactercontrol.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/geometry.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/geometry.gif new file mode 100644 index 000000000..eeab8ff3a Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/geometry.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/ghostcontrol.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/ghostcontrol.gif new file mode 100644 index 000000000..28305f93f Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/ghostcontrol.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/ghostnode.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/ghostnode.gif new file mode 100644 index 000000000..0504b5c64 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/ghostnode.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/light.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/light.gif new file mode 100644 index 000000000..18cc19cee Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/light.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/linknode.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/linknode.gif new file mode 100644 index 000000000..9223a9e22 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/linknode.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/mesh.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/mesh.gif new file mode 100644 index 000000000..af6eeddcc Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/mesh.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/node.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/node.gif new file mode 100644 index 000000000..95ca42aba Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/node.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/particleemitter.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/particleemitter.gif new file mode 100644 index 000000000..c24d2a507 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/particleemitter.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicscontrol.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicscontrol.gif new file mode 100644 index 000000000..b8411f295 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicscontrol.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicsnode.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicsnode.gif new file mode 100644 index 000000000..867c8c5e3 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicsnode.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicswheel.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicswheel.gif new file mode 100644 index 000000000..7a08bf03e Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/physicswheel.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/picture.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/picture.gif new file mode 100644 index 000000000..638f48ff0 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/picture.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/player.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/player.gif new file mode 100644 index 000000000..038567624 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/player.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/terrain.png b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/terrain.png new file mode 100644 index 000000000..7028eebb5 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/terrain.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/vehicle.png b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/vehicle.png new file mode 100644 index 000000000..a399abd39 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/icons/vehicle.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AnimationProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AnimationProperty.java new file mode 100644 index 000000000..3bd324a9f --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AnimationProperty.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.animation.AnimControl; +import com.jme3.gde.core.scene.SceneApplication; +import java.beans.PropertyEditor; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.nodes.PropertySupport; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class AnimationProperty extends PropertySupport.ReadWrite { + + private AnimControl control; + private String anim = "null"; + + public AnimationProperty(AnimControl node) { + super("Animation Control", String.class, "Animation Control", ""); + this.control = node; + } + + @Override + public String getValue() throws IllegalAccessException, InvocationTargetException { + return anim; + } + + @Override + public void setValue(final String val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + if (control == null) { + return; + } + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + if ("null".equals(val)) { + control.clearChannels(); + return null; + } + anim = val; + control.clearChannels(); + control.createChannel().setAnim(val); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + public PropertyEditor getPropertyEditor() { + return new AnimationPropertyEditor(control); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AnimationPropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AnimationPropertyEditor.java new file mode 100644 index 000000000..1b35537d1 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AnimationPropertyEditor.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.animation.AnimControl; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author normenhansen + */ +public class AnimationPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private String animName; + private AnimControl control; + + public AnimationPropertyEditor(AnimControl control) { + this.control = control; + } + + public void setValue(Object value) { + if (value instanceof String) { + animName = (String) value; + } + } + + public Object getValue() { + return animName; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + return animName.toString(); + } + + public void setAsText(String text) throws IllegalArgumentException { + String old = animName; + if ("".equals(text)) { + animName = "null"; + } + animName = text; + notifyListeners(old, animName); + } + + public String[] getTags() { + if(control==null)return new String[]{"none"}; + Collection names = control.getAnimationNames(); + String[] strings = new String[names.size() + 1]; + strings[0] = "null"; + int i = 1; + for (Iterator it = names.iterator(); it.hasNext();) { + strings[i] = it.next(); + i++; + } + return strings; + } + + public Component getCustomEditor() { +// return new AnimationPanel(control); + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(String before, String after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its Quaternion + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AudioDataProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AudioDataProperty.java new file mode 100644 index 000000000..f5f91c85c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AudioDataProperty.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.audio.AudioData; +import com.jme3.audio.AudioKey; +import com.jme3.audio.AudioNode; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneRequest; +import java.beans.PropertyEditor; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.nodes.PropertySupport; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class AudioDataProperty extends PropertySupport.ReadWrite { + + private AudioNode node; + + public AudioDataProperty(AudioNode node) { + super("Audio Data", String.class, "Audio Data", ""); + this.node = node; + } + + @Override + public String getValue() throws IllegalAccessException, InvocationTargetException { + if (node.getAudioData() != null) { + return node.getAudioData().toString(); + } else { + return "null"; + } + } + + @Override + public void setValue(final String val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + if ("null".equals(val)) { + return; + } + if (node.getAudioData() == null) { +// val = val.replace('[', ' ').trim(); +// val = val.replace(']', ' ').trim(); +// final String[] strings = val.split(","); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + SceneRequest request = SceneApplication.getApplication().getCurrentSceneRequest(); + AudioKey key = new AudioKey(val, false); + AudioData localMaterial = request.getManager().getManager().loadAudio(key); + if (localMaterial != null) { + node.setAudioData(localMaterial, key); + } + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + } + + @Override + public PropertyEditor getPropertyEditor() { + return new AudioDataPropertyEditor(); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AudioDataPropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AudioDataPropertyEditor.java new file mode 100644 index 000000000..b671a2f01 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/AudioDataPropertyEditor.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.audio.AudioData; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneRequest; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author normenhansen + */ +public class AudioDataPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private String material; + + public void setValue(Object value) { + if (value instanceof String) { + material = (String) value; + } + } + + public Object getValue() { + return material; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + return material.toString(); + } + + public void setAsText(String text) throws IllegalArgumentException { + String old=material; + if ("".equals(text)) { + material = "null"; + } + material = text; + notifyListeners(old, material); + } + + public String[] getTags() { + if ("null".equals(material)) { + SceneRequest request = SceneApplication.getApplication().getCurrentSceneRequest(); + if(request==null) return new String[]{}; + String[] mats = request.getManager().getSounds(); + return mats; + } + return new String[]{"can set only once"}; + } + + public Component getCustomEditor() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(String before, String after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its Quaternion + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Bundle.properties new file mode 100644 index 000000000..bd1283d27 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Bundle.properties @@ -0,0 +1,9 @@ +ColorRGBADialog.jButton1.text=OK +ColorRGBADialog.jButton2.text=Cancel +ColorRGBADialog.alphaLabel.text=Alpha: +AnimationPanel.pauseButton.text= +AnimationPanel.playButton.text= +TextureBrowser.cancelButton.text=Cancel +TextureBrowser.okButton.text=Ok +TextureBrowser.imagePreviewLabel.text= +TextureBrowser.title=Texture Browser \ No newline at end of file diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBADialog.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBADialog.form new file mode 100644 index 000000000..be8ab19ff --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBADialog.form @@ -0,0 +1,97 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBADialog.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBADialog.java new file mode 100644 index 000000000..eee73e2f1 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBADialog.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * ColorRGBADialog.java + * + * Created on 06.04.2010, 20:58:59 + */ +package com.jme3.gde.core.sceneexplorer.nodes.properties; + +import com.jme3.math.ColorRGBA; +import java.awt.Color; + +/** + * + * @author normenhansen + */ +public class ColorRGBADialog extends javax.swing.JDialog { + + private ColorRGBAPropertyEditor editor; + + /** Creates new form ColorRGBADialog */ + public ColorRGBADialog(java.awt.Frame parent, boolean modal, ColorRGBAPropertyEditor editor) { + super(parent, modal); + this.editor = editor; + initComponents(); + alphaSlider.setValue(Math.round(((ColorRGBA)editor.getValue()).getAlpha()*100)); + } + + public ColorRGBA setColor() { + Color cColor = jColorChooser1.getColor(); + ColorRGBA color = new ColorRGBA(); + float[] floats = new float[4]; + cColor.getComponents(floats); + color.set(floats[0], floats[1], floats[2], ((float)alphaSlider.getValue())/100.0f); + ColorRGBA color2 = new ColorRGBA((ColorRGBA) editor.getValue()); + editor.setValue(color); + editor.notifyListeners(color2, color); + return color; + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jColorChooser1 = new javax.swing.JColorChooser(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + jToolBar1 = new javax.swing.JToolBar(); + alphaLabel = new javax.swing.JLabel(); + alphaSlider = new javax.swing.JSlider(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jButton1.setText(org.openide.util.NbBundle.getMessage(ColorRGBADialog.class, "ColorRGBADialog.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText(org.openide.util.NbBundle.getMessage(ColorRGBADialog.class, "ColorRGBADialog.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + alphaLabel.setText(org.openide.util.NbBundle.getMessage(ColorRGBADialog.class, "ColorRGBADialog.alphaLabel.text")); // NOI18N + jToolBar1.add(alphaLabel); + + alphaSlider.setValue(100); + jToolBar1.add(alphaSlider); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1)) + .addComponent(jColorChooser1, javax.swing.GroupLayout.DEFAULT_SIZE, 496, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jColorChooser1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1) + .addComponent(jButton2)) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))) + ); + + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + setColor(); + dispose(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + dispose(); + }//GEN-LAST:event_jButton2ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel alphaLabel; + private javax.swing.JSlider alphaSlider; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JColorChooser jColorChooser1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBAPropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBAPropertyEditor.java new file mode 100644 index 000000000..e5bba674c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ColorRGBAPropertyEditor.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.math.ColorRGBA; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author normenhansen + */ +public class ColorRGBAPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private ColorRGBA color = new ColorRGBA(); + + public void setValue(Object value) { + if (value instanceof ColorRGBA) { + color.set((ColorRGBA) value); + } + } + + public Object getValue() { + return color; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + return "[" + color.r + ", " + color.g + ", " + color.b + ", " + color.a + "]"; + } + + public void setAsText(String text) throws IllegalArgumentException { + text = text.replace('[', ' '); + text = text.replace(']', ' '); + String[] values = text.split(","); + ColorRGBA old=color; + if (values.length != 4) { + throw (new IllegalArgumentException("String not correct")); + } + float[] floats = new float[4]; + for (int i = 0; i < values.length; i++) { + String string = values[i]; + floats[i] = Float.parseFloat(string); + } + color.set(floats[0], floats[1], floats[2], floats[3]); + notifyListeners(old, color); + } + + public String[] getTags() { + return null; + } + + public Component getCustomEditor() { + ColorRGBADialog dialog = new ColorRGBADialog(null, true, this); + dialog.setLocationRelativeTo(null); + return dialog; + } + + public boolean supportsCustomEditor() { + return true; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + public void notifyListeners(ColorRGBA before, ColorRGBA after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its ColorRGBA + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/EmitterShapePropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/EmitterShapePropertyEditor.java new file mode 100644 index 000000000..d28faa51c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/EmitterShapePropertyEditor.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.effect.EmitterBoxShape; +import com.jme3.effect.EmitterPointShape; +import com.jme3.effect.EmitterShape; +import com.jme3.effect.EmitterSphereShape; +import com.jme3.math.Vector3f; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; +import org.openide.awt.StatusDisplayer; + +/** + * + * @author normenhansen + */ +public class EmitterShapePropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private EmitterShape emitter;// = new EmitterPointShape(Vector3f.ZERO); + + public void setValue(Object value) { + if (value instanceof EmitterShape) { + emitter = (EmitterShape) value; + } + } + + public Object getValue() { + return emitter; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + if (emitter == null) { + return "null"; + } + if (emitter instanceof EmitterBoxShape) { + EmitterBoxShape shape = (EmitterBoxShape) emitter; + return "[Box, " + + shape.getMin().x + + ", " + + shape.getMin().y + + ", " + + shape.getMin().z + + ", " + + shape.getMin().x + shape.getLen().x + + ", " + + shape.getMin().x + shape.getLen().y + + ", " + + shape.getMin().x + shape.getLen().z + + "]"; + } else if (emitter instanceof EmitterPointShape) { + EmitterPointShape shape = (EmitterPointShape) emitter; + return "[Point, " + + shape.getPoint().x + + ", " + + shape.getPoint().y + + ", " + + shape.getPoint().z + + "]"; + } else if (emitter instanceof EmitterSphereShape) { + EmitterSphereShape shape = (EmitterSphereShape) emitter; + return "[Sphere, " + + shape.getCenter().x + + ", " + + shape.getCenter().y + + ", " + + shape.getCenter().z + + ", " + + shape.getRadius() + + "]"; + } + return emitter.toString(); + } + + public void setAsText(String text) throws IllegalArgumentException { + text = text.replace('[', ' ').trim(); + text = text.replace(']', ' ').trim(); + String[] strings = text.split(","); + EmitterShape old=emitter; + if (strings.length == 0) { + return; + } + if ("box".equals(strings[0].trim().toLowerCase())) { + if (strings.length == 7) { + StatusDisplayer.getDefault().setStatusText("try set parameterized box shape"); + emitter = new EmitterBoxShape( + new Vector3f(Float.parseFloat(strings[1]), Float.parseFloat(strings[2]), Float.parseFloat(strings[3])), new Vector3f(Float.parseFloat(strings[4]), Float.parseFloat(strings[5]), Float.parseFloat(strings[6]))); + } else { + StatusDisplayer.getDefault().setStatusText("try set standard box shape"); + emitter = new EmitterBoxShape(new Vector3f(-.5f, -.5f, -.5f), new Vector3f(.5f, .5f, .5f)); + } + } else if ("point".equals(strings[0].trim().toLowerCase())) { + if (strings.length == 4) { + emitter = new EmitterPointShape( + new Vector3f(Float.parseFloat(strings[1]), Float.parseFloat(strings[2]), Float.parseFloat(strings[3]))); + } else { + emitter = new EmitterPointShape(Vector3f.ZERO); + } + } else if ("sphere".equals(strings[0].trim().toLowerCase())) { + if (strings.length == 5) { + emitter = new EmitterSphereShape( + new Vector3f(Float.parseFloat(strings[1]), Float.parseFloat(strings[2]), Float.parseFloat(strings[3])), Float.parseFloat(strings[4])); + } else { + emitter = new EmitterSphereShape(Vector3f.ZERO, .5f); + } + } + notifyListeners(old, emitter); + } + + public String[] getTags() { +// String[] mats = new String[]{"[Point]", "[Sphere]", "[Box]"}; + return null; + } + + public Component getCustomEditor() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(EmitterShape before, EmitterShape after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its Quaternion + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/MaterialPropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/MaterialPropertyEditor.java new file mode 100644 index 000000000..776fb6c66 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/MaterialPropertyEditor.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.asset.AssetKey; +import com.jme3.asset.DesktopAssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneRequest; +import com.jme3.material.Material; +import com.jme3.math.Quaternion; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class MaterialPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private Material material = new Material(); + + public void setValue(Object value) { + if (value instanceof Material) { + material = (Material) value; + } + } + + public Object getValue() { + return material; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + return material.toString(); + } + + public void setAsText(final String text) throws IllegalArgumentException { + try { + Material old = material; + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + SceneRequest request = SceneApplication.getApplication().getCurrentSceneRequest(); + ((DesktopAssetManager) request.getManager().getManager()).deleteFromCache(new AssetKey(text)); + Material localMaterial = (Material) request.getManager().getManager().loadAsset(text); + if (localMaterial != null) { + material = localMaterial; + } + return null; + } + }).get(); + notifyListeners(old, material); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public String[] getTags() { + SceneRequest request = SceneApplication.getApplication().getCurrentSceneRequest(); + if(request==null) return new String[]{}; + String[] mats = request.getManager().getMaterials(); + return mats; + } + + public Component getCustomEditor() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(Material before, Material after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its Quaternion + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Matrix3fPropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Matrix3fPropertyEditor.java new file mode 100644 index 000000000..842204a7f --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Matrix3fPropertyEditor.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.math.Matrix3f; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author normenhansen + */ +public class Matrix3fPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private Matrix3f vector = new Matrix3f(); + + public void setValue(Object value) { + if (value instanceof Matrix3f) { + vector.set((Matrix3f) value); + } + } + + public Object getValue() { + return vector; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + return vector.toString(); + } + + public void setAsText(String text) throws IllegalArgumentException { + text = text.replace('[', ' '); + text = text.replace(']', ' '); + String[] values = text.split(","); + if (values.length != 3) { + throw (new IllegalArgumentException("String not correct")); + } + float[] floats = new float[3]; + for (int i = 0; i < values.length; i++) { + String string = values[i]; + floats[i] = Float.parseFloat(string); + } + Matrix3f old = new Matrix3f(); + old.set(vector); +// vector.set(floats[0], floats[1], floats[2]); + notifyListeners(old, vector); + } + + public String[] getTags() { + return null; + } + + public Component getCustomEditor() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(Matrix3f before, Matrix3f after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its Matrix3f + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/QuaternionPropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/QuaternionPropertyEditor.java new file mode 100644 index 000000000..733d332e0 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/QuaternionPropertyEditor.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.math.Quaternion; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author normenhansen + */ +public class QuaternionPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private Quaternion quaternion = new Quaternion(); + + public void setValue(Object value) { + if (value instanceof Quaternion) { + quaternion.set((Quaternion) value); + } + } + + public Object getValue() { + return quaternion; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + float[] angles=quaternion.toAngles(new float[3]); + return "[" + angles[0] + ", " + angles[1] + ", " + angles[2] + "]"; + } + + public void setAsText(String text) throws IllegalArgumentException { + text = text.replace('[', ' '); + text = text.replace(']', ' '); + String[] values = text.split(","); + if (values.length != 3) { + throw (new IllegalArgumentException("String not correct")); + } + float[] floats = new float[3]; + for (int i = 0; i < values.length; i++) { + String string = values[i]; + floats[i] = Float.parseFloat(string); + } + Quaternion old=new Quaternion(); + old.set(quaternion); + quaternion.fromAngles(floats); + notifyListeners(old,quaternion); + } + + public String[] getTags() { + return null; + } + + public Component getCustomEditor() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(Quaternion before, Quaternion after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its Quaternion + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/SceneExplorerProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/SceneExplorerProperty.java new file mode 100644 index 000000000..d2a55635a --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/SceneExplorerProperty.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.effect.EmitterShape; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Matrix3f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.nodes.PropertySupport; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +public class SceneExplorerProperty extends PropertySupport.Reflection { + + protected LinkedList listeners = new LinkedList(); + + public SceneExplorerProperty(T instance, Class valueType, String getter, String setter) throws NoSuchMethodException { + this(instance, valueType, getter, setter, null); + } + + public SceneExplorerProperty(T instance, Class valueType, String getter, String setter, ScenePropertyChangeListener listener) throws NoSuchMethodException { + super(instance, valueType, getter, setter); + addPropertyChangeListener(listener); + if (valueType == Vector3f.class) { + setPropertyEditorClass(Vector3fPropertyEditor.class); + } else if (valueType == Quaternion.class) { + setPropertyEditorClass(QuaternionPropertyEditor.class); + } else if (valueType == Matrix3f.class) { + setPropertyEditorClass(Matrix3fPropertyEditor.class); + } else if (valueType == ColorRGBA.class) { + setPropertyEditorClass(ColorRGBAPropertyEditor.class); + } else if (valueType == Material.class) { + setPropertyEditorClass(MaterialPropertyEditor.class); + } else if (valueType == EmitterShape.class) { + setPropertyEditorClass(EmitterShapePropertyEditor.class); + } + } + + @Override + public T getValue() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + return super.getValue(); +// try { +// return SceneApplication.getApplication().enqueue(new Callable() { +// +// public T call() throws Exception { +// return getSuperValue(); +// } +// }).get(); +// } catch (InterruptedException ex) { +// Exceptions.printStackTrace(ex); +// } catch (ExecutionException ex) { +// Exceptions.printStackTrace(ex); +// } +// return null; + } + + private T getSuperValue() { + try { + return super.getValue(); + } catch (IllegalAccessException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } catch (InvocationTargetException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + @Override + public void setValue(final T val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + try { + notifyListeners(getSuperValue(), val); + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + setSuperValue(val); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void setSuperValue(T val, boolean undo) { + try { + if (undo) { + try { + Object oldValue = getSuperValue(); + if (oldValue.getClass().getMethod("clone", null) != null) { + addUndo(oldValue.getClass().getMethod("clone", null).invoke(oldValue, null), val); + Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.INFO, "Add cloned undo {0}", oldValue.getClass().getMethod("clone", null).invoke(oldValue, null)); + } + } catch (Exception e) { + addUndo(getSuperValue(), val); + Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.INFO, "Add undo {0}", getSuperValue()); + } + } + super.setValue(val); + } catch (IllegalAccessException ex) { + Exceptions.printStackTrace(ex); + } catch (IllegalArgumentException ex) { + Exceptions.printStackTrace(ex); + } catch (InvocationTargetException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void setSuperValue(T val) { + setSuperValue(val, true); + } + + protected void addUndo(final Object before, final Object after) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() { + Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.INFO, "Do undo {0}", before); + setSuperValue((T) before, false); + } + + @Override + public void sceneRedo() { + setSuperValue((T) after, false); + } + + @Override + public void awtUndo() { + } + + @Override + public void awtRedo() { + } + }); + } + + public void addPropertyChangeListener(ScenePropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(ScenePropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(Object before, Object after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + ScenePropertyChangeListener propertyChangeListener = it.next(); + propertyChangeListener.propertyChange(getName(), before, after); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ScenePropertyChangeListener.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ScenePropertyChangeListener.java new file mode 100644 index 000000000..23b0c6d05 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/ScenePropertyChangeListener.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +/** + * + * @author normenhansen + */ +public interface ScenePropertyChangeListener { + public void propertyChange(String property, Object oldValue, Object newValue); +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/TextureBrowser.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/TextureBrowser.form new file mode 100644 index 000000000..4e28fcd14 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/TextureBrowser.form @@ -0,0 +1,128 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/TextureBrowser.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/TextureBrowser.java new file mode 100644 index 000000000..b7685cf5c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/TextureBrowser.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.texture.Texture; +import java.util.logging.Logger; +import javax.swing.DefaultListSelectionModel; +import javax.swing.Icon; +import jme3tools.converters.ImageToAwt; +import org.openide.util.ImageUtilities; + +/** + * Displays all textures in the ProjectAssetManager, + * lets you select one, and shows a preview of it. + * + * The user can de-select the currently selected texture to specify they + * do not want a texture, and in that case null is returned. + * + * @author bowens + */ +public class TextureBrowser extends javax.swing.JDialog { + + private ProjectAssetManager assetManager; + private TexturePropertyEditor editor; + + + public TextureBrowser(java.awt.Frame parent, boolean modal, ProjectAssetManager assetManager, TexturePropertyEditor editor) { + super(parent, modal); + this.assetManager = assetManager; + this.editor = editor; + initComponents(); + loadAvailableTextures(); + setSelectedTexture((Texture)editor.getValue()); + setLocationRelativeTo(null); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + cancelButton = new javax.swing.JButton(); + okButton = new javax.swing.JButton(); + jPanel1 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + textureList = new javax.swing.JList(); + jScrollPane2 = new javax.swing.JScrollPane(); + imagePreviewLabel = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle(org.openide.util.NbBundle.getMessage(TextureBrowser.class, "TextureBrowser.title")); // NOI18N + + cancelButton.setText(org.openide.util.NbBundle.getMessage(TextureBrowser.class, "TextureBrowser.cancelButton.text")); // NOI18N + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonActionPerformed(evt); + } + }); + + okButton.setText(org.openide.util.NbBundle.getMessage(TextureBrowser.class, "TextureBrowser.okButton.text")); // NOI18N + okButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + okButtonActionPerformed(evt); + } + }); + + textureList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + textureList.setSelectionModel(new ToggleSelectionModel()); + textureList.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + textureListValueChanged(evt); + } + }); + jScrollPane1.setViewportView(textureList); + + imagePreviewLabel.setText(org.openide.util.NbBundle.getMessage(TextureBrowser.class, "TextureBrowser.imagePreviewLabel.text")); // NOI18N + jScrollPane2.setViewportView(imagePreviewLabel); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 264, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 299, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 299, Short.MAX_VALUE) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(357, Short.MAX_VALUE) + .addComponent(cancelButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(okButton) + .addGap(17, 17, 17)) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(okButton) + .addComponent(cancelButton))) + ); + + pack(); + }// //GEN-END:initComponents + + private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed + setTexture(); + dispose(); + }//GEN-LAST:event_okButtonActionPerformed + + private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed + dispose(); + }//GEN-LAST:event_cancelButtonActionPerformed + + private void textureListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_textureListValueChanged + selectionChanged(); + }//GEN-LAST:event_textureListValueChanged + + private void setTexture() { + if (textureList.getSelectedIndex() > -1) { + textureList.getSelectedValue(); + String selected = (String) textureList.getSelectedValue(); + Texture tex = assetManager.loadTexture(selected); + editor.setValue(tex); + editor.setAsText(selected); + } else { + editor.setValue(null); + editor.setAsText(null); + } + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton cancelButton; + private javax.swing.JLabel imagePreviewLabel; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JButton okButton; + private javax.swing.JList textureList; + // End of variables declaration//GEN-END:variables + + private void loadAvailableTextures() { + if (assetManager == null) + return; + + textureList.setListData(assetManager.getTextures()); + + } + + private void selectionChanged() { + if (textureList.getSelectedIndex() > -1) { + String selected = (String) textureList.getSelectedValue(); + Texture tex = assetManager.loadTexture(selected); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + imagePreviewLabel.setIcon(newicon); + } else { + imagePreviewLabel.setIcon(null); + } + } + + private void setSelectedTexture(Texture texture) { + if (texture != null) { + Logger.getLogger(TextureBrowser.class.getName()).finer("Looking for Texture: "+texture.getName()); + for (int i=0; i listeners = new LinkedList(); + private Texture texture; + private AssetManager manager; + private String assetKey; + + public TexturePropertyEditor() { + } + + public TexturePropertyEditor(Texture texture) { + this.texture = texture; + } + + public TexturePropertyEditor(AssetManager manager) { + this.manager = manager; + } + + public TexturePropertyEditor(Texture texture, AssetManager manager) { + this.texture = texture; + this.manager = manager; + } + + public void setValue(Object value) { + if (value instanceof Texture) { + texture = (Texture) value; + } else { + texture = null; + } + } + + public Object getValue() { + return texture; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { +// if (texture != null) { +// return texture.getName(); +// } + return assetKey; + } + + public void setAsText(String text) throws IllegalArgumentException { + this.assetKey = text; + //TODO: load texture if not done.. maybe load here instead of panel.. + } + + public String[] getTags() { + return null; + } + + public Component getCustomEditor() { + ProjectAssetManager currentProjectAssetManager = null; + if (manager instanceof ProjectAssetManager) { + currentProjectAssetManager = (ProjectAssetManager) manager; + } + //try { + if (currentProjectAssetManager == null) { + currentProjectAssetManager = (ProjectAssetManager) SceneApplication.getApplication().getAssetManager(); + } + TextureBrowser textureBrowser = new TextureBrowser(null, true, currentProjectAssetManager, this); + return textureBrowser; + //} catch (Exception e) { + //Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, e.getMessage()+" Could not get project asset manager!", e); + //return null; + //} + } + + public boolean supportsCustomEditor() { + return true; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/UserDataProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/UserDataProperty.java new file mode 100644 index 000000000..636dc1ce4 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/UserDataProperty.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.scene.Spatial; +import java.beans.PropertyEditor; +import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.openide.nodes.PropertySupport; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class UserDataProperty extends PropertySupport.ReadWrite { + + private Spatial spatial; + private String name = "null"; + private int type = 0; + private List listeners = new LinkedList(); + + public UserDataProperty(Spatial node, String name) { + super(name, String.class, name, ""); + this.spatial = node; + this.name = name; + this.type = getObjectType(node.getUserData(name)); + } + + public static int getObjectType(Object type) { + if (type instanceof Integer) { + return 0; + } else if (type instanceof Float) { + return 1; + } else if (type instanceof Boolean) { + return 2; + } else if (type instanceof String) { + return 3; + } else if (type instanceof Long) { + return 4; + } else { + throw new IllegalArgumentException("Unsupported type: " + type); + } + } + + @Override + public String getValue() throws IllegalAccessException, InvocationTargetException { + return spatial.getUserData(name) + ""; + } + + @Override + public void setValue(final String val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + if (spatial == null) { + return; + } + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + switch (type) { + case 0: + spatial.setUserData(name, Integer.parseInt(val)); + break; + case 1: + spatial.setUserData(name, Float.parseFloat(val)); + break; + case 2: + spatial.setUserData(name, Boolean.parseBoolean(val)); + break; + case 3: + spatial.setUserData(name, val); + break; + case 4: + spatial.setUserData(name, Long.parseLong(val)); + break; + default: + throw new UnsupportedOperationException(); + } + return null; + } + }).get(); + notifyListeners(null, val); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + public PropertyEditor getPropertyEditor() { + return null; +// return new AnimationPropertyEditor(control); + } + + public void addPropertyChangeListener(ScenePropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(ScenePropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(Object before, Object after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + ScenePropertyChangeListener propertyChangeListener = it.next(); + propertyChangeListener.propertyChange(getName(), before, after); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Vector3fPropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Vector3fPropertyEditor.java new file mode 100644 index 000000000..9fa83912f --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/Vector3fPropertyEditor.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2009-2010 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.properties; + +import com.jme3.math.Vector3f; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyEditor; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author normenhansen + */ +public class Vector3fPropertyEditor implements PropertyEditor { + + private LinkedList listeners = new LinkedList(); + private Vector3f vector = new Vector3f(); + + public void setValue(Object value) { + if (value instanceof Vector3f) { + vector.set((Vector3f) value); + } + } + + public Object getValue() { + return vector; + } + + public boolean isPaintable() { + return false; + } + + public void paintValue(Graphics gfx, Rectangle box) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getJavaInitializationString() { + return null; + } + + public String getAsText() { + return "[" + vector.x + ", " + vector.y + ", " + vector.z + "]"; + } + + public void setAsText(String text) throws IllegalArgumentException { + text = text.replace('[', ' '); + text = text.replace(']', ' '); + String[] values = text.split(","); + if (values.length != 3) { + throw (new IllegalArgumentException("String not correct")); + } + float[] floats = new float[3]; + for (int i = 0; i < values.length; i++) { + String string = values[i]; + floats[i] = Float.parseFloat(string); + } + Vector3f old = new Vector3f(); + old.set(vector); + vector.set(floats[0], floats[1], floats[2]); + notifyListeners(old, vector); + } + + public String[] getTags() { + return null; + } + + public Component getCustomEditor() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean supportsCustomEditor() { + return false; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(Vector3f before, Vector3f after) { + for (Iterator it = listeners.iterator(); it.hasNext();) { + PropertyChangeListener propertyChangeListener = it.next(); + //TODO: check what the "programmatic name" is supposed to be here.. for now its Vector3f + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, null, before, after)); + } + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/Bundle.properties new file mode 100644 index 000000000..750f304a5 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/Bundle.properties @@ -0,0 +1,9 @@ +CTL_SceneViewerAction=SceneViewer +CTL_SceneViewerTopComponent=SceneViewer Window +HINT_SceneViewerTopComponent=This is a SceneViewer window +SceneViewerTopComponent.enableCamLight.text= +SceneViewerTopComponent.enableCamLight.toolTipText=Toggle cam light +SceneViewerTopComponent.enableWireframe.toolTipText=Toggle wireframe mode +SceneViewerTopComponent.enableWireframe.text= +SceneViewerTopComponent.enableStats.toolTipText=Display Stats +SceneViewerTopComponent.enableStats.text= diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.form new file mode 100644 index 000000000..9b64e40b0 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.form @@ -0,0 +1,121 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.java new file mode 100644 index 000000000..edc6c5bf6 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2009-2010 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.sceneviewer; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.system.JmeCanvasContext; +import java.util.logging.Logger; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Message; +import org.openide.awt.UndoRedo; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.lookup.InstanceContent; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.core.sceneviewer//SceneViewer//EN", +autostore = false) +public final class SceneViewerTopComponent extends TopComponent { + + private static SceneViewerTopComponent instance; + /** path to the icon used by the component and its open action */ + static final String ICON_PATH = "com/jme3/gde/core/sceneviewer/jme-logo.png"; + private static final String PREFERRED_ID = "SceneViewerTopComponent"; + private JmeCanvasContext ctx; + private SceneApplication app; + private Lookup lookup; + private final InstanceContent lookupContents = new InstanceContent(); + private HelpCtx helpContext = new HelpCtx("com.jme3.gde.core.sceneviewer"); + + public SceneViewerTopComponent() { + initComponents(); + oGLPanel.setMinimumSize(new java.awt.Dimension(10, 10)); + setName(NbBundle.getMessage(SceneViewerTopComponent.class, "CTL_SceneViewerTopComponent")); + setToolTipText(NbBundle.getMessage(SceneViewerTopComponent.class, "HINT_SceneViewerTopComponent")); + setIcon(ImageUtilities.loadImage(ICON_PATH, true)); +// lookup = new AbstractLookup(lookupContents); +// associateLookup(lookup); + putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE); + app = SceneApplication.getApplication(); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + enableCamLight = new javax.swing.JToggleButton(); + enableWireframe = new javax.swing.JToggleButton(); + jPanel1 = new javax.swing.JPanel(); + enableStats = new javax.swing.JToggleButton(); + oGLPanel = new javax.swing.JPanel(); + + setLayout(new java.awt.BorderLayout()); + + jToolBar1.setRollover(true); + + enableCamLight.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/core/sceneviewer/icons/lightbulb_off.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(enableCamLight, org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableCamLight.text")); // NOI18N + enableCamLight.setToolTipText(org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableCamLight.toolTipText")); // NOI18N + enableCamLight.setFocusable(false); + enableCamLight.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + enableCamLight.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/core/sceneviewer/icons/lightbulb.gif"))); // NOI18N + enableCamLight.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + enableCamLight.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + enableCamLightActionPerformed(evt); + } + }); + jToolBar1.add(enableCamLight); + + enableWireframe.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/core/sceneviewer/icons/box_color.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(enableWireframe, org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableWireframe.text")); // NOI18N + enableWireframe.setToolTipText(org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableWireframe.toolTipText")); // NOI18N + enableWireframe.setFocusable(false); + enableWireframe.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + enableWireframe.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/core/sceneviewer/icons/box_wire.gif"))); // NOI18N + enableWireframe.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + enableWireframe.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + enableWireframeActionPerformed(evt); + } + }); + jToolBar1.add(enableWireframe); + jToolBar1.add(jPanel1); + + enableStats.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/core/sceneviewer/icons/65.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(enableStats, org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableStats.text")); // NOI18N + enableStats.setToolTipText(org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableStats.toolTipText")); // NOI18N + enableStats.setFocusable(false); + enableStats.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + enableStats.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + enableStats.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + enableStatsActionPerformed(evt); + } + }); + jToolBar1.add(enableStats); + + add(jToolBar1, java.awt.BorderLayout.NORTH); + + oGLPanel.setPreferredSize(new java.awt.Dimension(100, 100)); + oGLPanel.setSize(new java.awt.Dimension(100, 100)); + oGLPanel.setLayout(new java.awt.GridLayout(1, 0)); + add(oGLPanel, java.awt.BorderLayout.CENTER); + }// //GEN-END:initComponents + + private void enableCamLightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableCamLightActionPerformed + app.enableCamLight(enableCamLight.isSelected()); + }//GEN-LAST:event_enableCamLightActionPerformed + + private void enableWireframeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableWireframeActionPerformed + app.enableWireFrame(enableWireframe.isSelected()); + }//GEN-LAST:event_enableWireframeActionPerformed + + private void enableStatsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableStatsActionPerformed + app.enableStats(enableStats.isSelected()); + }//GEN-LAST:event_enableStatsActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JToggleButton enableCamLight; + private javax.swing.JToggleButton enableStats; + private javax.swing.JToggleButton enableWireframe; + private javax.swing.JPanel jPanel1; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JPanel oGLPanel; + // End of variables declaration//GEN-END:variables + + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized SceneViewerTopComponent getDefault() { + if (instance == null) { + instance = new SceneViewerTopComponent(); + } + return instance; + } + + /** + * Obtain the SceneViewerTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized SceneViewerTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(SceneViewerTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof SceneViewerTopComponent) { + return (SceneViewerTopComponent) win; + } + Logger.getLogger(SceneViewerTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + public static void showOpenGLError(String e) { + Message msg = new NotifyDescriptor.Message( + "Error opening OpenGL window!\n" + + "Your graphics card needs to support at least OpenGL 2.0,\n" + + "if that is the case, please download the latest drivers.\n" + + "Error: " + e, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public HelpCtx getHelpCtx() { + //this call is for single components: + //HelpCtx.setHelpIDString(this, "com.jme3.gde.core.sceneviewer"); + return helpContext; + } + + public void setHelpContext(HelpCtx ctx) { + this.helpContext = ctx; + } + + @Override + public void componentOpened() { + super.componentOpened(); + try { + oGLPanel.add(((JmeCanvasContext) app.getContext()).getCanvas()); + app.setSceneActive(true); + } catch (Exception e) { + showOpenGLError(e.toString()); + } catch (Error err) { + showOpenGLError(err.toString()); + } + } + + @Override + protected void componentShowing() { + super.componentShowing(); + } + + @Override + protected void componentHidden() { + super.componentHidden(); + } + + @Override + public void componentClosed() { + super.componentClosed(); + app.setSceneActive(false); + oGLPanel.removeAll(); + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + @Override + public UndoRedo getUndoRedo() { + return Lookup.getDefault().lookup(UndoRedo.class); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/65.png b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/65.png new file mode 100644 index 000000000..1f22e1900 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/65.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/box_color.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/box_color.gif new file mode 100644 index 000000000..eeab8ff3a Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/box_color.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/box_wire.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/box_wire.gif new file mode 100644 index 000000000..af6eeddcc Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/box_wire.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/lightbulb.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/lightbulb.gif new file mode 100644 index 000000000..18cc19cee Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/lightbulb.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/lightbulb_off.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/lightbulb_off.gif new file mode 100644 index 000000000..13a17de79 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/lightbulb_off.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/wire.gif b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/wire.gif new file mode 100755 index 000000000..32e495160 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/icons/wire.gif differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/jme-logo.png b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/jme-logo.png new file mode 100644 index 000000000..d4c742a8c Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/jme-logo.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/jme-logo24.png b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/jme-logo24.png new file mode 100644 index 000000000..ee9f918a6 Binary files /dev/null and b/sdk/jme3-core/src/com/jme3/gde/core/sceneviewer/jme-logo24.png differ diff --git a/sdk/jme3-core/src/com/jme3/gde/core/undoredo/AbstractUndoableSceneEdit.java b/sdk/jme3-core/src/com/jme3/gde/core/undoredo/AbstractUndoableSceneEdit.java new file mode 100644 index 000000000..2e1a297e9 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/undoredo/AbstractUndoableSceneEdit.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2009-2010 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.undoredo; + +import com.jme3.gde.core.scene.SceneApplication; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import javax.swing.undo.AbstractUndoableEdit; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import org.openide.util.Exceptions; + +/** + * Unodablededit for scene operations, executes sceneUndo and sceneRedo on scene thread + * @author normenhansen + */ +public abstract class AbstractUndoableSceneEdit extends AbstractUndoableEdit { + + public abstract void sceneUndo(); + + public abstract void sceneRedo(); + + public void awtUndo(){ + + } + + public void awtRedo(){ + + } + + @Override + public void undo() throws CannotUndoException { + super.undo(); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + sceneUndo(); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + awtUndo(); + } + + @Override + public void redo() throws CannotRedoException { + super.redo(); + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Void call() throws Exception { + sceneRedo(); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + awtRedo(); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/undoredo/SceneUndoRedoManager.java b/sdk/jme3-core/src/com/jme3/gde/core/undoredo/SceneUndoRedoManager.java new file mode 100644 index 000000000..d1120e8c2 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/undoredo/SceneUndoRedoManager.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009-2010 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.undoredo; + +import javax.swing.event.UndoableEditEvent; +import javax.swing.undo.UndoableEdit; +import org.openide.awt.UndoRedo; + +/** + * + * @author normenhansen + */ +public class SceneUndoRedoManager extends UndoRedo.Manager { + + public void addEdit(final Object source, final UndoableEdit edit) { + if (!java.awt.EventQueue.isDispatchThread()) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + undoableEditHappened(new UndoableEditEvent(source, edit)); + } + }); + } else { + undoableEditHappened(new UndoableEditEvent(source, edit)); + } + } + + @Override + public void discardAllEdits() { + if (!java.awt.EventQueue.isDispatchThread()) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + superDiscardAllEdits(); + } + }); + } else { + super.discardAllEdits(); + } + } + + private void superDiscardAllEdits() { + super.discardAllEdits(); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/util/DataObjectSaveNode.java b/sdk/jme3-core/src/com/jme3/gde/core/util/DataObjectSaveNode.java new file mode 100644 index 000000000..af70eed9f --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/util/DataObjectSaveNode.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2009-2010 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.util; + +import org.openide.cookies.SaveCookie; +import org.openide.loaders.DataNode; +import org.openide.loaders.DataObject; +import org.openide.nodes.Children; + +/** + * Initialization:
+ * DataObjectSaveNode saveNode=new DataObjectSaveNode(dateObject);
+ * setActivatedNodes(new org.openide.nodes.Node[]{saveNode});
+ * To set save state:
+ * saveNode.setSaveCookie(saveCookie);
+ * saveNode.removeSaveCookie();
+ * @author normenhansen + */ +public class DataObjectSaveNode extends DataNode { + + protected SaveCookie cook; + + public DataObjectSaveNode(DataObject object) { + super(object, Children.LEAF); + } + + public void setSaveCookie(SaveCookie cookie) { + removeSaveCookie(); + cook = cookie; + getCookieSet().assign(SaveCookie.class, cookie); + getDataObject().setModified(true); + } + + public void removeSaveCookie() { + if (cook != null) { + getCookieSet().assign(SaveCookie.class); + } + getDataObject().setModified(false); + } + + @Override + public String toString() { + if (cook != null) + return "DataObjectSaveNode("+cook.toString()+" - "+getDisplayName()+")"; + else + return "DataObjectSaveNode("+getDisplayName()+")"; + } +} diff --git a/sdk/jme3-desktop-executables/build.xml b/sdk/jme3-desktop-executables/build.xml new file mode 100644 index 000000000..e4eed36b8 --- /dev/null +++ b/sdk/jme3-desktop-executables/build.xml @@ -0,0 +1,14 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.desktop.executables. + + + + + + + + diff --git a/sdk/jme3-desktop-executables/macapp-data/Info.plist b/sdk/jme3-desktop-executables/macapp-data/Info.plist new file mode 100644 index 000000000..e37072f0c --- /dev/null +++ b/sdk/jme3-desktop-executables/macapp-data/Info.plist @@ -0,0 +1,44 @@ + + + + + CFBundleName + ${application.title} + CFBundleIdentifier + ${main.class} + CFBundleVersion + 100.0 + CFBundleAllowMixedLocalizations + true + CFBundleExecutable + JavaApplicationStub + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleInfoDictionaryVersion + 6.0 + CFBundleIconFile + GenericApp.icns + Java + + VMOptions + ${run.jvmargs} + WorkingDirectory + $APP_PACKAGE/Contents/Resources/Java + MainClass + ${main.class} + JVMVersion + 1.5+ + ClassPath + $JAVAROOT/${application.title}.jar + Properties + + apple.laf.useScreenMenuBar + true + + + + diff --git a/sdk/jme3-desktop-executables/macapp-data/osx-icon.icns b/sdk/jme3-desktop-executables/macapp-data/osx-icon.icns new file mode 100644 index 000000000..232a02efb Binary files /dev/null and b/sdk/jme3-desktop-executables/macapp-data/osx-icon.icns differ diff --git a/sdk/jme3-desktop-executables/macapp-data/osx-stub b/sdk/jme3-desktop-executables/macapp-data/osx-stub new file mode 100755 index 000000000..ee2a6184a Binary files /dev/null and b/sdk/jme3-desktop-executables/macapp-data/osx-stub differ diff --git a/sdk/jme3-desktop-executables/manifest.mf b/sdk/jme3-desktop-executables/manifest.mf new file mode 100644 index 000000000..29f5d2c32 --- /dev/null +++ b/sdk/jme3-desktop-executables/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.desktop.executables +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/desktop/executables/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/desktop/executables/Bundle.properties + diff --git a/sdk/jme3-desktop-executables/nbproject/build-impl.xml b/sdk/jme3-desktop-executables/nbproject/build-impl.xml new file mode 100644 index 000000000..220f383ba --- /dev/null +++ b/sdk/jme3-desktop-executables/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-desktop-executables/nbproject/genfiles.properties b/sdk/jme3-desktop-executables/nbproject/genfiles.properties new file mode 100644 index 000000000..61574d3b5 --- /dev/null +++ b/sdk/jme3-desktop-executables/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=e87e1436 +build.xml.script.CRC32=af50e957 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=e87e1436 +nbproject/build-impl.xml.script.CRC32=9d24a12f +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-desktop-executables/nbproject/project.properties b/sdk/jme3-desktop-executables/nbproject/project.properties new file mode 100644 index 000000000..110121761 --- /dev/null +++ b/sdk/jme3-desktop-executables/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=1.0.0 diff --git a/sdk/jme3-desktop-executables/nbproject/project.xml b/sdk/jme3-desktop-executables/nbproject/project.xml new file mode 100644 index 000000000..a28e9ced4 --- /dev/null +++ b/sdk/jme3-desktop-executables/nbproject/project.xml @@ -0,0 +1,64 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.desktop.executables + + + + com.jme3.gde.core + + + + 1 + 0.9 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.30 + + + + org.netbeans.modules.projectuiapi + + + + 1 + 1.46 + + + + org.openide.filesystems + + + + 7.37 + + + + org.openide.util + + + + 8.5 + + + + org.openide.util.lookup + + + + 8.2 + + + + + + + diff --git a/sdk/jme3-desktop-executables/nbproject/suite.properties b/sdk/jme3-desktop-executables/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-desktop-executables/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-desktop-executables/release/libs/bin/COPYING b/sdk/jme3-desktop-executables/release/libs/bin/COPYING new file mode 100644 index 000000000..60549be51 --- /dev/null +++ b/sdk/jme3-desktop-executables/release/libs/bin/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-linux/ld b/sdk/jme3-desktop-executables/release/libs/bin/bin-linux/ld new file mode 100755 index 000000000..1d3f4091d Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-linux/ld differ diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-linux/windres b/sdk/jme3-desktop-executables/release/libs/bin/bin-linux/windres new file mode 100755 index 000000000..a67a74be4 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-linux/windres differ diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/ld b/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/ld new file mode 100755 index 000000000..cce8b13ce Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/ld differ diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/readme.txt b/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/readme.txt new file mode 100644 index 000000000..76b7753e3 --- /dev/null +++ b/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/readme.txt @@ -0,0 +1 @@ +The MinGW binutils were built on Mac OS X 10.4 by Peter Centgraf diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/windres b/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/windres new file mode 100755 index 000000000..6880d0e51 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-macosx/windres differ diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-solaris-sparc/ld b/sdk/jme3-desktop-executables/release/libs/bin/bin-solaris-sparc/ld new file mode 100755 index 000000000..428994c92 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-solaris-sparc/ld differ diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-solaris-sparc/windres b/sdk/jme3-desktop-executables/release/libs/bin/bin-solaris-sparc/windres new file mode 100755 index 000000000..c7120ba21 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-solaris-sparc/windres differ diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-windows/ld.exe b/sdk/jme3-desktop-executables/release/libs/bin/bin-windows/ld.exe new file mode 100644 index 000000000..f388b9513 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-windows/ld.exe differ diff --git a/sdk/jme3-desktop-executables/release/libs/bin/bin-windows/windres.exe b/sdk/jme3-desktop-executables/release/libs/bin/bin-windows/windres.exe new file mode 100644 index 000000000..4ad2ae98a Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/bin/bin-windows/windres.exe differ diff --git a/sdk/jme3-desktop-executables/release/libs/head/LICENSE.txt b/sdk/jme3-desktop-executables/release/libs/head/LICENSE.txt new file mode 100644 index 000000000..536488e61 --- /dev/null +++ b/sdk/jme3-desktop-executables/release/libs/head/LICENSE.txt @@ -0,0 +1,23 @@ +Copyright (c) 2004, 2007 Grzegorz Kowal + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +Except as contained in this notice, the name(s) of the above copyright holders +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/sdk/jme3-desktop-executables/release/libs/head/consolehead.o b/sdk/jme3-desktop-executables/release/libs/head/consolehead.o new file mode 100644 index 000000000..739d9767f Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/head/consolehead.o differ diff --git a/sdk/jme3-desktop-executables/release/libs/head/guihead.o b/sdk/jme3-desktop-executables/release/libs/head/guihead.o new file mode 100644 index 000000000..e830aa9e2 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/head/guihead.o differ diff --git a/sdk/jme3-desktop-executables/release/libs/head/head.o b/sdk/jme3-desktop-executables/release/libs/head/head.o new file mode 100644 index 000000000..b87fbde60 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/head/head.o differ diff --git a/sdk/jme3-desktop-executables/release/libs/launch4j.jar b/sdk/jme3-desktop-executables/release/libs/launch4j.jar new file mode 100644 index 000000000..f25f799eb Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/launch4j.jar differ diff --git a/sdk/jme3-desktop-executables/release/libs/manifest/uac.exe.manifest b/sdk/jme3-desktop-executables/release/libs/manifest/uac.exe.manifest new file mode 100644 index 000000000..3041fbc5b --- /dev/null +++ b/sdk/jme3-desktop-executables/release/libs/manifest/uac.exe.manifest @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/sdk/jme3-desktop-executables/release/libs/manifest/xp-themes.exe.manifest b/sdk/jme3-desktop-executables/release/libs/manifest/xp-themes.exe.manifest new file mode 100644 index 000000000..e2c7511f9 --- /dev/null +++ b/sdk/jme3-desktop-executables/release/libs/manifest/xp-themes.exe.manifest @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/MinGW.LICENSE.txt b/sdk/jme3-desktop-executables/release/libs/w32api/MinGW.LICENSE.txt new file mode 100644 index 000000000..aea85bd8d --- /dev/null +++ b/sdk/jme3-desktop-executables/release/libs/w32api/MinGW.LICENSE.txt @@ -0,0 +1,25 @@ +MinGW - Licensing Terms + +Various pieces distributed with MinGW come with its own copyright and license: + +Basic MinGW runtime + MinGW base runtime package is uncopyrighted and placed in the public domain. + This basically means that you can do what you want with the code. + +w32api + You are free to use, modify and copy this package. + No restrictions are imposed on programs or object files compiled with this library. + You may not restrict the the usage of this library. + You may distribute this library as part of another package or as a modified package + if and only if you do not restrict the usage of the portions consisting + of this (optionally modified) library. + If distributed as a modified package then this file must be included. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +MinGW profiling code + MinGW profiling code is distributed under the GNU General Public License. + +The development tools such as GCC, GDB, GNU Make, etc all covered by GNU General Public License. diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/crt2.o b/sdk/jme3-desktop-executables/release/libs/w32api/crt2.o new file mode 100644 index 000000000..f81f836cf Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/crt2.o differ diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/libadvapi32.a b/sdk/jme3-desktop-executables/release/libs/w32api/libadvapi32.a new file mode 100644 index 000000000..c471853c7 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/libadvapi32.a differ diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/libgcc.a b/sdk/jme3-desktop-executables/release/libs/w32api/libgcc.a new file mode 100644 index 000000000..d3f89479e Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/libgcc.a differ diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/libkernel32.a b/sdk/jme3-desktop-executables/release/libs/w32api/libkernel32.a new file mode 100644 index 000000000..5d3eb074f Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/libkernel32.a differ diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/libmingw32.a b/sdk/jme3-desktop-executables/release/libs/w32api/libmingw32.a new file mode 100644 index 000000000..d1f7888d8 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/libmingw32.a differ diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/libmsvcrt.a b/sdk/jme3-desktop-executables/release/libs/w32api/libmsvcrt.a new file mode 100644 index 000000000..6714146b6 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/libmsvcrt.a differ diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/libshell32.a b/sdk/jme3-desktop-executables/release/libs/w32api/libshell32.a new file mode 100644 index 000000000..d35fbdaf3 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/libshell32.a differ diff --git a/sdk/jme3-desktop-executables/release/libs/w32api/libuser32.a b/sdk/jme3-desktop-executables/release/libs/w32api/libuser32.a new file mode 100644 index 000000000..387fb650d Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/w32api/libuser32.a differ diff --git a/sdk/jme3-desktop-executables/release/libs/xstream.jar b/sdk/jme3-desktop-executables/release/libs/xstream.jar new file mode 100644 index 000000000..392e1c937 Binary files /dev/null and b/sdk/jme3-desktop-executables/release/libs/xstream.jar differ diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/Bundle.properties b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/Bundle.properties new file mode 100644 index 000000000..d965727a2 --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/Bundle.properties @@ -0,0 +1,11 @@ +launch4j=launch4j +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin adds support for creating executables of your jMonkeyEngine3 projects that work on various desktop systems including MacOSX, Linux and Windows. +OpenIDE-Module-Name=Desktop Executables Support +OpenIDE-Module-Short-Description=Adds support for creating executables for various desktop systems. +LBL_Category_Desktop_EXE=Desktop +DesktopExeCustomizerPanel.jCheckBox1.text=Create Windows .exe file +DesktopExeCustomizerPanel.jCheckBox2.text=Create Mac app bundle +DesktopExeCustomizerPanel.jCheckBox3.text=Create Linux launcher +DesktopExeCustomizerPanel.jLabel1.text=Select platforms to create launchers for diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCompositeProvider.java b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCompositeProvider.java new file mode 100644 index 000000000..cbcd273e8 --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCompositeProvider.java @@ -0,0 +1,139 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.desktop.executables; + +import com.jme3.gde.core.j2seproject.ProjectExtensionManager; +import com.jme3.gde.core.j2seproject.ProjectExtensionProperties; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import javax.swing.JComponent; + +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + +import org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; + +/** + * + * @author normenhansen + */ +@ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-java-j2seproject", category = "Application", position = 400) +public class DesktopExeCompositeProvider implements ProjectCustomizer.CompositeCategoryProvider { + + private static final String CAT_LWJGL_APPLET = "DesktopExe"; // NOI18N + private static ProjectExtensionProperties jwsProps = null; + private String[] keyList = new String[]{ + "launch4j.exe.enabled", + "mac.app.enabled", + "linux.launcher.enabled" + }; + + public DesktopExeCompositeProvider() { + } + + @Override + public ProjectCustomizer.Category createCategory(Lookup context) { + return ProjectCustomizer.Category.create(CAT_LWJGL_APPLET, + NbBundle.getMessage(DesktopExeCompositeProvider.class, "LBL_Category_Desktop_EXE"), null); + } + + @Override + public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) { + jwsProps = new ProjectExtensionProperties(context.lookup(Project.class), keyList); + DesktopExeCustomizerPanel panel = new DesktopExeCustomizerPanel(jwsProps); + category.setStoreListener(new SavePropsListener(jwsProps, context.lookup(Project.class))); + category.setOkButtonListener(panel); + return panel; + } + + private class SavePropsListener implements ActionListener { + + private ProjectExtensionManager launch4j; + private ProjectExtensionManager macapp; + private ProjectExtensionManager linux; + private ProjectExtensionProperties properties; + private Project project; + + public SavePropsListener(ProjectExtensionProperties props, Project project) { + this.properties = props; + this.project = project; + launch4j = new ProjectExtensionManager("launch4j", "v1.1", new String[]{"jar", "-launch4j-exe"}); + launch4j.setAntTaskLibrary("launch4j"); + macapp = new ProjectExtensionManager("macapp", "v1.1", new String[]{"jar", "-mac-app"}); + linux = new ProjectExtensionManager("linuxlauncher", "v1.0", new String[]{"jar", "-linux-launcher"}); + } + + public void actionPerformed(ActionEvent e) { + if ("true".equals(properties.getProperty("launch4j.exe.enabled"))) { + launch4j.loadTargets("nbres:/com/jme3/gde/desktop/executables/launch4j-targets.xml"); + launch4j.checkExtension(project); + } else { + launch4j.removeExtension(project); + } + if ("true".equals(properties.getProperty("linux.launcher.enabled"))) { + linux.loadTargets("nbres:/com/jme3/gde/desktop/executables/linux-targets.xml"); + linux.checkExtension(project); + } else { + linux.removeExtension(project); + } + if ("true".equals(properties.getProperty("mac.app.enabled"))) { + macapp.loadTargets("nbres:/com/jme3/gde/desktop/executables/macapp-targets.xml"); + macapp.checkExtension(project); + if (project.getProjectDirectory().getFileObject("osx-stub") == null) { + try { + unZipFile(new URL("nbres:/com/jme3/gde/desktop/executables/macapp-data.zip").openStream(), project.getProjectDirectory()); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + } else { + macapp.removeExtension(project); + } + + try { + properties.store(); + } catch (IOException ioe) { + Exceptions.printStackTrace(ioe); + } + } + + private void unZipFile(InputStream source, FileObject projectRoot) throws IOException { + try { + ZipInputStream str = new ZipInputStream(source); + ZipEntry entry; + while ((entry = str.getNextEntry()) != null) { + if (entry.isDirectory()) { + FileUtil.createFolder(projectRoot, entry.getName()); + } else { + FileObject fo = FileUtil.createData(projectRoot, entry.getName()); + writeFile(str, fo); + } + } + } finally { + source.close(); + } + } + + private void writeFile(ZipInputStream str, FileObject fo) throws IOException { + OutputStream out = fo.getOutputStream(); + try { + FileUtil.copy(str, out); + } finally { + out.close(); + } + } + } +} diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCustomizerPanel.form b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCustomizerPanel.form new file mode 100644 index 000000000..0bcbde9c0 --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCustomizerPanel.form @@ -0,0 +1,75 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCustomizerPanel.java b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCustomizerPanel.java new file mode 100644 index 000000000..50fb73c19 --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/DesktopExeCustomizerPanel.java @@ -0,0 +1,130 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * LwjglAppletCustomizerPanel.java + * + * Created on 11.11.2010, 16:56:53 + */ +package com.jme3.gde.desktop.executables; + +import com.jme3.gde.core.j2seproject.ProjectExtensionProperties; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.openide.util.HelpCtx; + +/** + * + * @author normenhansen + */ +public class DesktopExeCustomizerPanel extends javax.swing.JPanel implements ActionListener { + + private ProjectExtensionProperties properties; + + /** Creates new form LwjglAppletCustomizerPanel */ + public DesktopExeCustomizerPanel(ProjectExtensionProperties properties) { + this.properties = properties; + initComponents(); + loadProperties(); + HelpCtx.setHelpIDString(this, "sdk.application_deployment"); + } + + private void loadProperties() { + String str = properties.getProperty("launch4j.exe.enabled"); + if ("true".equals(str)) { + jCheckBox1.setSelected(true); + } else { + jCheckBox1.setSelected(false); + } + String str2 = properties.getProperty("mac.app.enabled"); + if ("true".equals(str2)) { + jCheckBox2.setSelected(true); + } else { + jCheckBox2.setSelected(false); + } + String str3 = properties.getProperty("linux.launcher.enabled"); + if ("true".equals(str3)) { + jCheckBox3.setSelected(true); + } else { + jCheckBox3.setSelected(false); + } + } + + private void saveProperties() { + if (jCheckBox1.isSelected()) { + properties.setProperty("launch4j.exe.enabled", "true"); + } else { + properties.setProperty("launch4j.exe.enabled", ""); + } + if (jCheckBox2.isSelected()) { + properties.setProperty("mac.app.enabled", "true"); + } else { + properties.setProperty("mac.app.enabled", ""); + } + if (jCheckBox3.isSelected()) { + properties.setProperty("linux.launcher.enabled", "true"); + } else { + properties.setProperty("linux.launcher.enabled", ""); + } + } + + public void actionPerformed(ActionEvent e) { + saveProperties(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jCheckBox1 = new javax.swing.JCheckBox(); + jCheckBox2 = new javax.swing.JCheckBox(); + jCheckBox3 = new javax.swing.JCheckBox(); + jLabel1 = new javax.swing.JLabel(); + + jCheckBox1.setText(org.openide.util.NbBundle.getMessage(DesktopExeCustomizerPanel.class, "DesktopExeCustomizerPanel.jCheckBox1.text")); // NOI18N + + jCheckBox2.setText(org.openide.util.NbBundle.getMessage(DesktopExeCustomizerPanel.class, "DesktopExeCustomizerPanel.jCheckBox2.text")); // NOI18N + + jCheckBox3.setText(org.openide.util.NbBundle.getMessage(DesktopExeCustomizerPanel.class, "DesktopExeCustomizerPanel.jCheckBox3.text")); // NOI18N + + jLabel1.setText(org.openide.util.NbBundle.getMessage(DesktopExeCustomizerPanel.class, "DesktopExeCustomizerPanel.jLabel1.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 398, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jCheckBox1, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE) + .addComponent(jCheckBox2, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE) + .addComponent(jCheckBox3, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBox1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jCheckBox2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jCheckBox3) + .addContainerGap(191, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JCheckBox jCheckBox2; + private javax.swing.JCheckBox jCheckBox3; + private javax.swing.JLabel jLabel1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/launch4j-targets.xml b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/launch4j-targets.xml new file mode 100644 index 000000000..c258908fb --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/launch4j-targets.xml @@ -0,0 +1,20 @@ + + Windows EXE Creation + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/launch4j.xml b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/launch4j.xml new file mode 100644 index 000000000..f9acea06c --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/launch4j.xml @@ -0,0 +1,22 @@ + + + + + launch4j + j2se + com.jme3.gde.desktop.executables.Bundle + + classpath + jar:nbinst://com.jme3.gde.desktop.executables/libs/launch4j.jar!/ + jar:nbinst://com.jme3.gde.desktop.executables/libs/xstream.jar!/ + + + src + + + javadoc + + diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/layer.xml b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/layer.xml new file mode 100644 index 000000000..b9c941cf9 --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/layer.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/linux-targets.xml b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/linux-targets.xml new file mode 100644 index 000000000..2929014cc --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/linux-targets.xml @@ -0,0 +1,18 @@ + + + Linux Launcher Creation + #!/bin/sh +java -jar ${application.title}.jar + + + + + + + + + + + + + diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/macapp-data.zip b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/macapp-data.zip new file mode 100644 index 000000000..a5e8e1f21 Binary files /dev/null and b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/macapp-data.zip differ diff --git a/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/macapp-targets.xml b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/macapp-targets.xml new file mode 100644 index 000000000..8d9e7c763 --- /dev/null +++ b/sdk/jme3-desktop-executables/src/com/jme3/gde/desktop/executables/macapp-targets.xml @@ -0,0 +1,23 @@ + + MacOSX Application Creation + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-gui/build.xml b/sdk/jme3-gui/build.xml new file mode 100644 index 000000000..f7d03ec94 --- /dev/null +++ b/sdk/jme3-gui/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.gui. + + diff --git a/sdk/jme3-gui/catalog.xml b/sdk/jme3-gui/catalog.xml new file mode 100644 index 000000000..1a17205ac --- /dev/null +++ b/sdk/jme3-gui/catalog.xml @@ -0,0 +1,4 @@ + + + + diff --git a/sdk/jme3-gui/manifest.mf b/sdk/jme3-gui/manifest.mf new file mode 100644 index 000000000..27ba6cf5c --- /dev/null +++ b/sdk/jme3-gui/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.gui/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/gui/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/gui/Bundle.properties + diff --git a/sdk/jme3-gui/nbproject/build-impl.xml b/sdk/jme3-gui/nbproject/build-impl.xml new file mode 100644 index 000000000..307e07b68 --- /dev/null +++ b/sdk/jme3-gui/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-gui/nbproject/genfiles.properties b/sdk/jme3-gui/nbproject/genfiles.properties new file mode 100644 index 000000000..14b13ec2a --- /dev/null +++ b/sdk/jme3-gui/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=66303b96 +build.xml.script.CRC32=a0136781 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=66303b96 +nbproject/build-impl.xml.script.CRC32=55a34aaf +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-gui/nbproject/project.properties b/sdk/jme3-gui/nbproject/project.properties new file mode 100644 index 000000000..802caef86 --- /dev/null +++ b/sdk/jme3-gui/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.5.0 diff --git a/sdk/jme3-gui/nbproject/project.xml b/sdk/jme3-gui/nbproject/project.xml new file mode 100644 index 000000000..566e497a5 --- /dev/null +++ b/sdk/jme3-gui/nbproject/project.xml @@ -0,0 +1,142 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.gui + + + + com.jme3.gde.core + + + + 1 + 0.9.1 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.5 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.8 + + + + org.netbeans.core.multiview + + + + 1 + 1.16.1 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.30 + + + + org.netbeans.modules.xml.multiview + + + + 1 + + + + + org.netbeans.spi.palette + + + + 1 + 1.20.1 + + + + org.openide.explorer + + + + 6.27 + + + + org.openide.filesystems + + + + 7.31 + + + + org.openide.loaders + + + + 7.9 + + + + org.openide.nodes + + + + 7.11 + + + + org.openide.text + + + + 6.27.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.2 + + + + org.openide.windows + + + + 6.30.1 + + + + + com.jme3.gde.gui + + + + diff --git a/sdk/jme3-gui/nbproject/suite.properties b/sdk/jme3-gui/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-gui/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/Bundle.properties b/sdk/jme3-gui/src/com/jme3/gde/gui/Bundle.properties new file mode 100644 index 000000000..8f3bb4286 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/Bundle.properties @@ -0,0 +1,8 @@ +LBL_NiftyGui_loader_name=NiftyGui Files +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin adds NiftyGUI XML file support to jMP. +OpenIDE-Module-Name=NiftyGUI Support +OpenIDE-Module-Short-Description=Provides NiftyGUI Support in jMP +Services/MIMEResolver/NiftyGuiResolver.xml=NiftyGui Files +Templates/Other/NiftyGuiTemplate.xml=Empty NiftyGui file diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/Computer_File_043.gif b/sdk/jme3-gui/src/com/jme3/gde/gui/Computer_File_043.gif new file mode 100644 index 000000000..421d54335 Binary files /dev/null and b/sdk/jme3-gui/src/com/jme3/gde/gui/Computer_File_043.gif differ diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGui.xml b/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGui.xml new file mode 100644 index 000000000..e0b1b7cae --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGui.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGuiDataObject.java b/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGuiDataObject.java new file mode 100644 index 000000000..e4633f75a --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGuiDataObject.java @@ -0,0 +1,84 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.gui; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.gui.multiview.PreviewView; +import java.io.IOException; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.modules.xml.multiview.DesignMultiViewDesc; +import org.netbeans.modules.xml.multiview.XmlMultiViewDataObject; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataNode; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.Node; +import org.openide.nodes.Children; +import org.openide.util.Lookup; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; +import org.openide.util.lookup.ProxyLookup; + +public class NiftyGuiDataObject extends XmlMultiViewDataObject { + private static final int TYPE_TOOLBAR = 0; + + protected final Lookup lookup; + protected final InstanceContent lookupContents = new InstanceContent(); + + public NiftyGuiDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + lookup = new ProxyLookup(getCookieSet().getLookup(), new AbstractLookup(getLookupContents())); + findAssetManager(); + } + + protected void findAssetManager() { + FileObject file = getPrimaryFile(); + ProjectManager pm = ProjectManager.getDefault(); + while (file != null) { + if (file.isFolder() && pm.isProject(file)) { + try { + Project project = ProjectManager.getDefault().findProject(file); + if (project != null) { + ProjectAssetManager mgr = project.getLookup().lookup(ProjectAssetManager.class); + if (mgr != null) { + getLookupContents().add(mgr); + return; + } + } + } catch (IOException ex) { + } catch (IllegalArgumentException ex) { + } + } + file = file.getParent(); + } + } + + @Override + public Lookup getLookup() { + return lookup; + } + + public InstanceContent getLookupContents() { + return lookupContents; + } + + @Override + protected Node createNodeDelegate() { + DataNode node = new DataNode(this, Children.LEAF, getLookup()); + node.setIconBaseWithExtension("com/jme3/gde/gui/Computer_File_043.gif"); + return node; + } + + @Override + protected DesignMultiViewDesc[] getMultiViewDesc() { + return new DesignMultiViewDesc[]{new PreviewView(this, TYPE_TOOLBAR)}; + } + + @Override + protected String getPrefixMark() { + return "Nifty"; + } +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGuiResolver.xml b/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGuiResolver.xml new file mode 100644 index 000000000..cab60462a --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/NiftyGuiResolver.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/layer.xml b/sdk/jme3-gui/src/com/jme3/gde/gui/layer.xml new file mode 100644 index 000000000..4b3fbf107 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/layer.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/Bundle.properties b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/Bundle.properties new file mode 100644 index 000000000..bc07788de --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/Bundle.properties @@ -0,0 +1,2 @@ + +PreviewPanel.jLabel1.text=jLabel1 diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyFileChildren.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyFileChildren.java new file mode 100644 index 000000000..ee70aa1d8 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyFileChildren.java @@ -0,0 +1,55 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.gui.multiview; + +import java.util.LinkedList; +import java.util.List; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.w3c.dom.Element; + +/** + * + * @author normenhansen + */ +public class NiftyFileChildren extends Children.Keys { + + Element xmlNode; + + public NiftyFileChildren(Element xmlNode) { + this.xmlNode = xmlNode; + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(createKeys()); + } + + protected List createKeys() { + LinkedList ret = new LinkedList(); + Element curElement = XmlHelper.findFirstChildElement(xmlNode); + while (curElement != null) { + if (checkElement(curElement)) { + ret.add(curElement); + } + curElement = XmlHelper.findNextSiblingElement(curElement); + } + + return ret; + } + + private boolean checkElement(Element curElement) { + if (!"screen".equals(curElement.getTagName())) { + return false; + } + return true; + } + + @Override + protected Node[] createNodes(Element key) { + return new Node[]{new NiftyScreenNode(key.getAttribute("id"))}; + } +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyFileNode.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyFileNode.java new file mode 100644 index 000000000..a3d15f188 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyFileNode.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.gui.multiview; + +import org.openide.nodes.AbstractNode; +import org.w3c.dom.Element; + +/** + * + * @author normenhansen + */ +public class NiftyFileNode extends AbstractNode{ + + public NiftyFileNode(Element xmlNode) { + super(new NiftyFileChildren(xmlNode)); + } + + +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyJmeDisplay.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyJmeDisplay.java new file mode 100644 index 000000000..e624bbe98 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyJmeDisplay.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2009-2010 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.gui.multiview; + +import com.jme3.asset.AssetManager; +import com.jme3.audio.AudioRenderer; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.niftygui.InputSystemJme; +import com.jme3.niftygui.RenderDeviceJme; +import com.jme3.niftygui.SoundDeviceJme; +import com.jme3.post.SceneProcessor; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.texture.FrameBuffer; +import de.lessvoid.nifty.Nifty; +import de.lessvoid.nifty.spi.input.InputSystem; + +public class NiftyJmeDisplay extends com.jme3.niftygui.NiftyJmeDisplay implements SceneProcessor { + + public NiftyJmeDisplay(AssetManager assetManager, + InputSystem inputManager, + AudioRenderer audioRenderer, + ViewPort vp){ + this.assetManager = assetManager; + //FIXME: needed, else npe + this.inputSys = new InputSystemJme(SceneApplication.getApplication().getInputManager()); + + w = vp.getCamera().getWidth(); + h = vp.getCamera().getHeight(); + + soundDev = new SoundDeviceJme(assetManager, audioRenderer); + renderDev = new RenderDeviceJme(this); + nifty = new Nifty(renderDev, soundDev, inputManager, this); + } + + @Override + public void initialize(RenderManager rm, ViewPort vp) { + this.renderManager = rm; + renderDev.setRenderManager(rm); + inited = true; + this.vp = vp; + this.renderer = rm.getRenderer(); + + } + + @Override + public Nifty getNifty() { + return nifty; + } + + RenderDeviceJme getRenderDevice() { + return renderDev; + } + + AssetManager getAssetManager() { + return assetManager; + } + + RenderManager getRenderManager() { + return renderManager; + } + + int getHeight() { + return h; + } + + int getWidth() { + return w; + } + + Renderer getRenderer(){ + return renderer; + } + + @Override + public void reshape(ViewPort vp, int w, int h) { + this.w = w; + this.h = h; + super.reshape(vp,w,h); + } + + @Override + public boolean isInitialized() { + return inited; + } + + @Override + public void preFrame(float tpf) { + } + + @Override + public void postQueue(RenderQueue rq) { + // render nifty before anything else + renderManager.setCamera(vp.getCamera(), true); + nifty.render(false); + renderManager.setCamera(vp.getCamera(), false); + } + + @Override + public void postFrame(FrameBuffer out) { + } + + @Override + public void cleanup() { + inited = false; +// nifty.exit(); + } + +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyPreviewInputHandler.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyPreviewInputHandler.java new file mode 100644 index 000000000..86bfc7355 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyPreviewInputHandler.java @@ -0,0 +1,48 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.gui.multiview; + +import de.lessvoid.nifty.NiftyInputConsumer; +import de.lessvoid.nifty.input.keyboard.KeyboardInputEvent; +import de.lessvoid.nifty.input.mouse.MouseInputEvent; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +/** + * + * @author normenhansen + */ +public class NiftyPreviewInputHandler implements de.lessvoid.nifty.spi.input.InputSystem { + + private List mouseEvents = new LinkedList(); + private List keyEvents = new LinkedList(); + + public synchronized void forwardEvents(NiftyInputConsumer nic) { + for (Iterator it = mouseEvents.iterator(); it.hasNext();) { + MouseInputEvent mouseInputEvent = it.next(); + nic.processMouseEvent(mouseInputEvent); + it.remove(); + } + for (Iterator it = keyEvents.iterator(); it.hasNext();) { + KeyboardInputEvent keyInputEvent = it.next(); + nic.processKeyboardEvent(keyInputEvent); + it.remove(); + } + } + + public synchronized void addMouseEvent(int newMouseX, int newMouseY, boolean mouseDown) { + MouseInputEvent event = new MouseInputEvent(newMouseX, newMouseY, mouseDown); + mouseEvents.add(event); + } + public synchronized void addKeyEvent(int newKey, char newCharacter, boolean newKeyDown, boolean newShiftDown, boolean newControlDown) { + KeyboardInputEvent event = new KeyboardInputEvent(newKey, newCharacter, newKeyDown, newShiftDown, newControlDown); + keyEvents.add(event); + } + + public void setMousePosition(int i, int i1) { +// throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyPreviewPanel.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyPreviewPanel.java new file mode 100644 index 000000000..694ac65ba --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyPreviewPanel.java @@ -0,0 +1,239 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.gui.multiview; + +import com.jme3.asset.AssetManager; +import com.jme3.audio.AudioRenderer; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.OffScenePanel; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.gui.NiftyGuiDataObject; +import com.jme3.renderer.ViewPort; +import de.lessvoid.nifty.Nifty; +import de.lessvoid.nifty.tools.resourceloader.FileSystemLocation; +import java.awt.Dimension; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.io.File; +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JToolBar; +import org.netbeans.modules.xml.multiview.Error; +import org.netbeans.modules.xml.multiview.ui.PanelView; +import org.netbeans.modules.xml.multiview.ui.ToolBarDesignEditor; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +/** + * + * @author normenhansen + */ +public class NiftyPreviewPanel extends PanelView { + + private NiftyGuiDataObject niftyObject; + private OffScenePanel offPanel; + private Nifty nifty; + private Document doc; + private ToolBarDesignEditor comp; + private String screen = ""; + private NiftyPreviewInputHandler inputHandler; + private NiftyJmeDisplay niftyDisplay; + private JScrollPane scrollPanel; + + public NiftyPreviewPanel(NiftyGuiDataObject niftyObject, ToolBarDesignEditor comp) { + super(); + setRoot(Node.EMPTY); + this.niftyObject = niftyObject; + this.comp = comp; + comp.setContentView(this); + preparePreview(); + updatePreView(); + } + + private void createToolbar() { + JToolBar toolBar = new JToolBar(); + toolBar.setPreferredSize(new Dimension(10000, 24)); + toolBar.setMaximumSize(new Dimension(10000, 24)); + toolBar.setFloatable(false); + JComboBox comboBox = new JComboBox(new String[]{"640x480", "1024x768", "1280x720"}); + comboBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + String string = (String) e.getItem(); + final int width; + final int height; + if ("640x480".equals(string)) { + width = 640; + height = 480; + } else if ("1024x768".equals(string)) { + width = 1024; + height = 768; + } else if ("1280x720".equals(string)) { + width = 1280; + height = 720; + } else { + width = 640; + height = 480; + } + offPanel.resizeGLView(width, height); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + niftyDisplay.reshape(offPanel.getViewPort(), width, height); + return null; + } + }); + updatePreView(screen); + } + }); + toolBar.add(comboBox); + toolBar.add(new JPanel()); + add(toolBar); + } + + + public void updatePreView() { + updatePreView(screen); + } + + public void updatePreView(final String screen) { + final ProjectAssetManager pm = niftyObject.getLookup().lookup(ProjectAssetManager.class); + if (pm == null) { + Logger.getLogger(NiftyPreviewPanel.class.getName()).log(Level.WARNING, "No Project AssetManager found!"); + } + try { + doc = XMLUtil.parse(new InputSource(niftyObject.getPrimaryFile().getInputStream()), false, false, null, null); + NiftyFileNode rootContext = new NiftyFileNode(doc.getDocumentElement()); + setRoot(rootContext); + comp.setRootContext(rootContext); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + nifty.fromXml(pm.getRelativeAssetPath(niftyObject.getPrimaryFile().getPath()), screen); + return null; + } + }); + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + validateTree(); + } + }); + } + + @Override + public void initComponents() { + super.initComponents(); + setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.PAGE_AXIS)); + createToolbar(); + scrollPanel = new JScrollPane(); + offPanel = new OffScenePanel(640, 480); + scrollPanel.getViewport().add(offPanel); + add(scrollPanel); + offPanel.startPreview(); + prepareInputHandler(); + } + + private void prepareInputHandler() { + inputHandler = new NiftyPreviewInputHandler(); + offPanel.addMouseMotionListener(new MouseMotionListener() { + + public void mouseDragged(MouseEvent e) { + inputHandler.addMouseEvent(e.getX(), e.getY(), e.getButton() == MouseEvent.NOBUTTON ? false : true); + } + + public void mouseMoved(MouseEvent e) { + inputHandler.addMouseEvent(e.getX(), e.getY(), e.getButton() == MouseEvent.NOBUTTON ? false : true); + } + }); + offPanel.addMouseListener(new MouseListener() { + + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + inputHandler.addMouseEvent(e.getX(), e.getY(), e.getButton() == MouseEvent.NOBUTTON ? false : true); + } + + public void mouseReleased(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + }); + offPanel.addKeyListener(new KeyListener() { + + public void keyTyped(KeyEvent e) { + } + + public void keyPressed(KeyEvent e) { + inputHandler.addKeyEvent(e.getKeyCode(), e.getKeyChar(), true, e.isShiftDown(), e.isControlDown()); + } + + public void keyReleased(KeyEvent e) { + } + }); + } + + private void preparePreview() { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + ViewPort guiViewPort = offPanel.getViewPort(); + ProjectAssetManager pm = niftyObject.getLookup().lookup(ProjectAssetManager.class); + if (pm == null) { + Logger.getLogger(NiftyPreviewPanel.class.getName()).log(Level.WARNING, "No Project AssetManager found!"); + return null; + } + AssetManager assetManager = pm.getManager(); + AudioRenderer audioRenderer = SceneApplication.getApplication().getAudioRenderer(); + niftyDisplay = new NiftyJmeDisplay(assetManager, + inputHandler, + audioRenderer, + guiViewPort); + nifty = niftyDisplay.getNifty(); + de.lessvoid.nifty.tools.resourceloader.ResourceLoader.addResourceLocation(new FileSystemLocation(new File(pm.getAssetFolderName()))); + + // attach the nifty display to the gui view port as a processor + guiViewPort.addProcessor(niftyDisplay); + return null; + } + }); + } + + @Override + protected Error validateView() { + return null; + } + + @Override + public void showSelection(Node[] nodes) { + this.screen = nodes[0].getName(); + updatePreView(); + } + + public void cleanup() { + offPanel.stopPreview(); + nifty.exit(); + } +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyScreenNode.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyScreenNode.java new file mode 100644 index 000000000..f6a9fa08f --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/NiftyScreenNode.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.gui.multiview; + +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; + +/** + * + * @author normenhansen + */ +public class NiftyScreenNode extends AbstractNode{ + + public NiftyScreenNode(String name) { + super(Children.LEAF); + setName(name); + } + +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/PreviewToolbarElement.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/PreviewToolbarElement.java new file mode 100644 index 000000000..80e9416e7 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/PreviewToolbarElement.java @@ -0,0 +1,48 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.gui.multiview; + +import com.jme3.gde.gui.NiftyGuiDataObject; +import org.netbeans.modules.xml.multiview.ToolBarMultiViewElement; +import org.netbeans.modules.xml.multiview.ui.SectionView; +import org.netbeans.modules.xml.multiview.ui.ToolBarDesignEditor; +import org.openide.nodes.Node; + +/** + * + * @author normenhansen + */ +public class PreviewToolbarElement extends ToolBarMultiViewElement { +// private NiftyGuiDataObject dObj; + private ToolBarDesignEditor comp; + private NiftyPreviewPanel viewPanel; + + public PreviewToolbarElement(NiftyGuiDataObject dObj) { + super(dObj); +// this.dObj = dObj; + comp = new ToolBarDesignEditor(); + setVisualEditor(comp); + viewPanel=new NiftyPreviewPanel(dObj, comp); + } + + @Override + public SectionView getSectionView() { + return null; + } + + @Override + public void componentShowing() { + super.componentShowing(); + viewPanel.updatePreView(); + } + + @Override + public void componentClosed() { + super.componentClosed(); + viewPanel.cleanup(); + } + +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/PreviewView.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/PreviewView.java new file mode 100644 index 000000000..989f14e42 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/PreviewView.java @@ -0,0 +1,35 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.gui.multiview; + +import com.jme3.gde.gui.NiftyGuiDataObject; +import org.netbeans.modules.xml.multiview.DesignMultiViewDesc; + +/** + * + * @author normenhansen + */ +public class PreviewView extends DesignMultiViewDesc { + + private int type; + + public PreviewView(NiftyGuiDataObject dObj, int type) { + super(dObj, "Design"); + this.type = type; + } + + public org.netbeans.core.spi.multiview.MultiViewElement createElement() { + NiftyGuiDataObject dObj = (NiftyGuiDataObject) getDataObject(); + return new PreviewToolbarElement(dObj); + } + + public java.awt.Image getIcon() { + return org.openide.util.Utilities.loadImage("com/jme3/gde/gui/Computer_File_043.gif"); //NOI18N + } + + public String preferredID() { + return "Toc_multiview_design" + String.valueOf(type); + } +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/XmlHelper.java b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/XmlHelper.java new file mode 100644 index 000000000..b58865d7c --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/multiview/XmlHelper.java @@ -0,0 +1,73 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.gui.multiview; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * + * @author normenhansen + */ +public class XmlHelper { + public static Element findFirstChildElement(Element parent) { + org.w3c.dom.Node ret = parent.getFirstChild(); + while (ret != null && (!(ret instanceof Element))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findChildElement(Element parent, String name) { + if (parent == null) { + return null; + } + org.w3c.dom.Node ret = parent.getFirstChild(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findNextElement(Node ret, String name) { + ret = ret.getNextSibling(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findChildElementWithAttribute(Element parent, String name, String attribute, String value) { + if (parent == null) { + return null; + } + org.w3c.dom.Node ret = parent.getFirstChild(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name) || ((Element)ret).getAttribute(attribute)==null || !((Element)ret).getAttribute(attribute).equals(value))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findNextElementWithAttribute(Node ret, String name, String attribute, String value) { + ret = ret.getNextSibling(); + while (ret != null && (!(ret instanceof Element) || !ret.getNodeName().equals(name) || ((Element)ret).getAttribute(attribute)==null || !((Element)ret).getAttribute(attribute).equals(value))) { + ret = ret.getNextSibling(); + } + return (Element) ret; + } + + public static Element findNextSiblingElement(Element current) { + org.w3c.dom.Node ret = current.getNextSibling(); + while (ret != null) { + if (ret instanceof Element) { + return (Element) ret; + } + ret = ret.getNextSibling(); + } + return null; + } + +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/palette/GuiXMLPaletteFactory.java b/sdk/jme3-gui/src/com/jme3/gde/gui/palette/GuiXMLPaletteFactory.java new file mode 100644 index 000000000..c79e7e114 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/palette/GuiXMLPaletteFactory.java @@ -0,0 +1,72 @@ +/* + * JavaSourceFileLayerPaletteFactory.java + * + * Created on Jun 4, 2007, 12:33:34 PM + * + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.gui.palette; + +import java.io.IOException; +import javax.swing.Action; +import org.netbeans.spi.palette.PaletteActions; +import org.netbeans.spi.palette.PaletteController; +import org.netbeans.spi.palette.PaletteFactory; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + +/** + * + * @author gw152771 + */ +public class GuiXMLPaletteFactory { + + public static final String JAVA_PALETTE_FOLDER = "JavaPalette"; + private static PaletteController palette = null; + + public GuiXMLPaletteFactory() { + } + + public static PaletteController createPalette() { + try { + if (null == palette) + palette = PaletteFactory.createPalette(JAVA_PALETTE_FOLDER, new MyActions()); + return palette; + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + private static class MyActions extends PaletteActions { + + //Add new buttons to the Palette Manager here: + public Action[] getImportActions() { + return null; + } + + //Add new contextual menu items to the palette here: + public Action[] getCustomPaletteActions() { + return null; + } + + //Add new contextual menu items to the categories here: + public Action[] getCustomCategoryActions(Lookup arg0) { + return null; + } + + //Add new contextual menu items to the items here: + public Action[] getCustomItemActions(Lookup arg0) { + return null; + } + + //Define the default action here: + public Action getPreferredAction(Lookup arg0) { + return null; + } + + } + +} diff --git a/sdk/jme3-gui/src/com/jme3/gde/gui/palette/JmePaletteUtilities.java b/sdk/jme3-gui/src/com/jme3/gde/gui/palette/JmePaletteUtilities.java new file mode 100644 index 000000000..9f508b349 --- /dev/null +++ b/sdk/jme3-gui/src/com/jme3/gde/gui/palette/JmePaletteUtilities.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2009-2010 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.gui.palette; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import javax.swing.text.StyledDocument; +import org.openide.text.NbDocument; + +public class JmePaletteUtilities { + + public static void insert(final String s,final JTextComponent target) throws BadLocationException { + + final StyledDocument doc = (StyledDocument)target.getDocument(); + + class AtomicChange implements Runnable { + + public void run() { + Document value = target.getDocument(); + if (value == null) + return; + try { + insert(s, target, doc); + } catch (BadLocationException e) {} + } + } + + try { + NbDocument.runAtomicAsUser(doc, new AtomicChange()); + } catch (BadLocationException ex) {} + + } + + private static int insert(String s, JTextComponent target, Document doc) throws BadLocationException { + + int start = -1; + + try { + + //firstly, find selected text range: + Caret caret = target.getCaret(); + int p0 = Math.min(caret.getDot(), caret.getMark()); + int p1 = Math.max(caret.getDot(), caret.getMark()); + doc.remove(p0, p1 - p0); + + //then, replace selected text range with the inserted one: + start = caret.getDot(); + doc.insertString(start, s, null); + + } catch (BadLocationException ble) {} + + return start; + + } + +} \ No newline at end of file diff --git a/sdk/jme3-lwjgl-applet/applet-data/appletlogo.png b/sdk/jme3-lwjgl-applet/applet-data/appletlogo.png new file mode 100644 index 000000000..f40cf4d3b Binary files /dev/null and b/sdk/jme3-lwjgl-applet/applet-data/appletlogo.png differ diff --git a/sdk/jme3-lwjgl-applet/build.xml b/sdk/jme3-lwjgl-applet/build.xml new file mode 100644 index 000000000..eb4002ad5 --- /dev/null +++ b/sdk/jme3-lwjgl-applet/build.xml @@ -0,0 +1,13 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.lwjgl.applet. + + + + + + + diff --git a/sdk/jme3-lwjgl-applet/manifest.mf b/sdk/jme3-lwjgl-applet/manifest.mf new file mode 100644 index 000000000..42c43fa72 --- /dev/null +++ b/sdk/jme3-lwjgl-applet/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.lwjgl.applet +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/lwjgl/applet/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/lwjgl/applet/Bundle.properties + diff --git a/sdk/jme3-lwjgl-applet/nbproject/build-impl.xml b/sdk/jme3-lwjgl-applet/nbproject/build-impl.xml new file mode 100644 index 000000000..8101e435a --- /dev/null +++ b/sdk/jme3-lwjgl-applet/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-lwjgl-applet/nbproject/genfiles.properties b/sdk/jme3-lwjgl-applet/nbproject/genfiles.properties new file mode 100644 index 000000000..4d76076e1 --- /dev/null +++ b/sdk/jme3-lwjgl-applet/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=c8f4ce4e +build.xml.script.CRC32=1ed5abd5 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=c8f4ce4e +nbproject/build-impl.xml.script.CRC32=a70d83dd +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-lwjgl-applet/nbproject/project.properties b/sdk/jme3-lwjgl-applet/nbproject/project.properties new file mode 100644 index 000000000..00311e62a --- /dev/null +++ b/sdk/jme3-lwjgl-applet/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.7.0 diff --git a/sdk/jme3-lwjgl-applet/nbproject/project.xml b/sdk/jme3-lwjgl-applet/nbproject/project.xml new file mode 100644 index 000000000..5debc0c64 --- /dev/null +++ b/sdk/jme3-lwjgl-applet/nbproject/project.xml @@ -0,0 +1,80 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.lwjgl.applet + + + + com.jme3.gde.core + + + + 1 + 0.9 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.30 + + + + org.netbeans.modules.projectuiapi + + + + 1 + 1.46 + + + + org.openide.filesystems + + + + 7.37 + + + + org.openide.loaders + + + + 7.15 + + + + org.openide.nodes + + + + 7.15 + + + + org.openide.util + + + + 8.5 + + + + org.openide.util.lookup + + + + 8.2 + + + + + + + diff --git a/sdk/jme3-lwjgl-applet/nbproject/suite.properties b/sdk/jme3-lwjgl-applet/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-lwjgl-applet/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-lwjgl-applet/release/libs/applet-loader.zip b/sdk/jme3-lwjgl-applet/release/libs/applet-loader.zip new file mode 100644 index 000000000..ce56575fa Binary files /dev/null and b/sdk/jme3-lwjgl-applet/release/libs/applet-loader.zip differ diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/Bundle.properties b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/Bundle.properties new file mode 100644 index 000000000..5525a594f --- /dev/null +++ b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/Bundle.properties @@ -0,0 +1,14 @@ +lwjgl-applet=lwjgl-applet +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides LWJGL Applet creation support for jMonkeyPlatform. \ + It uses the lwjgl applet method to create applets. +OpenIDE-Module-Name=LWJGL Applet Support +LwjglAppletCustomizerPanel.jCheckBox1.text=Create Applet +LwjglAppletCustomizerPanel.jLabel1.text=Width/Height: +LBL_Category_LWJGL_Applet=Applet +OpenIDE-Module-Short-Description=Provides LWJGL Applet creation support for jMP +LwjglAppletCustomizerPanel.jTextField1.text=640 +LwjglAppletCustomizerPanel.jLabel2.text=An applet can be launched in any browser supporting Java. +LwjglAppletCustomizerPanel.jTextField2.text=480 +LwjglAppletCustomizerPanel.jLabel3.text=X diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCompositeProvider.java b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCompositeProvider.java new file mode 100644 index 000000000..3c59b5fc3 --- /dev/null +++ b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCompositeProvider.java @@ -0,0 +1,123 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.lwjgl.applet; + +import com.jme3.gde.core.j2seproject.ProjectExtensionManager; +import com.jme3.gde.core.j2seproject.ProjectExtensionProperties; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import javax.swing.JComponent; + +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + +import org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; + +/** + * + * @author normenhansen + */ +@ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-java-j2seproject", category = "Application", position = 300) +public class LwjglAppletCompositeProvider implements ProjectCustomizer.CompositeCategoryProvider { + + private static final String CAT_LWJGL_APPLET = "LwjglApplet"; // NOI18N + private static ProjectExtensionProperties jwsProps = null; + private String[] keyList = new String[]{ + "lwjgl.applet.enabled", + "lwjgl.applet.width", + "lwjgl.applet.height" + }; + + public LwjglAppletCompositeProvider() { + } + + @Override + public ProjectCustomizer.Category createCategory(Lookup context) { + return ProjectCustomizer.Category.create(CAT_LWJGL_APPLET, + NbBundle.getMessage(LwjglAppletCompositeProvider.class, "LBL_Category_LWJGL_Applet"), null); + } + + @Override + public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) { + jwsProps = new ProjectExtensionProperties(context.lookup(Project.class), keyList); + LwjglAppletCustomizerPanel panel = new LwjglAppletCustomizerPanel(jwsProps); + category.setStoreListener(new SavePropsListener(jwsProps, context.lookup(Project.class))); + category.setOkButtonListener(panel); + return panel; + } + + private class SavePropsListener implements ActionListener { + + private String extensionName = "lwjglapplet"; + private String extensionVersion = "v0.95"; + private String[] extensionDependencies = new String[]{"jar", "-lwjgl-applet"}; + private ProjectExtensionManager manager = new ProjectExtensionManager(extensionName, extensionVersion, extensionDependencies); + private ProjectExtensionProperties properties; + private Project project; + + public SavePropsListener(ProjectExtensionProperties props, Project project) { + this.properties = props; + this.project = project; + manager.setAntTaskLibrary("lwjgl-applet"); + } + + public void actionPerformed(ActionEvent e) { + if ("true".equals(properties.getProperty("lwjgl.applet.enabled"))) { + manager.loadTargets("nbres:/com/jme3/gde/lwjgl/applet/lwjgl-applet-targets.xml"); + manager.checkExtension(project); + if (project.getProjectDirectory().getFileObject("appletlogo.png") == null) { + try { + unZipFile(new URL("nbres:/com/jme3/gde/lwjgl/applet/applet-data.zip").openStream(), project.getProjectDirectory()); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + } else { + manager.removeExtension(project); + } + try { + properties.store(); + } catch (IOException ioe) { + Exceptions.printStackTrace(ioe); + } + } + + private void unZipFile(InputStream source, FileObject projectRoot) throws IOException { + try { + ZipInputStream str = new ZipInputStream(source); + ZipEntry entry; + while ((entry = str.getNextEntry()) != null) { + if (entry.isDirectory()) { + FileUtil.createFolder(projectRoot, entry.getName()); + } else { + FileObject fo = FileUtil.createData(projectRoot, entry.getName()); + writeFile(str, fo); + } + } + } finally { + source.close(); + } + } + + private void writeFile(ZipInputStream str, FileObject fo) throws IOException { + OutputStream out = fo.getOutputStream(); + try { + FileUtil.copy(str, out); + } finally { + out.close(); + } + } + } +} diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCustomizerPanel.form b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCustomizerPanel.form new file mode 100644 index 000000000..01e92333e --- /dev/null +++ b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCustomizerPanel.form @@ -0,0 +1,95 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCustomizerPanel.java b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCustomizerPanel.java new file mode 100644 index 000000000..7900fa32a --- /dev/null +++ b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/LwjglAppletCustomizerPanel.java @@ -0,0 +1,128 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * LwjglAppletCustomizerPanel.java + * + * Created on 11.11.2010, 16:56:53 + */ +package com.jme3.gde.lwjgl.applet; + +import com.jme3.gde.core.j2seproject.ProjectExtensionProperties; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.openide.util.HelpCtx; + +/** + * + * @author normenhansen + */ +public class LwjglAppletCustomizerPanel extends javax.swing.JPanel implements ActionListener { + + private ProjectExtensionProperties properties; + + /** Creates new form LwjglAppletCustomizerPanel */ + public LwjglAppletCustomizerPanel(ProjectExtensionProperties properties) { + this.properties = properties; + initComponents(); + loadProperties(); + HelpCtx.setHelpIDString(this, "sdk.application_deployment"); + } + + private void loadProperties() { + String str = properties.getProperty("lwjgl.applet.enabled"); + if ("true".equals(str)) { + jCheckBox1.setSelected(true); + } else { + jCheckBox1.setSelected(false); + } + if (properties.getProperty("lwjgl.applet.width") != null) { + jTextField1.setText(properties.getProperty("lwjgl.applet.width")); + jTextField2.setText(properties.getProperty("lwjgl.applet.height")); + } + } + + private void saveProperties() { + if (jCheckBox1.isSelected()) { + properties.setProperty("lwjgl.applet.enabled", "true"); + } else { + properties.setProperty("lwjgl.applet.enabled", ""); + } + properties.setProperty("lwjgl.applet.width", jTextField1.getText()); + properties.setProperty("lwjgl.applet.height", jTextField2.getText()); + } + + public void actionPerformed(ActionEvent e) { + saveProperties(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jCheckBox1 = new javax.swing.JCheckBox(); + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jLabel3 = new javax.swing.JLabel(); + + jCheckBox1.setText(org.openide.util.NbBundle.getMessage(LwjglAppletCustomizerPanel.class, "LwjglAppletCustomizerPanel.jCheckBox1.text")); // NOI18N + + jLabel1.setText(org.openide.util.NbBundle.getMessage(LwjglAppletCustomizerPanel.class, "LwjglAppletCustomizerPanel.jLabel1.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(LwjglAppletCustomizerPanel.class, "LwjglAppletCustomizerPanel.jTextField1.text")); // NOI18N + + jLabel2.setText(org.openide.util.NbBundle.getMessage(LwjglAppletCustomizerPanel.class, "LwjglAppletCustomizerPanel.jLabel2.text")); // NOI18N + + jTextField2.setText(org.openide.util.NbBundle.getMessage(LwjglAppletCustomizerPanel.class, "LwjglAppletCustomizerPanel.jTextField2.text")); // NOI18N + + jLabel3.setText(org.openide.util.NbBundle.getMessage(LwjglAppletCustomizerPanel.class, "LwjglAppletCustomizerPanel.jLabel3.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jCheckBox1, javax.swing.GroupLayout.DEFAULT_SIZE, 408, Short.MAX_VALUE) + .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 408, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(169, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBox1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel3) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(212, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/applet-data.zip b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/applet-data.zip new file mode 100644 index 000000000..8065988d0 Binary files /dev/null and b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/applet-data.zip differ diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/layer.xml b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/layer.xml new file mode 100644 index 000000000..6c42d00ea --- /dev/null +++ b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/layer.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/lwjgl-applet-targets.xml b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/lwjgl-applet-targets.xml new file mode 100644 index 000000000..1c70b59a6 --- /dev/null +++ b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/lwjgl-applet-targets.xml @@ -0,0 +1,120 @@ + + Packing Splash + + + + + + + Applet Creation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${applet.title} + ${application.title} + + + + ${applet.main.class} + ${main.class} + + + + ${applet.archive} + ${applet.archive} + + + + ${applet.classpath} + ${applet.classpath} + + + + ${applet.logo} + ${applet.logo.name} + + + + ${applet.version} + ${applet.version} + + + + ${applet.width} + ${lwjgl.applet.width} + + + + ${applet.height} + ${lwjgl.applet.height} + + + + + + + + + + diff --git a/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/lwjgl-applet.xml b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/lwjgl-applet.xml new file mode 100644 index 000000000..690ee33d7 --- /dev/null +++ b/sdk/jme3-lwjgl-applet/src/com/jme3/gde/lwjgl/applet/lwjgl-applet.xml @@ -0,0 +1,21 @@ + + + + + lwjgl-applet + j2se + com.jme3.gde.lwjgl.applet.Bundle + + classpath + jar:nbinst://com.jme3.gde.lwjgl.applet/libs/applet-loader.zip!/ + + + src + + + javadoc + + diff --git a/sdk/jme3-materialeditor/build.xml b/sdk/jme3-materialeditor/build.xml new file mode 100644 index 000000000..c2947deab --- /dev/null +++ b/sdk/jme3-materialeditor/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.materials. + + diff --git a/sdk/jme3-materialeditor/manifest.mf b/sdk/jme3-materialeditor/manifest.mf new file mode 100644 index 000000000..a3b0fb009 --- /dev/null +++ b/sdk/jme3-materialeditor/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.materials/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/materials/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/materials/Bundle.properties + diff --git a/sdk/jme3-materialeditor/nbproject/build-impl.xml b/sdk/jme3-materialeditor/nbproject/build-impl.xml new file mode 100644 index 000000000..3d3016e62 --- /dev/null +++ b/sdk/jme3-materialeditor/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-materialeditor/nbproject/genfiles.properties b/sdk/jme3-materialeditor/nbproject/genfiles.properties new file mode 100644 index 000000000..6dac79da7 --- /dev/null +++ b/sdk/jme3-materialeditor/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=3a4f0982 +build.xml.script.CRC32=f284e28d +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=3a4f0982 +nbproject/build-impl.xml.script.CRC32=56cee44d +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-materialeditor/nbproject/project.properties b/sdk/jme3-materialeditor/nbproject/project.properties new file mode 100644 index 000000000..00311e62a --- /dev/null +++ b/sdk/jme3-materialeditor/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.7.0 diff --git a/sdk/jme3-materialeditor/nbproject/project.xml b/sdk/jme3-materialeditor/nbproject/project.xml new file mode 100644 index 000000000..f9fd6dd7c --- /dev/null +++ b/sdk/jme3-materialeditor/nbproject/project.xml @@ -0,0 +1,140 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.materials + + + + com.jme3.gde.core + + + + 1 + 0.12 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.5 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.5 + + + + org.netbeans.core.multiview + + + + 1 + 1.16.1 + + + + org.netbeans.modules.settings + + + + 1 + 1.22.1.1 + + + + org.openide.actions + + + + 6.12.1.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.text + + + + 6.27.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.30.1 + + + + + com.jme3.gde.materials + + + + diff --git a/sdk/jme3-materialeditor/nbproject/suite.properties b/sdk/jme3-materialeditor/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-materialeditor/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/Bundle.properties b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/Bundle.properties new file mode 100644 index 000000000..c9e4a6b2d --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/Bundle.properties @@ -0,0 +1,9 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + Provides support for editing jME3 material files +OpenIDE-Module-Name=Material Support +OpenIDE-Module-Short-Description=Provides support for editing jME3 material files +Services/MIMEResolver/JMEMaterialDefinitionResolver.xml=MaterialDefinition Files +Services/MIMEResolver/JMEMaterialResolver.xml=Material Files +Templates/Other/JMEMaterialDefinitionTemplate.j3md=Empty MaterialDefinition file +Templates/Other/JMEMaterialTemplate.j3m=Empty Material file diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDataObject.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDataObject.java new file mode 100644 index 000000000..603fe85ba --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDataObject.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2009-2010 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.materials; + +import com.jme3.gde.core.assets.AssetDataObject; +import com.jme3.gde.materials.multiview.MaterialOpenSupport; +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.text.DataEditorSupport; + +public class JMEMaterialDataObject extends AssetDataObject { + + public JMEMaterialDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + CookieSet cookies = getCookieSet(); +// cookies.add((Node.Cookie) DataEditorSupport.create(this, getPrimaryEntry(), cookies)); + cookies.add((Node.Cookie) new MaterialOpenSupport(getPrimaryEntry())); + } + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDefinitionDataObject.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDefinitionDataObject.java new file mode 100644 index 000000000..f8f91779c --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDefinitionDataObject.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009-2010 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.materials; + +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiDataObject; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.text.DataEditorSupport; + +public class JMEMaterialDefinitionDataObject extends MultiDataObject { + + public JMEMaterialDefinitionDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + CookieSet cookies = getCookieSet(); + cookies.add((Node.Cookie) DataEditorSupport.create(this, getPrimaryEntry(), cookies)); + } + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDefinitionResolver.xml b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDefinitionResolver.xml new file mode 100644 index 000000000..5ae719e8d --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialDefinitionResolver.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialResolver.xml b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialResolver.xml new file mode 100644 index 000000000..724feb47a --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/JMEMaterialResolver.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/Material.j3m b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/Material.j3m new file mode 100644 index 000000000..0a60b751a --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/Material.j3m @@ -0,0 +1,4 @@ +Material My Material : Common/MatDefs/Light/Lighting.j3md { + MaterialParameters { + } +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialDefinition.j3md b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialDefinition.j3md new file mode 100644 index 000000000..9a58e1e76 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialDefinition.j3md @@ -0,0 +1,16 @@ +MaterialDef My MaterialDef { + + MaterialParameters { + Vector4 Color + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Misc/SolidColor.vert + FragmentShader GLSL100: Common/MatDefs/Misc/SolidColor.frag + + WorldParameters { + WorldViewProjectionMatrix + } + } + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialEditorTopComponentSettings.xml b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialEditorTopComponentSettings.xml new file mode 100644 index 000000000..426d8796f --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialEditorTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialEditorTopComponentWstcref.xml b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialEditorTopComponentWstcref.xml new file mode 100644 index 000000000..72d92428d --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialEditorTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperties.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperties.java new file mode 100644 index 000000000..7098c721e --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperties.java @@ -0,0 +1,466 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.materials; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.system.JmeSystem; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; + +/** + * Provides an editable j3m file + * @author normenhansen + */ +public class MaterialProperties { + + private String name; + private String matDefName; + private FileObject material; + private FileObject matDef; + private Map materialParameters = new HashMap(); + private Map additionalRenderStates = new HashMap(); + private List matDefEntries = new ArrayList(); + private ProjectAssetManager manager; + private FileSystem fs; + public static final String[] variableTypes = new String[]{"Int", "Boolean", "Float", "Vector2", "Vector3", "Vector4", "Color", "Texture2D", "TextureCubeMap"}; + + public MaterialProperties(FileObject material, ProjectAssetManager manager) { + this.material = material; + this.manager = manager; + } + + private void prepareAdditionalStates() { + additionalRenderStates.clear(); + additionalRenderStates.put("Wireframe", new MaterialProperty("OnOff", "Wireframe", "")); + additionalRenderStates.put("DepthWrite", new MaterialProperty("OnOff", "DepthWrite", "")); + additionalRenderStates.put("DepthTest", new MaterialProperty("OnOff", "DepthTest", "")); + additionalRenderStates.put("ColorWrite", new MaterialProperty("OnOff", "ColorWrite", "")); + additionalRenderStates.put("PointSprite", new MaterialProperty("OnOff", "PointSprite", "")); + additionalRenderStates.put("FaceCull", new MaterialProperty("FaceCullMode", "FaceCull", "")); + additionalRenderStates.put("Blend", new MaterialProperty("BlendMode", "Blend", "")); + additionalRenderStates.put("AlphaTestFalloff", new MaterialProperty("Float", "AlphaTestFalloff", "")); + additionalRenderStates.put("PolyOffset", new MaterialProperty("Float,Float", "PolyOffset", "")); + } + + /** + * loads the data from the material and matdef files + */ + public void read() { + prepareAdditionalStates(); + materialParameters.clear(); + int level = 0; + boolean params = false; + boolean states = false; + try { + //scan material text + for (String line : material.asLines()) { + //trim line incl comments + line = trimLine(line); + //find and load matdef file + if (line.startsWith("Material ") || line.startsWith("Material\t") && level == 0) { + parseMaterialProperties(line); + } + //start parsing material parameters + if (line.startsWith("MaterialParameters ") || line.startsWith("MaterialParameters\t") || line.startsWith("MaterialParameters{") && level == 1) { + params = true; + } + //start parsing renderstates + if (line.startsWith("AdditionalRenderState ") || line.startsWith("AdditionalRenderState\t") || line.startsWith("AdditionalRenderState{") && level == 1) { + states = true; + } + //up a level + if (line.indexOf("{") != -1) { + level++; + } + //down a level, stop processing parameters/states + if (line.indexOf("}") != -1) { + level--; + if (params) { + params = false; + } + if (states) { + states = false; + } + } + //try reading parameter + if (level == 2 && params) { + int colonIdx = line.indexOf(":"); + if (colonIdx != -1) { + String[] lines = line.split(":"); + MaterialProperty prop = new MaterialProperty(); + prop.setName(lines[0].trim()); + if (lines.length > 1) { + prop.setValue(lines[lines.length - 1].trim()); + } + materialParameters.put(prop.getName(), prop); + } + } + //try reading state + if (level == 2 && states) { + String[] lines = null; + int colonIdx = line.indexOf(" "); + if (colonIdx != -1) { + lines = line.split(" "); + } + colonIdx = line.indexOf("\t"); + if (colonIdx != -1) { + lines = line.split("\t"); + } + if (lines != null) { + MaterialProperty prop = new MaterialProperty(); + String name = lines[0].trim(); + prop.setName(name); + if (additionalRenderStates.get(name) != null) { + prop.setType(additionalRenderStates.get(name).getType()); + if (lines.length > 1) { + prop.setValue(lines[lines.length - 1].trim()); + } + additionalRenderStates.put(prop.getName(), prop); + } + } + } + } + parseMatDef(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** + * finds and loads the matdef file either from project or from base jme + * @param line + */ + private void parseMaterialProperties(String line) { + int colonIdx = line.indexOf(":"); + //find matdef file + if (colonIdx != -1) { + line = line.replaceFirst("Material", ""); + line = line.replace("{", ""); + String[] lines = line.split(":"); + setName(lines[0].trim()); + setMatDefName(lines[1].trim()); + } + } + + private void initMatDef() { + //try to read from assets folder + matDef = manager.getAssetFolder().getFileObject(getMatDefName()); + + //try to read from classpath if not in assets folder and store in a virtual filesystem folder + if (matDef == null || !matDef.isValid()) { + try { + fs = FileUtil.createMemoryFileSystem(); + matDef = fs.getRoot().createData(name, "j3md"); + OutputStream out = matDef.getOutputStream(); + InputStream in = JmeSystem.getResourceAsStream("/" + getMatDefName()); + if (in != null) { + int input = in.read(); + while (input != -1) { + out.write(input); + input = in.read(); + } + in.close(); + } + out.close(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } + + /** + * finds and loads the matdef file either from project or from base jme + * @param line + */ + private void parseMatDef() { + //load matdef + matDefEntries.clear(); + boolean params = false; + int level = 0; + if (matDef != null && matDef.isValid()) { + try { + for (String defLine : matDef.asLines()) { + defLine = trimLine(defLine.trim()); + if (defLine.startsWith("MaterialParameters ") || defLine.startsWith("MaterialParameters\t") || defLine.startsWith("MaterialParameters{") && level == 1) { + params = true; + } + if (defLine.indexOf("{") != -1) { + level++; + } + if (defLine.indexOf("}") != -1) { + level--; + if (params) { + params = false; + } + } + //read variable types + if (level == 2 && params) { + for (int i = 0; i < variableTypes.length; i++) { + String string = variableTypes[i]; + if (defLine.startsWith(string)) { + String name = trimName(defLine.replaceFirst(string, "")); + matDefEntries.add(name); + MaterialProperty prop = materialParameters.get(name); + if (prop == null) { + prop = new MaterialProperty(); + prop.setName(name); + prop.setValue(""); + materialParameters.put(prop.getName(), prop); + } + prop.setType(string); + } + } + } + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } else { + Logger.getLogger(MaterialProperties.class.getName()).log(Level.WARNING, "Could not read MaterialDef!"); + } + for (Iterator> it = materialParameters.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = it.next(); + if (!matDefEntries.contains(entry.getKey())) { + it.remove(); + } + } + } + + /** + * returns the new content of the material file, filled with the new parameters + * @return + */ + public String getUpdatedContent() { + boolean params = false; + boolean states = false; + boolean addedstates = false; + int level = 0; + try { + List matLines = material.asLines(); + StringWriter out = new StringWriter(); + List setValues = new LinkedList(); + List setStates = new LinkedList(); + //goes through the lines of the material file and replaces the values it finds + for (String line : matLines) { + String newLine = line; + line = trimLine(line); + //write material header + if (line.startsWith("Material ") || line.startsWith("Material\t") && level == 0) { + String suffix = ""; + if (line.indexOf("{") > -1) { + suffix = "{"; + } + newLine = "Material " + getName() + " : " + matDefName + " " + suffix; + } + //start parameters + if (line.startsWith("MaterialParameters ") || line.startsWith("MaterialParameters\t") || line.startsWith("MaterialParameters{") && level == 1) { + params = true; + } + //start states + if (line.startsWith("AdditionalRenderState ") || line.startsWith("AdditionalRenderState\t") || line.startsWith("AdditionalRenderState{") && level == 1) { + states = true; + addedstates = true; + } + //up a level + if (line.indexOf("{") != -1) { + level++; + } + //down a level, stop processing states and check if all parameters and states have been written + if (line.indexOf("}") != -1) { + level--; + //find and write parameters we did not replace yet at end of parameters section + if (params) { + for (Iterator> it = materialParameters.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = it.next(); + if (!setValues.contains(entry.getKey()) && matDefEntries.contains(entry.getKey())) { + MaterialProperty prop = entry.getValue(); + if (prop.getValue() != null && prop.getValue().length() > 0) { + String myLine = " " + prop.getName() + " : " + prop.getValue() + "\n"; + out.write(myLine, 0, myLine.length()); + } + } + } + params = false; + } + //find and write states we did not replace yet at end of states section + if (states) { + for (Iterator> it = additionalRenderStates.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = it.next(); + if (!setStates.contains(entry.getKey())) { + MaterialProperty prop = entry.getValue(); + if (prop.getValue() != null && prop.getValue().length() > 0) { + String myLine = " " + prop.getName() + " " + prop.getValue() + "\n"; + out.write(myLine, 0, myLine.length()); + } + } + } + states = false; + } + //add renderstates if they havent been in the file yet + if (level == 0) { + if (!addedstates) { + String myLine = " AdditionalRenderState {\n"; + out.write(myLine, 0, myLine.length()); + for (Iterator> it = additionalRenderStates.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = it.next(); + if (!setStates.contains(entry.getKey())) { + MaterialProperty prop = entry.getValue(); + if (prop.getValue() != null && prop.getValue().length() > 0) { + myLine = " " + prop.getName() + " " + prop.getValue() + "\n"; + out.write(myLine, 0, myLine.length()); + } + } + } + myLine = " }\n"; + out.write(myLine, 0, myLine.length()); + } + } + } + //try replacing value of parameter line with new value + if (level == 2 && params) { + int colonIdx = newLine.indexOf(":"); + if (colonIdx != -1) { + String[] lines = newLine.split(":"); + String myName = lines[0].trim(); + if (materialParameters.containsKey(myName)) { + setValues.add(myName); + MaterialProperty prop = materialParameters.get(myName); + if (prop.getValue() != null && prop.getValue().length() > 0 && prop.getType() != null) { + newLine = lines[0] + ": " + prop.getValue(); + } else { + newLine = null; + } + } else if (!matDefEntries.contains(myName)) { + newLine = null; + } + } + } + //try replacing value of state line with new value + if (level == 2 && states) { + String cutLine = newLine.trim(); + String[] lines = null; + int colonIdx = cutLine.indexOf(" "); + if (colonIdx != -1) { + lines = cutLine.split(" "); + } + colonIdx = cutLine.indexOf("\t"); + if (colonIdx != -1) { + lines = cutLine.split("\t"); + } + if (lines != null) { + String myName = lines[0].trim(); + if (additionalRenderStates.containsKey(myName)) { + setStates.add(myName); + MaterialProperty prop = additionalRenderStates.get(myName); + if (prop.getValue() != null && prop.getValue().length() > 0 && prop.getType() != null) { + newLine = " " + lines[0] + " " + prop.getValue(); + } else { + newLine = null; + } + } + } + } + if (newLine != null) { + out.write(newLine + "\n", 0, newLine.length() + 1); + } + } + out.close(); + return out.toString(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + return ""; + } + + /** + * trims a line and removes comments + * @param line + * @return + */ + private String trimLine(String line) { + int idx = line.indexOf("//"); + if (idx != -1) { + line = line.substring(0, idx); + } + return line.trim(); + } + + /** + * trims a line and removes everything behind colon + * @param line + * @return + */ + private String trimName(String line) { + line = trimLine(line); + int idx = line.indexOf(":"); + if (idx != -1) { + line = line.substring(0, idx); + } + return line.trim(); + } + + public Map getParameterMap() { + return materialParameters; + } + + public Map getStateMap() { + return additionalRenderStates; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + public void setAsText(String text) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(material.getOutputStream()); + out.write(text, 0, text.length()); + out.close(); + } + + /** + * @return the matDefName + */ + public String getMatDefName() { + return matDefName; + } + + /** + * @param matDefName the matDefName to set + */ + public void setMatDefName(String matDefName) { + this.matDefName = matDefName; + initMatDef(); + parseMatDef(); + } + + public String getMaterialPath() { + return manager.getRelativeAssetPath(material.getPath()); + } +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java new file mode 100644 index 000000000..51cf37fdd --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java @@ -0,0 +1,70 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.materials; + +/** + * + * @author normenhansen + */ +public class MaterialProperty { + private String type; + private String name; + private String value; + + public MaterialProperty() { + } + + + public MaterialProperty(String type, String name, String value) { + this.type = type; + this.name = name; + this.value = value; + } + + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } + + /** + * @param value the value to set + */ + public void setValue(String value) { + this.value = value; + } + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/jme-logo.png b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/jme-logo.png new file mode 100644 index 000000000..f67785a6e Binary files /dev/null and b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/jme-logo.png differ diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/layer.xml b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/layer.xml new file mode 100644 index 000000000..b52fae921 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/layer.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/Bundle.properties b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/Bundle.properties new file mode 100644 index 000000000..98d60ceb6 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/Bundle.properties @@ -0,0 +1,15 @@ +CTL_MaterialEditorAction=MaterialEditor +CTL_MaterialEditorTopComponent=MaterialEditor Window +HINT_MaterialEditorTopComponent=This is a MaterialEditor window +MaterialEditorTopComponent.jLabel1.text=Material Definition +MaterialEditorTopComponent.jLabel2.text= +MaterialEditorTopComponent.jScrollPane1.TabConstraints.tabTitle=Source +MaterialEditorTopComponent.jScrollPane2.TabConstraints.tabTitle=Properties +MaterialEditorTopComponent.jPanel4.TabConstraints.tabTitle=Editor +MaterialEditorTopComponent.jLabel3.text=Name +MaterialEditorTopComponent.jTextField1.text=jTextField1 +MaterialEditorTopComponent.jToolBar1.toolTipText=preview - updates when saved +MaterialEditorTopComponent.jScrollPane3.TabConstraints.tabTitle=Textures & Colors +MaterialEditorTopComponent.jScrollPane9.TabConstraints.tabTitle=Additional RenderState +MaterialEditorTopComponent.jScrollPane2.TabConstraints.tabTitle_1=Options +MaterialEditorTopComponent.jCheckBox1.text=save immediately diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialEditorTopComponent.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialEditorTopComponent.form new file mode 100644 index 000000000..1fff677ae --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialEditorTopComponent.form @@ -0,0 +1,440 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialEditorTopComponent.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialEditorTopComponent.java new file mode 100644 index 000000000..fd39a4d30 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialEditorTopComponent.java @@ -0,0 +1,660 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.materials.multiview; + +import com.jme3.asset.AssetKey; +import com.jme3.asset.DesktopAssetManager; +import com.jme3.gde.core.assets.AssetDataObject; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.PreviewRequest; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneListener; +import com.jme3.gde.core.scene.SceneRequest; +import com.jme3.gde.materials.MaterialProperties; +import com.jme3.gde.materials.MaterialProperty; +import com.jme3.gde.materials.multiview.widgets.MaterialPropertyWidget; +import com.jme3.gde.materials.multiview.widgets.MaterialWidgetListener; +import com.jme3.gde.materials.multiview.widgets.WidgetFactory; +import com.jme3.material.Material; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Sphere; +import com.jme3.util.TangentBinormalGenerator; +import java.awt.Component; +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.logging.Logger; +import javax.swing.ImageIcon; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +//import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.cookies.SaveCookie; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.lookup.InstanceContent; +import org.openide.windows.CloneableTopComponent; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.materials.multiview//MaterialEditor//EN", +autostore = false) +public final class MaterialEditorTopComponent extends CloneableTopComponent implements SceneListener, MaterialWidgetListener { + + private static MaterialEditorTopComponent instance; + /** path to the icon used by the component and its open action */ +// static final String ICON_PATH = "SET/PATH/TO/ICON/HERE"; + private static final String PREFERRED_ID = "MaterialEditorTopComponent"; + private Lookup lookup; + private final InstanceContent lookupContents = new InstanceContent(); +// private SaveNode saveNode; + private DataObject dataObject; + private MaterialProperties properties; + private String materialFileName; + private ProjectAssetManager manager; + private Sphere sphMesh; + private SaveCookie saveCookie = new SaveCookieImpl(); + private boolean saveImmediate = true; + private boolean updateProperties = false; + + public MaterialEditorTopComponent() { + } + + public MaterialEditorTopComponent(DataObject dataObject) { + this.dataObject = dataObject; + materialFileName = dataObject.getPrimaryFile().getPath(); + initWindow(); + } + + private void initWindow() { + initComponents(); + setName(NbBundle.getMessage(MaterialEditorTopComponent.class, "CTL_MaterialEditorTopComponent")); + setToolTipText(NbBundle.getMessage(MaterialEditorTopComponent.class, "HINT_MaterialEditorTopComponent")); + setActivatedNodes(new Node[]{dataObject.getNodeDelegate()}); + ((AssetDataObject) dataObject).setSaveCookie(saveCookie); + manager = dataObject.getLookup().lookup(ProjectAssetManager.class); + properties = new MaterialProperties(dataObject.getPrimaryFile(), dataObject.getLookup().lookup(ProjectAssetManager.class)); + properties.read(); + setMatDefList(manager.getMatDefs(), properties.getMatDefName()); + try { + jTextArea1.setText(dataObject.getPrimaryFile().asText()); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + jTextArea1.getDocument().addDocumentListener(new DocumentChangeListener()); + + SceneApplication.getApplication().addSceneListener(this); + + sphMesh = new Sphere(32, 32, 2.5f); + sphMesh.setTextureMode(Sphere.TextureMode.Projected); + sphMesh.updateGeometry(32, 32, 2.5f, false, false); + TangentBinormalGenerator.generate(sphMesh); + updateProperties(); + showMaterial(); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel2 = new javax.swing.JPanel(); + jTabbedPane1 = new javax.swing.JTabbedPane(); + jPanel4 = new javax.swing.JPanel(); + jToolBar1 = new javax.swing.JToolBar(); + jLabel2 = new javax.swing.JLabel(); + jTabbedPane2 = new javax.swing.JTabbedPane(); + jScrollPane3 = new javax.swing.JScrollPane(); + texturePanel = new javax.swing.JPanel(); + jScrollPane9 = new javax.swing.JScrollPane(); + statesPanel = new javax.swing.JPanel(); + jTabbedPane3 = new javax.swing.JTabbedPane(); + jScrollPane2 = new javax.swing.JScrollPane(); + optionsPanel = new javax.swing.JPanel(); + jToolBar2 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel3 = new javax.swing.JPanel(); + jComboBox1 = new javax.swing.JComboBox(); + jToolBar3 = new javax.swing.JToolBar(); + jLabel3 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + jCheckBox1 = new javax.swing.JCheckBox(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + + setBackground(new java.awt.Color(204, 204, 204)); + + jTabbedPane1.setBackground(new java.awt.Color(204, 204, 204)); + jTabbedPane1.setMinimumSize(new java.awt.Dimension(0, 0)); + jTabbedPane1.setPreferredSize(new java.awt.Dimension(0, 0)); + + jPanel4.setBackground(new java.awt.Color(204, 204, 204)); + jPanel4.setPreferredSize(new java.awt.Dimension(0, 0)); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + jToolBar1.setToolTipText(org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jToolBar1.toolTipText")); // NOI18N + jToolBar1.setPreferredSize(new java.awt.Dimension(120, 120)); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jLabel2.text")); // NOI18N + jLabel2.setPreferredSize(new java.awt.Dimension(120, 120)); + jLabel2.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseReleased(java.awt.event.MouseEvent evt) { + reloadPreview(evt); + } + }); + jToolBar1.add(jLabel2); + + jScrollPane3.setBackground(new java.awt.Color(204, 204, 204)); + jScrollPane3.setBorder(null); + jScrollPane3.setMinimumSize(new java.awt.Dimension(0, 0)); + + texturePanel.setBackground(new java.awt.Color(204, 204, 204)); + texturePanel.setLayout(new javax.swing.BoxLayout(texturePanel, javax.swing.BoxLayout.PAGE_AXIS)); + jScrollPane3.setViewportView(texturePanel); + + jTabbedPane2.addTab(org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jScrollPane3.TabConstraints.tabTitle"), jScrollPane3); // NOI18N + + jScrollPane9.setBackground(new java.awt.Color(204, 204, 204)); + jScrollPane9.setBorder(null); + + statesPanel.setBackground(new java.awt.Color(204, 204, 204)); + statesPanel.setLayout(new javax.swing.BoxLayout(statesPanel, javax.swing.BoxLayout.PAGE_AXIS)); + jScrollPane9.setViewportView(statesPanel); + + jTabbedPane2.addTab(org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jScrollPane9.TabConstraints.tabTitle"), jScrollPane9); // NOI18N + + jScrollPane2.setBackground(new java.awt.Color(204, 204, 204)); + jScrollPane2.setBorder(null); + jScrollPane2.setMinimumSize(new java.awt.Dimension(220, 0)); + + optionsPanel.setBackground(new java.awt.Color(204, 204, 204)); + optionsPanel.setLayout(new javax.swing.BoxLayout(optionsPanel, javax.swing.BoxLayout.PAGE_AXIS)); + jScrollPane2.setViewportView(optionsPanel); + + jTabbedPane3.addTab(org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jScrollPane2.TabConstraints.tabTitle_1"), jScrollPane2); // NOI18N + + jToolBar2.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar2.setFloatable(false); + jToolBar2.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jLabel1.text")); // NOI18N + jToolBar2.add(jLabel1); + + jPanel3.setBackground(new java.awt.Color(204, 204, 204)); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar2.add(jPanel3); + + jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { " ", "Common/MatDefs/Misc/SolidColor.j3md", "Common/MatDefs/Misc/VertexColor.j3md", "Common/MatDefs/Misc/SimpleTextured.j3md", "Common/MatDefs/Misc/ColoredTextured.j3md", "Common/MatDefs/Misc/Particle.j3md", "Common/MatDefs/Misc/Sky.j3md", "Common/MatDefs/Gui/Gui.j3md", "Common/MatDefs/Light/Lighting.j3md", "Common/MatDefs/Light/Reflection.j3md", "Common/MatDefs/Misc/ShowNormals.j3md", "Common/MatDefs/Hdr/LogLum.j3md", "Common/MatDefs/Hdr/ToneMap.j3md", "Common/MatDefs/Shadow/PreShadow.j3md", "Common/MatDefs/Shadow/PostShadow.j3md" })); + jComboBox1.setMaximumSize(new java.awt.Dimension(32767, 27)); + jComboBox1.setMinimumSize(new java.awt.Dimension(256, 27)); + jComboBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jComboBox1ActionPerformed(evt); + } + }); + jToolBar2.add(jComboBox1); + + jToolBar3.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar3.setFloatable(false); + jToolBar3.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jLabel3.text")); // NOI18N + jToolBar3.add(jLabel3); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar3.add(jPanel1); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jTextField1.text")); // NOI18N + jTextField1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jTextField1ActionPerformed(evt); + } + }); + jToolBar3.add(jTextField1); + + jCheckBox1.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jCheckBox1.text")); // NOI18N + jCheckBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jCheckBox1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jCheckBox1, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jToolBar3, javax.swing.GroupLayout.DEFAULT_SIZE, 452, Short.MAX_VALUE) + .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 452, Short.MAX_VALUE))) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jTabbedPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 223, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTabbedPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 349, Short.MAX_VALUE)) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(jCheckBox1) + .addGap(3, 3, 3)) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(3, 3, 3) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 297, Short.MAX_VALUE) + .addComponent(jTabbedPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 297, Short.MAX_VALUE))) + ); + + jTabbedPane1.addTab(org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jPanel4.TabConstraints.tabTitle"), jPanel4); // NOI18N + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jScrollPane1.setViewportView(jTextArea1); + + jTabbedPane1.addTab(org.openide.util.NbBundle.getMessage(MaterialEditorTopComponent.class, "MaterialEditorTopComponent.jScrollPane1.TabConstraints.tabTitle"), jScrollPane1); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 593, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 466, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed + if (properties != null) { + updateProperties = true; + properties.setMatDefName((String) jComboBox1.getSelectedItem()); + String string = properties.getUpdatedContent(); + jTextArea1.setText(string); + } + }//GEN-LAST:event_jComboBox1ActionPerformed + + private void reloadPreview(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_reloadPreview + showMaterial(); + }//GEN-LAST:event_reloadPreview + + private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed + if (properties != null) { + properties.setName(jTextField1.getText()); + String string = properties.getUpdatedContent(); + jTextArea1.setText(string); + } +}//GEN-LAST:event_jTextField1ActionPerformed + + private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed + saveImmediate = jCheckBox1.isSelected(); + }//GEN-LAST:event_jCheckBox1ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JComboBox jComboBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JScrollPane jScrollPane9; + private javax.swing.JTabbedPane jTabbedPane1; + private javax.swing.JTabbedPane jTabbedPane2; + private javax.swing.JTabbedPane jTabbedPane3; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextField jTextField1; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToolBar jToolBar2; + private javax.swing.JToolBar jToolBar3; + private javax.swing.JPanel optionsPanel; + private javax.swing.JPanel statesPanel; + private javax.swing.JPanel texturePanel; + // End of variables declaration//GEN-END:variables + + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized MaterialEditorTopComponent getDefault() { + if (instance == null) { + instance = new MaterialEditorTopComponent(); + } + return instance; + } + + /** + * Obtain the MaterialEditorTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized MaterialEditorTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(MaterialEditorTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof MaterialEditorTopComponent) { + return (MaterialEditorTopComponent) win; + } + Logger.getLogger(MaterialEditorTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER;//ALWAYS; + } + + @Override + public HelpCtx getHelpCtx() { + HelpCtx ctx = new HelpCtx("sdk.material_editing"); + //this call is for single components: + //HelpCtx.setHelpIDString(this, "com.jme3.gde.core.sceneviewer"); + return ctx; + } + + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + SceneApplication.getApplication().removeSceneListener(this); + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + p.setProperty("MaterialFileName", materialFileName); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + try { + String version = p.getProperty("version"); + materialFileName = p.getProperty("MaterialFileName"); + // TODO read your settings according to their version + dataObject = DataObject.find(FileUtil.toFileObject(new File(materialFileName))); + initWindow(); + } catch (DataObjectNotFoundException ex) { + Exceptions.printStackTrace(ex); + } + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + private class DocumentChangeListener implements DocumentListener { + + String newline = "\n"; + + public void insertUpdate(DocumentEvent e) { + checkSave(); + } + + public void removeUpdate(DocumentEvent e) { + checkSave(); + } + + public void changedUpdate(DocumentEvent e) { + checkSave(); + } + + public void updateLog(DocumentEvent e, String action) { + } + + private void checkSave() { + if (saveImmediate) { + try { + saveCookie.save(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } else { + dataObject.setModified(true); + } + if (updateProperties) { + updateProperties(); + updateProperties = false; + } + } + } + + private class SaveCookieImpl implements SaveCookie { + + public void save() throws IOException { + String text = jTextArea1.getText(); + properties.setAsText(text); + dataObject.setModified(false); + showMaterial(); + } + } + + public void setMatDefList(final String[] strings, String selected) { + MaterialProperties prop = properties; + properties = null; + jComboBox1.removeAllItems(); + jComboBox1.addItem(""); + + for (int i = 0; i < strings.length; i++) { + String string = strings[i]; + jComboBox1.addItem(string); + } + + jComboBox1.addItem("Common/MatDefs/Light/Lighting.j3md"); + jComboBox1.addItem("Common/MatDefs/Misc/Unshaded.j3md"); + jComboBox1.addItem("Common/MatDefs/Misc/Particle.j3md"); + jComboBox1.addItem("Common/MatDefs/Misc/Sky.j3md"); + jComboBox1.addItem("Common/MatDefs/Gui/Gui.j3md"); + jComboBox1.addItem("Common/MatDefs/Terrain/Terrain.j3md"); +// jComboBox1.addItem("Common/MatDefs/Misc/ShowNormals.j3md"); + jComboBox1.setSelectedItem(selected); + properties = prop; + } + + private void updateProperties() { + for (int i = 0; i < optionsPanel.getComponents().length; i++) { + Component component = optionsPanel.getComponents()[i]; + if (component instanceof MaterialPropertyWidget) { + ((MaterialPropertyWidget) component).registerChangeListener(null); + } + } + for (int i = 0; i < texturePanel.getComponents().length; i++) { + Component component = texturePanel.getComponents()[i]; + if (component instanceof MaterialPropertyWidget) { + ((MaterialPropertyWidget) component).registerChangeListener(null); + } + } + optionsPanel.removeAll(); + texturePanel.removeAll(); + List optionList = new LinkedList(); + List colorList = new LinkedList(); + List valueList = new LinkedList(); + List textureList = new LinkedList(); + List otherList = new LinkedList(); + for (Iterator> it = properties.getParameterMap().entrySet().iterator(); it.hasNext();) { + Entry entry = it.next(); + MaterialPropertyWidget widget = WidgetFactory.getWidget(entry.getValue(), manager); + widget.registerChangeListener(this); + if ("Boolean".equals(entry.getValue().getType())) { + optionList.add(widget); + } else if ("Texture2D".equals(entry.getValue().getType())) { + textureList.add(widget); + } else if ("Color".equals(entry.getValue().getType())) { + colorList.add(widget); + } else if ("Float".equals(entry.getValue().getType())) { + valueList.add(widget); + } else if ("Int".equals(entry.getValue().getType())) { + valueList.add(widget); + } else { + otherList.add(widget); + } + } + for (Iterator it = textureList.iterator(); it.hasNext();) { + Component component = it.next(); + texturePanel.add(component); + } + for (Iterator it = optionList.iterator(); it.hasNext();) { + Component component = it.next(); + optionsPanel.add(component); + } + for (Iterator it = colorList.iterator(); it.hasNext();) { + Component component = it.next(); + texturePanel.add(component); + } + for (Iterator it = valueList.iterator(); it.hasNext();) { + Component component = it.next(); + optionsPanel.add(component); + } + for (Iterator it = otherList.iterator(); it.hasNext();) { + Component component = it.next(); + optionsPanel.add(component); + } + jScrollPane2.repaint(); + jScrollPane3.repaint(); + setDisplayName(properties.getName() + " - " + properties.getMaterialPath()); + MaterialProperties prop = properties; + properties = null; + jTextField1.setText(prop.getName()); + properties = prop; + updateStates(); + } + + private void updateStates() { + for (int i = 0; i < statesPanel.getComponents().length; i++) { + Component component = statesPanel.getComponents()[i]; + if (component instanceof MaterialPropertyWidget) { + ((MaterialPropertyWidget) component).registerChangeListener(null); + } + } + statesPanel.removeAll(); + for (Iterator> it = properties.getStateMap().entrySet().iterator(); it.hasNext();) { + Entry entry = it.next(); + MaterialPropertyWidget widget = WidgetFactory.getWidget(entry.getValue(), manager); + widget.registerChangeListener(this); + statesPanel.add(widget); + } + } + + private void showMaterial() { + try { + AssetKey key = new AssetKey(manager.getRelativeAssetPath(materialFileName)); + Geometry geom = new Geometry("TestSphere", sphMesh); + ((DesktopAssetManager) manager.getManager()).deleteFromCache(key); + geom.setMaterial((Material) manager.getManager().loadAsset(key)); + if (geom.getMaterial() != null) { + PreviewRequest request = new PreviewRequest(this, geom); + SceneApplication.getApplication().createPreview(request); + } + } catch (Exception e) { + } + } + + public void sceneRequested(SceneRequest request) { + } + + public boolean sceneClose(SceneRequest request) { + return true; + } + + public void previewRequested(PreviewRequest request) { + if (request.getRequester() == this) { + final ImageIcon icon = new ImageIcon(request.getImage()); + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jLabel2.setIcon(icon); + } + }); + } + } + + public void propertyChanged(MaterialProperty property) { + String string = properties.getUpdatedContent(); + jTextArea1.setText(string); + } +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialOpenSupport.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialOpenSupport.java new file mode 100644 index 000000000..ce1aecc5d --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/MaterialOpenSupport.java @@ -0,0 +1,30 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.materials.multiview; + +import com.jme3.gde.materials.JMEMaterialDataObject; +import org.openide.cookies.CloseCookie; +import org.openide.cookies.OpenCookie; +import org.openide.loaders.OpenSupport; +import org.openide.windows.CloneableTopComponent; + +/** + * + * @author normenhansen + */ +public class MaterialOpenSupport extends OpenSupport implements OpenCookie, CloseCookie { + + public MaterialOpenSupport(JMEMaterialDataObject.Entry entry) { + super(entry); + } + + protected CloneableTopComponent createCloneableTopComponent() { + JMEMaterialDataObject dobj = (JMEMaterialDataObject) entry.getDataObject(); + MaterialEditorTopComponent tc = new MaterialEditorTopComponent(dobj); + return tc; + } + +} \ No newline at end of file diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/BooleanPanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/BooleanPanel.form new file mode 100644 index 000000000..9e91c7f80 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/BooleanPanel.form @@ -0,0 +1,103 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/BooleanPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/BooleanPanel.java new file mode 100644 index 000000000..3754221ea --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/BooleanPanel.java @@ -0,0 +1,126 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * NumberPanel.java + * + * Created on 14.06.2010, 16:42:25 + */ +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.materials.MaterialProperty; + +/** + * + * @author normenhansen + */ +public class BooleanPanel extends MaterialPropertyWidget { + + /** Creates new form NumberPanel */ + public BooleanPanel() { + initComponents(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jCheckBox1 = new javax.swing.JCheckBox(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + jToolBar1.setPreferredSize(new java.awt.Dimension(81, 27)); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(BooleanPanel.class, "BooleanPanel.jLabel1.text")); // NOI18N + jLabel1.setPreferredSize(new java.awt.Dimension(100, 25)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setMinimumSize(new java.awt.Dimension(0, 0)); + jPanel1.setPreferredSize(new java.awt.Dimension(32767, 23)); + jPanel1.setSize(new java.awt.Dimension(10, 0)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 23, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(BooleanPanel.class, "BooleanPanel.jCheckBox1.text")); // NOI18N + jCheckBox1.setFocusable(false); + jCheckBox1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jCheckBox1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jCheckBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + valueChanged(evt); + } + }); + jToolBar1.add(jCheckBox1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void valueChanged(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_valueChanged + // TODO add your handling code here: + if (jCheckBox1.isSelected()) { + property.setValue("true"); + } else { + property.setValue("false"); + } + fireChanged(); + }//GEN-LAST:event_valueChanged + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jLabel1.setText(property.getName()); + jLabel1.setToolTipText(property.getName()); + MaterialProperty prop = property; + property = null; + if ("true".equals(prop.getValue())) { + jCheckBox1.setSelected(true); + } else { + jCheckBox1.setSelected(false); + } + property = prop; + } + }); + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/Bundle.properties b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/Bundle.properties new file mode 100644 index 000000000..3ad7c9c29 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/Bundle.properties @@ -0,0 +1,33 @@ +SelectionPanel.jLabel1.text=jLabel1 +TextPanel.jTextField1.text=jTextField1 +# To change this template, choose Tools | Templates +# and open the template in the editor. +TextPanel.jLabel1.text=jLabel1 +# To change this template, choose Tools | Templates +# and open the template in the editor. +BooleanPanel.jLabel1.text=jLabel1 +BooleanPanel.jCheckBox1.text= +ColorRGBADialog.jButton1.text=OK +ColorRGBADialog.jButton2.text=Cancel +ColorRGBADialog.alphaLabel.text=Alpha: +# To change this template, choose Tools | Templates +# and open the template in the editor. +ColorPanel.jLabel1.text=jLabel1 +ColorPanel.jTextField1.text=jTextField1 +ColorPanel.jButton1.text=select.. +TexturePanel.jLabel1.text=jLabel1 +TexturePanel.jButton1.text=set.. +TexturePanel.jLabel2.text= +TexturePanel.jButton2.text=x +# To change this template, choose Tools | Templates +# and open the template in the editor. +FloatPanel.jLabel1.text=jLabel1 +# To change this template, choose Tools | Templates +# and open the template in the editor. +IntPanel.jLabel1.text=jLabel1 +TexturePanel.jCheckBox1.text=flip +# To change this template, choose Tools | Templates +# and open the template in the editor. +OnOffPanel.jLabel1.text=jLabel1 +OnOffPanel.jCheckBox1.text= +TexturePanel.jCheckBox2.text=repeat diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorPanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorPanel.form new file mode 100644 index 000000000..f8bf1ee56 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorPanel.form @@ -0,0 +1,113 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorPanel.java new file mode 100644 index 000000000..2883e0a02 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorPanel.java @@ -0,0 +1,140 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * NumberPanel.java + * + * Created on 14.06.2010, 16:42:25 + */ + +package com.jme3.gde.materials.multiview.widgets; + +import javax.swing.JFrame; + +/** + * + * @author normenhansen + */ +public class ColorPanel extends MaterialPropertyWidget { + + /** Creates new form NumberPanel */ + public ColorPanel() { + initComponents(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(ColorPanel.class, "ColorPanel.jLabel1.text")); // NOI18N + jLabel1.setPreferredSize(new java.awt.Dimension(100, 0)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setMinimumSize(new java.awt.Dimension(0, 0)); + jPanel1.setPreferredSize(new java.awt.Dimension(10, 0)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 8, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 28, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(ColorPanel.class, "ColorPanel.jTextField1.text")); // NOI18N + jTextField1.setMaximumSize(new java.awt.Dimension(110, 2147483647)); + jTextField1.setPreferredSize(new java.awt.Dimension(110, 28)); + jTextField1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + textChanged(evt); + } + }); + jToolBar1.add(jTextField1); + + jButton1.setText(org.openide.util.NbBundle.getMessage(ColorPanel.class, "ColorPanel.jButton1.text")); // NOI18N + jButton1.setFocusable(false); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar1.add(jButton1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 248, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + // TODO add your handling code here: + ColorRGBADialog dialog=new ColorRGBADialog(new JFrame(), true); + dialog.setLocationRelativeTo(null); + dialog.setVisible(true); + if(dialog.getColor()!=null){ + jTextField1.setText(dialog.getColor()); + property.setValue(jTextField1.getText()); + fireChanged(); + } + + }//GEN-LAST:event_jButton1ActionPerformed + + private void textChanged(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_textChanged + property.setValue(jTextField1.getText()); + fireChanged(); + }//GEN-LAST:event_textChanged + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jLabel1.setText(property.getName()); + jLabel1.setToolTipText(property.getName()); + jTextField1.setText(property.getValue()); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JTextField jTextField1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorRGBADialog.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorRGBADialog.form new file mode 100644 index 000000000..dcf4e8353 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorRGBADialog.form @@ -0,0 +1,97 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorRGBADialog.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorRGBADialog.java new file mode 100644 index 000000000..732320ec8 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/ColorRGBADialog.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2009-2010 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. + */ + +/* + * ColorRGBADialog.java + * + * Created on 06.04.2010, 20:58:59 + */ +package com.jme3.gde.materials.multiview.widgets; + +import java.awt.Color; + +/** + * + * @author normenhansen + */ +public class ColorRGBADialog extends javax.swing.JDialog { + private String color; + + /** Creates new form ColorRGBADialog */ + public ColorRGBADialog(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); +// alphaSlider.setValue(Math.round(((ColorRGBA)editor.getValue()).getAlpha()*100)); + } + + private void convertColor() { + Color cColor = jColorChooser1.getColor(); + float[] floats = new float[4]; + cColor.getComponents(floats); + String str=new String(floats[0]+" "+ floats[1]+" "+ floats[2]+" "+ ((float)alphaSlider.getValue())/100.0f); + color=str; + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jColorChooser1 = new javax.swing.JColorChooser(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + jToolBar1 = new javax.swing.JToolBar(); + alphaLabel = new javax.swing.JLabel(); + alphaSlider = new javax.swing.JSlider(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jButton1.setText(org.openide.util.NbBundle.getMessage(ColorRGBADialog.class, "ColorRGBADialog.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText(org.openide.util.NbBundle.getMessage(ColorRGBADialog.class, "ColorRGBADialog.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + alphaLabel.setText(org.openide.util.NbBundle.getMessage(ColorRGBADialog.class, "ColorRGBADialog.alphaLabel.text")); // NOI18N + jToolBar1.add(alphaLabel); + + alphaSlider.setValue(100); + jToolBar1.add(alphaSlider); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1)) + .addComponent(jColorChooser1, javax.swing.GroupLayout.DEFAULT_SIZE, 496, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jColorChooser1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1) + .addComponent(jButton2)) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))) + ); + + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + convertColor(); + dispose(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + dispose(); + }//GEN-LAST:event_jButton2ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel alphaLabel; + private javax.swing.JSlider alphaSlider; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JColorChooser jColorChooser1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables + + /** + * @return the color + */ + public String getColor() { + return color; + } + + public void setColor(String color){ + this.color=color; + } +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/FloatPanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/FloatPanel.form new file mode 100644 index 000000000..6ca801754 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/FloatPanel.form @@ -0,0 +1,94 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/FloatPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/FloatPanel.java new file mode 100644 index 000000000..ddd4b8007 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/FloatPanel.java @@ -0,0 +1,119 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * NumberPanel.java + * + * Created on 14.06.2010, 16:42:25 + */ +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.materials.MaterialProperty; + +/** + * + * @author normenhansen + */ +public class FloatPanel extends MaterialPropertyWidget { + + /** Creates new form NumberPanel */ + public FloatPanel() { + initComponents(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jSpinner1 = new javax.swing.JSpinner(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(FloatPanel.class, "FloatPanel.jLabel1.text")); // NOI18N + jLabel1.setMaximumSize(new java.awt.Dimension(100, 16)); + jLabel1.setPreferredSize(new java.awt.Dimension(100, 0)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setPreferredSize(new java.awt.Dimension(100, 25)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 50, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 28, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + jSpinner1.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(0.0f), null, null, Float.valueOf(1.0f))); + jSpinner1.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + valueChanged(evt); + } + }); + jToolBar1.add(jSpinner1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 168, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void valueChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_valueChanged + if (property == null) { + return; + } + property.setValue(jSpinner1.getValue() + ""); + fireChanged(); + }//GEN-LAST:event_valueChanged + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jLabel1.setText(property.getName()); + jLabel1.setToolTipText(property.getName()); + MaterialProperty prop = property; + property = null; + try { + jSpinner1.setValue(Float.parseFloat(prop.getValue())); + } catch (Exception e) { + jSpinner1.setValue(0); + } + property = prop; + } + }); + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JSpinner jSpinner1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/IntPanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/IntPanel.form new file mode 100644 index 000000000..1091d807f --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/IntPanel.form @@ -0,0 +1,97 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/IntPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/IntPanel.java new file mode 100644 index 000000000..09eb0de37 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/IntPanel.java @@ -0,0 +1,120 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * NumberPanel.java + * + * Created on 14.06.2010, 16:42:25 + */ +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.materials.MaterialProperty; + +/** + * + * @author normenhansen + */ +public class IntPanel extends MaterialPropertyWidget { + + /** Creates new form NumberPanel */ + public IntPanel() { + initComponents(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jSpinner1 = new javax.swing.JSpinner(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(IntPanel.class, "IntPanel.jLabel1.text")); // NOI18N + jLabel1.setMaximumSize(new java.awt.Dimension(100, 16)); + jLabel1.setPreferredSize(new java.awt.Dimension(100, 0)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setPreferredSize(new java.awt.Dimension(100, 0)); + jPanel1.setSize(new java.awt.Dimension(0, 0)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 25, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 28, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + jSpinner1.setModel(new javax.swing.SpinnerNumberModel()); + jSpinner1.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + valueChanged(evt); + } + }); + jToolBar1.add(jSpinner1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 129, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void valueChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_valueChanged + if (property == null) { + return; + } + property.setValue(jSpinner1.getValue() + ""); + fireChanged(); + }//GEN-LAST:event_valueChanged + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jLabel1.setText(property.getName()); + jLabel1.setToolTipText(property.getName()); + MaterialProperty prop=property; + property=null; + try { + jSpinner1.setValue(Integer.parseInt(prop.getValue())); + } catch (Exception e) { + jSpinner1.setValue(0); + } + property=prop; + } + }); + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JSpinner jSpinner1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/MaterialPropertyWidget.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/MaterialPropertyWidget.java new file mode 100644 index 000000000..c8c95e666 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/MaterialPropertyWidget.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.materials.MaterialProperties; +import com.jme3.gde.materials.MaterialProperty; +import javax.swing.JPanel; + +/** + * + * @author normenhansen + */ +public abstract class MaterialPropertyWidget extends JPanel{ + protected MaterialProperty property; + private MaterialWidgetListener listener; + + public void registerChangeListener(MaterialWidgetListener listener){ + this.listener=listener; + } + + protected void fireChanged(){ + if(listener==null) return; + listener.propertyChanged(property); + } + + /** + * @return the properties + */ + public MaterialProperty getProperty() { + return property; + } + + /** + * @param properties the properties to set + */ + public void setProperty(MaterialProperty property) { + this.property = property; + readProperty(); + } + + protected abstract void readProperty(); + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/MaterialWidgetListener.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/MaterialWidgetListener.java new file mode 100644 index 000000000..627201453 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/MaterialWidgetListener.java @@ -0,0 +1,18 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.materials.MaterialProperty; + +/** + * + * @author normenhansen + */ +public interface MaterialWidgetListener { + + public void propertyChanged(MaterialProperty property); + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/OnOffPanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/OnOffPanel.form new file mode 100644 index 000000000..da43ab76a --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/OnOffPanel.form @@ -0,0 +1,103 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/OnOffPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/OnOffPanel.java new file mode 100644 index 000000000..31998b5c9 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/OnOffPanel.java @@ -0,0 +1,126 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * NumberPanel.java + * + * Created on 14.06.2010, 16:42:25 + */ +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.materials.MaterialProperty; + +/** + * + * @author normenhansen + */ +public class OnOffPanel extends MaterialPropertyWidget { + + /** Creates new form NumberPanel */ + public OnOffPanel() { + initComponents(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jCheckBox1 = new javax.swing.JCheckBox(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + jToolBar1.setPreferredSize(new java.awt.Dimension(81, 27)); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(OnOffPanel.class, "OnOffPanel.jLabel1.text")); // NOI18N + jLabel1.setPreferredSize(new java.awt.Dimension(100, 25)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setMinimumSize(new java.awt.Dimension(0, 0)); + jPanel1.setPreferredSize(new java.awt.Dimension(32767, 23)); + jPanel1.setSize(new java.awt.Dimension(10, 0)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 23, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(OnOffPanel.class, "OnOffPanel.jCheckBox1.text")); // NOI18N + jCheckBox1.setFocusable(false); + jCheckBox1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jCheckBox1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jCheckBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + valueChanged(evt); + } + }); + jToolBar1.add(jCheckBox1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void valueChanged(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_valueChanged + // TODO add your handling code here: + if (jCheckBox1.isSelected()) { + property.setValue("On"); + } else { + property.setValue("Off"); + } + fireChanged(); + }//GEN-LAST:event_valueChanged + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jLabel1.setText(property.getName()); + jLabel1.setToolTipText(property.getName()); + MaterialProperty prop = property; + property = null; + if ("On".equals(prop.getValue())) { + jCheckBox1.setSelected(true); + } else { + jCheckBox1.setSelected(false); + } + property = prop; + } + }); + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/SelectionPanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/SelectionPanel.form new file mode 100644 index 000000000..88a405ad2 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/SelectionPanel.form @@ -0,0 +1,114 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/SelectionPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/SelectionPanel.java new file mode 100644 index 000000000..f9f794ede --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/SelectionPanel.java @@ -0,0 +1,137 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SelectionPanel.java + * + * Created on 14.06.2010, 16:52:22 + */ + +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.materials.MaterialProperty; + +/** + * + * @author normenhansen + */ +public class SelectionPanel extends MaterialPropertyWidget { + + /** Creates new form SelectionPanel */ + public SelectionPanel() { + initComponents(); + } + + public void setSelectionList(final String[] strings){ + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + MaterialProperty prop=property; + property=null; + jComboBox1.removeAllItems(); + jComboBox1.addItem(""); + for (int i = 0; i < strings.length; i++) { + String string = strings[i]; + jComboBox1.addItem(string); + } + property=prop; + } + }); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jComboBox1 = new javax.swing.JComboBox(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + jToolBar1.setMinimumSize(new java.awt.Dimension(212, 32)); + jToolBar1.setPreferredSize(new java.awt.Dimension(212, 32)); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(SelectionPanel.class, "SelectionPanel.jLabel1.text")); // NOI18N + jLabel1.setPreferredSize(new java.awt.Dimension(100, 16)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setPreferredSize(new java.awt.Dimension(10, 0)); + jPanel1.setSize(new java.awt.Dimension(0, 0)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 56, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 28, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + jComboBox1.setMaximumSize(new java.awt.Dimension(200, 32767)); + jComboBox1.setMinimumSize(new java.awt.Dimension(0, 0)); + jComboBox1.setPreferredSize(new java.awt.Dimension(200, 27)); + jComboBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + selectTexture(evt); + } + }); + jToolBar1.add(jComboBox1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void selectTexture(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectTexture + if(property!=null){ + property.setValue((String)jComboBox1.getSelectedItem()); + fireChanged(); + } + }//GEN-LAST:event_selectTexture + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + jLabel1.setText(property.getName()); + jLabel1.setToolTipText(property.getName()); + MaterialProperty prop=property; + property=null; + jComboBox1.setSelectedItem(prop.getValue()); + property=prop; + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JComboBox jComboBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TextPanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TextPanel.form new file mode 100644 index 000000000..af906516b --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TextPanel.form @@ -0,0 +1,97 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TextPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TextPanel.java new file mode 100644 index 000000000..8319573af --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TextPanel.java @@ -0,0 +1,114 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * NumberPanel.java + * + * Created on 14.06.2010, 16:42:25 + */ + +package com.jme3.gde.materials.multiview.widgets; + +import java.lang.reflect.InvocationTargetException; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +public class TextPanel extends MaterialPropertyWidget { + + /** Creates new form NumberPanel */ + public TextPanel() { + initComponents(); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(TextPanel.class, "TextPanel.jLabel1.text")); // NOI18N + jLabel1.setPreferredSize(new java.awt.Dimension(100, 0)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setPreferredSize(new java.awt.Dimension(10, 0)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 4, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 28, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(TextPanel.class, "TextPanel.jTextField1.text")); // NOI18N + jTextField1.setMaximumSize(new java.awt.Dimension(200, 2147483647)); + jTextField1.setPreferredSize(new java.awt.Dimension(200, 28)); + jTextField1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + textChanged(evt); + } + }); + jToolBar1.add(jTextField1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 185, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void textChanged(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_textChanged + property.setValue(jTextField1.getText()); + fireChanged(); + }//GEN-LAST:event_textChanged + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jLabel1.setToolTipText(property.getName() + " (" + property.getType() + ")"); + jLabel1.setText(property.getName() + " (" + property.getType() + ")"); + jTextField1.setText(property.getValue()); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JTextField jTextField1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables + +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.form new file mode 100644 index 000000000..2bf1c2648 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.form @@ -0,0 +1,159 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.java new file mode 100644 index 000000000..05c4d1b86 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.java @@ -0,0 +1,253 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SelectionPanel.java + * + * Created on 14.06.2010, 16:52:22 + */ +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.sceneexplorer.nodes.properties.TexturePropertyEditor; +import com.jme3.gde.materials.MaterialProperty; +import java.awt.Component; + +/** + * + * @author normenhansen + */ +public class TexturePanel extends MaterialPropertyWidget { + + private TexturePropertyEditor editor; + private ProjectAssetManager manager; + private boolean flip = false; + private boolean repeat = false; + private String textureName = null; + + /** Creates new form SelectionPanel */ + public TexturePanel(ProjectAssetManager manager) { + this.manager = manager; + editor = new TexturePropertyEditor(manager); + initComponents(); + } + + private String getName(String path) { + int idx = path.lastIndexOf("/"); + if (idx != -1 && path.length() > idx + 1) { + path = path.substring(idx + 1, path.length()); + } + if (path.length() > 15) { + path = path.substring(0, 15) + ".."; + } + return path; + } + + private void updateFlipRepeat() { + if (flip && repeat) { + property.setValue("Flip Repeat " + textureName); + jLabel2.setToolTipText("Flip Repeat " + textureName); + } else if (flip) { + property.setValue("Flip " + textureName); + jLabel2.setToolTipText("Flip " + textureName); + } else if (repeat) { + property.setValue("Repeat " + textureName); + jLabel2.setToolTipText("Repeat " + textureName); + } else { + property.setValue(textureName); + } + } + + private String getTextureName(String string) { + string = string.replaceFirst("Flip ", ""); + return string.replaceFirst("Repeat ", ""); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + jButton1 = new javax.swing.JButton(); + jCheckBox1 = new javax.swing.JCheckBox(); + jCheckBox2 = new javax.swing.JCheckBox(); + jButton2 = new javax.swing.JButton(); + + setBackground(new java.awt.Color(204, 204, 204)); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + jToolBar1.setMinimumSize(new java.awt.Dimension(212, 32)); + jToolBar1.setPreferredSize(new java.awt.Dimension(212, 32)); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(TexturePanel.class, "TexturePanel.jLabel1.text")); // NOI18N + jLabel1.setPreferredSize(new java.awt.Dimension(100, 0)); + jToolBar1.add(jLabel1); + + jPanel1.setBackground(new java.awt.Color(204, 204, 204)); + jPanel1.setPreferredSize(new java.awt.Dimension(10, 0)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 1, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 28, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel1); + + jLabel2.setFont(new java.awt.Font("Courier", 0, 13)); // NOI18N + jLabel2.setText(org.openide.util.NbBundle.getMessage(TexturePanel.class, "TexturePanel.jLabel2.text")); // NOI18N + jLabel2.setMaximumSize(new java.awt.Dimension(200, 30)); + jLabel2.setPreferredSize(new java.awt.Dimension(200, 14)); + jToolBar1.add(jLabel2); + + jButton1.setText(org.openide.util.NbBundle.getMessage(TexturePanel.class, "TexturePanel.jButton1.text")); // NOI18N + jButton1.setFocusable(false); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar1.add(jButton1); + + jCheckBox1.setFont(new java.awt.Font("Lucida Grande", 0, 10)); // NOI18N + jCheckBox1.setText(org.openide.util.NbBundle.getMessage(TexturePanel.class, "TexturePanel.jCheckBox1.text")); // NOI18N + jCheckBox1.setFocusable(false); + jCheckBox1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jCheckBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jCheckBox1ActionPerformed(evt); + } + }); + jToolBar1.add(jCheckBox1); + + jCheckBox2.setFont(new java.awt.Font("Lucida Grande", 0, 10)); // NOI18N + jCheckBox2.setText(org.openide.util.NbBundle.getMessage(TexturePanel.class, "TexturePanel.jCheckBox2.text")); // NOI18N + jCheckBox2.setFocusable(false); + jCheckBox2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jCheckBox2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jCheckBox2ActionPerformed(evt); + } + }); + jToolBar1.add(jCheckBox2); + + jButton2.setText(org.openide.util.NbBundle.getMessage(TexturePanel.class, "TexturePanel.jButton2.text")); // NOI18N + jButton2.setFocusable(false); + jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + jToolBar1.add(jButton2); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 261, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + Component view = editor.getCustomEditor(); + view.setVisible(true); + if (editor.getValue() != null) { + textureName = editor.getAsText(); + jLabel2.setText(getName(textureName)); + updateFlipRepeat(); + fireChanged(); + } + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + textureName = ""; + jLabel2.setText(""); + jLabel2.setToolTipText(""); + property.setValue(""); + fireChanged(); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed + if (property == null) { + return; + } + flip = jCheckBox1.isSelected(); + updateFlipRepeat(); + fireChanged(); + }//GEN-LAST:event_jCheckBox1ActionPerformed + + private void jCheckBox2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox2ActionPerformed + if (property == null) { + return; + } + repeat = jCheckBox2.isSelected(); + updateFlipRepeat(); + fireChanged(); + }//GEN-LAST:event_jCheckBox2ActionPerformed + + @Override + protected void readProperty() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (property.getValue().startsWith("Flip Repeat ")) { + flip = true; + repeat = true; + textureName = property.getValue().replaceFirst("Flip Repeat ", "").trim(); + } else if (property.getValue().startsWith("Flip ")) { + flip = true; + textureName = property.getValue().replaceFirst("Flip ", "").trim(); + } else if (property.getValue().startsWith("Repeat ")) { + repeat = true; + textureName = property.getValue().replaceFirst("Repeat ", "").trim(); + } else { + textureName = property.getValue(); + } + jLabel1.setText(property.getName()); + jLabel1.setToolTipText(property.getName()); + jLabel2.setText(getName(textureName)); + jLabel2.setToolTipText(property.getValue()); + MaterialProperty prop = property; + property = null; + jCheckBox1.setSelected(flip); + jCheckBox2.setSelected(repeat); + property = prop; + } + }); + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JCheckBox jCheckBox2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JPanel jPanel1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/WidgetFactory.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/WidgetFactory.java new file mode 100644 index 000000000..ea7647e4a --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/WidgetFactory.java @@ -0,0 +1,76 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.materials.multiview.widgets; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.materials.MaterialProperty; +import com.jme3.material.RenderState.BlendMode; +import com.jme3.material.RenderState.FaceCullMode; + +/** + * + * @author normenhansen + */ +public class WidgetFactory { + + public static MaterialPropertyWidget getWidget(MaterialProperty prop, ProjectAssetManager manager){ + MaterialPropertyWidget widget; + if("Texture2D".equals(prop.getType())){ + widget=new TexturePanel(manager); + widget.setProperty(prop); + return widget; + } + else if("Boolean".equals(prop.getType())){ + widget=new BooleanPanel(); + widget.setProperty(prop); + return widget; + } + else if("OnOff".equals(prop.getType())){ + widget=new OnOffPanel(); + widget.setProperty(prop); + return widget; + } + else if("Float".equals(prop.getType())){ + widget=new FloatPanel(); + widget.setProperty(prop); + return widget; + } + else if("Int".equals(prop.getType())){ + widget=new IntPanel(); + widget.setProperty(prop); + return widget; + } + else if("Color".equals(prop.getType())){ + widget=new ColorPanel(); + widget.setProperty(prop); + return widget; + } + else if("FaceCullMode".equals(prop.getType())){ + widget=new SelectionPanel(); + String[] strings=new String[FaceCullMode.values().length]; + for (int i = 0; i < strings.length; i++) { + strings[i]=FaceCullMode.values()[i].name(); + } + ((SelectionPanel)widget).setSelectionList(strings); + widget.setProperty(prop); + return widget; + } + else if("BlendMode".equals(prop.getType())){ + widget=new SelectionPanel(); + String[] strings=new String[BlendMode.values().length]; + for (int i = 0; i < strings.length; i++) { + strings[i]=BlendMode.values()[i].name(); + } + ((SelectionPanel)widget).setSelectionList(strings); + widget.setProperty(prop); + return widget; + } + widget = new TextPanel(); + widget.setProperty(prop); + return widget; + } + +} diff --git a/sdk/jme3-model-importer/build.xml b/sdk/jme3-model-importer/build.xml new file mode 100644 index 000000000..053902940 --- /dev/null +++ b/sdk/jme3-model-importer/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.modelimporter. + + diff --git a/sdk/jme3-model-importer/manifest.mf b/sdk/jme3-model-importer/manifest.mf new file mode 100644 index 000000000..e9cda5a6a --- /dev/null +++ b/sdk/jme3-model-importer/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.modelimporter +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/modelimporter/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/modelimporter/Bundle.properties + diff --git a/sdk/jme3-model-importer/nbproject/build-impl.xml b/sdk/jme3-model-importer/nbproject/build-impl.xml new file mode 100644 index 000000000..43639cec8 --- /dev/null +++ b/sdk/jme3-model-importer/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-model-importer/nbproject/genfiles.properties b/sdk/jme3-model-importer/nbproject/genfiles.properties new file mode 100644 index 000000000..735fdcf6b --- /dev/null +++ b/sdk/jme3-model-importer/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=61a6f3dc +build.xml.script.CRC32=b6310686 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=61a6f3dc +nbproject/build-impl.xml.script.CRC32=4db64ed5 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-model-importer/nbproject/project.properties b/sdk/jme3-model-importer/nbproject/project.properties new file mode 100644 index 000000000..833863ee2 --- /dev/null +++ b/sdk/jme3-model-importer/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.8.0 diff --git a/sdk/jme3-model-importer/nbproject/project.xml b/sdk/jme3-model-importer/nbproject/project.xml new file mode 100644 index 000000000..8a3cbdfe4 --- /dev/null +++ b/sdk/jme3-model-importer/nbproject/project.xml @@ -0,0 +1,105 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.modelimporter + + + + com.jme3.gde.core + + + + 1 + 0.9 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.7 + + + + org.netbeans.api.progress + + + + 1 + 1.19 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.30 + + + + org.openide.awt + + + + 7.23 + + + + org.openide.dialogs + + + + 7.14 + + + + org.openide.filesystems + + + + 7.37 + + + + org.openide.loaders + + + + 7.15 + + + + org.openide.nodes + + + + 7.15 + + + + org.openide.util + + + + 8.5 + + + + org.openide.util.lookup + + + + 8.2 + + + + + + + diff --git a/sdk/jme3-model-importer/nbproject/suite.properties b/sdk/jme3-model-importer/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-model-importer/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/103_.png b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/103_.png new file mode 100644 index 000000000..424d16abd Binary files /dev/null and b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/103_.png differ diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/103_24.png b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/103_24.png new file mode 100644 index 000000000..64626c5cf Binary files /dev/null and b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/103_24.png differ diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/Bundle.properties b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/Bundle.properties new file mode 100644 index 000000000..e53c9d183 --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/Bundle.properties @@ -0,0 +1,19 @@ +CTL_ImportModel=Import Model +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin allows importing models to a project using a Wizard. +OpenIDE-Module-Name=Model Import Tool +ModelImporterVisualPanel2.jLabel1.text=Import to path: +ModelImporterVisualPanel2.jTextField1.text=/Models/MyModel +ModelImporterVisualPanel2.jCheckBox1.text=copy original model file(s) to project folder +ModelImporterVisualPanel1.jPanel2.border.title=Properties +ModelImporterVisualPanel1.jTextField1.text= +ModelImporterVisualPanel1.jButton1.text=+ +ModelImporterVisualPanel1.jButton2.text=- +ModelImporterVisualPanel1.jButton3.text=< +ModelImporterVisualPanel1.jButton4.text=> +ModelImporterVisualPanel1.jButton5.text=open model.. +ModelImporterVisualPanel1.jLabel1.text=Imported Model Path: +ModelImporterVisualPanel2.jTextArea1.text=The model will be converted to j3o binary format and copied \nto the project folder including associated texture etc. files.\nThe given path will be used as the root folder for the model.\n\nIf you copy the original model files to the project folder you can re-convert the model at any time by double-clicking it. +ModelImporterVisualPanel1.jPanel3.border.title=Files +OpenIDE-Module-Short-Description=Allows importing models to a project using a Wizard diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ImportModel.java b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ImportModel.java new file mode 100644 index 000000000..49dc2e13c --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ImportModel.java @@ -0,0 +1,176 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.modelimporter; + +import com.jme3.asset.AssetKey; +import com.jme3.asset.DesktopAssetManager; +import com.jme3.asset.TextureKey; +import com.jme3.export.binary.BinaryExporter; +import com.jme3.gde.core.assets.AssetManagerConfigurator; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import com.jme3.scene.Spatial; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +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; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + +public final class ImportModel implements ActionListener { + + private final Project context; + private WizardDescriptor.Panel[] panels; + + public ImportModel(Project context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final WizardDescriptor wiz = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wiz.setTitleFormat(new MessageFormat("{0}")); + wiz.setTitle("Import Model to Project"); + wiz.putProperty("project", context); + DesktopAssetManager manager = new DesktopAssetManager(true); + for (AssetManagerConfigurator di : Lookup.getDefault().lookupAll(AssetManagerConfigurator.class)) { + di.prepareManager(manager); + } + wiz.putProperty("manager", manager); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wiz); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wiz.getValue() != WizardDescriptor.FINISH_OPTION; + ((ModelImporterWizardPanel1)panels[0]).cleanup(); + if (!cancelled) { + new Thread(new Runnable() { + + public void run() { + ProgressHandle handle=ProgressHandleFactory.createHandle("Importing Model.."); + handle.start(); + try { + copyModel(wiz); + } catch (Exception e) { + Exceptions.printStackTrace(e); + } + handle.finish(); + } + }).start(); + } + } + + private void copyModel(WizardDescriptor wiz) { + AssetKey key = (AssetKey) wiz.getProperty("mainkey"); + boolean keepFiles = (Boolean) wiz.getProperty("keepfiles"); + List keyList = (List) wiz.getProperty("assetlist"); + String path = (String) wiz.getProperty("path"); + String importPath = (String) wiz.getProperty("destpath"); + ProjectAssetManager manager = context.getLookup().lookup(ProjectAssetManager.class); + if (manager == null) { + throw new IllegalStateException("Cannot find project AssetManager!"); + } + List deleteList=new LinkedList(); + for (Iterator it = keyList.iterator(); it.hasNext();) { + AssetKey assetKey = it.next(); + File file = new File(path + "/" + assetKey.getFolder() + assetKey.getName()); + if (file.exists()) { + FileObject source = FileUtil.toFileObject(file); + File destFolder = new File(manager.getAssetFolderName() + "/" + importPath + "/" + assetKey.getFolder() + "/"); + destFolder.mkdirs(); + FileObject dest = FileUtil.toFileObject(destFolder); + try { + FileObject fileObj=source.copy(dest, source.getName(), source.getExt()); + if(!(assetKey instanceof TextureKey)){ + deleteList.add(fileObj); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } + File file = new File(manager.getAssetFolderName() + "/" + importPath + "/" + key.getName()); + File outFile = new File(manager.getAssetFolderName() + "/" + importPath + "/" + key.getName().replaceAll(key.getExtension(), "j3o")); + DataObject targetModel; + try { + targetModel = DataObject.find(FileUtil.toFileObject(file)); + if (targetModel instanceof SpatialAssetDataObject) { + //TODO: wtf? why do i have to add the assetmanager? + ((SpatialAssetDataObject) targetModel).getLookupContents().add(manager); + Spatial spat = ((SpatialAssetDataObject) targetModel).loadAsset(); + if (spat == null) { + throw new IllegalStateException("Cannot load model after copying!"); + + } + BinaryExporter exp = BinaryExporter.getInstance(); + exp.save(spat, outFile); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + if(!keepFiles){ + for (Iterator it = deleteList.iterator(); it.hasNext();) { + FileObject fileObject = it.next(); + try { + fileObject.delete(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } + FileObject dest = FileUtil.toFileObject(new File(manager.getAssetFolderName() + "/" + importPath).getParentFile()); + dest.refresh(); + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new ModelImporterWizardPanel1(), + new ModelImporterWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } +} diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel1.form b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel1.form new file mode 100644 index 000000000..8c2ac7165 --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel1.form @@ -0,0 +1,230 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel1.java b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel1.java new file mode 100644 index 000000000..143c95638 --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel1.java @@ -0,0 +1,322 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.modelimporter; + +import com.jme3.asset.AssetEventListener; +import com.jme3.asset.AssetKey; +import com.jme3.asset.DesktopAssetManager; +import com.jme3.asset.ModelKey; +import com.jme3.asset.plugins.FileLocator; +import com.jme3.gde.core.scene.OffScenePanel; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.io.File; +import java.util.LinkedList; +import java.util.List; +import javax.swing.JPanel; +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; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileChooserBuilder; + +public final class ModelImporterVisualPanel1 extends JPanel implements AssetEventListener { + + private OffScenePanel offPanel; + private DesktopAssetManager manager; + private String currentPath; + private Spatial currentModel; + private List requestedAssets = new LinkedList(); + private AssetKey mainKey; + + /** Creates new form ModelImporterVisualPanel1 */ + public ModelImporterVisualPanel1() { + initComponents(); + offPanel = new OffScenePanel(320, 320); + offPanel.startPreview(); + jPanel1.add(offPanel); + } + + @Override + public String getName() { + return "Preview Model"; + } + + public void loadSettings(WizardDescriptor wiz) { + manager = (DesktopAssetManager) wiz.getProperty("manager"); + manager.setAssetEventListener(this); + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("path", currentPath); + wiz.putProperty("assetlist", requestedAssets); + wiz.putProperty("mainkey", mainKey); + if (mainKey != null) { + wiz.putProperty("destpath", "Models/" + mainKey.getName().replaceAll(mainKey.getExtension(), "").replaceAll("\\.", "") + "/"); + } + } + + public synchronized void loadModel(File path) { + try { + if (currentPath != null) { + manager.unregisterLocator(currentPath, FileLocator.class); + manager.clearCache(); + requestedAssets.clear(); + mainKey = null; + } + if (currentModel != null) { + offPanel.detach(currentModel); + } + currentPath = path.getParent(); + manager.registerLocator(currentPath, FileLocator.class); + mainKey = new ModelKey(path.getName()); + currentModel = (Spatial) manager.loadAsset(mainKey); + if (currentModel != null) { + offPanel.attach(currentModel); + }else{ + Message msg = new NotifyDescriptor.Message( + "Cannot import this file!", + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + } catch (Exception e) { + Message msg = new NotifyDescriptor.Message( + "Error importing file!\n" + + "(" + e + ")", + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + updateList(); + } + }); + } + + private synchronized void updateList() { + jList1.setListData(requestedAssets.toArray()); + } + + public void assetRequested(AssetKey ak) { + if (!"j3md".equalsIgnoreCase(ak.getExtension()) + && !"frag".equalsIgnoreCase(ak.getExtension()) + && !"vert".equalsIgnoreCase(ak.getExtension())) { + requestedAssets.add(ak); + } + } + + public void assetLoaded(AssetKey ak) { + } + + public void cleanup() { + offPanel.stopPreview(); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jPanel2 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + jToolBar1 = new javax.swing.JToolBar(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + jSeparator1 = new javax.swing.JToolBar.Separator(); + jButton3 = new javax.swing.JButton(); + jButton4 = new javax.swing.JButton(); + jButton5 = new javax.swing.JButton(); + jLabel1 = new javax.swing.JLabel(); + jPanel3 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jList1 = new javax.swing.JList(); + + jPanel1.setPreferredSize(new java.awt.Dimension(320, 320)); + jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.LINE_AXIS)); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jPanel2.border.title"))); // NOI18N + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 227, Short.MAX_VALUE) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 131, Short.MAX_VALUE) + ); + + jTextField1.setEditable(false); + jTextField1.setText(org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jTextField1.text")); // NOI18N + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jButton1.text")); // NOI18N + jButton1.setFocusable(false); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar1.add(jButton1); + + org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jButton2.text")); // NOI18N + jButton2.setFocusable(false); + jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + jToolBar1.add(jButton2); + jToolBar1.add(jSeparator1); + + org.openide.awt.Mnemonics.setLocalizedText(jButton3, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jButton3.text")); // NOI18N + jButton3.setFocusable(false); + jButton3.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton3.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton3.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton3ActionPerformed(evt); + } + }); + jToolBar1.add(jButton3); + + org.openide.awt.Mnemonics.setLocalizedText(jButton4, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jButton4.text")); // NOI18N + jButton4.setFocusable(false); + jButton4.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton4.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton4.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton4ActionPerformed(evt); + } + }); + jToolBar1.add(jButton4); + + org.openide.awt.Mnemonics.setLocalizedText(jButton5, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jButton5.text")); // NOI18N + jButton5.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton5ActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jLabel1.text")); // NOI18N + + jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel1.class, "ModelImporterVisualPanel1.jPanel3.border.title"))); // NOI18N + + jScrollPane1.setViewportView(jList1); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 424, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton5)) + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 559, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jButton5))) + ); + }// //GEN-END:initComponents + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + offPanel.zoomCamera(-.1f); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed + FileChooserBuilder builder = new FileChooserBuilder(this.getClass()); + builder.setTitle("Select Model File"); + final File file = builder.showOpenDialog(); + if (file != null) { + jTextField1.setText(file.getAbsolutePath()); + new Thread(new Runnable() { + + public void run() { + ProgressHandle handle = ProgressHandleFactory.createHandle("Opening Model.."); + handle.start(); + loadModel(file); + handle.finish(); + } + }).start(); + } + }//GEN-LAST:event_jButton5ActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + offPanel.zoomCamera(.1f); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed + offPanel.rotateCamera(Vector3f.UNIT_Y, .1f); + }//GEN-LAST:event_jButton3ActionPerformed + + private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed + offPanel.rotateCamera(Vector3f.UNIT_Y, -.1f); + }//GEN-LAST:event_jButton4ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JButton jButton3; + private javax.swing.JButton jButton4; + private javax.swing.JButton jButton5; + private javax.swing.JLabel jLabel1; + private javax.swing.JList jList1; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JToolBar.Separator jSeparator1; + private javax.swing.JTextField jTextField1; + private javax.swing.JToolBar jToolBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel2.form b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel2.form new file mode 100644 index 000000000..af3611238 --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel2.form @@ -0,0 +1,86 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel2.java b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel2.java new file mode 100644 index 000000000..75c7e613a --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel2.java @@ -0,0 +1,89 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.modelimporter; + +import javax.swing.JPanel; +import org.openide.WizardDescriptor; + +public final class ModelImporterVisualPanel2 extends JPanel { + + /** Creates new form ModelImporterVisualPanel2 */ + public ModelImporterVisualPanel2() { + initComponents(); + } + + @Override + public String getName() { + return "Import Options"; + } + + public void loadSettings(WizardDescriptor wiz) { + jTextField1.setText((String)wiz.getProperty("destpath")); + } + + public void applySettings(WizardDescriptor wiz) { + wiz.putProperty("destpath", jTextField1.getText()); + wiz.putProperty("keepfiles", jCheckBox1.isSelected()); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jCheckBox1 = new javax.swing.JCheckBox(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel2.class, "ModelImporterVisualPanel2.jLabel1.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel2.class, "ModelImporterVisualPanel2.jTextField1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel2.class, "ModelImporterVisualPanel2.jCheckBox1.text")); // NOI18N + + jTextArea1.setColumns(20); + jTextArea1.setEditable(false); + jTextArea1.setLineWrap(true); + jTextArea1.setRows(5); + jTextArea1.setText(org.openide.util.NbBundle.getMessage(ModelImporterVisualPanel2.class, "ModelImporterVisualPanel2.jTextArea1.text")); // NOI18N + jTextArea1.setWrapStyleWord(true); + jScrollPane1.setViewportView(jTextArea1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addContainerGap(305, Short.MAX_VALUE)) + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addComponent(jCheckBox1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBox1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 204, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterWizardPanel1.java b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterWizardPanel1.java new file mode 100644 index 000000000..83c259238 --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterWizardPanel1.java @@ -0,0 +1,91 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.modelimporter; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class ModelImporterWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private ModelImporterVisualPanel1 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. + public Component getComponent() { + if (component == null) { + component = new ModelImporterVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.model_loader_and_viewer"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + component.loadSettings((WizardDescriptor)settings); + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor)settings); + } + public void cleanup(){ + component.cleanup(); + } +} diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterWizardPanel2.java b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterWizardPanel2.java new file mode 100644 index 000000000..b31e0ff40 --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterWizardPanel2.java @@ -0,0 +1,88 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.modelimporter; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class ModelImporterWizardPanel2 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private ModelImporterVisualPanel2 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. + public Component getComponent() { + if (component == null) { + component = new ModelImporterVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return new HelpCtx("sdk.model_loader_and_viewer"); + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + component.loadSettings((WizardDescriptor)settings); + } + + public void storeSettings(Object settings) { + component.applySettings((WizardDescriptor)settings); + } +} diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/layer.xml b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/layer.xml new file mode 100644 index 000000000..f7bdd7f02 --- /dev/null +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/layer.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-ogretools/build.xml b/sdk/jme3-ogretools/build.xml new file mode 100644 index 000000000..a4a3b4b55 --- /dev/null +++ b/sdk/jme3-ogretools/build.xml @@ -0,0 +1,19 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.ogretools. + + + + + + + + + + + + + diff --git a/sdk/jme3-ogretools/manifest.mf b/sdk/jme3-ogretools/manifest.mf new file mode 100644 index 000000000..a94fc020d --- /dev/null +++ b/sdk/jme3-ogretools/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.ogretools/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/ogretools/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/ogretools/Bundle.properties + diff --git a/sdk/jme3-ogretools/nbproject/build-impl.xml b/sdk/jme3-ogretools/nbproject/build-impl.xml new file mode 100644 index 000000000..d04d1dfa6 --- /dev/null +++ b/sdk/jme3-ogretools/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-ogretools/nbproject/genfiles.properties b/sdk/jme3-ogretools/nbproject/genfiles.properties new file mode 100644 index 000000000..d3fe71373 --- /dev/null +++ b/sdk/jme3-ogretools/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=01f20fa7 +build.xml.script.CRC32=6423eb2c +build.xml.stylesheet.CRC32=79c3b980@1.31.2.7 +# 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=34ba26c9 +nbproject/build-impl.xml.script.CRC32=4a050ba2 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-ogretools/nbproject/project.properties b/sdk/jme3-ogretools/nbproject/project.properties new file mode 100644 index 000000000..c6ff638f1 --- /dev/null +++ b/sdk/jme3-ogretools/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.6.1 diff --git a/sdk/jme3-ogretools/nbproject/project.xml b/sdk/jme3-ogretools/nbproject/project.xml new file mode 100644 index 000000000..a4e06e7de --- /dev/null +++ b/sdk/jme3-ogretools/nbproject/project.xml @@ -0,0 +1,124 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.ogretools + + + + com.jme3.gde.core + + + + 1 + 0.7 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.5 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.5 + + + + com.jme3.gde.ogrexml + + 1 + 0.1 + + + + org.netbeans.api.progress + + + + 1 + 1.16.1.1 + + + + org.openide.awt + + + + 7.23.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.30.1 + + + + + com.jme3.gde.ogretools + com.jme3.gde.ogretools.blender + com.jme3.gde.ogretools.convert + + + + diff --git a/sdk/jme3-ogretools/nbproject/suite.properties b/sdk/jme3-ogretools/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-ogretools/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/Bundle.properties b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/Bundle.properties new file mode 100644 index 000000000..22fc96a9b --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/Bundle.properties @@ -0,0 +1,8 @@ +LBL_OgreBinaryMesh_loader_name=OgreBinaryMesh Files +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides additional tools for OgreXML e.g. blender export scripts. +OpenIDE-Module-Name=OgreXML Tools +OpenIDE-Module-Short-Description=Provides Additional Tools for OgreXML +Services/MIMEResolver/OgreBinaryMeshResolver.xml=OgreBinaryMesh Files +Templates/Other/OgreBinaryMeshTemplate.mesh=Empty OgreBinaryMesh file diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/OgreBinaryMeshDataObject.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/OgreBinaryMeshDataObject.java new file mode 100644 index 000000000..7130d66fe --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/OgreBinaryMeshDataObject.java @@ -0,0 +1,71 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.ogretools; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import com.jme3.gde.ogretools.convert.OgreXMLConvert; +import com.jme3.gde.ogretools.convert.OgreXMLConvertOptions; +import com.jme3.scene.Spatial; +import java.io.File; +import java.io.IOException; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressHandleFactory; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; +import org.openide.util.Exceptions; + +public class OgreBinaryMeshDataObject extends SpatialAssetDataObject { + + public OgreBinaryMeshDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + } + + @Override + public Spatial loadAsset() { + ProgressHandle handle = ProgressHandleFactory.createHandle("Converting OgreBinary"); + handle.start(4); + //mesh + OgreXMLConvertOptions options = new OgreXMLConvertOptions(getPrimaryFile().getPath()); + options.setBinaryFile(true); + OgreXMLConvert conv = new OgreXMLConvert(); + conv.doConvert(options, handle); + //try skeleton + if (getPrimaryFile().existsExt("skeleton")) { + OgreXMLConvertOptions options2 = new OgreXMLConvertOptions(getPrimaryFile().getParent().getFileObject(getPrimaryFile().getName(), "skeleton").getPath()); + options2.setBinaryFile(true); + OgreXMLConvert conv2 = new OgreXMLConvert(); + conv2.doConvert(options2, handle); + } + handle.progress(3); + ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class); + if (mgr == null) { + return null; + } + String assetKey = mgr.getRelativeAssetPath(options.getDestFile()); + FileLock lock = null; + try { + lock = getPrimaryFile().lock(); + Spatial spatial = mgr.getManager().loadModel(assetKey); + savable = spatial; + lock.releaseLock(); + File deleteFile = new File(options.getDestFile()); + deleteFile.delete(); + handle.finish(); + return spatial; + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + if (lock != null) { + lock.releaseLock(); + } + } + File deleteFile = new File(options.getDestFile()); + deleteFile.delete(); + handle.finish(); + return null; + } +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/OgreBinaryMeshResolver.xml b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/OgreBinaryMeshResolver.xml new file mode 100644 index 000000000..a260194a3 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/OgreBinaryMeshResolver.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/Bundle.properties b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/Bundle.properties new file mode 100644 index 000000000..34ef9b580 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/Bundle.properties @@ -0,0 +1,9 @@ +CTL_InstallBlenderExporter=Install Blender OgreXML +InstallBlenderExporterPanel.jLabel1.text=Install OgreXML Exporter to Blender Scripts Folder +InstallBlenderExporterPanel.jTextField1.text=jTextField1 +InstallBlenderExporterPanel.jButton1.text=change +InstallBlenderExporterPanel.jButton2.text=Install Exporter Script +InstallBlenderExporterPanel.jButton3.text=Cancel +InstallBlenderExporterPanel.jLabel2.text=Note that you will need Phython 2.6 +InstallBlenderExporterPanel.jLabel3.text=installed on your computer to use this plugin! +InstallBlenderExporterPanel.jLabel4.text=http://www.python.org/download/releases/2.6/ diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporter.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporter.java new file mode 100644 index 000000000..84a604dcf --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporter.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.ogretools.blender; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public final class InstallBlenderExporter implements ActionListener { + + public void actionPerformed(ActionEvent e) { + InstallBlenderExporterPanel panel=new InstallBlenderExporterPanel(null, false); + panel.setLocationRelativeTo(null); + panel.setVisible(true); + } +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporterPanel.form b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporterPanel.form new file mode 100644 index 000000000..da4890327 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporterPanel.form @@ -0,0 +1,152 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporterPanel.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporterPanel.java new file mode 100644 index 000000000..a5bb368bf --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/InstallBlenderExporterPanel.java @@ -0,0 +1,421 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * InstallBlenderExporterPanel.java + * + * Created on 08.05.2010, 18:41:38 + */ +package com.jme3.gde.ogretools.blender; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import org.openide.filesystems.FileChooserBuilder; +import org.openide.util.Exceptions; +import org.openide.util.Utilities; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.prefs.Preferences; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import javax.swing.JOptionPane; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Confirmation; + +/** + * + * @author normenhansen + */ +public class InstallBlenderExporterPanel extends javax.swing.JDialog { + + /** Creates new form InstallBlenderExporterPanel */ + public InstallBlenderExporterPanel(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + jTextField1.setText(findBlenderFolder()); + } + }); + } + + private String findBlenderFolder() { + if (Utilities.isMac()) { + File scriptsDir = new File(System.getProperty("user.home") + "/.blender/scripts/"); + if (!scriptsDir.exists()) { + scriptsDir = new File("/Applications/blender.app/Contents/Resources/MacOS/.blender/scripts/"); + if (!scriptsDir.exists()) { + scriptsDir = new File(System.getProperty("user.home") + "/Applications/blender.app/Contents/Resources/MacOS/.blender/scripts/"); + if (!scriptsDir.exists()) { + scriptsDir = new File("/Applications/blender/blender.app/Contents/Resources/MacOS/.blender/scripts/"); + } + } + } + if (!scriptsDir.exists()) { + FileChooserBuilder builder = new FileChooserBuilder("/Applications/"); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Blender.app Application"); + File file = builder.showOpenDialog(); + if (file != null) { + scriptsDir = new File(file.getPath() + "/Contents/Resources/MacOS/.blender/scripts/"); + } + return scriptsDir.getPath(); + } else { + return scriptsDir.getPath(); + } + } else if (Utilities.isUnix()) { + File scriptsDir = new File("/usr/share/blender/"); + if (!scriptsDir.exists()) { + scriptsDir = new File("/usr/lib/blender/"); + } + if (!scriptsDir.exists()) { + FileChooserBuilder builder = new FileChooserBuilder(""); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Blender Scripts Directory"); + File file = builder.showOpenDialog(); + if (file != null) { + scriptsDir = file; + } + return scriptsDir.getPath(); + } else { + return scriptsDir.getPath(); + } + } else if (Utilities.isWindows()) { + File scriptsDir = new File(System.getProperty("user.home") + "\\AppData\\Roaming\\Blender Foundation\\Blender\\scripts\\"); + if (!scriptsDir.exists()) { + scriptsDir = new File(System.getProperty("user.home") + "\\Application Data\\Roaming\\Blender Foundation\\Blender\\scripts\\"); + if (!scriptsDir.exists()) { + scriptsDir = new File(System.getProperty("user.home") + "C:\\Program Files\\Blender\\.blender\\scripts\\"); + } + } + if (!scriptsDir.exists()) { + FileChooserBuilder builder = new FileChooserBuilder(""); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Blender Scripts Directory"); + File file = builder.showOpenDialog(); + if (file != null) { + scriptsDir = file; + } + return scriptsDir.getPath(); + } else { + return scriptsDir.getPath(); + } + } + return "could not find path"; + } + static final int BUFFER = 2048; + + private void installBlenderPlugin(String scriptsFolder) { + try { + File scriptsFolderFile = new File(scriptsFolder); + if (!scriptsFolderFile.exists()) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Folder does not exist!", + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + return; + } + // "https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/blendersceneexporter/ogredotscene.py" + // + BufferedOutputStream dest = null; + ZipInputStream zis = new ZipInputStream(new BufferedInputStream(getClass().getResourceAsStream("/com/jme3/gde/ogretools/blender/scripts.zip"))); + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) { + int count; + byte data[] = new byte[BUFFER]; + if (entry.getName().contains(".svn") || entry.getName().contains(".DS_Store")) { + continue; + } + if (entry.isDirectory()) { + File dir = new File(scriptsFolder + File.separator + entry.getName()); + dir.mkdirs(); + continue; + } + // write the files to the disk + FileOutputStream fos = new FileOutputStream(scriptsFolder + File.separator + entry.getName()); + dest = new BufferedOutputStream(fos, BUFFER); + while ((count = zis.read(data, 0, BUFFER)) + != -1) { + dest.write(data, 0, count); + } + dest.flush(); + dest.close(); + } + zis.close(); + Confirmation msg = new NotifyDescriptor.Confirmation( + "Sucessuflly Installed Blender Exporter!", + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.INFORMATION_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + dispose(); + + } catch (IOException ex) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error:\n" + ex.toString(), + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + Exceptions.printStackTrace(ex); + } + + } + + private static String getWindowsRegistryBlenderPath() { + + final int HKEY_CURRENT_USER = 0x80000001; + final int KEY_QUERY_VALUE = 1; + final int KEY_SET_VALUE = 2; + final int KEY_READ = 0x20019; + + String value = null; + + final Preferences userRoot = Preferences.userRoot(); + final Class clz = userRoot.getClass(); + try { + Class[] parms1 = {byte[].class, int.class, int.class}; + final Method mOpenKey = clz.getDeclaredMethod("openKey", + parms1); + mOpenKey.setAccessible(true); + + Class[] parms2 = {int.class}; + final Method mCloseKey = clz.getDeclaredMethod("closeKey", + parms2); + mCloseKey.setAccessible(true); + + Class[] parms3 = {int.class, byte[].class}; + final Method mWinRegQueryValue = clz.getDeclaredMethod( + "WindowsRegQueryValueEx", parms3); + mWinRegQueryValue.setAccessible(true); + + Class[] parms4 = {int.class, int.class, int.class}; + final Method mWinRegEnumValue = clz.getDeclaredMethod( + "WindowsRegEnumValue1", parms4); + mWinRegEnumValue.setAccessible(true); + + Class[] parms5 = {int.class}; + final Method mWinRegQueryInfo = clz.getDeclaredMethod( + "WindowsRegQueryInfoKey1", parms5); + mWinRegQueryInfo.setAccessible(true); + + // Should be: HKEY_CURRENT_USER\Volatile Environment, key NWUSERNAME + final String subKey = "Volatile Environment"; + + Object[] objects1 = {toByteArray(subKey), new Integer(KEY_READ), new Integer(KEY_READ)}; + Integer hSettings = (Integer) mOpenKey.invoke(userRoot, + objects1); + + Object[] objects2 = {hSettings, toByteArray("NWUSERNAME")}; + byte[] b = (byte[]) mWinRegQueryValue.invoke(userRoot, + objects2); + value = (b != null ? new String(b).trim() : null); + System.out.println(value); + + Object[] objects3 = {hSettings}; + mCloseKey.invoke(Preferences.userRoot(), objects3); + + } catch (Exception e) { + System.out.println("Error getting value Windows registry: "); + e.printStackTrace(); + } + return value; + } + + private static byte[] toByteArray(String str) { + byte[] result = new byte[str.length() + 1]; + for (int i = 0; i < str.length(); i++) { + result[i] = (byte) str.charAt(i); + } + result[str.length()] = 0; + return result; + } + + static final String[] browsers = {"google-chrome", "firefox", "opera", + "konqueror", "epiphany", "seamonkey", "galeon", "kazehakase", "mozilla"}; + static final String errMsg = "Error attempting to launch web browser"; + + public static void openURL(String url) { +// try { //attempt to use Desktop library from JDK 1.6+ (even if on 1.5) +// Class d = Class.forName("java.awt.Desktop"); +// d.getDeclaredMethod("browse", new Class[]{java.net.URI.class}).invoke( +// d.getDeclaredMethod("getDesktop").invoke(null), +// new Object[]{java.net.URI.create(url)}); +// //above code mimics: +// // java.awt.Desktop.getDesktop().browse(java.net.URI.create(url)); +// } catch (Exception ignore) { //library not available or failed + String osName = System.getProperty("os.name"); + try { + if (osName.startsWith("Mac OS")) { + Class.forName("com.apple.eio.FileManager").getDeclaredMethod( + "openURL", new Class[]{String.class}).invoke(null, + new Object[]{url}); + } else if (osName.startsWith("Windows")) { + Runtime.getRuntime().exec( + "rundll32 url.dll,FileProtocolHandler " + url); + } else { //assume Unix or Linux + boolean found = false; + for (String browser : browsers) { + if (!found) { + found = Runtime.getRuntime().exec( + new String[]{"which", browser}).waitFor() == 0; + if (found) { + Runtime.getRuntime().exec(new String[]{browser, url}); + } + } + } + if (!found) { + throw new Exception(Arrays.toString(browsers)); + } + } + } catch (Exception e) { + JOptionPane.showMessageDialog(null, errMsg + "\n" + e.toString()); + } +// } + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + jButton3 = new javax.swing.JButton(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/ogretools/blender/ogre-logo24.png"))); // NOI18N + jLabel1.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jLabel1.text")); // NOI18N + + jTextField1.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jTextField1.text")); // NOI18N + + jButton1.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + jButton3.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jButton3.text")); // NOI18N + jButton3.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton3ActionPerformed(evt); + } + }); + + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabel2.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jLabel2.text")); // NOI18N + + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabel3.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jLabel3.text")); // NOI18N + + jLabel4.setForeground(new java.awt.Color(0, 51, 255)); + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabel4.setText(org.openide.util.NbBundle.getMessage(InstallBlenderExporterPanel.class, "InstallBlenderExporterPanel.jLabel4.text")); // NOI18N + jLabel4.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseReleased(java.awt.event.MouseEvent evt) { + openBrowser(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE) + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 243, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jButton3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton2)) + .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE) + .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jButton1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton2) + .addComponent(jButton3)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + FileChooserBuilder builder = new FileChooserBuilder(""); + builder.setDirectoriesOnly(true); + builder.setTitle("Select Blender Scripts Directory"); + File file = builder.showOpenDialog(); + if (file != null) { + jTextField1.setText(file.getPath()); + } + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + installBlenderPlugin(jTextField1.getText()); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed + dispose(); + }//GEN-LAST:event_jButton3ActionPerformed + + private void openBrowser(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_openBrowser + openURL("http://www.python.org/download/releases/2.6/"); + }//GEN-LAST:event_openBrowser + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JButton jButton3; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/ogre-logo.png b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/ogre-logo.png new file mode 100644 index 000000000..a11242fde Binary files /dev/null and b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/ogre-logo.png differ diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/ogre-logo24.png b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/ogre-logo24.png new file mode 100644 index 000000000..d195de8b2 Binary files /dev/null and b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/ogre-logo24.png differ diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/scripts.zip b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/scripts.zip new file mode 100644 index 000000000..08298c9bf Binary files /dev/null and b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/blender/scripts.zip differ diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertAction.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertAction.java new file mode 100644 index 000000000..44c958737 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertAction.java @@ -0,0 +1,116 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.ogretools.convert; + +import com.jme3.asset.DesktopAssetManager; +import com.jme3.export.binary.BinaryExporter; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.scene.Spatial; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +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; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; +import org.openide.util.Exceptions; +import org.openide.windows.WindowManager; + +public final class AdvOgreXMLConvertAction implements ActionListener { + + private final DataObject context; + + public AdvOgreXMLConvertAction(DataObject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final ProjectAssetManager manager = context.getLookup().lookup(ProjectAssetManager.class); + if (manager == null) { +// StatusDisplayer.getDefault().setStatusText("Project has no AssetManager!"); + return; + } + + // TODO use context + final FileObject file = context.getPrimaryFile(); + final OgreXMLConvertOptions options = new OgreXMLConvertOptions(file.getPath(), file.getParent().getPath() + "/" + "+" + file.getNameExt()); + AdvOgreXMLConvertDialog dialog = new AdvOgreXMLConvertDialog(WindowManager.getDefault().getMainWindow(), true, options); + dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); + dialog.setVisible(true); + + + Runnable run = new Runnable() { + + public void run() { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Converting OgreXML"); + progressHandle.start(4); + + OgreXMLConvert converter = new OgreXMLConvert(); + if (!converter.doConvert(options, progressHandle)) { + progressHandle.finish(); + return; + } + FileObject sourceMatFile = FileUtil.toFileObject(new File(options.getSourceFile().replaceAll("mesh.xml", "material"))); + if (sourceMatFile.isValid()) { + try { + sourceMatFile.copy(sourceMatFile.getParent(), "+" + sourceMatFile.getName(), sourceMatFile.getExt()); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } else { + Confirmation msg = new NotifyDescriptor.Confirmation( + "No material file found for " + file.getNameExt() + "\n" + + "A file named " + file.getNameExt().replaceAll(".mesh.xml", ".material") + " should be in the same folder.\n" + + "Press OK to import mesh only.", + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.WARNING_MESSAGE); + Object result = DialogDisplayer.getDefault().notify(msg); + if (!NotifyDescriptor.OK_OPTION.equals(result)) { + return; + } + } + + FileObject file = FileUtil.toFileObject(new File(options.getDestFile())); +// FileLock lock = null; + try { +// lock = file.lock(); + progressHandle.progress("Creating j3o file", 3); + String outputPath = file.getParent().getPath() + "/" + context.getPrimaryFile().getName() + ".j3o"; + ((DesktopAssetManager) manager.getManager()).clearCache(); + Spatial model = manager.getManager().loadModel(manager.getRelativeAssetPath(file.getPath())); + BinaryExporter exp = BinaryExporter.getInstance(); + exp.save(model, new File(outputPath)); + //cleanup + try { + FileUtil.toFileObject(new File(options.getDestFile())).delete(); + FileUtil.toFileObject(new File(options.getDestFile().replaceAll("mesh.xml", "material"))).delete(); + } catch (Exception e) { + } + context.getPrimaryFile().getParent().refresh(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error converting " + file.getNameExt() + "\n" + ex.toString(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } finally { +// if (lock != null) { +// lock.releaseLock(); +// } + progressHandle.finish(); + } + } + }; + + new Thread(run).start(); + } +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertDialog.form b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertDialog.form new file mode 100644 index 000000000..7a2b40db1 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertDialog.form @@ -0,0 +1,215 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertDialog.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertDialog.java new file mode 100644 index 000000000..a11740495 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/AdvOgreXMLConvertDialog.java @@ -0,0 +1,203 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * AdvOgreXMLConvertDialog.java + * + * Created on 13.06.2010, 14:18:31 + */ + +package com.jme3.gde.ogretools.convert; + +/** + * + * @author normenhansen + */ +public class AdvOgreXMLConvertDialog extends javax.swing.JDialog { + OgreXMLConvertOptions options; + + /** Creates new form AdvOgreXMLConvertDialog */ + public AdvOgreXMLConvertDialog(java.awt.Frame parent, boolean modal, OgreXMLConvertOptions options) { + super(parent, modal); + this.options=options; + initComponents(); + loadSettings(options); + } + + private void loadSettings(OgreXMLConvertOptions options){ + jSpinner1.setValue(options.getLodLevels()); + jSlider1.setValue(options.getLodPercent()); + jCheckBox1.setSelected(options.isGenerateTangents()); + jCheckBox2.setSelected(options.isGenerateEdgeLists()); + } + + private void saveSettings(OgreXMLConvertOptions options){ + options.setLodLevels((Integer)jSpinner1.getValue()); + options.setLodPercent(jSlider1.getValue()); + options.setGenerateTangents(jCheckBox1.isSelected()); + options.setGenerateEdgeLists(jCheckBox2.isSelected()); + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jToolBar1 = new javax.swing.JToolBar(); + jLabel1 = new javax.swing.JLabel(); + jSpinner1 = new javax.swing.JSpinner(); + jToolBar3 = new javax.swing.JToolBar(); + jLabel3 = new javax.swing.JLabel(); + jSlider1 = new javax.swing.JSlider(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + jCheckBox1 = new javax.swing.JCheckBox(); + jCheckBox2 = new javax.swing.JCheckBox(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jPanel1.border.title"))); // NOI18N + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jLabel1.text")); // NOI18N + jToolBar1.add(jLabel1); + + jSpinner1.setToolTipText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jSpinner1.toolTipText")); // NOI18N + jToolBar1.add(jSpinner1); + + jToolBar3.setFloatable(false); + jToolBar3.setRollover(true); + + jLabel3.setText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jLabel3.text")); // NOI18N + jToolBar3.add(jLabel3); + + jSlider1.setToolTipText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jSlider1.toolTipText")); // NOI18N + jSlider1.setValue(20); + jToolBar3.add(jSlider1); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 305, Short.MAX_VALUE) + .addComponent(jToolBar3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 305, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + jButton1.setText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jPanel2.border.title"))); // NOI18N + + jCheckBox1.setText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jCheckBox1.text")); // NOI18N + + jCheckBox2.setText(org.openide.util.NbBundle.getMessage(AdvOgreXMLConvertDialog.class, "AdvOgreXMLConvertDialog.jCheckBox2.text")); // NOI18N + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jCheckBox1, javax.swing.GroupLayout.DEFAULT_SIZE, 345, Short.MAX_VALUE) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jCheckBox2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jCheckBox1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBox2) + .addContainerGap(8, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jButton1)) + .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1) + .addComponent(jButton2)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + dispose(); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + // TODO add your handling code here: + saveSettings(options); + dispose(); + }//GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JCheckBox jCheckBox2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JSlider jSlider1; + private javax.swing.JSpinner jSpinner1; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToolBar jToolBar3; + // End of variables declaration//GEN-END:variables + +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/Bundle.properties b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/Bundle.properties new file mode 100644 index 000000000..86994fea5 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/Bundle.properties @@ -0,0 +1,12 @@ +CTL_AdvOgreXMLConvert=Advanced JME Binary convert.. +AdvOgreXMLConvertDialog.jCheckBox1.text=create tangents (needed for normal maps) +AdvOgreXMLConvertDialog.jLabel1.text=LOD Levels: +AdvOgreXMLConvertDialog.jPanel1.border.title=LOD +AdvOgreXMLConvertDialog.jLabel3.text=Reduction % +AdvOgreXMLConvertDialog.jCheckBox2.text=generate edge lists (stencil shadows otherwise) +AdvOgreXMLConvertDialog.jButton1.text=Import +AdvOgreXMLConvertDialog.jButton2.text=Cancel +AdvOgreXMLConvertDialog.jSpinner1.toolTipText=defines how many different LOD meshes are created, 0 for none +AdvOgreXMLConvertDialog.jSlider1.toolTipText=defines in percent how much the mesh is reduced on each step +AdvOgreXMLConvertDialog.jPanel2.border.title=Mesh Options +CTL_OgreBinaryConvert=Convert to JME Binary diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreTools-Mac-Intel.zip b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreTools-Mac-Intel.zip new file mode 100644 index 000000000..7c6e7962f Binary files /dev/null and b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreTools-Mac-Intel.zip differ diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreTools-Windows.zip b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreTools-Windows.zip new file mode 100644 index 000000000..8ded04028 Binary files /dev/null and b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreTools-Windows.zip differ diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreXMLConvert.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreXMLConvert.java new file mode 100644 index 000000000..619627035 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreXMLConvert.java @@ -0,0 +1,337 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.ogretools.convert; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import org.netbeans.api.progress.ProgressHandle; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Confirmation; +import org.openide.util.Exceptions; +import org.openide.util.Utilities; + +/** + * + * @author normenhansen + */ +public class OgreXMLConvert { + + static final int BUFFER = 2048; + public static String osx_path = System.getProperty("user.home") + "/Library/Application Support/jmonkeyplatform/ogretools/"; + public static String windows_path = System.getProperty("user.home") + "\\.jmonkeyplatform\\ogretools\\"; + public static String linux_path = System.getProperty("user.home") + "/.jmonkeyplatform/ogretools/"; + + public boolean doConvert(OgreXMLConvertOptions options, ProgressHandle handle) { + if (!checkTools()) { + return false; + } + String[] cmdOptions = getCommandString(options); + Process proc = null; + if (!options.isBinaryFile()) { + handle.progress("Optimizing Mesh / Creating LOD meshes", 1); + //convert to binary + modify + try { + proc = Runtime.getRuntime().exec(cmdOptions); + OutputReader outReader = new OutputReader(proc.getInputStream()); + outReader.setProgress(handle); + OutputReader errReader = new OutputReader(proc.getErrorStream()); + errReader.setProgress(handle); + outReader.start(); + errReader.start(); + try { + proc.waitFor(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } + if (proc.exitValue() != 0) { + return false; + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + cleanUp(options); + return false; + } + } + handle.progress("Converting Binary Mesh", 2); + //convert back to xml + cmdOptions = getBackCommandString(options); + try { + proc = Runtime.getRuntime().exec(cmdOptions); + OutputReader outReader = new OutputReader(proc.getInputStream()); + outReader.setProgress(handle); + OutputReader errReader = new OutputReader(proc.getErrorStream()); + errReader.setProgress(handle); + outReader.start(); + errReader.start(); + try { + proc.waitFor(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } + if (proc.exitValue() != 0) { + return false; + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + cleanUp(options); + return false; + } + cleanUp(options); + return true; + } + + private void cleanUp(OgreXMLConvertOptions options) { + if (!options.isBinaryFile()) { + File file = new File(options.getBinaryFileName()); + if (file.exists()) { + file.delete(); + } + } + } + + private String[] getBackCommandString(OgreXMLConvertOptions options) { + ArrayList strings = new ArrayList(); + if (Utilities.isWindows()) { + strings.add(windows_path + "OgreXMLConverter.exe"); + strings.add("-log"); + strings.add(windows_path + "OgreXMLConverter.log"); + } else if (Utilities.isMac()) { + strings.add(osx_path + "bin/OgreXMLConverter"); + strings.add("-log"); + strings.add(osx_path + "OgreXMLConverter.log"); + } else { + strings.add(linux_path + "OgreXMLConverter"); + strings.add("-log"); + strings.add(linux_path + "OgreXMLConverter.log"); + } + + strings.add(options.getBinaryFileName()); + strings.add(options.getDestFile()); + + return strings.toArray(new String[strings.size()]); + } + + private String[] getCommandString(OgreXMLConvertOptions options) { + ArrayList strings = new ArrayList(); + if (Utilities.isWindows()) { + strings.add(windows_path + "OgreXMLConverter.exe"); + strings.add("-log"); + strings.add(windows_path + "OgreXMLConverter.log"); + } else if (Utilities.isMac()) { + strings.add(osx_path + "bin/OgreXMLConverter"); + strings.add("-log"); + strings.add(osx_path + "OgreXMLConverter.log"); + } else { + strings.add(linux_path + "OgreXMLConverter"); + strings.add("-log"); + strings.add(linux_path + "OgreXMLConverter.log"); + } + + strings.add("-gl"); + + if (options.isGenerateTangents()) { + strings.add("-t"); + } + if (!options.isGenerateEdgeLists()) { + strings.add("-e"); + } + if (options.getLodLevels() > 0) { + strings.add("-l"); + strings.add(options.getLodLevels() + ""); +// strings.add("-v"); +// strings.add(options.getLodValue() + ""); + strings.add("-p"); + strings.add(options.getLodPercent() + ""); +// strings.add("-s"); +// strings.add(options.getLodStrategy()); + } + + strings.add(options.getSourceFile()); + strings.add(options.getBinaryFileName()); + + return strings.toArray(new String[strings.size()]); + } + + private boolean checkTools() { + if (Utilities.isWindows()) { + File file = new File(windows_path + "OgreXMLConverter.exe"); + if (!file.exists()) { + return extractToolsWindows(); + } + } else if (Utilities.isMac()) { + File file = new File(osx_path + "bin/OgreXMLConverter"); + if (!file.exists()) { + return extractToolsOSX(); + } + } else { + File file = new File(linux_path + "OgreXMLConverter"); + if (!file.exists()) { + return extractToolsLinux(); + } + } + return true; + } + + private boolean extractToolsOSX() { + File path = new File(osx_path); + if (!path.exists()) { + path.mkdirs(); + } + + try { + BufferedInputStream in = new BufferedInputStream(getClass().getResourceAsStream("/com/jme3/gde/ogretools/convert/OgreTools-Mac-Intel.zip")); + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(osx_path + "tools.zip")); + int inbyte = in.read(); + while (inbyte != -1) { + out.write(inbyte); + inbyte = in.read(); + } + in.close(); + out.close(); + String[] cmdStrings = new String[]{ + "unzip", + "-o", + "-q", + osx_path + "tools.zip", + "-d", + osx_path + }; + Process p = Runtime.getRuntime().exec(cmdStrings); + OutputReader outReader = new OutputReader(p.getInputStream()); + OutputReader errReader = new OutputReader(p.getErrorStream()); + outReader.start(); + errReader.start(); + p.waitFor(); + File zipFile = new File(osx_path + "tools.zip"); + zipFile.delete(); + if (p.exitValue() != 0) { + return false; + } + } catch (Exception e) { + e.printStackTrace(); + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error extracting OgreTools!", + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + return false; + } + return true; + } + + private boolean extractToolsWindows() { + File path = new File(windows_path); + if (!path.exists()) { + path.mkdirs(); + } + + try { + File scriptsFolderFile = new File(windows_path); + if (!scriptsFolderFile.exists()) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error extracting OgreTools!", + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + return false; + } + BufferedOutputStream dest = null; + ZipInputStream zis = new ZipInputStream(new BufferedInputStream(getClass().getResourceAsStream("/com/jme3/gde/ogretools/convert/OgreTools-Windows.zip"))); + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) { + int count; + byte data[] = new byte[BUFFER]; + if (entry.getName().contains(".svn") || entry.getName().contains(".DS_Store")) { + continue; + } + if (entry.isDirectory()) { + File dir = new File(windows_path + File.separator + entry.getName()); + dir.mkdirs(); + continue; + } + // write the files to the disk + FileOutputStream fos = new FileOutputStream(windows_path + File.separator + entry.getName()); + dest = new BufferedOutputStream(fos, BUFFER); + while ((count = zis.read(data, 0, BUFFER)) + != -1) { + dest.write(data, 0, count); + } + dest.flush(); + dest.close(); + } + zis.close(); + } catch (IOException ex) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error extracting OgreXMLTools:\n" + ex.toString(), + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + Exceptions.printStackTrace(ex); + return false; + } + + return true; + } + + private boolean extractToolsLinux() { + File path = new File(linux_path); + if (!path.exists()) { + path.mkdirs(); + } + + try { + File scriptsFolderFile = new File(linux_path); + if (!scriptsFolderFile.exists()) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error extracting OgreTools!", + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + return false; + } + BufferedOutputStream dest = null; + ZipInputStream zis = new ZipInputStream(new BufferedInputStream(getClass().getResourceAsStream("/com/jme3/gde/ogretools/convert/OgreTools-Linux.zip"))); + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) { + int count; + byte data[] = new byte[BUFFER]; + if (entry.getName().contains(".svn") || entry.getName().contains(".DS_Store")) { + continue; + } + if (entry.isDirectory()) { + File dir = new File(linux_path + File.separator + entry.getName()); + dir.mkdirs(); + continue; + } + // write the files to the disk + FileOutputStream fos = new FileOutputStream(linux_path + File.separator + entry.getName()); + dest = new BufferedOutputStream(fos, BUFFER); + while ((count = zis.read(data, 0, BUFFER)) + != -1) { + dest.write(data, 0, count); + } + dest.flush(); + dest.close(); + } + zis.close(); + } catch (IOException ex) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error extracting OgreXMLTools:\n" + ex.toString(), + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + Exceptions.printStackTrace(ex); + return false; + } + return true; + } +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreXMLConvertOptions.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreXMLConvertOptions.java new file mode 100644 index 000000000..947c8dac5 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OgreXMLConvertOptions.java @@ -0,0 +1,123 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.ogretools.convert; + +import java.io.File; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + +/** + * + * @author normenhansen + */ +public class OgreXMLConvertOptions { + + private String sourceFile = ""; + private String destFile = ""; + private int lodLevels = 0; + private int lodValue = 250000; + private int lodPercent = 20; + private String lodStrategy = "Distance"; + private boolean generateTangents = true; + private boolean generateEdgeLists = false; + private boolean binaryFile = false; + + public OgreXMLConvertOptions() { + } + + public OgreXMLConvertOptions(String sourceFile) { + this.sourceFile = sourceFile; + this.destFile = sourceFile; + } + + public OgreXMLConvertOptions(String sourceFile, String destFile) { + this.sourceFile = sourceFile; + this.destFile = destFile; + } + + public String getSourceFile() { + return sourceFile; + } + + public void setSourceFile(String sourceFile) { + this.sourceFile = sourceFile; + } + + public String getBinaryFileName() { + if (binaryFile) { + return sourceFile; + } else { + FileObject fobj = FileUtil.toFileObject(new File(sourceFile)); + return fobj.getParent().getPath() + "/" + fobj.getName(); + } + } + + public String getDestFile() { + if(binaryFile){ + return sourceFile+".xml"; + } + return destFile; + } + + public void setDestFile(String destFile) { + this.destFile = destFile; + } + + public int getLodLevels() { + return lodLevels; + } + + public void setLodLevels(int lodLevels) { + this.lodLevels = lodLevels; + } + + public int getLodValue() { + return lodValue; + } + + public void setLodValue(int lodValue) { + this.lodValue = lodValue; + } + + public int getLodPercent() { + return lodPercent; + } + + public void setLodPercent(int lodPercent) { + this.lodPercent = lodPercent; + } + + public String getLodStrategy() { + return lodStrategy; + } + + public void setLodStrategy(String lodStrategy) { + this.lodStrategy = lodStrategy; + } + + public boolean isGenerateTangents() { + return generateTangents; + } + + public void setGenerateTangents(boolean generateTangents) { + this.generateTangents = generateTangents; + } + + public boolean isGenerateEdgeLists() { + return generateEdgeLists; + } + + public void setGenerateEdgeLists(boolean generateEdgeLists) { + this.generateEdgeLists = generateEdgeLists; + } + + public boolean isBinaryFile() { + return binaryFile; + } + + public void setBinaryFile(boolean binaryFile) { + this.binaryFile = binaryFile; + } +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OutputReader.java b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OutputReader.java new file mode 100644 index 000000000..3e1d4fd67 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/convert/OutputReader.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.ogretools.convert; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import org.netbeans.api.progress.ProgressHandle; + +/** + * + * @author normenhansen + */ +public class OutputReader implements Runnable { + + private Thread thread; + private BufferedReader in; + private ProgressHandle progress; + + public OutputReader(InputStream in) { + this.in = new BufferedReader(new InputStreamReader(in)); + } + + public OutputReader(BufferedReader in) { + this.in = in; + } + + public void start() { + thread = new Thread(this); + thread.start(); + } + + public void run() { + try { + String line; + while ((line = in.readLine()) != null) { + if (line.trim().length() > 0) { + if (progress != null) { + progress.progress(line); + } else { + System.out.println(line); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @param progress the progress to set + */ + public void setProgress(ProgressHandle progress) { + this.progress = progress; + } +} diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/layer.xml b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/layer.xml new file mode 100644 index 000000000..f513f7502 --- /dev/null +++ b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/layer.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/ogre-logo.png b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/ogre-logo.png new file mode 100644 index 000000000..a11242fde Binary files /dev/null and b/sdk/jme3-ogretools/src/com/jme3/gde/ogretools/ogre-logo.png differ diff --git a/sdk/jme3-ogrexml/build.xml b/sdk/jme3-ogrexml/build.xml new file mode 100644 index 000000000..8bf67dcfb --- /dev/null +++ b/sdk/jme3-ogrexml/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.ogrexml. + + diff --git a/sdk/jme3-ogrexml/manifest.mf b/sdk/jme3-ogrexml/manifest.mf new file mode 100644 index 000000000..6d29650e6 --- /dev/null +++ b/sdk/jme3-ogrexml/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.ogrexml/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/ogrexml/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/ogrexml/Bundle.properties + diff --git a/sdk/jme3-ogrexml/nbproject/build-impl.xml b/sdk/jme3-ogrexml/nbproject/build-impl.xml new file mode 100644 index 000000000..9cd9d2386 --- /dev/null +++ b/sdk/jme3-ogrexml/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-ogrexml/nbproject/genfiles.properties b/sdk/jme3-ogrexml/nbproject/genfiles.properties new file mode 100644 index 000000000..6c39f955e --- /dev/null +++ b/sdk/jme3-ogrexml/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=06ce291e +build.xml.script.CRC32=a910387a +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=06ce291e +nbproject/build-impl.xml.script.CRC32=2abbef60 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-ogrexml/nbproject/project.properties b/sdk/jme3-ogrexml/nbproject/project.properties new file mode 100644 index 000000000..833863ee2 --- /dev/null +++ b/sdk/jme3-ogrexml/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.8.0 diff --git a/sdk/jme3-ogrexml/nbproject/project.xml b/sdk/jme3-ogrexml/nbproject/project.xml new file mode 100644 index 000000000..b2beb64d4 --- /dev/null +++ b/sdk/jme3-ogrexml/nbproject/project.xml @@ -0,0 +1,141 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.ogrexml + + + + com.jme3.gde.core + + + + 1 + 0.1 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.5 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.5 + + + + org.netbeans.api.progress + + + + 1 + 1.16.1.1 + + + + org.netbeans.modules.java.project + + + + 1 + 1.29.1 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.28.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.text + + + + 6.27.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.30.1 + + + + + com.jme3.gde.ogrexml + + + + diff --git a/sdk/jme3-ogrexml/nbproject/suite.properties b/sdk/jme3-ogrexml/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-ogrexml/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/Bundle.properties b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/Bundle.properties new file mode 100644 index 000000000..e9f83928d --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/Bundle.properties @@ -0,0 +1,8 @@ +LBL_OgreScene_loader_name=OgreScene Files +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides OgreXML importing and file type support in jMP. +OpenIDE-Module-Name=OgreXML Support +OpenIDE-Module-Short-Description=Provides OgreXML Importing and File Type Support in jMP +Services/MIMEResolver/OgreSceneResolver.xml=OgreScene Files +Templates/Other/OgreSceneTemplate.scene=Empty OgreScene file diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreMaterialDataObject.java b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreMaterialDataObject.java new file mode 100644 index 000000000..5488686d3 --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreMaterialDataObject.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2009-2010 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.ogrexml; + +import com.jme3.gde.core.assets.AssetDataObject; +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.text.DataEditorSupport; + +public class OgreMaterialDataObject extends AssetDataObject { + + public OgreMaterialDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + CookieSet cookies = getCookieSet(); + cookies.add((Node.Cookie) DataEditorSupport.create(this, getPrimaryEntry(), cookies)); + } +} diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreMaterialResolver.xml b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreMaterialResolver.xml new file mode 100644 index 000000000..4e9f0ea89 --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreMaterialResolver.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreSceneDataObject.java b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreSceneDataObject.java new file mode 100644 index 000000000..751fdee88 --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreSceneDataObject.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009-2010 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.ogrexml; + +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; + +public class OgreSceneDataObject extends SpatialAssetDataObject { + + public OgreSceneDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + } + +} diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreSceneResolver.xml b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreSceneResolver.xml new file mode 100644 index 000000000..79aea733b --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreSceneResolver.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLDataObject.java b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLDataObject.java new file mode 100644 index 000000000..a4c215ab6 --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLDataObject.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009-2010 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.ogrexml; + +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; + +public class OgreXMLDataObject extends SpatialAssetDataObject { + + public OgreXMLDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + } + +} diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLResolver.xml b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLResolver.xml new file mode 100644 index 000000000..99804483a --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLResolver.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLTemplate.xml b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLTemplate.xml new file mode 100644 index 000000000..381197470 --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/OgreXMLTemplate.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/layer.xml b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/layer.xml new file mode 100644 index 000000000..092ab88c7 --- /dev/null +++ b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/layer.xml @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-logo.png b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-logo.png new file mode 100644 index 000000000..a11242fde Binary files /dev/null and b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-logo.png differ diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-logo24.png b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-logo24.png new file mode 100644 index 000000000..d195de8b2 Binary files /dev/null and b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-logo24.png differ diff --git a/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-scene.png b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-scene.png new file mode 100644 index 000000000..9526fb31a Binary files /dev/null and b/sdk/jme3-ogrexml/src/com/jme3/gde/ogrexml/ogre-scene.png differ diff --git a/sdk/jme3-project-baselibs/build.xml b/sdk/jme3-project-baselibs/build.xml new file mode 100644 index 000000000..a1c2acb15 --- /dev/null +++ b/sdk/jme3-project-baselibs/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.project.baselibs. + + diff --git a/sdk/jme3-project-baselibs/manifest.mf b/sdk/jme3-project-baselibs/manifest.mf new file mode 100644 index 000000000..fa5e9ec47 --- /dev/null +++ b/sdk/jme3-project-baselibs/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.project.baselibs/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/project/baselibs/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/project/baselibs/Bundle.properties + diff --git a/sdk/jme3-project-baselibs/nbproject/build-impl.xml b/sdk/jme3-project-baselibs/nbproject/build-impl.xml new file mode 100644 index 000000000..c66eb11f4 --- /dev/null +++ b/sdk/jme3-project-baselibs/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-project-baselibs/nbproject/genfiles.properties b/sdk/jme3-project-baselibs/nbproject/genfiles.properties new file mode 100644 index 000000000..885200dd9 --- /dev/null +++ b/sdk/jme3-project-baselibs/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=bb4041ef +build.xml.script.CRC32=7557c275 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.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=bb4041ef +nbproject/build-impl.xml.script.CRC32=61f5f4e1 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.1 diff --git a/sdk/jme3-project-baselibs/nbproject/project.properties b/sdk/jme3-project-baselibs/nbproject/project.properties new file mode 100644 index 000000000..7a33d7a9d --- /dev/null +++ b/sdk/jme3-project-baselibs/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=jMonkeyEngine +nbm.needs.restart=true +spec.version.base=0.8.0 diff --git a/sdk/jme3-project-baselibs/nbproject/project.xml b/sdk/jme3-project-baselibs/nbproject/project.xml new file mode 100644 index 000000000..368f47843 --- /dev/null +++ b/sdk/jme3-project-baselibs/nbproject/project.xml @@ -0,0 +1,12 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.project.baselibs + + + + + + diff --git a/sdk/jme3-project-baselibs/nbproject/suite.properties b/sdk/jme3-project-baselibs/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-project-baselibs/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/Bundle.properties b/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/Bundle.properties new file mode 100644 index 000000000..090311157 --- /dev/null +++ b/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/Bundle.properties @@ -0,0 +1,6 @@ +jme3=jme3 +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin contains the jMonkeyEngine3 version used to run and distribute your jMonkeyPlatform applications. +OpenIDE-Module-Name=Project jME3 +OpenIDE-Module-Short-Description=Provides jME3 Base Libraries for jMP Projects diff --git a/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/jme3.xml b/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/jme3.xml new file mode 100644 index 000000000..253ece6d8 --- /dev/null +++ b/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/jme3.xml @@ -0,0 +1,23 @@ + + + + + jme3 + j2se + com.jme3.gde.project.baselibs.Bundle + + classpath + jar:nbinst://com.jme3.gde.project.baselibs/libs/jMonkeyEngine3.jar!/ + + + src + jar:nbinst://com.jme3.gde.project.baselibs/libs/jMonkeyEngine3-sources.zip!/ + + + javadoc + jar:nbinst://com.jme3.gde.project.baselibs/libs/jMonkeyEngine3-javadoc.zip!/ + + diff --git a/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/layer.xml b/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/layer.xml new file mode 100644 index 000000000..972a3d141 --- /dev/null +++ b/sdk/jme3-project-baselibs/src/com/jme3/gde/project/baselibs/layer.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sdk/jme3-project-libraries/build.xml b/sdk/jme3-project-libraries/build.xml new file mode 100644 index 000000000..1b7a90de2 --- /dev/null +++ b/sdk/jme3-project-libraries/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.project.libraries. + + diff --git a/sdk/jme3-project-libraries/manifest.mf b/sdk/jme3-project-libraries/manifest.mf new file mode 100644 index 000000000..c56bdace0 --- /dev/null +++ b/sdk/jme3-project-libraries/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.project.libraries/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/project/libraries/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/project/libraries/Bundle.properties + diff --git a/sdk/jme3-project-libraries/nbproject/build-impl.xml b/sdk/jme3-project-libraries/nbproject/build-impl.xml new file mode 100644 index 000000000..c7ae11292 --- /dev/null +++ b/sdk/jme3-project-libraries/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-project-libraries/nbproject/genfiles.properties b/sdk/jme3-project-libraries/nbproject/genfiles.properties new file mode 100644 index 000000000..1b8781fcf --- /dev/null +++ b/sdk/jme3-project-libraries/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=951eb173 +build.xml.script.CRC32=b759faa7 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.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=951eb173 +nbproject/build-impl.xml.script.CRC32=4a5c1fa6 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.1 diff --git a/sdk/jme3-project-libraries/nbproject/platform.properties b/sdk/jme3-project-libraries/nbproject/platform.properties new file mode 100644 index 000000000..c61807864 --- /dev/null +++ b/sdk/jme3-project-libraries/nbproject/platform.properties @@ -0,0 +1,42 @@ +cluster.path=\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/java:\ + ${nbplatform.active.dir}/nb:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + org.netbeans.lib.uihandler,\ + org.netbeans.modules.autoupdate.pluginimporter,\ + org.netbeans.modules.editor.deprecated.pre61settings,\ + org.netbeans.modules.editor.highlights,\ + org.netbeans.modules.glassfish.common,\ + org.netbeans.modules.gsf,\ + org.netbeans.modules.gsf.api,\ + org.netbeans.modules.gsfpath.api,\ + org.netbeans.modules.hibernate,\ + org.netbeans.modules.hibernatelib,\ + org.netbeans.modules.hudson,\ + org.netbeans.modules.hudson.ant,\ + org.netbeans.modules.hudson.maven,\ + org.netbeans.modules.hudson.mercurial,\ + org.netbeans.modules.hudson.subversion,\ + org.netbeans.modules.ide.branding,\ + org.netbeans.modules.ide.branding.kit,\ + org.netbeans.modules.jellytools,\ + org.netbeans.modules.jellytools.ide,\ + org.netbeans.modules.jellytools.java,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.lexer.editorbridge,\ + org.netbeans.modules.projectimport.eclipse.j2se,\ + org.netbeans.modules.registration,\ + org.netbeans.modules.reglib,\ + org.netbeans.modules.uihandler,\ + org.netbeans.modules.uihandler.exceptionreporter,\ + org.netbeans.modules.web.client.tools.api,\ + org.netbeans.modules.websvc.saas.codegen.java,\ + org.netbeans.modules.welcome,\ + org.netbeans.modules.xml.wsdl.model,\ + org.netbeans.upgrader,\ + org.openide.compat,\ + org.openide.options,\ + org.openide.util.enumerations +nbplatform.active=default diff --git a/sdk/jme3-project-libraries/nbproject/project.properties b/sdk/jme3-project-libraries/nbproject/project.properties new file mode 100644 index 000000000..7a33d7a9d --- /dev/null +++ b/sdk/jme3-project-libraries/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=jMonkeyEngine +nbm.needs.restart=true +spec.version.base=0.8.0 diff --git a/sdk/jme3-project-libraries/nbproject/project.xml b/sdk/jme3-project-libraries/nbproject/project.xml new file mode 100644 index 000000000..c767a4d15 --- /dev/null +++ b/sdk/jme3-project-libraries/nbproject/project.xml @@ -0,0 +1,12 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.project.libraries + + + + + + diff --git a/sdk/jme3-project-libraries/nbproject/suite.properties b/sdk/jme3-project-libraries/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-project-libraries/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/Bundle.properties b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/Bundle.properties new file mode 100644 index 000000000..0769c47d8 --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/Bundle.properties @@ -0,0 +1,6 @@ +jme3-libraries=jme3-libraries +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin contains the external libraries needed by jMonkeyEngine3 that are used to run and distribute your jMonkeyPlatform applications. +OpenIDE-Module-Name=Project Libraries +OpenIDE-Module-Short-Description=Provides jME3 External Libraries for jMP Projects diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-gui.xml b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-gui.xml new file mode 100644 index 000000000..f639c2154 --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-gui.xml @@ -0,0 +1,27 @@ + + + + + jme3-libraries-gui + j2se + com.jme3.gde.project.libraries.Bundle + + classpath + jar:nbinst://com.jme3.gde.project.libraries/libs/eventbus-1.4.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/nifty-1.3-SNAPSHOT.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/nifty-default-controls-1.3-SNAPSHOT.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/nifty-style-black-1.3-SNAPSHOT.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/xmlpull-xpp3-1.1.4c.jar!/ + + + src + + + + javadoc + + + diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-lwjgl-minimum.xml b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-lwjgl-minimum.xml new file mode 100644 index 000000000..914c59938 --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-lwjgl-minimum.xml @@ -0,0 +1,25 @@ + + + + + jme3-libraries-lwjgl-minimum + j2se + com.jme3.gde.project.libraries.Bundle + + classpath + jar:nbinst://com.jme3.gde.project.libraries/libs/jME3-lwjgl-natives.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/jinput.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/lwjgl.jar!/ + + + src + + + + javadoc + + + diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-oggvorbis.xml b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-oggvorbis.xml new file mode 100644 index 000000000..660a66a45 --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-oggvorbis.xml @@ -0,0 +1,24 @@ + + + + + jme3-libraries-oggvorbis + j2se + com.jme3.gde.project.libraries.Bundle + + classpath + jar:nbinst://com.jme3.gde.project.libraries/libs/j-ogg-oggd.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/j-ogg-vorbisd.jar!/ + + + src + + + + javadoc + + + diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-physics.xml b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-physics.xml new file mode 100644 index 000000000..eeafd03b3 --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-physics.xml @@ -0,0 +1,25 @@ + + + + + jme3-libraries-physics + j2se + com.jme3.gde.project.libraries.Bundle + + classpath + jar:nbinst://com.jme3.gde.project.libraries/libs/jbullet.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/stack-alloc.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/vecmath.jar!/ + + + src + + + + javadoc + + + diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-video.xml b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-video.xml new file mode 100644 index 000000000..082f6792e --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries-video.xml @@ -0,0 +1,22 @@ + + + + + jme3-libraries-video + j2se + com.jme3.gde.project.libraries.Bundle + + classpath + + + src + + + + javadoc + + + diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries.xml b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries.xml new file mode 100644 index 000000000..b04d01b63 --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/jme3-libraries.xml @@ -0,0 +1,35 @@ + + + + + jme3-libraries + j2se + com.jme3.gde.project.libraries.Bundle + + classpath + jar:nbinst://com.jme3.gde.project.libraries/libs/j-ogg-oggd.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/j-ogg-vorbisd.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/jME3-lwjgl-natives.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/jbullet.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/jinput.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/lwjgl.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/eventbus-1.4.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/nifty-1.3-SNAPSHOT.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/nifty-default-controls-1.3-SNAPSHOT.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/nifty-style-black-1.3-SNAPSHOT.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/stack-alloc.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/vecmath.jar!/ + jar:nbinst://com.jme3.gde.project.libraries/libs/xmlpull-xpp3-1.1.4c.jar!/ + + + src + + + + javadoc + + + diff --git a/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/layer.xml b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/layer.xml new file mode 100644 index 000000000..8ab0510ae --- /dev/null +++ b/sdk/jme3-project-libraries/src/com/jme3/gde/project/libraries/layer.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/sdk/jme3-project-testdata/build.xml b/sdk/jme3-project-testdata/build.xml new file mode 100644 index 000000000..88e7d85b6 --- /dev/null +++ b/sdk/jme3-project-testdata/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.project.testdata. + + diff --git a/sdk/jme3-project-testdata/manifest.mf b/sdk/jme3-project-testdata/manifest.mf new file mode 100644 index 000000000..1dae9591a --- /dev/null +++ b/sdk/jme3-project-testdata/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.project.testdata/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/project/testdata/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/project/testdata/Bundle.properties + diff --git a/sdk/jme3-project-testdata/nbproject/build-impl.xml b/sdk/jme3-project-testdata/nbproject/build-impl.xml new file mode 100644 index 000000000..f257fc50b --- /dev/null +++ b/sdk/jme3-project-testdata/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-project-testdata/nbproject/genfiles.properties b/sdk/jme3-project-testdata/nbproject/genfiles.properties new file mode 100644 index 000000000..1b12c464b --- /dev/null +++ b/sdk/jme3-project-testdata/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=ea5e0ad8 +build.xml.script.CRC32=29c54332 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.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=ea5e0ad8 +nbproject/build-impl.xml.script.CRC32=bbb19b51 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.1 diff --git a/sdk/jme3-project-testdata/nbproject/project.properties b/sdk/jme3-project-testdata/nbproject/project.properties new file mode 100644 index 000000000..ea6e9234e --- /dev/null +++ b/sdk/jme3-project-testdata/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=jMonkeyEngine +nbm.needs.restart=true +spec.version.base=0.5.0 diff --git a/sdk/jme3-project-testdata/nbproject/project.xml b/sdk/jme3-project-testdata/nbproject/project.xml new file mode 100644 index 000000000..f8ba0fa6c --- /dev/null +++ b/sdk/jme3-project-testdata/nbproject/project.xml @@ -0,0 +1,12 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.project.testdata + + + + + + diff --git a/sdk/jme3-project-testdata/nbproject/suite.properties b/sdk/jme3-project-testdata/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-project-testdata/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/Bundle.properties b/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/Bundle.properties new file mode 100644 index 000000000..cc7c70d01 --- /dev/null +++ b/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/Bundle.properties @@ -0,0 +1,6 @@ +jme3-test-data=jme3-test-data +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin contains the test data needed for the jme3 test classes. +OpenIDE-Module-Name=Project Test Data +OpenIDE-Module-Short-Description=Provides Test Data for jME3 Tests and Examples diff --git a/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/jme3-test-data.xml b/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/jme3-test-data.xml new file mode 100644 index 000000000..e935c509b --- /dev/null +++ b/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/jme3-test-data.xml @@ -0,0 +1,23 @@ + + + + + jme3-test-data + j2se + com.jme3.gde.project.testdata.Bundle + + classpath + jar:nbinst://com.jme3.gde.project.testdata/libs/jme3testdata.jar!/ + + + src + + + + javadoc + + + diff --git a/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/layer.xml b/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/layer.xml new file mode 100644 index 000000000..47e2501b5 --- /dev/null +++ b/sdk/jme3-project-testdata/src/com/jme3/gde/project/testdata/layer.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sdk/jme3-scenecomposer/build.xml b/sdk/jme3-scenecomposer/build.xml new file mode 100644 index 000000000..a6c694637 --- /dev/null +++ b/sdk/jme3-scenecomposer/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.scenecomposer. + + diff --git a/sdk/jme3-scenecomposer/manifest.mf b/sdk/jme3-scenecomposer/manifest.mf new file mode 100644 index 000000000..04bbdaf5c --- /dev/null +++ b/sdk/jme3-scenecomposer/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.scenecomposer/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/scenecomposer/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/scenecomposer/Bundle.properties + diff --git a/sdk/jme3-scenecomposer/nbproject/build-impl.xml b/sdk/jme3-scenecomposer/nbproject/build-impl.xml new file mode 100644 index 000000000..0823d4816 --- /dev/null +++ b/sdk/jme3-scenecomposer/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-scenecomposer/nbproject/genfiles.properties b/sdk/jme3-scenecomposer/nbproject/genfiles.properties new file mode 100644 index 000000000..6a7a8030a --- /dev/null +++ b/sdk/jme3-scenecomposer/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=d9817bc3 +build.xml.script.CRC32=866b78de +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=d9817bc3 +nbproject/build-impl.xml.script.CRC32=a6bab88d +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-scenecomposer/nbproject/project.properties b/sdk/jme3-scenecomposer/nbproject/project.properties new file mode 100644 index 000000000..c6ff638f1 --- /dev/null +++ b/sdk/jme3-scenecomposer/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen +nbm.needs.restart=true +spec.version.base=0.6.1 diff --git a/sdk/jme3-scenecomposer/nbproject/project.xml b/sdk/jme3-scenecomposer/nbproject/project.xml new file mode 100644 index 000000000..adeb3671d --- /dev/null +++ b/sdk/jme3-scenecomposer/nbproject/project.xml @@ -0,0 +1,158 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.scenecomposer + + + + com.jme3.gde.core + + + + 1 + 0.11 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.5 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.5 + + + + com.jme3.gde.ogrexml + + + + 1 + 0.8 + + + + org.netbeans.api.progress + + + + 1 + 1.16.1.1 + + + + org.netbeans.modules.settings + + + + 1 + 1.22.1.1 + + + + org.netbeans.spi.palette + + + + 1 + 1.20.1 + + + + org.openide.actions + + + + 6.12.1.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.explorer + + + + 6.22.2.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.30.1 + + + + + com.jme3.gde.scenecomposer + + + + diff --git a/sdk/jme3-scenecomposer/nbproject/suite.properties b/sdk/jme3-scenecomposer/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-scenecomposer/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/AddSceneComposer.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/AddSceneComposer.java new file mode 100644 index 000000000..7e29f9ef4 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/AddSceneComposer.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.util.Iterator; +import java.util.List; + +public final class AddSceneComposer implements ActionListener { + + private final List context; + + public AddSceneComposer(List context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + for (Iterator it = context.iterator(); it.hasNext();) { + SpatialAssetDataObject spatialAssetDataObject = it.next(); + ProjectAssetManager manager=spatialAssetDataObject.getLookup().lookup(ProjectAssetManager.class); + if(manager == null) return; + SceneComposerTopComponent composer=SceneComposerTopComponent.findInstance(); + composer.addModel(spatialAssetDataObject); + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties new file mode 100644 index 000000000..74dd0b095 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties @@ -0,0 +1,46 @@ +CTL_AddSceneComposer=Add in SceneComposer +CTL_LinkSceneComposer=Link in SceneComposer +CTL_OpenSceneComposer=Edit in SceneComposer +CTL_SceneComposerAction=SceneComposer +CTL_SceneComposerTopComponent=SceneComposer Window +CTL_SomeAction=SomeAction +HINT_SceneComposerTopComponent=This is a SceneComposer window +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides simple scene composing for jMonkeyPlatform. +OpenIDE-Module-Name=Simple SceneComposer +OpenIDE-Module-Short-Description=Provides Simple Scene Composing for jMP +SceneComposerTopComponent.addObjectButton.text= +SceneComposerTopComponent.jLabel1.text= +SceneComposerTopComponent.jLabel2.text= +SceneComposerTopComponent.sceneInfoLabel3.text=jLabel3 +SceneComposerTopComponent.scenInfoLabel4.text=jLabel3 +SceneComposerTopComponent.sceneInfoLabel1.text=.. +SceneComposerTopComponent.sceneInfoLabel2.text=.. +SceneComposerTopComponent.addObjectButton.toolTipText=add selected item +SceneComposerTopComponent.addCursorButton.toolTipText=add selected item at cursor location +SceneComposerTopComponent.addCursorButton.text=cursor +SceneComposerTopComponent.moveToCursorButton.toolTipText=move selected item to cursor +SceneComposerTopComponent.moveToCursorButton.text=cursor +SceneComposerTopComponent.showSelectionToggleButton.toolTipText=display selection +SceneComposerTopComponent.showSelectionToggleButton.text=selection +SceneComposerTopComponent.showGridToggleButton.toolTipText=display grid +SceneComposerTopComponent.showGridToggleButton.text=grid +SceneComposerTopComponent.resetCursorButton.toolTipText=snap cursor to zero +SceneComposerTopComponent.resetCursorButton.text=zero +SceneComposerTopComponent.camToCursorSelectionButton.toolTipText=set camera center to cursor center +SceneComposerTopComponent.camToCursorSelectionButton.text=cursor +SceneComposerTopComponent.cursorToSelectionButton.text=selection +SceneComposerTopComponent.cursorToSelectionButton.toolTipText=snap cursor to selection center +SceneComposerTopComponent.createPhysicsMeshButton.text=add collision shape +SceneComposerTopComponent.createPhysicsMeshButton.toolTipText=Makes the Spatial physics enabled and generates a CollisionShape +SceneComposerTopComponent.jLabel3.text= +SceneComposerTopComponent.sceneInfoPanel.border.title=no scene loaded +SceneComposerTopComponent.palettePanel.border.title=no spatial selected +Templates/JME3/Scene.j3o=Empty jME3 Scene +SceneComposerTopComponent.jPanel4.border.title=Utilities +SceneComposerTopComponent.jCheckBox1.text=dynamic: +SceneComposerTopComponent.jTextField1.text=10 +SceneComposerTopComponent.jLabel4.text=kg +SceneComposerTopComponent.jButton1.text=make character +SceneComposerTopComponent.fixedCheckBox.text=radius/height diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java new file mode 100644 index 000000000..105c1d85d --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009-2010 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.scenecomposer; + +import com.jme3.collision.CollisionResult; +import com.jme3.collision.CollisionResults; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.controller.AbstractCameraController; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.math.Ray; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.scene.Node; + +/** + * + * @author normenhansen + */ +public class ComposerCameraController extends AbstractCameraController { + + private Node rootNode; + private JmeNode jmeRootNode; + + public ComposerCameraController(Camera cam, JmeNode rootNode) { + super(cam, SceneApplication.getApplication().getInputManager()); + this.jmeRootNode = rootNode; + this.rootNode = rootNode.getLookup().lookup(Node.class); + } + + public void checkClick(int button) { + if (button == 0) { + CollisionResults results = new CollisionResults(); + Ray ray = new Ray(); + Vector3f pos = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0).clone(); + Vector3f dir = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0.3f).clone(); + dir.subtractLocal(pos).normalizeLocal(); + ray.setOrigin(pos); + ray.setDirection(dir); + rootNode.collideWith(ray, results); + if (results == null) { + return; + } + final CollisionResult result = results.getClosestCollision(); + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (result != null && result.getGeometry() != null) { + SceneApplication.getApplication().setSelectedNode(jmeRootNode.getChild(result.getGeometry())); + } else { + SceneApplication.getApplication().setSelectedNode(jmeRootNode); + } + } + }); + checkClick = false; + } + if (button == 1) { + CollisionResults results = new CollisionResults(); + Ray ray = new Ray(); + Vector3f pos = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0).clone(); + Vector3f dir = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0.3f).clone(); + dir.subtractLocal(pos).normalizeLocal(); + ray.setOrigin(pos); + ray.setDirection(dir); + rootNode.collideWith(ray, results); + if (results == null) { + return; + } + CollisionResult result = results.getClosestCollision(); + if (result != null) { + ((SceneComposerTopComponent) master).doMoveCursor(result.getContactPoint());//getGeometry().getWorldTranslation().add(result.getGeometry().getWorldRotation().mult(result.getContactPoint()))); + } + checkClickR = false; + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/LinkSceneComposer.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/LinkSceneComposer.java new file mode 100644 index 000000000..c920bd42f --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/LinkSceneComposer.java @@ -0,0 +1,36 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.util.Iterator; +import java.util.List; +import org.openide.filesystems.FileObject; + +public final class LinkSceneComposer implements ActionListener { + + private final List context; + + public LinkSceneComposer(List context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + for (Iterator it = context.iterator(); it.hasNext();) { + SpatialAssetDataObject spatialAssetDataObject = it.next(); + ProjectAssetManager manager = spatialAssetDataObject.getLookup().lookup(ProjectAssetManager.class); + if (manager == null) { + return; + } + FileObject file = spatialAssetDataObject.getPrimaryFile(); + String assetName = manager.getRelativeAssetPath(file.getPath()); + SceneComposerTopComponent composer = SceneComposerTopComponent.findInstance(); + composer.linkModel(manager.getManager(), assetName); + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/OpenSceneComposer.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/OpenSceneComposer.java new file mode 100644 index 000000000..a0574ba5e --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/OpenSceneComposer.java @@ -0,0 +1,69 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer; + +import com.jme3.asset.DesktopAssetManager; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.BinaryModelDataObject; +import com.jme3.scene.Spatial; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.io.IOException; +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; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import sun.misc.Perf.GetPerfAction; + +public final class OpenSceneComposer implements ActionListener { + + private final BinaryModelDataObject context; + + public OpenSceneComposer(BinaryModelDataObject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final ProjectAssetManager manager = context.getLookup().lookup(ProjectAssetManager.class); + if (manager == null) { + return; + } + Runnable call = new Runnable() { + + public void run() { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening in SceneComposer"); + progressHandle.start(); + try { + + final Spatial asset = context.loadAsset(); + + if (asset != null) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + ((DesktopAssetManager) manager.getManager()).clearCache(); + SceneComposerTopComponent composer = SceneComposerTopComponent.findInstance(); + composer.openScene(asset, context, manager); + } + }); + } else { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error opening " + context.getPrimaryFile().getNameExt(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + } finally { + progressHandle.finish(); + } + } + }; + new Thread(call).start(); + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/People_035.gif b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/People_035.gif new file mode 100644 index 000000000..038567624 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/People_035.gif differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Scene.j3o b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Scene.j3o new file mode 100644 index 000000000..95bcaafb6 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Scene.j3o differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form new file mode 100644 index 000000000..c8d7ccaca --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form @@ -0,0 +1,476 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java new file mode 100644 index 000000000..41632df59 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java @@ -0,0 +1,846 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer; + +import com.jme3.asset.AssetManager; +import com.jme3.gde.core.assets.AssetDataObject; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import com.jme3.gde.core.scene.PreviewRequest; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneListener; +import com.jme3.gde.core.scene.SceneRequest; +import com.jme3.gde.core.scene.controller.SceneToolController; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import java.util.Collection; +import java.util.logging.Logger; +import javax.swing.border.TitledBorder; +import org.openide.util.Lookup.Result; +import org.openide.util.LookupEvent; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Confirmation; +import org.openide.awt.Toolbar; +import org.openide.awt.ToolbarPool; +import org.openide.awt.UndoRedo; +import org.openide.filesystems.FileObject; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; + +/** + * TODO: some threading stuff + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.scenecomposer//SceneComposer//EN", +autostore = false) +public final class SceneComposerTopComponent extends TopComponent implements SceneListener, LookupListener { + + private static SceneComposerTopComponent instance; + /** path to the icon used by the component and its open action */ + static final String ICON_PATH = "com/jme3/gde/scenecomposer/jme-logo24.png"; + private static final String PREFERRED_ID = "SceneComposerTopComponent"; + private final Result result; + ComposerCameraController camController; + SceneToolController toolController; + SceneEditorController editorController; +// private SaveCookie saveCookie = new SaveCookieImpl(); + private SceneRequest currentRequest; + private HelpCtx ctx = new HelpCtx("sdk.scene_composer"); + + public SceneComposerTopComponent() { + initComponents(); + setName(NbBundle.getMessage(SceneComposerTopComponent.class, "CTL_SceneComposerTopComponent")); + setToolTipText(NbBundle.getMessage(SceneComposerTopComponent.class, "HINT_SceneComposerTopComponent")); + setIcon(ImageUtilities.loadImage(ICON_PATH, true)); + result = Utilities.actionsGlobalContext().lookupResult(JmeSpatial.class); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + sceneInfoPanel = new javax.swing.JPanel(); + sceneInfoLabel1 = new javax.swing.JLabel(); + sceneInfoLabel2 = new javax.swing.JLabel(); + palettePanel = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jList1 = new javax.swing.JList(); + jToolBar1 = new javax.swing.JToolBar(); + addObjectButton = new javax.swing.JButton(); + addCursorButton = new javax.swing.JButton(); + moveToCursorButton = new javax.swing.JButton(); + jSeparator4 = new javax.swing.JToolBar.Separator(); + jLabel3 = new javax.swing.JLabel(); + showSelectionToggleButton = new javax.swing.JToggleButton(); + showGridToggleButton = new javax.swing.JToggleButton(); + jSeparator3 = new javax.swing.JToolBar.Separator(); + jLabel1 = new javax.swing.JLabel(); + resetCursorButton = new javax.swing.JButton(); + cursorToSelectionButton = new javax.swing.JButton(); + jSeparator2 = new javax.swing.JToolBar.Separator(); + jLabel2 = new javax.swing.JLabel(); + camToCursorSelectionButton = new javax.swing.JButton(); + jSeparator1 = new javax.swing.JToolBar.Separator(); + jPanel3 = new javax.swing.JPanel(); + jPanel4 = new javax.swing.JPanel(); + jToolBar2 = new javax.swing.JToolBar(); + createPhysicsMeshButton = new javax.swing.JButton(); + jCheckBox1 = new javax.swing.JCheckBox(); + jTextField1 = new javax.swing.JTextField(); + jLabel4 = new javax.swing.JLabel(); + jToolBar3 = new javax.swing.JToolBar(); + jButton1 = new javax.swing.JButton(); + fixedCheckBox = new javax.swing.JCheckBox(); + radiusSpinner = new javax.swing.JSpinner(); + heightSpinner = new javax.swing.JSpinner(); + + setBackground(new java.awt.Color(204, 204, 204)); + + sceneInfoPanel.setBackground(new java.awt.Color(204, 204, 204)); + sceneInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.sceneInfoPanel.border.title"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(sceneInfoLabel1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.sceneInfoLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(sceneInfoLabel2, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.sceneInfoLabel2.text")); // NOI18N + + javax.swing.GroupLayout sceneInfoPanelLayout = new javax.swing.GroupLayout(sceneInfoPanel); + sceneInfoPanel.setLayout(sceneInfoPanelLayout); + sceneInfoPanelLayout.setHorizontalGroup( + sceneInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(sceneInfoLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) + .addComponent(sceneInfoLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) + ); + sceneInfoPanelLayout.setVerticalGroup( + sceneInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sceneInfoPanelLayout.createSequentialGroup() + .addComponent(sceneInfoLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(sceneInfoLabel2) + .addContainerGap(93, Short.MAX_VALUE)) + ); + + palettePanel.setBackground(new java.awt.Color(204, 204, 204)); + palettePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.palettePanel.border.title"))); // NOI18N + + jScrollPane1.setViewportView(jList1); + + javax.swing.GroupLayout palettePanelLayout = new javax.swing.GroupLayout(palettePanel); + palettePanel.setLayout(palettePanelLayout); + palettePanelLayout.setHorizontalGroup( + palettePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 211, Short.MAX_VALUE) + ); + palettePanelLayout.setVerticalGroup( + palettePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) + ); + + jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + addObjectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/add.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(addObjectButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.addObjectButton.text")); // NOI18N + addObjectButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.addObjectButton.toolTipText")); // NOI18N + addObjectButton.setEnabled(false); + addObjectButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + addObjectButtonActionPerformed(evt); + } + }); + jToolBar1.add(addObjectButton); + + addCursorButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/add.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(addCursorButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.addCursorButton.text")); // NOI18N + addCursorButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.addCursorButton.toolTipText")); // NOI18N + addCursorButton.setEnabled(false); + addCursorButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + addCursorButtonActionPerformed(evt); + } + }); + jToolBar1.add(addCursorButton); + + moveToCursorButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/move.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(moveToCursorButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveToCursorButton.text")); // NOI18N + moveToCursorButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveToCursorButton.toolTipText")); // NOI18N + moveToCursorButton.setFocusable(false); + moveToCursorButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + moveToCursorButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + moveToCursorButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + moveToCursorButtonActionPerformed(evt); + } + }); + jToolBar1.add(moveToCursorButton); + jToolBar1.add(jSeparator4); + + jLabel3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/box_wire.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel3.text")); // NOI18N + jToolBar1.add(jLabel3); + + org.openide.awt.Mnemonics.setLocalizedText(showSelectionToggleButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showSelectionToggleButton.text")); // NOI18N + showSelectionToggleButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showSelectionToggleButton.toolTipText")); // NOI18N + showSelectionToggleButton.setFocusable(false); + showSelectionToggleButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + showSelectionToggleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + showSelectionToggleButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + showSelectionToggleButtonActionPerformed(evt); + } + }); + jToolBar1.add(showSelectionToggleButton); + + org.openide.awt.Mnemonics.setLocalizedText(showGridToggleButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showGridToggleButton.text")); // NOI18N + showGridToggleButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showGridToggleButton.toolTipText")); // NOI18N + showGridToggleButton.setFocusable(false); + showGridToggleButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + showGridToggleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + showGridToggleButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + showGridToggleButtonActionPerformed(evt); + } + }); + jToolBar1.add(showGridToggleButton); + jToolBar1.add(jSeparator3); + + jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/cursor.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel1.text")); // NOI18N + jToolBar1.add(jLabel1); + + org.openide.awt.Mnemonics.setLocalizedText(resetCursorButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.resetCursorButton.text")); // NOI18N + resetCursorButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.resetCursorButton.toolTipText")); // NOI18N + resetCursorButton.setFocusable(false); + resetCursorButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + resetCursorButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + resetCursorButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + resetCursorButtonActionPerformed(evt); + } + }); + jToolBar1.add(resetCursorButton); + + org.openide.awt.Mnemonics.setLocalizedText(cursorToSelectionButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.cursorToSelectionButton.text")); // NOI18N + cursorToSelectionButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.cursorToSelectionButton.toolTipText")); // NOI18N + cursorToSelectionButton.setFocusable(false); + cursorToSelectionButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + cursorToSelectionButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + cursorToSelectionButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cursorToSelectionButtonActionPerformed(evt); + } + }); + jToolBar1.add(cursorToSelectionButton); + jToolBar1.add(jSeparator2); + + jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/camera.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel2.text")); // NOI18N + jToolBar1.add(jLabel2); + + org.openide.awt.Mnemonics.setLocalizedText(camToCursorSelectionButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.camToCursorSelectionButton.text")); // NOI18N + camToCursorSelectionButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.camToCursorSelectionButton.toolTipText")); // NOI18N + camToCursorSelectionButton.setFocusable(false); + camToCursorSelectionButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + camToCursorSelectionButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + camToCursorSelectionButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + camToCursorSelectionButtonActionPerformed(evt); + } + }); + jToolBar1.add(camToCursorSelectionButton); + jToolBar1.add(jSeparator1); + + jPanel3.setBackground(new java.awt.Color(204, 204, 204)); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 190, Short.MAX_VALUE) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel3); + + jPanel4.setBackground(new java.awt.Color(204, 204, 204)); + jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jPanel4.border.title"))); // NOI18N + + jToolBar2.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar2.setFloatable(false); + jToolBar2.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(createPhysicsMeshButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.createPhysicsMeshButton.text")); // NOI18N + createPhysicsMeshButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.createPhysicsMeshButton.toolTipText")); // NOI18N + createPhysicsMeshButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + createPhysicsMeshButtonActionPerformed(evt); + } + }); + jToolBar2.add(createPhysicsMeshButton); + + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jCheckBox1.text")); // NOI18N + jToolBar2.add(jCheckBox1); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jTextField1.text")); // NOI18N + jToolBar2.add(jTextField1); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel4.text")); // NOI18N + jToolBar2.add(jLabel4); + + jToolBar3.setBackground(new java.awt.Color(204, 204, 204)); + jToolBar3.setFloatable(false); + jToolBar3.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar3.add(jButton1); + + fixedCheckBox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(fixedCheckBox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.fixedCheckBox.text")); // NOI18N + fixedCheckBox.setEnabled(false); + jToolBar3.add(fixedCheckBox); + + radiusSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(0.5f), null, null, Float.valueOf(0.1f))); + jToolBar3.add(radiusSpinner); + + heightSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(1.8f), null, null, Float.valueOf(0.1f))); + jToolBar3.add(heightSpinner); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE) + .addComponent(jToolBar3, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(83, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(palettePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(sceneInfoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 696, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(palettePanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(sceneInfoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + }// //GEN-END:initComponents + + private void addObjectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addObjectButtonActionPerformed + if (jList1.getSelectedValue() != null && editorController != null) { + editorController.addSpatial(jList1.getSelectedValue().toString()); + } + + }//GEN-LAST:event_addObjectButtonActionPerformed + + private void addCursorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addCursorButtonActionPerformed + if (jList1.getSelectedValue() != null && editorController != null) { + editorController.addSpatial(jList1.getSelectedValue().toString(), toolController.getCursorLocation()); + } + + }//GEN-LAST:event_addCursorButtonActionPerformed + + private void showSelectionToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showSelectionToggleButtonActionPerformed + if (toolController != null) { + toolController.setShowSelection(showSelectionToggleButton.isSelected()); + } + }//GEN-LAST:event_showSelectionToggleButtonActionPerformed + + private void showGridToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showGridToggleButtonActionPerformed + if (toolController != null) { + toolController.setShowGrid(showGridToggleButton.isSelected()); + } + }//GEN-LAST:event_showGridToggleButtonActionPerformed + + private void moveToCursorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveToCursorButtonActionPerformed + if (editorController != null) { + editorController.moveSelectedSpatial(toolController.getCursorLocation()); + } + }//GEN-LAST:event_moveToCursorButtonActionPerformed + + private void resetCursorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetCursorButtonActionPerformed + if (toolController != null) { + toolController.setCursorLocation(Vector3f.ZERO); + } + }//GEN-LAST:event_resetCursorButtonActionPerformed + + private void camToCursorSelectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_camToCursorSelectionButtonActionPerformed + camController.setCamFocus(toolController.getCursorLocation()); + }//GEN-LAST:event_camToCursorSelectionButtonActionPerformed + + private void cursorToSelectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cursorToSelectionButtonActionPerformed + if (toolController != null) { + toolController.snapCursorToSelection(); + } + }//GEN-LAST:event_cursorToSelectionButtonActionPerformed + + private void createPhysicsMeshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createPhysicsMeshButtonActionPerformed + if (editorController != null) { + if (jCheckBox1.isSelected()) { + try { + editorController.createDynamicPhysicsMeshForSelectedSpatial(Float.parseFloat(jTextField1.getText())); + } catch (Exception e) { + } + } else { + editorController.createPhysicsMeshForSelectedSpatial(); + } + } + }//GEN-LAST:event_createPhysicsMeshButtonActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + // TODO add your handling code here: + if (editorController != null) { + boolean auto = !fixedCheckBox.isSelected(); + float radius = (Float) radiusSpinner.getValue(); + float height = (Float) heightSpinner.getValue(); + editorController.createCharacterControlForSelectedSpatial(false, radius, height); + } + + }//GEN-LAST:event_jButton1ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton addCursorButton; + private javax.swing.JButton addObjectButton; + private javax.swing.JButton camToCursorSelectionButton; + private javax.swing.JButton createPhysicsMeshButton; + private javax.swing.JButton cursorToSelectionButton; + private javax.swing.JCheckBox fixedCheckBox; + private javax.swing.JSpinner heightSpinner; + private javax.swing.JButton jButton1; + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JList jList1; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JToolBar.Separator jSeparator1; + private javax.swing.JToolBar.Separator jSeparator2; + private javax.swing.JToolBar.Separator jSeparator3; + private javax.swing.JToolBar.Separator jSeparator4; + private javax.swing.JTextField jTextField1; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToolBar jToolBar2; + private javax.swing.JToolBar jToolBar3; + private javax.swing.JButton moveToCursorButton; + private javax.swing.JPanel palettePanel; + private javax.swing.JSpinner radiusSpinner; + private javax.swing.JButton resetCursorButton; + private javax.swing.JLabel sceneInfoLabel1; + private javax.swing.JLabel sceneInfoLabel2; + private javax.swing.JPanel sceneInfoPanel; + private javax.swing.JToggleButton showGridToggleButton; + private javax.swing.JToggleButton showSelectionToggleButton; + // End of variables declaration//GEN-END:variables + + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized SceneComposerTopComponent getDefault() { + if (instance == null) { + instance = new SceneComposerTopComponent(); + } + return instance; + } + + /** + * Obtain the SceneComposerTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized SceneComposerTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(SceneComposerTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof SceneComposerTopComponent) { + return (SceneComposerTopComponent) win; + } + Logger.getLogger(SceneComposerTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public HelpCtx getHelpCtx() { + //this call is for single components: + //HelpCtx.setHelpIDString(this, "com.jme3.gde.core.sceneviewer"); + return ctx; + } + + @Override + public UndoRedo getUndoRedo() { + return Lookup.getDefault().lookup(UndoRedo.class); + } + + @Override + public void componentOpened() { + super.componentOpened(); + Toolbar tb = ToolbarPool.getDefault().findToolbar("SceneComposer-Tools"); + if (tb != null) { + if (!tb.isVisible()) { + tb.setVisible(true); + } + } + } + + @Override + public void componentClosed() { + super.componentClosed(); + if (currentRequest != null) { + SceneApplication.getApplication().closeScene(currentRequest); + } + Toolbar tb = ToolbarPool.getDefault().findToolbar("SceneComposer-Tools"); + if (tb != null) { + if (tb.isVisible()) { + tb.setVisible(false); + } + } + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + private void setSelectedObjectText(final String text) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (text != null) { + //XXX: wtf? why do i have to repaint? + ((TitledBorder) palettePanel.getBorder()).setTitle("Palette:" + text); + palettePanel.repaint(); + addObjectButton.setEnabled(true); + addCursorButton.setEnabled(true); + } else { + ((TitledBorder) palettePanel.getBorder()).setTitle("no spatial selected"); + palettePanel.repaint(); + addObjectButton.setEnabled(false); + addCursorButton.setEnabled(false); + } + } + }); + } + + private void setSelectionData(final Boolean node) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (node == null) { + jList1.setListData(new String[]{}); + } else if (node) { + jList1.setListData(new String[]{"Node", "Particle Emitter", "Audio Node", "Picture", "Point Light", "Directional Light", "Ambient Light"}); + } else { + jList1.setListData(new String[]{"Point Light", "Directional Light", "Ambient Light"}); + } + } + }); + } + + /** + * method to set the state of the ui items + */ + private void setSceneInfo(final JmeNode jmeNode, final FileObject file, final boolean active) { + final SceneComposerTopComponent inst = this; + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (jmeNode != null) { + ((TitledBorder) sceneInfoPanel.getBorder()).setTitle(jmeNode.getName()); + selectSpatial(jmeNode); + } else { + ((TitledBorder) sceneInfoPanel.getBorder()).setTitle(""); + } + //XXX: wtf? why do i have to repaint? + sceneInfoPanel.repaint(); + + if (!active) { + result.removeLookupListener(inst); + addObjectButton.setEnabled(false); + addCursorButton.setEnabled(false); + showSelectionToggleButton.setSelected(false); + showGridToggleButton.setSelected(false); + sceneInfoLabel1.setText(""); + sceneInfoLabel2.setText(""); + sceneInfoLabel1.setToolTipText(""); + sceneInfoLabel2.setToolTipText(""); + close(); + } else { + showSelectionToggleButton.setSelected(false); + showGridToggleButton.setSelected(false); + //TODO: threading + if (file != null) { + sceneInfoLabel1.setText("Name: " + file.getNameExt()); + sceneInfoLabel2.setText("Size: " + file.getSize() / 1024 + " kB"); + sceneInfoLabel1.setToolTipText("Name: " + file.getNameExt()); + sceneInfoLabel2.setToolTipText("Size: " + file.getSize() / 1024 + " kB"); + } + open(); + requestActive(); + } + } + }); + } + + public void openScene(Spatial spat, AssetDataObject file, ProjectAssetManager manager) { + cleanupControllers(); + SceneApplication.getApplication().addSceneListener(this); + result.addLookupListener(this); + //TODO: handle request change + Node node; + if (spat instanceof Node) { + node = (Node) spat; + } else { + node = new Node(); + node.attachChild(spat); + } + JmeNode jmeNode = NodeUtility.createNode(node, file, false); + SceneRequest request = new SceneRequest(this, jmeNode, manager); + request.setDataObject(file); + request.setHelpCtx(ctx); +// file.setSaveCookie(saveCookie); + if (editorController != null) { + editorController.cleanup(); + } + editorController = new SceneEditorController(jmeNode, file); + this.currentRequest = request; + request.setWindowTitle("SceneComposer - " + manager.getRelativeAssetPath(file.getPrimaryFile().getPath())); + request.setToolNode(new Node("SceneComposerToolNode")); + SceneApplication.getApplication().requestScene(request); + } + + public void addModel(Spatial model) { + if (editorController != null) { + editorController.addModel(model, toolController.getCursorLocation()); + } + } + + public void addModel(SpatialAssetDataObject model) { + if (editorController != null) { + editorController.addModel(model, toolController.getCursorLocation()); + } + } + + public void linkModel(AssetManager manager, String assetName) { + if (editorController != null) { + editorController.linkModel(manager, assetName, toolController.getCursorLocation()); + } + } + + public void doMoveCursor(Vector3f vector) { + if (toolController != null) { + toolController.doSetCursorLocation(vector); + } + } + + /** + * listener for node selection changes + */ + public void resultChanged(LookupEvent ev) { + if (currentRequest == null || !currentRequest.isDisplayed()) { + return; + } + Collection items = (Collection) result.allInstances(); + for (JmeSpatial spatial : items) { + selectSpatial(spatial); + return; + } + } + + private void selectSpatial(JmeSpatial spatial) { + if (spatial == null) { + setSelectedObjectText(null); + setSelectionData(null); + if (editorController != null) { + editorController.setSelectedSpat(spatial); + } + setActivatedNodes(new org.openide.nodes.Node[]{}); + return; + } else { + if (toolController != null) { + toolController.updateSelection(spatial.getLookup().lookup(Spatial.class)); + } + } + if (editorController == null) { + return; + } + editorController.setSelectedSpat(spatial); + if (spatial.getLookup().lookup(Node.class) != null) { + setSelectionData(true); + setSelectedObjectText(spatial.getLookup().lookup(Node.class).getName()); + } else if (spatial.getLookup().lookup(Spatial.class) != null) { + setSelectionData(false); + setSelectedObjectText(spatial.getLookup().lookup(Spatial.class).getName()); + } else { + setSelectedObjectText(null); + setSelectionData(false); + } + SceneApplication.getApplication().setSelectedNode(spatial); + setActivatedNodes(new org.openide.nodes.Node[]{spatial}); + } + + private boolean checkSaved() { + if (editorController != null && editorController.isNeedSave()) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Your Scene is not saved, do you want to save?", + NotifyDescriptor.YES_NO_OPTION, + NotifyDescriptor.WARNING_MESSAGE); + Object result = DialogDisplayer.getDefault().notify(msg); + if (NotifyDescriptor.CANCEL_OPTION.equals(result)) { + return false; + } else if (NotifyDescriptor.YES_OPTION.equals(result)) { + editorController.saveScene(); + return true; + } else if (NotifyDescriptor.NO_OPTION.equals(result)) { + return true; + } + } + return true; + } + +// public class SaveCookieImpl implements SaveCookie { +// +// public void save() throws IOException { +// editorController.saveScene(); +// //TODO: update infos.. runs on callable.. +//// if (currentRequest != null) { +//// setSceneInfo(currentRequest.getRootNode(), editorController.getCurrentFileObject(), true); +//// } +// } +// } + private void cleanupControllers() { + if (camController != null) { + camController.disable(); + camController = null; + } + if (toolController != null) { + toolController.cleanup(); + toolController = null; + } + if (editorController != null) { + editorController.cleanup(); + editorController = null; + } + setActivatedNodes(new org.openide.nodes.Node[]{}); + } + + /* + * SceneListener + */ + public void sceneRequested(SceneRequest request) { + if (request.equals(currentRequest)) { + setSceneInfo(currentRequest.getJmeNode(), editorController.getCurrentFileObject(), true); + if (camController != null) { + camController.disable(); + } + if (toolController != null) { + toolController.cleanup(); + } + toolController = new SceneToolController(currentRequest.getToolNode(), currentRequest.getManager().getManager()); + camController = new ComposerCameraController(SceneApplication.getApplication().getCamera(), request.getJmeNode()); + camController.setMaster(this); + camController.enable(); + }/* else { + SceneApplication.getApplication().removeSceneListener(this); + currentRequest = null; + setSceneInfo(null, false); + cleanupControllers(); + }*/ + } + + public boolean sceneClose(SceneRequest request) { + if (request.equals(currentRequest)) { +// if (checkSaved()) { + SceneApplication.getApplication().removeSceneListener(this); + currentRequest = null; + setSceneInfo(null, null, false); + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + cleanupControllers(); + } + }); +// } else { +// return false; +// } + } + return true; + } + + public void previewRequested(PreviewRequest request) { + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponentSettings.xml b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponentSettings.xml new file mode 100644 index 000000000..1fa7ad314 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponentWstcref.xml b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponentWstcref.xml new file mode 100644 index 000000000..26a40bd3f --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditorController.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditorController.java new file mode 100644 index 000000000..1082bea2f --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditorController.java @@ -0,0 +1,928 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer; + +import com.jme3.asset.AssetManager; +import com.jme3.asset.DesktopAssetManager; +import com.jme3.asset.ModelKey; +import com.jme3.audio.AudioNode; +import com.jme3.bullet.collision.shapes.CapsuleCollisionShape; +import com.jme3.bullet.control.CharacterControl; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.effect.EmitterSphereShape; +import com.jme3.effect.ParticleEmitter; +import com.jme3.effect.ParticleMesh; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.light.AmbientLight; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.light.PointLight; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.AssetLinkNode; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.VertexBuffer.Type; +import com.jme3.scene.control.Control; +import com.jme3.ui.Picture; +import com.jme3.util.TangentBinormalGenerator; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +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; +import org.openide.cookies.SaveCookie; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObject; +import org.openide.nodes.NodeEvent; +import org.openide.nodes.NodeListener; +import org.openide.nodes.NodeMemberEvent; +import org.openide.nodes.NodeReorderEvent; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + +/** + * + * @author normenhansen + */ +public class SceneEditorController implements PropertyChangeListener, NodeListener { + + private JmeSpatial jmeRootNode; + private JmeSpatial selectedSpat; + private DataObject currentFileObject; +// private boolean needSave = false; + + public SceneEditorController(JmeSpatial jmeRootNode, DataObject currentFileObject) { + this.jmeRootNode = jmeRootNode; + this.currentFileObject = currentFileObject; + } + + public JmeSpatial getJmeRootNode() { + return jmeRootNode; + } + + public JmeSpatial getSelectedSpat() { + return selectedSpat; + } + + public void setSelectedSpat(JmeSpatial selectedSpat) { + if (this.selectedSpat == selectedSpat) { + return; + } + if (this.selectedSpat != null) { + this.selectedSpat.removePropertyChangeListener(this); + this.selectedSpat.removeNodeListener(this); + } + this.selectedSpat = selectedSpat; + if (selectedSpat != null) { + selectedSpat.addPropertyChangeListener(this);//WeakListeners.propertyChange(this, selectedSpat)); + selectedSpat.addNodeListener(this);//WeakListeners.propertyChange(this, selectedSpat)); + } + } + + public FileObject getCurrentFileObject() { + return currentFileObject.getPrimaryFile(); + } + + public DataObject getCurrentDataObject() { + return currentFileObject; + } + + public void addSpatial(final String name) { + addSpatial(name, new Vector3f(0, 0, 0)); + } + + public void addSpatial(final String name, final Vector3f point) { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doAddSpatial(node, name, point); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doAddSpatial(Spatial selected, String name, Vector3f point) { + Node undoParent = null; + Light undoLight = null; + Spatial undoSpatial = null; + if (selected instanceof Node) { + if ("Node".equals(name)) { + Node node = new Node("Node"); + ((Node) selected).attachChild(node); + refreshSelected(); + undoSpatial = node; + undoParent = ((Node) selected); + } else if ("Particle Emitter".equals(name)) { + ParticleEmitter emit = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 200); + emit.setShape(new EmitterSphereShape(Vector3f.ZERO, 1f)); + emit.setGravity(0); + emit.setLowLife(5); + emit.setHighLife(10); + emit.setInitialVelocity(new Vector3f(0, 0, 0)); + emit.setImagesX(15); + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/Particle.j3md"); + // mat.setTexture("Texture", SceneApplication.getApplication().getAssetManager().loadTexture("Effects/Smoke/Smoke.png")); + emit.setMaterial(mat); + if (point != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(point, localVec); + emit.setLocalTranslation(localVec); + } + ((Node) selected).attachChild(emit); + refreshSelected(); + undoSpatial = emit; + undoParent = ((Node) selected); + } else if ("Audio Node".equals(name)) { + AudioNode node = new AudioNode(); + node.setName("Audio Node"); + if (point != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(point, localVec); + node.setLocalTranslation(localVec); + } + ((Node) selected).attachChild(node); + refreshSelected(); + undoSpatial = node; + undoParent = ((Node) selected); + } else if ("Picture".equals(name)) { + Picture pic = new Picture("Picture"); + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/Particle.j3md"); + pic.setMaterial(mat); + if (point != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(point, localVec); + pic.setLocalTranslation(localVec); + } + ((Node) selected).attachChild(pic); + refreshSelected(); + undoSpatial = pic; + undoParent = ((Node) selected); + } else if ("Point Light".equals(name)) { + PointLight light = new PointLight(); + if (point != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(point, localVec); + light.setPosition(localVec); + } + light.setColor(ColorRGBA.White); + ((Node) selected).addLight(light); + refreshSelected(); + undoLight = light; + undoParent = ((Node) selected); + } else if ("Directional Light".equals(name)) { + DirectionalLight dl = new DirectionalLight(); + dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal()); + dl.setColor(ColorRGBA.White); + ((Node) selected).addLight(dl); + refreshSelected(); + undoLight = dl; + undoParent = ((Node) selected); + } else if ("Node".equals(name)) { + Node node = new Node("Node"); + ((Node) selected).attachChild(node); + refreshSelected(); + undoSpatial = node; + undoParent = ((Node) selected); + } + } else if (selected instanceof Geometry) { + if ("Point Light".equals(name)) { + PointLight light = new PointLight(); + if (point != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(point, localVec); + light.setPosition(localVec); + } + light.setColor(ColorRGBA.White); + selected.addLight(light); + refreshSelected(); + undoLight = light; + undoParent = ((Node) selected); + } else if ("Directional Light".equals(name)) { + DirectionalLight dl = new DirectionalLight(); + dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal()); + dl.setColor(ColorRGBA.White); + selected.addLight(dl); + refreshSelected(); + undoLight = dl; + undoParent = ((Node) selected); + } else if ("Ambient Light".equals(name)) { + AmbientLight dl = new AmbientLight(); + dl.setColor(ColorRGBA.White); + selected.addLight(dl); + refreshSelected(); + undoLight = dl; + undoParent = ((Node) selected); + } + } + AbstractSceneExplorerNode selectedSpat = this.selectedSpat; + addSpatialUndo(undoParent, undoSpatial, undoLight, selectedSpat); + } + + private void addSpatialUndo(final Node undoParent, final Spatial undoSpatial, final Light undoLight, final AbstractSceneExplorerNode parentNode) { + //add undo + if (undoParent != null && undoSpatial != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + //undo stuff here + undoSpatial.removeFromParent(); + } + + @Override + public void sceneRedo() throws CannotRedoException { + //redo stuff here + undoParent.attachChild(undoSpatial); + } + + @Override + public void awtRedo() { + if (parentNode != null) { + parentNode.refresh(true); + } + } + + @Override + public void awtUndo() { + if (parentNode != null) { + parentNode.refresh(true); + } + } + }); + } + if (undoParent != null && undoLight != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + //undo stuff here + undoParent.removeLight(undoLight); + } + + @Override + public void sceneRedo() throws CannotRedoException { + //redo stuff here + undoParent.addLight(undoLight); + } + + @Override + public void awtRedo() { + if (parentNode != null) { + parentNode.refresh(true); + } + } + + @Override + public void awtUndo() { + if (parentNode != null) { + parentNode.refresh(true); + } + } + }); + } + } + + public void moveSelectedSpatial(final Vector3f point) { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doMoveSpatial(node, point); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doMoveSpatial(Spatial selected, Vector3f translation) { + Vector3f localTranslation = selected.getLocalTranslation(); + Vector3f before = new Vector3f(localTranslation); + Node parent = selected.getParent(); + if (parent != null) { + localTranslation.set(translation).subtractLocal(parent.getWorldTranslation()); + localTranslation.divideLocal(parent.getWorldScale()); + //TODO: reuse quaternion.. + new Quaternion().set(parent.getWorldRotation()).inverseLocal().multLocal(localTranslation); + } else { + localTranslation.set(translation); + } + Vector3f after = new Vector3f(localTranslation); + selected.setLocalTranslation(localTranslation); + AbstractSceneExplorerNode selectedSpat = this.selectedSpat; + moveUndo(selected, before, after, selectedSpat); + } + + private void moveUndo(final Spatial spatial, final Vector3f before, final Vector3f after, final AbstractSceneExplorerNode parentNode) { + if (spatial != null && before != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + //undo stuff here + spatial.setLocalTranslation(before); + } + + @Override + public void sceneRedo() throws CannotRedoException { + //redo stuff here + spatial.setLocalTranslation(after); + } + }); + } + } + + public void nudgeSelectedSpatial(final Vector3f amount) { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doNudgeSpatial(node, amount); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doNudgeSpatial(Spatial selected, Vector3f translation) { + Vector3f before = new Vector3f(selected.getLocalTranslation()); + selected.setLocalTranslation(before.add(translation)); + Vector3f after = new Vector3f(selected.getLocalTranslation()); + nudgeUndo(selected, before, after, selectedSpat); + } + + private void nudgeUndo(final Spatial spatial, final Vector3f before, final Vector3f after, final AbstractSceneExplorerNode parentNode) { + if (spatial != null && before != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + //undo stuff here + spatial.setLocalTranslation(before); + } + + @Override + public void sceneRedo() throws CannotRedoException { + //redo stuff here + spatial.setLocalTranslation(after); + } + }); + } + } + + public void rotateSelectedSpatial(final Quaternion amount) { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doRotateSpatial(node, amount); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doRotateSpatial(Spatial selected, Quaternion rotation) { + Quaternion before=new Quaternion(selected.getLocalRotation()); + selected.rotate(rotation); + Quaternion after=new Quaternion(selected.getLocalRotation()); + rotateUndo(selected, before, after, selectedSpat); + } + + private void rotateUndo(final Spatial spatial, final Quaternion before, final Quaternion after, final AbstractSceneExplorerNode parentNode) { + if (spatial != null && before != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + //undo stuff here + spatial.setLocalRotation(before); + } + + @Override + public void sceneRedo() throws CannotRedoException { + //redo stuff here + spatial.setLocalRotation(after); + } + }); + } + } + + public void createTangentsForSelectedSpatial() { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doCreateTangents(node); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doCreateTangents(Spatial selected) { + if (selected instanceof Geometry) { + Geometry geom = (Geometry) selected; + Mesh mesh = geom.getMesh(); + if (mesh != null) { + TangentBinormalGenerator.generate(mesh); + createTrangentsUndo(mesh); + } + } + } + + private void createTrangentsUndo(final Mesh mesh) { + if (mesh != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + mesh.clearBuffer(Type.Tangent); + } + + @Override + public void sceneRedo() throws CannotRedoException { + TangentBinormalGenerator.generate(mesh); + } + }); + } + } + + public void createPhysicsMeshForSelectedSpatial() { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + setNeedsSave(true); + if (node != null) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doCreatePhysicsMesh(node); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doCreatePhysicsMesh(Spatial selected) { + RigidBodyControl control = selected.getControl(RigidBodyControl.class); + if (control != null) { + selected.removeControl(control); + } + Node parent = selected.getParent(); + selected.removeFromParent(); + control = new RigidBodyControl(0); + selected.addControl(new RigidBodyControl(0)); + if (parent != null) { + parent.attachChild(selected); + } + refreshSelected(); + AbstractSceneExplorerNode selectedSpat = this.selectedSpat; + addControlUndo(parent, control, selectedSpat); + } + + public void createDynamicPhysicsMeshForSelectedSpatial(final float weight) { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + setNeedsSave(true); + if (node != null) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doCreateDynamicPhysicsMesh(node, weight); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doCreateDynamicPhysicsMesh(Spatial selected, float weight) { + RigidBodyControl control = selected.getControl(RigidBodyControl.class); + if (control != null) { + selected.removeControl(control); + } + Node parent = selected.getParent(); + selected.removeFromParent(); + control = new RigidBodyControl(weight); + selected.addControl(control); + if (parent != null) { + parent.attachChild(selected); + } + refreshSelected(); + AbstractSceneExplorerNode selectedSpat = this.selectedSpat; + addControlUndo(parent, control, selectedSpat); + } + + public void createCharacterControlForSelectedSpatial(final boolean auto, final float radius, final float height) { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + setNeedsSave(true); + if (node != null) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doCreateCharacterControl(node, auto, radius, height); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doCreateCharacterControl(Spatial selected, boolean auto, float radius, float height) { + CharacterControl control = selected.getControl(CharacterControl.class); + if (control != null) { + selected.removeControl(control); + } + Node parent = selected.getParent(); + selected.removeFromParent(); + if (!auto) { + control = new CharacterControl(new CapsuleCollisionShape(radius, height), 0.03f); + } else { + //TODO: auto-creation by bounding volume + control = new CharacterControl(new CapsuleCollisionShape(radius, height), 0.03f); + } + selected.addControl(control); + if (parent != null) { + parent.attachChild(selected); + } + refreshSelected(); + AbstractSceneExplorerNode selectedSpat = this.selectedSpat; + addControlUndo(parent, control, selectedSpat); + } + + private void addControlUndo(final Node undoParent, final Control undoControl, final AbstractSceneExplorerNode parentNode) { + if (undoParent != null && undoControl != null) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + //undo stuff here + undoParent.removeControl(undoControl); + } + + @Override + public void sceneRedo() throws CannotRedoException { + //redo stuff here + undoParent.addControl(undoControl); + } + + @Override + public void awtRedo() { + if (parentNode != null) { + parentNode.refresh(true); + } + } + + @Override + public void awtUndo() { + if (parentNode != null) { + parentNode.refresh(true); + } + } + }); + } + } + + public void addModel(final SpatialAssetDataObject file, final Vector3f location) { + if (selectedSpat == null) { + return; + } + final Node selected = selectedSpat.getLookup().lookup(Node.class); + ProjectAssetManager manager = file.getLookup().lookup(ProjectAssetManager.class); + if (manager != null) { + ((DesktopAssetManager) manager.getManager()).clearCache(); + } + if (selected != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doAddModel(file, selected, location); + return null; + } + }); + } + } + + public void doAddModel(SpatialAssetDataObject file, Node selected, Vector3f location) { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Adding Model.."); + progressHandle.start(); + try { + Spatial linkNode = (Spatial) file.loadAsset(); + if (linkNode != null) { + selected.attachChild(linkNode); + if (location != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(location, localVec); + linkNode.setLocalTranslation(localVec); + } + } + refreshSelected(); + addSpatialUndo(selected, linkNode, null, selectedSpat); + } catch (Exception ex) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error importing " + file.getName() + "\n" + ex.toString(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + progressHandle.finish(); + + } + + public void linkModel(final AssetManager manager, final String assetName, final Vector3f location) { + if (selectedSpat == null) { + return; + } + final Node selected = selectedSpat.getLookup().lookup(Node.class); + if (selected != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doLinkModel(manager, assetName, selected, location); + return null; + } + }); + } + } + + public void doLinkModel(AssetManager manager, String assetName, Node selected, Vector3f location) { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Adding Model.."); + progressHandle.start(); + try { + if (selected instanceof AssetLinkNode) { + AssetLinkNode linkNode = (AssetLinkNode) selected; + linkNode.attachLinkedChild(manager, new ModelKey(assetName)); + } else { + ((DesktopAssetManager) manager).clearCache(); + ModelKey key = new ModelKey(assetName); + AssetLinkNode linkNode = new AssetLinkNode(key); + linkNode.attachLinkedChildren(manager); + selected.attachChild(linkNode); + if (location != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(location, localVec); + linkNode.setLocalTranslation(localVec); + } + addSpatialUndo(selected, linkNode, null, selectedSpat); + } + refreshSelected(); + } catch (Exception ex) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error importing " + assetName + "\n" + ex.toString(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + progressHandle.finish(); + + } + + public void addModel(final Spatial file) { + addModel(file, null); + } + + public void addModel(final Spatial file, final Vector3f location) { + if (selectedSpat == null) { + return; + } + final Node selected = selectedSpat.getLookup().lookup(Node.class); + if (selected != null) { + setNeedsSave(true); + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doAddModel(file, selected, location); + return null; + } + }); + } + } + + public void doAddModel(Spatial file, Node selected, Vector3f location) { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Adding Model.."); + progressHandle.start(); + try { + if (file != null) { + selected.attachChild(file); + if (location != null) { + Vector3f localVec = new Vector3f(); + selected.worldToLocal(location, localVec); + file.setLocalTranslation(localVec); + } + } + refreshSelected(); + addSpatialUndo(selected, file, null, selectedSpat); + } catch (Exception ex) { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error importing " + file.getName() + "\n" + ex.toString(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(msg); + } + progressHandle.finish(); + + } + + public void setNeedsSave(boolean state) { + currentFileObject.setModified(state); + } + + public boolean isNeedSave() { + return currentFileObject.isModified(); + } + + public void propertyChange(PropertyChangeEvent evt) { +// if ((evt.getOldValue() == null && !(evt.getNewValue() == null)) || ((evt.getOldValue() != null) && !evt.getOldValue().equals(evt.getNewValue()))) { +// setNeedsSave(true); +// } + } + + public void childrenAdded(NodeMemberEvent ev) { +// setNeedsSave(true); + } + + public void childrenRemoved(NodeMemberEvent ev) { +// setNeedsSave(true); + } + + public void childrenReordered(NodeReorderEvent ev) { +// setNeedsSave(true); + } + + public void nodeDestroyed(NodeEvent ev) { +// setNeedsSave(true); + } + + public void saveScene() { + try { + currentFileObject.getLookup().lookup(SaveCookie.class).save(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void refreshSelected(final JmeSpatial spat) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (spat != null) { + spat.refresh(false); + } + } + }); + + } + + private void refreshSelected() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (getSelectedSpat() != null) { + getSelectedSpat().refresh(false); + } + } + }); + + } + + private void refreshSelectedParent() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (getSelectedSpat() != null) { + ((JmeSpatial) getSelectedSpat().getParentNode()).refresh(false); + } + } + }); + + } + + private void refreshRoot() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (getJmeRootNode() != null) { + getJmeRootNode().refresh(true); + } + } + }); + + } + + public void cleanup() { + final Node node = jmeRootNode.getLookup().lookup(Node.class); + if (selectedSpat != null) { + selectedSpat.removePropertyChangeListener(this); + } + } + +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/add.gif b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/add.gif new file mode 100644 index 000000000..e549f6cc2 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/add.gif differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/box_wire.gif b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/box_wire.gif new file mode 100644 index 000000000..af6eeddcc Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/box_wire.gif differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/camera.gif b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/camera.gif new file mode 100644 index 000000000..7a3e07819 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/camera.gif differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/cursor.gif b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/cursor.gif new file mode 100644 index 000000000..64dbd6786 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/cursor.gif differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/jme-logo.png b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/jme-logo.png new file mode 100644 index 000000000..a06344bbd Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/jme-logo.png differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/jme-logo24.png b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/jme-logo24.png new file mode 100644 index 000000000..8a8e03123 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/jme-logo24.png differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/layer.xml b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/layer.xml new file mode 100644 index 000000000..a663d4594 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/layer.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/link.gif b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/link.gif new file mode 100644 index 000000000..9223a9e22 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/link.gif differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/move.gif b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/move.gif new file mode 100644 index 000000000..4c96f262b Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/move.gif differ diff --git a/sdk/jme3-templates/build.xml b/sdk/jme3-templates/build.xml new file mode 100644 index 000000000..04ff75323 --- /dev/null +++ b/sdk/jme3-templates/build.xml @@ -0,0 +1,9 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.templates. + + + diff --git a/sdk/jme3-templates/manifest.mf b/sdk/jme3-templates/manifest.mf new file mode 100644 index 000000000..6ae2bc6e9 --- /dev/null +++ b/sdk/jme3-templates/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.templates/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/templates/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/templates/Bundle.properties + diff --git a/sdk/jme3-templates/nbproject/build-impl.xml b/sdk/jme3-templates/nbproject/build-impl.xml new file mode 100644 index 000000000..0b8bf2d94 --- /dev/null +++ b/sdk/jme3-templates/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-templates/nbproject/genfiles.properties b/sdk/jme3-templates/nbproject/genfiles.properties new file mode 100644 index 000000000..1139ecfcc --- /dev/null +++ b/sdk/jme3-templates/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=a024823f +build.xml.script.CRC32=f4df7687 +build.xml.stylesheet.CRC32=79c3b980@1.31.1.7 +# 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=a024823f +nbproject/build-impl.xml.script.CRC32=1ba6776b +nbproject/build-impl.xml.stylesheet.CRC32=261c4bef@1.31.1.7 diff --git a/sdk/jme3-templates/nbproject/platform.properties b/sdk/jme3-templates/nbproject/platform.properties new file mode 100644 index 000000000..a5e1957da --- /dev/null +++ b/sdk/jme3-templates/nbproject/platform.properties @@ -0,0 +1,21 @@ +cluster.path=\ + ${nbplatform.active.dir}/harness:\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/java:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + org.netbeans.modules.apisupport.harness,\ + org.netbeans.modules.apisupport.tc.cobertura,\ + org.netbeans.modules.editor.highlights,\ + org.netbeans.modules.gsf,\ + org.netbeans.modules.gsf.api,\ + org.netbeans.modules.gsfpath.api,\ + org.netbeans.modules.hibernate,\ + org.netbeans.modules.hibernatelib,\ + org.netbeans.modules.hudson.ant,\ + org.netbeans.modules.hudson.maven,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.websvc.saas.codegen.java,\ + org.openide.compat,\ + org.openide.util.enumerations +nbplatform.active=default diff --git a/sdk/jme3-templates/nbproject/project.properties b/sdk/jme3-templates/nbproject/project.properties new file mode 100644 index 000000000..bbafbfd2c --- /dev/null +++ b/sdk/jme3-templates/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=jMonkeyEngine +nbm.needs.restart=true +spec.version.base=0.1.0 diff --git a/sdk/jme3-templates/nbproject/project.xml b/sdk/jme3-templates/nbproject/project.xml new file mode 100644 index 000000000..7e296b9c7 --- /dev/null +++ b/sdk/jme3-templates/nbproject/project.xml @@ -0,0 +1,94 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.templates + + + + com.jme3.gde.project.baselibs + + 1 + 0.5 + + + + com.jme3.gde.project.libraries + + 1 + 0.5 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.28.1 + + + + org.netbeans.modules.projectuiapi + + + + 1 + 1.40.1.6 + + + + org.netbeans.spi.palette + + + + 1 + 1.20.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.util + + + + 7.31.1.1 + + + + + + + diff --git a/sdk/jme3-templates/nbproject/suite.properties b/sdk/jme3-templates/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-templates/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip b/sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip new file mode 100644 index 000000000..c7e2be49b Binary files /dev/null and b/sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip differ diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/Bundle.properties b/sdk/jme3-templates/src/com/jme3/gde/templates/Bundle.properties new file mode 100644 index 000000000..7abf938ff --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/Bundle.properties @@ -0,0 +1,7 @@ +LBL_CreateProjectStep=Name and Location +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin contains the basic project templates for jMonkeyPlatform. +OpenIDE-Module-Name=Project Templates +OpenIDE-Module-Short-Description=Provides Project Templates for jMP +Templates/Project/JME3/BasicGameProject.zip=BasicGame diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameDescription.html b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameDescription.html new file mode 100644 index 000000000..545dd3c1e --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameDescription.html @@ -0,0 +1,13 @@ + + + + + + + This basic jme3 application is based on SimpleApplication to allow an + easy start with jme3. + + diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGamePanelVisual.form b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGamePanelVisual.form new file mode 100644 index 000000000..f869982a5 --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGamePanelVisual.form @@ -0,0 +1,122 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGamePanelVisual.java b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGamePanelVisual.java new file mode 100644 index 000000000..eb7975d7e --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGamePanelVisual.java @@ -0,0 +1,260 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.templates.basic; + +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.JPanel; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Document; +import org.netbeans.spi.project.ui.support.ProjectChooser; +import org.openide.WizardDescriptor; +import org.openide.WizardValidationException; +import org.openide.filesystems.FileUtil; + +public class BasicGamePanelVisual extends JPanel implements DocumentListener { + + public static final String PROP_PROJECT_NAME = "projectName"; + private BasicGameWizardPanel panel; + + public BasicGamePanelVisual(BasicGameWizardPanel panel) { + initComponents(); + this.panel = panel; + // Register listener on the textFields to make the automatic updates + projectNameTextField.getDocument().addDocumentListener(this); + projectLocationTextField.getDocument().addDocumentListener(this); + } + + public String getProjectName() { + return this.projectNameTextField.getText(); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + projectNameLabel = new javax.swing.JLabel(); + projectNameTextField = new javax.swing.JTextField(); + projectLocationLabel = new javax.swing.JLabel(); + projectLocationTextField = new javax.swing.JTextField(); + browseButton = new javax.swing.JButton(); + createdFolderLabel = new javax.swing.JLabel(); + createdFolderTextField = new javax.swing.JTextField(); + + projectNameLabel.setLabelFor(projectNameTextField); + org.openide.awt.Mnemonics.setLocalizedText(projectNameLabel, org.openide.util.NbBundle.getMessage(BasicGamePanelVisual.class, "BasicGamePanelVisual.projectNameLabel.text")); // NOI18N + + projectLocationLabel.setLabelFor(projectLocationTextField); + org.openide.awt.Mnemonics.setLocalizedText(projectLocationLabel, org.openide.util.NbBundle.getMessage(BasicGamePanelVisual.class, "BasicGamePanelVisual.projectLocationLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(BasicGamePanelVisual.class, "BasicGamePanelVisual.browseButton.text")); // NOI18N + browseButton.setActionCommand(org.openide.util.NbBundle.getMessage(BasicGamePanelVisual.class, "BasicGamePanelVisual.browseButton.actionCommand")); // NOI18N + browseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseButtonActionPerformed(evt); + } + }); + + createdFolderLabel.setLabelFor(createdFolderTextField); + org.openide.awt.Mnemonics.setLocalizedText(createdFolderLabel, org.openide.util.NbBundle.getMessage(BasicGamePanelVisual.class, "BasicGamePanelVisual.createdFolderLabel.text")); // NOI18N + + createdFolderTextField.setEditable(false); + + 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(projectNameLabel) + .addComponent(projectLocationLabel) + .addComponent(createdFolderLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(projectNameTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE) + .addComponent(projectLocationTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE) + .addComponent(createdFolderTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(browseButton) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(projectNameLabel) + .addComponent(projectNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(projectLocationLabel) + .addComponent(projectLocationTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(browseButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(createdFolderLabel) + .addComponent(createdFolderTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(213, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + String command = evt.getActionCommand(); + if ("BROWSE".equals(command)) { + JFileChooser chooser = new JFileChooser(); + FileUtil.preventFileChooserSymlinkTraversal(chooser, null); + chooser.setDialogTitle("Select Project Location"); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + String path = this.projectLocationTextField.getText(); + if (path.length() > 0) { + File f = new File(path); + if (f.exists()) { + chooser.setSelectedFile(f); + } + } + if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(this)) { + File projectDir = chooser.getSelectedFile(); + projectLocationTextField.setText(FileUtil.normalizeFile(projectDir).getAbsolutePath()); + } + panel.fireChangeEvent(); + } + + }//GEN-LAST:event_browseButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + javax.swing.JButton browseButton; + javax.swing.JLabel createdFolderLabel; + javax.swing.JTextField createdFolderTextField; + javax.swing.JLabel projectLocationLabel; + javax.swing.JTextField projectLocationTextField; + javax.swing.JLabel projectNameLabel; + javax.swing.JTextField projectNameTextField; + // End of variables declaration//GEN-END:variables + + @Override + public void addNotify() { + super.addNotify(); + //same problem as in 31086, initial focus on Cancel button + projectNameTextField.requestFocus(); + } + + boolean valid(WizardDescriptor wizardDescriptor) { + + if (projectNameTextField.getText().length() == 0) { + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_ERROR_MESSAGE: + wizardDescriptor.putProperty("WizardPanel_errorMessage", + "Project Name is not a valid folder name."); + return false; // Display name not specified + } + File f = FileUtil.normalizeFile(new File(projectLocationTextField.getText()).getAbsoluteFile()); + if (!f.isDirectory()) { + String message = "Project Folder is not a valid path."; + wizardDescriptor.putProperty("WizardPanel_errorMessage", message); + return false; + } + final File destFolder = FileUtil.normalizeFile(new File(createdFolderTextField.getText()).getAbsoluteFile()); + + File projLoc = destFolder; + while (projLoc != null && !projLoc.exists()) { + projLoc = projLoc.getParentFile(); + } + if (projLoc == null || !projLoc.canWrite()) { + wizardDescriptor.putProperty("WizardPanel_errorMessage", + "Project Folder cannot be created."); + return false; + } + + if (FileUtil.toFileObject(projLoc) == null) { + String message = "Project Folder is not a valid path."; + wizardDescriptor.putProperty("WizardPanel_errorMessage", message); + return false; + } + + File[] kids = destFolder.listFiles(); + if (destFolder.exists() && kids != null && kids.length > 0) { + // Folder exists and is not empty + wizardDescriptor.putProperty("WizardPanel_errorMessage", + "Project Folder already exists and is not empty."); + return false; + } + wizardDescriptor.putProperty("WizardPanel_errorMessage", ""); + return true; + } + + void store(WizardDescriptor d) { + String name = projectNameTextField.getText().trim(); + String folder = createdFolderTextField.getText().trim(); + + d.putProperty("projdir", new File(folder)); + d.putProperty("name", name); + } + + void read(WizardDescriptor settings) { + File projectLocation = (File) settings.getProperty("projdir"); + if (projectLocation == null || projectLocation.getParentFile() == null || !projectLocation.getParentFile().isDirectory()) { + projectLocation = ProjectChooser.getProjectsFolder(); + } else { + projectLocation = projectLocation.getParentFile(); + } + this.projectLocationTextField.setText(projectLocation.getAbsolutePath()); + + String projectName = (String) settings.getProperty("name"); + if (projectName == null) { + projectName = "BasicGame"; + } + this.projectNameTextField.setText(projectName); + this.projectNameTextField.selectAll(); + } + + void validate(WizardDescriptor d) throws WizardValidationException { + // nothing to validate + } + + // Implementation of DocumentListener -------------------------------------- + public void changedUpdate(DocumentEvent e) { + updateTexts(e); + if (this.projectNameTextField.getDocument() == e.getDocument()) { + firePropertyChange(PROP_PROJECT_NAME, null, this.projectNameTextField.getText()); + } + } + + public void insertUpdate(DocumentEvent e) { + updateTexts(e); + if (this.projectNameTextField.getDocument() == e.getDocument()) { + firePropertyChange(PROP_PROJECT_NAME, null, this.projectNameTextField.getText()); + } + } + + public void removeUpdate(DocumentEvent e) { + updateTexts(e); + if (this.projectNameTextField.getDocument() == e.getDocument()) { + firePropertyChange(PROP_PROJECT_NAME, null, this.projectNameTextField.getText()); + } + } + + /** Handles changes in the Project name and project directory, */ + private void updateTexts(DocumentEvent e) { + + Document doc = e.getDocument(); + + if (doc == projectNameTextField.getDocument() || doc == projectLocationTextField.getDocument()) { + // Change in the project name + + String projectName = projectNameTextField.getText(); + String projectFolder = projectLocationTextField.getText(); + + //if (projectFolder.trim().length() == 0 || projectFolder.equals(oldName)) { + createdFolderTextField.setText(projectFolder + File.separatorChar + projectName); + //} + + } + panel.fireChangeEvent(); // Notify that the panel changed + } +} diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameWizardIterator.java b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameWizardIterator.java new file mode 100644 index 000000000..d2f0e2b7c --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameWizardIterator.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2009-2010 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.templates.basic; + +import java.awt.Component; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.MessageFormat; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import javax.swing.JComponent; +import javax.swing.event.ChangeListener; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.spi.project.ui.support.ProjectChooser; +import org.netbeans.spi.project.ui.templates.support.Templates; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +public class BasicGameWizardIterator implements WizardDescriptor./*Progress*/InstantiatingIterator { + + private int index; + private WizardDescriptor.Panel[] panels; + private WizardDescriptor wiz; + + public BasicGameWizardIterator() { + } + + public static BasicGameWizardIterator createIterator() { + return new BasicGameWizardIterator(); + } + + private WizardDescriptor.Panel[] createPanels() { + return new WizardDescriptor.Panel[]{ + new BasicGameWizardPanel(),}; + } + + private String[] createSteps() { + return new String[]{ + NbBundle.getMessage(BasicGameWizardIterator.class, "LBL_CreateProjectStep") + }; + } + + public Set/**/ instantiate(/*ProgressHandle handle*/) throws IOException { + Set resultSet = new LinkedHashSet(); + File dirF = FileUtil.normalizeFile((File) wiz.getProperty("projdir")); + dirF.mkdirs(); + + FileObject template = Templates.getTemplate(wiz); + FileObject dir = FileUtil.toFileObject(dirF); + unZipFile(template.getInputStream(), dir); + + // Always open top dir as a project: + resultSet.add(dir); + // Look for nested projects to open as well: + Enumeration e = dir.getFolders(true); + while (e.hasMoreElements()) { + FileObject subfolder = e.nextElement(); + if (ProjectManager.getDefault().isProject(subfolder)) { + resultSet.add(subfolder); + } + } + + File parent = dirF.getParentFile(); + if (parent != null && parent.exists()) { + ProjectChooser.setProjectsFolder(parent); + } + + return resultSet; + } + + public void initialize(WizardDescriptor wiz) { + this.wiz = wiz; + index = 0; + panels = createPanels(); + // Make sure list of steps is accurate. + String[] steps = createSteps(); + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + if (steps[i] == null) { + // Default step name to component name of panel. + // Mainly useful for getting the name of the target + // chooser to appear in the list of steps. + steps[i] = c.getName(); + } + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Step #. + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Step name (actually the whole list for reference). + jc.putClientProperty("WizardPanel_contentData", steps); + } + } + } + + public void uninitialize(WizardDescriptor wiz) { + this.wiz.putProperty("projdir", null); + this.wiz.putProperty("name", null); + this.wiz = null; + panels = null; + } + + public String name() { + return MessageFormat.format("{0} of {1}", + new Object[]{new Integer(index + 1), new Integer(panels.length)}); + } + + public boolean hasNext() { + return index < panels.length - 1; + } + + public boolean hasPrevious() { + return index > 0; + } + + public void nextPanel() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + index++; + } + + public void previousPanel() { + if (!hasPrevious()) { + throw new NoSuchElementException(); + } + index--; + } + + public WizardDescriptor.Panel current() { + return panels[index]; + } + + // If nothing unusual changes in the middle of the wizard, simply: + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + + private static void unZipFile(InputStream source, FileObject projectRoot) throws IOException { + try { + ZipInputStream str = new ZipInputStream(source); + ZipEntry entry; + while ((entry = str.getNextEntry()) != null) { + if (entry.isDirectory()) { + FileUtil.createFolder(projectRoot, entry.getName()); + } else { + FileObject fo = FileUtil.createData(projectRoot, entry.getName()); + if ("nbproject/project.xml".equals(entry.getName())) { + // Special handling for setting name of Ant-based projects; customize as needed: + filterProjectXML(fo, str, projectRoot.getName()); + } else { + writeFile(str, fo); + } + } + } + } finally { + source.close(); + } + } + + private static void writeFile(ZipInputStream str, FileObject fo) throws IOException { + OutputStream out = fo.getOutputStream(); + try { + FileUtil.copy(str, out); + } finally { + out.close(); + } + } + + private static void filterProjectXML(FileObject fo, ZipInputStream str, String name) throws IOException { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + FileUtil.copy(str, baos); + Document doc = XMLUtil.parse(new InputSource(new ByteArrayInputStream(baos.toByteArray())), false, false, null, null); + NodeList nl = doc.getDocumentElement().getElementsByTagName("name"); + if (nl != null) { + for (int i = 0; i < nl.getLength(); i++) { + Element el = (Element) nl.item(i); + if (el.getParentNode() != null && "data".equals(el.getParentNode().getNodeName())) { + NodeList nl2 = el.getChildNodes(); + if (nl2.getLength() > 0) { + nl2.item(0).setNodeValue(name); + } + break; + } + } + } + OutputStream out = fo.getOutputStream(); + try { + XMLUtil.write(doc, out, "UTF-8"); + } finally { + out.close(); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + writeFile(str, fo); + } + + } +} diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameWizardPanel.java b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameWizardPanel.java new file mode 100644 index 000000000..9c10b390a --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/BasicGameWizardPanel.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2009-2010 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.templates.basic; + +import java.awt.Component; +import java.util.HashSet; +import java.util.Set; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.WizardValidationException; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; + +/** + * Panel just asking for basic info. + */ +public class BasicGameWizardPanel implements WizardDescriptor.Panel, + WizardDescriptor.ValidatingPanel, WizardDescriptor.FinishablePanel { + + private WizardDescriptor wizardDescriptor; + private BasicGamePanelVisual component; + + public BasicGameWizardPanel() { + } + + public Component getComponent() { + if (component == null) { + component = new BasicGamePanelVisual(this); + component.setName(NbBundle.getMessage(BasicGameWizardPanel.class, "LBL_CreateProjectStep")); + } + return component; + } + + public HelpCtx getHelp() { + return new HelpCtx("sdk.project_creation"); + } + + public boolean isValid() { + getComponent(); + return component.valid(wizardDescriptor); + } + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + + protected final void fireChangeEvent() { + Set ls; + synchronized (listeners) { + ls = new HashSet(listeners); + } + ChangeEvent ev = new ChangeEvent(this); + for (ChangeListener l : ls) { + l.stateChanged(ev); + } + } + + public void readSettings(Object settings) { + wizardDescriptor = (WizardDescriptor) settings; + component.read(wizardDescriptor); + } + + public void storeSettings(Object settings) { + WizardDescriptor d = (WizardDescriptor) settings; + component.store(d); + } + + public boolean isFinishPanel() { + return true; + } + + public void validate() throws WizardValidationException { + getComponent(); + component.validate(wizardDescriptor); + } +} diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/basic/Bundle.properties b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/Bundle.properties new file mode 100644 index 000000000..b9bd4a348 --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/basic/Bundle.properties @@ -0,0 +1,6 @@ +LBL_CreateProjectStep=Name and Location +BasicGamePanelVisual.browseButton.text=Br&owse... +BasicGamePanelVisual.createdFolderLabel.text=Project &Folder: +BasicGamePanelVisual.projectNameLabel.text=Project &Name: +BasicGamePanelVisual.projectLocationLabel.text=Project &Location: +BasicGamePanelVisual.browseButton.actionCommand=BROWSE diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/jme-logo.png b/sdk/jme3-templates/src/com/jme3/gde/templates/jme-logo.png new file mode 100644 index 000000000..f67785a6e Binary files /dev/null and b/sdk/jme3-templates/src/com/jme3/gde/templates/jme-logo.png differ diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/layer.xml b/sdk/jme3-templates/src/com/jme3/gde/templates/layer.xml new file mode 100644 index 000000000..35edf970a --- /dev/null +++ b/sdk/jme3-templates/src/com/jme3/gde/templates/layer.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/build.xml b/sdk/jme3-terrain-editor/build.xml new file mode 100644 index 000000000..a7209799e --- /dev/null +++ b/sdk/jme3-terrain-editor/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.terraineditor. + + diff --git a/sdk/jme3-terrain-editor/manifest.mf b/sdk/jme3-terrain-editor/manifest.mf new file mode 100644 index 000000000..8eb88019d --- /dev/null +++ b/sdk/jme3-terrain-editor/manifest.mf @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.terraineditor +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/terraineditor/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/terraineditor/Bundle.properties +OpenIDE-Module-Requires: org.openide.windows.WindowManager + diff --git a/sdk/jme3-terrain-editor/nbproject/build-impl.xml b/sdk/jme3-terrain-editor/nbproject/build-impl.xml new file mode 100644 index 000000000..26d078e47 --- /dev/null +++ b/sdk/jme3-terrain-editor/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/nbproject/genfiles.properties b/sdk/jme3-terrain-editor/nbproject/genfiles.properties new file mode 100644 index 000000000..abab73443 --- /dev/null +++ b/sdk/jme3-terrain-editor/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=d0a68b25 +build.xml.script.CRC32=5fb89d93 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=d0a68b25 +nbproject/build-impl.xml.script.CRC32=fe2b940f +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-terrain-editor/nbproject/project.properties b/sdk/jme3-terrain-editor/nbproject/project.properties new file mode 100644 index 000000000..3f2734c81 --- /dev/null +++ b/sdk/jme3-terrain-editor/nbproject/project.properties @@ -0,0 +1,6 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen, Brent Owens +spec.version.base=0.1 diff --git a/sdk/jme3-terrain-editor/nbproject/project.xml b/sdk/jme3-terrain-editor/nbproject/project.xml new file mode 100644 index 000000000..434c86007 --- /dev/null +++ b/sdk/jme3-terrain-editor/nbproject/project.xml @@ -0,0 +1,122 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.terraineditor + + + + com.jme3.gde.core + + + + 1 + 0.8 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.6 + + + + org.jdesktop.beansbinding + + + + 1 + 1.7.1.121 + + + + org.netbeans.api.progress + + + + 1 + 1.0 + + + + org.netbeans.modules.settings + + + + 1 + 1.0 + + + + org.openide.awt + + + + 7.0 + + + + org.openide.dialogs + + + + 7.0 + + + + org.openide.filesystems + + + + 7.0 + + + + org.openide.loaders + + + + 7.0 + + + + org.openide.nodes + + + + 7.0 + + + + org.openide.util + + + + 8.0 + + + + org.openide.util.lookup + + + + 8.0 + + + + org.openide.windows + + + + 6.0 + + + + + + + diff --git a/sdk/jme3-terrain-editor/nbproject/suite.properties b/sdk/jme3-terrain-editor/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-terrain-editor/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties new file mode 100644 index 000000000..2c9f3ac9e --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties @@ -0,0 +1,100 @@ +CTL_EditTerrainAction=Edit Terrain +CTL_TerrainEditorAction=TerrainEditor +CTL_TerrainEditorTopComponent=TerrainEditor Window +HINT_TerrainEditorTopComponent=This is a TerrainEditor window +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + Terrain Editor for jMonkeyPlatform +OpenIDE-Module-Name=Terrain Editor +OpenIDE-Module-Short-Description=Terrain Editor for jMonkeyPlatform +TerrainEditorTopComponent.createTerrainButton.text= +TerrainEditorTopComponent.raiseTerrainButton.text= +TerrainEditorTopComponent.lowerTerrainButton.text= +TerrainEditorTopComponent.smoothTerrainButton.text= +TerrainEditorTopComponent.roughTerrainButton.text= +TerrainEditorTopComponent.radiusLabel.text=Radius: +TerrainEditorTopComponent.radiusSlider.toolTipText=Terrain tool height and paint radius +CreateTerrainWindow.jLabel1.text=Create Terrain +TerrainSizePanel.CancelButton.text=Cancel +TerrainSizePanel.jLabel2.text=Total Size: +TerrainSizePanel.jLabel6.text=Terrain Size: +TerrainSizePanel.jLabel5.text=(must be power of 2, and less than Total Size) +TerrainSizePanel.jLabel3.text=Patch Size: +TerrainSizePanel.jLabel4.text=(must be power of 2) +TerrainSizePanel.nextButton.text=Next +CreateTerrainWizard.terrainLabel.text=Create Terrain +TerrainSizePanel.totalSizeField.text=256 +TerrainSizePanel.patchSizeField.text=64 +CreateTerrainVisualPanel2.jLabel1.text=Heightmap +CreateTerrainVisualPanel1.totalSizeField.text=256 +CreateTerrainVisualPanel1.patchSizeField.text=64 +CreateTerrainVisualPanel1.totalSizeLabel.text=Total Size: +CreateTerrainVisualPanel1.patchSizeLabel.text=Patch Size: +CreateTerrainVisualPanel1.terrainSizeLabel.text=Terrain Size +CreateTerrainVisualPanel2._imageBrowseButton.text=Browse +CreateTerrainVisualPanel2._imageBrowseTextField.text=... +CreateTerrainVisualPanel2._imageDescriptionLabel.text=Load a heightmap image +CreateTerrainVisualPanel2._flatDescriptionLabel.text=This will create a flat heightmap +CreateTerrainVisualPanel2._hillDescriptionLabel.text=Procedurally spawns random hills throughout the terrain +CreateTerrainVisualPanel2.jLabel2.text=Iterations: +CreateTerrainVisualPanel2.jLabel3.text=Min radius: +CreateTerrainVisualPanel2.jLabel4.text=Max radius: +CreateTerrainVisualPanel2.jLabel5.text=Flattening: +CreateTerrainVisualPanel2._hillIterationsTextField.text=2000 +CreateTerrainVisualPanel2._hillFlatteningTextField.text=4 +CreateTerrainVisualPanel2._hillMinRadiusTextField.text=20 +CreateTerrainVisualPanel2._hillMaxRadiusTextField.text=50 +CreateTerrainVisualPanel2._faultDescriptionLabel.text=Uses the fault fractal procedural technique to generate random hills and valleys +CreateTerrainVisualPanel1.totalSizeHintLabel.text=(must be power of 2) +CreateTerrainVisualPanel1.patchSizeHintLabel.text=(must be power of 2 and less than Total Size) +CreateTerrainVisualPanel2.imageFileChooser.approveButtonText=Load +CreateTerrainVisualPanel2.imageFileChooser.approveButtonToolTipText=Use this heightmap image +CreateTerrainVisualPanel2.imageFileChooser.dialogTitle=Load a heightmap image +TerrainEditorTopComponent.heightLabel.text=Height/Weight: +TerrainEditorTopComponent.raiseTerrainButton.actionCommand=Raise +TerrainEditorTopComponent.raiseTerrainButton.toolTipText=Raise terrain +TerrainEditorTopComponent.lowerTerrainButton.toolTipText=Lower terrain +TerrainEditorTopComponent.lowerTerrainButton.actionCommand=Lower +TerrainEditorTopComponent.smoothTerrainButton.toolTipText=Smooth terrain +TerrainEditorTopComponent.smoothTerrainButton.actionCommand=Smooth +TerrainEditorTopComponent.roughTerrainButton.toolTipText=Rough terrain +TerrainEditorTopComponent.roughTerrainButton.actionCommand=Rough +TerrainEditorTopComponent.createTerrainButton.toolTipText=Add Terrain +TerrainEditorTopComponent.genEntropiesButton.toolTipText=Pre-calculate the terrain entropy values. This will improve launch startup time +TerrainEditorTopComponent.genEntropiesButton.text=Generate Entropies +TerrainEditorTopComponent.hintPanel.border.title=Hints +TerrainEditorTopComponent.terrainOpsPanel.border.title=Terrain Operations +TerrainEditorTopComponent.toolSettingsPanel.border.title=Tool Settings +TerrainEditorTopComponent.jTable1.columnModel.title3=Title 4 +TerrainEditorTopComponent.jTable1.columnModel.title2=Title 3 +TerrainEditorTopComponent.addTextureButton.text= +TerrainEditorTopComponent.removeTextureButton.text= +TerrainEditorTopComponent.removeTextureButton.toolTipText=Remove the last texture layer +TerrainEditorTopComponent.addTextureButton.toolTipText=Add another texture layer +TerrainEditorTopComponent.textureFileChooser.dialogTitle=Load texture +TerrainEditorTopComponent.textureFileChooser.approveButtonText=Attach +TerrainEditorTopComponent.textureFileChooser.approveButtonToolTipText=Use this selected texture +TerrainEditorTopComponent.remainingTexTitleLabel.text=Remaining Textures +CreateTerrainVisualPanel3.jLabel1.text=Material +CreateTerrainVisualPanel3.jLabel2.text=Alpha-blend texture size: +CreateTerrainVisualPanel3.jTextField1.text=512 +CreateTerrainVisualPanel3.jTextArea1.text=The size of one side of the texture, eg 512. This will be used to blend several textures together into one texture for the terrain. The larger the size, the more detailed the image, but the more memory it will use, and possibly will slow down the editor. You cannot change this value after it is set! +CreateTerrainVisualPanel3.jLabel1.text_1=Material +CreateTerrainVisualPanel3.jLabel2.text_1=Alpha-blend texture size: +CreateTerrainVisualPanel3.jTextArea1.text_1=The size of one side of the texture, eg. 512. This will be used to blend several textures together into one texture for the terrain. The larger the size, the more detailed the image. But it will use more memory and possibly slow down the editor. You cannot change this value after it is set! +CreateTerrainVisualPanel3.alphaBlendSize.text_1=256 +TerrainEditorTopComponent.textureTable.columnModel.title3_1=Rotation +TerrainEditorTopComponent.textureTable.columnModel.title2_1=Scale +TerrainEditorTopComponent.textureFileChooser.dialogTitle_1=Attach texture +TerrainEditorTopComponent.textureFileChooser.approveButtonText_1=Load +TerrainEditorTopComponent.remainingTexturesLabel.text=\ +4 +TerrainEditorTopComponent.textureTable.columnModel.title4=Normal +TerrainEditorTopComponent.eraseButton.toolTipText=Erase a texture from the terrain +TerrainEditorTopComponent.eraseButton.text= +TerrainEditorTopComponent.paintButton.toolTipText=Paint a texture onto the terrain +TerrainEditorTopComponent.paintButton.text= +TerrainEditorTopComponent.paintingPanel.border.title=Painting +TerrainEditorTopComponent.triPlanarCheckBox.toolTipText=Enable if you have a lot of vertical surfaces. It will look nice but lower performance +TerrainEditorTopComponent.triPlanarCheckBox.text=Tri-planar mapping +TerrainEditorTopComponent.jButton1.text=Create Skybox diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel1.form b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel1.form new file mode 100644 index 000000000..d363df4c0 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel1.form @@ -0,0 +1,149 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel1.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel1.java new file mode 100644 index 000000000..32e0e6107 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel1.java @@ -0,0 +1,139 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.terraineditor; + +import javax.swing.JPanel; +import javax.swing.JTextField; + +public final class CreateTerrainVisualPanel1 extends JPanel { + + /** Creates new form CreateTerrainVisualPanel1 */ + public CreateTerrainVisualPanel1() { + initComponents(); + } + + @Override + public String getName() { + return "Terrain Size"; + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + terrainSizeLabel = new javax.swing.JLabel(); + totalSizeLabel = new javax.swing.JLabel(); + totalSizeField = new javax.swing.JTextField(); + patchSizeLabel = new javax.swing.JLabel(); + patchSizeField = new javax.swing.JTextField(); + totalSizeHintLabel = new javax.swing.JLabel(); + patchSizeHintLabel = new javax.swing.JLabel(); + + terrainSizeLabel.setFont(new java.awt.Font("Tahoma", 1, 12)); + org.openide.awt.Mnemonics.setLocalizedText(terrainSizeLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel1.class, "CreateTerrainVisualPanel1.terrainSizeLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(totalSizeLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel1.class, "CreateTerrainVisualPanel1.totalSizeLabel.text")); // NOI18N + + totalSizeField.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel1.class, "CreateTerrainVisualPanel1.totalSizeField.text")); // NOI18N + totalSizeField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + totalSizeFieldActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(patchSizeLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel1.class, "CreateTerrainVisualPanel1.patchSizeLabel.text")); // NOI18N + + patchSizeField.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel1.class, "CreateTerrainVisualPanel1.patchSizeField.text")); // NOI18N + + totalSizeHintLabel.setFont(new java.awt.Font("Tahoma", 2, 11)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(totalSizeHintLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel1.class, "CreateTerrainVisualPanel1.totalSizeHintLabel.text")); // NOI18N + + patchSizeHintLabel.setFont(new java.awt.Font("Tahoma", 2, 11)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(patchSizeHintLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel1.class, "CreateTerrainVisualPanel1.patchSizeHintLabel.text")); // NOI18N + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(terrainSizeLabel) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(patchSizeLabel) + .addComponent(totalSizeLabel)) + .addGap(3, 3, 3))) + .addGap(18, 18, 18) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(totalSizeField) + .addComponent(patchSizeField, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)) + .addGap(18, 18, 18) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(totalSizeHintLabel) + .addComponent(patchSizeHintLabel)) + .addContainerGap(14, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(terrainSizeLabel) + .addGap(51, 51, 51) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(totalSizeLabel) + .addComponent(totalSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(totalSizeHintLabel)) + .addGap(18, 18, 18) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(patchSizeLabel) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(patchSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(patchSizeHintLabel))) + .addContainerGap(166, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void totalSizeFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_totalSizeFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_totalSizeFieldActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel jPanel1; + private javax.swing.JTextField patchSizeField; + private javax.swing.JLabel patchSizeHintLabel; + private javax.swing.JLabel patchSizeLabel; + private javax.swing.JLabel terrainSizeLabel; + private javax.swing.JTextField totalSizeField; + private javax.swing.JLabel totalSizeHintLabel; + private javax.swing.JLabel totalSizeLabel; + // End of variables declaration//GEN-END:variables + + public JTextField getPatchSizeField() { + return patchSizeField; + } + + public JTextField getTotalSizeField() { + return totalSizeField; + } + + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel2.form b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel2.form new file mode 100644 index 000000000..be1ffb743 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel2.form @@ -0,0 +1,368 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel2.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel2.java new file mode 100644 index 000000000..583ec1d4c --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel2.java @@ -0,0 +1,367 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.terraineditor; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.JTextField; + +public final class CreateTerrainVisualPanel2 extends JPanel { + + //String[] types = {"Flat", "Image Based", "Hill", "Fault Fractal"}; + + + /** Creates new form CreateTerrainVisualPanel2 */ + public CreateTerrainVisualPanel2() { + initComponents(); + + _flatPanel.setVisible(true); + _imagePanel.setVisible(false); + _hillPanel.setVisible(false); + _faultPanel.setVisible(false); + this.validate(); + } + + @Override + public String getName() { + return "Heightmap"; + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + imageFileChooser = new javax.swing.JFileChooser(); + jPanel2 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + heightmapTypeComboBox = new javax.swing.JComboBox(); + _flatPanel = new javax.swing.JPanel(); + _flatDescriptionLabel = new javax.swing.JLabel(); + _imagePanel = new javax.swing.JPanel(); + _imageDescriptionLabel = new javax.swing.JLabel(); + _imageBrowseTextField = new javax.swing.JTextField(); + _imageBrowseButton = new javax.swing.JButton(); + _hillPanel = new javax.swing.JPanel(); + _hillDescriptionLabel = new javax.swing.JLabel(); + _hillIterationsTextField = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + _hillFlatteningTextField = new javax.swing.JTextField(); + _hillMinRadiusTextField = new javax.swing.JTextField(); + _hillMaxRadiusTextField = new javax.swing.JTextField(); + _faultPanel = new javax.swing.JPanel(); + _faultDescriptionLabel = new javax.swing.JLabel(); + + imageFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.imageFileChooser.approveButtonText")); // NOI18N + imageFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.imageFileChooser.approveButtonToolTipText")); // NOI18N + imageFileChooser.setCurrentDirectory(new java.io.File("C:\\Java\\NetBeans 6.9.1")); + imageFileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.imageFileChooser.dialogTitle")); // NOI18N + + jLabel1.setFont(new java.awt.Font("Tahoma", 1, 12)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.jLabel1.text")); // NOI18N + + heightmapTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Flat", "Image Based", "Hill" })); + heightmapTypeComboBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + heightmapTypeComboBoxActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(_flatDescriptionLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._flatDescriptionLabel.text")); // NOI18N + + javax.swing.GroupLayout _flatPanelLayout = new javax.swing.GroupLayout(_flatPanel); + _flatPanel.setLayout(_flatPanelLayout); + _flatPanelLayout.setHorizontalGroup( + _flatPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_flatPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(_flatDescriptionLabel) + .addContainerGap(267, Short.MAX_VALUE)) + ); + _flatPanelLayout.setVerticalGroup( + _flatPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_flatPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(_flatDescriptionLabel) + .addContainerGap(33, Short.MAX_VALUE)) + ); + + org.openide.awt.Mnemonics.setLocalizedText(_imageDescriptionLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._imageDescriptionLabel.text")); // NOI18N + + _imageBrowseTextField.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._imageBrowseTextField.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(_imageBrowseButton, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._imageBrowseButton.text")); // NOI18N + _imageBrowseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + _imageBrowseButtonActionPerformed(evt); + } + }); + + javax.swing.GroupLayout _imagePanelLayout = new javax.swing.GroupLayout(_imagePanel); + _imagePanel.setLayout(_imagePanelLayout); + _imagePanelLayout.setHorizontalGroup( + _imagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_imagePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(_imagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_imagePanelLayout.createSequentialGroup() + .addComponent(_imageBrowseTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 246, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(_imageBrowseButton)) + .addComponent(_imageDescriptionLabel)) + .addContainerGap(99, Short.MAX_VALUE)) + ); + _imagePanelLayout.setVerticalGroup( + _imagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_imagePanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(_imageDescriptionLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(_imagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(_imageBrowseTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(_imageBrowseButton)) + .addContainerGap(44, Short.MAX_VALUE)) + ); + + org.openide.awt.Mnemonics.setLocalizedText(_hillDescriptionLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._hillDescriptionLabel.text")); // NOI18N + + _hillIterationsTextField.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._hillIterationsTextField.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.jLabel2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.jLabel4.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2.jLabel5.text")); // NOI18N + + _hillFlatteningTextField.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._hillFlatteningTextField.text")); // NOI18N + + _hillMinRadiusTextField.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._hillMinRadiusTextField.text")); // NOI18N + + _hillMaxRadiusTextField.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._hillMaxRadiusTextField.text")); // NOI18N + + javax.swing.GroupLayout _hillPanelLayout = new javax.swing.GroupLayout(_hillPanel); + _hillPanel.setLayout(_hillPanelLayout); + _hillPanelLayout.setHorizontalGroup( + _hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_hillPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(_hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(_hillDescriptionLabel, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, _hillPanelLayout.createSequentialGroup() + .addGroup(_hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, _hillPanelLayout.createSequentialGroup() + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(_hillFlatteningTextField)) + .addGroup(_hillPanelLayout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(_hillIterationsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 59, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(70, 70, 70))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(_hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel3) + .addComponent(jLabel4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(_hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(_hillMinRadiusTextField) + .addComponent(_hillMaxRadiusTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 55, Short.MAX_VALUE)) + .addContainerGap(23, Short.MAX_VALUE)) + ); + _hillPanelLayout.setVerticalGroup( + _hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_hillPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(_hillDescriptionLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(_hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(_hillIterationsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel3) + .addComponent(_hillMinRadiusTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(_hillPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(_hillFlatteningTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel4) + .addComponent(_hillMaxRadiusTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(31, Short.MAX_VALUE)) + ); + + org.openide.awt.Mnemonics.setLocalizedText(_faultDescriptionLabel, org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel2.class, "CreateTerrainVisualPanel2._faultDescriptionLabel.text")); // NOI18N + + javax.swing.GroupLayout _faultPanelLayout = new javax.swing.GroupLayout(_faultPanel); + _faultPanel.setLayout(_faultPanelLayout); + _faultPanelLayout.setHorizontalGroup( + _faultPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_faultPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(_faultDescriptionLabel) + .addContainerGap(37, Short.MAX_VALUE)) + ); + _faultPanelLayout.setVerticalGroup( + _faultPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(_faultPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(_faultDescriptionLabel) + .addContainerGap(75, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGap(30, 30, 30) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jLabel1) + .addComponent(_hillPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(_imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(_flatPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(heightmapTypeComboBox, 0, 428, Short.MAX_VALUE) + .addComponent(_faultPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addGap(26, 26, 26) + .addComponent(heightmapTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(_flatPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(_imagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(_hillPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(_faultPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(27, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + private void openFileActionPerformed(java.awt.event.ActionEvent evt) { + int returnVal = imageFileChooser.showOpenDialog(this); + if (returnVal == imageFileChooser.APPROVE_OPTION) { + File file = imageFileChooser.getSelectedFile(); + //try { + // What to do with the file, e.g. display it in a TextArea + _imageBrowseTextField.setText( file.getAbsolutePath() ); + //} catch (IOException ex) { + // System.out.println("problem accessing file"+file.getAbsolutePath()); + //} + } else { + System.out.println("File access cancelled by user."); + } + } + + private void heightmapTypeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_heightmapTypeComboBoxActionPerformed + if ("Flat".equals(heightmapTypeComboBox.getSelectedItem()) ) { + _flatPanel.setVisible(true); + _imagePanel.setVisible(false); + _hillPanel.setVisible(false); + _faultPanel.setVisible(false); + } + else if ("Image Based".equals(heightmapTypeComboBox.getSelectedItem()) ) { + _flatPanel.setVisible(false); + _imagePanel.setVisible(true); + _hillPanel.setVisible(false); + _faultPanel.setVisible(false); + } + else if ("Hill".equals(heightmapTypeComboBox.getSelectedItem()) ) { + _flatPanel.setVisible(false); + _imagePanel.setVisible(false); + _hillPanel.setVisible(true); + _faultPanel.setVisible(false); + } + else if ("Fault Fractal".equals(heightmapTypeComboBox.getSelectedItem()) ) { + _flatPanel.setVisible(false); + _imagePanel.setVisible(false); + _hillPanel.setVisible(false); + _faultPanel.setVisible(true); + } + + this.validate(); + }//GEN-LAST:event_heightmapTypeComboBoxActionPerformed + + private void _imageBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__imageBrowseButtonActionPerformed + openFileActionPerformed(evt); + }//GEN-LAST:event__imageBrowseButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel _faultDescriptionLabel; + private javax.swing.JPanel _faultPanel; + private javax.swing.JLabel _flatDescriptionLabel; + private javax.swing.JPanel _flatPanel; + private javax.swing.JLabel _hillDescriptionLabel; + private javax.swing.JTextField _hillFlatteningTextField; + private javax.swing.JTextField _hillIterationsTextField; + private javax.swing.JTextField _hillMaxRadiusTextField; + private javax.swing.JTextField _hillMinRadiusTextField; + private javax.swing.JPanel _hillPanel; + private javax.swing.JButton _imageBrowseButton; + private javax.swing.JTextField _imageBrowseTextField; + private javax.swing.JLabel _imageDescriptionLabel; + private javax.swing.JPanel _imagePanel; + private javax.swing.JComboBox heightmapTypeComboBox; + private javax.swing.JFileChooser imageFileChooser; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JPanel jPanel2; + // End of variables declaration//GEN-END:variables + + public JComboBox getHeightmapTypeComboBox() { + return heightmapTypeComboBox; + } + + public JTextField getHillFlatteningTextField() { + return _hillFlatteningTextField; + } + + public JTextField getHillIterationsTextField() { + return _hillIterationsTextField; + } + + public JTextField getHillMaxRadiusTextField() { + return _hillMaxRadiusTextField; + } + + public JTextField getHillMinRadiusTextField() { + return _hillMinRadiusTextField; + } + + public JTextField getImageBrowseTextField() { + return _imageBrowseTextField; + } + + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel3.form b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel3.form new file mode 100644 index 000000000..7506baffa --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel3.form @@ -0,0 +1,101 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel3.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel3.java new file mode 100644 index 000000000..39e5271d9 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainVisualPanel3.java @@ -0,0 +1,113 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * CreateTerrainVisualPanel3.java + * + * Created on Jan 20, 2011, 5:15:12 PM + */ + +package com.jme3.gde.terraineditor; + +import javax.swing.JTextField; + +/** + * + * @author sploreg + */ +public class CreateTerrainVisualPanel3 extends javax.swing.JPanel { + + /** Creates new form CreateTerrainVisualPanel3 */ + public CreateTerrainVisualPanel3() { + initComponents(); + } + + protected void setDefaultImageSize(int size) { + alphaBlendSize.setText(""+size); + } + + public JTextField getAlphaBlendSize() { + return alphaBlendSize; + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + alphaBlendSize = new javax.swing.JTextField(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + jLabel1.setFont(new java.awt.Font("Tahoma", 1, 12)); + jLabel1.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel3.class, "CreateTerrainVisualPanel3.jLabel1.text_1")); // NOI18N + + jLabel2.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel3.class, "CreateTerrainVisualPanel3.jLabel2.text_1")); // NOI18N + + alphaBlendSize.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel3.class, "CreateTerrainVisualPanel3.alphaBlendSize.text_1")); // NOI18N + alphaBlendSize.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + alphaBlendSizeActionPerformed(evt); + } + }); + + jTextArea1.setColumns(20); + jTextArea1.setEditable(false); + jTextArea1.setLineWrap(true); + jTextArea1.setRows(5); + jTextArea1.setText(org.openide.util.NbBundle.getMessage(CreateTerrainVisualPanel3.class, "CreateTerrainVisualPanel3.jTextArea1.text_1")); // NOI18N + jTextArea1.setWrapStyleWord(true); + jScrollPane1.setViewportView(jTextArea1); + + 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, javax.swing.GroupLayout.PREFERRED_SIZE, 322, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(alphaBlendSize, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jLabel1)) + .addContainerGap(68, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(alphaBlendSize, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(47, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void alphaBlendSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_alphaBlendSizeActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_alphaBlendSizeActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTextField alphaBlendSize; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + // End of variables declaration//GEN-END:variables + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardAction.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardAction.java new file mode 100644 index 000000000..d7700e1ec --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardAction.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import java.awt.Component; +import java.awt.Dialog; +import java.text.MessageFormat; +import javax.swing.JComponent; +import org.openide.DialogDisplayer; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CallableSystemAction; + +// An example action demonstrating how the wizard could be called from within +// your code. You can copy-paste the code below wherever you need. +public final class CreateTerrainWizardAction extends CallableSystemAction { + + private WizardDescriptor.Panel[] panels; + private TerrainEditorTopComponent controller; + + public CreateTerrainWizardAction(TerrainEditorTopComponent controller) { + this.controller = controller; + } + + public void performAction() { + WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle("Terrain Wizard"); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + if (!cancelled) { + controller.generateTerrain(wizardDescriptor); + } + } + + + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new CreateTerrainWizardPanel1(), + new CreateTerrainWizardPanel2(), + new CreateTerrainWizardPanel3() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } + + public String getName() { + return "Terrain Wizard"; + } + + @Override + public String iconResource() { + return null; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel1.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel1.java new file mode 100644 index 000000000..fa4d943ec --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel1.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class CreateTerrainWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private Component 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. + public Component getComponent() { + if (component == null) { + component = new CreateTerrainVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + } + + public void storeSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + CreateTerrainVisualPanel1 comp = (CreateTerrainVisualPanel1) getComponent(); + int totalSize = new Integer(comp.getTotalSizeField().getText()) + 1; + int patchSize = new Integer(comp.getPatchSizeField().getText()) + 1; + wiz.putProperty("totalSize", totalSize ); + wiz.putProperty("patchSize", patchSize ); + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel2.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel2.java new file mode 100644 index 000000000..28376999a --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel2.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import com.jme3.asset.TextureKey; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.terrain.heightmap.AbstractHeightMap; +import com.jme3.terrain.heightmap.HillHeightMap; +import com.jme3.terrain.heightmap.ImageBasedHeightMap; +import com.jme3.texture.Texture; +import java.awt.Component; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.net.URL; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import javax.imageio.ImageIO; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import jme3tools.converters.ImageToAwt; +import org.openide.WizardDescriptor; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; + +public class CreateTerrainWizardPanel2 implements WizardDescriptor.Panel { + + private int terrainTotalSize; + private AbstractHeightMap heightmap; + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private Component 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. + public Component getComponent() { + if (component == null) { + component = new CreateTerrainVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + // If it is always OK to press Next or Finish, then: + public boolean isValid() { + CreateTerrainVisualPanel2 comp = (CreateTerrainVisualPanel2) getComponent(); + + if ("Image Based".equals(comp.getHeightmapTypeComboBox().getSelectedItem())) { + //new File(comp.getImageBrowseTextField().getText()) + } + + return true; + // If it depends on some condition (form filled out...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + /*public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + }*/ + + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + terrainTotalSize = (Integer)wiz.getProperty("totalSize"); + } + + public void storeSettings(Object settings) { + + CreateTerrainVisualPanel2 comp = (CreateTerrainVisualPanel2) getComponent(); + + if ("Flat".equals(comp.getHeightmapTypeComboBox().getSelectedItem()) ) { + heightmap = new FlatHeightmap(terrainTotalSize); + } + else if ("Image Based".equals(comp.getHeightmapTypeComboBox().getSelectedItem()) ) { + + BufferedImage bi = null; + try { + bi = ImageIO.read(new File(comp.getImageBrowseTextField().getText())); + } catch (IOException e) { + e.printStackTrace(); + } + ImageBasedHeightMap ibhm = new ImageBasedHeightMap(bi, 1f); + + heightmap = ibhm; + } + else if ("Hill".equals(comp.getHeightmapTypeComboBox().getSelectedItem()) ) { + int iterations = new Integer(comp.getHillIterationsTextField().getText()); + byte flattening = new Byte(comp.getHillFlatteningTextField().getText()); + float min = new Float(comp.getHillMinRadiusTextField().getText()); + float max = new Float(comp.getHillMaxRadiusTextField().getText()); + try { + heightmap = new HillHeightMap(terrainTotalSize, iterations, min, max, flattening); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + + WizardDescriptor wiz = (WizardDescriptor) settings; + wiz.putProperty("abstractHeightMap", heightmap); + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel3.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel3.java new file mode 100644 index 000000000..471b1bbc6 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/CreateTerrainWizardPanel3.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +/** + * + * @author bowens + */ +public class CreateTerrainWizardPanel3 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private Component 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. + public Component getComponent() { + if (component == null) { + component = new CreateTerrainVisualPanel3(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + int totalSize = (Integer) wiz.getProperty("totalSize"); + CreateTerrainVisualPanel3 comp = (CreateTerrainVisualPanel3) getComponent(); + comp.setDefaultImageSize(totalSize-1); // eg. was 257, now 256 + } + + public void storeSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + CreateTerrainVisualPanel3 comp = (CreateTerrainVisualPanel3) getComponent(); + int textureSize = new Integer(comp.getAlphaBlendSize().getText()); + wiz.putProperty("alphaTextureSize", textureSize ); + } + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/EditTerrainAction.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/EditTerrainAction.java new file mode 100644 index 000000000..8051104f4 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/EditTerrainAction.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import com.jme3.asset.DesktopAssetManager; +import com.jme3.gde.core.assets.BinaryModelDataObject; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.scene.Spatial; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +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 EditTerrainAction implements ActionListener { + + private final BinaryModelDataObject context; + + public EditTerrainAction(BinaryModelDataObject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final ProjectAssetManager manager = context.getLookup().lookup(ProjectAssetManager.class); + if (manager == null) { + return; + } + Runnable call = new Runnable() { + + public void run() { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening in Terrain Editor"); + progressHandle.start(); + + + final Spatial asset = context.loadAsset(); + + if(asset!=null){ + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + ((DesktopAssetManager)manager.getManager()).clearCache(); + TerrainEditorTopComponent composer = TerrainEditorTopComponent.findInstance(); + composer.openScene(asset, context, manager); + } + }); + }else { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error opening " + context.getPrimaryFile().getNameExt(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + progressHandle.finish(); + } + }; + new Thread(call).start(); + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/FlatHeightmap.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/FlatHeightmap.java new file mode 100644 index 000000000..8f9969ee1 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/FlatHeightmap.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import com.jme3.terrain.heightmap.AbstractHeightMap; + +/** + * Very simple heightmap class that is a heightmap of floats that is size*size + * in size, and has height values of zero. + * + * @author bowens + */ +public class FlatHeightmap extends AbstractHeightMap { + + private int size; + private float[] heightmapData; + + public FlatHeightmap(int size) { + this.size = size; + } + + @Override + public boolean load() { + heightmapData = new float[size*size]; + return true; + } + + @Override + public float[] getHeightMap() { + return heightmapData; + } + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/NotifyDescriptor.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/NotifyDescriptor.java new file mode 100644 index 000000000..d693cc8c3 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/NotifyDescriptor.java @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.jme3.gde.terraineditor; + +/** + * + * @author bowens + */ +class NotifyDescriptor { + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerraMonkey.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerraMonkey.png new file mode 100644 index 000000000..7028eebb5 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerraMonkey.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java new file mode 100644 index 000000000..dcca98e77 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import com.jme3.app.Application; +import com.jme3.app.state.AppStateManager; +import com.jme3.collision.CollisionResult; +import com.jme3.collision.CollisionResults; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.controller.AbstractCameraController; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.input.InputManager; +import com.jme3.input.KeyInput; +import com.jme3.input.event.KeyInputEvent; +import com.jme3.input.event.MouseMotionEvent; +import com.jme3.math.Ray; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; + + +/** + * Runs in the JME thread, not awt thread. + * Listens to mouse/camera input and relays the movements + * to other controllers: editorController, toolController + * + * @author normenhansen, bowens + */ +public class TerrainCameraController extends AbstractCameraController { + + private TerrainToolController toolController; + private TerrainEditorController editorController; + private boolean forceCameraControls = false; // when user holds shift, this is true + + private boolean terrainEditToolActivated = false; + protected Application app; + private float toolModifyRate = 0.01f; // how frequently (in seconds) it should update + private long lastModifyTime; + + public TerrainCameraController(Camera cam) { + super(cam, SceneApplication.getApplication().getInputManager()); + app = SceneApplication.getApplication(); + } + + public void setToolController(TerrainToolController toolController) { + this.toolController = toolController; + } + + public void setEditorController(TerrainEditorController editorController) { + this.editorController = editorController; + } + + + @Override + public void onMouseMotionEvent(MouseMotionEvent mme) { + super.onMouseMotionEvent(mme); + + + // if one of the terrain edit buttons is not enabled, return + if (!isTerrainEditButtonEnabled()) + return; + + // move the marker + Vector3f pos = getTerrainCollisionPoint(); + if (pos != null) + toolController.doMoveEditTool(pos); + } + + private boolean isTerrainEditButtonEnabled() { + return toolController.isTerrainEditButtonEnabled(); + } + + @Override + public void onAnalog(String string, float f1, float f) { + if ("MouseAxisX".equals(string)) { + moved = true; + movedR = true; + if (isTerrainEditButtonEnabled() && !forceCameraControls) { + if (leftMouse) + terrainEditToolActivated = true;//toolController.doTerrainEditToolActivated(); + } + else { + if (leftMouse) { + rotateCamera(Vector3f.UNIT_Y, -f1 * 2.5f); + } + if (rightMouse) { + panCamera(f1 * 2.5f, 0); + } + } + } else if ("MouseAxisY".equals(string)) { + moved = true; + movedR = true; + if (isTerrainEditButtonEnabled() && !forceCameraControls) { + if (leftMouse) + terrainEditToolActivated = true;//toolController.doTerrainEditToolActivated(); + } + else { + if (leftMouse) { + rotateCamera(cam.getLeft(), -f1 * 2.5f); + } + if (rightMouse) { + panCamera(0, -f1 * 2.5f); + } + } + } else if ("MouseAxisX-".equals(string)) { + moved = true; + movedR = true; + if (isTerrainEditButtonEnabled() && !forceCameraControls) { + if (leftMouse) + terrainEditToolActivated = true;//toolController.doTerrainEditToolActivated(); + } + else { + if (leftMouse) { + rotateCamera(Vector3f.UNIT_Y, f1 * 2.5f); + } + if (rightMouse) { + panCamera(-f1 * 2.5f, 0); + } + } + } else if ("MouseAxisY-".equals(string)) { + moved = true; + movedR = true; + if (isTerrainEditButtonEnabled() && !forceCameraControls) { + if (leftMouse) + terrainEditToolActivated = true;//toolController.doTerrainEditToolActivated(); + } + else { + if (leftMouse) { + rotateCamera(cam.getLeft(), f1 * 2.5f); + } + if (rightMouse) { + panCamera(0, f1 * 2.5f); + } + } + } else if ("MouseWheel".equals(string)) { + zoomCamera(.1f); + } else if ("MouseWheel-".equals(string)) { + zoomCamera(-.1f); + } + } + + @Override + public void update(float f) { + super.update(f); + + doTerrainUpdates(f); + } + + @Override + protected void checkClick(int button) { + if (button == 0) { + if (isTerrainEditButtonEnabled() && !forceCameraControls) { + if (leftMouse) + terrainEditToolActivated = true;//toolController.doTerrainEditToolActivated(); + } + } + } + + /** + * Update the terrain if it has had any editing done on it. + * We do it with a Timer to control the intensity and frequency + * of the editing. + */ + private void doTerrainUpdates(float dt) { + + if (terrainEditToolActivated) { + if (app.getContext().getTimer().getTime() >= lastModifyTime + (toolModifyRate*1000)) { + toolController.doTerrainEditToolActivated(); + terrainEditToolActivated = false; + lastModifyTime = app.getContext().getTimer().getTime(); + } + } + } + + @Override + public void onKeyEvent(KeyInputEvent kie) { + if (kie.isPressed()) { + if ( KeyInput.KEY_LSHIFT == kie.getKeyCode() ) { + forceCameraControls = true; + } + } else if (kie.isReleased()){ + if ( KeyInput.KEY_LSHIFT == kie.getKeyCode() ) { + forceCameraControls = false; + } + } + } + + /** + * Find where on the terrain the mouse intersects. + */ + private Vector3f getTerrainCollisionPoint() { + + if (editorController.getTerrain(null) == null) + return null; + + CollisionResults results = new CollisionResults(); + Ray ray = new Ray(); + Vector3f pos = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0).clone(); + Vector3f dir = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0.3f).clone(); + dir.subtractLocal(pos).normalizeLocal(); + ray.setOrigin(pos); + ray.setDirection(dir); + editorController.getTerrain(null).collideWith(ray, results); + if (results == null) { + return null; + } + final CollisionResult result = results.getClosestCollision(); + if (result == null) + return null; + return result.getContactPoint(); + } + + + + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java new file mode 100644 index 000000000..e543cbbfd --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java @@ -0,0 +1,1301 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import com.jme3.asset.AssetManager; +import com.jme3.asset.TextureKey; +import com.jme3.bounding.BoundingBox; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.util.DataObjectSaveNode; +import com.jme3.material.MatParam; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.terrain.ProgressMonitor; +import com.jme3.terrain.Terrain; +import com.jme3.terrain.geomipmap.TerrainLodControl; +import com.jme3.terrain.geomipmap.TerrainQuad; +import com.jme3.texture.Image; +import com.jme3.texture.Texture; +import com.jme3.texture.Texture.WrapMode; +import com.jme3.util.SkyFactory; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.logging.Logger; +import javax.imageio.ImageIO; +import jme3tools.converters.ImageToAwt; +import org.openide.cookies.SaveCookie; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.util.Exceptions; + +/** + * Modifies the actual terrain in the scene. + * + * @author normenhansen, bowens + */ +public class TerrainEditorController { + private JmeSpatial jmeRootNode; + private Node terrainNode; + private Node rootNode; + private DataObject currentFileObject; + private DataObjectSaveNode alphaDataObject; + + // texture settings + protected final String DEFAULT_TERRAIN_TEXTURE = "com/jme3/gde/terraineditor/dirt.jpg"; + protected final float DEFAULT_TEXTURE_SCALE = 16.0625f; + private final int NUM_ALPHA_TEXTURES = 3; + private final int BASE_TEXTURE_COUNT = NUM_ALPHA_TEXTURES; // add any others here, like a global specular map + protected final int MAX_TEXTURE_LAYERS = 7-BASE_TEXTURE_COUNT; // 16 max, minus the ones we are reserving + + public TerrainEditorController(JmeSpatial jmeRootNode, DataObject currentFileObject, TerrainEditorTopComponent topComponent) { + this.jmeRootNode = jmeRootNode; + rootNode = this.jmeRootNode.getLookup().lookup(Node.class); + this.currentFileObject = currentFileObject; + alphaDataObject = null; + } + + public void setToolController(TerrainToolController toolController) { + + } + + /** + * Saves the data object into the topComponent via + * TerrainEditorTopComponent.addDataObject() + */ + public void getAlphaSaveDataObject(final TerrainEditorTopComponent topComponent) { + if (alphaDataObject != null) + topComponent.addDataObject(alphaDataObject); + else { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doCreateAlphaSaveDataObject(); + topComponent.addDataObject(alphaDataObject); + return null; + } + }); + } + + } + + public void doGetAlphaSaveDataObject(final TerrainEditorTopComponent topComponent) { + if (alphaDataObject != null) + topComponent.addDataObject(alphaDataObject); + else { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + doCreateAlphaSaveDataObject(); + topComponent.addDataObject(alphaDataObject); + } + + } + + /*public void createAlphaSaveDataObject() throws DataObjectNotFoundException { + + if (alphaDataObject != null) + return; + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doCreateAlphaSaveDataObject(); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + }*/ + + private void doCreateAlphaSaveDataObject() { + if (alphaDataObject != null) + return; + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + String assetFolder = ""; + AssetManager manager = SceneApplication.getApplication().getAssetManager(); + if (manager != null && manager instanceof ProjectAssetManager) + assetFolder = ((ProjectAssetManager)manager).getAssetFolderName(); + Texture alpha0 = doGetAlphaTexture(terrain, 0); + String path = alpha0.getKey().getName(); + Logger.getLogger(TerrainEditorController.class.getName()).info("Creating AlphaSaveDataObject, path: "+assetFolder+path); + FileObject fb = FileUtil.toFileObject(new File(assetFolder+path)); + try { + alphaDataObject = new DataObjectSaveNode(DataObject.find(fb)); + } catch (DataObjectNotFoundException ex) { + Exceptions.printStackTrace(ex); + } + } + + public FileObject getCurrentFileObject() { + return currentFileObject.getPrimaryFile(); + } + + public DataObject getCurrentDataObject() { + return currentFileObject; + } + + public void setNeedsSave(boolean state) { + currentFileObject.setModified(state); + setNeedsSaveAlpha(state); + } + + private void setNeedsSaveAlpha(boolean state) { + if (alphaDataObject == null) + doCreateAlphaSaveDataObject(); + + Terrain terrain = (Terrain)getTerrain(null); + AlphaTextureSaveCookie cookie = new AlphaTextureSaveCookie(terrain); + if(!alphaDataObject.getDataObject().isModified()){ + alphaDataObject.setSaveCookie(cookie); + } + } + + class AlphaTextureSaveCookie implements SaveCookie { + + private Terrain terrain; + + AlphaTextureSaveCookie(Terrain terrain) { + this.terrain = terrain; + } + + public String getId() { + return terrain.getSpatial().getName(); + } + + public void save() throws IOException { + saveAlphaImages(terrain); + alphaDataObject.removeSaveCookie(); + } + + } + + public boolean isNeedSave() { + return currentFileObject.isModified(); + } + + public void saveScene() { + try { + currentFileObject.getLookup().lookup(SaveCookie.class).save(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + protected Node getTerrain(Spatial root) { + if (terrainNode != null) + return terrainNode; + + if (root == null) + root = rootNode; + + // is this the terrain? + if (root instanceof Terrain && root instanceof Node) { + terrainNode = (Node)root; + return terrainNode; + } + + if (root instanceof Node) { + Node n = (Node) root; + for (Spatial c : n.getChildren()) { + if (c instanceof Node){ + Node res = getTerrain(c); + if (res != null) + return res; + } + } + } + + return terrainNode; + } + + /** + * Perform the actual height modification on the terrain. + * @param worldLoc the location in the world where the tool was activated + * @param radius of the tool, terrain in this radius will be affected + * @param heightFactor the amount to adjust the height by + */ + protected void doModifyTerrainHeight(Vector3f worldLoc, float radius, float heightFactor) { + + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + + setNeedsSave(true); + + int radiusStepsX = (int) (radius / ((Node)terrain).getLocalScale().x); + int radiusStepsZ = (int) (radius / ((Node)terrain).getLocalScale().z); + + float xStepAmount = ((Node)terrain).getLocalScale().x; + float zStepAmount = ((Node)terrain).getLocalScale().z; + + for (int z=-radiusStepsZ; z() { + + public Object call() throws Exception { + doGenerateEntropies(progressMonitor); + return null; + } + }); + } + + private void doGenerateEntropies(ProgressMonitor progressMonitor) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + + terrain.generateEntropy(progressMonitor); + } + + // blocks on scale get + public Float getTextureScale(final int layer) { + try { + Float scale = + SceneApplication.getApplication().enqueue(new Callable() { + public Float call() throws Exception { + return doGetTextureScale(layer); + } + }).get(); + return scale; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + private Float doGetTextureScale(int layer) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return 1f; + MatParam matParam = null; + matParam = terrain.getMaterial().getParam("DiffuseMap_"+layer+"_scale"); + return (Float) matParam.getValue(); + } + + + // blocks on scale set + public void setTextureScale(final int layer, final float scale) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doSetTextureScale(layer, scale); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void doSetTextureScale(int layer, float scale) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + terrain.getMaterial().setFloat("DiffuseMap_"+layer+"_scale", scale); + setNeedsSave(true); + } + + + // blocks on texture get + public Texture getDiffuseTexture(final int layer) { + try { + Texture tex = + SceneApplication.getApplication().enqueue(new Callable() { + public Texture call() throws Exception { + return doGetDiffuseTexture(layer); + } + }).get(); + return tex; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + /** + * Get the diffuse texture at the specified layer. + * Run this on the GL thread! + */ + private Texture doGetDiffuseTexture(int layer) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return null; + MatParam matParam = null; + if (layer == 0) + matParam = terrain.getMaterial().getParam("DiffuseMap"); + else + matParam = terrain.getMaterial().getParam("DiffuseMap_"+layer); + + if (matParam == null || matParam.getValue() == null) { + return null; + } + Texture tex = (Texture) matParam.getValue(); + + return tex; + } + + private Texture getAlphaTexture(final int layer) { + try { + Texture tex = + SceneApplication.getApplication().enqueue(new Callable() { + public Texture call() throws Exception { + Terrain terrain = (Terrain) getTerrain(null); + return doGetAlphaTexture(terrain, layer); + } + }).get(); + return tex; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + private Texture doGetAlphaTexture(Terrain terrain, int alphaLayer) { + if (terrain == null) + return null; + MatParam matParam = null; + if (alphaLayer == 0) + matParam = terrain.getMaterial().getParam("AlphaMap"); + else if(alphaLayer == 1) + matParam = terrain.getMaterial().getParam("AlphaMap_1"); + else if(alphaLayer == 2) + matParam = terrain.getMaterial().getParam("AlphaMap_2"); + + if (matParam == null || matParam.getValue() == null) { + return null; + } + Texture tex = (Texture) matParam.getValue(); + return tex; + } + + /** + * Get the diffuse texture at the specified layer. + * Run this on the GL thread! + */ + private Texture doGetAlphaTextureFromDiffuse(Terrain terrain, int diffuseLayer) { + int alphaIdx = diffuseLayer/4; // 4 = rgba = 4 textures + + return doGetAlphaTexture(terrain, alphaIdx); + /* Terrain terrain = (Terrain) getTerrain(null); + MatParam matParam = null; + //TODO: add when supported +// if (alphaIdx == 0) + matParam = terrain.getMaterial().getParam("AlphaMap"); +// else +// matParam = terrain.getMaterial().getParam("AlphaMap_"+alphaIdx); + + if (matParam == null || matParam.getValue() == null) { + return null; + } + Texture tex = (Texture) matParam.getValue(); + return tex; + */ + } + + /*private void doSetAlphaTexture(int layer, Texture tex) { + int alphaIdx = layer/4; // 4 = rgba = 4 textures + + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + if (alphaIdx == 0) + terrain.getMaterial().setTexture("AlphaMap", tex); + else + terrain.getMaterial().setTexture("AlphaMap_"+alphaIdx, tex); + }*/ + + /** + * Set the diffuse texture at the specified layer. + * Blocks on the GL thread + * @param layer number to set the texture + * @param texturePath if null, the default texture will be used + */ + public void setDiffuseTexture(final int layer, final String texturePath) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doSetDiffuseTexture(layer, texturePath); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void doSetDiffuseTexture(int layer, String texturePath) { + if (texturePath == null || texturePath.equals("")) + texturePath = DEFAULT_TERRAIN_TEXTURE; + + Texture tex = SceneApplication.getApplication().getAssetManager().loadTexture(texturePath); + tex.setWrap(WrapMode.Repeat); + Terrain terrain = (Terrain) getTerrain(null); + + if (layer == 0) + terrain.getMaterial().setTexture("DiffuseMap", tex); + else + terrain.getMaterial().setTexture("DiffuseMap_"+layer, tex); + + setNeedsSave(true); + } + + private void doSetDiffuseTexture(int layer, Texture tex) { + tex.setWrap(WrapMode.Repeat); + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + if (layer == 0) + terrain.getMaterial().setTexture("DiffuseMap", tex); + else + terrain.getMaterial().setTexture("DiffuseMap_"+layer, tex); + + setNeedsSave(true); + } + + public void setDiffuseTexture(final int layer, final Texture texture) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doSetDiffuseTexture(layer, texture); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** + * Remove a whole texture layer: diffuse and normal map + * @param layer + * @param texturePath + */ + public void removeTextureLayer(final int layer) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doRemoveDiffuseTexture(layer); + doRemoveNormalMap(layer); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void doRemoveDiffuseTexture(int layer) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + if (layer == 0) + terrain.getMaterial().clearParam("DiffuseMap"); + else + terrain.getMaterial().clearParam("DiffuseMap_"+layer); + + setNeedsSave(true); + } + + /** + * Remove the normal map at the specified layer. + * @param layer + */ + public void removeNormalMap(final int layer) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doRemoveNormalMap(layer); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void doRemoveNormalMap(int layer) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + if (layer == 0) + terrain.getMaterial().clearParam("NormalMap"); + else + terrain.getMaterial().clearParam("NormalMap_"+layer); + + setNeedsSave(true); + } + + // blocks on normal map get + public Texture getNormalMap(final int layer) { + try { + Texture tex = + SceneApplication.getApplication().enqueue(new Callable() { + public Texture call() throws Exception { + return doGetNormalMap(layer); + } + }).get(); + return tex; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + /** + * Get the normal map texture at the specified layer. + * Run this on the GL thread! + */ + private Texture doGetNormalMap(int layer) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return null; + MatParam matParam = null; + if (layer == 0) + matParam = terrain.getMaterial().getParam("NormalMap"); + else + matParam = terrain.getMaterial().getParam("NormalMap_"+layer); + + if (matParam == null || matParam.getValue() == null) { + return null; + } + Texture tex = (Texture) matParam.getValue(); + return tex; + } + + /** + * Set the normal map at the specified layer. + * Blocks on the GL thread + */ + public void setNormalMap(final int layer, final String texturePath) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doSetNormalMap(layer, texturePath); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void doSetNormalMap(int layer, String texturePath) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + + if (texturePath == null) { + // remove the texture if it is null + if (layer == 0) + terrain.getMaterial().clearParam("NormalMap"); + else + terrain.getMaterial().clearParam("NormalMap_"+layer); + return; + } + + Texture tex = SceneApplication.getApplication().getAssetManager().loadTexture(texturePath); + tex.setWrap(WrapMode.Repeat); + + if (layer == 0) + terrain.getMaterial().setTexture("NormalMap", tex); + else + terrain.getMaterial().setTexture("NormalMap_"+layer, tex); + + setNeedsSave(true); + } + + public void setNormalMap(final int layer, final Texture texture) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doSetNormalMap(layer, texture); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void doSetNormalMap(int layer, Texture tex) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + if (tex == null) { + // remove the texture if it is null + if (layer == 0) + terrain.getMaterial().clearParam("NormalMap"); + else + terrain.getMaterial().clearParam("NormalMap_"+layer); + return; + } + + tex.setWrap(WrapMode.Repeat); + + if (layer == 0) + terrain.getMaterial().setTexture("NormalMap", tex); + else + terrain.getMaterial().setTexture("NormalMap_"+layer, tex); + + setNeedsSave(true); + } + + // blocks on GL thread until terrain is created + public Terrain createTerrain(final Node parent, + final int totalSize, + final int patchSize, + final int alphaTextureSize, + final float[] heightmapData, + final String sceneName) throws IOException + { + try { + Terrain terrain = + SceneApplication.getApplication().enqueue(new Callable() { + public Terrain call() throws Exception { + return doCreateTerrain(parent, totalSize, patchSize, alphaTextureSize, heightmapData, sceneName); + } + }).get(); + return terrain; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + //doCreateTerrain(totalSize, patchSize, alphaTextureSize, heightmapData, sceneName, defaultTextureScale); + return null; // if failed + } + + private Terrain doCreateTerrain(Node parent, + int totalSize, + int patchSize, + int alphaTextureSize, + float[] heightmapData, + String sceneName) throws IOException + { + AssetManager manager = SceneApplication.getApplication().getAssetManager(); + + TerrainQuad terrain = new TerrainQuad("terrain-"+sceneName, patchSize, totalSize, heightmapData); //TODO make this pluggable for different Terrain implementations + com.jme3.material.Material mat = new com.jme3.material.Material(manager, "Common/MatDefs/Terrain/TerrainLighting.j3md"); + + String assetFolder = ""; + if (manager != null && manager instanceof ProjectAssetManager) + assetFolder = ((ProjectAssetManager)manager).getAssetFolderName(); + + // write out 3 alpha blend images + for (int i=0; i cameras = new ArrayList(); + cameras.add(SceneApplication.getApplication().getCamera()); + TerrainLodControl control = new TerrainLodControl(terrain, cameras); + //terrain.addControl(control); // removing this until we figure out a way to have it get the cameras when saved/loaded + + parent.attachChild(terrain); + + doCreateAlphaSaveDataObject(); + + setNeedsSave(true); + + return terrain; + } + + public void saveAlphaImages(final Terrain terrain) { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doSaveAlphaImages(terrain); + return null; + } + }); + } + + /** + * Save the terrain's alpha maps to disk, in the Textures/terrain-alpha/ directory + * @throws IOException + */ + private synchronized void doSaveAlphaImages(Terrain terrain) { + + AssetManager manager = SceneApplication.getApplication().getAssetManager(); + String assetFolder = null; + if (manager != null && manager instanceof ProjectAssetManager) + assetFolder = ((ProjectAssetManager)manager).getAssetFolderName(); + if (assetFolder == null) + throw new IllegalStateException("AssetManager was not a ProjectAssetManager. Could not locate image save directories."); + + Texture alpha = doGetAlphaTexture(terrain, 0); + BufferedImage bi = ImageToAwt.convert(alpha.getImage(), false, true, 0); + File imageFile = new File(assetFolder+alpha.getKey().getName()); + try { + ImageIO.write(bi, "png", imageFile); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + + /*alpha = doGetAlphaTexture(1); + bi = ImageToAwt.convert(alpha.getImage(), false, true, 0); + imageFile = new File(alpha.getKey().getName()); + ImageIO.write(bi, "png", imageFile); + + alpha = doGetAlphaTexture(2); + bi = ImageToAwt.convert(alpha.getImage(), false, true, 0); + imageFile = new File(alpha.getKey().getName()); + ImageIO.write(bi, "png", imageFile); + */ + } + + /** + * Create a skybox with 6 textures. + * Blocking call. + */ + protected Spatial createSky(final Node parent, + final Texture west, + final Texture east, + final Texture north, + final Texture south, + final Texture top, + final Texture bottom, + final Vector3f normalScale) + { + try { + Spatial sky = + SceneApplication.getApplication().enqueue(new Callable() { + public Spatial call() throws Exception { + return doCreateSky(parent, west, east, north, south, top, bottom, normalScale); + } + }).get(); + return sky; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; // if failed + } + + private Spatial doCreateSky(Node parent, + Texture west, + Texture east, + Texture north, + Texture south, + Texture top, + Texture bottom, + Vector3f normalScale) + { + AssetManager manager = SceneApplication.getApplication().getAssetManager(); + Spatial sky = SkyFactory.createSky(manager, west, east, north, south, top, bottom, normalScale); + parent.attachChild(sky); + return sky; + } + + /** + * Create a skybox with a single texture. + * Blocking call. + */ + protected Spatial createSky(final Node parent, + final Texture texture, + final boolean useSpheremap, + final Vector3f normalScale) + { + try { + Spatial sky = + SceneApplication.getApplication().enqueue(new Callable() { + public Spatial call() throws Exception { + return doCreateSky(parent, texture, useSpheremap, normalScale); + } + }).get(); + return sky; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return null; // if failed + } + + private Spatial doCreateSky(Node parent, + Texture texture, + boolean useSpheremap, + Vector3f normalScale) + { + AssetManager manager = SceneApplication.getApplication().getAssetManager(); + Spatial sky = SkyFactory.createSky(manager, texture, normalScale, useSpheremap); + parent.attachChild(sky); + return sky; + } + + public boolean hasTextureAt(final int i) { + try { + Boolean result = + SceneApplication.getApplication().enqueue(new Callable() { + public Boolean call() throws Exception { + Texture tex = doGetDiffuseTexture(i); + return tex != null; + } + }).get(); + return result; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return false; + } + + /** + * Paint the texture at the specified location + * @param selectedTextureIndex the texture to paint + * @param markerLocation the location + * @param toolRadius radius of the brush tool + * @param toolWeight brush weight [0,1] + */ + public void doPaintTexture(int selectedTextureIndex, Vector3f markerLocation, float toolRadius, float toolWeight) { + if (selectedTextureIndex < 0 || markerLocation == null) + return; + + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + + + setNeedsSaveAlpha(true); + + Texture tex = doGetAlphaTextureFromDiffuse(terrain, selectedTextureIndex); + Image image = tex.getImage(); + + Vector2f UV = terrain.getPointPercentagePosition(markerLocation.x, markerLocation.z); + + // get the radius of the brush in pixel-percent + float brushSize = toolRadius/((TerrainQuad)terrain).getTotalSize(); + int texIndex = selectedTextureIndex - ((selectedTextureIndex/4)*4); // selectedTextureIndex/4 is an int floor, do not simplify the equation + boolean erase = toolWeight<0; + if (erase) + toolWeight *= -1; + + doPaintAction(texIndex, image, UV, true, brushSize, erase, toolWeight); + + tex.getImage().setUpdateNeeded(); + } + + /** + * Goes through each pixel in the image. At each pixel it looks to see if the UV mouse coordinate is within the + * of the brush. If it is in the brush radius, it gets the existing color from that pixel so it can add/subtract to/from it. + * Essentially it does a radius check and adds in a fade value. It does this to the color value returned by the + * first pixel color query. + * Next it sets the color of that pixel. If it was within the radius, the color will change. If it was outside + * the radius, then nothing will change, the color will be the same; but it will set it nonetheless. Not efficient. + * + * If the mouse is being dragged with the button down, then the dragged value should be set to true. This will reduce + * the intensity of the brush to 10% of what it should be per spray. Otherwise it goes to 100% opacity within a few pixels. + * This makes it work a little more realistically. + * + * @param image to manipulate + * @param uv the world x,z coordinate + * @param dragged true if the mouse button is down and it is being dragged, use to reduce brush intensity + * @param radius in percentage so it can be translated to the image dimensions + * @param erase true if the tool should remove the paint instead of add it + * @param fadeFalloff the percentage of the radius when the paint begins to start fading + */ + protected void doPaintAction(int texIndex, Image image, Vector2f uv, boolean dragged, float radius, boolean erase, float fadeFalloff){ + Vector2f texuv = new Vector2f(); + ColorRGBA color = ColorRGBA.Black; + + float width = image.getWidth(); + float height = image.getHeight(); + + int minx = (int) (uv.x*width - radius*width); // convert percents to pixels to limit how much we iterate + int maxx = (int) (uv.x*width + radius*width); + int miny = (int) (uv.y*height - radius*height); + int maxy = (int) (uv.y*height + radius*height); + + float radiusSquared = radius*radius; + float radiusFalloff = radius*fadeFalloff; + // go through each pixel, in the radius of the tool, in the image + for (int y = miny; y < maxy; y++){ + for (int x = minx; x < maxx; x++){ + + texuv.set((float)x / width, (float)y / height);// gets the position in percentage so it can compare with the mouse UV coordinate + + float dist = texuv.distanceSquared(uv); + if (dist < radiusSquared ) { // if the pixel is within the distance of the radius, set a color (distance times intensity) + manipulatePixel(image, x, y, color, false); // gets the color at that location (false means don't write to the buffer) + + // calculate the fade falloff intensity + float intensity = 0.1f; + if (dist > radiusFalloff) { + float dr = radius - radiusFalloff; // falloff to radius length + float d2 = dist - radiusFalloff; // dist minus falloff + d2 = d2/dr; // dist percentage of falloff length + intensity = 1-d2; // fade out more the farther away it is + } + + //if (dragged) + // intensity = intensity*0.1f; // magical divide it by 10 to reduce its intensity when mouse is dragged + + if (erase) { + switch (texIndex) { + case 0: + color.r -= intensity; break; + case 1: + color.g -= intensity; break; + case 2: + color.b -= intensity; break; + case 3: + color.a -= intensity; break; + } + } else { + switch (texIndex) { + case 0: + color.r += intensity; break; + case 1: + color.g += intensity; break; + case 2: + color.b += intensity; break; + case 3: + color.a += intensity; break; + } + } + color.clamp(); + + manipulatePixel(image, x, y, color, true); // set the new color + } + + } + } + + image.getData(0).rewind(); + } + + /** + * We are only using RGBA8 images for alpha textures right now. + * @param image to get/set the color on + * @param x location + * @param y location + * @param color color to get/set + * @param write to write the color or not + */ + protected void manipulatePixel(Image image, int x, int y, ColorRGBA color, boolean write){ + ByteBuffer buf = image.getData(0); + int width = image.getWidth(); + + int position = (y * width + x) * 4; + + if ( position> buf.capacity()-1 || position<0 ) + return; + + if (write) { + switch (image.getFormat()){ + case RGBA8: + buf.position( position ); + buf.put(float2byte(color.r)) + .put(float2byte(color.g)) + .put(float2byte(color.b)) + .put(float2byte(color.a)); + return; + default: + throw new UnsupportedOperationException("Image format: "+image.getFormat()); + } + } else { + switch (image.getFormat()){ + case RGBA8: + buf.position( position ); + color.set(byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get())); + return; + default: + throw new UnsupportedOperationException("Image format: "+image.getFormat()); + } + } + + } + + private float byte2float(byte b){ + return ((float)(b & 0xFF)) / 255f; + } + + private byte float2byte(float f){ + return (byte) (f * 255f); + } + + /** + * How many textures are currently being used. + * Blocking call on GL thread + */ + protected int getNumUsedTextures() { + try { + Integer count = + SceneApplication.getApplication().enqueue(new Callable() { + public Integer call() throws Exception { + return doGetNumUsedTextures(); + } + }).get(); + return count; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return -1; + } + + private int doGetNumUsedTextures() { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return 0; + + int count = 0; + + for (int i=0; i() { + public Boolean call() throws Exception { + return doIsTriPlanarEnabled(); + } + }).get(); + return isEnabled; + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return false; + } + + private boolean doIsTriPlanarEnabled() { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return false; + MatParam param = terrain.getMaterial().getParam("useTriPlanarMapping"); + if (param != null) + return (Boolean)param.getValue(); + + return false; + } + + public void setTriPlanarEnabled(final boolean selected) { + try { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doSetTriPlanarEnabled(selected); + return null; + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + /** + * Also adjusts the scale. Normal texture scale uses texture coordinates, + * which are each 1/(total size of the terrain). But for tri planar it doesn't + * use texture coordinates, so we need to re-calculate it to be the same scale. + * @param enabled + * @param terrainTotalSize + */ + private void doSetTriPlanarEnabled(boolean enabled) { + Terrain terrain = (Terrain) getTerrain(null); + if (terrain == null) + return; + terrain.getMaterial().setBoolean("useTriPlanarMapping", enabled); + + float texCoordSize = 1/terrain.getTextureCoordinateScale(); + + if (enabled) { + for (int i=0; i + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java new file mode 100644 index 000000000..b7f15d9fd --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java @@ -0,0 +1,1531 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import com.jme3.gde.core.assets.AssetDataObject; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.PreviewRequest; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneListener; +import com.jme3.gde.core.scene.SceneRequest; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility; +import com.jme3.gde.core.sceneexplorer.nodes.properties.TexturePropertyEditor; +import com.jme3.gde.core.util.DataObjectSaveNode; +import com.jme3.gde.terraineditor.sky.SkyboxWizardAction; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.terrain.ProgressMonitor; +import com.jme3.terrain.Terrain; +import com.jme3.terrain.heightmap.AbstractHeightMap; +import com.jme3.texture.Texture; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Vector; +import java.util.logging.Logger; +import javax.swing.AbstractCellEditor; +import javax.swing.DefaultListSelectionModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import jme3tools.converters.ImageToAwt; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressHandleFactory; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Confirmation; +import org.openide.WizardDescriptor; +import org.openide.cookies.SaveCookie; +import org.openide.loaders.DataObject; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup.Result; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.terraineditor//TerrainEditor//EN", +autostore = false) +public final class TerrainEditorTopComponent extends TopComponent implements SceneListener, LookupListener { + + private static TerrainEditorTopComponent instance; + /** path to the icon used by the component and its open action */ + static final String ICON_PATH = "com/jme3/gde/terraineditor/TerraMonkey.png"; + private static final String PREFERRED_ID = "TerrainEditorTopComponent"; + private final Result result; + TerrainCameraController camController; + TerrainToolController toolController; + TerrainEditorController editorController; + private SceneRequest currentRequest; + private int currentTextureCount; + private boolean alreadyChoosing = false; // used for texture table selection + private CreateTerrainWizardAction terrainWizard; + private SkyboxWizardAction skyboxWizard; + private JmeSpatial selectedSpat; + + public enum TerrainEditButton {none, raiseTerrain, lowerTerrain, smoothTerrain, levelTerrain, paintTerrain, eraseTerrain}; + + private HelpCtx ctx = new HelpCtx("sdk.terrain_editor"); + + public TerrainEditorTopComponent() { + initComponents(); + setName(NbBundle.getMessage(TerrainEditorTopComponent.class, "CTL_TerrainEditorTopComponent")); + setToolTipText(NbBundle.getMessage(TerrainEditorTopComponent.class, "HINT_TerrainEditorTopComponent")); + setIcon(ImageUtilities.loadImage(ICON_PATH, true)); + result = Utilities.actionsGlobalContext().lookupResult(JmeSpatial.class); + } + + + class EntropyCalcProgressMonitor implements ProgressMonitor { + + private ProgressHandle progressHandle; + private float progress = 0; + private float max = 0; + private final Object lock = new Object(); + + public void incrementProgress(float f) { + progress += f; + progressHandle.progress((int)progress); + } + + public void setMonitorMax(float f) { + max = f; +// java.awt.EventQueue.invokeLater(new Runnable() { +// public void run() { +// synchronized(lock){ + if (progressHandle == null) { + progressHandle = ProgressHandleFactory.createHandle("Calculating terrain entropies..."); + progressHandle.start((int) max); + } +// } +// } +// }); + } + + public float getMonitorMax() { + return max; + } + + public void progressComplete() { +// SwingUtilities.invokeLater(new Runnable() { +// public void run() { + progressHandle.finish(); +// } +// }); + } + + } + + private void setHintText(String text) { + hintTextArea.setText(text); + } + + private void setHintText(TerrainEditButton terrainEditButton) { + if (TerrainEditButton.none.equals(terrainEditButton) ) + hintTextArea.setText(""); + else + hintTextArea.setText("Switch between camera and tool controls by holding down SHIFT"); + } + + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + terrainModButtonGroup = new ToggleButtonGroup(); + textureFileChooser = new javax.swing.JFileChooser(); + jPanel1 = new javax.swing.JPanel(); + hintPanel = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + hintTextArea = new javax.swing.JTextArea(); + toolSettingsPanel = new javax.swing.JPanel(); + radiusLabel = new javax.swing.JLabel(); + radiusSlider = new javax.swing.JSlider(); + heightSlider = new javax.swing.JSlider(); + heightLabel = new javax.swing.JLabel(); + paintingPanel = new javax.swing.JPanel(); + jScrollPane2 = new javax.swing.JScrollPane(); + textureTable = new javax.swing.JTable(); + remainingTexTitleLabel = new javax.swing.JLabel(); + remainingTexturesLabel = new javax.swing.JLabel(); + addTextureButton = new javax.swing.JButton(); + removeTextureButton = new javax.swing.JButton(); + triPlanarCheckBox = new javax.swing.JCheckBox(); + terrainOpsPanel = new javax.swing.JPanel(); + genEntropiesButton = new javax.swing.JButton(); + jButton1 = new javax.swing.JButton(); + jToolBar1 = new javax.swing.JToolBar(); + createTerrainButton = new javax.swing.JButton(); + jSeparator1 = new javax.swing.JToolBar.Separator(); + raiseTerrainButton = new javax.swing.JToggleButton(); + lowerTerrainButton = new javax.swing.JToggleButton(); + smoothTerrainButton = new javax.swing.JToggleButton(); + roughTerrainButton = new javax.swing.JToggleButton(); + jSeparator2 = new javax.swing.JToolBar.Separator(); + paintButton = new javax.swing.JToggleButton(); + eraseButton = new javax.swing.JToggleButton(); + + textureFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.textureFileChooser.approveButtonText_1")); // NOI18N + textureFileChooser.setCurrentDirectory(new java.io.File("C:\\Assets\\Textures")); + textureFileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.textureFileChooser.dialogTitle_1")); // NOI18N + textureFileChooser.setFileFilter(new ImageFilter()); + + hintPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.hintPanel.border.title"))); // NOI18N + + hintTextArea.setColumns(20); + hintTextArea.setEditable(false); + hintTextArea.setLineWrap(true); + hintTextArea.setRows(2); + hintTextArea.setTabSize(4); + hintTextArea.setWrapStyleWord(true); + hintTextArea.setFocusable(false); + hintTextArea.setRequestFocusEnabled(false); + jScrollPane1.setViewportView(hintTextArea); + + javax.swing.GroupLayout hintPanelLayout = new javax.swing.GroupLayout(hintPanel); + hintPanel.setLayout(hintPanelLayout); + hintPanelLayout.setHorizontalGroup( + hintPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE) + ); + hintPanelLayout.setVerticalGroup( + hintPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE) + ); + + toolSettingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.toolSettingsPanel.border.title"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(radiusLabel, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.radiusLabel.text")); // NOI18N + + radiusSlider.setMajorTickSpacing(5); + radiusSlider.setMaximum(20); + radiusSlider.setMinorTickSpacing(1); + radiusSlider.setPaintTicks(true); + radiusSlider.setSnapToTicks(true); + radiusSlider.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.radiusSlider.toolTipText")); // NOI18N + radiusSlider.setValue(5); + radiusSlider.addPropertyChangeListener(new java.beans.PropertyChangeListener() { + public void propertyChange(java.beans.PropertyChangeEvent evt) { + radiusSliderPropertyChange(evt); + } + }); + + heightSlider.setMajorTickSpacing(20); + heightSlider.setMaximum(200); + heightSlider.setPaintTicks(true); + heightSlider.addPropertyChangeListener(new java.beans.PropertyChangeListener() { + public void propertyChange(java.beans.PropertyChangeEvent evt) { + heightSliderPropertyChange(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(heightLabel, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.heightLabel.text")); // NOI18N + + javax.swing.GroupLayout toolSettingsPanelLayout = new javax.swing.GroupLayout(toolSettingsPanel); + toolSettingsPanel.setLayout(toolSettingsPanelLayout); + toolSettingsPanelLayout.setHorizontalGroup( + toolSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(toolSettingsPanelLayout.createSequentialGroup() + .addGroup(toolSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(radiusLabel) + .addComponent(heightLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(toolSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(heightSlider, 0, 0, Short.MAX_VALUE) + .addComponent(radiusSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(46, Short.MAX_VALUE)) + ); + toolSettingsPanelLayout.setVerticalGroup( + toolSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(toolSettingsPanelLayout.createSequentialGroup() + .addGroup(toolSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(radiusSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(radiusLabel)) + .addGap(21, 21, 21) + .addGroup(toolSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(heightLabel) + .addComponent(heightSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(56, Short.MAX_VALUE)) + ); + + paintingPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.paintingPanel.border.title"))); // NOI18N + + textureTable.setModel(new TextureTableModel()); + textureTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); + textureTable.setCellEditor(new TextureCellRendererEditor()); + textureTable.setColumnSelectionAllowed(true); + textureTable.setSelectionModel(new TableSelectionModel()); + textureTable.getTableHeader().setReorderingAllowed(false); + jScrollPane2.setViewportView(textureTable); + textureTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + + org.openide.awt.Mnemonics.setLocalizedText(remainingTexTitleLabel, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.remainingTexTitleLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(remainingTexturesLabel, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.remainingTexturesLabel.text")); // NOI18N + + addTextureButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-add-texture.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(addTextureButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.addTextureButton.text")); // NOI18N + addTextureButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.addTextureButton.toolTipText")); // NOI18N + addTextureButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + addTextureButtonActionPerformed(evt); + } + }); + + removeTextureButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-remove-texture.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(removeTextureButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.removeTextureButton.text")); // NOI18N + removeTextureButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.removeTextureButton.toolTipText")); // NOI18N + removeTextureButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + removeTextureButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(triPlanarCheckBox, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.triPlanarCheckBox.text")); // NOI18N + triPlanarCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.triPlanarCheckBox.toolTipText")); // NOI18N + triPlanarCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + triPlanarCheckBoxActionPerformed(evt); + } + }); + + javax.swing.GroupLayout paintingPanelLayout = new javax.swing.GroupLayout(paintingPanel); + paintingPanel.setLayout(paintingPanelLayout); + paintingPanelLayout.setHorizontalGroup( + paintingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(paintingPanelLayout.createSequentialGroup() + .addGroup(paintingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, paintingPanelLayout.createSequentialGroup() + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 277, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(paintingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(removeTextureButton, 0, 0, Short.MAX_VALUE) + .addComponent(addTextureButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, Short.MAX_VALUE))) + .addGroup(paintingPanelLayout.createSequentialGroup() + .addComponent(remainingTexTitleLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(remainingTexturesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 78, Short.MAX_VALUE) + .addComponent(triPlanarCheckBox))) + .addContainerGap()) + ); + paintingPanelLayout.setVerticalGroup( + paintingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(paintingPanelLayout.createSequentialGroup() + .addGroup(paintingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(paintingPanelLayout.createSequentialGroup() + .addComponent(addTextureButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(removeTextureButton)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 106, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(paintingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(remainingTexTitleLabel) + .addComponent(remainingTexturesLabel) + .addComponent(triPlanarCheckBox))) + ); + + terrainOpsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.terrainOpsPanel.border.title"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(genEntropiesButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.genEntropiesButton.text")); // NOI18N + genEntropiesButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.genEntropiesButton.toolTipText")); // NOI18N + genEntropiesButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + genEntropiesButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout terrainOpsPanelLayout = new javax.swing.GroupLayout(terrainOpsPanel); + terrainOpsPanel.setLayout(terrainOpsPanelLayout); + terrainOpsPanelLayout.setHorizontalGroup( + terrainOpsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(terrainOpsPanelLayout.createSequentialGroup() + .addGroup(terrainOpsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(genEntropiesButton) + .addComponent(jButton1)) + .addContainerGap(31, Short.MAX_VALUE)) + ); + terrainOpsPanelLayout.setVerticalGroup( + terrainOpsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(terrainOpsPanelLayout.createSequentialGroup() + .addComponent(genEntropiesButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1) + .addContainerGap(79, Short.MAX_VALUE)) + ); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + createTerrainButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-new.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(createTerrainButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.createTerrainButton.text")); // NOI18N + createTerrainButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.createTerrainButton.toolTipText")); // NOI18N + createTerrainButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + createTerrainButtonActionPerformed(evt); + } + }); + jToolBar1.add(createTerrainButton); + jToolBar1.add(jSeparator1); + + terrainModButtonGroup.add(raiseTerrainButton); + raiseTerrainButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-up.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(raiseTerrainButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.raiseTerrainButton.text")); // NOI18N + raiseTerrainButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.raiseTerrainButton.toolTipText")); // NOI18N + raiseTerrainButton.setActionCommand(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.raiseTerrainButton.actionCommand")); // NOI18N + raiseTerrainButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + raiseTerrainButtonActionPerformed(evt); + } + }); + jToolBar1.add(raiseTerrainButton); + + terrainModButtonGroup.add(lowerTerrainButton); + lowerTerrainButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-down.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(lowerTerrainButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.lowerTerrainButton.text")); // NOI18N + lowerTerrainButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.lowerTerrainButton.toolTipText")); // NOI18N + lowerTerrainButton.setActionCommand(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.lowerTerrainButton.actionCommand")); // NOI18N + lowerTerrainButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + lowerTerrainButtonActionPerformed(evt); + } + }); + jToolBar1.add(lowerTerrainButton); + + terrainModButtonGroup.add(smoothTerrainButton); + smoothTerrainButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-smooth.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(smoothTerrainButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.smoothTerrainButton.text")); // NOI18N + smoothTerrainButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.smoothTerrainButton.toolTipText")); // NOI18N + smoothTerrainButton.setActionCommand(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.smoothTerrainButton.actionCommand")); // NOI18N + smoothTerrainButton.setEnabled(false); + jToolBar1.add(smoothTerrainButton); + + terrainModButtonGroup.add(roughTerrainButton); + roughTerrainButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-rough.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(roughTerrainButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.roughTerrainButton.text")); // NOI18N + roughTerrainButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.roughTerrainButton.toolTipText")); // NOI18N + roughTerrainButton.setActionCommand(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.roughTerrainButton.actionCommand")); // NOI18N + roughTerrainButton.setEnabled(false); + jToolBar1.add(roughTerrainButton); + jToolBar1.add(jSeparator2); + + terrainModButtonGroup.add(paintButton); + paintButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-paint-circle.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(paintButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.paintButton.text")); // NOI18N + paintButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.paintButton.toolTipText")); // NOI18N + paintButton.setFocusable(false); + paintButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + paintButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + paintButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + paintButtonActionPerformed(evt); + } + }); + jToolBar1.add(paintButton); + + terrainModButtonGroup.add(eraseButton); + eraseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-erase-circle.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(eraseButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.eraseButton.text")); // NOI18N + eraseButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.eraseButton.toolTipText")); // NOI18N + eraseButton.setFocusable(false); + eraseButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + eraseButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + eraseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + eraseButtonActionPerformed(evt); + } + }); + jToolBar1.add(eraseButton); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(toolSettingsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(paintingPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(terrainOpsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(hintPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 1019, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(hintPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(terrainOpsPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(paintingPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(toolSettingsPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void createTerrainButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createTerrainButtonActionPerformed + addSpatial("Terrain"); + }//GEN-LAST:event_createTerrainButtonActionPerformed + + private void raiseTerrainButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_raiseTerrainButtonActionPerformed + + //toolController.setShowGrid(true); + + if (raiseTerrainButton.isSelected()) { + toolController.setTerrainEditButtonState(TerrainEditButton.raiseTerrain); + setHintText(TerrainEditButton.raiseTerrain); + } else { + toolController.setTerrainEditButtonState(TerrainEditButton.none); + setHintText(TerrainEditButton.none); + } + }//GEN-LAST:event_raiseTerrainButtonActionPerformed + + private void lowerTerrainButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lowerTerrainButtonActionPerformed + if (lowerTerrainButton.isSelected()) { + toolController.setTerrainEditButtonState(TerrainEditButton.lowerTerrain); + setHintText(TerrainEditButton.lowerTerrain); + } else { + toolController.setTerrainEditButtonState(TerrainEditButton.none); + setHintText(TerrainEditButton.none); + } + }//GEN-LAST:event_lowerTerrainButtonActionPerformed + + private void radiusSliderPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_radiusSliderPropertyChange + if (toolController != null) + toolController.setHeightToolRadius(radiusSlider.getValue()); + }//GEN-LAST:event_radiusSliderPropertyChange + + private void heightSliderPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_heightSliderPropertyChange + if (toolController != null) + toolController.setHeightToolHeight(heightSlider.getValue()); // should always be values upto and over 100, because it will be divided by 100 + }//GEN-LAST:event_heightSliderPropertyChange + + private void genEntropiesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_genEntropiesButtonActionPerformed + if (editorController != null) { + setHintText("Run entropy generation when you are finished modifying the terrain's height. It is a slow process but required for some LOD operations."); + EntropyCalcProgressMonitor monitor = new EntropyCalcProgressMonitor(); + editorController.generateEntropies(monitor); + } + }//GEN-LAST:event_genEntropiesButtonActionPerformed + + private void paintButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_paintButtonActionPerformed + if (paintButton.isSelected()) { + toolController.setTerrainEditButtonState(TerrainEditButton.paintTerrain); + setHintText(TerrainEditButton.paintTerrain); + } else { + toolController.setTerrainEditButtonState(TerrainEditButton.none); + setHintText(TerrainEditButton.none); + } + }//GEN-LAST:event_paintButtonActionPerformed + + private void addTextureButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTextureButtonActionPerformed + if (editorController == null || editorController.getTerrain(null) == null) + return; + int index = getTableModel().getRowCount(); // get the last row + addNewTextureLayer(index); + if (currentTextureCount >= editorController.MAX_TEXTURE_LAYERS) + addTextureButton.setEnabled(false); + if (currentTextureCount > 0) + removeTextureButton.setEnabled(true); + remainingTexturesLabel.setText(""+(editorController.MAX_TEXTURE_LAYERS-currentTextureCount)); + }//GEN-LAST:event_addTextureButtonActionPerformed + + private void removeTextureButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeTextureButtonActionPerformed + if (editorController == null || editorController.getTerrain(null) == null) + return; + if (getTableModel().getRowCount() == 0) + return; + int index = getTableModel().getRowCount() - 1; // get the last row + removeTextureLayer(index); + if (currentTextureCount == 0) + removeTextureButton.setEnabled(false); + if (currentTextureCount < editorController.MAX_TEXTURE_LAYERS) + addTextureButton.setEnabled(true); + remainingTexturesLabel.setText(""+(editorController.MAX_TEXTURE_LAYERS-currentTextureCount)); + }//GEN-LAST:event_removeTextureButtonActionPerformed + + private void eraseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_eraseButtonActionPerformed + if (eraseButton.isSelected()) { + toolController.setTerrainEditButtonState(TerrainEditButton.eraseTerrain); + setHintText(TerrainEditButton.eraseTerrain); + } else { + toolController.setTerrainEditButtonState(TerrainEditButton.none); + setHintText(TerrainEditButton.none); + } + }//GEN-LAST:event_eraseButtonActionPerformed + + private void triPlanarCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_triPlanarCheckBoxActionPerformed + editorController.setTriPlanarEnabled(triPlanarCheckBox.isSelected()); + ((TextureTableModel)textureTable.getModel()).updateScales(); + if ( triPlanarCheckBox.isSelected()) + setHintText("Make sure your scale is a power of 2, (1/2^n), when in tri-planar mode"); + }//GEN-LAST:event_triPlanarCheckBoxActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + addSpatial("Skybox"); + }//GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton addTextureButton; + private javax.swing.JButton createTerrainButton; + private javax.swing.JToggleButton eraseButton; + private javax.swing.JButton genEntropiesButton; + private javax.swing.JLabel heightLabel; + private javax.swing.JSlider heightSlider; + private javax.swing.JPanel hintPanel; + private javax.swing.JTextArea hintTextArea; + private javax.swing.JButton jButton1; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JToolBar.Separator jSeparator1; + private javax.swing.JToolBar.Separator jSeparator2; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToggleButton lowerTerrainButton; + private javax.swing.JToggleButton paintButton; + private javax.swing.JPanel paintingPanel; + private javax.swing.JLabel radiusLabel; + private javax.swing.JSlider radiusSlider; + private javax.swing.JToggleButton raiseTerrainButton; + private javax.swing.JLabel remainingTexTitleLabel; + private javax.swing.JLabel remainingTexturesLabel; + private javax.swing.JButton removeTextureButton; + private javax.swing.JToggleButton roughTerrainButton; + private javax.swing.JToggleButton smoothTerrainButton; + private javax.swing.ButtonGroup terrainModButtonGroup; + private javax.swing.JPanel terrainOpsPanel; + private javax.swing.JFileChooser textureFileChooser; + private javax.swing.JTable textureTable; + private javax.swing.JPanel toolSettingsPanel; + private javax.swing.JCheckBox triPlanarCheckBox; + // End of variables declaration//GEN-END:variables + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized TerrainEditorTopComponent getDefault() { + if (instance == null) { + instance = new TerrainEditorTopComponent(); + } + return instance; + } + + + public void addSpatial(final String name) { + if (selectedSpat == null) { + + Confirmation msg = new NotifyDescriptor.Confirmation( + "You must select a Node to add the "+name+" to in the Scene Explorer window", + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + return; + } + + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + if ("Terrain".equals(name)) { + if (terrainWizard == null) + terrainWizard = new CreateTerrainWizardAction(this); + terrainWizard.performAction(); + } else if ("Skybox".equals(name)) { + if (skyboxWizard == null) + skyboxWizard = new SkyboxWizardAction(this); + skyboxWizard.performAction(); + } else if ("Ocean".equals(name)) { + + } + } + + } + + + protected void generateTerrain(final WizardDescriptor wizardDescriptor) { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + + int totalSize = (Integer) wizardDescriptor.getProperty("totalSize"); + int patchSize = (Integer) wizardDescriptor.getProperty("patchSize"); + int alphaTextureSize = (Integer) wizardDescriptor.getProperty("alphaTextureSize"); + + float[] heightmapData = null; + AbstractHeightMap heightmap = (AbstractHeightMap) wizardDescriptor.getProperty("abstractHeightMap"); + if (heightmap != null) { + heightmap.load(); // can take a while + heightmapData = heightmap.getHeightMap(); + } + + // eg. Scenes/newScene1.j3o + String[] split1 = currentRequest.getWindowTitle().split("/"); + String[] split2 = split1[split1.length-1].split("\\."); + + Terrain terrain = null; + try { + terrain = editorController.createTerrain((Node)node, + totalSize, + patchSize, + alphaTextureSize, + heightmapData, + split2[0]); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + + addSaveNode(selectedSpat); + + editorController.getAlphaSaveDataObject(this); + + editorController.setNeedsSave(true); + + currentTextureCount = editorController.getNumUsedTextures(); + remainingTexturesLabel.setText(""+(editorController.MAX_TEXTURE_LAYERS-currentTextureCount)); + + reinitTextureTable(); // update the UI + + refreshSelected(); + + } + + public void generateSkybox(WizardDescriptor wiz) { + + Spatial sky = null; + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + + if ((Boolean)wiz.getProperty("multipleTextures")) { + Texture south = (Texture)wiz.getProperty("textureSouth"); + Texture north = (Texture)wiz.getProperty("textureNorth"); + Texture east = (Texture)wiz.getProperty("textureEast"); + Texture west = (Texture)wiz.getProperty("textureWest"); + Texture top = (Texture)wiz.getProperty("textureTop"); + Texture bottom = (Texture)wiz.getProperty("textureBottom"); + Vector3f normalScale = (Vector3f)wiz.getProperty("normalScale"); + sky = editorController.createSky((Node)node, west, east, north, south, top, bottom, normalScale); + } else { + Texture textureSingle = (Texture)wiz.getProperty("textureSingle"); + Vector3f normalScale = (Vector3f)wiz.getProperty("normalScale"); + boolean useSpheremap = (Boolean)wiz.getProperty("useSpheremap"); + sky = editorController.createSky((Node)node, textureSingle, useSpheremap, normalScale); + } + + editorController.setNeedsSave(true); + refreshSelected(); + } + + private void refreshSelected() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (selectedSpat != null) { + selectedSpat.refresh(false); + } + } + }); + + } + + /** + * listener for node selection changes + */ + public void resultChanged(LookupEvent ev) { + if (currentRequest == null || !currentRequest.isDisplayed()) { + return; + } + Collection items = (Collection) result.allInstances(); + for (JmeSpatial spatial : items) { + selectSpatial(spatial); + return; + } + } + + private void selectSpatial(JmeSpatial spatial) { + selectedSpat = spatial; + } + + + + /* + * + *******************************************************************/ + + /** + * Obtain the TerrainEditorTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized TerrainEditorTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(TerrainEditorTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof TerrainEditorTopComponent) { + return (TerrainEditorTopComponent) win; + } + Logger.getLogger(TerrainEditorTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public void componentOpened() { + super.componentOpened(); + + } + + @Override + public void componentClosed() { + super.componentClosed(); + if (currentRequest != null) { + SceneApplication.getApplication().closeScene(currentRequest); + } + + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + @Override + public HelpCtx getHelpCtx() { + return ctx; + } + + public void openScene(Spatial spat, AssetDataObject file, ProjectAssetManager manager) { + cleanupControllers(); + SceneApplication.getApplication().addSceneListener(this); + result.addLookupListener(this); + //TODO: handle request change + Node node; + if (spat instanceof Node) { + node = (Node) spat; + } else { + node = new Node(); + node.attachChild(spat); + } + JmeNode jmeNode = NodeUtility.createNode(node, file, false); + SceneRequest request = new SceneRequest(this, jmeNode, manager); + request.setDataObject(file); + request.setHelpCtx(ctx); + + addSaveNode(jmeNode); + + Logger.getLogger(TerrainEditorTopComponent.class.getName()).finer("Terrain openScene "+file.getName()); + + if (editorController != null) { + editorController.cleanup(); + } + editorController = new TerrainEditorController(jmeNode, file, this); + this.currentRequest = request; + request.setWindowTitle("TerrainEditor - " + manager.getRelativeAssetPath(file.getPrimaryFile().getPath())); + request.setToolNode(new Node("TerrainEditorToolNode")); + SceneApplication.getApplication().requestScene(request); + } + + // run on GL thread + public void sceneRequested(SceneRequest request) { + + if (request.equals(currentRequest)) { + Logger.getLogger(TerrainEditorTopComponent.class.getName()).finer("Terrain sceneRequested "+request.getWindowTitle()); + + setSceneInfo(currentRequest.getJmeNode(), true); + + editorController.doGetAlphaSaveDataObject(this); + + // if the opened scene has terrain, add it to a save node + Terrain terrain = (Terrain)editorController.getTerrain(null); + if (terrain != null) { + // add the terrain root save node + + // ugh! wtf, why is this fixing the material problem? + ((Node)terrain).setMaterial(terrain.getMaterial()); + // it appears when loading the actual applied material on the terrain + // does not reflect the material that we get from the terrain. + + refreshSelected(); + } + + if (camController != null) { + camController.disable(); + } + if (toolController != null) { + toolController.cleanup(); + } + + for (int i=0; i 0) + toolController.setSelectedTextureIndex(0); // select the first row by default + else + toolController.setSelectedTextureIndex(-1); + + currentTextureCount = editorController.getNumUsedTextures(); + remainingTexturesLabel.setText(""+(editorController.MAX_TEXTURE_LAYERS-currentTextureCount)); + triPlanarCheckBox.setSelected(editorController.isTriPlanarEnabled()); + } + + /** + * Adds another texture layer to the material, sets a default texture for it. + * Assumes that the new index is in the range of the amount of available textures + * the material can support. + * Assumes this is the last index, or else messy stuff in the material will happen. + * @param the index it is being placed at. + */ + private void addNewTextureLayer(int newIndex) { + getTableModel().addNewTexture(newIndex); + } + + /** + * Removes the selected index. + * If the index is -1, it just returns. + * Assumes this is the last index, or else messy stuff in the material will happen. + * @param selectedIndex + */ + private void removeTextureLayer(int selectedIndex) { + if (selectedIndex < 0) + return; // abort + + getTableModel().removeTexture(selectedIndex); + } + + private TextureTableModel getTableModel() { + if (textureTable == null) + return null; + return (TextureTableModel) textureTable.getModel(); + } + + /** + * Holds the table information and relays changes to that data to the actual + * terrain material. Info such as textures and texture scales. + */ + public class TextureTableModel extends DefaultTableModel { + //private Material terrainMaterial; + + public TextureTableModel() { + super(new String[]{"", "Texture", "Normal", "Scale"}, 0); + } + + public void initModel() { + + // empty the table + while (getRowCount() > 0) + removeRow(0); + + // fill the table with the proper data + for (int i=0; i getRowCount()-1) + return; + super.setValueAt(aValue, row, column); + + if (column == 3) + setTextureScale(row, new Float((String)aValue)); + } + + protected void addNewTexture(int newIndex) { + float scale = editorController.DEFAULT_TEXTURE_SCALE; + + // add it to the table model + addRow(new Object[]{"", newIndex, null, scale}); // add to the table model + + // and add it to the actual material + setTexture(newIndex, (String)null); + setTextureScale(newIndex, scale); + currentTextureCount = editorController.getNumUsedTextures(); + } + + protected void setTexture(final int index, final Texture texture) { + setValueAt(index, index, 1); + editorController.setDiffuseTexture(index, texture); + } + + protected void setTexture(final int index, final String texturePath) { + setValueAt(index, index, 1); + editorController.setDiffuseTexture(index, texturePath); + } + + protected void setNormal(final int index, final String texturePath) { + setValueAt(index, index, 2); + editorController.setNormalMap(index, texturePath); + currentTextureCount = editorController.getNumUsedTextures(); + } + + protected void setNormal(final int index, final Texture texture) { + setValueAt(index, index, 2); + editorController.setNormalMap(index, texture); + currentTextureCount = editorController.getNumUsedTextures(); + } + + protected void setTextureScale(int index, float scale) { + editorController.setTextureScale(index, scale); + } + + protected void removeTexture(final int index) { + removeRow(index); + editorController.removeTextureLayer(index); + currentTextureCount = editorController.getNumUsedTextures(); + } + + } + + /** + * signals to the tool controller when a different row is selected + */ + public class TableSelectionModel extends DefaultListSelectionModel { + + public TableSelectionModel() { + super.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + if (toolController != null) + toolController.setSelectedTextureIndex(textureTable.getSelectedRow()); + } + }); + } + } + + /** + * The renderer and editor for the Diffuse and Normal texture buttons in the texture table. + * Delegates texture changes and queries to the table model, which then delegates to + * the TerrainEditorController. + */ + public abstract class CellRendererEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + return getButton(value, row, column); + + } + + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + return getButton(value, row, column); + } + + protected abstract void setTextureInModel(int row, String path); + + protected abstract void setTextureInModel(int row, Texture tex); + + protected abstract Texture getTextureFromModel(int index); + + protected abstract boolean supportsNullTexture(); + + private JButton getButton(Object value, final int row, final int column) { + + final JButton lbl = new JButton(); + //TODO check if there is a normal or a texture here at this index + if (value == null) + value = getTableModel().getValueAt(row, column); + + if (value != null) { + int index = 0; + // this is messy, fix it so we know what values are coming in from where: + if (value instanceof String) + index = new Float((String)value).intValue(); + else if (value instanceof Float) + index = ((Float)value).intValue(); + else if (value instanceof Integer) + index = (Integer)value; + + Texture tex = getTextureFromModel(index); // delegate to sub-class + + //Texture tex = SceneApplication.getApplication().getAssetManager().loadTexture((String)value); + if (tex != null) { + Icon icon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + lbl.setIcon(icon); + } + } + + lbl.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) { + + if (alreadyChoosing) + return; + + alreadyChoosing = true; + + try { + Texture selectedTex = getTextureFromModel(row); // delegates to sub class + TexturePropertyEditor editor = new TexturePropertyEditor(selectedTex); + Component view = editor.getCustomEditor(); + view.setVisible(true); + Texture tex = (Texture)editor.getValue(); + if (editor.getValue() != null) { + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + lbl.setIcon(newicon); + } else if (supportsNullTexture()){ + lbl.setIcon(null); + } + setTextureInModel(row, tex); + } finally { + alreadyChoosing = false; + } + } + }); + return lbl; + } + } + + public class TextureCellRendererEditor extends CellRendererEditor { + @Override + public Object getCellEditorValue() { + int row = textureTable.getSelectedRow(); + if (row < 0) + return null; + return getTableModel().getValueAt(row, 1); + } + + @Override + protected void setTextureInModel(int row, String path) { + if (path != null) + getTableModel().setTexture(row, path); + } + + @Override + protected void setTextureInModel(int row, Texture tex) { + if (tex != null) + getTableModel().setTexture(row, tex); + } + + @Override + protected Texture getTextureFromModel(int index) { + return editorController.getDiffuseTexture(index); + } + + @Override + protected boolean supportsNullTexture() { + return false; + } + + } + + public class NormalCellRendererEditor extends CellRendererEditor { + @Override + public Object getCellEditorValue() { + int row = textureTable.getSelectedRow(); + if (row < 0) + return null; + return getTableModel().getValueAt(row, 2); + } + + @Override + protected void setTextureInModel(int row, String path) { + getTableModel().setNormal(row, path); + } + + @Override + protected void setTextureInModel(int row, Texture tex) { + getTableModel().setNormal(row, tex); + } + + @Override + protected Texture getTextureFromModel(int index) { + return editorController.getNormalMap(index); + } + + @Override + protected boolean supportsNullTexture() { + return true; + } + } + + private Component getTopComponent() { + return this; + } + + + /** + * A file filter to only show images + */ + public class ImageFilter extends FileFilter { + + Utils utils = new Utils(); + //Accept all directories and all gif, jpg, tiff, or png files. + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + + String extension = utils.getExtension(f); + if (extension != null) { + if (extension.equals(utils.tiff) || + extension.equals(utils.tif) || + extension.equals(utils.gif) || + extension.equals(utils.jpeg) || + extension.equals(utils.jpg) || + extension.equals(utils.png)) { + return true; + } else { + return false; + } + } + + return false; + } + + //The description of this filter + public String getDescription() { + return "Just Images"; + } + } + + /** + * restricts the file chooser to a specified directory tree, such as the assets folder + */ + class DirectoryRestrictedFileSystemView extends FileSystemView + { + private final File[] rootDirectories; + + DirectoryRestrictedFileSystemView(File rootDirectory) + { + this.rootDirectories = new File[] {rootDirectory}; + } + + DirectoryRestrictedFileSystemView(File[] rootDirectories) + { + this.rootDirectories = rootDirectories; + } + + @Override + public Boolean isTraversable(File f) { + if (f.getAbsolutePath().indexOf(rootDirectories[0].getAbsolutePath()) >= 0) + return Boolean.valueOf(f.isDirectory()); + else + return false; + } + + @Override + public File getDefaultDirectory() + { + return rootDirectories[0]; + } + + @Override + public File getHomeDirectory() + { + return rootDirectories[0]; + } + + @Override + public File[] getRoots() + { + return rootDirectories; + } + + + @Override + public File createNewFolder(File containingDir) throws IOException + { + throw new UnsupportedOperationException("Unable to create directory"); + } + /* + @Override + public File[] getRoots() + { + return rootDirectories; + } + + @Override + public boolean isRoot(File file) + { + for (File root : rootDirectories) { + if (root.equals(file)) { + return true; + } + } + return false; + }*/ + } + + public class Utils { + public final String jpeg = "jpeg"; + public final String jpg = "jpg"; + public final String gif = "gif"; + public final String tiff = "tiff"; + public final String tif = "tif"; + public final String png = "png"; + + /* + * Get the extension of a file. + */ + public String getExtension(File f) { + String ext = null; + String s = f.getName(); + int i = s.lastIndexOf('.'); + + if (i > 0 && i < s.length() - 1) { + ext = s.substring(i+1).toLowerCase(); + } + return ext; + } + + /** Returns an ImageIcon, or null if the path was invalid. */ + protected ImageIcon createImageIcon(String path) { + java.net.URL imgURL = Utils.class.getResource(path); + if (imgURL != null) { + return new ImageIcon(imgURL); + } else { + //System.err.println("Couldn't find file: " + path); + return null; + } + } + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponentSettings.xml b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponentSettings.xml new file mode 100644 index 000000000..733cbba60 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponentWstcref.xml b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponentWstcref.xml new file mode 100644 index 000000000..f7e19921f --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java new file mode 100644 index 000000000..7931e3417 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import com.jme3.asset.AssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.controller.SceneToolController; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.terraineditor.TerrainEditorTopComponent.TerrainEditButton; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.VertexBuffer; +import com.jme3.scene.shape.Sphere; +import com.jme3.util.IntMap.Entry; +import java.util.concurrent.Callable; + +/** + * The controller for the terrain modification tools. It will in turn interact + * with the TerrainEditorController to actually modify the terrain in the scene. + * + * Maintains the edit tool state: what tool is activated and what should be done with it. + * + * @author bowens + */ +public class TerrainToolController extends SceneToolController { + + private JmeSpatial jmeRootNode; + private TerrainEditButton currentEditButtonState = TerrainEditButton.none; + private Geometry marker; + private TerrainEditorController editorController; + private float heightToolRadius; + private float heightToolHeight; + private float heightAmount; + private float paintAmount; + private int selectedTextureIndex = -1; + + public TerrainToolController(Node toolsNode, AssetManager manager, JmeNode rootNode) { + super(toolsNode, manager); + this.jmeRootNode = rootNode; + } + + public void setEditorController(TerrainEditorController editorController) { + this.editorController = editorController; + } + + /** + * assumes [0,200] + */ + public void setHeightToolHeight(float heightToolHeight) { + this.heightToolHeight = heightToolHeight; + this.heightAmount = heightToolHeight/100f; + this.paintAmount = heightToolHeight/200f; + } + + public void setHeightToolRadius(float radius) { + this.heightToolRadius = radius; + setEditToolSize(radius); + } + + public void setSelectedTextureIndex(int index) { + this.selectedTextureIndex = index; + } + + + @Override + protected void initTools() { + super.initTools(); + + marker = new Geometry("edit marker"); + Mesh m = new Sphere(8, 8, 3); + marker.setMesh(m); + Material mat = new Material(manager, "Common/MatDefs/Misc/WireColor.j3md"); + mat.setColor("Color", ColorRGBA.Green); + marker.setMaterial(mat); + marker.setLocalTranslation(0,0,0); + } + + protected void setMarkerRadius(float radius) { + //((Sphere)marker.getMesh()).set; + } + + public TerrainEditButton getCurrentEditButtonState() { + return currentEditButtonState; + } + + public void setTerrainEditButtonState(final TerrainEditButton state) { + + currentEditButtonState = state; + if (state == TerrainEditButton.none) { + hideEditTool(); + } else if (state == TerrainEditButton.raiseTerrain || state == TerrainEditButton.lowerTerrain) { + showEditTool(state); + } else if (state == TerrainEditButton.paintTerrain || state == TerrainEditButton.eraseTerrain) { + showEditTool(state); + } + } + + + public void hideEditTool() { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doHideEditTool(); + return null; + } + }); + } + + private void doHideEditTool() { + marker.removeFromParent(); + } + + public void showEditTool(final TerrainEditButton terrainEditButton) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doShowEditTool(terrainEditButton); + return null; + } + }); + + } + + private void doShowEditTool(TerrainEditButton terrainEditButton) { + //TODO show different tool marker depending on terrainEditButton type + + toolsNode.attachChild(marker); + + + } + + public void setEditToolSize(final float size) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doSetEditToolSize(size); + return null; + } + }); + } + + private void doSetEditToolSize(float size) { + for (Entry e: marker.getMesh().getBuffers()) + ((VertexBuffer)e.getValue()).resetObject(); + ((Sphere)marker.getMesh()).updateGeometry(8, 8, size); + } + + public void doMoveEditTool(Vector3f pos) { + if (marker != null) { + marker.setLocalTranslation(pos); + //System.out.println(marker.getLocalTranslation()); + } + } + + public Vector3f getMarkerLocation() { + if (marker != null) + return marker.getLocalTranslation(); + else + return null; + } + + public boolean isTerrainEditButtonEnabled() { + return getCurrentEditButtonState() != TerrainEditButton.none; + } + + /** + * raise/lower/paint the terrain + */ + public void doTerrainEditToolActivated() { + + if (TerrainEditButton.raiseTerrain == getCurrentEditButtonState() ) { + editorController.doModifyTerrainHeight(getMarkerLocation(), heightToolRadius, heightAmount); + } + else if (TerrainEditButton.lowerTerrain == getCurrentEditButtonState() ) { + editorController.doModifyTerrainHeight(getMarkerLocation(), heightToolRadius, -heightAmount); + } + else if(TerrainEditButton.paintTerrain == getCurrentEditButtonState()) { + editorController.doPaintTexture(selectedTextureIndex, getMarkerLocation(), heightToolRadius, paintAmount); + } + else if (TerrainEditButton.eraseTerrain == getCurrentEditButtonState() ) { + editorController.doPaintTexture(selectedTextureIndex, getMarkerLocation(), heightToolRadius, -paintAmount); + } + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/ToggleButtonGroup.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/ToggleButtonGroup.java new file mode 100644 index 000000000..d3048a02c --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/ToggleButtonGroup.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.ButtonModel; + +/** + * A custom toggle button group that allows you to deselect + * a button that is already selected. + * + * @author bowens + */ +public class ToggleButtonGroup extends ButtonGroup { + private ButtonModel modifiedSelection; + + public void add(AbstractButton b) { + if (b == null) { + return; + } + buttons.addElement(b); + + if (b.isSelected()) { + if (modifiedSelection == null) { + modifiedSelection = b.getModel(); + } else { + b.setSelected(false); + } + } + + b.getModel().setGroup(this); + } + + public void remove(AbstractButton b) { + if (b == null) { + return; + } + buttons.removeElement(b); + if (b.getModel() == modifiedSelection) { + modifiedSelection = null; + } + b.getModel().setGroup(null); + } + + public ButtonModel getSelection() { + return modifiedSelection; + } + + public void setSelected(ButtonModel m, boolean b) { + if (!b && m == modifiedSelection) { + modifiedSelection = null; + return; + } + if (b && m != null && m != modifiedSelection) { + ButtonModel oldSelection = modifiedSelection; + modifiedSelection = m; + if (oldSelection != null) { + oldSelection.setSelected(false); + } + m.setSelected(true); + } + } + + public boolean isSelected(ButtonModel m) { + return (m == modifiedSelection); + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/dirt.jpg b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/dirt.jpg new file mode 100644 index 000000000..474206828 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/dirt.jpg differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-add-texture.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-add-texture.png new file mode 100644 index 000000000..75c2ed495 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-add-texture.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-down.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-down.png new file mode 100644 index 000000000..d6acdc8d0 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-down.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-erase-circle.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-erase-circle.png new file mode 100644 index 000000000..c17d22bc9 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-erase-circle.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-new.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-new.png new file mode 100644 index 000000000..bde82de0e Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-new.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-paint-circle.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-paint-circle.png new file mode 100644 index 000000000..5f321e5e1 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-paint-circle.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-remove-texture.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-remove-texture.png new file mode 100644 index 000000000..84c5e318f Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-remove-texture.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-rough.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-rough.png new file mode 100644 index 000000000..2c3d60dd0 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-rough.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-smooth.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-smooth.png new file mode 100644 index 000000000..1b626e862 Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-smooth.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-up.png b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-up.png new file mode 100644 index 000000000..52769455f Binary files /dev/null and b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/icon_terrain-up.png differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/layer.xml b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/layer.xml new file mode 100644 index 000000000..eeec4f04e --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/layer.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/AddSkyboxAction.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/AddSkyboxAction.java new file mode 100644 index 000000000..856b0eb95 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/AddSkyboxAction.java @@ -0,0 +1,119 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.terraineditor.sky; + +import com.jme3.asset.AssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractNewSpatialAction; +import com.jme3.gde.core.sceneexplorer.nodes.actions.NewSpatialAction; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.texture.Texture; +import com.jme3.util.SkyFactory; +import java.awt.Component; +import java.awt.Dialog; +import java.lang.reflect.InvocationTargetException; +import java.text.MessageFormat; +import javax.swing.JComponent; +import org.openide.DialogDisplayer; +import org.openide.WizardDescriptor; +import org.openide.util.Exceptions; + +/** + * + * @author normenhansen + */ +@org.openide.util.lookup.ServiceProvider(service = NewSpatialAction.class) +public class AddSkyboxAction extends AbstractNewSpatialAction { + + private WizardDescriptor.Panel[] panels; + + public AddSkyboxAction() { + name = "Skybox.."; + } + + @Override + protected Spatial doCreateSpatial(Node parent) { + try { + final WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + java.awt.EventQueue.invokeAndWait(new Runnable() { + + public void run() { + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle("Skybox Wizard"); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.setVisible(true); + dialog.toFront(); + } + }); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + if (!cancelled) { + return generateSkybox(wizardDescriptor); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (InvocationTargetException ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + + public Spatial generateSkybox(WizardDescriptor wiz) { + AssetManager assetManager = SceneApplication.getApplication().getAssetManager(); + if ((Boolean) wiz.getProperty("multipleTextures")) { + Texture south = (Texture) wiz.getProperty("textureSouth"); + Texture north = (Texture) wiz.getProperty("textureNorth"); + Texture east = (Texture) wiz.getProperty("textureEast"); + Texture west = (Texture) wiz.getProperty("textureWest"); + Texture top = (Texture) wiz.getProperty("textureTop"); + Texture bottom = (Texture) wiz.getProperty("textureBottom"); + Vector3f normalScale = (Vector3f) wiz.getProperty("normalScale"); + return SkyFactory.createSky(assetManager, west, east, north, south, top, bottom, normalScale); + } else { + Texture textureSingle = (Texture) wiz.getProperty("textureSingle"); + Vector3f normalScale = (Vector3f) wiz.getProperty("normalScale"); + boolean useSpheremap = (Boolean) wiz.getProperty("useSpheremap"); + return SkyFactory.createSky(assetManager, textureSingle, normalScale, useSpheremap); + } + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new SkyboxWizardPanel1(), + new SkyboxWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/Bundle.properties b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/Bundle.properties new file mode 100644 index 000000000..4efcbacfa --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/Bundle.properties @@ -0,0 +1,33 @@ +SkyboxVisualPanel1.jLabel1.text=Skybox Type +SkyboxVisualPanel1.jTextArea1.text=Multiple textures has 6 textures: North, South, East, West, Top, Bottom.\n\nSingle texture has just one texture that is wrapped. +SkyboxVisualPanel2.titleLabel.text=Texture +SkyboxVisualPanel2.jLabel1.text=North +SkyboxVisualPanel2.jLabel2.text=South +SkyboxVisualPanel2.jLabel3.text=East +SkyboxVisualPanel2.jLabel4.text=West +SkyboxVisualPanel2.jLabel5.text=Top +SkyboxVisualPanel2.jLabel6.text=Bottom +SkyboxVisualPanel2.jLabel7.text=Normal Scale (x,y,z): +SkyboxVisualPanel2.jLabel8.text=Texture +SkyboxVisualPanel2.singleTexLoadButton.text=Load +SkyboxVisualPanel2.multipleTexNorthLoadButton.text=Load +SkyboxVisualPanel2.multipleTexSouthLoadButton.text=Load +SkyboxVisualPanel2.multipleTexEastLoadButton.text=Load +SkyboxVisualPanel2.multipleTexWestLoadButton.text=Load +SkyboxVisualPanel2.multipleTexTopLoadButton.text=Load +SkyboxVisualPanel2.multipleTexBottomLoadButton.text=Load +SkyboxVisualPanel2.jLabel9.text=Normal Scale (x,y,z): +SkyboxVisualPanel2.spheremapCheckBox.text=Sphere map +SkyboxVisualPanel2.normal1X.text=1 +SkyboxVisualPanel2.normal1Y.text=1 +SkyboxVisualPanel2.normal1Z.text=1 +SkyboxVisualPanel2.normal2X.text=1 +SkyboxVisualPanel2.normal2Y.text=1 +SkyboxVisualPanel2.normal2Z.text=1 +SkyboxVisualPanel2.northPic.text= +SkyboxVisualPanel2.southPic.text= +SkyboxVisualPanel2.eastPic.text= +SkyboxVisualPanel2.westPic.text= +SkyboxVisualPanel2.topPic.text= +SkyboxVisualPanel2.bottomPic.text= +SkyboxVisualPanel2.singlePic.text= diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel1.form b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel1.form new file mode 100644 index 000000000..ba01d2bc2 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel1.form @@ -0,0 +1,91 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel1.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel1.java new file mode 100644 index 000000000..8353daf32 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel1.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor.sky; + +import javax.swing.JComboBox; +import javax.swing.JPanel; + +public final class SkyboxVisualPanel1 extends JPanel { + + /** Creates new form SkyboxVisualPanel1 */ + public SkyboxVisualPanel1() { + initComponents(); + } + + @Override + public String getName() { + return "Single or multiple textures?"; + } + + public JComboBox getSkyTypeCombo() { + return skyTypeCombo; + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + skyTypeCombo = new javax.swing.JComboBox(); + jLabel1 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + skyTypeCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Multiple textures", "Single texture" })); + + jLabel1.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel1.class, "SkyboxVisualPanel1.jLabel1.text")); // NOI18N + + jTextArea1.setColumns(20); + jTextArea1.setEditable(false); + jTextArea1.setLineWrap(true); + jTextArea1.setRows(5); + jTextArea1.setText(org.openide.util.NbBundle.getMessage(SkyboxVisualPanel1.class, "SkyboxVisualPanel1.jTextArea1.text")); // NOI18N + jTextArea1.setWrapStyleWord(true); + jScrollPane1.setViewportView(jTextArea1); + + 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(jLabel1) + .addGroup(layout.createSequentialGroup() + .addComponent(skyTypeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 236, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(55, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addGap(41, 41, 41) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(skyTypeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(103, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JComboBox skyTypeCombo; + // End of variables declaration//GEN-END:variables +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel2.form b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel2.form new file mode 100644 index 000000000..b8f5b0fa3 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel2.form @@ -0,0 +1,489 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel2.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel2.java new file mode 100644 index 000000000..0c1044ed9 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxVisualPanel2.java @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor.sky; + +import com.jme3.gde.core.sceneexplorer.nodes.properties.TexturePropertyEditor; +import com.jme3.texture.Texture; +import java.awt.Component; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import javax.swing.JTextField; +import jme3tools.converters.ImageToAwt; +import org.openide.util.ImageUtilities; + +public final class SkyboxVisualPanel2 extends JPanel { + + /** Creates new form SkyboxVisualPanel2 */ + public SkyboxVisualPanel2() { + initComponents(); + } + + @Override + public String getName() { + return "Textures"; + } + + public JPanel getMultipleTexturePanel() { + return multipleTexturePanel; + } + + public JPanel getSingleTexturePanel() { + return singleTexturePanel; + } + + TexturePropertyEditor editorNorth = new TexturePropertyEditor(); + TexturePropertyEditor editorSouth = new TexturePropertyEditor(); + TexturePropertyEditor editorEast = new TexturePropertyEditor(); + TexturePropertyEditor editorWest = new TexturePropertyEditor(); + TexturePropertyEditor editorTop = new TexturePropertyEditor(); + TexturePropertyEditor editorBottom = new TexturePropertyEditor(); + TexturePropertyEditor editorSingle = new TexturePropertyEditor(); + + public TexturePropertyEditor getEditorBottom() { + return editorBottom; + } + + public TexturePropertyEditor getEditorEast() { + return editorEast; + } + + public TexturePropertyEditor getEditorNorth() { + return editorNorth; + } + + public TexturePropertyEditor getEditorSingle() { + return editorSingle; + } + + public TexturePropertyEditor getEditorSouth() { + return editorSouth; + } + + public TexturePropertyEditor getEditorTop() { + return editorTop; + } + + public TexturePropertyEditor getEditorWest() { + return editorWest; + } + + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + titleLabel = new javax.swing.JLabel(); + multipleTexturePanel = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + multipleTexNorthLoadButton = new javax.swing.JButton(); + multipleTexSouthLoadButton = new javax.swing.JButton(); + multipleTexEastLoadButton = new javax.swing.JButton(); + multipleTexWestLoadButton = new javax.swing.JButton(); + multipleTexTopLoadButton = new javax.swing.JButton(); + multipleTexBottomLoadButton = new javax.swing.JButton(); + jLabel7 = new javax.swing.JLabel(); + normal1X = new javax.swing.JTextField(); + normal1Y = new javax.swing.JTextField(); + normal1Z = new javax.swing.JTextField(); + northPic = new javax.swing.JLabel(); + southPic = new javax.swing.JLabel(); + eastPic = new javax.swing.JLabel(); + westPic = new javax.swing.JLabel(); + topPic = new javax.swing.JLabel(); + bottomPic = new javax.swing.JLabel(); + singleTexturePanel = new javax.swing.JPanel(); + jLabel8 = new javax.swing.JLabel(); + singleTexLoadButton = new javax.swing.JButton(); + jLabel9 = new javax.swing.JLabel(); + normal2X = new javax.swing.JTextField(); + normal2Y = new javax.swing.JTextField(); + normal2Z = new javax.swing.JTextField(); + spheremapCheckBox = new javax.swing.JCheckBox(); + singlePic = new javax.swing.JLabel(); + + titleLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); + org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.titleLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel4.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel5.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel6.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(multipleTexNorthLoadButton, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.multipleTexNorthLoadButton.text")); // NOI18N + multipleTexNorthLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + multipleTexNorthLoadButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(multipleTexSouthLoadButton, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.multipleTexSouthLoadButton.text")); // NOI18N + multipleTexSouthLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + multipleTexSouthLoadButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(multipleTexEastLoadButton, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.multipleTexEastLoadButton.text")); // NOI18N + multipleTexEastLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + multipleTexEastLoadButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(multipleTexWestLoadButton, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.multipleTexWestLoadButton.text")); // NOI18N + multipleTexWestLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + multipleTexWestLoadButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(multipleTexTopLoadButton, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.multipleTexTopLoadButton.text")); // NOI18N + multipleTexTopLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + multipleTexTopLoadButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(multipleTexBottomLoadButton, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.multipleTexBottomLoadButton.text")); // NOI18N + multipleTexBottomLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + multipleTexBottomLoadButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel7.text")); // NOI18N + + normal1X.setText(org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.normal1X.text")); // NOI18N + + normal1Y.setText(org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.normal1Y.text")); // NOI18N + + normal1Z.setText(org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.normal1Z.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(northPic, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.northPic.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(southPic, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.southPic.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(eastPic, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.eastPic.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(westPic, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.westPic.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(topPic, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.topPic.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(bottomPic, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.bottomPic.text")); // NOI18N + + javax.swing.GroupLayout multipleTexturePanelLayout = new javax.swing.GroupLayout(multipleTexturePanel); + multipleTexturePanel.setLayout(multipleTexturePanelLayout); + multipleTexturePanelLayout.setHorizontalGroup( + multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addGap(16, 16, 16) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel1) + .addComponent(jLabel3) + .addComponent(jLabel2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addComponent(multipleTexNorthLoadButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(northPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(47, 47, 47) + .addComponent(jLabel7) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(normal1X, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(normal1Y, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(6, 6, 6) + .addComponent(normal1Z, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addComponent(multipleTexSouthLoadButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(southPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addComponent(multipleTexEastLoadButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(eastPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addGap(19, 19, 19) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel5) + .addComponent(jLabel4))) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel6))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addComponent(multipleTexBottomLoadButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(bottomPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addComponent(multipleTexWestLoadButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(westPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addComponent(multipleTexTopLoadButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(topPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))))) + .addContainerGap(27, Short.MAX_VALUE)) + ); + multipleTexturePanelLayout.setVerticalGroup( + multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addGap(11, 11, 11) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(jLabel7) + .addComponent(normal1X, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(normal1Y, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(normal1Z, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(multipleTexNorthLoadButton) + .addComponent(northPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(multipleTexSouthLoadButton)) + .addComponent(southPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(eastPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3) + .addComponent(multipleTexEastLoadButton))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel4) + .addComponent(multipleTexWestLoadButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(multipleTexTopLoadButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)) + .addGroup(multipleTexturePanelLayout.createSequentialGroup() + .addComponent(westPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(topPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(12, 12, 12))) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(bottomPic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(multipleTexBottomLoadButton) + .addComponent(jLabel6))) + .addGap(58, 58, 58)) + ); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel8.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(singleTexLoadButton, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.singleTexLoadButton.text")); // NOI18N + singleTexLoadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + singleTexLoadButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel9, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel9.text")); // NOI18N + + normal2X.setText(org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.normal2X.text")); // NOI18N + + normal2Y.setText(org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.normal2Y.text")); // NOI18N + + normal2Z.setText(org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.normal2Z.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(spheremapCheckBox, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.spheremapCheckBox.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(singlePic, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.singlePic.text")); // NOI18N + + javax.swing.GroupLayout singleTexturePanelLayout = new javax.swing.GroupLayout(singleTexturePanel); + singleTexturePanel.setLayout(singleTexturePanelLayout); + singleTexturePanelLayout.setHorizontalGroup( + singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(singleTexturePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(singleTexturePanelLayout.createSequentialGroup() + .addComponent(jLabel8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(singleTexLoadButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(singlePic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(39, 39, 39) + .addComponent(jLabel9) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(normal2X, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(normal2Y, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(6, 6, 6) + .addComponent(normal2Z, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(spheremapCheckBox)) + .addContainerGap(31, Short.MAX_VALUE)) + ); + singleTexturePanelLayout.setVerticalGroup( + singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(singleTexturePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(singlePic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel8) + .addComponent(singleTexLoadButton)) + .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(normal2X, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(normal2Y, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(normal2Z, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel9)))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(spheremapCheckBox) + .addContainerGap(98, Short.MAX_VALUE)) + ); + + 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(multipleTexturePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(titleLabel) + .addComponent(singleTexturePanel, 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(titleLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(multipleTexturePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(singleTexturePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(46, 46, 46)) + ); + }// //GEN-END:initComponents + + private void multipleTexSouthLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multipleTexSouthLoadButtonActionPerformed + Component view = editorSouth.getCustomEditor(); + view.setVisible(true); + if (editorSouth.getValue() != null) { + Texture tex = (Texture)editorSouth.getValue(); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + southPic.setIcon(newicon); + } + }//GEN-LAST:event_multipleTexSouthLoadButtonActionPerformed + + private void multipleTexNorthLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multipleTexNorthLoadButtonActionPerformed + Component view = editorNorth.getCustomEditor(); + view.setVisible(true); + if (editorNorth.getValue() != null) { + Texture tex = (Texture)editorNorth.getValue(); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + northPic.setIcon(newicon); + } + }//GEN-LAST:event_multipleTexNorthLoadButtonActionPerformed + + private void multipleTexEastLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multipleTexEastLoadButtonActionPerformed + Component view = editorEast.getCustomEditor(); + view.setVisible(true); + if (editorEast.getValue() != null) { + Texture tex = (Texture)editorEast.getValue(); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + eastPic.setIcon(newicon); + } + }//GEN-LAST:event_multipleTexEastLoadButtonActionPerformed + + private void multipleTexWestLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multipleTexWestLoadButtonActionPerformed + Component view = editorWest.getCustomEditor(); + view.setVisible(true); + if (editorWest.getValue() != null) { + Texture tex = (Texture)editorWest.getValue(); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + westPic.setIcon(newicon); + } + }//GEN-LAST:event_multipleTexWestLoadButtonActionPerformed + + private void multipleTexTopLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multipleTexTopLoadButtonActionPerformed + Component view = editorTop.getCustomEditor(); + view.setVisible(true); + if (editorTop.getValue() != null) { + Texture tex = (Texture)editorTop.getValue(); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + topPic.setIcon(newicon); + } + }//GEN-LAST:event_multipleTexTopLoadButtonActionPerformed + + private void multipleTexBottomLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multipleTexBottomLoadButtonActionPerformed + Component view = editorBottom.getCustomEditor(); + view.setVisible(true); + if (editorBottom.getValue() != null) { + Texture tex = (Texture)editorBottom.getValue(); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + bottomPic.setIcon(newicon); + } + }//GEN-LAST:event_multipleTexBottomLoadButtonActionPerformed + + private void singleTexLoadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_singleTexLoadButtonActionPerformed + Component view = editorSingle.getCustomEditor(); + view.setVisible(true); + if (editorSingle.getValue() != null) { + Texture tex = (Texture)editorSingle.getValue(); + Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); + singlePic.setIcon(newicon); + } + }//GEN-LAST:event_singleTexLoadButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel bottomPic; + private javax.swing.JLabel eastPic; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JButton multipleTexBottomLoadButton; + private javax.swing.JButton multipleTexEastLoadButton; + private javax.swing.JButton multipleTexNorthLoadButton; + private javax.swing.JButton multipleTexSouthLoadButton; + private javax.swing.JButton multipleTexTopLoadButton; + private javax.swing.JButton multipleTexWestLoadButton; + private javax.swing.JPanel multipleTexturePanel; + private javax.swing.JTextField normal1X; + private javax.swing.JTextField normal1Y; + private javax.swing.JTextField normal1Z; + private javax.swing.JTextField normal2X; + private javax.swing.JTextField normal2Y; + private javax.swing.JTextField normal2Z; + private javax.swing.JLabel northPic; + private javax.swing.JLabel singlePic; + private javax.swing.JButton singleTexLoadButton; + private javax.swing.JPanel singleTexturePanel; + private javax.swing.JLabel southPic; + private javax.swing.JCheckBox spheremapCheckBox; + private javax.swing.JLabel titleLabel; + private javax.swing.JLabel topPic; + private javax.swing.JLabel westPic; + // End of variables declaration//GEN-END:variables + + public JTextField getNormal1X() { + return normal1X; + } + + public JTextField getNormal1Y() { + return normal1Y; + } + + public JTextField getNormal1Z() { + return normal1Z; + } + + public JTextField getNormal2X() { + return normal2X; + } + + public JTextField getNormal2Y() { + return normal2Y; + } + + public JTextField getNormal2Z() { + return normal2Z; + } + + public JCheckBox getSpheremapCheckBox() { + return spheremapCheckBox; + } + + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardAction.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardAction.java new file mode 100644 index 000000000..fb26054dc --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardAction.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor.sky; + +import com.jme3.gde.terraineditor.TerrainEditorTopComponent; +import java.awt.Component; +import java.awt.Dialog; +import java.text.MessageFormat; +import javax.swing.JComponent; +import org.openide.DialogDisplayer; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CallableSystemAction; + +// An example action demonstrating how the wizard could be called from within +// your code. You can copy-paste the code below wherever you need. +public final class SkyboxWizardAction extends CallableSystemAction { + + private WizardDescriptor.Panel[] panels; + private TerrainEditorTopComponent topComponent; + + public SkyboxWizardAction(TerrainEditorTopComponent topComponent) { + this.topComponent = topComponent; + } + + public void performAction() { + WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() + wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); + wizardDescriptor.setTitle("Skybox Wizard"); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); + dialog.setVisible(true); + dialog.toFront(); + boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION; + if (!cancelled) { + topComponent.generateSkybox(wizardDescriptor); + } + } + + /** + * Initialize panels representing individual wizard's steps and sets + * various properties for them influencing wizard appearance. + */ + private WizardDescriptor.Panel[] getPanels() { + if (panels == null) { + panels = new WizardDescriptor.Panel[]{ + new SkyboxWizardPanel1(), + new SkyboxWizardPanel2() + }; + String[] steps = new String[panels.length]; + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + // Default step name to component name of panel. Mainly useful + // for getting the name of the target chooser to appear in the + // list of steps. + steps[i] = c.getName(); + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Sets step number of a component + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Sets steps names for a panel + jc.putClientProperty("WizardPanel_contentData", steps); + // Turn on subtitle creation on each step + jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); + // Show steps on the left side with the image on the background + jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); + // Turn on numbering of all steps + jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); + } + } + } + return panels; + } + + public String getName() { + return "Start Sample Wizard"; + } + + @Override + public String iconResource() { + return null; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardPanel1.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardPanel1.java new file mode 100644 index 000000000..4494af363 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardPanel1.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor.sky; + +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class SkyboxWizardPanel1 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private Component 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. + public Component getComponent() { + if (component == null) { + component = new SkyboxVisualPanel1(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + } + + public void storeSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + SkyboxVisualPanel1 comp = (SkyboxVisualPanel1) getComponent(); + boolean multiple = "Multiple textures".equalsIgnoreCase( comp.getSkyTypeCombo().getSelectedItem().toString() ); + wiz.putProperty("multipleTextures", multiple ); + } +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardPanel2.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardPanel2.java new file mode 100644 index 000000000..85010ab92 --- /dev/null +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/sky/SkyboxWizardPanel2.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2009-2010 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.terraineditor.sky; + +import com.jme3.math.Vector3f; +import com.jme3.texture.Texture; +import java.awt.Component; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; + +public class SkyboxWizardPanel2 implements WizardDescriptor.Panel { + + /** + * The visual component that displays this panel. If you need to access the + * component from this class, just use getComponent(). + */ + private Component component; + + private boolean multipleTextures; + + // 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. + public Component getComponent() { + if (component == null) { + component = new SkyboxVisualPanel2(); + } + return component; + } + + public HelpCtx getHelp() { + // Show no Help button for this panel: + return HelpCtx.DEFAULT_HELP; + // If you have context help: + // return new HelpCtx(SampleWizardPanel1.class); + } + + 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...), then: + // return someCondition(); + // and when this condition changes (last form field filled in...) then: + // fireChangeEvent(); + // and uncomment the complicated stuff below. + } + + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + /* + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + protected final void fireChangeEvent() { + Iterator it; + synchronized (listeners) { + it = new HashSet(listeners).iterator(); + } + ChangeEvent ev = new ChangeEvent(this); + while (it.hasNext()) { + it.next().stateChanged(ev); + } + } + */ + + // You can use a settings object to keep track of state. Normally the + // settings object will be the WizardDescriptor, so you can use + // WizardDescriptor.getProperty & putProperty to store information entered + // by the user. + public void readSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + multipleTextures = (Boolean)wiz.getProperty("multipleTextures"); + SkyboxVisualPanel2 comp = (SkyboxVisualPanel2) getComponent(); + if (multipleTextures) { + comp.getMultipleTexturePanel().setVisible(true); + comp.getSingleTexturePanel().setVisible(false); + } else { + comp.getMultipleTexturePanel().setVisible(false); + comp.getSingleTexturePanel().setVisible(true); + } + } + + public void storeSettings(Object settings) { + WizardDescriptor wiz = (WizardDescriptor) settings; + SkyboxVisualPanel2 comp = (SkyboxVisualPanel2) getComponent(); + if (multipleTextures) { + wiz.putProperty("textureSouth", (Texture)comp.getEditorSouth().getValue()); + wiz.putProperty("textureNorth", (Texture)comp.getEditorNorth().getValue()); + wiz.putProperty("textureEast", (Texture)comp.getEditorEast().getValue()); + wiz.putProperty("textureWest", (Texture)comp.getEditorWest().getValue()); + wiz.putProperty("textureTop", (Texture)comp.getEditorTop().getValue()); + wiz.putProperty("textureBottom", (Texture)comp.getEditorBottom().getValue()); + float x = new Float(comp.getNormal1X().getText()); + float y = new Float(comp.getNormal1Y().getText()); + float z = new Float(comp.getNormal1Z().getText()); + wiz.putProperty("normalScale", new Vector3f(x,y,z) ); + } else { + wiz.putProperty("textureSingle", (Texture)comp.getEditorSingle().getValue()); + float x = new Float(comp.getNormal2X().getText()); + float y = new Float(comp.getNormal2Y().getText()); + float z = new Float(comp.getNormal2Z().getText()); + wiz.putProperty("normalScale", new Vector3f(x,y,z) ); + wiz.putProperty("useSpheremap", comp.getSpheremapCheckBox().isSelected()); + } + } +} diff --git a/sdk/jme3-tests-template/build.xml b/sdk/jme3-tests-template/build.xml new file mode 100644 index 000000000..b40595350 --- /dev/null +++ b/sdk/jme3-tests-template/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.templates.tests. + + diff --git a/sdk/jme3-tests-template/manifest.mf b/sdk/jme3-tests-template/manifest.mf new file mode 100644 index 000000000..b02ca26a0 --- /dev/null +++ b/sdk/jme3-tests-template/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.templates.tests/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/templates/tests/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/templates/tests/Bundle.properties + diff --git a/sdk/jme3-tests-template/nbproject/build-impl.xml b/sdk/jme3-tests-template/nbproject/build-impl.xml new file mode 100644 index 000000000..4d25c4df3 --- /dev/null +++ b/sdk/jme3-tests-template/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-tests-template/nbproject/genfiles.properties b/sdk/jme3-tests-template/nbproject/genfiles.properties new file mode 100644 index 000000000..9893c15fb --- /dev/null +++ b/sdk/jme3-tests-template/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=23c8cf2e +build.xml.script.CRC32=0dd27b54 +build.xml.stylesheet.CRC32=79c3b980@1.31.2.7 +# 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=23c8cf2e +nbproject/build-impl.xml.script.CRC32=9b9554d3 +nbproject/build-impl.xml.stylesheet.CRC32=261c4bef@1.31.2.7 diff --git a/sdk/jme3-tests-template/nbproject/project.properties b/sdk/jme3-tests-template/nbproject/project.properties new file mode 100644 index 000000000..67b025e71 --- /dev/null +++ b/sdk/jme3-tests-template/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=jMonkeyEngine +nbm.needs.restart=true +spec.version.base=0.6.0 diff --git a/sdk/jme3-tests-template/nbproject/project.xml b/sdk/jme3-tests-template/nbproject/project.xml new file mode 100644 index 000000000..a38443e4b --- /dev/null +++ b/sdk/jme3-tests-template/nbproject/project.xml @@ -0,0 +1,78 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.templates.tests + + + + com.jme3.gde.project.testdata + + 1 + 0.5 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.28.1 + + + + org.netbeans.modules.projectuiapi + + + + 1 + 1.40.1.6 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + + + + diff --git a/sdk/jme3-tests-template/nbproject/suite.properties b/sdk/jme3-tests-template/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-tests-template/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/Bundle.properties b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/Bundle.properties new file mode 100644 index 000000000..e090309a2 --- /dev/null +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/Bundle.properties @@ -0,0 +1,12 @@ +LBL_CreateProjectStep=Name and Location +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin provides a project template containing all test classes of jMonkeyEngine3. +OpenIDE-Module-Name=jMonkeyEngine3 Tests Template +OpenIDE-Module-Short-Description=Provides jMP Project Template with jME3 Tests +Templates/Project/JME3/JmeTestsProject.zip=JME3 Tests +JmeTestsPanelVisual.browseButton.text=Br&owse... +JmeTestsPanelVisual.createdFolderLabel.text=Project &Folder: +JmeTestsPanelVisual.projectLocationLabel.text=Project &Location: +JmeTestsPanelVisual.projectNameLabel.text=Project &Name: +JmeTestsPanelVisual.browseButton.actionCommand=BROWSE diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsDescription.html b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsDescription.html new file mode 100644 index 000000000..32c9c1f5c --- /dev/null +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsDescription.html @@ -0,0 +1,13 @@ + + + + + + + This template creates a project with all test classes from the jme3 source to get examples for jme3 features.
+ Feel free to modify the code samples and experiment! If you break something, you can always recreate the packaged samples from this template. + + diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsPanelVisual.form b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsPanelVisual.form new file mode 100644 index 000000000..7e5fd5e2b --- /dev/null +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsPanelVisual.form @@ -0,0 +1,122 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsPanelVisual.java b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsPanelVisual.java new file mode 100644 index 000000000..ce0ed0af0 --- /dev/null +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsPanelVisual.java @@ -0,0 +1,260 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.templates.tests; + +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.JPanel; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Document; +import org.netbeans.spi.project.ui.support.ProjectChooser; +import org.openide.WizardDescriptor; +import org.openide.WizardValidationException; +import org.openide.filesystems.FileUtil; + +public class JmeTestsPanelVisual extends JPanel implements DocumentListener { + + public static final String PROP_PROJECT_NAME = "projectName"; + private JmeTestsWizardPanel panel; + + public JmeTestsPanelVisual(JmeTestsWizardPanel panel) { + initComponents(); + this.panel = panel; + // Register listener on the textFields to make the automatic updates + projectNameTextField.getDocument().addDocumentListener(this); + projectLocationTextField.getDocument().addDocumentListener(this); + } + + public String getProjectName() { + return this.projectNameTextField.getText(); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + projectNameLabel = new javax.swing.JLabel(); + projectNameTextField = new javax.swing.JTextField(); + projectLocationLabel = new javax.swing.JLabel(); + projectLocationTextField = new javax.swing.JTextField(); + browseButton = new javax.swing.JButton(); + createdFolderLabel = new javax.swing.JLabel(); + createdFolderTextField = new javax.swing.JTextField(); + + projectNameLabel.setLabelFor(projectNameTextField); + org.openide.awt.Mnemonics.setLocalizedText(projectNameLabel, org.openide.util.NbBundle.getMessage(JmeTestsPanelVisual.class, "JmeTestsPanelVisual.projectNameLabel.text")); // NOI18N + + projectLocationLabel.setLabelFor(projectLocationTextField); + org.openide.awt.Mnemonics.setLocalizedText(projectLocationLabel, org.openide.util.NbBundle.getMessage(JmeTestsPanelVisual.class, "JmeTestsPanelVisual.projectLocationLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(JmeTestsPanelVisual.class, "JmeTestsPanelVisual.browseButton.text")); // NOI18N + browseButton.setActionCommand(org.openide.util.NbBundle.getMessage(JmeTestsPanelVisual.class, "JmeTestsPanelVisual.browseButton.actionCommand")); // NOI18N + browseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseButtonActionPerformed(evt); + } + }); + + createdFolderLabel.setLabelFor(createdFolderTextField); + org.openide.awt.Mnemonics.setLocalizedText(createdFolderLabel, org.openide.util.NbBundle.getMessage(JmeTestsPanelVisual.class, "JmeTestsPanelVisual.createdFolderLabel.text")); // NOI18N + + createdFolderTextField.setEditable(false); + + 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(projectNameLabel) + .addComponent(projectLocationLabel) + .addComponent(createdFolderLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(projectNameTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE) + .addComponent(projectLocationTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE) + .addComponent(createdFolderTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(browseButton) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(projectNameLabel) + .addComponent(projectNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(projectLocationLabel) + .addComponent(projectLocationTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(browseButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(createdFolderLabel) + .addComponent(createdFolderTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(213, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + String command = evt.getActionCommand(); + if ("BROWSE".equals(command)) { + JFileChooser chooser = new JFileChooser(); + FileUtil.preventFileChooserSymlinkTraversal(chooser, null); + chooser.setDialogTitle("Select Project Location"); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + String path = this.projectLocationTextField.getText(); + if (path.length() > 0) { + File f = new File(path); + if (f.exists()) { + chooser.setSelectedFile(f); + } + } + if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(this)) { + File projectDir = chooser.getSelectedFile(); + projectLocationTextField.setText(FileUtil.normalizeFile(projectDir).getAbsolutePath()); + } + panel.fireChangeEvent(); + } + + }//GEN-LAST:event_browseButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton browseButton; + private javax.swing.JLabel createdFolderLabel; + private javax.swing.JTextField createdFolderTextField; + private javax.swing.JLabel projectLocationLabel; + private javax.swing.JTextField projectLocationTextField; + private javax.swing.JLabel projectNameLabel; + private javax.swing.JTextField projectNameTextField; + // End of variables declaration//GEN-END:variables + + @Override + public void addNotify() { + super.addNotify(); + //same problem as in 31086, initial focus on Cancel button + projectNameTextField.requestFocus(); + } + + boolean valid(WizardDescriptor wizardDescriptor) { + + if (projectNameTextField.getText().length() == 0) { + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_ERROR_MESSAGE: + wizardDescriptor.putProperty("WizardPanel_errorMessage", + "Project Name is not a valid folder name."); + return false; // Display name not specified + } + File f = FileUtil.normalizeFile(new File(projectLocationTextField.getText()).getAbsoluteFile()); + if (!f.isDirectory()) { + String message = "Project Folder is not a valid path."; + wizardDescriptor.putProperty("WizardPanel_errorMessage", message); + return false; + } + final File destFolder = FileUtil.normalizeFile(new File(createdFolderTextField.getText()).getAbsoluteFile()); + + File projLoc = destFolder; + while (projLoc != null && !projLoc.exists()) { + projLoc = projLoc.getParentFile(); + } + if (projLoc == null || !projLoc.canWrite()) { + wizardDescriptor.putProperty("WizardPanel_errorMessage", + "Project Folder cannot be created."); + return false; + } + + if (FileUtil.toFileObject(projLoc) == null) { + String message = "Project Folder is not a valid path."; + wizardDescriptor.putProperty("WizardPanel_errorMessage", message); + return false; + } + + File[] kids = destFolder.listFiles(); + if (destFolder.exists() && kids != null && kids.length > 0) { + // Folder exists and is not empty + wizardDescriptor.putProperty("WizardPanel_errorMessage", + "Project Folder already exists and is not empty."); + return false; + } + wizardDescriptor.putProperty("WizardPanel_errorMessage", ""); + return true; + } + + void store(WizardDescriptor d) { + String name = projectNameTextField.getText().trim(); + String folder = createdFolderTextField.getText().trim(); + + d.putProperty("projdir", new File(folder)); + d.putProperty("name", name); + } + + void read(WizardDescriptor settings) { + File projectLocation = (File) settings.getProperty("projdir"); + if (projectLocation == null || projectLocation.getParentFile() == null || !projectLocation.getParentFile().isDirectory()) { + projectLocation = ProjectChooser.getProjectsFolder(); + } else { + projectLocation = projectLocation.getParentFile(); + } + this.projectLocationTextField.setText(projectLocation.getAbsolutePath()); + + String projectName = (String) settings.getProperty("name"); + if (projectName == null) { + projectName = "JmeTests"; + } + this.projectNameTextField.setText(projectName); + this.projectNameTextField.selectAll(); + } + + void validate(WizardDescriptor d) throws WizardValidationException { + // nothing to validate + } + + // Implementation of DocumentListener -------------------------------------- + public void changedUpdate(DocumentEvent e) { + updateTexts(e); + if (this.projectNameTextField.getDocument() == e.getDocument()) { + firePropertyChange(PROP_PROJECT_NAME, null, this.projectNameTextField.getText()); + } + } + + public void insertUpdate(DocumentEvent e) { + updateTexts(e); + if (this.projectNameTextField.getDocument() == e.getDocument()) { + firePropertyChange(PROP_PROJECT_NAME, null, this.projectNameTextField.getText()); + } + } + + public void removeUpdate(DocumentEvent e) { + updateTexts(e); + if (this.projectNameTextField.getDocument() == e.getDocument()) { + firePropertyChange(PROP_PROJECT_NAME, null, this.projectNameTextField.getText()); + } + } + + /** Handles changes in the Project name and project directory, */ + private void updateTexts(DocumentEvent e) { + + Document doc = e.getDocument(); + + if (doc == projectNameTextField.getDocument() || doc == projectLocationTextField.getDocument()) { + // Change in the project name + + String projectName = projectNameTextField.getText(); + String projectFolder = projectLocationTextField.getText(); + + //if (projectFolder.trim().length() == 0 || projectFolder.equals(oldName)) { + createdFolderTextField.setText(projectFolder + File.separatorChar + projectName); + //} + + } + panel.fireChangeEvent(); // Notify that the panel changed + } +} diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsWizardIterator.java b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsWizardIterator.java new file mode 100644 index 000000000..409346d1f --- /dev/null +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsWizardIterator.java @@ -0,0 +1,220 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.templates.tests; + +import java.awt.Component; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.MessageFormat; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import javax.swing.JComponent; +import javax.swing.event.ChangeListener; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.spi.project.ui.support.ProjectChooser; +import org.netbeans.spi.project.ui.templates.support.Templates; +import org.openide.WizardDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +public class JmeTestsWizardIterator implements WizardDescriptor./*Progress*/InstantiatingIterator { + + private int index; + private WizardDescriptor.Panel[] panels; + private WizardDescriptor wiz; + + public JmeTestsWizardIterator() { + } + + public static JmeTestsWizardIterator createIterator() { + return new JmeTestsWizardIterator(); + } + + private WizardDescriptor.Panel[] createPanels() { + return new WizardDescriptor.Panel[]{ + new JmeTestsWizardPanel(),}; + } + + private String[] createSteps() { + return new String[]{ + NbBundle.getMessage(JmeTestsWizardIterator.class, "LBL_CreateProjectStep") + }; + } + + public Set/**/ instantiate(/*ProgressHandle handle*/) throws IOException { + Set resultSet = new LinkedHashSet(); + File dirF = FileUtil.normalizeFile((File) wiz.getProperty("projdir")); + dirF.mkdirs(); + + FileObject template = Templates.getTemplate(wiz); + FileObject dir = FileUtil.toFileObject(dirF); + unZipFile(template.getInputStream(), dir); + + // Always open top dir as a project: + resultSet.add(dir); + // Look for nested projects to open as well: + Enumeration e = dir.getFolders(true); + while (e.hasMoreElements()) { + FileObject subfolder = e.nextElement(); + if (ProjectManager.getDefault().isProject(subfolder)) { + resultSet.add(subfolder); + } + } + + File parent = dirF.getParentFile(); + if (parent != null && parent.exists()) { + ProjectChooser.setProjectsFolder(parent); + } + + return resultSet; + } + + public void initialize(WizardDescriptor wiz) { + this.wiz = wiz; + index = 0; + panels = createPanels(); + // Make sure list of steps is accurate. + String[] steps = createSteps(); + for (int i = 0; i < panels.length; i++) { + Component c = panels[i].getComponent(); + if (steps[i] == null) { + // Default step name to component name of panel. + // Mainly useful for getting the name of the target + // chooser to appear in the list of steps. + steps[i] = c.getName(); + } + if (c instanceof JComponent) { // assume Swing components + JComponent jc = (JComponent) c; + // Step #. + // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: + jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); + // Step name (actually the whole list for reference). + jc.putClientProperty("WizardPanel_contentData", steps); + } + } + } + + public void uninitialize(WizardDescriptor wiz) { + this.wiz.putProperty("projdir", null); + this.wiz.putProperty("name", null); + this.wiz = null; + panels = null; + } + + public String name() { + return MessageFormat.format("{0} of {1}", + new Object[]{new Integer(index + 1), new Integer(panels.length)}); + } + + public boolean hasNext() { + return index < panels.length - 1; + } + + public boolean hasPrevious() { + return index > 0; + } + + public void nextPanel() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + index++; + } + + public void previousPanel() { + if (!hasPrevious()) { + throw new NoSuchElementException(); + } + index--; + } + + public WizardDescriptor.Panel current() { + return panels[index]; + } + + // If nothing unusual changes in the middle of the wizard, simply: + public final void addChangeListener(ChangeListener l) { + } + + public final void removeChangeListener(ChangeListener l) { + } + + private static void unZipFile(InputStream source, FileObject projectRoot) throws IOException { + try { + ZipInputStream str = new ZipInputStream(source); + ZipEntry entry; + while ((entry = str.getNextEntry()) != null) { + if (entry.isDirectory()) { + FileUtil.createFolder(projectRoot, entry.getName()); + } else { + FileObject fo = FileUtil.createData(projectRoot, entry.getName()); + if ("nbproject/project.xml".equals(entry.getName())) { + // Special handling for setting name of Ant-based projects; customize as needed: + filterProjectXML(fo, str, projectRoot.getName()); + } else { + writeFile(str, fo); + } + } + } + } finally { + source.close(); + } + } + + private static void writeFile(ZipInputStream str, FileObject fo) throws IOException { + OutputStream out = fo.getOutputStream(); + try { + FileUtil.copy(str, out); + } finally { + out.close(); + } + } + + private static void filterProjectXML(FileObject fo, ZipInputStream str, String name) throws IOException { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + FileUtil.copy(str, baos); + Document doc = XMLUtil.parse(new InputSource(new ByteArrayInputStream(baos.toByteArray())), false, false, null, null); + NodeList nl = doc.getDocumentElement().getElementsByTagName("name"); + if (nl != null) { + for (int i = 0; i < nl.getLength(); i++) { + Element el = (Element) nl.item(i); + if (el.getParentNode() != null && "data".equals(el.getParentNode().getNodeName())) { + NodeList nl2 = el.getChildNodes(); + if (nl2.getLength() > 0) { + nl2.item(0).setNodeValue(name); + } + break; + } + } + } + OutputStream out = fo.getOutputStream(); + try { + XMLUtil.write(doc, out, "UTF-8"); + } finally { + out.close(); + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + writeFile(str, fo); + } + + } +} diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsWizardPanel.java b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsWizardPanel.java new file mode 100644 index 000000000..cfb287e1a --- /dev/null +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/JmeTestsWizardPanel.java @@ -0,0 +1,88 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.templates.tests; + +import java.awt.Component; +import java.util.HashSet; +import java.util.Set; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.WizardValidationException; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; + +/** + * Panel just asking for basic info. + */ +public class JmeTestsWizardPanel implements WizardDescriptor.Panel, + WizardDescriptor.ValidatingPanel, WizardDescriptor.FinishablePanel { + + private WizardDescriptor wizardDescriptor; + private JmeTestsPanelVisual component; + + public JmeTestsWizardPanel() { + } + + public Component getComponent() { + if (component == null) { + component = new JmeTestsPanelVisual(this); + component.setName(NbBundle.getMessage(JmeTestsWizardPanel.class, "LBL_CreateProjectStep")); + } + return component; + } + + public HelpCtx getHelp() { + return new HelpCtx("sdk.project_creation"); + } + + public boolean isValid() { + getComponent(); + return component.valid(wizardDescriptor); + } + private final Set listeners = new HashSet(1); // or can use ChangeSupport in NB 6.0 + + public final void addChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + + public final void removeChangeListener(ChangeListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + + protected final void fireChangeEvent() { + Set ls; + synchronized (listeners) { + ls = new HashSet(listeners); + } + ChangeEvent ev = new ChangeEvent(this); + for (ChangeListener l : ls) { + l.stateChanged(ev); + } + } + + public void readSettings(Object settings) { + wizardDescriptor = (WizardDescriptor) settings; + component.read(wizardDescriptor); + } + + public void storeSettings(Object settings) { + WizardDescriptor d = (WizardDescriptor) settings; + component.store(d); + } + + public boolean isFinishPanel() { + return true; + } + + public void validate() throws WizardValidationException { + getComponent(); + component.validate(wizardDescriptor); + } +} diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/layer.xml b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/layer.xml new file mode 100644 index 000000000..75852cbe9 --- /dev/null +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/layer.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-texture-editor/build.xml b/sdk/jme3-texture-editor/build.xml new file mode 100644 index 000000000..532a00862 --- /dev/null +++ b/sdk/jme3-texture-editor/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.textureeditor. + + diff --git a/sdk/jme3-texture-editor/manifest.mf b/sdk/jme3-texture-editor/manifest.mf new file mode 100644 index 000000000..eaac5f0a8 --- /dev/null +++ b/sdk/jme3-texture-editor/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.textureeditor/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/textureeditor/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/textureeditor/Bundle.properties + diff --git a/sdk/jme3-texture-editor/nbproject/build-impl.xml b/sdk/jme3-texture-editor/nbproject/build-impl.xml new file mode 100644 index 000000000..da1fee342 --- /dev/null +++ b/sdk/jme3-texture-editor/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-texture-editor/nbproject/genfiles.properties b/sdk/jme3-texture-editor/nbproject/genfiles.properties new file mode 100644 index 000000000..a4bf06c76 --- /dev/null +++ b/sdk/jme3-texture-editor/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=3b9326db +build.xml.script.CRC32=8ff5ca92 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=3b9326db +nbproject/build-impl.xml.script.CRC32=512d1004 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-texture-editor/nbproject/project.properties b/sdk/jme3-texture-editor/nbproject/project.properties new file mode 100644 index 000000000..ee1321688 --- /dev/null +++ b/sdk/jme3-texture-editor/nbproject/project.properties @@ -0,0 +1,7 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=pgi +nbm.needs.restart=true +spec.version.base=0.8.0 diff --git a/sdk/jme3-texture-editor/nbproject/project.xml b/sdk/jme3-texture-editor/nbproject/project.xml new file mode 100644 index 000000000..d04700165 --- /dev/null +++ b/sdk/jme3-texture-editor/nbproject/project.xml @@ -0,0 +1,87 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.textureeditor + + + + org.netbeans.modules.settings + + + + 1 + 1.22.1.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.13.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.windows + + + + 6.30.1 + + + + + com.jme3.gde.textureeditor + com.jme3.gde.textureeditor.filters + com.jme3.gde.textureeditor.tools + tgaimageplugin + + + ext/TGAImagePlugin.jar + release/modules/ext/TGAImagePlugin.jar + + + + diff --git a/sdk/jme3-texture-editor/nbproject/suite.properties b/sdk/jme3-texture-editor/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-texture-editor/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-texture-editor/release/modules/ext/TGAImagePlugin.jar b/sdk/jme3-texture-editor/release/modules/ext/TGAImagePlugin.jar new file mode 100644 index 000000000..e3efe7219 Binary files /dev/null and b/sdk/jme3-texture-editor/release/modules/ext/TGAImagePlugin.jar differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Bundle.properties b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Bundle.properties new file mode 100644 index 000000000..da5888f17 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Bundle.properties @@ -0,0 +1,13 @@ +CTL_ImageEditorAction=ImageEditor +CTL_ImageEditorTopComponent=ImageEditor Window +CTL_OpenTexture=Edit Texture +CTL_SomeAction=sfefe +HINT_ImageEditorTopComponent=This is a ImageEditor window +LBL_JmeTexture_loader_name=JmeTexture Files +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin combines commonly needed image operations for textures. +OpenIDE-Module-Name=Texture Editor +OpenIDE-Module-Short-Description=Combines commonly needed image operations for textures +Services/MIMEResolver/JmeTextureResolver.xml=JmeTexture Files +Templates/Other/JmeTextureTemplate.jpg=Empty JmeTexture file diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ColorController.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ColorController.java new file mode 100644 index 000000000..3bbbde820 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ColorController.java @@ -0,0 +1,98 @@ +package com.jme3.gde.textureeditor; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JColorChooser; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +public class ColorController { + + public static ColorController create() { + return new ColorController(); + } + private final JPanel COMPONENT; + private Color background = Color.WHITE; + private Color foreground = Color.BLACK; + + protected ColorController() { + final JPanel display = new JPanel() { + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + int w3 = getWidth() / 3; + int h3 = getHeight() / 3; + g.setColor(ColorController.this.getBackground()); + g.fillRect(w3, h3, 2*w3, 2*h3); + g.setColor(Color.BLACK); + g.drawRect(w3, h3, 2*w3, 2*h3); + g.setColor(ColorController.this.getForeground()); + g.fillRect(0, 0, 2*w3, 2*h3); + g.setColor(Color.BLACK); + g.drawRect(0, 0, 2*w3, 2*h3); + } + }; + display.addMouseListener(new MouseAdapter() { + + @Override + public void mouseReleased(MouseEvent e) { + int w3 = display.getWidth() / 3; + int h3 = display.getHeight() / 3; + if(new Rectangle(0, 0, 2*w3, 2*h3).contains(e.getPoint())) { + chooseColor(foreground); + } else if(new Rectangle(w3, h3, 2*w3, 2*h3).contains(e.getPoint())) { + chooseColor(background); + } + } + }); + Dimension dim = new Dimension(40, 40); + display.setMinimumSize(dim); + display.setPreferredSize(dim); + display.setMaximumSize(dim); + COMPONENT = display; + } + + public Color getBackground() { + return background; + } + + public Color getForeground() { + return foreground; + } + + public void setBackground(Color color) { + background = color; + COMPONENT.repaint(); + } + + public void setForeground(Color color) { + foreground = color; + COMPONENT.repaint(); + } + + public JComponent getComponent() { + return COMPONENT; + } + + private void chooseColor(Color source) { + Color initial = source; + String title = source == foreground ? "Foreground Color" : "Background Color"; + Frame parent = JOptionPane.getFrameForComponent(COMPONENT); + Color choice = JColorChooser.showDialog(parent, title, initial); + if(choice != null) { + if(source == foreground) { + setForeground(choice); + } else { + setBackground(choice); + } + } + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Computer_File_067.gif b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Computer_File_067.gif new file mode 100644 index 000000000..669b21456 Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Computer_File_067.gif differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Computer_File_068.gif b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Computer_File_068.gif new file mode 100644 index 000000000..638f48ff0 Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/Computer_File_068.gif differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/EditorTool.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/EditorTool.java new file mode 100644 index 000000000..02f5df08b --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/EditorTool.java @@ -0,0 +1,13 @@ +package com.jme3.gde.textureeditor; + +import java.awt.Graphics2D; + +public interface EditorTool { + + public void install(EditorToolTarget t); + + public void uninstall(EditorToolTarget t); + + public void drawTrack(Graphics2D g, int width, int height, float scaleX, float scaleY); + +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/EditorToolTarget.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/EditorToolTarget.java new file mode 100644 index 000000000..9303ed7d3 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/EditorToolTarget.java @@ -0,0 +1,20 @@ +package com.jme3.gde.textureeditor; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import javax.swing.JComponent; + +public interface EditorToolTarget { + + JComponent getImageCanvas(); + + float getScaleX(); + float getScaleY(); + BufferedImage getCurrentImage(); + + public void setForeground(Color picked); + + public void setBackground(Color picked); + + void spawnEditor(BufferedImage editedImage); +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ExtensionFileFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ExtensionFileFilter.java new file mode 100644 index 000000000..d89a60fbf --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ExtensionFileFilter.java @@ -0,0 +1,32 @@ +package com.jme3.gde.textureeditor; + +import java.io.File; +import javax.swing.filechooser.FileFilter; + +public class ExtensionFileFilter extends FileFilter { + + public static ExtensionFileFilter create(String ext, String desc) { + return new ExtensionFileFilter(ext, desc); + } + private final String EXTENSION; + private final String DESCRIPTION; + + protected ExtensionFileFilter(String ext, String desc) { + EXTENSION = ext; + DESCRIPTION = desc; + } + + @Override + public boolean accept(File f) { + return f.isDirectory() || f.getName().toLowerCase().endsWith(EXTENSION); + } + + public String getExtension() { + return EXTENSION; + } + + @Override + public String getDescription() { + return DESCRIPTION; + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/FileFilters.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/FileFilters.java new file mode 100644 index 000000000..cf1b5b65d --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/FileFilters.java @@ -0,0 +1,9 @@ +package com.jme3.gde.textureeditor; + +public interface FileFilters { + + ExtensionFileFilter PNG = new ExtensionFileFilter(".png", "PNG Image"); + ExtensionFileFilter JPG = new ExtensionFileFilter(".jpg", "JPG Image"); + ExtensionFileFilter BMP = new ExtensionFileFilter(".bmp", "BMP Image"); + ExtensionFileFilter TGA = new ExtensionFileFilter(".tga", "TGA Image"); +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/IOModule.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/IOModule.java new file mode 100644 index 000000000..e50c4e64d --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/IOModule.java @@ -0,0 +1,49 @@ +package com.jme3.gde.textureeditor; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import javax.imageio.ImageIO; +import javax.imageio.stream.FileImageInputStream; +import javax.imageio.stream.FileImageOutputStream; +import javax.imageio.stream.ImageInputStream; +import org.openide.filesystems.FileObject; +import tgaimageplugin.TGAImageReader; +import tgaimageplugin.TGAImageReaderSpi; +import tgaimageplugin.TGAImageWriter; +import tgaimageplugin.TGAImageWriterSpi; + +public class IOModule { + + public static IOModule create() { + return new IOModule(); + } + + private IOModule() { + } + + public void store(BufferedImage editedImage, String type, File file) throws IOException { + if (type.equals("tga")) { + TGAImageWriterSpi spi = new TGAImageWriterSpi(); + TGAImageWriter wri = new TGAImageWriter(spi); + wri.setOutput(new FileImageOutputStream(file)); + wri.write(editedImage); + } else { + ImageIO.write(editedImage, type, file); + } + } + + public BufferedImage load(FileObject file) throws IOException, URISyntaxException { + if(file.getExt().equalsIgnoreCase("tga")) { + ImageInputStream in = new FileImageInputStream(new File(file.getURL().toURI())); + TGAImageReaderSpi spi = new TGAImageReaderSpi(); + TGAImageReader rea = new TGAImageReader(spi); + rea.setInput(in); + return rea.read(0); + } else { + BufferedImage image = ImageIO.read(file.getInputStream()); + return image; + } + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorComponent.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorComponent.java new file mode 100644 index 000000000..1d29d7a9e --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorComponent.java @@ -0,0 +1,451 @@ +package com.jme3.gde.textureeditor; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.Arrays; +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSpinner; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.SpinnerNumberModel; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; +import org.openide.windows.TopComponent; +import com.jme3.gde.textureeditor.filters.BrightFilter; +import com.jme3.gde.textureeditor.filters.BumpMapFilter; +import com.jme3.gde.textureeditor.filters.GrayscaleFilter; +import com.jme3.gde.textureeditor.filters.MirrorFilter; +import com.jme3.gde.textureeditor.filters.ResizeFilter; +import com.jme3.gde.textureeditor.filters.RotateLeftFilter; +import com.jme3.gde.textureeditor.tools.ColorPicker; +import com.jme3.gde.textureeditor.tools.CropTool; +import java.io.IOException; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Confirmation; +import org.openide.NotifyDescriptor.Message; +import org.openide.cookies.SaveCookie; +import org.openide.filesystems.FileChooserBuilder; +import org.openide.filesystems.FileObject; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; + +public class ImageEditorComponent implements EditorToolTarget { + + private static ImageIcon Icon(String name) { + return new ImageIcon(ImageEditorComponent.class.getResource("/com/jme3/gde/textureeditor/resources/" + name)); + } + + public static ImageEditorComponent create() { + return new ImageEditorComponent(); + } + private final JPanel COMPONENT = new JPanel(new BorderLayout()); + private FileObject editedFile; + private BufferedImage editedImage; + private float scaleX = 1; + private float scaleY = 1; + private JPanel imageScreen = new JPanel() { + + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + doPaint((Graphics2D) graphics); + } + }; + private final ColorController COLOR_CONTROLLER = ColorController.create(); + private final JScrollPane scroller; + private final JPanel imageContainer; + private JPanel topContainer = new JPanel(new BorderLayout()); + private TopComponent owner; + private EditorTool currentTool; + private SaveNode saveNode = new SaveNode(); + private boolean newFile = false; + + private void doPaint(Graphics2D g) { + if (editedImage != null) { + g.drawImage(editedImage, 0, 0, imageScreen.getWidth(), imageScreen.getHeight(), null); + } + if (currentTool != null) { + currentTool.drawTrack(g, imageScreen.getWidth(), imageScreen.getHeight(), scaleX, scaleY); + } + } + + public ImageEditorComponent() { + JToolBar bottomBar = new JToolBar(); + bottomBar.setFloatable(false); + bottomBar.add(COLOR_CONTROLLER.getComponent()); + createToolBar(); + createMenuBar(); + imageContainer = new JPanel(new GridBagLayout()); + GridBagConstraints lim = new GridBagConstraints(); + lim.gridx = lim.gridy = 0; + imageContainer.add(imageScreen, lim); + scroller = new JScrollPane(imageContainer); + COMPONENT.add(scroller); + COMPONENT.add(topContainer, BorderLayout.NORTH); + COMPONENT.add(bottomBar, BorderLayout.SOUTH); + } + + public void setCurrentTool(EditorTool t) { + if (currentTool != null) { + currentTool.uninstall(this); + } + currentTool = t; + if (currentTool != null) { + currentTool.install(this); + } + } + + public void setScaleFactor(float value) { + value = Math.max(value, 0.01f); + scaleX = value; + scaleY = value; + resizeDisplay(); + } + + public float getScaleFactor() { + return scaleX; + } + + public JComponent getComponent() { + return COMPONENT; + } + + private void enableSaving() { + saveNode.fire(true); + } + + private void disableSaving() { + saveNode.fire(false); + } + + public void setEditedImage(TopComponent component, BufferedImage image, FileObject file) { + this.owner = component; + component.setActivatedNodes(new Node[]{saveNode}); + if (file == null) { + newFile = true; + enableSaving(); + } else { + newFile = false; + disableSaving(); + } + editedFile = file; + editedImage = image; + resizeDisplay(); + } + + private void resizeDisplay() { + Dimension s = new Dimension( + (int) (editedImage.getWidth() * scaleX), + (int) (editedImage.getHeight() * scaleY)); + imageScreen.setPreferredSize(s); + imageScreen.setMinimumSize(s); + imageScreen.setMaximumSize(s); + COMPONENT.revalidate(); + COMPONENT.repaint(); + scroller.setViewportView(imageContainer); + } + + private void createToolBar() { + final JButton zoomIn = new JButton(Icon("zoom-in-2.png")); + final JButton zoomOut = new JButton(Icon("zoom-out-2.png")); + final JButton resize = new JButton(Icon("transform-scale-2.png")); + final JButton rotateLeft = new JButton(Icon("object-rotate-left-2.png")); + final JButton mirrorX = new JButton(Icon("mirror_x.png")); + final JButton mirrorY = new JButton(Icon("mirror_y.png")); + + JToolBar toolbar1 = new JToolBar(); + toolbar1.add(zoomIn); + toolbar1.add(zoomOut); + toolbar1.addSeparator(); + toolbar1.add(resize); + toolbar1.add(rotateLeft); + toolbar1.add(mirrorX); + toolbar1.add(mirrorY); + toolbar1.setFloatable(false); + topContainer.add(toolbar1, BorderLayout.CENTER); + + final ButtonGroup toolsGroup = new ButtonGroup(); + final JToggleButton colorPicker = new JToggleButton(Icon("color-picker.png")); + final JToggleButton imageCrop = new JToggleButton(Icon("transform-crop.png")); + toolsGroup.add(colorPicker); + toolsGroup.add(imageCrop); + JToolBar toolbar2 = new JToolBar(); + toolbar2.setOrientation(JToolBar.VERTICAL); + toolbar2.setFloatable(false); + toolbar2.add(colorPicker); + toolbar2.add(imageCrop); + COMPONENT.add(toolbar2, BorderLayout.WEST); + + ActionListener al = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + if (source == zoomIn) { + setScaleFactor(getScaleFactor() + 0.1f); + } else if (source == zoomOut) { + setScaleFactor(getScaleFactor() - 0.1f); + } else if (source == resize) { + querySizeAndResize(); + } else if (source == rotateLeft) { + editedImage = RotateLeftFilter.create().filter(editedImage); + resizeDisplay(); + enableSaving(); + } else if (source == mirrorX) { + editedImage = MirrorFilter.create().filter(editedImage, MirrorFilter.X); + resizeDisplay(); + enableSaving(); + } else if (source == mirrorY) { + editedImage = MirrorFilter.create().filter(editedImage, MirrorFilter.Y); + resizeDisplay(); + enableSaving(); + } else if (source == colorPicker) { + setCurrentTool(ColorPicker.create()); + } else if (source == imageCrop) { + setCurrentTool(CropTool.create()); + } + } + }; + for (AbstractButton b : Arrays.asList(zoomIn, zoomOut, resize, /*save, saveAs,*/ + rotateLeft, mirrorX, mirrorY, colorPicker, imageCrop)) { + b.addActionListener(al); + } + } + + private void confirmAndSave() { + Confirmation msg = new NotifyDescriptor.Confirmation("Confirm overwriting?", + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.QUESTION_MESSAGE); + + Object result = DialogDisplayer.getDefault().notify(msg); + + if (NotifyDescriptor.YES_OPTION.equals(result)) { + String name = editedFile.getExt(); + try { + IOModule.create().store(editedImage, name, new File(editedFile.getURL().toURI())); + disableSaving(); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + } + + private void requestFileAndSave() { + FileChooserBuilder builder = new FileChooserBuilder(ImageEditorComponent.class); + builder.addFileFilter(FileFilters.JPG); + builder.addFileFilter(FileFilters.TGA); + builder.addFileFilter(FileFilters.PNG); + + JFileChooser fc= builder.createFileChooser(); + fc.setFileSelectionMode(fc.SAVE_DIALOG); + fc.setAcceptAllFileFilterUsed(false); + + int a = fc.showOpenDialog(COMPONENT); + if (a == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + String name = file.getName().toLowerCase(); + String type; + if (name.endsWith(".png")) { + type = "png"; + } else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) { + type = "jpg"; + } else if (name.endsWith(".bmp")) { + type = "bmp"; + } else if (name.endsWith(".tga")) { + type ="tga"; + } else { + ExtensionFileFilter filter = (ExtensionFileFilter) fc.getFileFilter(); + file = new File(file.getParentFile(), file.getName() + filter.getExtension()); + type = filter.getExtension().substring(1); + } + if (file.exists()) { + a = JOptionPane.showConfirmDialog(COMPONENT, "Overwrite existing file?", "Confirm", JOptionPane.YES_NO_OPTION); + if (a != JOptionPane.YES_OPTION) { + return; + } + } + try { + IOModule.create().store(editedImage, type, file); + + Message msg = new NotifyDescriptor.Message("Image saved."); + DialogDisplayer.getDefault().notify(msg); + + editedFile = FileUtil.toFileObject(file); + newFile = false; + owner.setName("PixelHead - " + editedFile.getName()); + disableSaving(); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + } + + private void querySizeAndResize() { + final SpinnerNumberModel w = new SpinnerNumberModel(editedImage.getWidth(), 1, 10000, 1); + final SpinnerNumberModel h = new SpinnerNumberModel(editedImage.getHeight(), 1, 10000, 1); + final JSpinner ws = new JSpinner(w); + final JSpinner hs = new JSpinner(h); + final JPanel lab = new JPanel(new GridLayout(2, 1, 8, 8)); + final JPanel spi = new JPanel(new GridLayout(2, 1, 8, 8)); + lab.add(new JLabel("New Width")); + lab.add(new JLabel("New Height")); + spi.add(ws); + spi.add(hs); + final JPanel box = new JPanel(new BorderLayout(8, 8)); + box.add(lab, BorderLayout.LINE_START); + box.add(spi, BorderLayout.CENTER); + final Object[] options = {"Ok", "Cancel"}; + + int a = JOptionPane.showOptionDialog( + COMPONENT, + box, + "Resize Image", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE, + null, + options, + options[1]); + if (a == 0) { + int newWidth = w.getNumber().intValue(); + int newHeight = h.getNumber().intValue(); + if (newWidth != editedImage.getWidth() || newHeight != editedImage.getHeight()) { + spawnEditor(ResizeFilter.create().filter(editedImage, newWidth, newHeight)); + } + } + } + + private void createMenuBar() { + JMenuBar menuBar = new JMenuBar(); + JMenu filters = new JMenu("Filters"); + menuBar.add(filters); + topContainer.add(menuBar, BorderLayout.NORTH); + + final JMenu bumpMenu = new JMenu("Bump Map"); + final JMenuItem bumpSoft = bumpMenu.add("Soft"); + final JMenuItem bumpMedium = bumpMenu.add("Medium"); + final JMenuItem bumpStrong = bumpMenu.add("Strong"); + filters.add(bumpMenu); + + final JMenuItem gray = filters.add("Grayscale"); + final JMenuItem bright = filters.add("Brightness"); + + ActionListener al = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + if (source == bumpSoft) { + spawnEditor(BumpMapFilter.create().filter(editedImage, 0.01f)); + } else if (source == bumpMedium) { + spawnEditor(BumpMapFilter.create().filter(editedImage, 0.025f)); + } else if (source == bumpStrong) { + spawnEditor(BumpMapFilter.create().filter(editedImage, 0.5f)); + } else if (source == gray) { + spawnEditor(GrayscaleFilter.create().filter(editedImage)); + } else if (source == bright) { + spawnEditor(BrightFilter.create().filter(editedImage, ImageEditorComponent.this)); + } + } + }; + + for (AbstractButton b : Arrays.asList(bumpSoft, bumpMedium, bumpStrong, gray, bright)) { + b.addActionListener(al); + } + } + + public void spawnEditor(BufferedImage image) { + if (image != null) { + ImageEditorTopComponent component = new ImageEditorTopComponent(); + component.setEditedImage(image); + component.open(); + component.requestActive(); + } + } + + public JComponent getImageCanvas() { + return this.imageScreen; + } + + public float getScaleX() { + return scaleX; + } + + public float getScaleY() { + return scaleY; + } + + public BufferedImage getCurrentImage() { + return editedImage; + } + + public void setForeground(Color picked) { + COLOR_CONTROLLER.setForeground(picked); + } + + public void setBackground(Color picked) { + COLOR_CONTROLLER.setBackground(picked); + } + + public BufferedImage createIcon(int w, int h) { + BufferedImage icon = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + icon.getGraphics().drawImage(editedImage, 0, 0, w, h, null); + return icon; + } + + public class SaveNode extends AbstractNode { + + SaveCookie impl; + + public SaveNode() { + super(Children.LEAF); + impl = new SaveCookieImpl(); + } + + public SaveNode(SaveCookie impl) { + super(Children.LEAF); + this.impl = impl; + } + + public void fire(boolean modified) { + if (modified) { + getCookieSet().assign(SaveCookie.class, impl); + } else { + getCookieSet().assign(SaveCookie.class); + } + } + + private class SaveCookieImpl implements SaveCookie { + + public void save() throws IOException { + + if (newFile) { + requestFileAndSave(); + } else { + confirmAndSave(); + } + } + } + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponent.form b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponent.form new file mode 100644 index 000000000..225962ab2 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponent.form @@ -0,0 +1,17 @@ + + +
+ + + + + + + + + + + + + + diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponent.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponent.java new file mode 100644 index 000000000..255e366a2 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponent.java @@ -0,0 +1,138 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.textureeditor; + +import java.awt.image.BufferedImage; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.logging.Logger; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.filesystems.FileObject; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.textureeditor//ImageEditor//EN", +autostore = false) +public final class ImageEditorTopComponent extends TopComponent { + + private static ImageEditorTopComponent instance; + /** path to the icon used by the component and its open action */ + static final String ICON_PATH = "com/jme3/gde/textureeditor/Computer_File_067.gif"; + private static final String PREFERRED_ID = "ImageEditorTopComponent"; + private final ImageEditorComponent EDITOR = ImageEditorComponent.create(); + + public ImageEditorTopComponent() { + initComponents(); + setName(NbBundle.getMessage(ImageEditorTopComponent.class, "CTL_ImageEditorTopComponent")); + setToolTipText(NbBundle.getMessage(ImageEditorTopComponent.class, "HINT_ImageEditorTopComponent")); + setIcon(ImageUtilities.loadImage(ICON_PATH, true)); + add(EDITOR.getComponent()); + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS)); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized ImageEditorTopComponent getDefault() { + if (instance == null) { + instance = new ImageEditorTopComponent(); + } + return instance; + } + + /** + * Obtain the ImageEditorTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized ImageEditorTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(ImageEditorTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof ImageEditorTopComponent) { + return (ImageEditorTopComponent) win; + } + Logger.getLogger(ImageEditorTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER; + } + + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + // TODO add custom code on component closing + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + public void setEditedImage(FileObject file) throws FileNotFoundException, IOException, URISyntaxException { + if (file != null) { + setName("PixelHead - " + file.getName()); + } else { + setName("PixelHead - No name"); + } + BufferedImage image = IOModule.create().load(file); + EDITOR.setEditedImage(this, image, file); + } + + void setEditedImage(BufferedImage image) { + setName("PixelHead - NoName"); + EDITOR.setEditedImage(this, image, null); + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponentSettings.xml b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponentSettings.xml new file mode 100644 index 000000000..3ec21d475 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponentWstcref.xml b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponentWstcref.xml new file mode 100644 index 000000000..74a4aa607 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/ImageEditorTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureDataObject.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureDataObject.java new file mode 100644 index 000000000..4dc118c69 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureDataObject.java @@ -0,0 +1,34 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.textureeditor; + +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataNode; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiDataObject; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.nodes.Children; +import org.openide.util.Lookup; + +public class JmeTextureDataObject extends MultiDataObject { + + public JmeTextureDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + + } + + @Override + protected Node createNodeDelegate() { + return new DataNode(this, Children.LEAF, getLookup()); + } + + @Override + public Lookup getLookup() { + return getCookieSet().getLookup(); + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureResolver.xml b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureResolver.xml new file mode 100644 index 000000000..a8824c809 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureResolver.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureTemplate.jpg b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureTemplate.jpg new file mode 100644 index 000000000..0d6f364b7 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/JmeTextureTemplate.jpg @@ -0,0 +1 @@ +sample content \ No newline at end of file diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/OpenTexture.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/OpenTexture.java new file mode 100644 index 000000000..0858882b7 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/OpenTexture.java @@ -0,0 +1,39 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.textureeditor; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URISyntaxException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObject; +import org.openide.util.Exceptions; + +public final class OpenTexture implements ActionListener { + + private final DataObject context; + + public OpenTexture(DataObject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + FileObject file = context.getPrimaryFile(); + ImageEditorTopComponent display = new ImageEditorTopComponent(); + try { + display.setEditedImage(file); + display.open(); + display.requestActive(); + } catch (URISyntaxException ex) { + Exceptions.printStackTrace(ex); + } catch (FileNotFoundException ex) { + Exceptions.printStackTrace(ex); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/SomeAction.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/SomeAction.java new file mode 100644 index 000000000..a4220fbcb --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/SomeAction.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.textureeditor; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import org.openide.loaders.DataObject; + +public final class SomeAction implements ActionListener { + + private final DataObject context; + + public SomeAction(DataObject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + // TODO use context + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BrightFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BrightFilter.java new file mode 100644 index 000000000..27780a6d8 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BrightFilter.java @@ -0,0 +1,85 @@ +package com.jme3.gde.textureeditor.filters; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.image.BufferedImage; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import com.jme3.gde.textureeditor.ImageEditorComponent; + +public class BrightFilter implements BufferedImageFilter { + + public static BrightFilter create() { + return new BrightFilter(); + } + + private final int[] lookup; + + protected BrightFilter() { + int[] arr = new int[256]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) (Math.sqrt(i / 255.0) * 255.0); + } + lookup = arr; + } + + public BufferedImage filter(BufferedImage source, Object... args) { + ImageEditorComponent parent = (ImageEditorComponent) args[0]; + final BufferedImage sourceIcon = parent.createIcon(256, 256); + final JLabel label = new JLabel(new ImageIcon(sourceIcon)); + final JSlider slider = new JSlider(0, 200, 100); + slider.addChangeListener(new ChangeListener() { + + public void stateChanged(ChangeEvent e) { + if(!slider.getValueIsAdjusting()) { + label.setIcon(new ImageIcon(doFilter(sourceIcon, slider.getValue() / 100f))); + } + } + }); + slider.setOrientation(JSlider.HORIZONTAL); + JPanel sliderContainer = new JPanel(new GridLayout(1, 1)); + sliderContainer.setBorder(BorderFactory.createTitledBorder("Brightness value")); + sliderContainer.add(slider); + JPanel labelContainer = new JPanel(new GridBagLayout()); + GridBagConstraints lim = new GridBagConstraints(); lim.gridx = lim.gridy = 0; + labelContainer.add(label, lim); + labelContainer.setBorder(BorderFactory.createTitledBorder("Preview")); + JPanel container = new JPanel(new BorderLayout()); + container.add(labelContainer, BorderLayout.CENTER); + container.add(sliderContainer, BorderLayout.SOUTH); + + int choice = JOptionPane.showConfirmDialog(parent.getComponent(), container, "Brightness Filter", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null); + if(choice == JOptionPane.OK_OPTION) { + return doFilter(source, slider.getValue() / 100f); + } else { + return null; + } + } + + private BufferedImage doFilter(BufferedImage source, float factor) { + BufferedImage dest = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB); + for (int i = 0; i < source.getWidth(); i++) { + for (int j = 0; j < source.getHeight(); j++) { + int rgb = source.getRGB(i, j); + int a = (rgb >> 24) & 0xff; + int r = (rgb >> 16) & 0xff; + int g = (rgb >> 8) & 0xff; + int b = rgb & 0xff; + r = Math.min(255, Math.round(lookup[r] * factor)); + g = Math.min(255, Math.round(lookup[g] * factor)); + b = Math.min(255, Math.round(lookup[b] * factor)); + rgb = (a << 24) + (r << 16) + (g << 8) + b; + dest.setRGB(i, j, rgb); + } + } + return dest; + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BufferedImageFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BufferedImageFilter.java new file mode 100644 index 000000000..ce106d1cd --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BufferedImageFilter.java @@ -0,0 +1,8 @@ +package com.jme3.gde.textureeditor.filters; + +import java.awt.image.BufferedImage; + +public interface BufferedImageFilter { + + BufferedImage filter(BufferedImage source, Object...args); +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BumpMapFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BumpMapFilter.java new file mode 100644 index 000000000..f9a1e7768 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/BumpMapFilter.java @@ -0,0 +1,85 @@ +package com.jme3.gde.textureeditor.filters; + +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; +import com.jme3.gde.textureeditor.ImageEditorComponent; + +public class BumpMapFilter implements BufferedImageFilter { + private static class Vec3f { + float x, y, z; + + void divideLocal(float d) { + x /= d; + y /= d; + z /= d; + } + }; + + public static BumpMapFilter create() { + return new BumpMapFilter(); + } + + protected BumpMapFilter() { + } + + public BufferedImage filter(BufferedImage sourceImage, Object... args) { + float a = (Float) args[0]; + BufferedImage heightMap = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB); + BufferedImage bumpMap = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB); + ColorConvertOp gscale = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null); + gscale.filter(sourceImage, heightMap); + for(int x = 0; x < bumpMap.getWidth(); x++) { + for(int y = 0; y < bumpMap.getHeight(); y++) { + bumpMap.setRGB(x, y, generateBumpPixel(heightMap, x, y, a)); + } + } + return bumpMap; + } + + public int generateBumpPixel(BufferedImage image, int x, int y, float a) { + Vec3f S = new Vec3f(); + Vec3f T = new Vec3f(); + Vec3f N = new Vec3f(); + Vec3f ST = new Vec3f(); + S.x = 1; + S.y = 0; + S.z = a * getHeight(image, x + 1, y) - a * getHeight(image, x - 1, y); + T.x = 0; + T.y = 1; + T.z = a * getHeight(image, x, y + 1) - a * getHeight(image, x, y - 1); + + float den = (float) Math.sqrt(S.z * S.z + T.z * T.z + 1); + N.x = -S.z; + N.y = -T.z; + N.z = 1; + N.divideLocal(den); + return vectorToColor(N.x, N.y, N.z); + } + + private float getHeight(BufferedImage image, int x, int y) { + if(x < 0) { + x = 0; + } else if(x >= image.getWidth()) { + x = image.getWidth() - 1; + } + if(y < 0) { + y = 0; + } else if(y >= image.getHeight()) { + y = image.getHeight() - 1; + } + return image.getRGB(x, y) & 0xff; + } + + public int vectorToColor(float x, float y, float z) { + int r = Math.round(255 * ((x + 1f) / 2f)); + int g = Math.round(255 * ((y + 1f) / 2f)); + int b = Math.round(255 * ((z + 1f) / 2f)); + return (255 << 24) + (r << 16) + (g << 8) + b; + } + + @Override + public String toString() { + return "Bump Map"; + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/GrayscaleFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/GrayscaleFilter.java new file mode 100644 index 000000000..a557c4171 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/GrayscaleFilter.java @@ -0,0 +1,22 @@ +package com.jme3.gde.textureeditor.filters; + +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; + +public class GrayscaleFilter implements BufferedImageFilter { + + public static GrayscaleFilter create() { + return new GrayscaleFilter(); + } + + protected GrayscaleFilter() { + } + + public BufferedImage filter(BufferedImage sourceImage, Object... args) { + BufferedImage filtered = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB); + ColorConvertOp gscale = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null); + gscale.filter(sourceImage, filtered); + return filtered; + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/MirrorFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/MirrorFilter.java new file mode 100644 index 000000000..a7fef7388 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/MirrorFilter.java @@ -0,0 +1,30 @@ +package com.jme3.gde.textureeditor.filters; + +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; + +public class MirrorFilter implements BufferedImageFilter { + public static final Integer X = 0; + public static final Integer Y = 1; + + public static MirrorFilter create() { + return new MirrorFilter(); + } + + protected MirrorFilter() {} + + public BufferedImage filter(BufferedImage source, Object... args) { + if(args[0] == Y) { + AffineTransform op = AffineTransform.getScaleInstance(1, -1); + op.translate(0, -source.getHeight(null)); + return new AffineTransformOp(op, null).filter(source, null); + } else if(args[0] == X) { + AffineTransform op = AffineTransform.getScaleInstance(-1, 1); + op.translate(-source.getWidth(null), 0); + return new AffineTransformOp(op, null).filter(source, null); + } else { + throw new IllegalArgumentException("MirrorFilter requires MirrorFilter.X or MirrorFilter.Y as argument"); + } + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/ResizeFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/ResizeFilter.java new file mode 100644 index 000000000..932e3bea4 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/ResizeFilter.java @@ -0,0 +1,27 @@ +package com.jme3.gde.textureeditor.filters; + +import java.awt.Image; +import java.awt.image.BufferedImage; + +public class ResizeFilter implements BufferedImageFilter { + + public static ResizeFilter create() { + return new ResizeFilter(); + } + + protected ResizeFilter() {} + + public BufferedImage filter(BufferedImage source, Object... args) { + int newWidth = (Integer) args[0]; + int newHeight = (Integer) args[1]; + int type = source.getType(); + if (type == BufferedImage.TYPE_CUSTOM) { + type = BufferedImage.TYPE_INT_ARGB; + } + BufferedImage scaled = new BufferedImage(newWidth, newHeight, type); + scaled.getGraphics().drawImage( + source.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), + 0, 0, null); + return scaled; + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/RotateLeftFilter.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/RotateLeftFilter.java new file mode 100644 index 000000000..67c954619 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/filters/RotateLeftFilter.java @@ -0,0 +1,35 @@ +package com.jme3.gde.textureeditor.filters; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; + +public class RotateLeftFilter implements BufferedImageFilter { + + public static RotateLeftFilter create() { + return new RotateLeftFilter(); + } + + protected RotateLeftFilter() {} + + public BufferedImage filter(BufferedImage source, Object... args) { + int type = source.getType(); + if(type == BufferedImage.TYPE_CUSTOM) { + type = BufferedImage.TYPE_INT_ARGB; + } +// BufferedImage dest = new BufferedImage(source.getHeight(), source.getWidth(), type); + AffineTransform rot = AffineTransform.getRotateInstance( + Math.PI / 2, source.getWidth() / 2, + source.getHeight() / 2); + Point2D p0 = new Point2D.Double(); + Point2D p1 = rot.transform(p0, null); + double dy = p1.getY(); + p0.setLocation(0, source.getHeight()); + rot.transform(p0, p1); + double dx = p1.getX(); + AffineTransform trans = AffineTransform.getTranslateInstance(-dx, -dy); + rot.preConcatenate(trans); + return new AffineTransformOp(rot, null).filter(source, null); + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/layer.xml b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/layer.xml new file mode 100644 index 000000000..e10396a2e --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/layer.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/color-picker.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/color-picker.png new file mode 100644 index 000000000..bd6ad6316 Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/color-picker.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/document-save-4.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/document-save-4.png new file mode 100644 index 000000000..77f31128a Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/document-save-4.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/document-save-as-4.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/document-save-as-4.png new file mode 100644 index 000000000..88024d0ea Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/document-save-as-4.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/mirror_x.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/mirror_x.png new file mode 100644 index 000000000..26542cd3f Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/mirror_x.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/mirror_y.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/mirror_y.png new file mode 100644 index 000000000..50148a417 Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/mirror_y.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/object-rotate-left-2.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/object-rotate-left-2.png new file mode 100644 index 000000000..9906b29cb Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/object-rotate-left-2.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-crop-and-resize.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-crop-and-resize.png new file mode 100644 index 000000000..05989ee86 Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-crop-and-resize.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-crop.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-crop.png new file mode 100644 index 000000000..df7940ae8 Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-crop.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-scale-2.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-scale-2.png new file mode 100644 index 000000000..f05c5594a Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/transform-scale-2.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/zoom-in-2.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/zoom-in-2.png new file mode 100644 index 000000000..883abf708 Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/zoom-in-2.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/zoom-out-2.png b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/zoom-out-2.png new file mode 100644 index 000000000..2d41ed75d Binary files /dev/null and b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/resources/zoom-out-2.png differ diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/tools/ColorPicker.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/tools/ColorPicker.java new file mode 100644 index 000000000..b81b0d8f6 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/tools/ColorPicker.java @@ -0,0 +1,45 @@ +package com.jme3.gde.textureeditor.tools; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.SwingUtilities; +import com.jme3.gde.textureeditor.EditorTool; +import com.jme3.gde.textureeditor.EditorToolTarget; + +public class ColorPicker extends MouseAdapter implements EditorTool { + + public static ColorPicker create() { + return new ColorPicker(); + } + private EditorToolTarget target; + + protected ColorPicker() {} + + public void install(EditorToolTarget t) { + target = t; + target.getImageCanvas().addMouseListener(this); + } + + public void uninstall(EditorToolTarget t) { + target.getImageCanvas().removeMouseListener(this); + } + + public void drawTrack(Graphics2D g, int width, int height, float scaleX, float scaleY) { + } + + @Override + public void mousePressed(MouseEvent e) { + Point p = e.getPoint(); + p.x /= target.getScaleX(); + p.y /= target.getScaleY(); + Color picked = new Color(target.getCurrentImage().getRGB(p.x, p.y)); + if(SwingUtilities.isLeftMouseButton(e)) { + target.setForeground(picked); + } else if(SwingUtilities.isRightMouseButton(e)) { + target.setBackground(picked); + } + } +} diff --git a/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/tools/CropTool.java b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/tools/CropTool.java new file mode 100644 index 000000000..e79928c94 --- /dev/null +++ b/sdk/jme3-texture-editor/src/com/jme3/gde/textureeditor/tools/CropTool.java @@ -0,0 +1,82 @@ +package com.jme3.gde.textureeditor.tools; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Stroke; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import javax.swing.event.MouseInputAdapter; +import com.jme3.gde.textureeditor.EditorTool; +import com.jme3.gde.textureeditor.EditorToolTarget; + +public class CropTool extends MouseInputAdapter implements EditorTool { + + public static CropTool create() { + return new CropTool(); + } + private EditorToolTarget target; + private Stroke stroke = new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 0, new float[] { 4, 4 }, 0); + private Rectangle track; + private Point last; + + protected CropTool() {} + + public void install(EditorToolTarget t) { + target = t; + target.getImageCanvas().addMouseListener(this); + target.getImageCanvas().addMouseMotionListener(this); + } + + public void uninstall(EditorToolTarget t) { + target.getImageCanvas().removeMouseListener(this); + target.getImageCanvas().removeMouseMotionListener(this); + } + + @Override + public void mousePressed(MouseEvent e) { + last = e.getPoint(); + track = new Rectangle(last.x, last.y, 1, 1); + target.getImageCanvas().repaint(); + } + + @Override + public void mouseReleased(MouseEvent e) { + int x = (int)(track.x / target.getScaleX()); + int y = (int)(track.y / target.getScaleY()); + int w = (int)(track.width / target.getScaleX()); + int h = (int)(track.height / target.getScaleY()); + BufferedImage source = target.getCurrentImage(); + int type = source.getType(); + if(type == BufferedImage.TYPE_CUSTOM) { + type = BufferedImage.TYPE_INT_ARGB; + } + BufferedImage dest = new BufferedImage(w, h, type); + dest.createGraphics().drawImage(source.getSubimage(x, y, w, h), 0, 0, null); + target.spawnEditor(dest); + track = null; + target.getImageCanvas().repaint(); + } + + @Override + public void mouseDragged(MouseEvent e) { + Point current = e.getPoint(); + int x = Math.min(last.x, current.x); + int y = Math.min(last.y, current.y); + int w = Math.abs(current.x - last.x); + int h = Math.abs(current.y - last.y); + track.setRect(x, y, w, h); + track = track.intersection(new Rectangle(0, 0, target.getImageCanvas().getWidth() - 1, target.getImageCanvas().getHeight() - 1)); + target.getImageCanvas().repaint(); + } + + public void drawTrack(Graphics2D g, int width, int height, float scaleX, float scaleY) { + if(track != null) { + g.setPaint(Color.GREEN); + g.setStroke(stroke); + g.draw(track); + } + } +} diff --git a/sdk/jme3-vehicle-creator/build.xml b/sdk/jme3-vehicle-creator/build.xml new file mode 100644 index 000000000..294399fe4 --- /dev/null +++ b/sdk/jme3-vehicle-creator/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.vehiclecreator. + + diff --git a/sdk/jme3-vehicle-creator/manifest.mf b/sdk/jme3-vehicle-creator/manifest.mf new file mode 100644 index 000000000..2bca5b19f --- /dev/null +++ b/sdk/jme3-vehicle-creator/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.vehiclecreator +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/vehiclecreator/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/vehiclecreator/Bundle.properties + diff --git a/sdk/jme3-vehicle-creator/nbproject/build-impl.xml b/sdk/jme3-vehicle-creator/nbproject/build-impl.xml new file mode 100644 index 000000000..02cdfa038 --- /dev/null +++ b/sdk/jme3-vehicle-creator/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-vehicle-creator/nbproject/genfiles.properties b/sdk/jme3-vehicle-creator/nbproject/genfiles.properties new file mode 100644 index 000000000..fb0e629e5 --- /dev/null +++ b/sdk/jme3-vehicle-creator/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=63c53212 +build.xml.script.CRC32=39e31f0c +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=63c53212 +nbproject/build-impl.xml.script.CRC32=90c55096 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-vehicle-creator/nbproject/project.properties b/sdk/jme3-vehicle-creator/nbproject/project.properties new file mode 100644 index 000000000..4ecd09668 --- /dev/null +++ b/sdk/jme3-vehicle-creator/nbproject/project.properties @@ -0,0 +1,3 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +spec.version.base=0.1 diff --git a/sdk/jme3-vehicle-creator/nbproject/project.xml b/sdk/jme3-vehicle-creator/nbproject/project.xml new file mode 100644 index 000000000..3d8db1b4a --- /dev/null +++ b/sdk/jme3-vehicle-creator/nbproject/project.xml @@ -0,0 +1,113 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.vehiclecreator + + + + com.jme3.gde.core + + + + 1 + 0.1 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.6 + + + + org.netbeans.api.progress + + + + 1 + 1.16.1.1 + + + + org.netbeans.modules.settings + + + + 1 + 1.22.1.1 + + + + org.openide.awt + + + + 7.19.1.1 + + + + org.openide.dialogs + + + + 7.15.1 + + + + org.openide.filesystems + + + + 7.32.1.1.1 + + + + org.openide.loaders + + + + 7.10.1 + + + + org.openide.nodes + + + + 7.12.1.1 + + + + org.openide.util + + + + 7.31.2.1 + + + + org.openide.util.lookup + + + + 8.2 + + + + org.openide.windows + + + + 6.30.1 + + + + + + + diff --git a/sdk/jme3-vehicle-creator/nbproject/suite.properties b/sdk/jme3-vehicle-creator/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-vehicle-creator/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-vehicle-creator/src/Models/Racetrack/Concrete_Wall.PNG b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Concrete_Wall.PNG new file mode 100644 index 000000000..b6713622e Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Concrete_Wall.PNG differ diff --git a/sdk/jme3-vehicle-creator/src/Models/Racetrack/Grass_256.png b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Grass_256.png new file mode 100644 index 000000000..4b6cd8466 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Grass_256.png differ diff --git a/sdk/jme3-vehicle-creator/src/Models/Racetrack/Raceway.j3o b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Raceway.j3o new file mode 100644 index 000000000..fc6612484 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Raceway.j3o differ diff --git a/sdk/jme3-vehicle-creator/src/Models/Racetrack/SandDesert_StartTower.png b/sdk/jme3-vehicle-creator/src/Models/Racetrack/SandDesert_StartTower.png new file mode 100644 index 000000000..7b2e6ddd2 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/Models/Racetrack/SandDesert_StartTower.png differ diff --git a/sdk/jme3-vehicle-creator/src/Models/Racetrack/SkyBox-Mountain.png b/sdk/jme3-vehicle-creator/src/Models/Racetrack/SkyBox-Mountain.png new file mode 100644 index 000000000..ac0821d56 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/Models/Racetrack/SkyBox-Mountain.png differ diff --git a/sdk/jme3-vehicle-creator/src/Models/Racetrack/Tar_Cracked.png b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Tar_Cracked.png new file mode 100644 index 000000000..27ba25f32 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/Models/Racetrack/Tar_Cracked.png differ diff --git a/sdk/jme3-vehicle-creator/src/Models/Racetrack/WarningStrip.png b/sdk/jme3-vehicle-creator/src/Models/Racetrack/WarningStrip.png new file mode 100644 index 000000000..05366a7af Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/Models/Racetrack/WarningStrip.png differ diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/Bundle.properties b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/Bundle.properties new file mode 100644 index 000000000..f4b3fefd6 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/Bundle.properties @@ -0,0 +1,57 @@ +CTL_EditVehicleAction=Edit Vehicle +CTL_EditVehicleAction=Edit Vehicle +CTL_VehicleCreatorAction=VehicleCreator +CTL_VehicleCreatorTopComponent=VehicleCreator Window +HINT_VehicleCreatorTopComponent=This is a VehicleCreator window +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin lets you create and tune bullet-based raycast vehicles for jme3 +OpenIDE-Module-Name=Vehicle Creator +OpenIDE-Module-Short-Description=Lets you create and tune vehicles for jme3 +VehicleCreatorTopComponent.jButton1.text=make selected spatial wheel.. +VehicleCreatorTopComponent.jPanel2.border.title=CollisionShape / Tools +VehicleCreatorTopComponent.jLabel1.text=Release: +VehicleCreatorTopComponent.jLabel2.text=Damping Compression: +VehicleCreatorTopComponent.jButton2.text=create hull shape from selected +VehicleCreatorTopComponent.jLabel6.text=Stiffness: +VehicleCreatorTopComponent.jButton3.text=all wheels +VehicleCreatorTopComponent.jPanel8.border.title=Suspension / Wheel Settings +VehicleCreatorTopComponent.jLabel7.text=Max force: +VehicleCreatorTopComponent.jButton5.text=test vehicle +VehicleCreatorTopComponent.jLabel8.text=apply to: +VehicleCreatorTopComponent.jButton6.text=front wheels +VehicleCreatorTopComponent.jButton7.text=back wheels +VehicleCreatorTopComponent.jLabel9.text=Friction: +VehicleCreatorTopComponent.jLabel10.text=Roll influence: +VehicleCreatorTopComponent.jLabel11.text=Rest length: +VehicleCreatorTopComponent.jPanel1.border.title=Add Wheel.. +VehicleCreatorTopComponent.jLabel5.text=Forward Axis: +VehicleCreatorTopComponent.stiffnessSlider.toolTipText=the stiffness for the suspension from buggy to F1 car +VehicleCreatorTopComponent.rollSlider.toolTipText="hack" to reduce the influence of the wheels on the car tipping over +VehicleCreatorTopComponent.compressionSlider.toolTipText=the damping on the force the suspension gives back when compressed (should be lower than release) +VehicleCreatorTopComponent.releaseSlider.toolTipText=the damping on the force the suspension creates when the suspension releases (should be higher than compression) +VehicleCreatorTopComponent.boundingRadioButton.text=bounding radius with factor: +VehicleCreatorTopComponent.fixedRadioButton.text=fixed radius: +VehicleCreatorTopComponent.jButton8.text=center selected in visual center +VehicleCreatorTopComponent.boundingSpinner.toolTipText=scale value for wheel radius when using bounding volume +VehicleCreatorTopComponent.fixedSpinner.toolTipText=fixed radius for new wheel +VehicleCreatorTopComponent.frontCheckBox.toolTipText=makes the new wheel a front wheel (for steering) +VehicleCreatorTopComponent.frontCheckBox.text=front wheel +VehicleCreatorTopComponent.jLabel4.text=acceleration / brake force: +VehicleCreatorTopComponent.jButton8.toolTipText=puts the selected spatial into its visual center +VehicleCreatorTopComponent.jButton5.toolTipText=test drive the vehicle +VehicleCreatorTopComponent.motorForceSpinner.toolTipText=the motor force used while testing +VehicleCreatorTopComponent.brakeForceSpinner.toolTipText=the brake force used while testing +VehicleCreatorTopComponent.jButton2.toolTipText=creates a hull shape for the vehicle from the selected spatial +VehicleCreatorTopComponent.jButton1.toolTipText=add a new wheel to the vehicle using the selected spatial as wheel spatial +VehicleCreatorTopComponent.boundingRadioButton.toolTipText=when selected the y extent bounding volume of the wheel will be used as radius +VehicleCreatorTopComponent.fixedRadioButton.toolTipText=set a fixed radius +VehicleCreatorTopComponent.restSpinner.toolTipText=the length of the wheel rest +VehicleCreatorTopComponent.forceSpinner.toolTipText=the maximum force the vehicle suspension will use +VehicleCreatorTopComponent.frictionSpinner.toolTipText=the friction of the wheel +VehicleCreatorTopComponent.axisSpinner.toolTipText=the forward axis of the car +VehicleCreatorTopComponent.jButton3.toolTipText=apply the values to all wheels +VehicleCreatorTopComponent.jButton6.toolTipText=apply the values to front wheels +VehicleCreatorTopComponent.jButton7.toolTipText=apply the values to back wheels +VehicleCreatorTopComponent.createNodeCheckBox.text=create parent node and center +VehicleCreatorTopComponent.createNodeCheckBox.toolTipText=creates a node for the wheel, attaches and centers the selected spatial diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/EditVehicleAction.java b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/EditVehicleAction.java new file mode 100644 index 000000000..1c5f89e40 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/EditVehicleAction.java @@ -0,0 +1,63 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.vehiclecreator; + +import com.jme3.asset.DesktopAssetManager; +import com.jme3.gde.core.assets.BinaryModelDataObject; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +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 EditVehicleAction implements ActionListener { + + private final BinaryModelDataObject context; + + public EditVehicleAction(BinaryModelDataObject context) { + this.context = context; + } + + public void actionPerformed(ActionEvent ev) { + final ProjectAssetManager manager = context.getLookup().lookup(ProjectAssetManager.class); + if (manager == null) { + return; + } + Runnable call = new Runnable() { + + public void run() { + ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening in Vehicle Editor"); + progressHandle.start(); + + + final Spatial asset = context.loadAsset(); + + if (asset != null && asset instanceof Node) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + manager.clearCache(); + VehicleCreatorTopComponent composer = VehicleCreatorTopComponent.findInstance(); + composer.openFile(context, (Node) asset); + } + }); + } else { + Confirmation msg = new NotifyDescriptor.Confirmation( + "Error opening " + context.getPrimaryFile().getNameExt(), + NotifyDescriptor.OK_CANCEL_OPTION, + NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + progressHandle.finish(); + } + }; + new Thread(call).start(); + } +} diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/SuspensionSettings.java b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/SuspensionSettings.java new file mode 100644 index 000000000..4f90e2ece --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/SuspensionSettings.java @@ -0,0 +1,184 @@ +/* + * To change this template;choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.vehiclecreator; + +import com.jme3.bullet.objects.VehicleWheel; +import com.jme3.math.Vector3f; + +/** + * + * @author normenhansen + */ +public class SuspensionSettings { + + private float boundingScale = 0; + private boolean createNode = true; + private Vector3f direction = new Vector3f(0, -1, 0); + private Vector3f axle = new Vector3f(-1, 0, 0); + private boolean frontWheel = false; + private float radius = 0; + private float restLength = 1; + private float maxForce = 6000; + private float stiffness = 50; + private float rollInfluence = 1.0f; + private float compression = 0.83f; + private float release = 0.88f; + private float friction = 10.5f; + + public SuspensionSettings() { + } + + public SuspensionSettings(VehicleWheel wheel) { + this.direction.set(wheel.getDirection()); + this.axle.set(wheel.getAxle()); + this.frontWheel = wheel.isFrontWheel(); + this.radius = wheel.getRadius(); + this.restLength = wheel.getRestLength(); + this.maxForce = wheel.getMaxSuspensionForce(); + this.stiffness = wheel.getSuspensionStiffness(); + this.rollInfluence = wheel.getRollInfluence(); + this.compression = wheel.getWheelsDampingCompression(); + this.release = wheel.getWheelsDampingRelaxation(); + this.friction = wheel.getFrictionSlip(); + } + + public void applyData(VehicleWheel wheel){ + wheel.setRadius(getRadius()); + wheel.setFrictionSlip(getFriction()); + wheel.setRollInfluence(getRollInfluence()); + wheel.setMaxSuspensionForce(getMaxForce()); + wheel.setSuspensionStiffness(getStiffness()); + wheel.setWheelsDampingCompression(getCompression()); + wheel.setWheelsDampingRelaxation(getRelease()); + } + + public float getBoundingScale() { + return boundingScale; + } + + public void setBoundingScale(float boundingScale) { + this.boundingScale = boundingScale; + } + + /** + * @return the createNode + */ + public boolean isCreateNode() { + return createNode; + } + + /** + * @param createNode the createNode to set + */ + public void setCreateNode(boolean createNode) { + this.createNode = createNode; + } + + /** + * @return the direction + */ + public Vector3f getDirection() { + return direction; + } + + /** + * @param direction the direction to set + */ + public void setDirection(Vector3f direction) { + this.direction = direction; + } + + /** + * @return the axle + */ + public Vector3f getAxle() { + return axle; + } + + /** + * @param axle the axle to set + */ + public void setAxle(Vector3f axle) { + this.axle = axle; + } + + /** + * @return the frontWheel + */ + public boolean isFrontWheel() { + return frontWheel; + } + + /** + * @param frontWheel the frontWheel to set + */ + public void setFrontWheel(boolean frontWheel) { + this.frontWheel = frontWheel; + } + + public float getRadius() { + return radius; + } + + public void setRadius(float radius) { + this.radius = radius; + } + + public float getRestLength() { + return restLength; + } + + public void setRestLength(float restLength) { + this.restLength = restLength; + } + + public float getMaxForce() { + return maxForce; + } + + public void setMaxForce(float maxForce) { + this.maxForce = maxForce; + } + + public float getStiffness() { + return stiffness; + } + + public void setStiffness(float stiffness) { + this.stiffness = stiffness; + } + + public float getRollInfluence() { + return rollInfluence; + } + + public void setRollInfluence(float rollInfluence) { + this.rollInfluence = rollInfluence; + } + + public float getCompression() { + return compression; + } + + public void setCompression(float compression) { + this.compression = compression; + } + + public float getRelease() { + return release; + } + + public void setRelease(float release) { + this.release = release; + } + + public float getFriction() { + return friction; + } + + public void setFriction(float friction) { + this.friction = friction; + } +} diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorCameraController.java b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorCameraController.java new file mode 100644 index 000000000..6e6ba8885 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorCameraController.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009-2010 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.vehiclecreator; + +import com.jme3.gde.core.scene.controller.AbstractCameraController; +import com.jme3.input.InputManager; +import com.jme3.renderer.Camera; +import com.jme3.scene.Spatial; + +/** + * + * @author normenhansen + */ +public class VehicleCreatorCameraController extends AbstractCameraController { + + private Spatial vehicle; + + public VehicleCreatorCameraController(Camera cam, InputManager inputManager) { + super(cam, inputManager); + } + + @Override + public void update(float f) { + super.update(f); + if (vehicle != null) { + doSetCamFocus(vehicle.getWorldTranslation()); + } + } + + @Override + protected void checkClick(int button) { + } + + /** + * @param vehicle the vehicle to set + */ + public void setVehicle(Spatial vehicle) { + this.vehicle = vehicle; + } +} diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponent.form b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponent.form new file mode 100644 index 000000000..bc79261bd --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponent.form @@ -0,0 +1,916 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponent.java b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponent.java new file mode 100644 index 000000000..aebe3b3c5 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponent.java @@ -0,0 +1,920 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.vehiclecreator; + +import com.jme3.gde.core.assets.BinaryModelDataObject; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.PreviewRequest; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneListener; +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.sceneviewer.SceneViewerTopComponent; +import com.jme3.light.DirectionalLight; +import com.jme3.math.FastMath; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import java.util.logging.Logger; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.openide.util.ImageUtilities; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.util.HelpCtx; + +/** + * Top component which displays something. + */ +@ConvertAsProperties(dtd = "-//com.jme3.gde.vehiclecreator//VehicleCreator//EN", +autostore = false) +public final class VehicleCreatorTopComponent extends TopComponent implements SceneListener { + + private static VehicleCreatorTopComponent instance; + /** path to the icon used by the component and its open action */ + static final String ICON_PATH = "com/jme3/gde/vehiclecreator/objects_039.gif"; + private static final String PREFERRED_ID = "VehicleCreatorTopComponent"; + private VehicleEditorController editorController; + private SceneRequest currentRequest; + private boolean testing = false; + DirectionalLight dirLight = new DirectionalLight(); + private HelpCtx ctx = new HelpCtx("sdk.vehicle_creator"); + + public VehicleCreatorTopComponent() { + initComponents(); + setName(NbBundle.getMessage(VehicleCreatorTopComponent.class, "CTL_VehicleCreatorTopComponent")); + setToolTipText(NbBundle.getMessage(VehicleCreatorTopComponent.class, "HINT_VehicleCreatorTopComponent")); + setIcon(ImageUtilities.loadImage(ICON_PATH, true)); + + } + + /** 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + buttonGroup1 = new javax.swing.ButtonGroup(); + jToolBar10 = new javax.swing.JToolBar(); + jButton5 = new javax.swing.JButton(); + jSeparator4 = new javax.swing.JToolBar.Separator(); + jLabel4 = new javax.swing.JLabel(); + motorForceSpinner = new javax.swing.JSpinner(); + brakeForceSpinner = new javax.swing.JSpinner(); + jSeparator3 = new javax.swing.JToolBar.Separator(); + jPanel10 = new javax.swing.JPanel(); + jSeparator1 = new javax.swing.JToolBar.Separator(); + jPanel13 = new javax.swing.JPanel(); + jPanel2 = new javax.swing.JPanel(); + jToolBar3 = new javax.swing.JToolBar(); + jButton2 = new javax.swing.JButton(); + jPanel5 = new javax.swing.JPanel(); + jToolBar4 = new javax.swing.JToolBar(); + jButton8 = new javax.swing.JButton(); + jPanel1 = new javax.swing.JPanel(); + jToolBar11 = new javax.swing.JToolBar(); + jPanel12 = new javax.swing.JPanel(); + jToolBar13 = new javax.swing.JToolBar(); + jButton1 = new javax.swing.JButton(); + jPanel3 = new javax.swing.JPanel(); + frontCheckBox = new javax.swing.JCheckBox(); + jToolBar14 = new javax.swing.JToolBar(); + boundingRadioButton = new javax.swing.JRadioButton(); + jPanel14 = new javax.swing.JPanel(); + boundingSpinner = new javax.swing.JSpinner(); + jToolBar15 = new javax.swing.JToolBar(); + jLabel5 = new javax.swing.JLabel(); + jPanel6 = new javax.swing.JPanel(); + axisSpinner = new javax.swing.JSpinner(); + jToolBar16 = new javax.swing.JToolBar(); + fixedRadioButton = new javax.swing.JRadioButton(); + jPanel11 = new javax.swing.JPanel(); + fixedSpinner = new javax.swing.JSpinner(); + jToolBar5 = new javax.swing.JToolBar(); + createNodeCheckBox = new javax.swing.JCheckBox(); + jPanel8 = new javax.swing.JPanel(); + jToolBar2 = new javax.swing.JToolBar(); + jLabel2 = new javax.swing.JLabel(); + compressionSlider = new javax.swing.JSlider(); + jLabel1 = new javax.swing.JLabel(); + releaseSlider = new javax.swing.JSlider(); + jToolBar6 = new javax.swing.JToolBar(); + jLabel6 = new javax.swing.JLabel(); + stiffnessSlider = new javax.swing.JSlider(); + jLabel10 = new javax.swing.JLabel(); + rollSlider = new javax.swing.JSlider(); + jToolBar7 = new javax.swing.JToolBar(); + jLabel11 = new javax.swing.JLabel(); + restSpinner = new javax.swing.JSpinner(); + jSeparator6 = new javax.swing.JToolBar.Separator(); + jLabel7 = new javax.swing.JLabel(); + forceSpinner = new javax.swing.JSpinner(); + jPanel7 = new javax.swing.JPanel(); + jToolBar9 = new javax.swing.JToolBar(); + jLabel9 = new javax.swing.JLabel(); + frictionSpinner = new javax.swing.JSpinner(); + jPanel15 = new javax.swing.JPanel(); + jPanel4 = new javax.swing.JPanel(); + jToolBar1 = new javax.swing.JToolBar(); + jLabel8 = new javax.swing.JLabel(); + jPanel9 = new javax.swing.JPanel(); + jButton3 = new javax.swing.JButton(); + jButton6 = new javax.swing.JButton(); + jButton7 = new javax.swing.JButton(); + + jToolBar10.setFloatable(false); + jToolBar10.setRollover(true); + + jButton5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/vehiclecreator/car-icon.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jButton5, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton5.text")); // NOI18N + jButton5.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton5.toolTipText")); // NOI18N + jButton5.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton5ActionPerformed(evt); + } + }); + jToolBar10.add(jButton5); + jToolBar10.add(jSeparator4); + + jLabel4.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel4.text")); // NOI18N + jToolBar10.add(jLabel4); + + motorForceSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(800.0f), null, null, Float.valueOf(1.0f))); + motorForceSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.motorForceSpinner.toolTipText")); // NOI18N + motorForceSpinner.setPreferredSize(new java.awt.Dimension(80, 28)); + motorForceSpinner.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + motorForceSpinnerStateChanged(evt); + } + }); + jToolBar10.add(motorForceSpinner); + + brakeForceSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(40.0f), null, null, Float.valueOf(1.0f))); + brakeForceSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.brakeForceSpinner.toolTipText")); // NOI18N + brakeForceSpinner.setPreferredSize(new java.awt.Dimension(80, 28)); + brakeForceSpinner.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + brakeForceSpinnerStateChanged(evt); + } + }); + jToolBar10.add(brakeForceSpinner); + jToolBar10.add(jSeparator3); + + javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10); + jPanel10.setLayout(jPanel10Layout); + jPanel10Layout.setHorizontalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 434, Short.MAX_VALUE) + ); + jPanel10Layout.setVerticalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar10.add(jPanel10); + jToolBar10.add(jSeparator1); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jPanel2.border.title"))); // NOI18N + + jToolBar3.setFloatable(false); + jToolBar3.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton2.text")); // NOI18N + jButton2.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton2.toolTipText")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + jToolBar3.add(jButton2); + + jPanel5.setPreferredSize(new java.awt.Dimension(100, 21)); + + javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); + jPanel5.setLayout(jPanel5Layout); + jPanel5Layout.setHorizontalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + jPanel5Layout.setVerticalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar3.add(jPanel5); + + jToolBar4.setFloatable(false); + jToolBar4.setRollover(true); + + org.openide.awt.Mnemonics.setLocalizedText(jButton8, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton8.text")); // NOI18N + jButton8.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton8.toolTipText")); // NOI18N + jButton8.setFocusable(false); + jButton8.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton8.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton8.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton8ActionPerformed(evt); + } + }); + jToolBar4.add(jButton8); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar3, javax.swing.GroupLayout.DEFAULT_SIZE, 187, Short.MAX_VALUE) + .addComponent(jToolBar4, javax.swing.GroupLayout.DEFAULT_SIZE, 187, Short.MAX_VALUE) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 115, Short.MAX_VALUE) + .addComponent(jToolBar4, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jPanel1.border.title"))); // NOI18N + + jToolBar11.setFloatable(false); + jToolBar11.setRollover(true); + + javax.swing.GroupLayout jPanel12Layout = new javax.swing.GroupLayout(jPanel12); + jPanel12.setLayout(jPanel12Layout); + jPanel12Layout.setHorizontalGroup( + jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 276, Short.MAX_VALUE) + ); + jPanel12Layout.setVerticalGroup( + jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar11.add(jPanel12); + + jToolBar13.setFloatable(false); + jToolBar13.setRollover(true); + + jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/vehiclecreator/objects_039.gif"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton1.text")); // NOI18N + jButton1.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton1.toolTipText")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + jToolBar13.add(jButton1); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar13.add(jPanel3); + + frontCheckBox.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(frontCheckBox, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.frontCheckBox.text")); // NOI18N + frontCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.frontCheckBox.toolTipText")); // NOI18N + frontCheckBox.setFocusable(false); + frontCheckBox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jToolBar13.add(frontCheckBox); + + jToolBar14.setFloatable(false); + jToolBar14.setRollover(true); + + buttonGroup1.add(boundingRadioButton); + boundingRadioButton.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(boundingRadioButton, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.boundingRadioButton.text")); // NOI18N + boundingRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.boundingRadioButton.toolTipText")); // NOI18N + boundingRadioButton.setFocusable(false); + boundingRadioButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jToolBar14.add(boundingRadioButton); + + javax.swing.GroupLayout jPanel14Layout = new javax.swing.GroupLayout(jPanel14); + jPanel14.setLayout(jPanel14Layout); + jPanel14Layout.setHorizontalGroup( + jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 15, Short.MAX_VALUE) + ); + jPanel14Layout.setVerticalGroup( + jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar14.add(jPanel14); + + boundingSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(1.0f), null, null, Float.valueOf(0.1f))); + boundingSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.boundingSpinner.toolTipText")); // NOI18N + boundingSpinner.setPreferredSize(new java.awt.Dimension(50, 28)); + jToolBar14.add(boundingSpinner); + + jToolBar15.setFloatable(false); + jToolBar15.setRollover(true); + + jLabel5.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel5.text")); // NOI18N + jToolBar15.add(jLabel5); + + javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); + jPanel6.setLayout(jPanel6Layout); + jPanel6Layout.setHorizontalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 155, Short.MAX_VALUE) + ); + jPanel6Layout.setVerticalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar15.add(jPanel6); + + axisSpinner.setModel(new javax.swing.SpinnerListModel(new String[] {"+Z", "-Z", "+X", "-X"})); + axisSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.axisSpinner.toolTipText")); // NOI18N + jToolBar15.add(axisSpinner); + + jToolBar16.setFloatable(false); + jToolBar16.setRollover(true); + + buttonGroup1.add(fixedRadioButton); + fixedRadioButton.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(fixedRadioButton, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.fixedRadioButton.text")); // NOI18N + fixedRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.fixedRadioButton.toolTipText")); // NOI18N + fixedRadioButton.setFocusable(false); + fixedRadioButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jToolBar16.add(fixedRadioButton); + + javax.swing.GroupLayout jPanel11Layout = new javax.swing.GroupLayout(jPanel11); + jPanel11.setLayout(jPanel11Layout); + jPanel11Layout.setHorizontalGroup( + jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 127, Short.MAX_VALUE) + ); + jPanel11Layout.setVerticalGroup( + jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar16.add(jPanel11); + + fixedSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(1.0f), null, null, Float.valueOf(0.1f))); + fixedSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.fixedSpinner.toolTipText")); // NOI18N + fixedSpinner.setPreferredSize(new java.awt.Dimension(50, 28)); + jToolBar16.add(fixedSpinner); + + jToolBar5.setFloatable(false); + jToolBar5.setRollover(true); + + createNodeCheckBox.setFont(new java.awt.Font("Lucida Grande", 0, 11)); // NOI18N + createNodeCheckBox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(createNodeCheckBox, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.createNodeCheckBox.text")); // NOI18N + createNodeCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.createNodeCheckBox.toolTipText")); // NOI18N + createNodeCheckBox.setFocusable(false); + createNodeCheckBox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jToolBar5.add(createNodeCheckBox); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar13, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) + .addComponent(jToolBar14, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) + .addComponent(jToolBar16, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) + .addComponent(jToolBar15, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) + .addComponent(jToolBar11, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) + .addComponent(jToolBar5, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jToolBar13, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar14, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar16, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar15, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar5, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE) + .addComponent(jToolBar11, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + jPanel8.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jPanel8.border.title"))); // NOI18N + + jToolBar2.setFloatable(false); + jToolBar2.setRollover(true); + + jLabel2.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel2.text")); // NOI18N + jToolBar2.add(jLabel2); + + compressionSlider.setMinimum(1); + compressionSlider.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.compressionSlider.toolTipText")); // NOI18N + compressionSlider.setValue(30); + jToolBar2.add(compressionSlider); + + jLabel1.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel1.text")); // NOI18N + jToolBar2.add(jLabel1); + + releaseSlider.setMinimum(1); + releaseSlider.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.releaseSlider.toolTipText")); // NOI18N + releaseSlider.setValue(40); + jToolBar2.add(releaseSlider); + + jToolBar6.setFloatable(false); + jToolBar6.setRollover(true); + + jLabel6.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel6.text")); // NOI18N + jToolBar6.add(jLabel6); + + stiffnessSlider.setMaximum(220); + stiffnessSlider.setMinimum(10); + stiffnessSlider.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.stiffnessSlider.toolTipText")); // NOI18N + stiffnessSlider.setPreferredSize(new java.awt.Dimension(260, 29)); + jToolBar6.add(stiffnessSlider); + + jLabel10.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel10, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel10.text")); // NOI18N + jToolBar6.add(jLabel10); + + rollSlider.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.rollSlider.toolTipText")); // NOI18N + jToolBar6.add(rollSlider); + + jToolBar7.setFloatable(false); + jToolBar7.setRollover(true); + + jLabel11.setFont(new java.awt.Font("Lucida Grande", 0, 11)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel11, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel11.text")); // NOI18N + jToolBar7.add(jLabel11); + + restSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(0.2f), null, null, Float.valueOf(0.01f))); + restSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.restSpinner.toolTipText")); // NOI18N + restSpinner.setPreferredSize(new java.awt.Dimension(80, 28)); + jToolBar7.add(restSpinner); + jToolBar7.add(jSeparator6); + + jLabel7.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel7.text")); // NOI18N + jToolBar7.add(jLabel7); + + forceSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(6000.0f), null, null, Float.valueOf(1.0f))); + forceSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.forceSpinner.toolTipText")); // NOI18N + forceSpinner.setPreferredSize(new java.awt.Dimension(80, 28)); + jToolBar7.add(forceSpinner); + + javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); + jPanel7.setLayout(jPanel7Layout); + jPanel7Layout.setHorizontalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 46, Short.MAX_VALUE) + ); + jPanel7Layout.setVerticalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 28, Short.MAX_VALUE) + ); + + jToolBar7.add(jPanel7); + + jToolBar9.setFloatable(false); + jToolBar9.setRollover(true); + + jLabel9.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel9, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel9.text")); // NOI18N + jToolBar9.add(jLabel9); + + frictionSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(10.5f), null, null, Float.valueOf(0.1f))); + frictionSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.frictionSpinner.toolTipText")); // NOI18N + frictionSpinner.setPreferredSize(new java.awt.Dimension(80, 28)); + jToolBar9.add(frictionSpinner); + + javax.swing.GroupLayout jPanel15Layout = new javax.swing.GroupLayout(jPanel15); + jPanel15.setLayout(jPanel15Layout); + jPanel15Layout.setHorizontalGroup( + jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 101, Short.MAX_VALUE) + ); + jPanel15Layout.setVerticalGroup( + jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar9.add(jPanel15); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 127, Short.MAX_VALUE) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar9.add(jPanel4); + + jToolBar1.setFloatable(false); + jToolBar1.setRollover(true); + + jLabel8.setFont(new java.awt.Font("Lucida Grande", 0, 11)); + org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jLabel8.text")); // NOI18N + jToolBar1.add(jLabel8); + + javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9); + jPanel9.setLayout(jPanel9Layout); + jPanel9Layout.setHorizontalGroup( + jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 93, Short.MAX_VALUE) + ); + jPanel9Layout.setVerticalGroup( + jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 21, Short.MAX_VALUE) + ); + + jToolBar1.add(jPanel9); + + org.openide.awt.Mnemonics.setLocalizedText(jButton3, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton3.text")); // NOI18N + jButton3.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton3.toolTipText")); // NOI18N + jButton3.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton3ActionPerformed(evt); + } + }); + jToolBar1.add(jButton3); + + org.openide.awt.Mnemonics.setLocalizedText(jButton6, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton6.text")); // NOI18N + jButton6.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton6.toolTipText")); // NOI18N + jButton6.setFocusable(false); + jButton6.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton6.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton6.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton6ActionPerformed(evt); + } + }); + jToolBar1.add(jButton6); + + org.openide.awt.Mnemonics.setLocalizedText(jButton7, org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton7.text")); // NOI18N + jButton7.setToolTipText(org.openide.util.NbBundle.getMessage(VehicleCreatorTopComponent.class, "VehicleCreatorTopComponent.jButton7.toolTipText")); // NOI18N + jButton7.setFocusable(false); + jButton7.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton7.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jButton7.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton7ActionPerformed(evt); + } + }); + jToolBar1.add(jButton7); + + javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8); + jPanel8.setLayout(jPanel8Layout); + jPanel8Layout.setHorizontalGroup( + jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar7, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE) + .addComponent(jToolBar6, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE) + .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE) + .addComponent(jToolBar9, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE) + ); + jPanel8Layout.setVerticalGroup( + jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel8Layout.createSequentialGroup() + .addComponent(jToolBar7, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar6, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jToolBar9, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 33, Short.MAX_VALUE) + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + javax.swing.GroupLayout jPanel13Layout = new javax.swing.GroupLayout(jPanel13); + jPanel13.setLayout(jPanel13Layout); + jPanel13Layout.setHorizontalGroup( + jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel13Layout.createSequentialGroup() + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel13Layout.setVerticalGroup( + jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel13, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jToolBar10, javax.swing.GroupLayout.DEFAULT_SIZE, 871, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jToolBar10, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel13, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + editorController.addWheel(getSuspensionSettings()); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + editorController.createHullShapeFromSelected(); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton8ActionPerformed + editorController.centerSelected(); + }//GEN-LAST:event_jButton8ActionPerformed + + private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed + if (testing) { + editorController.stopVehicle(); + jButton5.setText("test vehicle"); + testing = false; + } else { + SceneViewerTopComponent.findInstance().requestActive(); + editorController.testVehicle(); + jButton5.setText("stop testing"); + testing = true; + } + }//GEN-LAST:event_jButton5ActionPerformed + + private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed + editorController.applyWheelData(0, getSuspensionSettings()); + }//GEN-LAST:event_jButton3ActionPerformed + + private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton6ActionPerformed + editorController.applyWheelData(1, getSuspensionSettings()); + }//GEN-LAST:event_jButton6ActionPerformed + + private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton7ActionPerformed + editorController.applyWheelData(2, getSuspensionSettings()); + }//GEN-LAST:event_jButton7ActionPerformed + + private void motorForceSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_motorForceSpinnerStateChanged + editorController.setMotorForce((Float) motorForceSpinner.getValue()); + }//GEN-LAST:event_motorForceSpinnerStateChanged + + private void brakeForceSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_brakeForceSpinnerStateChanged + editorController.setBrakeForce((Float) brakeForceSpinner.getValue()); + }//GEN-LAST:event_brakeForceSpinnerStateChanged + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JSpinner axisSpinner; + private javax.swing.JRadioButton boundingRadioButton; + private javax.swing.JSpinner boundingSpinner; + private javax.swing.JSpinner brakeForceSpinner; + private javax.swing.ButtonGroup buttonGroup1; + private javax.swing.JSlider compressionSlider; + private javax.swing.JCheckBox createNodeCheckBox; + private javax.swing.JRadioButton fixedRadioButton; + private javax.swing.JSpinner fixedSpinner; + private javax.swing.JSpinner forceSpinner; + private javax.swing.JSpinner frictionSpinner; + private javax.swing.JCheckBox frontCheckBox; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JButton jButton3; + private javax.swing.JButton jButton5; + private javax.swing.JButton jButton6; + private javax.swing.JButton jButton7; + private javax.swing.JButton jButton8; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel10; + private javax.swing.JLabel jLabel11; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel10; + private javax.swing.JPanel jPanel11; + private javax.swing.JPanel jPanel12; + private javax.swing.JPanel jPanel13; + private javax.swing.JPanel jPanel14; + private javax.swing.JPanel jPanel15; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JPanel jPanel7; + private javax.swing.JPanel jPanel8; + private javax.swing.JPanel jPanel9; + private javax.swing.JToolBar.Separator jSeparator1; + private javax.swing.JToolBar.Separator jSeparator3; + private javax.swing.JToolBar.Separator jSeparator4; + private javax.swing.JToolBar.Separator jSeparator6; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JToolBar jToolBar10; + private javax.swing.JToolBar jToolBar11; + private javax.swing.JToolBar jToolBar13; + private javax.swing.JToolBar jToolBar14; + private javax.swing.JToolBar jToolBar15; + private javax.swing.JToolBar jToolBar16; + private javax.swing.JToolBar jToolBar2; + private javax.swing.JToolBar jToolBar3; + private javax.swing.JToolBar jToolBar4; + private javax.swing.JToolBar jToolBar5; + private javax.swing.JToolBar jToolBar6; + private javax.swing.JToolBar jToolBar7; + private javax.swing.JToolBar jToolBar9; + private javax.swing.JSpinner motorForceSpinner; + private javax.swing.JSlider releaseSlider; + private javax.swing.JSpinner restSpinner; + private javax.swing.JSlider rollSlider; + private javax.swing.JSlider stiffnessSlider; + // End of variables declaration//GEN-END:variables + + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link #findInstance}. + */ + public static synchronized VehicleCreatorTopComponent getDefault() { + if (instance == null) { + instance = new VehicleCreatorTopComponent(); + } + return instance; + } + + /** + * Obtain the VehicleCreatorTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized VehicleCreatorTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + Logger.getLogger(VehicleCreatorTopComponent.class.getName()).warning( + "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof VehicleCreatorTopComponent) { + return (VehicleCreatorTopComponent) win; + } + Logger.getLogger(VehicleCreatorTopComponent.class.getName()).warning( + "There seem to be multiple components with the '" + PREFERRED_ID + + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + // TODO add custom code on component closing + if (currentRequest != null) { + SceneApplication.getApplication().closeScene(currentRequest); + } + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + Object readProperties(java.util.Properties p) { + if (instance == null) { + instance = this; + } + instance.readPropertiesImpl(p); + return instance; + } + + private void readPropertiesImpl(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + @Override + public HelpCtx getHelpCtx() { + return ctx; + } + + + private SuspensionSettings getSuspensionSettings() { + SuspensionSettings settings = new SuspensionSettings(); + settings.setFriction((Float) frictionSpinner.getValue()); + settings.setMaxForce((Float) forceSpinner.getValue()); + settings.setRestLength((Float) restSpinner.getValue()); + if (boundingRadioButton.isSelected()) { + settings.setBoundingScale((Float) boundingSpinner.getValue()); + } else { + settings.setBoundingScale(0); + settings.setRadius((Float) fixedSpinner.getValue()); + } + float stiffness = stiffnessSlider.getValue(); + float compValue = (float) compressionSlider.getValue() / 100.0f; + float dampValue = (float) releaseSlider.getValue() / 100.0f; + settings.setCompression(compValue * 2.0f * FastMath.sqrt(stiffness)); + settings.setRelease(dampValue * 2.0f * FastMath.sqrt(stiffness)); + settings.setStiffness(stiffness); + settings.setFrontWheel(frontCheckBox.isSelected()); + if ("-Z".equals(axisSpinner.getValue())) { + settings.setAxle(new Vector3f(1, 0, 0)); + } else if ("X".equals(axisSpinner.getValue())) { + settings.setAxle(new Vector3f(0, 0, 1)); + } else if ("-X".equals(axisSpinner.getValue())) { + settings.setAxle(new Vector3f(0, 0, -1)); + } + settings.setCreateNode(createNodeCheckBox.isSelected()); + return settings; + } + + public void openFile(BinaryModelDataObject file, Node spatial) { + JmeNode node = NodeUtility.createNode(spatial, false); + editorController = new VehicleEditorController(node, file); + SceneApplication.getApplication().addSceneListener(this); + currentRequest = new SceneRequest(this, node, file.getLookup().lookup(ProjectAssetManager.class)); + currentRequest.setWindowTitle("Vehicle Creator"); + currentRequest.setDataObject(file); + currentRequest.setToolNode(editorController.getToolsNode()); + currentRequest.setHelpCtx(ctx); + SceneApplication.getApplication().requestScene(currentRequest); + } + + public void previewRequested(PreviewRequest request) { + } + + public boolean sceneClose(SceneRequest request) { + if (request == currentRequest) { + SceneApplication.getApplication().removeSceneListener(this); + currentRequest.getRootNode().getParent().removeLight(dirLight); + editorController.cleanupApplication(); + SceneApplication.getApplication().getStateManager().detach(editorController.getBulletState()); + setLoadedScene(null, false); + currentRequest = null; + } + return true; + } + + public void sceneRequested(SceneRequest request) { + if (request == currentRequest) { + editorController.prepareApplication(); + SceneApplication.getApplication().getStateManager().attach(editorController.getBulletState()); + setLoadedScene(currentRequest.getJmeNode(), true); + currentRequest.getRootNode().getParent().addLight(dirLight); + } + } + + private void setLoadedScene(final org.openide.nodes.Node jmeNode, final boolean active) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (!active) { + close(); + setActivatedNodes(new org.openide.nodes.Node[]{}); + if (editorController != null) { + editorController.cleanup(); + editorController = null; + } + } else { + if (!isOpened()) { + open(); + } + requestActive(); +// setActivatedNodes(new org.openide.nodes.Node[]{jmeNode}); + editorController.checkVehicle(); + } + } + }); + } +} diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponentSettings.xml b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponentSettings.xml new file mode 100644 index 000000000..2bc119ff7 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponentSettings.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponentWstcref.xml b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponentWstcref.xml new file mode 100644 index 000000000..65c71dc20 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorTopComponentWstcref.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleEditorController.java b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleEditorController.java new file mode 100644 index 000000000..c20f60780 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleEditorController.java @@ -0,0 +1,636 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.vehiclecreator; + +import com.jme3.asset.DesktopAssetManager; +import com.jme3.bounding.BoundingBox; +import com.jme3.bullet.BulletAppState; +import com.jme3.bullet.collision.shapes.BoxCollisionShape; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.bullet.control.VehicleControl; +import com.jme3.bullet.objects.VehicleWheel; +import com.jme3.bullet.util.CollisionShapeFactory; +import com.jme3.gde.core.assets.BinaryModelDataObject; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.controller.SceneToolController; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.input.KeyInput; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.KeyTrigger; +import com.jme3.light.DirectionalLight; +import com.jme3.math.FastMath; +import com.jme3.math.Matrix3f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import java.util.Iterator; +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 org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.Lookup.Result; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; + +/** + * + * @author normenhansen + */ +public class VehicleEditorController implements LookupListener, ActionListener { + + private JmeSpatial jmeRootNode; + private Node rootNode; + private JmeSpatial selectedSpat; + private BinaryModelDataObject currentFileObject; + private VehicleControl vehicleControl; + private Result result; + private Result result2; + private List list = new LinkedList(); + private SceneToolController toolController; + private VehicleCreatorCameraController cameraController; + private Node toolsNode; + private BulletAppState bulletState; + private boolean testing = false; + private float motorForce = 800; + private float brakeForce = 40; + + public VehicleEditorController(JmeSpatial jmeRootNode, BinaryModelDataObject currentFileObject) { + this.jmeRootNode = jmeRootNode; + this.currentFileObject = currentFileObject; + rootNode = jmeRootNode.getLookup().lookup(Node.class); + toolsNode = new Node("ToolsNode"); + toolController = new SceneToolController(toolsNode, currentFileObject.getLookup().lookup(ProjectAssetManager.class)); + toolController.setShowSelection(true); + result = Utilities.actionsGlobalContext().lookupResult(JmeSpatial.class); + result.addLookupListener(this); + toolsNode.addLight(new DirectionalLight()); + Node track = (Node) new DesktopAssetManager(true).loadModel("Models/Racetrack/Raceway.j3o"); + track.getChild("Grass").getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(30, -1, 0)); + track.getChild("Grass").getControl(RigidBodyControl.class).setPhysicsRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI * 0.68f, Vector3f.UNIT_Y).toRotationMatrix()); + track.getChild("Road").getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(30, 0, 0)); + track.getChild("Road").getControl(RigidBodyControl.class).setPhysicsRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI * 0.68f, Vector3f.UNIT_Y).toRotationMatrix()); + toolsNode.attachChild(track); + bulletState = new BulletAppState(); + + result2 = Utilities.actionsGlobalContext().lookupResult(VehicleWheel.class); + LookupListener listener = new LookupListener() { + + public void resultChanged(LookupEvent ev) { + for (Iterator it = result2.allInstances().iterator(); it.hasNext();) { + VehicleWheel wheel = it.next(); + toolController.updateSelection(wheel.getWheelSpatial()); + } + } + }; + result2.addLookupListener(listener); + } + + public void prepareApplication() { + SceneApplication.getApplication().getInputManager().addMapping("VehicleEditor_Left", new KeyTrigger(KeyInput.KEY_A)); + SceneApplication.getApplication().getInputManager().addMapping("VehicleEditor_Right", new KeyTrigger(KeyInput.KEY_D)); + SceneApplication.getApplication().getInputManager().addMapping("VehicleEditor_Up", new KeyTrigger(KeyInput.KEY_W)); + SceneApplication.getApplication().getInputManager().addMapping("VehicleEditor_Down", new KeyTrigger(KeyInput.KEY_S)); + SceneApplication.getApplication().getInputManager().addMapping("VehicleEditor_Space", new KeyTrigger(KeyInput.KEY_SPACE)); + SceneApplication.getApplication().getInputManager().addMapping("VehicleEditor_Reset", new KeyTrigger(KeyInput.KEY_RETURN)); + SceneApplication.getApplication().getInputManager().addListener(this, "VehicleEditor_Left", "VehicleEditor_Right", "VehicleEditor_Up", "VehicleEditor_Down", "VehicleEditor_Space", "VehicleEditor_Reset"); + cameraController = new VehicleCreatorCameraController(SceneApplication.getApplication().getCamera(), SceneApplication.getApplication().getInputManager()); + cameraController.setMaster(this); + cameraController.enable(); + cameraController.setVehicle(rootNode); + } + + public void cleanupApplication() { + SceneApplication.getApplication().getInputManager().removeListener(this); + cameraController.disable(); + cameraController = null; + } + + public JmeSpatial getJmeRootNode() { + return jmeRootNode; + } + + public JmeSpatial getSelectedSpat() { + return selectedSpat; + } + + public void setSelectedSpat(JmeSpatial selectedSpat) { + this.selectedSpat = selectedSpat; + } + + public BinaryModelDataObject getCurrentFileObject() { + return currentFileObject; + } + + public void awtCall() { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doAwtCall(node); + return null; + + } + }).get(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doAwtCall(Spatial selected) { + } + + public void testVehicle() { + if (jmeRootNode == null) { + return; + } + final Node node = jmeRootNode.getLookup().lookup(Node.class); + if (node != null) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doTestVehicle(node); + return null; + + } + }); + } + } +// private ChaseCamera chaseCam; + + public void doTestVehicle(Node vehicleNode) { + testing = true; + bulletState.getPhysicsSpace().addAll(toolsNode); + bulletState.getPhysicsSpace().add(vehicleControl); + vehicleControl.detachDebugShape(); +// cameraController.disable(); +// if (chaseCam == null) { +// chaseCam = new ChaseCamera(SceneApplication.getApplication().getCamera(), vehicleNode); +// chaseCam.registerWithInput(SceneApplication.getApplication().getInputManager()); +// } +// chaseCam.setEnabled(true); + } + + public void stopVehicle() { + try { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doStopVehicle(); + return null; + + } + }).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doStopVehicle() { + testing = false; + vehicleControl.setPhysicsLocation(Vector3f.ZERO); + vehicleControl.setPhysicsRotation(new Matrix3f()); + vehicleControl.setLinearVelocity(Vector3f.ZERO); + vehicleControl.setAngularVelocity(Vector3f.ZERO); + vehicleControl.resetSuspension(); + vehicleControl.attachDebugShape(SceneApplication.getApplication().getAssetManager()); + bulletState.getPhysicsSpace().removeAll(toolsNode); + bulletState.getPhysicsSpace().remove(vehicleControl); +// chaseCam.setEnabled(false); +// cameraController.enable(); + } + + public void centerSelected() { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + if (node != null) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doCenterSelected(node); + return null; + + } + }).get(); + currentFileObject.setModified(true); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doCenterSelected(final Spatial selected) { + final Vector3f location = new Vector3f(selected.getLocalTranslation()); + selected.center(); + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() { + //undo stuff here + selected.setLocalTranslation(location); + } + + @Override + public void sceneRedo() { + //redo stuff here + selected.center(); + } + + @Override + public void awtRedo() { + } + + @Override + public void awtUndo() { + } + }); + } + + public void addWheel(final SuspensionSettings settings) { + if (selectedSpat == null || selectedSpat == jmeRootNode) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + final Node rootNode = jmeRootNode.getLookup().lookup(Node.class); + if (node != null) { + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doAddWheel(node, rootNode, settings); + return null; + } + }).get(); + currentFileObject.setModified(true); + refreshSelectedParent(); + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doAddWheel(Spatial selected, Spatial vehicle, SuspensionSettings settings) { + Spatial node = null; + Vector3f wheelLocation = vehicle.worldToLocal(selected.getWorldBound().getCenter(), new Vector3f()); + wheelLocation.add(0, settings.getRestLength(), 0); + + //compute radius from bounding volue with scale if set + if (settings.getBoundingScale() > 0) { + BoundingBox worldBound = null; + if (selected.getWorldBound() instanceof BoundingBox) { + worldBound = (BoundingBox) selected.getWorldBound(); + settings.setRadius(worldBound.getYExtent() * settings.getBoundingScale()); + } else { + Logger.getLogger(VehicleEditorController.class.getName()).log(Level.WARNING, "Cannot get bounding box!"); + } + } + + if (settings.isCreateNode()) { + node = new Node(selected.getName() + "-WheelNode"); + } else { + node = selected; + } + + node.setLocalTranslation(selected.worldToLocal(selected.getWorldBound().getCenter(), new Vector3f())); + + VehicleWheel wheel = vehicleControl.addWheel(node, wheelLocation, settings.getDirection(), settings.getAxle(), settings.getRestLength(), settings.getRadius(), settings.isFrontWheel()); + settings.applyData(wheel); + if (settings.isCreateNode()) { + selected.center(); + Node parent = selected.getParent(); + ((Node) node).attachChild(selected); + parent.attachChild(node); + } + +// Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() { +// +// @Override +// public void sceneUndo() throws CannotUndoException { +// //undo stuff here +// } +// +// @Override +// public void sceneRedo() throws CannotRedoException { +// //redo stuff here +// } +// +// @Override +// public void awtRedo() { +// } +// +// @Override +// public void awtUndo() { +// } +// }); + } + + public void checkVehicle() { + if (jmeRootNode == null) { + return; + } + try { + final Node node = jmeRootNode.getLookup().lookup(Node.class); + if (node != null) { + if (SceneApplication.getApplication().enqueue(new Callable() { + + public Boolean call() throws Exception { + return doCheckVehicle(node); + } + }).get().booleanValue()) { + currentFileObject.setModified(true); + refreshRoot(); + } + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public boolean doCheckVehicle(Node rootNode) { + VehicleControl control = rootNode.getControl(VehicleControl.class); + if (control == null) { + vehicleControl = new VehicleControl(new BoxCollisionShape(Vector3f.UNIT_XYZ), 200); + vehicleControl.attachDebugShape(SceneApplication.getApplication().getAssetManager()); + rootNode.addControl(vehicleControl); + return true; + } else { + vehicleControl = control; + vehicleControl.attachDebugShape(SceneApplication.getApplication().getAssetManager()); + return false; + } + } + + public void createHullShapeFromSelected() { + if (selectedSpat == null) { + return; + } + try { + final Spatial node = selectedSpat.getLookup().lookup(Spatial.class); + Logger.getLogger(VehicleEditorController.class.getName()).log(Level.INFO, "Creating hull shape"); +// if (list.isEmpty()) { +// return; +// } + final VehicleControl control = vehicleControl; + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doCreateHullShapeFromSelected(control, node);// new LinkedList(list)); + return null; + } + }).get(); + currentFileObject.setModified(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doCreateHullShapeFromSelected(VehicleControl control, Spatial spat) { +// Logger.getLogger(VehicleEditorController.class.getName()).log(Level.INFO, "Merging Geometries"); +// Mesh mesh = new Mesh(); +// GeometryBatchFactory.mergeGeometries(list, mesh); +// control.setCollisionShape(new HullCollisionShape(list.get(0).getMesh())); + control.setCollisionShape(CollisionShapeFactory.createDynamicMeshShape(spat)); + refreshSelected(); + } + + public void applyWheelData(final int wheels, final SuspensionSettings settings) { + try { + final VehicleControl vehicleControl = this.vehicleControl; + SceneApplication.getApplication().enqueue(new Callable() { + + public Object call() throws Exception { + doApplyWheelData(vehicleControl, wheels, settings); + return null; + + } + }).get(); + currentFileObject.setModified(true); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + } + + public void doApplyWheelData(VehicleControl control, int wheels, SuspensionSettings settings) { + for (int i = 0; i < control.getNumWheels(); i++) { + VehicleWheel wheel = control.getWheel(i); + switch (wheels) { + case 0: + break; + case 1: + if (!wheel.isFrontWheel()) { + continue; + } + break; + case 2: + if (wheel.isFrontWheel()) { + continue; + } + break; + } + wheel.setRestLength(settings.getRestLength()); + wheel.setMaxSuspensionForce(settings.getMaxForce()); + wheel.setSuspensionStiffness(settings.getStiffness()); + wheel.setRollInfluence(settings.getRollInfluence()); + wheel.setWheelsDampingCompression(settings.getCompression()); + wheel.setWheelsDampingRelaxation(settings.getRelease()); +// wheel.setRadius(settings.getRadius()); + wheel.setFrictionSlip(settings.getFriction()); + } + } + + private void refreshSelected(final JmeSpatial spat) { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (spat != null) { + spat.refresh(false); + } + } + }); + + } + + private void refreshSelected() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (getSelectedSpat() != null) { + getSelectedSpat().refresh(false); + } + } + }); + + } + + private void refreshSelectedParent() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (getSelectedSpat() != null) { + ((JmeSpatial) getSelectedSpat().getParentNode()).refresh(false); + } + } + }); + + } + + private void refreshRoot() { + java.awt.EventQueue.invokeLater(new Runnable() { + + public void run() { + if (getJmeRootNode() != null) { + getJmeRootNode().refresh(true); + } + } + }); + + } + + public void cleanup() { + result.removeLookupListener(this); + result2.removeLookupListener(this); + final Node node = jmeRootNode.getLookup().lookup(Node.class); + toolController.cleanup(); + } + + public void resultChanged(LookupEvent ev) { + boolean cleared = false; + for (Iterator it = result.allInstances().iterator(); it.hasNext();) { + JmeSpatial jmeSpatial = it.next(); + selectedSpat = jmeSpatial; + Spatial spat = jmeSpatial.getLookup().lookup(Spatial.class); + toolController.updateSelection(spat); + Geometry geom = jmeSpatial.getLookup().lookup(Geometry.class); + if (geom != null) { + if (!cleared) { + list.clear(); + cleared = true; + } + Logger.getLogger(VehicleEditorController.class.getName()).log(Level.INFO, "adding:" + jmeSpatial.getName()); + list.add(geom); + } + } + } + + /** + * @return the toolsNode + */ + public Node getToolsNode() { + return toolsNode; + } + + /** + * @return the bulletState + */ + public BulletAppState getBulletState() { + return bulletState; + } + float steeringValue = 0; + float accelerationValue = 0; + + public void onAction(String binding, boolean value, float f) { + if (!testing) { + return; + } + if (binding.equals("VehicleEditor_Left")) { + if (value) { + steeringValue += .5f; + } else { + steeringValue += -.5f; + } + vehicleControl.steer(steeringValue); + } else if (binding.equals("VehicleEditor_Right")) { + if (value) { + steeringValue += -.5f; + } else { + steeringValue += .5f; + } + vehicleControl.steer(steeringValue); + } else if (binding.equals("VehicleEditor_Up")) { + if (value) { + accelerationValue += motorForce; + } else { + accelerationValue -= motorForce; + } + vehicleControl.accelerate(accelerationValue); + } else if (binding.equals("VehicleEditor_Down")) { + if (value) { + vehicleControl.brake(brakeForce); + } else { + vehicleControl.brake(0); + } + } else if (binding.equals("VehicleEditor_Reset")) { + if (value) { + System.out.println("Reset"); + vehicleControl.setPhysicsLocation(Vector3f.ZERO); + vehicleControl.setPhysicsRotation(new Matrix3f()); + vehicleControl.setLinearVelocity(Vector3f.ZERO); + vehicleControl.setAngularVelocity(Vector3f.ZERO); + vehicleControl.resetSuspension(); + } else { + } + } + } + + /** + * @return the motorForce + */ + public float getMotorForce() { + return motorForce; + } + + /** + * @param motorForce the motorForce to set + */ + public void setMotorForce(float motorForce) { + this.motorForce = motorForce; + } + + /** + * @return the brakeForce + */ + public float getBrakeForce() { + return brakeForce; + } + + /** + * @param brakeForce the brakeForce to set + */ + public void setBrakeForce(float brakeForce) { + this.brakeForce = brakeForce; + } +} diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon.png b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon.png new file mode 100644 index 000000000..a399abd39 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon.png differ diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon24.png b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon24.png new file mode 100644 index 000000000..3166f3e01 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon24.png differ diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon32.png b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon32.png new file mode 100644 index 000000000..643fb18b1 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/car-icon32.png differ diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/layer.xml b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/layer.xml new file mode 100644 index 000000000..553068344 --- /dev/null +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/layer.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/new_file.gif b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/new_file.gif new file mode 100644 index 000000000..08630f673 Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/new_file.gif differ diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/objects_039.gif b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/objects_039.gif new file mode 100644 index 000000000..7a08bf03e Binary files /dev/null and b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/objects_039.gif differ diff --git a/sdk/jme3-wavefront/build.xml b/sdk/jme3-wavefront/build.xml new file mode 100644 index 000000000..6ac3a204d --- /dev/null +++ b/sdk/jme3-wavefront/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.wavefront. + + diff --git a/sdk/jme3-wavefront/manifest.mf b/sdk/jme3-wavefront/manifest.mf new file mode 100644 index 000000000..93b4672be --- /dev/null +++ b/sdk/jme3-wavefront/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.wavefront/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Layer: com/jme3/gde/wavefront/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/wavefront/Bundle.properties + diff --git a/sdk/jme3-wavefront/nbproject/build-impl.xml b/sdk/jme3-wavefront/nbproject/build-impl.xml new file mode 100644 index 000000000..7d4569384 --- /dev/null +++ b/sdk/jme3-wavefront/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-wavefront/nbproject/genfiles.properties b/sdk/jme3-wavefront/nbproject/genfiles.properties new file mode 100644 index 000000000..a5d15d1d1 --- /dev/null +++ b/sdk/jme3-wavefront/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=45685247 +build.xml.script.CRC32=fa305471 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.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=45685247 +nbproject/build-impl.xml.script.CRC32=8239585b +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.1 diff --git a/sdk/jme3-wavefront/nbproject/project.properties b/sdk/jme3-wavefront/nbproject/project.properties new file mode 100644 index 000000000..570e13467 --- /dev/null +++ b/sdk/jme3-wavefront/nbproject/project.properties @@ -0,0 +1,3 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +spec.version.base=0.8.0 diff --git a/sdk/jme3-wavefront/nbproject/project.xml b/sdk/jme3-wavefront/nbproject/project.xml new file mode 100644 index 000000000..ccd8e6465 --- /dev/null +++ b/sdk/jme3-wavefront/nbproject/project.xml @@ -0,0 +1,114 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.wavefront + + + + com.jme3.gde.core + + + + 1 + 0.7 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.6 + + + + org.netbeans.api.progress + + + + 1 + 1.20.1 + + + + org.openide.awt + + + + 7.23.1 + + + + org.openide.dialogs + + + + 7.15.1 + + + + org.openide.filesystems + + + + 7.38.1 + + + + org.openide.loaders + + + + 7.16.1 + + + + org.openide.nodes + + + + 7.16.1 + + + + org.openide.text + + + + 6.30.1 + + + + org.openide.util + + + + 8.6.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.33.1 + + + + + com.jme3.gde.wavefront + + + + diff --git a/sdk/jme3-wavefront/nbproject/suite.properties b/sdk/jme3-wavefront/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-wavefront/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/Bundle.properties b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/Bundle.properties new file mode 100644 index 000000000..1b6b64cc3 --- /dev/null +++ b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/Bundle.properties @@ -0,0 +1,9 @@ +LBL_WaveFrontMaterial_loader_name=WaveFrontMaterial Files +LBL_WaveFrontOBJ_loader_name=WaveFrontOBJ Files +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + This plugin adds Wavefront OBJ support to jMonkeyPlatform. +OpenIDE-Module-Name=Wavefront OBJ Support +OpenIDE-Module-Short-Description=Adds Wavefront OBJ support to jMonkeyPlatform +Services/MIMEResolver/WaveFrontMaterialResolver.xml=WaveFrontMaterial Files +Services/MIMEResolver/WaveFrontOBJResolver.xml=WaveFrontOBJ Files diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/Computer_File_083.gif b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/Computer_File_083.gif new file mode 100644 index 000000000..7f524523f Binary files /dev/null and b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/Computer_File_083.gif differ diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/People_039.gif b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/People_039.gif new file mode 100644 index 000000000..041baa0bd Binary files /dev/null and b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/People_039.gif differ diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontMaterialDataObject.java b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontMaterialDataObject.java new file mode 100644 index 000000000..91f9c118e --- /dev/null +++ b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontMaterialDataObject.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.wavefront; + +import com.jme3.gde.core.assets.AssetDataObject; +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.text.DataEditorSupport; + +public class WaveFrontMaterialDataObject extends AssetDataObject { + + public WaveFrontMaterialDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + } + +} diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontMaterialResolver.xml b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontMaterialResolver.xml new file mode 100644 index 000000000..bbeabb9ab --- /dev/null +++ b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontMaterialResolver.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontOBJDataObject.java b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontOBJDataObject.java new file mode 100644 index 000000000..dd5dcd4a0 --- /dev/null +++ b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontOBJDataObject.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.wavefront; + +import com.jme3.gde.core.assets.SpatialAssetDataObject; +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.text.DataEditorSupport; + +public class WaveFrontOBJDataObject extends SpatialAssetDataObject { + + public WaveFrontOBJDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); + } + +} diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontOBJResolver.xml b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontOBJResolver.xml new file mode 100644 index 000000000..f11299e35 --- /dev/null +++ b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/WaveFrontOBJResolver.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/layer.xml b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/layer.xml new file mode 100644 index 000000000..10554773a --- /dev/null +++ b/sdk/jme3-wavefront/src/com/jme3/gde/wavefront/layer.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-welcome-screen/build.xml b/sdk/jme3-welcome-screen/build.xml new file mode 100644 index 000000000..5d871e8eb --- /dev/null +++ b/sdk/jme3-welcome-screen/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.jme3.gde.welcome. + + diff --git a/sdk/jme3-welcome-screen/catalog.xml b/sdk/jme3-welcome-screen/catalog.xml new file mode 100644 index 000000000..8e0ae8bcc --- /dev/null +++ b/sdk/jme3-welcome-screen/catalog.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/sdk/jme3-welcome-screen/manifest.mf b/sdk/jme3-welcome-screen/manifest.mf new file mode 100644 index 000000000..55e598a0f --- /dev/null +++ b/sdk/jme3-welcome-screen/manifest.mf @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.jme3.gde.welcome +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Install: com/jme3/gde/welcome/Installer.class +OpenIDE-Module-Layer: com/jme3/gde/welcome/layer.xml +OpenIDE-Module-Localizing-Bundle: com/jme3/gde/welcome/Bundle.properties + diff --git a/sdk/jme3-welcome-screen/nbproject/build-impl.xml b/sdk/jme3-welcome-screen/nbproject/build-impl.xml new file mode 100644 index 000000000..304e7fc2e --- /dev/null +++ b/sdk/jme3-welcome-screen/nbproject/build-impl.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-welcome-screen/nbproject/genfiles.properties b/sdk/jme3-welcome-screen/nbproject/genfiles.properties new file mode 100644 index 000000000..1ca1d7451 --- /dev/null +++ b/sdk/jme3-welcome-screen/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=dc88386f +build.xml.script.CRC32=e68af6b0 +build.xml.stylesheet.CRC32=a56c6a5b@1.42.2 +# 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=dc88386f +nbproject/build-impl.xml.script.CRC32=5d3b3399 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2 diff --git a/sdk/jme3-welcome-screen/nbproject/project.properties b/sdk/jme3-welcome-screen/nbproject/project.properties new file mode 100644 index 000000000..614f31204 --- /dev/null +++ b/sdk/jme3-welcome-screen/nbproject/project.properties @@ -0,0 +1,9 @@ +file.reference.nifty-default-controls-1.2.jar=release/modules/ext/nifty-default-controls-1.2.jar +file.reference.nifty-style-black-1.2.jar=release/modules/ext/nifty-style-black-1.2.jar +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.com +nbm.module.author=Normen Hansen, jiyarza +nbm.needs.restart=true +spec.version.base=0.6.0 diff --git a/sdk/jme3-welcome-screen/nbproject/project.xml b/sdk/jme3-welcome-screen/nbproject/project.xml new file mode 100644 index 000000000..ec76ce908 --- /dev/null +++ b/sdk/jme3-welcome-screen/nbproject/project.xml @@ -0,0 +1,106 @@ + + + org.netbeans.modules.apisupport.project + + + com.jme3.gde.welcome + + + + com.jme3.gde.core + + + + 1 + 0.10 + + + + com.jme3.gde.core.baselibs + + + + 1 + 0.7 + + + + com.jme3.gde.core.libraries + + + + 1 + 0.8 + + + + org.netbeans.modules.javahelp + + + + 1 + 2.16 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.30 + + + + org.openide.modules + + + + 7.16 + + + + org.openide.nodes + + + + 7.15 + + + + org.openide.util + + + + 8.5 + + + + org.openide.util.lookup + + + + 8.2 + + + + + + ext/nifty-style-black-1.2.jar + release/modules/ext/nifty-style-black-1.2.jar + + + ext/assets.jar + release/modules/ext/assets.jar + + + ext/nifty-default-controls-1.2.jar + release/modules/ext/nifty-default-controls-1.2.jar + + + ext/jme3-atmosphere-scattering.jar + release/modules/ext/jme3-atmosphere-scattering.jar + + + + diff --git a/sdk/jme3-welcome-screen/nbproject/suite.properties b/sdk/jme3-welcome-screen/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-welcome-screen/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-welcome-screen/release/modules/ext/assets.jar b/sdk/jme3-welcome-screen/release/modules/ext/assets.jar new file mode 100644 index 000000000..b70261df5 Binary files /dev/null and b/sdk/jme3-welcome-screen/release/modules/ext/assets.jar differ diff --git a/sdk/jme3-welcome-screen/release/modules/ext/jme3-atmosphere-scattering.jar b/sdk/jme3-welcome-screen/release/modules/ext/jme3-atmosphere-scattering.jar new file mode 100644 index 000000000..646ccf051 Binary files /dev/null and b/sdk/jme3-welcome-screen/release/modules/ext/jme3-atmosphere-scattering.jar differ diff --git a/sdk/jme3-welcome-screen/release/modules/ext/nifty-default-controls-1.2.jar b/sdk/jme3-welcome-screen/release/modules/ext/nifty-default-controls-1.2.jar new file mode 100644 index 000000000..7d87c5102 Binary files /dev/null and b/sdk/jme3-welcome-screen/release/modules/ext/nifty-default-controls-1.2.jar differ diff --git a/sdk/jme3-welcome-screen/release/modules/ext/nifty-style-black-1.2.jar b/sdk/jme3-welcome-screen/release/modules/ext/nifty-style-black-1.2.jar new file mode 100644 index 000000000..d1b9b4d6d Binary files /dev/null and b/sdk/jme3-welcome-screen/release/modules/ext/nifty-style-black-1.2.jar differ diff --git a/sdk/jme3-welcome-screen/src/Interface/WelcomeScreen.xml b/sdk/jme3-welcome-screen/src/Interface/WelcomeScreen.xml new file mode 100644 index 000000000..a2e041631 --- /dev/null +++ b/sdk/jme3-welcome-screen/src/Interface/WelcomeScreen.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-welcome-screen/src/Textures/f1-help.png b/sdk/jme3-welcome-screen/src/Textures/f1-help.png new file mode 100644 index 000000000..62ba4c8a0 Binary files /dev/null and b/sdk/jme3-welcome-screen/src/Textures/f1-help.png differ diff --git a/sdk/jme3-welcome-screen/src/Textures/jme-logo.png b/sdk/jme3-welcome-screen/src/Textures/jme-logo.png new file mode 100644 index 000000000..5491a6445 Binary files /dev/null and b/sdk/jme3-welcome-screen/src/Textures/jme-logo.png differ diff --git a/sdk/jme3-welcome-screen/src/Textures/monkey-logo-small.png b/sdk/jme3-welcome-screen/src/Textures/monkey-logo-small.png new file mode 100644 index 000000000..04fa4fd2b Binary files /dev/null and b/sdk/jme3-welcome-screen/src/Textures/monkey-logo-small.png differ diff --git a/sdk/jme3-welcome-screen/src/Textures/monkey-logo.png b/sdk/jme3-welcome-screen/src/Textures/monkey-logo.png new file mode 100644 index 000000000..17dbf490c Binary files /dev/null and b/sdk/jme3-welcome-screen/src/Textures/monkey-logo.png differ diff --git a/sdk/jme3-welcome-screen/src/Textures/updating.png b/sdk/jme3-welcome-screen/src/Textures/updating.png new file mode 100644 index 000000000..e17c97db3 Binary files /dev/null and b/sdk/jme3-welcome-screen/src/Textures/updating.png differ diff --git a/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/Bundle.properties b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/Bundle.properties new file mode 100644 index 000000000..f7f12515d --- /dev/null +++ b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/Bundle.properties @@ -0,0 +1,5 @@ +OpenIDE-Module-Display-Category=jMonkeyPlatform +OpenIDE-Module-Long-Description=\ + The jMonkeyPlatform Welcome Screen +OpenIDE-Module-Name=Welcome Screen +OpenIDE-Module-Short-Description=The jMonkeyPlatform Welcome Screen diff --git a/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/Installer.java b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/Installer.java new file mode 100644 index 000000000..abe9e04a2 --- /dev/null +++ b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/Installer.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.welcome; + +import org.openide.modules.ModuleInstall; +import org.openide.util.NbPreferences; + +/** + * Manages a module's lifecycle. Remember that an installer is optional and + * often not needed at all. + */ +public class Installer extends ModuleInstall { + + @Override + public void restored() { + if(!"true".equals(NbPreferences.forModule(Installer.class).get("NO_WELCOME_SCREEN", null))){ + new WelcomeScreen().startScreen(); + } + } +} diff --git a/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/WelcomeScreen.java b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/WelcomeScreen.java new file mode 100644 index 000000000..77835088c --- /dev/null +++ b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/WelcomeScreen.java @@ -0,0 +1,196 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.welcome; + +import atmosphere.Planet; +import atmosphere.PlanetRendererState; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.scene.PreviewRequest; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.SceneListener; +import com.jme3.gde.core.scene.SceneRequest; +import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility; +import com.jme3.light.DirectionalLight; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import com.jme3.niftygui.NiftyJmeDisplay; +import com.jme3.renderer.Caps; +import com.jme3.renderer.queue.RenderQueue.Bucket; +import com.jme3.renderer.queue.RenderQueue.ShadowMode; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.shape.Sphere; +import com.jme3.texture.Image; +import com.jme3.texture.TextureCubeMap; +import de.lessvoid.nifty.Nifty; +import de.lessvoid.nifty.controls.checkbox.CheckboxControl; +import de.lessvoid.nifty.screen.Screen; +import de.lessvoid.nifty.screen.ScreenController; +import java.net.URL; +import java.util.concurrent.Callable; +import org.netbeans.api.javahelp.Help; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.NbPreferences; + +/** + * + * @author normenhansen + */ +public class WelcomeScreen implements ScreenController { + + PlanetRendererState planetView; + SceneRequest request; + NiftyJmeDisplay niftyDisplay; + Nifty nifty; + Screen screen; + Spatial skyBox; + + public void startScreen() { + final Node rootNode = new Node("Welcome Screen"); + request = new SceneRequest(this, NodeUtility.createNode(rootNode), new ProjectAssetManager(null)); + request.setHelpCtx(new HelpCtx("com.jme3.gde.core.about")); + request.setWindowTitle("Welcome to jMonkeyPlatform"); + final WelcomeScreen welcomeScreen = this; + final DirectionalLight dirLight = new DirectionalLight(); + dirLight.setDirection(new Vector3f(.1f, 1, .1f).normalizeLocal()); + dirLight.setColor(ColorRGBA.Gray); + SceneApplication.getApplication().addSceneListener(new SceneListener() { + + @Override + public void sceneRequested(SceneRequest request) { + if (request.getRequester() == WelcomeScreen.this) { + //FIXME: planet location dont work? + if (SceneApplication.getApplication().getRenderer().getCaps().contains(Caps.OpenGL21)) { + planetView = new PlanetRendererState(new Planet(100f, new Vector3f(0, 0, 0)), dirLight); + SceneApplication.getApplication().getStateManager().attach(planetView); + } + SceneApplication.getApplication().getViewPort().getScenes().get(0).addLight(dirLight); + SceneApplication.getApplication().getCamera().setLocation(new Vector3f(0, 0, 400)); + setupSkyBox(); + niftyDisplay = new NiftyJmeDisplay(SceneApplication.getApplication().getAssetManager(), + SceneApplication.getApplication().getInputManager(), + SceneApplication.getApplication().getAudioRenderer(), + SceneApplication.getApplication().getGuiViewPort()); + nifty = niftyDisplay.getNifty(); + try { + nifty.fromXml("Interface/WelcomeScreen.xml", new URL("nbres:/Interface/WelcomeScreen.xml").openStream(), "start", welcomeScreen); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + + // attach the nifty display to the gui view port as a processor + SceneApplication.getApplication().getGuiViewPort().addProcessor(niftyDisplay); + } + } + + @Override + public boolean sceneClose(SceneRequest request) { + SceneApplication.getApplication().getViewPort().getScenes().get(0).removeLight(dirLight); + skyBox.removeFromParent(); + SceneApplication.getApplication().getGuiViewPort().removeProcessor(niftyDisplay); + nifty.exit(); + if (planetView != null) { + SceneApplication.getApplication().getStateManager().detach(planetView); + } + SceneApplication.getApplication().removeSceneListener(this); + return true; + } + + @Override + public void previewRequested(PreviewRequest request) { + } + }); + SceneApplication.getApplication().enqueue(new Callable() { + + @Override + public Object call() throws Exception { + SceneApplication.getApplication().requestScene(request); + return null; + } + }); + } + + private void setupSkyBox() { + Mesh sphere = new Sphere(32, 32, 10f); + sphere.setStatic(); + skyBox = new Geometry("SkyBox", sphere); + skyBox.setQueueBucket(Bucket.Sky); + skyBox.setShadowMode(ShadowMode.Off); + + Image cube = SceneApplication.getApplication().getAssetManager().loadTexture("Textures/blue-glow-1024.dds").getImage(); + TextureCubeMap cubemap = new TextureCubeMap(cube); + + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/Sky.j3md"); + mat.setBoolean("SphereMap", false); + mat.setTexture("Texture", cubemap); + mat.setVector3("NormalScale", new Vector3f(1, 1, 1)); + skyBox.setMaterial(mat); + + ((Node) SceneApplication.getApplication().getViewPort().getScenes().get(0)).attachChild(skyBox); + } + + public void setNoStartup() { + NbPreferences.forModule(Installer.class).put("NO_WELCOME_SCREEN", "true"); + } + + public void startUpdating() { + nifty.gotoScreen("updating"); + } + + public void startIntro() { + nifty.gotoScreen("intro"); + } + + public void startPlanet() { + nifty.gotoScreen("planet"); + } + + public void creatingProjects() { + Lookup.getDefault().lookup(Help.class).showHelp(new HelpCtx("sdk.project_creation")); + } + + public void importingModels() { + Lookup.getDefault().lookup(Help.class).showHelp(new HelpCtx("sdk.model_loader_and_viewer")); + } + + public void editingScenes() { + Lookup.getDefault().lookup(Help.class).showHelp(new HelpCtx("sdk.scene_composer")); + } + + public void editingCode() { + Lookup.getDefault().lookup(Help.class).showHelp(new HelpCtx("sdk.code_editor")); + } + + public void updatingJmp() { + Lookup.getDefault().lookup(Help.class).showHelp(new HelpCtx("com.jme3.gde.core.updating")); + } + + public void tutorials() { + Lookup.getDefault().lookup(Help.class).showHelp(new HelpCtx("jme3.beginner.hello_simpleapplication")); + } + + public void quit() { + if (screen.findNiftyControl("checkbox", CheckboxControl.class).isChecked()) { + setNoStartup(); + } + SceneApplication.getApplication().closeScene(request); + } + + public void bind(Nifty nifty, Screen screen) { + this.nifty = nifty; + this.screen = screen; + } + + public void onStartScreen() { + } + + public void onEndScreen() { + } +} diff --git a/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/layer.xml b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/layer.xml new file mode 100644 index 000000000..40f6e5e00 --- /dev/null +++ b/sdk/jme3-welcome-screen/src/com/jme3/gde/welcome/layer.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jmonkeyplatform.icns b/sdk/jmonkeyplatform.icns new file mode 100644 index 000000000..232a02efb Binary files /dev/null and b/sdk/jmonkeyplatform.icns differ diff --git a/sdk/jmonkeyplatform.png b/sdk/jmonkeyplatform.png new file mode 100644 index 000000000..f40cf4d3b Binary files /dev/null and b/sdk/jmonkeyplatform.png differ diff --git a/sdk/license-jme.txt b/sdk/license-jme.txt new file mode 100644 index 000000000..b6f20437b --- /dev/null +++ b/sdk/license-jme.txt @@ -0,0 +1,29 @@ +Copyright (c) 2003-2010 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. diff --git a/sdk/nbproject/build-impl.xml b/sdk/nbproject/build-impl.xml new file mode 100644 index 000000000..4cb1b270c --- /dev/null +++ b/sdk/nbproject/build-impl.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/nbproject/genfiles.properties b/sdk/nbproject/genfiles.properties new file mode 100644 index 000000000..95f4ba30b --- /dev/null +++ b/sdk/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=cbef27ca +build.xml.script.CRC32=7efad5da +build.xml.stylesheet.CRC32=531c622b@1.31.1.7 +# 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=cbef27ca +nbproject/build-impl.xml.script.CRC32=ce1d717c +nbproject/build-impl.xml.stylesheet.CRC32=183e6ef3@1.42.1 diff --git a/sdk/nbproject/platform.properties b/sdk/nbproject/platform.properties new file mode 100644 index 000000000..c2f6adec0 --- /dev/null +++ b/sdk/nbproject/platform.properties @@ -0,0 +1,83 @@ +cluster.path=\ + ${nbplatform.active.dir}/extra:\ + ${nbplatform.active.dir}/harness:\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/java:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + org.netbeans.libs.bugtracking,\ + org.netbeans.libs.bugzilla,\ + org.netbeans.libs.jsr223,\ + org.netbeans.libs.smack,\ + org.netbeans.libs.springframework,\ + org.netbeans.libs.swingx,\ + org.netbeans.modules.apisupport.apidocs,\ + org.netbeans.modules.bugtracking,\ + org.netbeans.modules.bugtracking.bridge,\ + org.netbeans.modules.bugzilla,\ + org.netbeans.modules.db,\ + org.netbeans.modules.db.core,\ + org.netbeans.modules.db.dataview,\ + org.netbeans.modules.db.drivers,\ + org.netbeans.modules.db.kit,\ + org.netbeans.modules.db.metadata.model,\ + org.netbeans.modules.db.mysql,\ + org.netbeans.modules.db.sql.editor,\ + org.netbeans.modules.db.sql.visualeditor,\ + org.netbeans.modules.dbapi,\ + org.netbeans.modules.dbschema,\ + org.netbeans.modules.derby,\ + org.netbeans.modules.form,\ + org.netbeans.modules.form.j2ee,\ + org.netbeans.modules.form.kit,\ + org.netbeans.modules.glassfish.common,\ + org.netbeans.modules.hibernate,\ + org.netbeans.modules.hibernatelib,\ + org.netbeans.modules.hudson,\ + org.netbeans.modules.hudson.ant,\ + org.netbeans.modules.hudson.maven,\ + org.netbeans.modules.hudson.mercurial,\ + org.netbeans.modules.hudson.subversion,\ + org.netbeans.modules.i18n.form,\ + org.netbeans.modules.j2ee.core.utilities,\ + org.netbeans.modules.j2ee.jpa.refactoring,\ + org.netbeans.modules.j2ee.jpa.verification,\ + org.netbeans.modules.j2ee.persistence,\ + org.netbeans.modules.j2ee.persistence.kit,\ + org.netbeans.modules.j2ee.toplinklib,\ + org.netbeans.modules.jellytools,\ + org.netbeans.modules.jellytools.ide,\ + org.netbeans.modules.jellytools.java,\ + org.netbeans.modules.jellytools.platform,\ + org.netbeans.modules.jemmy,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.maven,\ + org.netbeans.modules.maven.embedder,\ + org.netbeans.modules.maven.grammar,\ + org.netbeans.modules.maven.graph,\ + org.netbeans.modules.maven.hints,\ + org.netbeans.modules.maven.indexer,\ + org.netbeans.modules.maven.junit,\ + org.netbeans.modules.maven.kit,\ + org.netbeans.modules.maven.model,\ + org.netbeans.modules.maven.osgi,\ + org.netbeans.modules.maven.persistence,\ + org.netbeans.modules.maven.repository,\ + org.netbeans.modules.maven.search,\ + org.netbeans.modules.maven.spring,\ + org.netbeans.modules.server,\ + org.netbeans.modules.spellchecker,\ + org.netbeans.modules.spellchecker.bindings.htmlxml,\ + org.netbeans.modules.spellchecker.bindings.properties,\ + org.netbeans.modules.spellchecker.dictionary_en,\ + org.netbeans.modules.spellchecker.kit,\ + org.netbeans.modules.spring.beans,\ + org.netbeans.modules.swing.validation,\ + org.netbeans.modules.swingapp,\ + org.netbeans.modules.websvc.saas.codegen.java,\ + org.netbeans.modules.xml.wsdl.model,\ + org.openide.compat,\ + org.openide.options,\ + org.openide.util.enumerations +nbjdk.active=default +nbplatform.active=default diff --git a/sdk/nbproject/project.properties b/sdk/nbproject/project.properties new file mode 100644 index 000000000..10a31c6d3 --- /dev/null +++ b/sdk/nbproject/project.properties @@ -0,0 +1,69 @@ +app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif +app.name=jmonkeyplatform +app.title=jMonkeyPlatform +app.icon.icns=jmonkeyplatform.icns +app.version=0.6 Alpha 2 +branding.token=${app.name} +#jme-specific: +app.release.name=jME3_SDK_Alpha2 +app.release.version=0.6 Alpha 2 +auxiliary.org-netbeans-modules-apisupport-installer.license-file=license-jme.txt +auxiliary.org-netbeans-modules-apisupport-installer.os-linux=true +auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=true +auxiliary.org-netbeans-modules-apisupport-installer.os-solaris=false +auxiliary.org-netbeans-modules-apisupport-installer.os-windows=true +auxiliary.org-netbeans-modules-apisupport-installer.pack200-enabled=true +modules=\ + ${project.com.jme3.gde.core}:\ + ${project.com.jme3.gde.core.baselibs}:\ + ${project.com.jme3.gde.core.libraries}:\ + ${project.com.jme3.gde.templates}:\ + ${project.com.jme3.gde.project.baselibs}:\ + ${project.com.jme3.gde.project.libraries}:\ + ${project.com.jme3.gde.tests}:\ + ${project.com.jme3.gde.project.testdata}:\ + ${project.com.jme3.gde.ogrexml}:\ + ${project.com.jme3.gde.scenecomposer}:\ + ${project.com.jme3.gde.materials}:\ + ${project.com.jme3.gde.gui}:\ + ${project.com.jme3.gde.ogretools}:\ + ${project.com.jme3.gde.codepalette}:\ + ${project.com.jme3.gde.textureeditor}:\ + ${project.com.jme3.gde.core.updatecenters}:\ + ${project.com.jme3.gde.wavefront}:\ + ${project.com.jme3.gde.terraineditor}:\ + ${project.com.jme3.gde.assetpack}:\ + ${project.com.jme3.gde.modelimporter}:\ + ${project.com.jme3.gde.lwjgl.applet}:\ + ${project.com.jme3.gde.desktop.executables}:\ + ${project.com.jme3.gde.cinematics}:\ + ${project.com.jme3.gde.vehiclecreator}:\ + ${project.com.jme3.gde.welcome}:\ + ${project.com.jme3.gde.codecheck} +project.com.jme3.gde.codecheck=jme3-code-check +project.com.jme3.gde.desktop.executables=jme3-desktop-executables +project.com.jme3.gde.assetpack=jme3-assetpack-support +project.com.jme3.gde.cinematics=jme3-cinematics +project.com.jme3.gde.codepalette=jme3-codepalette +project.com.jme3.gde.core=jme3-core +project.com.jme3.gde.core.baselibs=jme3-core-baselibs +project.com.jme3.gde.core.libraries=jme3-core-libraries +project.com.jme3.gde.core.updatecenters=jme3-core-updatecenters +project.com.jme3.gde.gui=jme3-gui +project.com.jme3.gde.lwjgl.applet=jme3-lwjgl-applet +project.com.jme3.gde.materials=jme3-materialeditor +project.com.jme3.gde.modelimporter=jme3-model-importer +project.com.jme3.gde.ogretools=jme3-ogretools +project.com.jme3.gde.ogrexml=jme3-ogrexml +project.com.jme3.gde.project.baselibs=jme3-project-baselibs +project.com.jme3.gde.project.libraries=jme3-project-libraries +project.com.jme3.gde.project.testdata=jme3-project-testdata +project.com.jme3.gde.scenecomposer=jme3-scenecomposer +project.com.jme3.gde.templates=jme3-templates +project.com.jme3.gde.terraineditor=jme3-terrain-editor +project.com.jme3.gde.tests=jme3-tests-template +project.com.jme3.gde.textureeditor=jme3-texture-editor +project.com.jme3.gde.vehiclecreator=jme3-vehicle-creator +project.com.jme3.gde.wavefront=jme3-wavefront +project.com.jme3.gde.welcome=jme3-welcome-screen +run.args.extra=-J-Xmx512m -J-XX:PermSize=256m diff --git a/sdk/nbproject/project.xml b/sdk/nbproject/project.xml new file mode 100644 index 000000000..7209d62c6 --- /dev/null +++ b/sdk/nbproject/project.xml @@ -0,0 +1,9 @@ + + + org.netbeans.modules.apisupport.project.suite + + + jme-gde + + +