diff --git a/.gitignore b/.gitignore index 6b6f30e2d..8baaf9fc4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ /.gradle/ /.nb-gradle/private/ /.nb-gradle/profiles/private/ +/.idea/ /dist/ /build/ /netbeans/ +/sdk/jdks/local/ /jme3-core/build/ -/jme3-core/src/main/java/com/jme3/system/JmeVersion.java +/jme3-core/src/main/resources/com/jme3/system/version.properties /jme3-plugins/build/ /jme3-desktop/build/ /jme3-android-native/build/ @@ -80,6 +82,7 @@ /sdk/jme3-vehicle-creator/build/ /sdk/jme3-welcome-screen/build/ /sdk/jme3-glsl-support/build/ +/sdk/jme3-dark-laf/build/ /sdk/nbproject/private/ /sdk/jme3-scenecomposer/nbproject/private/ /sdk/jme3-core/nbproject/private/ @@ -125,6 +128,7 @@ *.so *.jnilib *.dylib +*.iml /sdk/dist/ !/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll !/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll @@ -132,3 +136,14 @@ !/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib !/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so !/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so +/.nb-gradle/ +/sdk/ant-jme/nbproject/private/ +/sdk/nbi/stub/ext/engine/nbproject/private/ +/sdk/nbi/stub/ext/components/products/jdk/nbproject/private/ +/sdk/nbi/stub/ext/components/products/blender/nbproject/private/ +/sdk/nbi/stub/ext/components/products/helloworld/nbproject/private/ +/sdk/BasicGameTemplate/nbproject/private/ +/sdk/nbi/stub/ext/components/products/jdk/build/ +/sdk/nbi/stub/ext/components/products/jdk/dist/ +/sdk/jme3-dark-laf/nbproject/private/ +jme3-lwjgl3/build/ diff --git a/.travis.yml b/.travis.yml index 71c3b576f..48e75d0b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,9 @@ cache: - gradle-cache - netbeans -branches: - only: - - master +# branches: +# only: +# - master notifications: slack: @@ -25,16 +25,26 @@ install: script: - ./gradlew check - ./gradlew createZipDistribution + - "[ $TRAVIS_BRANCH == 'master' ] && [ $TRAVIS_PULL_REQUEST == 'false' ] && ./gradlew uploadArchives || :" + +before_deploy: + - export RELEASE_DIST=$(ls build/distributions/*.zip) deploy: provider: releases api_key: - secure: "KbFiMt0a8FxUKvCJUYwikLYaqqGMn1p6k4OsXnGqwptQZEUIayabNLHeaD2kTNT3e6AY1ETwQLff/lB2LttmIo4g5NWW63g1K3A/HwgnhJwETengiProZ/Udl+ugPeDL/+ar43HUhFq4knBnzFKnEcHAThTPVqH/RMDvZf1UUYI=" - file: build/distributions/jME3.1.0_snapshot-github_2015-06-20.zip + secure: PuEsJd6juXBH29ByITW3ntSAyrwWs0IeFvXJ5Y2YlhojhSMtTwkoWeB6YmDJWP4fhzbajk4TQ1HlOX2IxJXSW/8ShOEIUlGXz9fHiST0dkSM+iRAUgC5enCLW5ITPTiem7eY9ZhS9miIam7ngce9jHNMh75PTzZrEJtezoALT9w= + file_glob: true + file: "${RELEASE_DIST}" skip_cleanup: true on: + repo: jMonkeyEngine/jmonkeyengine tags: true +before_install: + - git fetch --unshallow + - "[ $TRAVIS_PULL_REQUEST == 'false' ] && openssl aes-256-cbc -K $encrypted_a1949b55824a_key -iv $encrypted_a1949b55824a_iv -in private/www-updater.key.enc -out private/www-updater.key -d || :" + # before_install: # required libs for android build tools # sudo apt-get update diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ebecab28b..82ffeb4e8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,13 +16,6 @@ When you're ready to submit your code, just make a [pull request](https://help.g - When committing, always be sure to run an update before you commit. If there is a conflict between the latest revision and your patch after the update, then it is your responsibility to track down the update that caused the conflict and determine the issue (and fix it). In the case where the breaking commit has no thread linked (and one cannot be found in the forum), then the contributor should contact an administrator and wait for feedback before committing. - If your code is committed and it introduces new functionality, please edit the wiki accordingly. We can easily roll back to previous revisions, so just do your best; point us to it and we’ll see if it sticks! -**Note to Eclipse users:** The Eclipse [git client does not support https](http://hub.jmonkeyengine.org/forum/topic/problem-cloning-the-new-git-repository/#post-265594). The current workaround is to use the command line to clone the repository. -To import the local repository as a project follow these steps: - -1. Add a line 'apply plugin: eclipse' to your common.gradle file in the main project directory. -2. Navigate to the project directory in command line and execute command 'gradle eclipse'. This will load all the dependancies for eclipse. -3. In Eclipse, add the repository as an existing Java Project. - p.s. We will try hold ourselves to a [certain standard](http://www.defmacro.org/2013/04/03/issue-etiquette.html) when it comes to GitHub etiquette. If at any point we fail to uphold this standard, let us know. #### Core Contributors diff --git a/build.gradle b/build.gradle index 8e6790230..192bc32d3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,17 @@ import org.gradle.api.artifacts.* buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.1.0' - } + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.1.0' + } } apply plugin: 'base' +apply from: file('version.gradle') +apply from: file('upload.gradle') // This is applied to all sub projects subprojects { @@ -58,15 +60,14 @@ task libDist(dependsOn: subprojects.build) << { } } -task createZipDistribution(type:Zip,dependsOn:["dist","libDist"], description:"Package the nightly zip distribution"){ - archiveName "jME"+jmeVersion+"_"+jmeVersionTag+"_"+new Date().format("yyyy-MM-dd")+".zip" - - into("/") { - from {"./dist"} - } - into("/sources") { - from {"$buildDir/libDist/sources"} - } +task createZipDistribution(type:Zip,dependsOn:["dist","libDist"], description:"Package the nightly zip distribution"){ + archiveName "jME" + jmeFullVersion + ".zip" + into("/") { + from {"./dist"} + } + into("/sources") { + from {"$buildDir/libDist/sources"} + } } task copyLibs(type: Copy){ @@ -114,7 +115,12 @@ task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper gradleVersion = '2.2.1' } -String findNDK() { +ext { + ndkCommandPath = "" + ndkExists = false +} + +task configureAndroidNDK { def ndkBuildFile = "ndk-build" // if windows, use ndk-build.cmd instead if (System.properties['os.name'].toLowerCase().contains('windows')) { @@ -127,27 +133,13 @@ String findNDK() { if (System.env.ANDROID_NDK != null) { ndkBuildPath = System.env.ANDROID_NDK + File.separator + ndkBuildFile } + if (new File(ndkBuildPath).exists()) { - return ndkBuildPath - } else { - return null - } -} - -boolean checkNdkExists(String ndkCommandPath) { -// String ndkCommandPath = findNDK() - if (ndkCommandPath != null && new File(ndkCommandPath).exists()) { - return true - } else { - return false + ndkExists = true + ndkCommandPath = ndkBuildPath } } -ext { - ndkCommandPath = findNDK() - ndkExists = checkNdkExists(ndkCommandPath) -} - //class IncrementalReverseTask extends DefaultTask { // @InputDirectory // def File inputDir diff --git a/common.gradle b/common.gradle index 6af4c664f..237ee5e7f 100644 --- a/common.gradle +++ b/common.gradle @@ -4,10 +4,9 @@ apply plugin: 'java' apply plugin: 'maven' -apply plugin: 'maven-publish' -group = 'com.jme3' -version = jmeVersion + '-' + jmeVersionTag +group = 'com.jme3' +version = jmePomVersion sourceCompatibility = '1.6' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' @@ -19,9 +18,23 @@ repositories { } } +configurations { + deployerJars +} + dependencies { // Adding dependencies here will add the dependencies to each subproject. - testCompile group: 'junit', name: 'junit', version: '4.10' + testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'org.mockito', name: 'mockito-core', version: '2.0.28-beta' + testCompile group: 'org.easytesting', name: 'fest-assert-core', version: '2.0M10' + deployerJars "org.apache.maven.wagon:wagon-ssh:2.9" +} + +jar { + manifest { + attributes 'Implementation-Title': 'jMonkeyEngine', + 'Implementation-Version': jmeFullVersion + } } javadoc { @@ -56,41 +69,35 @@ artifacts { } } -publishing { - publications { - maven(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - - pom.withXml { - asNode().children().last() + { - resolveStrategy = Closure.DELEGATE_FIRST - name POM_NAME - description POM_DESCRIPTION - url POM_URL - scm { - url POM_SCM_URL - connection POM_SCM_CONNECTION - developerConnection POM_SCM_DEVELOPER_CONNECTION - } - licenses { - license { - name POM_LICENSE_NAME - url POM_LICENSE_URL - distribution POM_LICENSE_DISTRIBUTION - } - } +uploadArchives { + repositories.mavenDeployer { + configuration = configurations.deployerJars + + // disable this otherwise it will fill up the server with stale jars + uniqueVersion = false + + repository(url: "scp://updates.jmonkeyengine.org/var/www/updates/maven") { + authentication(userName: "www-updater", privateKey: "private/www-updater.key") + } + + pom.project { + name POM_NAME + description POM_DESCRIPTION + url POM_URL + scm { + url POM_SCM_URL + connection POM_SCM_CONNECTION + developerConnection POM_SCM_DEVELOPER_CONNECTION + } + licenses { + license { + name POM_LICENSE_NAME + url POM_LICENSE_URL + distribution POM_LICENSE_DISTRIBUTION } } } } - - repositories { - maven { - url "${rootProject.buildDir}/repo" // change to point to your repo, e.g. http://my.org/repo - } - } } task createFolders(description: 'Creates the source folders if they do not exist.') doLast { diff --git a/gradle.properties b/gradle.properties index a00139bdf..4380c31a0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,9 @@ jmeVersion = 3.1.0 # Version used for application and settings folder, no spaces! jmeMainVersion = 3.1 # Version addition pre-alpha-svn, Stable, Beta -jmeVersionTag = snapshot-github +jmeVersionTag = SNAPSHOT +# Increment this each time jmeVersionTag changes but jmeVersion stays the same +jmeVersionTagID = 0 # specify if JavaDoc should be built buildJavaDoc = true diff --git a/jme3-android/src/main/java/com/jme3/system/android/JmeAndroidSystem.java b/jme3-android/src/main/java/com/jme3/system/android/JmeAndroidSystem.java index bbbfaca7a..efaf4f3bb 100644 --- a/jme3-android/src/main/java/com/jme3/system/android/JmeAndroidSystem.java +++ b/jme3-android/src/main/java/com/jme3/system/android/JmeAndroidSystem.java @@ -122,9 +122,13 @@ public class JmeAndroidSystem extends JmeSystemDelegate { return Platform.Android_ARM6; } else if (arch.contains("v7")) { return Platform.Android_ARM7; + } else if (arch.contains("v8")) { + return Platform.Android_ARM8; } else { return Platform.Android_ARM5; // unknown ARM } + } else if (arch.contains("aarch")) { + return Platform.Android_ARM8; } else { return Platform.Android_Other; } diff --git a/jme3-blender/src/main/java/com/jme3/asset/BlenderKey.java b/jme3-blender/src/main/java/com/jme3/asset/BlenderKey.java index c412c07b3..3b72088ab 100644 --- a/jme3-blender/src/main/java/com/jme3/asset/BlenderKey.java +++ b/jme3-blender/src/main/java/com/jme3/asset/BlenderKey.java @@ -230,18 +230,22 @@ public class BlenderKey extends ModelKey { } /** + * Not used any more. * This method sets the asset root path. * @param assetRootPath * the assets root path */ + @Deprecated public void setAssetRootPath(String assetRootPath) { this.assetRootPath = assetRootPath; } /** + * Not used any more. * This method returns the asset root path. * @return the asset root path */ + @Deprecated public String getAssetRootPath() { return assetRootPath; } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java index e11101c14..142f757e2 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java @@ -31,8 +31,6 @@ */ package com.jme3.scene.plugins.blender; -import java.io.File; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -40,25 +38,17 @@ import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; -import com.jme3.animation.Animation; import com.jme3.asset.AssetNotFoundException; import com.jme3.asset.BlenderKey; import com.jme3.export.Savable; -import com.jme3.light.Light; import com.jme3.math.FastMath; import com.jme3.math.Quaternion; -import com.jme3.post.Filter; -import com.jme3.renderer.Camera; -import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType; import com.jme3.scene.plugins.blender.file.BlenderFileException; import com.jme3.scene.plugins.blender.file.Pointer; import com.jme3.scene.plugins.blender.file.Structure; -import com.jme3.scene.plugins.blender.materials.MaterialContext; -import com.jme3.scene.plugins.blender.meshes.TemporalMesh; import com.jme3.scene.plugins.blender.objects.Properties; -import com.jme3.texture.Texture; /** * A purpose of the helper class is to split calculation code into several classes. Each helper after use should be cleared because it can @@ -157,7 +147,6 @@ public abstract class AbstractBlenderHelper { * @throws BlenderFileException * and exception is throw when problems with reading a blend file occur */ - @SuppressWarnings("unchecked") protected Object loadLibrary(Structure id) throws BlenderFileException { Pointer pLib = (Pointer) id.getFieldValue("lib"); if (pLib.isNotNull()) { @@ -167,79 +156,21 @@ public abstract class AbstractBlenderHelper { String path = library.getFieldValue("filepath").toString(); if (!blenderContext.getLinkedFeatures().keySet().contains(path)) { - File file = new File(path); - List pathsToCheck = new ArrayList(); - String currentPath = file.getName(); - do { - pathsToCheck.add(currentPath); - file = file.getParentFile(); - if (file != null) { - currentPath = file.getName() + '/' + currentPath; - } - } while (file != null); - Spatial loadedAsset = null; - BlenderKey blenderKey = null; - for (String p : pathsToCheck) { - blenderKey = new BlenderKey(p); - blenderKey.setLoadUnlinkedAssets(true); - try { - loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey); - break;// break if no exception was thrown - } catch (AssetNotFoundException e) { - LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", p); - } + BlenderKey blenderKey = new BlenderKey(path); + blenderKey.setLoadUnlinkedAssets(true); + try { + loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey); + } catch (AssetNotFoundException e) { + LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", path); } - + if (loadedAsset != null) { Map> linkedData = loadedAsset.getUserData("linkedData"); + for (Entry> entry : linkedData.entrySet()) { String linkedDataFilePath = "this".equals(entry.getKey()) ? path : entry.getKey(); - - List scenes = (List) entry.getValue().get("scenes"); - for (Node scene : scenes) { - blenderContext.addLinkedFeature(linkedDataFilePath, "SC" + scene.getName(), scene); - } - List objects = (List) entry.getValue().get("objects"); - for (Node object : objects) { - blenderContext.addLinkedFeature(linkedDataFilePath, "OB" + object.getName(), object); - } - List meshes = (List) entry.getValue().get("meshes"); - for (TemporalMesh mesh : meshes) { - blenderContext.addLinkedFeature(linkedDataFilePath, "ME" + mesh.getName(), mesh); - } - List materials = (List) entry.getValue().get("materials"); - for (MaterialContext materialContext : materials) { - blenderContext.addLinkedFeature(linkedDataFilePath, "MA" + materialContext.getName(), materialContext); - } - List textures = (List) entry.getValue().get("textures"); - for (Texture texture : textures) { - blenderContext.addLinkedFeature(linkedDataFilePath, "TE" + texture.getName(), texture); - } - List images = (List) entry.getValue().get("images"); - for (Texture image : images) { - blenderContext.addLinkedFeature(linkedDataFilePath, "IM" + image.getName(), image); - } - List animations = (List) entry.getValue().get("animations"); - for (Animation animation : animations) { - blenderContext.addLinkedFeature(linkedDataFilePath, "AC" + animation.getName(), animation); - } - List cameras = (List) entry.getValue().get("cameras"); - for (Camera camera : cameras) { - blenderContext.addLinkedFeature(linkedDataFilePath, "CA" + camera.getName(), camera); - } - List lights = (List) entry.getValue().get("lights"); - for (Light light : lights) { - blenderContext.addLinkedFeature(linkedDataFilePath, "LA" + light.getName(), light); - } - Spatial sky = (Spatial) entry.getValue().get("sky"); - if (sky != null) { - blenderContext.addLinkedFeature(linkedDataFilePath, sky.getName(), sky); - } - List filters = (List) entry.getValue().get("filters"); - for (Filter filter : filters) { - blenderContext.addLinkedFeature(linkedDataFilePath, filter.getName(), filter); - } + blenderContext.getLinkedFeatures().put(linkedDataFilePath, entry.getValue()); } } else { LOGGER.log(Level.WARNING, "No features loaded from path: {0}.", path); diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderContext.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderContext.java index 6e8042b09..58114cf28 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderContext.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderContext.java @@ -44,8 +44,11 @@ import com.jme3.animation.Bone; import com.jme3.animation.Skeleton; import com.jme3.asset.AssetManager; import com.jme3.asset.BlenderKey; +import com.jme3.light.Light; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.renderer.Camera; import com.jme3.scene.Node; import com.jme3.scene.plugins.blender.animations.BlenderAction; import com.jme3.scene.plugins.blender.animations.BoneContext; @@ -55,6 +58,8 @@ import com.jme3.scene.plugins.blender.file.DnaBlockData; import com.jme3.scene.plugins.blender.file.FileBlockHeader; import com.jme3.scene.plugins.blender.file.FileBlockHeader.BlockCode; import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.materials.MaterialContext; +import com.jme3.texture.Texture; /** * The class that stores temporary data and manages it during loading the belnd @@ -77,7 +82,7 @@ public class BlenderContext { /** The asset manager. */ private AssetManager assetManager; /** The blocks read from the file. */ - protected List blocks; + protected List blocks = new ArrayList(); /** * A map containing the file block headers. The key is the old memory address. */ @@ -233,6 +238,7 @@ public class BlenderContext { * the block header to store */ public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) { + blocks.add(fileBlockHeader); fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader); List headers = fileBlockHeadersByCode.get(fileBlockHeader.getCode()); if (headers == null) { @@ -242,6 +248,13 @@ public class BlenderContext { headers.add(fileBlockHeader); } + /** + * @return the block headers + */ + public List getBlocks() { + return blocks; + } + /** * This method returns the block header of a given memory address. If the * header is not present then null is returned. @@ -332,22 +345,14 @@ public class BlenderContext { * The method adds linked content to the blender context. * @param blenderFilePath * the path of linked blender file - * @param featureName - * the linked feature name + * @param featureGroup + * the linked feature group (ie. scenes, materials, meshes, etc.) * @param feature * the linked feature */ - public void addLinkedFeature(String blenderFilePath, String featureName, Object feature) { - if (feature != null) { - Map linkedFeatures = this.linkedFeatures.get(blenderFilePath); - if (linkedFeatures == null) { - linkedFeatures = new HashMap(); - this.linkedFeatures.put(blenderFilePath, linkedFeatures); - } - if (!linkedFeatures.containsKey(featureName)) { - linkedFeatures.put(featureName, feature); - } - } + @Deprecated + public void addLinkedFeature(String blenderFilePath, String featureGroup, Object feature) { + // the method is deprecated and empty at the moment } /** @@ -358,9 +363,106 @@ public class BlenderContext { * the feature name we want to get * @return linked feature or null if none was found */ + @SuppressWarnings("unchecked") public Object getLinkedFeature(String blenderFilePath, String featureName) { Map linkedFeatures = this.linkedFeatures.get(blenderFilePath); - return linkedFeatures != null ? linkedFeatures.get(featureName) : null; + if(linkedFeatures != null) { + String namePrefix = (featureName.charAt(0) + "" + featureName.charAt(1)).toUpperCase(); + featureName = featureName.substring(2); + + if("SC".equals(namePrefix)) { + List scenes = (List) linkedFeatures.get("scenes"); + if(scenes != null) { + for(Node scene : scenes) { + if(featureName.equals(scene.getName())) { + return scene; + } + } + } + } else if("OB".equals(namePrefix)) { + List features = (List) linkedFeatures.get("objects"); + if(features != null) { + for(Node feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("ME".equals(namePrefix)) { + List features = (List) linkedFeatures.get("meshes"); + if(features != null) { + for(Node feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("MA".equals(namePrefix)) { + List features = (List) linkedFeatures.get("materials"); + if(features != null) { + for(MaterialContext feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("TX".equals(namePrefix)) { + List features = (List) linkedFeatures.get("textures"); + if(features != null) { + for(Texture feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("IM".equals(namePrefix)) { + List features = (List) linkedFeatures.get("images"); + if(features != null) { + for(Texture feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("AC".equals(namePrefix)) { + List features = (List) linkedFeatures.get("animations"); + if(features != null) { + for(Animation feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("CA".equals(namePrefix)) { + List features = (List) linkedFeatures.get("cameras"); + if(features != null) { + for(Camera feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("LA".equals(namePrefix)) { + List features = (List) linkedFeatures.get("lights"); + if(features != null) { + for(Light feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } else if("FI".equals(featureName)) { + List features = (List) linkedFeatures.get("lights"); + if(features != null) { + for(Filter feature : features) { + if(featureName.equals(feature.getName())) { + return feature; + } + } + } + } + } + return null; } /** @@ -659,4 +761,9 @@ public class BlenderContext { public static enum LoadedDataType { STRUCTURE, FEATURE, TEMPORAL_MESH; } + + @Override + public String toString() { + return blenderKey == null ? "BlenderContext [key = null]" : "BlenderContext [ key = " + blenderKey.toString() + " ]"; + } } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderLoader.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderLoader.java index dd0160063..f519cb9b5 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderLoader.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderLoader.java @@ -31,6 +31,9 @@ */ package com.jme3.scene.plugins.blender; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -41,9 +44,13 @@ import java.util.logging.Logger; import com.jme3.animation.Animation; import com.jme3.asset.AssetInfo; +import com.jme3.asset.AssetKey; import com.jme3.asset.AssetLoader; +import com.jme3.asset.AssetLocator; +import com.jme3.asset.AssetManager; import com.jme3.asset.BlenderKey; import com.jme3.asset.ModelKey; +import com.jme3.asset.StreamAssetInfo; import com.jme3.light.Light; import com.jme3.math.ColorRGBA; import com.jme3.post.Filter; @@ -81,22 +88,17 @@ import com.jme3.texture.Texture; public class BlenderLoader implements AssetLoader { private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName()); - /** The blocks read from the file. */ - protected List blocks; - /** The blender context. */ - protected BlenderContext blenderContext; - @Override public Spatial load(AssetInfo assetInfo) throws IOException { try { - this.setup(assetInfo); + BlenderContext blenderContext = this.setup(assetInfo); AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class); animationHelper.loadAnimations(); BlenderKey blenderKey = blenderContext.getBlenderKey(); LoadedFeatures loadedFeatures = new LoadedFeatures(); - for (FileBlockHeader block : blocks) { + for (FileBlockHeader block : blenderContext.getBlocks()) { switch (block.getCode()) { case BLOCK_OB00: ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); @@ -181,7 +183,7 @@ public class BlenderLoader implements AssetLoader { LOGGER.fine("Loading scenes and attaching them to the root object."); for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) { - loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext))); + loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext), blenderContext)); } LOGGER.fine("Creating the root node of the model and applying loaded nodes of the scene and loaded features to it."); @@ -220,7 +222,7 @@ public class BlenderLoader implements AssetLoader { } catch (Exception e) { throw new IOException("Unexpected importer exception occured: " + e.getLocalizedMessage(), e); } finally { - this.clear(); + this.clear(assetInfo); } } @@ -228,11 +230,12 @@ public class BlenderLoader implements AssetLoader { * This method converts the given structure to a scene node. * @param structure * structure of a scene + * @param blenderContext the blender context * @return scene's node * @throws BlenderFileException * an exception throw when problems with blender file occur */ - private Node toScene(Structure structure) throws BlenderFileException { + private Node toScene(Structure structure, BlenderContext blenderContext) throws BlenderFileException { ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); Node result = new Node(structure.getName()); List base = ((Structure) structure.getFieldValue("base")).evaluateListBase(); @@ -265,7 +268,7 @@ public class BlenderLoader implements AssetLoader { * @throws BlenderFileException * an exception is throw when something wrong happens with blender file */ - protected void setup(AssetInfo assetInfo) throws BlenderFileException { + protected BlenderContext setup(AssetInfo assetInfo) throws BlenderFileException { // registering loaders ModelKey modelKey = (ModelKey) assetInfo.getKey(); BlenderKey blenderKey; @@ -273,16 +276,15 @@ public class BlenderLoader implements AssetLoader { blenderKey = (BlenderKey) modelKey; } else { blenderKey = new BlenderKey(modelKey.getName()); - blenderKey.setAssetRootPath(modelKey.getFolder()); } // opening stream BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream()); // reading blocks - blocks = new ArrayList(); + List blocks = new ArrayList(); FileBlockHeader fileBlock; - blenderContext = new BlenderContext(); + BlenderContext blenderContext = new BlenderContext(); blenderContext.setBlenderVersion(inputStream.getVersionNumber()); blenderContext.setAssetManager(assetInfo.getManager()); blenderContext.setInputStream(inputStream); @@ -317,15 +319,19 @@ public class BlenderLoader implements AssetLoader { if (sceneFileBlock != null) { blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext)); } + + // adding locator for linked content + assetInfo.getManager().registerLocator(assetInfo.getKey().getName(), LinkedContentLocator.class); + + return blenderContext; } /** * The internal data is only needed during loading so make it unreachable so that the GC can release * that memory (which can be quite large amount). */ - protected void clear() { - blenderContext = null; - blocks = null; + protected void clear(AssetInfo assetInfo) { + assetInfo.getManager().unregisterLocator(assetInfo.getKey().getName(), LinkedContentLocator.class); } /** @@ -362,4 +368,50 @@ public class BlenderLoader implements AssetLoader { */ private ColorRGBA backgroundColor = ColorRGBA.Gray; } + + public static class LinkedContentLocator implements AssetLocator { + private File rootFolder; + + @Override + public void setRootPath(String rootPath) { + rootFolder = new File(rootPath); + if(rootFolder.isFile()) { + rootFolder = rootFolder.getParentFile(); + } + } + + @SuppressWarnings("rawtypes") + @Override + public AssetInfo locate(AssetManager manager, AssetKey key) { + if(key instanceof BlenderKey) { + File linkedAbsoluteFile = new File(key.getName()); + if(linkedAbsoluteFile.exists() && linkedAbsoluteFile.isFile()) { + try { + return new StreamAssetInfo(manager, key, new FileInputStream(linkedAbsoluteFile)); + } catch (FileNotFoundException e) { + return null; + } + } + + File linkedFileInCurrentAssetFolder = new File(rootFolder, linkedAbsoluteFile.getName()); + if(linkedFileInCurrentAssetFolder.exists() && linkedFileInCurrentAssetFolder.isFile()) { + try { + return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentAssetFolder)); + } catch (FileNotFoundException e) { + return null; + } + } + + File linkedFileInCurrentFolder = new File(".", linkedAbsoluteFile.getName()); + if(linkedFileInCurrentFolder.exists() && linkedFileInCurrentFolder.isFile()) { + try { + return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentFolder)); + } catch (FileNotFoundException e) { + return null; + } + } + } + return null; + } + } } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/Ipo.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/Ipo.java index f5113129f..6665752b7 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/Ipo.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/Ipo.java @@ -145,7 +145,7 @@ public class Ipo { float[] times = new float[framesAmount + 1]; Vector3f[] translations = new Vector3f[framesAmount + 1]; - float[] translation = new float[] { localTranslation.x, localTranslation.y, localTranslation.z }; + float[] translation = new float[3]; Quaternion[] rotations = new Quaternion[framesAmount + 1]; float[] quaternionRotation = new float[] { localRotation.getX(), localRotation.getY(), localRotation.getZ(), localRotation.getW(), }; float[] eulerRotation = localRotation.toAngles(null); @@ -165,6 +165,8 @@ public class Ipo { // calculating track data for (int frame = startFrame; frame <= stopFrame; ++frame) { + boolean translationSet = false; + translation[0] = translation[1] = translation[2] = 0; int index = frame - startFrame; times[index] = index * timeBetweenFrames;// start + (frame - 1) * timeBetweenFrames; for (int j = 0; j < bezierCurves.length; ++j) { @@ -173,15 +175,18 @@ public class Ipo { // LOCATION case AC_LOC_X: translation[0] = (float) value; + translationSet = true; break; case AC_LOC_Y: if (swapAxes && value != 0) { value = -value; } translation[yIndex] = (float) value; + translationSet = true; break; case AC_LOC_Z: translation[zIndex] = (float) value; + translationSet = true; break; // EULER ROTATION @@ -235,7 +240,11 @@ public class Ipo { LOGGER.log(Level.WARNING, "Unknown ipo curve type: {0}.", bezierCurves[j].getType()); } } - translations[index] = localRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2])); + if(translationSet) { + translations[index] = localRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2])); + } else { + translations[index] = new Vector3f(); + } if(boneContext != null) { if(boneContext.getBone().getParent() == null && boneContext.is(BoneContext.NO_LOCAL_LOCATION)) { diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java index 69e087a28..69c0a6f50 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java @@ -174,7 +174,7 @@ public class ConstraintDefinitionIK extends ConstraintDefinition { private static class BonesChain extends ArrayList { private static final long serialVersionUID = -1850524345643600718L; - private List bonesMatrices = new ArrayList(); + private List localBonesMatrices = new ArrayList(); public BonesChain(Bone bone, boolean useTail, int bonesAffected, Collection alteredOmas, BlenderContext blenderContext) { if (bone != null) { @@ -187,12 +187,21 @@ public class ConstraintDefinitionIK extends ConstraintDefinition { this.add(boneContext); alteredOmas.add(boneContext.getBoneOma()); - Space space = this.size() < bonesAffected ? Space.CONSTRAINT_SPACE_LOCAL : Space.CONSTRAINT_SPACE_WORLD; - Transform transform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), space); - bonesMatrices.add(new DTransform(transform).toMatrix()); + Transform transform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD); + localBonesMatrices.add(new DTransform(transform).toMatrix()); bone = bone.getParent(); } + + if(localBonesMatrices.size() > 0) { + // making the matrices describe the local transformation + Matrix parentWorldMatrix = localBonesMatrices.get(localBonesMatrices.size() - 1); + for(int i=localBonesMatrices.size() - 2;i>=0;--i) { + SimpleMatrix m = parentWorldMatrix.invert().mult(localBonesMatrices.get(i)); + parentWorldMatrix = localBonesMatrices.get(i); + localBonesMatrices.set(i, new Matrix(m)); + } + } } } @@ -211,16 +220,16 @@ public class ConstraintDefinitionIK extends ConstraintDefinition { SimpleMatrix m = parentWorldMatrix.invert().mult(boneMatrix); boneMatrix = new Matrix(m); } - bonesMatrices.set(index, boneMatrix); + localBonesMatrices.set(index, boneMatrix); } public Matrix getWorldMatrix(int index) { if (index == this.size() - 1) { - return new Matrix(bonesMatrices.get(this.size() - 1)); + return new Matrix(localBonesMatrices.get(this.size() - 1)); } SimpleMatrix result = this.getWorldMatrix(index + 1); - result = result.mult(bonesMatrices.get(index)); + result = result.mult(localBonesMatrices.get(index)); return new Matrix(result); } } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesTemporalMesh.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesTemporalMesh.java index 41117bf85..51a5aeb63 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesTemporalMesh.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesTemporalMesh.java @@ -180,8 +180,8 @@ public class CurvesTemporalMesh extends TemporalMesh { if (bevelObject != null && beziers.size() > 0) { this.append(this.applyBevelAndTaper(this, bevelObject, taperObject, blenderContext)); } else { - int originalVerticesAmount = vertices.size(); for (BezierLine bezierLine : beziers) { + int originalVerticesAmount = vertices.size(); vertices.add(bezierLine.vertices[0]); Vector3f v = bezierLine.vertices[1].subtract(bezierLine.vertices[0]).normalizeLocal(); float temp = v.x; diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/landscape/LandscapeHelper.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/landscape/LandscapeHelper.java index 8466d5cce..32160c13a 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/landscape/LandscapeHelper.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/landscape/LandscapeHelper.java @@ -81,6 +81,7 @@ public class LandscapeHelper extends AbstractBlenderHelper { if ((mode & MODE_MIST) != 0) { LOGGER.fine("Loading fog."); result = new FogFilter(); + result.setName("FIfog"); result.setFogColor(this.toBackgroundColor(worldStructure)); } return result; diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java index 51c7072b1..3b5a8eefb 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java @@ -168,9 +168,11 @@ public final class MaterialContext implements Savable { this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture()); List uvs = combinedTexture.getResultUVS(); - VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]); - uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()]))); - geometry.getMesh().setBuffer(uvCoordsBuffer); + if(uvs != null && uvs.size() > 0) { + VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]); + uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()]))); + geometry.getMesh().setBuffer(uvCoordsBuffer); + }//uvs might be null if the user assigned non existing UV coordinates group name to the mesh (this should be fixed in blender file) } else { LOGGER.log(Level.WARNING, "The texture could not be applied because JME only supports up to {0} different UV's.", TextureHelper.TEXCOORD_TYPES.length); } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java index d4ef0d1bc..da20d3fb4 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java @@ -46,7 +46,9 @@ import com.jme3.scene.plugins.blender.objects.Properties; */ public class TemporalMesh extends Geometry { private static final Logger LOGGER = Logger.getLogger(TemporalMesh.class.getName()); - + /** A minimum weight value. */ + private static final double MINIMUM_BONE_WEIGHT = FastMath.DBL_EPSILON; + /** The blender context. */ protected final BlenderContext blenderContext; @@ -530,7 +532,11 @@ public class TemporalMesh extends Geometry { for (Entry entry : boneIndexes.entrySet()) { if (vertexGroupsForVertex.containsKey(entry.getKey())) { float weight = vertexGroupsForVertex.get(entry.getKey()); - if (weight > 0) {// no need to use such weights + if (weight > MINIMUM_BONE_WEIGHT) { + // only values of weight greater than MINIMUM_BONE_WEIGHT are used + // if all non zero weights were used, and they were samm enough, problems with normalisation would occur + // because adding a very small value to 1.0 will give 1.0 + // so in order to avoid such errors, which can cause severe animation artifacts we need to use some minimum weight value boneBuffersForVertex.put(weight, entry.getValue()); } } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java index 2f3d12d60..2945b3413 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java @@ -2,6 +2,7 @@ package com.jme3.scene.plugins.blender.modifiers; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -129,13 +130,18 @@ public class SubdivisionSurfaceModifier extends Modifier { for (int i = 0; i < temporalMesh.getVertexCount(); ++i) { // finding adjacent edges that were created by dividing original edges List adjacentOriginalEdges = new ArrayList(); - for (Edge edge : temporalMesh.getAdjacentEdges(i)) { - if (verticesOnOriginalEdges.contains(edge.getFirstIndex()) || verticesOnOriginalEdges.contains(edge.getSecondIndex())) { - adjacentOriginalEdges.add(edge); + Collection adjacentEdges = temporalMesh.getAdjacentEdges(i); + if(adjacentEdges != null) {// this can be null if a vertex with index 'i' is not connected to any face nor edge + for (Edge edge : temporalMesh.getAdjacentEdges(i)) { + if (verticesOnOriginalEdges.contains(edge.getFirstIndex()) || verticesOnOriginalEdges.contains(edge.getSecondIndex())) { + adjacentOriginalEdges.add(edge); + } } + + creasePoints.add(new CreasePoint(i, boundaryVertices.contains(i), adjacentOriginalEdges, temporalMesh)); + } else { + creasePoints.add(null);//the count of crease points must be equal to vertex count; otherwise we'll get IndexOutofBoundsException later } - - creasePoints.add(new CreasePoint(i, boundaryVertices.contains(i), adjacentOriginalEdges, temporalMesh)); } Vector3f[] averageVert = new Vector3f[temporalMesh.getVertexCount()]; @@ -174,23 +180,25 @@ public class SubdivisionSurfaceModifier extends Modifier { } for (int i = 0; i < averageVert.length; ++i) { - Vector3f v = temporalMesh.getVertices().get(i); - averageVert[i].divideLocal(averageCount[i]); - - // computing translation vector - Vector3f t = averageVert[i].subtract(v); - if (!boundaryVertices.contains(i)) { - t.multLocal(4 / (float) averageCount[i]); - } - - // moving the vertex - v.addLocal(t); + if(averageVert[i] != null && averageCount[i] > 0) { + Vector3f v = temporalMesh.getVertices().get(i); + averageVert[i].divideLocal(averageCount[i]); + + // computing translation vector + Vector3f t = averageVert[i].subtract(v); + if (!boundaryVertices.contains(i)) { + t.multLocal(4 / (float) averageCount[i]); + } - // applying crease weight if neccessary - CreasePoint creasePoint = creasePoints.get(i); - if (creasePoint.getTarget() != null && creasePoint.getWeight() != 0) { - t = creasePoint.getTarget().subtractLocal(v).multLocal(creasePoint.getWeight()); + // moving the vertex v.addLocal(t); + + // applying crease weight if neccessary + CreasePoint creasePoint = creasePoints.get(i); + if (creasePoint.getTarget() != null && creasePoint.getWeight() != 0) { + t = creasePoint.getTarget().subtractLocal(v).multLocal(creasePoint.getWeight()); + v.addLocal(t); + } } } } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java index b7d6958ca..e406447eb 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java @@ -158,6 +158,9 @@ public class CombinedTexture { } else { resultUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName); } + if(resultUVS == null && LOGGER.isLoggable(Level.WARNING)) { + LOGGER.warning("The texture " + textureData.texture.getName() + " has assigned non existing UV coordinates group: " + textureData.uvCoordinatesName + "."); + } masterUserUVSetName = textureData.uvCoordinatesName; } else { TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH); diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp index d3e0ba719..f416e46b4 100644 --- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp +++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp @@ -51,6 +51,7 @@ extern "C" { jmeClasses::initJavaClasses(env); btTriangleIndexVertexArray* array = reinterpret_cast(meshId); btGImpactMeshShape* shape = new btGImpactMeshShape(array); + shape->updateBound(); return reinterpret_cast(shape); } diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp index 0d9621bb8..c9fef97cb 100644 --- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp +++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp @@ -811,39 +811,72 @@ extern "C" { /* * Class: com_jme3_bullet_objects_PhysicsRigidBody * Method: getAngularFactor - * Signature: (J)F + * Signature: (JLcom/jme3/math/Vector3f;)V */ - JNIEXPORT jfloat JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor - (JNIEnv *env, jobject object, jlong bodyId) { + JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor + (JNIEnv *env, jobject object, jlong bodyId, jobject factor) { btRigidBody* body = reinterpret_cast(bodyId); if (body == NULL) { jclass newExc = env->FindClass("java/lang/NullPointerException"); env->ThrowNew(newExc, "The native object does not exist."); - return 0; + return; } - return body->getAngularFactor().getX(); + jmeBulletUtil::convert(env, &body->getAngularFactor(), factor); } + /* * Class: com_jme3_bullet_objects_PhysicsRigidBody * Method: setAngularFactor - * Signature: (JF)V + * Signature: (JLcom/jme3/math/Vector3f;)V */ JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setAngularFactor - (JNIEnv *env, jobject object, jlong bodyId, jfloat value) { + (JNIEnv *env, jobject object, jlong bodyId, jobject factor) { btRigidBody* body = reinterpret_cast(bodyId); if (body == NULL) { jclass newExc = env->FindClass("java/lang/NullPointerException"); env->ThrowNew(newExc, "The native object does not exist."); return; } - btVector3 vec1 = btVector3(); - vec1.setX(value); - vec1.setY(value); - vec1.setZ(value); - body->setAngularFactor(vec1); + btVector3 vec = btVector3(); + jmeBulletUtil::convert(env, factor, &vec); + body->setAngularFactor(vec); } + /* + * Class: com_jme3_bullet_objects_PhysicsRigidBody + * Method: getLinearFactor + * Signature: (JLcom/jme3/math/Vector3f;)V + */ + JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getLinearFactor + (JNIEnv *env, jobject object, jlong bodyId, jobject factor) { + btRigidBody* body = reinterpret_cast(bodyId); + if (body == NULL) { + jclass newExc = env->FindClass("java/lang/NullPointerException"); + env->ThrowNew(newExc, "The native object does not exist."); + return; + } + jmeBulletUtil::convert(env, &body->getLinearFactor(), factor); + } + + /* + * Class: com_jme3_bullet_objects_PhysicsRigidBody + * Method: setLinearFactor + * Signature: (JLcom/jme3/math/Vector3f;)V + */ + JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setLinearFactor + (JNIEnv *env, jobject object, jlong bodyId, jobject factor) { + btRigidBody* body = reinterpret_cast(bodyId); + if (body == NULL) { + jclass newExc = env->FindClass("java/lang/NullPointerException"); + env->ThrowNew(newExc, "The native object does not exist."); + return; + } + btVector3 vec = btVector3(); + jmeBulletUtil::convert(env, factor, &vec); + body->setLinearFactor(vec); + } + #ifdef __cplusplus } #endif diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.h b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.h index aa09a620a..67ba9e609 100644 --- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.h +++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.h @@ -396,18 +396,35 @@ JNIEXPORT jfloat JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngula /* * Class: com_jme3_bullet_objects_PhysicsRigidBody * Method: getAngularFactor - * Signature: (J)F + * Signature: (JLcom/jme3/math/Vector3f;)V */ -JNIEXPORT jfloat JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor - (JNIEnv *, jobject, jlong); +JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor + (JNIEnv *, jobject, jlong, jobject); + /* * Class: com_jme3_bullet_objects_PhysicsRigidBody * Method: setAngularFactor - * Signature: (JF)V + * Signature: (JLcom/jme3/math/Vector3f;)V */ JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setAngularFactor - (JNIEnv *, jobject, jlong, jfloat); + (JNIEnv *, jobject, jlong, jobject); + +/* + * Class: com_jme3_bullet_objects_PhysicsRigidBody + * Method: getLinearFactor + * Signature: (JLcom/jme3/math/Vector3f;)V + */ +JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getLinearFactor + (JNIEnv *, jobject, jlong, jobject); + +/* + * Class: com_jme3_bullet_objects_PhysicsRigidBody + * Method: setLinearFactor + * Signature: (JLcom/jme3/math/Vector3f;)V + */ +JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setLinearFactor + (JNIEnv *, jobject, jlong, jobject); #ifdef __cplusplus } diff --git a/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp b/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp index 04b56a545..a51bcf833 100644 --- a/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp +++ b/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp @@ -351,7 +351,7 @@ void jmeBulletUtil::addResult(JNIEnv* env, jobject resultlist, btVector3* hitnor env->SetFloatField(singleresult, jmeClasses::PhysicsRay_hitfraction, m_hitFraction); env->SetObjectField(singleresult, jmeClasses::PhysicsRay_collisionObject, up1->javaCollisionObject); - env->CallVoidMethod(resultlist, jmeClasses::PhysicsRay_addmethod, singleresult); + env->CallBooleanMethod(resultlist, jmeClasses::PhysicsRay_addmethod, singleresult); if (env->ExceptionCheck()) { env->Throw(env->ExceptionOccurred()); return; @@ -371,7 +371,7 @@ void jmeBulletUtil::addSweepResult(JNIEnv* env, jobject resultlist, btVector3* h env->SetFloatField(singleresult, jmeClasses::PhysicsSweep_hitfraction, m_hitFraction); env->SetObjectField(singleresult, jmeClasses::PhysicsSweep_collisionObject, up1->javaCollisionObject); - env->CallVoidMethod(resultlist, jmeClasses::PhysicsSweep_addmethod, singleresult); + env->CallBooleanMethod(resultlist, jmeClasses::PhysicsSweep_addmethod, singleresult); if (env->ExceptionCheck()) { env->Throw(env->ExceptionOccurred()); return; diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CapsuleCollisionShape.java b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CapsuleCollisionShape.java index 525e2e281..00ccdf74e 100644 --- a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CapsuleCollisionShape.java +++ b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CapsuleCollisionShape.java @@ -93,7 +93,9 @@ public class CapsuleCollisionShape extends CollisionShape{ */ @Override public void setScale(Vector3f scale) { - Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "CapsuleCollisionShape cannot be scaled"); + if (!scale.equals(Vector3f.UNIT_XYZ)) { + Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "CapsuleCollisionShape cannot be scaled"); + } } public void write(JmeExporter ex) throws IOException { diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java b/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java index 40417c775..0342f4c77 100644 --- a/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java +++ b/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java @@ -627,16 +627,44 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { private native float getAngularSleepingThreshold(long objectId); public float getAngularFactor() { - return getAngularFactor(objectId); + return getAngularFactor(null).getX(); } - private native float getAngularFactor(long objectId); + public Vector3f getAngularFactor(Vector3f store) { + // doing like this prevent from breaking the API + if (store == null) { + store = new Vector3f(); + } + getAngularFactor(objectId, store); + return store; + } + + private native void getAngularFactor(long objectId, Vector3f vec); public void setAngularFactor(float factor) { - setAngularFactor(objectId, factor); + setAngularFactor(objectId, new Vector3f(factor, factor, factor)); + } + + public void setAngularFactor(Vector3f factor) { + setAngularFactor(objectId, factor); + } + + private native void setAngularFactor(long objectId, Vector3f factor); + + public Vector3f getLinearFactor() { + Vector3f vec = new Vector3f(); + getLinearFactor(objectId, vec); + return vec; } - private native void setAngularFactor(long objectId, float factor); + private native void getLinearFactor(long objectId, Vector3f vec); + + public void setLinearFactor(Vector3f factor) { + setLinearFactor(objectId, factor); + } + + private native void setLinearFactor(long objectId, Vector3f factor); + /** * do not use manually, joints are added automatically @@ -673,7 +701,13 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { capsule.write(getGravity(), "gravity", Vector3f.ZERO); capsule.write(getFriction(), "friction", 0.5f); capsule.write(getRestitution(), "restitution", 0); - capsule.write(getAngularFactor(), "angularFactor", 1); + Vector3f angularFactor = getAngularFactor(null); + if (angularFactor.x == angularFactor.y && angularFactor.y == angularFactor.z) { + capsule.write(getAngularFactor(), "angularFactor", 1); + } else { + capsule.write(getAngularFactor(null), "angularFactor", Vector3f.UNIT_XYZ); + capsule.write(getLinearFactor(), "linearFactor", Vector3f.UNIT_XYZ); + } capsule.write(kinematic, "kinematic", false); capsule.write(getLinearDamping(), "linearDamping", 0); @@ -703,7 +737,13 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { setKinematic(capsule.readBoolean("kinematic", false)); setRestitution(capsule.readFloat("restitution", 0)); - setAngularFactor(capsule.readFloat("angularFactor", 1)); + Vector3f angularFactor = (Vector3f) capsule.readSavable("angularFactor", null); + if(angularFactor == null) { + setAngularFactor(capsule.readFloat("angularFactor", 1)); + } else { + setAngularFactor(angularFactor); + setLinearFactor((Vector3f) capsule.readSavable("linearFactor", Vector3f.UNIT_XYZ.clone())); + } setDamping(capsule.readFloat("linearDamping", 0), capsule.readFloat("angularDamping", 0)); setSleepingThresholds(capsule.readFloat("linearSleepingThreshold", 0.8f), capsule.readFloat("angularSleepingThreshold", 1.0f)); setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0)); diff --git a/jme3-core/build.gradle b/jme3-core/build.gradle index bd699f52a..8d55c3e76 100644 --- a/jme3-core/build.gradle +++ b/jme3-core/build.gradle @@ -10,57 +10,30 @@ sourceSets { srcDir 'src/tools/java' } } -} - -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath 'org.ajoberstar:gradle-git:1.0.0-rc.1' + test { + java { + srcDir 'src/test/java' + } } } -import java.text.SimpleDateFormat -import org.ajoberstar.grgit.* - -task updateVersion << { - - def verfile = file('src/main/java/com/jme3/system/JmeVersion.java') - def jmeGitHash - def jmeShortGitHash - def jmeBuildDate - def jmeBranchName - - try { - def grgit = Grgit.open(project.file('.').parent) - jmeGitHash = grgit.head().id - jmeShortGitHash = grgit.head().abbreviatedId - jmeBuildDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) - jmeBranchName = grgit.branch.current.name - } catch (ex) { - // Failed to get repo info - logger.warn("Failed to get repository info: " + ex.message + ". " + \ - "Only partial build info will be generated.") - - jmeGitHash = "" - jmeShortGitHash = "" - jmeBuildDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) - jmeBranchName = "unknown" - } - - verfile.text = "\npackage com.jme3.system;\n\n" + - "/**\n * THIS IS AN AUTO-GENERATED FILE..\n * DO NOT MODIFY!\n */\n" + - "public class JmeVersion {\n" + - " public static final String BUILD_DATE = \"${jmeBuildDate}\";\n" + - " public static final String BRANCH_NAME = \"${jmeBranchName}\";\n" + - " public static final String GIT_HASH = \"${jmeGitHash}\";\n" + - " public static final String GIT_SHORT_HASH = \"${jmeShortGitHash}\";\n" + - " public static final String FULL_NAME = \"jMonkeyEngine ${jmeVersion} (${jmeVersionTag})\";\n" + - "}\n" +task updateVersionPropertiesFile << { + def verfile = file('src/main/resources/com/jme3/system/version.properties') + verfile.text = "# THIS IS AN AUTO-GENERATED FILE..\n" + + "# DO NOT MODIFY!\n" + + "build.date=${jmeBuildDate}\n" + + "git.revision=${jmeRevision}\n" + + "git.branch=${jmeBranchName}\n" + + "git.hash=${jmeGitHash}\n" + + "git.hash.short=${jmeShortGitHash}\n" + + "git.tag=${jmeGitTag}\n" + + "name.full=jMonkeyEngine ${jmeFullVersion}\n" + + "version.full=${jmeFullVersion}\n" + + "version.number=${jmeVersion}\n" + + "version.tag=${jmeVersionTag}" } -compileJava.dependsOn(updateVersion) +compileJava.dependsOn(updateVersionPropertiesFile) dependencies { } diff --git a/jme3-core/src/main/java/com/jme3/animation/Bone.java b/jme3-core/src/main/java/com/jme3/animation/Bone.java index a78b4b931..29c0f38e9 100644 --- a/jme3-core/src/main/java/com/jme3/animation/Bone.java +++ b/jme3-core/src/main/java/com/jme3/animation/Bone.java @@ -553,7 +553,6 @@ public final class Bone implements Savable { Vector3f translate = modelPos.add(rotate.mult(scale.mult(modelBindInversePos, tmp2), tmp2), tmp2); // Populating the matrix - outTransform.loadIdentity(); outTransform.setTransform(translate, scale, rotate.toRotationMatrix(tmp4)); } diff --git a/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java b/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java index 73e6d8df3..3bbd19c14 100644 --- a/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java +++ b/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java @@ -75,7 +75,7 @@ final class ImplHandler { this.assetManager = assetManager; } - protected static class ImplThreadLocal extends ThreadLocal { + protected static class ImplThreadLocal extends ThreadLocal { private final Class type; private final String path; @@ -112,9 +112,13 @@ final class ImplHandler { } @Override - protected Object initialValue(){ + protected T initialValue(){ try { - return type.newInstance(); + T obj = type.newInstance(); + if (path != null) { + ((AssetLocator)obj).setRootPath(path); + } + return obj; } catch (InstantiationException ex) { logger.log(Level.SEVERE,"Cannot create locator of type {0}, does" + " the class have an empty and publically accessible"+ @@ -169,14 +173,11 @@ final class ImplHandler { return null; } - for (ImplThreadLocal local : locatorsList){ - AssetLocator locator = (AssetLocator) local.get(); - if (local.getPath() != null){ - locator.setRootPath((String) local.getPath()); - } - AssetInfo info = locator.locate(assetManager, key); - if (info != null) + for (ImplThreadLocal local : locatorsList){ + AssetInfo info = local.get().locate(assetManager, key); + if (info != null) { return info; + } } return null; diff --git a/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java b/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java index 62f04018a..0878e23fa 100644 --- a/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java +++ b/jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java @@ -31,22 +31,20 @@ */ package com.jme3.audio.openal; -import com.jme3.audio.AudioSource.Status; import com.jme3.audio.*; +import com.jme3.audio.AudioSource.Status; import com.jme3.math.Vector3f; import com.jme3.util.BufferUtils; import com.jme3.util.NativeObjectManager; + import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; import static com.jme3.audio.openal.AL.*; -import static com.jme3.audio.openal.ALC.*; -import static com.jme3.audio.openal.EFX.*; public class ALAudioRenderer implements AudioRenderer, Runnable { @@ -102,16 +100,6 @@ public class ALAudioRenderer implements AudioRenderer, Runnable { return; } - String deviceName = alc.alcGetString(ALC.ALC_DEVICE_SPECIFIER); - - logger.log(Level.INFO, "Audio Device: {0}", deviceName); - logger.log(Level.INFO, "Audio Vendor: {0}", al.alGetString(AL_VENDOR)); - logger.log(Level.INFO, "Audio Renderer: {0}", al.alGetString(AL_RENDERER)); - logger.log(Level.INFO, "Audio Version: {0}", al.alGetString(AL_VERSION)); - - logger.log(Level.INFO, "ALC extensions: {0}", alc.alcGetString(ALC.ALC_EXTENSIONS)); - logger.log(Level.INFO, "AL extensions: {0}", al.alGetString(AL_EXTENSIONS)); - // Find maximum # of sources supported by this implementation ArrayList channelList = new ArrayList(); for (int i = 0; i < MAX_NUM_CHANNELS; i++) { @@ -131,7 +119,25 @@ public class ALAudioRenderer implements AudioRenderer, Runnable { ib = BufferUtils.createIntBuffer(channels.length); chanSrcs = new AudioSource[channels.length]; - logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length); + final String deviceName = alc.alcGetString(ALC.ALC_DEVICE_SPECIFIER); + + logger.log(Level.INFO, "Audio Renderer Information\n" + + " * Device: {0}\n" + + " * Vendor: {1}\n" + + " * Renderer: {2}\n" + + " * Version: {3}\n" + + " * Supported channels: {4}\n" + + " * ALC extensions: {5}\n" + + " * AL extensions: {6}", + new Object[]{ + deviceName, + al.alGetString(AL_VENDOR), + al.alGetString(AL_RENDERER), + al.alGetString(AL_VERSION), + channels.length, + alc.alcGetString(ALC.ALC_EXTENSIONS), + al.alGetString(AL_EXTENSIONS) + }); // Pause device is a feature used specifically on Android // where the application could be closed but still running, @@ -153,7 +159,7 @@ public class ALAudioRenderer implements AudioRenderer, Runnable { alc.alcGetInteger(EFX.ALC_MAX_AUXILIARY_SENDS, ib, 1); auxSends = ib.get(0); - logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends); + logger.log(Level.INFO, "Audio max auxiliary sends: {0}", auxSends); // create slot ib.position(0).limit(1); diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java index bdba19fe3..c087950a3 100644 --- a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java +++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java @@ -41,6 +41,7 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.*; import com.jme3.scene.Mesh; +import com.jme3.scene.Spatial; import com.jme3.util.TempVars; import java.io.IOException; import java.nio.FloatBuffer; @@ -313,7 +314,7 @@ public class BoundingBox extends BoundingVolume { transMatrix.absoluteLocal(); Vector3f scale = trans.getScale(); - vars.vect1.set(xExtent * scale.x, yExtent * scale.y, zExtent * scale.z); + vars.vect1.set(xExtent * FastMath.abs(scale.x), yExtent * FastMath.abs(scale.y), zExtent * FastMath.abs(scale.z)); transMatrix.mult(vars.vect1, vars.vect2); // Assign the biggest rotations after scales. box.xExtent = FastMath.abs(vars.vect2.getX()); @@ -593,18 +594,7 @@ public class BoundingBox extends BoundingVolume { * @see BoundingVolume#intersectsSphere(com.jme3.bounding.BoundingSphere) */ public boolean intersectsSphere(BoundingSphere bs) { - assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center); - - if (FastMath.abs(center.x - bs.center.x) < bs.getRadius() - + xExtent - && FastMath.abs(center.y - bs.center.y) < bs.getRadius() - + yExtent - && FastMath.abs(center.z - bs.center.z) < bs.getRadius() - + zExtent) { - return true; - } - - return false; + return bs.intersectsBoundingBox(this); } /** @@ -790,6 +780,7 @@ public class BoundingBox extends BoundingVolume { } } + @Override public int collideWith(Collidable other, CollisionResults results) { if (other instanceof Ray) { Ray ray = (Ray) other; @@ -802,6 +793,15 @@ public class BoundingBox extends BoundingVolume { return 1; } return 0; + } else if (other instanceof BoundingVolume) { + if (intersects((BoundingVolume) other)) { + CollisionResult r = new CollisionResult(); + results.addCollision(r); + return 1; + } + return 0; + } else if (other instanceof Spatial) { + return ((Spatial)other).collideWith(this, results); } else { throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName()); } @@ -818,6 +818,8 @@ public class BoundingBox extends BoundingVolume { return 1; } return 0; + } else if (other instanceof BoundingVolume) { + return intersects((BoundingVolume) other) ? 1 : 0; } else { throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName()); } diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java index d5dd56203..3137f2cbf 100644 --- a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java +++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java @@ -38,6 +38,7 @@ import com.jme3.collision.UnsupportedCollisionException; import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.math.*; +import com.jme3.scene.Spatial; import com.jme3.util.BufferUtils; import com.jme3.util.TempVars; import java.io.IOException; @@ -670,15 +671,7 @@ public class BoundingSphere extends BoundingVolume { * @see com.jme.bounding.BoundingVolume#intersectsSphere(com.jme.bounding.BoundingSphere) */ public boolean intersectsSphere(BoundingSphere bs) { - assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center); - - TempVars vars = TempVars.get(); - - Vector3f diff = center.subtract(bs.center, vars.vect1); - float rsum = getRadius() + bs.getRadius(); - boolean eq = (diff.dot(diff) <= rsum * rsum); - vars.release(); - return eq; + return Intersection.intersect(bs, center, radius); } /* @@ -687,18 +680,7 @@ public class BoundingSphere extends BoundingVolume { * @see com.jme.bounding.BoundingVolume#intersectsBoundingBox(com.jme.bounding.BoundingBox) */ public boolean intersectsBoundingBox(BoundingBox bb) { - assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center); - - if (FastMath.abs(bb.center.x - center.x) < getRadius() - + bb.xExtent - && FastMath.abs(bb.center.y - center.y) < getRadius() - + bb.yExtent - && FastMath.abs(bb.center.z - center.z) < getRadius() - + bb.zExtent) { - return true; - } - - return false; + return Intersection.intersect(bb, center, radius); } /* @@ -1013,17 +995,29 @@ public class BoundingSphere extends BoundingVolume { } else if (other instanceof Triangle){ Triangle t = (Triangle) other; return collideWithTri(t, results); + } else if (other instanceof BoundingVolume) { + if (intersects((BoundingVolume)other)) { + CollisionResult result = new CollisionResult(); + results.addCollision(result); + return 1; + } + return 0; + } else if (other instanceof Spatial) { + return ((Spatial)other).collideWith(this, results); } else { throw new UnsupportedCollisionException(); } } - @Override public int collideWith(Collidable other) { + @Override + public int collideWith(Collidable other) { if (other instanceof Ray) { Ray ray = (Ray) other; return collideWithRay(ray); } else if (other instanceof Triangle){ return super.collideWith(other); + } else if (other instanceof BoundingVolume) { + return intersects((BoundingVolume)other) ? 1 : 0; } else { throw new UnsupportedCollisionException(); } diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java index f9be2e573..4491fcedf 100644 --- a/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java +++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java @@ -327,12 +327,13 @@ public abstract class BoundingVolume implements Savable, Cloneable, Collidable { public int collideWith(Collidable other) { TempVars tempVars = TempVars.get(); - CollisionResults tempResults = tempVars.collisionResults; - tempResults.clear(); - int retval = collideWith(other, tempResults); - tempVars.release(); - return retval; + try { + CollisionResults tempResults = tempVars.collisionResults; + tempResults.clear(); + return collideWith(other, tempResults); + } finally { + tempVars.release(); + } } - } diff --git a/jme3-core/src/main/java/com/jme3/bounding/Intersection.java b/jme3-core/src/main/java/com/jme3/bounding/Intersection.java index 9deb62abc..c627e23e5 100644 --- a/jme3-core/src/main/java/com/jme3/bounding/Intersection.java +++ b/jme3-core/src/main/java/com/jme3/bounding/Intersection.java @@ -41,10 +41,56 @@ import static java.lang.Math.min; /** * This class includes some utility methods for computing intersection * between bounding volumes and triangles. + * * @author Kirill */ -public class Intersection { +public final class Intersection { + private Intersection() { + } + + public static boolean intersect(BoundingSphere sphere, Vector3f center, float radius) { + assert Vector3f.isValidVector(center) && Vector3f.isValidVector(sphere.center); + + TempVars vars = TempVars.get(); + try { + Vector3f diff = center.subtract(sphere.center, vars.vect1); + float rsum = sphere.getRadius() + radius; + return (diff.dot(diff) <= rsum * rsum); + } finally { + vars.release(); + } + } + + public static boolean intersect(BoundingBox bbox, Vector3f center, float radius) { + assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bbox.center); + + // Arvo's algorithm + float distSqr = radius * radius; + + float minX = bbox.center.x - bbox.xExtent; + float maxX = bbox.center.x + bbox.xExtent; + + float minY = bbox.center.y - bbox.yExtent; + float maxY = bbox.center.y + bbox.yExtent; + + float minZ = bbox.center.z - bbox.zExtent; + float maxZ = bbox.center.z + bbox.zExtent; + + if (center.x < minX) distSqr -= FastMath.sqr(center.x - minX); + else if (center.x > maxX) distSqr -= FastMath.sqr(center.x - maxX); + + + if (center.y < minY) distSqr -= FastMath.sqr(center.y - minY); + else if (center.y > maxY) distSqr -= FastMath.sqr(center.y - maxY); + + + if (center.z < minZ) distSqr -= FastMath.sqr(center.z - minZ); + else if (center.z > maxZ) distSqr -= FastMath.sqr(center.z - maxZ); + + return distSqr > 0; + } + private static final void findMinMax(float x0, float x1, float x2, Vector3f minMax) { minMax.set(x0, x0, 0); if (x1 < minMax.x) { diff --git a/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java b/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java index 373f6fac0..e610ef40b 100644 --- a/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java +++ b/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java @@ -702,7 +702,9 @@ public class Cinematic extends AbstractCinematicEvent implements AppState { dispose(); cinematicEvents.clear(); timeLine.clear(); - eventsData.clear(); + if (eventsData != null) { + eventsData.clear(); + } } /** diff --git a/jme3-core/src/main/java/com/jme3/cinematic/events/AnimationEvent.java b/jme3-core/src/main/java/com/jme3/cinematic/events/AnimationEvent.java index e8bfc5392..738b445b1 100644 --- a/jme3-core/src/main/java/com/jme3/cinematic/events/AnimationEvent.java +++ b/jme3-core/src/main/java/com/jme3/cinematic/events/AnimationEvent.java @@ -43,7 +43,7 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.scene.Spatial; import java.io.IOException; -import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; @@ -431,15 +431,17 @@ public class AnimationEvent extends AbstractCinematicEvent { @Override public void dispose() { super.dispose(); - Object o = cinematic.getEventData(MODEL_CHANNELS, model); - if (o != null) { - ArrayList list = (ArrayList) o; - list.remove(channel); - if (list.isEmpty()) { - cinematic.removeEventData(MODEL_CHANNELS, model); + if (cinematic != null) { + Object o = cinematic.getEventData(MODEL_CHANNELS, model); + if (o != null) { + Collection values = ((HashMap) o).values(); + while (values.remove(channel)); + if (values.isEmpty()) { + cinematic.removeEventData(MODEL_CHANNELS, model); + } } + cinematic = null; + channel = null; } - cinematic = null; - channel = null; } } diff --git a/jme3-core/src/main/java/com/jme3/collision/bih/BIHTree.java b/jme3-core/src/main/java/com/jme3/collision/bih/BIHTree.java index 38a633e96..5db94b409 100644 --- a/jme3-core/src/main/java/com/jme3/collision/bih/BIHTree.java +++ b/jme3-core/src/main/java/com/jme3/collision/bih/BIHTree.java @@ -48,6 +48,7 @@ import com.jme3.math.Vector3f; import com.jme3.scene.CollisionData; import com.jme3.scene.Mesh; import com.jme3.scene.Mesh.Mode; +import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.mesh.IndexBuffer; import com.jme3.scene.mesh.VirtualIndexBuffer; @@ -114,8 +115,13 @@ public class BIHTree implements CollisionData { bihSwapTmp = new float[9]; - FloatBuffer vb = (FloatBuffer) mesh.getBuffer(Type.Position).getData(); + VertexBuffer vBuffer = mesh.getBuffer(Type.Position); + if(vBuffer == null){ + throw new IllegalArgumentException("A mesh should at least contain a Position buffer"); + } IndexBuffer ib = mesh.getIndexBuffer(); + FloatBuffer vb = (FloatBuffer) vBuffer.getData(); + if (ib == null) { ib = new VirtualIndexBuffer(mesh.getVertexCount(), mesh.getMode()); } else if (mesh.getMode() != Mode.Triangles) { diff --git a/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java b/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java index 1edac967c..58dc87550 100644 --- a/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java +++ b/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java @@ -59,6 +59,7 @@ class BitmapTextPage extends Geometry { BitmapTextPage(BitmapFont font, boolean arrayBased, int page) { super("BitmapFont", new Mesh()); + setRequiresUpdates(false); setBatchHint(BatchHint.Never); if (font == null) { throw new IllegalArgumentException("font cannot be null."); diff --git a/jme3-core/src/main/java/com/jme3/input/DefaultJoystickAxis.java b/jme3-core/src/main/java/com/jme3/input/DefaultJoystickAxis.java index 954451145..7d7901911 100644 --- a/jme3-core/src/main/java/com/jme3/input/DefaultJoystickAxis.java +++ b/jme3-core/src/main/java/com/jme3/input/DefaultJoystickAxis.java @@ -72,8 +72,10 @@ public class DefaultJoystickAxis implements JoystickAxis { * @param negativeMapping The mapping to receive events when the axis is positive */ public void assignAxis(String positiveMapping, String negativeMapping){ - inputManager.addMapping(positiveMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, false)); - inputManager.addMapping(negativeMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, true)); + if (axisIndex != -1) { + inputManager.addMapping(positiveMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, false)); + inputManager.addMapping(negativeMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, true)); + } } /** @@ -133,6 +135,14 @@ public class DefaultJoystickAxis implements JoystickAxis { return deadZone; } + /** + * Sets/overrides the dead zone for this axis. This indicates that values + * within +/- deadZone should be ignored. + */ + public void setDeadZone( float f ) { + this.deadZone = f; + } + @Override public String toString(){ return "JoystickAxis[name=" + name + ", parent=" + parent.getName() + ", id=" + axisIndex diff --git a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java index d1dbe0aef..dd9f00dc1 100644 --- a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java +++ b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java @@ -277,8 +277,7 @@ public class FlyByCamera implements AnalogListener, ActionListener { } /** - * Registers the FlyByCamera to receive input events from the provided - * Dispatcher. + * Unregisters the FlyByCamera from the event Dispatcher. */ public void unregisterInput(){ diff --git a/jme3-core/src/main/java/com/jme3/input/InputManager.java b/jme3-core/src/main/java/com/jme3/input/InputManager.java index 660731a08..b21d225bb 100644 --- a/jme3-core/src/main/java/com/jme3/input/InputManager.java +++ b/jme3-core/src/main/java/com/jme3/input/InputManager.java @@ -39,6 +39,7 @@ import com.jme3.math.FastMath; import com.jme3.math.Vector2f; import com.jme3.util.IntMap; import com.jme3.util.IntMap.Entry; +import com.jme3.util.SafeArrayList; import java.util.ArrayList; import java.util.HashMap; import java.util.logging.Level; @@ -96,16 +97,15 @@ public class InputManager implements RawInputListener { private boolean eventsPermitted = false; private boolean mouseVisible = true; private boolean safeMode = false; - private float axisDeadZone = 0.05f; - private Vector2f cursorPos = new Vector2f(); + private float globalAxisDeadZone = 0.05f; + private final Vector2f cursorPos = new Vector2f(); private Joystick[] joysticks; private final IntMap> bindings = new IntMap>(); private final HashMap mappings = new HashMap(); private final IntMap pressedButtons = new IntMap(); private final IntMap axisValues = new IntMap(); - private ArrayList rawListeners = new ArrayList(); - private RawInputListener[] rawListenerArray = null; - private ArrayList inputQueue = new ArrayList(); + private final SafeArrayList rawListeners = new SafeArrayList(RawInputListener.class); + private final ArrayList inputQueue = new ArrayList(); private static class Mapping { @@ -248,8 +248,8 @@ public class InputManager implements RawInputListener { } } - private void invokeAnalogsAndActions(int hash, float value, boolean applyTpf) { - if (value < axisDeadZone) { + private void invokeAnalogsAndActions(int hash, float value, float effectiveDeadZone, boolean applyTpf) { + if (value < effectiveDeadZone) { invokeAnalogs(hash, value, !applyTpf); return; } @@ -287,12 +287,14 @@ public class InputManager implements RawInputListener { /** * Callback from RawInputListener. Do not use. */ + @Override public void beginInput() { } /** * Callback from RawInputListener. Do not use. */ + @Override public void endInput() { } @@ -304,17 +306,18 @@ public class InputManager implements RawInputListener { int joyId = evt.getJoyIndex(); int axis = evt.getAxisIndex(); float value = evt.getValue(); - if (value < axisDeadZone && value > -axisDeadZone) { + float effectiveDeadZone = Math.max(globalAxisDeadZone, evt.getAxis().getDeadZone()); + if (value < effectiveDeadZone && value > -effectiveDeadZone) { int hash1 = JoyAxisTrigger.joyAxisHash(joyId, axis, true); int hash2 = JoyAxisTrigger.joyAxisHash(joyId, axis, false); Float val1 = axisValues.get(hash1); Float val2 = axisValues.get(hash2); - if (val1 != null && val1.floatValue() > axisDeadZone) { + if (val1 != null && val1 > effectiveDeadZone) { invokeActions(hash1, false); } - if (val2 != null && val2.floatValue() > axisDeadZone) { + if (val2 != null && val2 > effectiveDeadZone) { invokeActions(hash2, false); } @@ -328,11 +331,11 @@ public class InputManager implements RawInputListener { // Clear the reverse direction's actions in case we // crossed center too quickly Float otherVal = axisValues.get(otherHash); - if (otherVal != null && otherVal.floatValue() > axisDeadZone) { + if (otherVal != null && otherVal > effectiveDeadZone) { invokeActions(otherHash, false); } - invokeAnalogsAndActions(hash, -value, true); + invokeAnalogsAndActions(hash, -value, effectiveDeadZone, true); axisValues.put(hash, -value); axisValues.remove(otherHash); } else { @@ -342,11 +345,11 @@ public class InputManager implements RawInputListener { // Clear the reverse direction's actions in case we // crossed center too quickly Float otherVal = axisValues.get(otherHash); - if (otherVal != null && otherVal.floatValue() > axisDeadZone) { + if (otherVal != null && otherVal > effectiveDeadZone) { invokeActions(otherHash, false); } - invokeAnalogsAndActions(hash, value, true); + invokeAnalogsAndActions(hash, value, effectiveDeadZone, true); axisValues.put(hash, value); axisValues.remove(otherHash); } @@ -355,6 +358,7 @@ public class InputManager implements RawInputListener { /** * Callback from RawInputListener. Do not use. */ + @Override public void onJoyAxisEvent(JoyAxisEvent evt) { if (!eventsPermitted) { throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time."); @@ -376,6 +380,7 @@ public class InputManager implements RawInputListener { /** * Callback from RawInputListener. Do not use. */ + @Override public void onJoyButtonEvent(JoyButtonEvent evt) { if (!eventsPermitted) { throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time."); @@ -391,15 +396,15 @@ public class InputManager implements RawInputListener { if (evt.getDX() != 0) { float val = Math.abs(evt.getDX()) / 1024f; - invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_X, evt.getDX() < 0), val, false); + invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_X, evt.getDX() < 0), val, globalAxisDeadZone, false); } if (evt.getDY() != 0) { float val = Math.abs(evt.getDY()) / 1024f; - invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_Y, evt.getDY() < 0), val, false); + invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_Y, evt.getDY() < 0), val, globalAxisDeadZone, false); } if (evt.getDeltaWheel() != 0) { float val = Math.abs(evt.getDeltaWheel()) / 100f; - invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_WHEEL, evt.getDeltaWheel() < 0), val, false); + invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_WHEEL, evt.getDeltaWheel() < 0), val, globalAxisDeadZone, false); } } @@ -419,6 +424,7 @@ public class InputManager implements RawInputListener { /** * Callback from RawInputListener. Do not use. */ + @Override public void onMouseMotionEvent(MouseMotionEvent evt) { if (!eventsPermitted) { throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time."); @@ -437,6 +443,7 @@ public class InputManager implements RawInputListener { /** * Callback from RawInputListener. Do not use. */ + @Override public void onMouseButtonEvent(MouseButtonEvent evt) { if (!eventsPermitted) { throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time."); @@ -459,6 +466,7 @@ public class InputManager implements RawInputListener { /** * Callback from RawInputListener. Do not use. */ + @Override public void onKeyEvent(KeyInputEvent evt) { if (!eventsPermitted) { throw new UnsupportedOperationException("KeyInput has raised an event at an illegal time."); @@ -477,7 +485,7 @@ public class InputManager implements RawInputListener { * @param deadZone the deadzone for joystick axes. */ public void setAxisDeadZone(float deadZone) { - this.axisDeadZone = deadZone; + this.globalAxisDeadZone = deadZone; } /** @@ -486,7 +494,7 @@ public class InputManager implements RawInputListener { * @return the deadzone for joystick axes. */ public float getAxisDeadZone() { - return axisDeadZone; + return globalAxisDeadZone; } /** @@ -721,7 +729,6 @@ public class InputManager implements RawInputListener { */ public void addRawInputListener(RawInputListener listener) { rawListeners.add(listener); - rawListenerArray = null; } /** @@ -734,7 +741,6 @@ public class InputManager implements RawInputListener { */ public void removeRawInputListener(RawInputListener listener) { rawListeners.remove(listener); - rawListenerArray = null; } /** @@ -744,13 +750,6 @@ public class InputManager implements RawInputListener { */ public void clearRawInputListeners() { rawListeners.clear(); - rawListenerArray = null; - } - - private RawInputListener[] getRawListenerArray() { - if (rawListenerArray == null) - rawListenerArray = rawListeners.toArray(new RawInputListener[rawListeners.size()]); - return rawListenerArray; } /** @@ -813,7 +812,7 @@ public class InputManager implements RawInputListener { private void processQueue() { int queueSize = inputQueue.size(); - RawInputListener[] array = getRawListenerArray(); + RawInputListener[] array = rawListeners.getArray(); for (RawInputListener listener : array) { listener.beginInput(); diff --git a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java index e147c6590..a2dc1cd38 100644 --- a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java +++ b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2012, 2015 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,8 @@ package com.jme3.light; import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingSphere; +import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; import com.jme3.scene.Spatial; @@ -49,11 +51,23 @@ import com.jme3.util.TempVars; */ public class AmbientLight extends Light { + public AmbientLight() { + } + + public AmbientLight(ColorRGBA color) { + super(color); + } + @Override public boolean intersectsBox(BoundingBox box, TempVars vars) { return true; } + @Override + public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) { + return true; + } + @Override public boolean intersectsFrustum(Camera camera, TempVars vars) { return true; @@ -61,6 +75,8 @@ public class AmbientLight extends Light { @Override public void computeLastDistance(Spatial owner) { + // ambient lights must always be before directional lights. + lastDistance = -2; } @Override diff --git a/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java b/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java index 81287279e..5d07e1a8d 100644 --- a/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java +++ b/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2014 jMonkeyEngine + * Copyright (c) 2009-2015 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ public final class DefaultLightFilter implements LightFilter { private Camera camera; private final HashSet processedLights = new HashSet(); + @Override public void setCamera(Camera camera) { this.camera = camera; for (Light light : processedLights) { @@ -51,6 +52,7 @@ public final class DefaultLightFilter implements LightFilter { } } + @Override public void filterLights(Geometry geometry, LightList filteredLightList) { TempVars vars = TempVars.get(); try { @@ -76,8 +78,9 @@ public final class DefaultLightFilter implements LightFilter { } } else if (bv instanceof BoundingSphere) { if (!Float.isInfinite( ((BoundingSphere)bv).getRadius() )) { - // Non-infinite bounding sphere... Not supported yet. - throw new UnsupportedOperationException("Only AABB supported for now"); + if (!light.intersectsSphere((BoundingSphere)bv, vars)) { + continue; + } } } diff --git a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java index c4258a67f..b1abb65cf 100644 --- a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java +++ b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2012, 2015 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,10 +32,12 @@ package com.jme3.light; import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingSphere; import com.jme3.export.InputCapsule; import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; +import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; import com.jme3.scene.Spatial; @@ -53,9 +55,35 @@ public class DirectionalLight extends Light { protected Vector3f direction = new Vector3f(0f, -1f, 0f); + /** + * Creates a DirectionalLight + */ + public DirectionalLight() { + } + + /** + * Creates a DirectionalLight with the given direction + * @param direction the light's direction + */ + public DirectionalLight(Vector3f direction) { + setDirection(direction); + } + + /** + * Creates a DirectionalLight with the given direction and the given color + * @param direction the light's direction + * @param color the light's color + */ + public DirectionalLight(Vector3f direction, ColorRGBA color) { + super(color); + setDirection(direction); + } + @Override public void computeLastDistance(Spatial owner) { - lastDistance = 0; // directional lights are always closest to their owner + // directional lights are after ambient lights + // but before all other lights. + lastDistance = -1; } /** @@ -77,7 +105,7 @@ public class DirectionalLight extends Light { * * @param dir the direction of the light. */ - public void setDirection(Vector3f dir){ + public final void setDirection(Vector3f dir){ direction.set(dir); if (!direction.isUnitVector()) { direction.normalizeLocal(); @@ -89,6 +117,11 @@ public class DirectionalLight extends Light { return true; } + @Override + public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) { + return true; + } + @Override public boolean intersectsFrustum(Camera camera, TempVars vars) { return true; diff --git a/jme3-core/src/main/java/com/jme3/light/Light.java b/jme3-core/src/main/java/com/jme3/light/Light.java index 4217e1b62..39a30980b 100644 --- a/jme3-core/src/main/java/com/jme3/light/Light.java +++ b/jme3-core/src/main/java/com/jme3/light/Light.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2012, 2015 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ package com.jme3.light; import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingSphere; import com.jme3.export.*; import com.jme3.math.ColorRGBA; import com.jme3.renderer.Camera; @@ -94,7 +95,7 @@ public abstract class Light implements Savable, Cloneable { } } - protected ColorRGBA color = new ColorRGBA(1f,1f,1f,1f); + protected ColorRGBA color = new ColorRGBA(ColorRGBA.White); /** * Used in LightList for caching the distance @@ -115,6 +116,13 @@ public abstract class Light implements Savable, Cloneable { boolean frustumCheckNeeded = true; boolean intersectsFrustum = false; + protected Light() { + } + + protected Light(ColorRGBA color) { + setColor(color); + } + /** * Returns the color of the light. * @@ -190,7 +198,21 @@ public abstract class Light implements Savable, Cloneable { public abstract boolean intersectsBox(BoundingBox box, TempVars vars); /** - * Determines if the lgiht intersects with the given camera frustum. + * Determines if the light intersects with the given bounding sphere. + *

+ * For non-local lights, such as {@link DirectionalLight directional lights}, + * {@link AmbientLight ambient lights}, or {@link PointLight point lights} + * without influence radius, this method should always return true. + * + * @param sphere The sphere to check intersection against. + * @param vars TempVars in case it is needed. + * + * @return True if the light intersects the sphere, false otherwise. + */ + public abstract boolean intersectsSphere(BoundingSphere sphere, TempVars vars); + + /** + * Determines if the light intersects with the given camera frustum. * * For non-local lights, such as {@link DirectionalLight directional lights}, * {@link AmbientLight ambient lights}, or {@link PointLight point lights} diff --git a/jme3-core/src/main/java/com/jme3/light/PointLight.java b/jme3-core/src/main/java/com/jme3/light/PointLight.java index 55a129275..4b5224c30 100644 --- a/jme3-core/src/main/java/com/jme3/light/PointLight.java +++ b/jme3-core/src/main/java/com/jme3/light/PointLight.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2012, 2015 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,12 +34,13 @@ package com.jme3.light; import com.jme3.bounding.BoundingBox; import com.jme3.bounding.BoundingSphere; import com.jme3.bounding.BoundingVolume; +import com.jme3.bounding.Intersection; import com.jme3.export.InputCapsule; import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.FastMath; -import com.jme3.math.Plane; +import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; import com.jme3.scene.Spatial; @@ -62,6 +63,52 @@ public class PointLight extends Light { protected float radius = 0; protected float invRadius = 0; + /** + * Creates a PointLight + */ + public PointLight() { + } + + /** + * Creates a PointLight at the given position + * @param position the position in world space + */ + public PointLight(Vector3f position) { + setPosition(position); + } + + /** + * Creates a PointLight at the given position and with the given color + * @param position the position in world space + * @param color the light color + */ + public PointLight(Vector3f position, ColorRGBA color) { + super(color); + setPosition(position); + } + + /** + * Creates a PointLight at the given position, with the given color and the + * given radius + * @param position the position in world space + * @param color the light color + * @param radius the light radius + */ + public PointLight(Vector3f position, ColorRGBA color, float radius) { + this(position, color); + setRadius(radius); + } + + /** + * Creates a PointLight at the given position, with the given radius + * @param position the position in world space + * @param radius the light radius + */ + public PointLight(Vector3f position, float radius) { + this(position); + setRadius(radius); + } + @Override public void computeLastDistance(Spatial owner) { if (owner.getWorldBound() != null) { @@ -88,7 +135,7 @@ public class PointLight extends Light { * * @param position the world space position of the light. */ - public void setPosition(Vector3f position) { + public final void setPosition(Vector3f position) { this.position.set(position); } @@ -115,13 +162,13 @@ public class PointLight extends Light { * * @throws IllegalArgumentException If radius is negative */ - public void setRadius(float radius) { + public final void setRadius(float radius) { if (radius < 0) { throw new IllegalArgumentException("Light radius cannot be negative"); } this.radius = radius; - if (radius != 0) { - this.invRadius = 1 / radius; + if (radius != 0f) { + this.invRadius = 1f / radius; } else { this.invRadius = 0; } @@ -146,9 +193,17 @@ public class PointLight extends Light { return true; } else { // Sphere v. box collision - return FastMath.abs(box.getCenter().x - position.x) < radius + box.getXExtent() - && FastMath.abs(box.getCenter().y - position.y) < radius + box.getYExtent() - && FastMath.abs(box.getCenter().z - position.z) < radius + box.getZExtent(); + return Intersection.intersect(box, position, radius); + } + } + + @Override + public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) { + if (this.radius == 0) { + return true; + } else { + // Sphere v. sphere collision + return Intersection.intersect(sphere, position, radius); } } diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java index e6443df7c..bc1335b5b 100644 --- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java +++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2012, 2015 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,8 +32,11 @@ package com.jme3.light; import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingSphere; import com.jme3.bounding.BoundingVolume; +import com.jme3.bounding.Intersection; import com.jme3.export.*; +import com.jme3.math.ColorRGBA; import com.jme3.math.FastMath; import com.jme3.math.Plane; import com.jme3.math.Vector3f; @@ -44,36 +47,121 @@ import java.io.IOException; /** * Represents a spot light. - * A spot light emmit a cone of light from a position and in a direction. - * It can be used to fake torch lights or car's lights. + * A spot light emits a cone of light from a position and in a direction. + * It can be used to fake torch lights or cars' lights. *

* In addition to a position and a direction, spot lights also have a range which * can be used to attenuate the influence of the light depending on the - * distance between the light and the effected object. + * distance between the light and the affected object. * Also the angle of the cone can be tweaked by changing the spot inner angle and the spot outer angle. - * the spot inner angle determin the cone of light where light has full influence. - * the spot outer angle determin the cone global cone of light of the spot light. - * the light intensity slowly decrease between the inner cone and the outer cone. + * the spot inner angle determines the cone of light where light has full influence. + * the spot outer angle determines the cone global cone of light of the spot light. + * the light intensity slowly decreases between the inner cone and the outer cone. * @author Nehon */ public class SpotLight extends Light { protected Vector3f position = new Vector3f(); - protected Vector3f direction = new Vector3f(0,-1,0); + protected Vector3f direction = new Vector3f(0, -1, 0); protected float spotInnerAngle = FastMath.QUARTER_PI / 8; protected float spotOuterAngle = FastMath.QUARTER_PI / 6; protected float spotRange = 100; protected float invSpotRange = 1f / 100; - protected float packedAngleCos=0; + protected float packedAngleCos = 0; protected float outerAngleCosSqr, outerAngleSinSqr; protected float outerAngleSinRcp, outerAngleSin, outerAngleCos; + /** + * Creates a SpotLight. + */ public SpotLight() { super(); computeAngleParameters(); } + /** + * Creates a SpotLight at the given position and with the given direction. + * @param position the position in world space. + * @param direction the direction of the light. + */ + public SpotLight(Vector3f position, Vector3f direction) { + this(); + setPosition(position); + setDirection(direction); + } + + /** + * Creates a SpotLight at the given position, with the given direction, and the + * given range. + * @param position the position in world space. + * @param direction the direction of the light. + * @param range the spot light range + */ + public SpotLight(Vector3f position, Vector3f direction, float range) { + this(); + setPosition(position); + setDirection(direction); + this.spotRange = range; + } + + /** + * Creates a SpotLight at the given position, with the given direction and + * the given color. + * @param position the position in world space. + * @param direction the direction of the light. + * @param color the light's color. + */ + public SpotLight(Vector3f position, Vector3f direction, ColorRGBA color) { + super(color); + computeAngleParameters(); + setPosition(position); + setDirection(direction); + } + + + /** + * Creates a SpotLight at the given position, with the given direction, + * the given range and the given color. + * @param position the position in world space. + * @param direction the direction of the light. + * @param range the spot light range + * @param color the light's color. + */ + public SpotLight(Vector3f position, Vector3f direction, float range, ColorRGBA color) { + super(color); + computeAngleParameters(); + setPosition(position); + setDirection(direction); + this.spotRange = range; + } + + /** + * Creates a SpotLight at the given position, with the given direction, + * the given color and the given inner and outer angles + * (controls the falloff of the light) + * + * @param position the position in world space. + * @param direction the direction of the light. + * @param range the spot light range + * @param color the light's color. + * @param innerAngle the inner angle of the spot light. + * @param outerAngle the outer angle of the spot light. + * + * @see SpotLight#setSpotInnerAngle(float) + * @see SpotLight#setSpotOuterAngle(float) + */ + public SpotLight(Vector3f position, Vector3f direction, float range, ColorRGBA color, float innerAngle, float outerAngle) { + super(color); + this.spotInnerAngle = innerAngle; + this.spotOuterAngle = outerAngle; + computeAngleParameters(); + setPosition(position); + setDirection(direction); + this.spotRange = range; + } + + private void computeAngleParameters() { float innerCos = FastMath.cos(spotInnerAngle); outerAngleCos = FastMath.cos(spotOuterAngle); @@ -102,9 +190,7 @@ public class SpotLight extends Light { if (this.spotRange > 0f) { // Check spot range first. // Sphere v. box collision - if (FastMath.abs(box.getCenter().x - position.x) >= spotRange + box.getXExtent() - || FastMath.abs(box.getCenter().y - position.y) >= spotRange + box.getYExtent() - || FastMath.abs(box.getCenter().z - position.z) >= spotRange + box.getZExtent()) { + if (!Intersection.intersect(box, position, spotRange)) { return false; } } @@ -140,8 +226,48 @@ public class SpotLight extends Light { } @Override - public boolean intersectsFrustum(Camera cam, TempVars vars) { + public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) { + if (this.spotRange > 0f) { + // Check spot range first. + // Sphere v. sphere collision + if (!Intersection.intersect(sphere, position, spotRange)) { + return false; + } + } + + float otherRadiusSquared = FastMath.sqr(sphere.getRadius()); + float otherRadius = sphere.getRadius(); + + // Check if sphere is within spot angle. + // Cone v. sphere collision. + Vector3f E = direction.mult(otherRadius * outerAngleSinRcp, vars.vect1); + Vector3f U = position.subtract(E, vars.vect2); + Vector3f D = sphere.getCenter().subtract(U, vars.vect3); + + float dsqr = D.dot(D); + float e = direction.dot(D); + + if (e > 0f && e * e >= dsqr * outerAngleCosSqr) { + D = sphere.getCenter().subtract(position, vars.vect3); + dsqr = D.dot(D); + e = -direction.dot(D); + + if (e > 0f && e * e >= dsqr * outerAngleSinSqr) { + return dsqr <= otherRadiusSquared; + } else { + return true; + } + } + return false; + } + + @Override + public boolean intersectsFrustum(Camera cam, TempVars vars) { + if (spotRange == 0) { + // The algorithm below does not support infinite spot range. + return true; + } Vector3f farPoint = vars.vect1.set(position).addLocal(vars.vect2.set(direction).multLocal(spotRange)); for (int i = 5; i >= 0; i--) { //check origin against the plane @@ -189,7 +315,7 @@ public class SpotLight extends Light { return direction; } - public void setDirection(Vector3f direction) { + public final void setDirection(Vector3f direction) { this.direction.set(direction); } @@ -197,7 +323,7 @@ public class SpotLight extends Light { return position; } - public void setPosition(Vector3f position) { + public final void setPosition(Vector3f position) { this.position.set(position); } diff --git a/jme3-core/src/main/java/com/jme3/material/Material.java b/jme3-core/src/main/java/com/jme3/material/Material.java index 5f0ab8f91..44bfb73f5 100644 --- a/jme3-core/src/main/java/com/jme3/material/Material.java +++ b/jme3-core/src/main/java/com/jme3/material/Material.java @@ -69,7 +69,7 @@ import java.util.logging.Logger; * Setting the parameters can modify the behavior of a * shader. *

- * + * * @author Kirill Vainer */ public class Material implements CloneableSmartAsset, Cloneable, Savable { @@ -146,7 +146,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { public String getName() { return name; } - + /** * This method sets the name of the material. * The name is not the same as the asset name. @@ -222,11 +222,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { } /** - * Compares two materials and returns true if they are equal. + * Compares two materials and returns true if they are equal. * This methods compare definition, parameters, additional render states. - * Since materials are mutable objects, implementing equals() properly is not possible, + * Since materials are mutable objects, implementing equals() properly is not possible, * hence the name contentEquals(). - * + * * @param otherObj the material to compare to this material * @return true if the materials are equal. */ @@ -234,15 +234,15 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { if (!(otherObj instanceof Material)) { return false; } - + Material other = (Material) otherObj; - + // Early exit if the material are the same object if (this == other) { return true; } - // Check material definition + // Check material definition if (this.getMaterialDef() != other.getMaterialDef()) { return false; } @@ -251,12 +251,12 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { if (this.paramValues.size() != other.paramValues.size()) { return false; } - + // Checking technique if (this.technique != null || other.technique != null) { // Techniques are considered equal if their names are the same - // E.g. if user chose custom technique for one material but - // uses default technique for other material, the materials + // E.g. if user chose custom technique for one material but + // uses default technique for other material, the materials // are not equal. String thisDefName = this.technique != null ? this.technique.getDef().getName() : "Default"; String otherDefName = other.technique != null ? other.technique.getDef().getName() : "Default"; @@ -290,7 +290,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { return false; } } - + return true; } @@ -305,7 +305,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { hash = 29 * hash + (this.additionalState != null ? this.additionalState.contentHashCode() : 0); return hash; } - + /** * Returns the currently active technique. *

@@ -436,7 +436,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { public Collection getParams() { return paramValues.values(); } - + /** * Returns the ListMap of all parameters set on this material. * @@ -473,7 +473,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { */ public void setParam(String name, VarType type, Object value) { checkSetParam(type, name); - + if (type.isTextureType()) { setTextureParam(name, type, (Texture)value); } else { @@ -501,7 +501,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { if (matParam == null) { return; } - + paramValues.remove(name); if (matParam instanceof MatParamTexture) { int texUnit = ((MatParamTexture) matParam).getUnit(); @@ -728,7 +728,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { renderer.renderMesh(mesh, lodLevel, 1, null); } } - + /** * Uploads the lights in the light list as two uniform arrays.

* *

@@ -747,30 +747,30 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { return 0; } - Uniform lightData = shader.getUniform("g_LightData"); - lightData.setVector4Length(numLights * 3);//8 lights * max 3 + Uniform lightData = shader.getUniform("g_LightData"); + lightData.setVector4Length(numLights * 3);//8 lights * max 3 Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); - - if (startIndex != 0) { + + if (startIndex != 0) { // apply additive blending for 2nd and future passes rm.getRenderer().applyRenderState(additiveLight); - ambientColor.setValue(VarType.Vector4, ColorRGBA.Black); + ambientColor.setValue(VarType.Vector4, ColorRGBA.Black); }else{ ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList,true)); } - + int lightDataIndex = 0; TempVars vars = TempVars.get(); Vector4f tmpVec = vars.vect4f1; int curIndex; int endIndex = numLights + startIndex; for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) { - - - Light l = lightList.get(curIndex); + + + Light l = lightList.get(curIndex); if(l.getType() == Light.Type.Ambient){ - endIndex++; + endIndex++; continue; } ColorRGBA color = l.getColor(); @@ -781,14 +781,14 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { l.getType().getId(), lightDataIndex); lightDataIndex++; - + switch (l.getType()) { case Directional: DirectionalLight dl = (DirectionalLight) l; - Vector3f dir = dl.getDirection(); + Vector3f dir = dl.getDirection(); //Data directly sent in view space to avoid a matrix mult for each pixel tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f); - rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); + rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); // tmpVec.divideLocal(tmpVec.w); // tmpVec.normalizeLocal(); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex); @@ -802,7 +802,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { Vector3f pos = pl.getPosition(); float invRadius = pl.getInvRadius(); tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f); - rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); + rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); //tmpVec.divideLocal(tmpVec.w); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex); lightDataIndex++; @@ -810,37 +810,37 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { lightData.setVector4InArray(0,0,0,0, lightDataIndex); lightDataIndex++; break; - case Spot: + case Spot: SpotLight sl = (SpotLight) l; Vector3f pos2 = sl.getPosition(); Vector3f dir2 = sl.getDirection(); float invRange = sl.getInvSpotRange(); float spotAngleCos = sl.getPackedAngleCos(); tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f); - rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); + rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); // tmpVec.divideLocal(tmpVec.w); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex); lightDataIndex++; - + //We transform the spot direction in view space here to save 5 varying later in the lighting shader //one vec4 less and a vec4 that becomes a vec3 //the downside is that spotAngleCos decoding happens now in the frag shader. tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f); - rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); + rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); tmpVec.normalizeLocal(); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex); lightDataIndex++; - break; + break; default: throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); } } - vars.release(); + vars.release(); //Padding of unsued buffer space while(lightDataIndex < numLights * 3) { lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex); - lightDataIndex++; - } + lightDataIndex++; + } return curIndex; } @@ -887,10 +887,10 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { case Directional: DirectionalLight dl = (DirectionalLight) l; Vector3f dir = dl.getDirection(); - //FIXME : there is an inconstency here due to backward + //FIXME : there is an inconstency here due to backward //compatibility of the lighting shader. - //The directional light direction is passed in the - //LightPosition uniform. The lighting shader needs to be + //The directional light direction is passed in the + //LightPosition uniform. The lighting shader needs to be //reworked though in order to fix this. tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); lightPos.setValue(VarType.Vector4, tmpLightPosition); @@ -987,11 +987,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { for (TechniqueDef techDef : techDefs) { if (rendererCaps.containsAll(techDef.getRequiredCaps())) { // use the first one that supports all the caps - tech = new Technique(this, techDef); + tech = new Technique(this, techDef); techniques.put(name, tech); if(tech.getDef().getLightMode() == renderManager.getPreferredLightMode() || tech.getDef().getLightMode() == LightMode.Disable){ - break; + break; } } lastTech = techDef; @@ -1078,7 +1078,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { Uniform u = uniforms.getValue(i); if (!u.isSetByCurrentMaterial()) { if (u.getName().charAt(0) != 'g') { - // Don't reset world globals! + // Don't reset world globals! // The benefits gained from this are very minimal // and cause lots of matrix -> FloatBuffer conversions. u.clearValue(); @@ -1093,21 +1093,21 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { *

* The material is rendered as follows: *

    - *
  • Determine which technique to use to render the material - - * either what the user selected via - * {@link #selectTechnique(java.lang.String, com.jme3.renderer.RenderManager) - * Material.selectTechnique()}, - * or the first default technique that the renderer supports + *
  • Determine which technique to use to render the material - + * either what the user selected via + * {@link #selectTechnique(java.lang.String, com.jme3.renderer.RenderManager) + * Material.selectTechnique()}, + * or the first default technique that the renderer supports * (based on the technique's {@link TechniqueDef#getRequiredCaps() requested rendering capabilities})
      - *
    • If the technique has been changed since the last frame, then it is notified via - * {@link Technique#makeCurrent(com.jme3.asset.AssetManager, boolean, java.util.EnumSet) - * Technique.makeCurrent()}. - * If the technique wants to use a shader to render the model, it should load it at this part - - * the shader should have all the proper defines as declared in the technique definition, - * including those that are bound to material parameters. - * The technique can re-use the shader from the last frame if + *
    • If the technique has been changed since the last frame, then it is notified via + * {@link Technique#makeCurrent(com.jme3.asset.AssetManager, boolean, java.util.EnumSet) + * Technique.makeCurrent()}. + * If the technique wants to use a shader to render the model, it should load it at this part - + * the shader should have all the proper defines as declared in the technique definition, + * including those that are bound to material parameters. + * The technique can re-use the shader from the last frame if * no changes to the defines occurred.
    - *
  • Set the {@link RenderState} to use for rendering. The render states are + *
  • Set the {@link RenderState} to use for rendering. The render states are * applied in this order (later RenderStates override earlier RenderStates):
      *
    1. {@link TechniqueDef#getRenderState() Technique Definition's RenderState} * - i.e. specific renderstate that is required for the shader.
    2. @@ -1120,22 +1120,22 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { *
    3. Uniforms bound to material parameters are updated based on the current material parameter values.
    4. *
    5. Uniforms bound to world parameters are updated from the RenderManager. * Internally {@link UniformBindingManager} is used for this task.
    6. - *
    7. Uniforms bound to textures will cause the texture to be uploaded as necessary. + *
    8. Uniforms bound to textures will cause the texture to be uploaded as necessary. * The uniform is set to the texture unit where the texture is bound.
- *
  • If the technique uses a shader, the model is then rendered according + *
  • If the technique uses a shader, the model is then rendered according * to the lighting mode specified on the technique definition.
      - *
    • {@link LightMode#SinglePass single pass light mode} fills the shader's light uniform arrays + *
    • {@link LightMode#SinglePass single pass light mode} fills the shader's light uniform arrays * with the first 4 lights and renders the model once.
    • - *
    • {@link LightMode#MultiPass multi pass light mode} light mode renders the model multiple times, - * for the first light it is rendered opaque, on subsequent lights it is + *
    • {@link LightMode#MultiPass multi pass light mode} light mode renders the model multiple times, + * for the first light it is rendered opaque, on subsequent lights it is * rendered with {@link BlendMode#AlphaAdditive alpha-additive} blending and depth writing disabled.
    • *
    - *
  • For techniques that do not use shaders, + *
  • For techniques that do not use shaders, * fixed function OpenGL is used to render the model (see {@link GL1Renderer} interface):
      *
    • OpenGL state ({@link FixedFuncBinding}) that is bound to material parameters is updated.
    • - *
    • The texture set on the material is uploaded and bound. + *
    • The texture set on the material is uploaded and bound. * Currently only 1 texture is supported for fixed function techniques.
    • - *
    • If the technique uses lighting, then OpenGL lighting state is updated + *
    • If the technique uses lighting, then OpenGL lighting state is updated * based on the light list on the geometry, otherwise OpenGL lighting is disabled.
    • *
    • The mesh is uploaded and rendered.
    • *
    @@ -1147,10 +1147,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { */ public void render(Geometry geom, LightList lights, RenderManager rm) { autoSelectTechnique(rm); + TechniqueDef techDef = technique.getDef(); - Renderer r = rm.getRenderer(); + if (techDef.isNoRender()) return; - TechniqueDef techDef = technique.getDef(); + Renderer r = rm.getRenderer(); if (rm.getForcedRenderState() != null) { r.applyRenderState(rm.getForcedRenderState()); @@ -1169,7 +1170,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { // reset unchanged uniform flag clearUniformsSetByCurrent(technique.getShader()); rm.updateUniformBindings(technique.getWorldBindUniforms()); - + // setup textures and uniforms for (int i = 0; i < paramValues.size(); i++) { @@ -1212,24 +1213,24 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { // any unset uniforms will be set to 0 resetUniformsNotSetByCurrent(shader); r.setShader(shader); - + renderMeshFromGeometry(r, geom); } /** * Called by {@link RenderManager} to render the geometry by * using this material. - * + * * Note that this version of the render method * does not perform light filtering. - * + * * @param geom The geometry to render * @param rm The render manager requesting the rendering */ public void render(Geometry geom, RenderManager rm) { render(geom, geom.getWorldLightList(), rm); } - + public void write(JmeExporter ex) throws IOException { OutputCapsule oc = ex.getCapsule(this); oc.write(def.getAssetName(), "material_def", null); @@ -1304,14 +1305,14 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { continue; } } - + if (im.getFormatVersion() == 0 && param.getName().startsWith("m_")) { // Ancient version of jME3 ... param.setName(param.getName().substring(2)); } - + if (def.getMaterialParam(param.getName()) == null) { - logger.log(Level.WARNING, "The material parameter is not defined: {0}. Ignoring..", + logger.log(Level.WARNING, "The material parameter is not defined: {0}. Ignoring..", param.getName()); } else { checkSetParam(param.getVarType(), param.getName()); diff --git a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java index f8152e563..d7523956c 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -40,7 +40,7 @@ import java.util.*; /** * Describes a technique definition. - * + * * @author Kirill Vainer */ public class TechniqueDef implements Savable { @@ -49,7 +49,7 @@ public class TechniqueDef implements Savable { * Version #1: Separate shader language for each shader source. */ public static final int SAVABLE_VERSION = 1; - + /** * Describes light rendering mode. */ @@ -58,15 +58,15 @@ public class TechniqueDef implements Savable { * Disable light-based rendering */ Disable, - + /** - * Enable light rendering by using a single pass. + * Enable light rendering by using a single pass. *

    * An array of light positions and light colors is passed to the shader * containing the world light list for the geometry being rendered. */ SinglePass, - + /** * Enable light rendering by using multi-pass rendering. *

    @@ -77,7 +77,7 @@ public class TechniqueDef implements Savable { * passes have it set to black. */ MultiPass, - + /** * @deprecated OpenGL1 is not supported anymore */ @@ -96,15 +96,16 @@ public class TechniqueDef implements Savable { private EnumMap shaderLanguages; private EnumMap shaderNames; - + private DefineList presetDefines; private boolean usesNodes = false; private List shaderNodes; private ShaderGenerationInfo shaderGenerationInfo; + private boolean noRender = false; private RenderState renderState; private RenderState forcedRenderState; - + private LightMode lightMode = LightMode.Disable; private ShadowMode shadowMode = ShadowMode.Disable; @@ -115,7 +116,7 @@ public class TechniqueDef implements Savable { * Creates a new technique definition. *

    * Used internally by the J3M/J3MD loader. - * + * * @param name The name of the technique, should be set to null * for default techniques. */ @@ -135,7 +136,7 @@ public class TechniqueDef implements Savable { /** * Returns the name of this technique as specified in the J3MD file. * Default techniques have the name "Default". - * + * * @return the name of this technique */ public String getName(){ @@ -153,9 +154,9 @@ public class TechniqueDef implements Savable { /** * Set the light mode - * + * * @param lightMode the light mode - * + * * @see LightMode */ public void setLightMode(LightMode lightMode) { @@ -172,9 +173,9 @@ public class TechniqueDef implements Savable { /** * Set the shadow mode. - * + * * @param shadowMode the shadow mode. - * + * * @see ShadowMode */ public void setShadowMode(ShadowMode shadowMode) { @@ -184,7 +185,7 @@ public class TechniqueDef implements Savable { /** * Returns the render state that this technique is using * @return the render state that this technique is using - * @see #setRenderState(com.jme3.material.RenderState) + * @see #setRenderState(com.jme3.material.RenderState) */ public RenderState getRenderState() { return renderState; @@ -192,15 +193,37 @@ public class TechniqueDef implements Savable { /** * Sets the render state that this technique is using. - * + * * @param renderState the render state that this technique is using. - * + * * @see RenderState */ public void setRenderState(RenderState renderState) { this.renderState = renderState; } + /** + * Sets if this technique should not be used to render. + * + * @param noRender not render or render ? + * + * @see NoRender + */ + public void setNoRender(boolean noRender) { + this.noRender = noRender; + } + + /** + * Returns true if this technique should not be used to render. + * (eg. to not render a material with default technique) + * + * @return true if this technique should not be rendered, false otherwise. + * + */ + public boolean isNoRender(){ + return noRender; + } + /** * @deprecated jME3 always requires shaders now */ @@ -208,12 +231,12 @@ public class TechniqueDef implements Savable { public boolean isUsingShaders(){ return true; } - + /** * Returns true if this technique uses Shader Nodes, false otherwise. - * + * * @return true if this technique uses Shader Nodes, false otherwise. - * + * */ public boolean isUsingShaderNodes(){ return usesNodes; @@ -222,7 +245,7 @@ public class TechniqueDef implements Savable { /** * Gets the {@link Caps renderer capabilities} that are required * by this technique. - * + * * @return the required renderer capabilities */ public EnumSet getRequiredCaps() { @@ -231,7 +254,7 @@ public class TechniqueDef implements Savable { /** * Sets the shaders that this technique definition will use. - * + * * @param vertexShader The name of the vertex shader * @param fragmentShader The name of the fragment shader * @param vertLanguage The vertex shader language @@ -242,7 +265,7 @@ public class TechniqueDef implements Savable { this.shaderNames.put(Shader.ShaderType.Vertex, vertexShader); this.shaderLanguages.put(Shader.ShaderType.Fragment, fragLanguage); this.shaderNames.put(Shader.ShaderType.Fragment, fragmentShader); - + requiredCaps.clear(); Caps vertCap = Caps.valueOf(vertLanguage); requiredCaps.add(vertCap); @@ -259,17 +282,17 @@ public class TechniqueDef implements Savable { */ public void setShaderFile(EnumMap shaderNames, EnumMap shaderLanguages) { requiredCaps.clear(); - + for (Shader.ShaderType shaderType : shaderNames.keySet()) { String language = shaderLanguages.get(shaderType); String shaderFile = shaderNames.get(shaderType); - + this.shaderLanguages.put(shaderType, language); this.shaderNames.put(shaderType, shaderFile); - + Caps vertCap = Caps.valueOf(language); requiredCaps.add(vertCap); - + if (shaderType.equals(Shader.ShaderType.Geometry)) { requiredCaps.add(Caps.GeometryShader); } else if (shaderType.equals(Shader.ShaderType.TessellationControl)) { @@ -280,11 +303,11 @@ public class TechniqueDef implements Savable { /** * Returns the define name which the given material parameter influences. - * + * * @param paramName The parameter name to look up * @return The define name - * - * @see #addShaderParamDefine(java.lang.String, java.lang.String) + * + * @see #addShaderParamDefine(java.lang.String, java.lang.String) */ public String getShaderParamDefine(String paramName){ if (defineParams == null) { @@ -297,11 +320,11 @@ public class TechniqueDef implements Savable { * Adds a define linked to a material parameter. *

    * Any time the material parameter on the parent material is altered, - * the appropriate define on the technique will be modified as well. - * See the method + * the appropriate define on the technique will be modified as well. + * See the method * {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) } * on the exact details of how the material parameter changes the define. - * + * * @param paramName The name of the material parameter to link to. * @param defineName The name of the define parameter, e.g. USE_LIGHTING */ @@ -314,26 +337,26 @@ public class TechniqueDef implements Savable { /** * Returns the {@link DefineList} for the preset defines. - * + * * @return the {@link DefineList} for the preset defines. - * - * @see #addShaderPresetDefine(java.lang.String, com.jme3.shader.VarType, java.lang.Object) + * + * @see #addShaderPresetDefine(java.lang.String, com.jme3.shader.VarType, java.lang.Object) */ public DefineList getShaderPresetDefines() { return presetDefines; } - + /** - * Adds a preset define. + * Adds a preset define. *

    * Preset defines do not depend upon any parameters to be activated, * they are always passed to the shader as long as this technique is used. - * + * * @param defineName The name of the define parameter, e.g. USE_LIGHTING - * @param type The type of the define. See + * @param type The type of the define. See * {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) } * to see why it matters. - * + * * @param value The value of the define */ public void addShaderPresetDefine(String defineName, VarType type, Object value){ @@ -346,18 +369,18 @@ public class TechniqueDef implements Savable { /** * Returns the name of the fragment shader used by the technique, or null * if no fragment shader is specified. - * + * * @return the name of the fragment shader to be used. */ public String getFragmentShaderName() { return shaderNames.get(Shader.ShaderType.Fragment); } - + /** * Returns the name of the vertex shader used by the technique, or null * if no vertex shader is specified. - * + * * @return the name of the vertex shader to be used. */ public String getVertexShaderName() { @@ -370,7 +393,7 @@ public class TechniqueDef implements Savable { public String getFragmentShaderLanguage() { return shaderLanguages.get(Shader.ShaderType.Fragment); } - + /** * Returns the language of the vertex shader used in this technique. */ @@ -390,10 +413,10 @@ public class TechniqueDef implements Savable { public String getShaderProgramName(Shader.ShaderType shaderType){ return shaderNames.get(shaderType); } - + /** * Adds a new world parameter by the given name. - * + * * @param name The world parameter to add. * @return True if the world parameter name was found and added * to the list of world parameters, false otherwise. @@ -402,7 +425,7 @@ public class TechniqueDef implements Savable { if (worldBinds == null){ worldBinds = new ArrayList(); } - + try { worldBinds.add( UniformBinding.valueOf(name) ); return true; @@ -418,11 +441,11 @@ public class TechniqueDef implements Savable { public void setForcedRenderState(RenderState forcedRenderState) { this.forcedRenderState = forcedRenderState; } - + /** * Returns a list of world parameters that are used by this * technique definition. - * + * * @return The list of world parameters */ public List getWorldBindings() { @@ -448,10 +471,11 @@ public class TechniqueDef implements Savable { oc.write(lightMode, "lightMode", LightMode.Disable); oc.write(shadowMode, "shadowMode", ShadowMode.Disable); oc.write(renderState, "renderState", null); + oc.write(noRender, "noRender", false); oc.write(usesNodes, "usesNodes", false); oc.writeSavableArrayList((ArrayList)shaderNodes,"shaderNodes", null); oc.write(shaderGenerationInfo, "shaderGenerationInfo", null); - + // TODO: Finish this when Map export is available // oc.write(defineParams, "defineParams", null); // TODO: Finish this when List export is available @@ -470,7 +494,8 @@ public class TechniqueDef implements Savable { lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable); shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable); renderState = (RenderState) ic.readSavable("renderState", null); - + noRender = ic.readBoolean("noRender", false); + if (ic.getSavableVersion(TechniqueDef.class) == 0) { // Old version shaderLanguages.put(Shader.ShaderType.Vertex,ic.readString("shaderLang", null)); @@ -483,7 +508,7 @@ public class TechniqueDef implements Savable { shaderLanguages.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrlLanguage", null)); shaderLanguages.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tsevalLanguage", null)); } - + usesNodes = ic.readBoolean("usesNodes", false); shaderNodes = ic.readSavableArrayList("shaderNodes", null); shaderGenerationInfo = (ShaderGenerationInfo) ic.readSavable("shaderGenerationInfo", null); @@ -525,6 +550,6 @@ public class TechniqueDef implements Savable { //todo: make toString return something usefull @Override public String toString() { - return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + '}'; - } + return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + ", noRender=" + noRender + '}'; + } } diff --git a/jme3-core/src/main/java/com/jme3/math/FastMath.java b/jme3-core/src/main/java/com/jme3/math/FastMath.java index d9d944057..4f1a7feed 100644 --- a/jme3-core/src/main/java/com/jme3/math/FastMath.java +++ b/jme3-core/src/main/java/com/jme3/math/FastMath.java @@ -87,8 +87,25 @@ final public class FastMath { return (number > 0) && (number & (number - 1)) == 0; } + /** + * Get the next power of two of the given number. + * + * E.g. for an input 100, this returns 128. + * Returns 1 for all numbers <= 1. + * + * @param number The number to obtain the POT for. + * @return The next power of two. + */ public static int nearestPowerOfTwo(int number) { - return (int) Math.pow(2, Math.ceil(Math.log(number) / Math.log(2))); + number--; + number |= number >> 1; + number |= number >> 2; + number |= number >> 4; + number |= number >> 8; + number |= number >> 16; + number++; + number += (number == 0) ? 1 : 0; + return number; } /** diff --git a/jme3-core/src/main/java/com/jme3/math/Matrix4f.java b/jme3-core/src/main/java/com/jme3/math/Matrix4f.java index c8dd3ef4a..159e39932 100644 --- a/jme3-core/src/main/java/com/jme3/math/Matrix4f.java +++ b/jme3-core/src/main/java/com/jme3/math/Matrix4f.java @@ -154,53 +154,34 @@ public final class Matrix4f implements Savable, Cloneable, java.io.Serializable } public void fromFrame(Vector3f location, Vector3f direction, Vector3f up, Vector3f left) { - loadIdentity(); - TempVars vars = TempVars.get(); - - Vector3f f = vars.vect1.set(direction); - Vector3f s = vars.vect2.set(f).crossLocal(up); - Vector3f u = vars.vect3.set(s).crossLocal(f); -// s.normalizeLocal(); -// u.normalizeLocal(); - - m00 = s.x; - m01 = s.y; - m02 = s.z; - - m10 = u.x; - m11 = u.y; - m12 = u.z; - - m20 = -f.x; - m21 = -f.y; - m22 = -f.z; - -// m00 = -left.x; -// m10 = -left.y; -// m20 = -left.z; -// -// m01 = up.x; -// m11 = up.y; -// m21 = up.z; -// -// m02 = -direction.x; -// m12 = -direction.y; -// m22 = -direction.z; -// - - Matrix4f transMatrix = vars.tempMat4; - transMatrix.loadIdentity(); - transMatrix.m03 = -location.x; - transMatrix.m13 = -location.y; - transMatrix.m23 = -location.z; - this.multLocal(transMatrix); - - vars.release(); - -// transMatrix.multLocal(this); - -// set(transMatrix); + try { + Vector3f fwdVector = vars.vect1.set(direction); + Vector3f leftVector = vars.vect2.set(fwdVector).crossLocal(up); + Vector3f upVector = vars.vect3.set(leftVector).crossLocal(fwdVector); + + m00 = leftVector.x; + m01 = leftVector.y; + m02 = leftVector.z; + m03 = -leftVector.dot(location); + + m10 = upVector.x; + m11 = upVector.y; + m12 = upVector.z; + m13 = -upVector.dot(location); + + m20 = -fwdVector.x; + m21 = -fwdVector.y; + m22 = -fwdVector.z; + m23 = fwdVector.dot(location); + + m30 = 0f; + m31 = 0f; + m32 = 0f; + m33 = 1f; + } finally { + vars.release(); + } } /** diff --git a/jme3-core/src/main/java/com/jme3/math/Transform.java b/jme3-core/src/main/java/com/jme3/math/Transform.java index ac7a324d0..9d8a72a1e 100644 --- a/jme3-core/src/main/java/com/jme3/math/Transform.java +++ b/jme3-core/src/main/java/com/jme3/math/Transform.java @@ -49,7 +49,7 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable private Quaternion rot = new Quaternion(); private Vector3f translation = new Vector3f(); - private Vector3f scale = new Vector3f(1,1,1); + private Vector3f scale = new Vector3f(1, 1, 1); public Transform(Vector3f translation, Quaternion rot){ this.translation.set(translation); @@ -283,9 +283,32 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable * Loads the identity. Equal to translation=0,0,0 scale=1,1,1 rot=0,0,0,1. */ public void loadIdentity() { - translation.set(0,0,0); - scale.set(1,1,1); - rot.set(0,0,0,1); + translation.set(0, 0, 0); + scale.set(1, 1, 1); + rot.set(0, 0, 0, 1); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 89 * hash + rot.hashCode(); + hash = 89 * hash + translation.hashCode(); + hash = 89 * hash + scale.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Transform other = (Transform) obj; + return this.translation.equals(other.translation) + && this.scale.equals(other.scale) + && this.rot.equals(other.rot); } @Override @@ -307,22 +330,21 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable return this; } + @Override public void write(JmeExporter e) throws IOException { OutputCapsule capsule = e.getCapsule(this); - capsule.write(rot, "rot", new Quaternion()); + capsule.write(rot, "rot", Quaternion.IDENTITY); capsule.write(translation, "translation", Vector3f.ZERO); capsule.write(scale, "scale", Vector3f.UNIT_XYZ); } + @Override public void read(JmeImporter e) throws IOException { InputCapsule capsule = e.getCapsule(this); - rot = (Quaternion)capsule.readSavable("rot", new Quaternion()); - translation = (Vector3f)capsule.readSavable("translation", null); - if( translation == null ) { - translation = new Vector3f(); - } - scale = (Vector3f)capsule.readSavable("scale", Vector3f.UNIT_XYZ); + rot.set((Quaternion)capsule.readSavable("rot", Quaternion.IDENTITY)); + translation.set((Vector3f)capsule.readSavable("translation", Vector3f.ZERO)); + scale.set((Vector3f)capsule.readSavable("scale", Vector3f.UNIT_XYZ)); } @Override diff --git a/jme3-core/src/main/java/com/jme3/post/Filter.java b/jme3-core/src/main/java/com/jme3/post/Filter.java index a6e2e3c01..feaacbe5d 100644 --- a/jme3-core/src/main/java/com/jme3/post/Filter.java +++ b/jme3-core/src/main/java/com/jme3/post/Filter.java @@ -409,6 +409,19 @@ public abstract class Filter implements Savable { return true; } + /** + * Override this method and return true if you want the scene (input) texture + * to use bilinear filtering or false to use nearest filtering. + * + * Typically filters that perform samples in between pixels + * should enable filtering. + * + * @return true to use linear filtering, false to use nearest filtering. + */ + protected boolean isRequiresBilinear() { + return false; + } + /** * returns the list of the postRender passes * @return diff --git a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java index 2cd8b83f8..2f52eb425 100644 --- a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java +++ b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java @@ -38,6 +38,7 @@ import com.jme3.renderer.*; import com.jme3.renderer.queue.RenderQueue; import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image.Format; +import com.jme3.texture.Texture; import com.jme3.texture.Texture2D; import com.jme3.ui.Picture; import com.jme3.util.SafeArrayList; @@ -284,6 +285,12 @@ public class FilterPostProcessor implements SceneProcessor, Savable { mat.clearParam("NumSamples"); } } + + boolean wantsBilinear = filter.isRequiresBilinear(); + if (wantsBilinear) { + tex.setMagFilter(Texture.MagFilter.Bilinear); + tex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps); + } buff = outputBuffer; if (i != lastFilterIndex) { @@ -293,6 +300,11 @@ public class FilterPostProcessor implements SceneProcessor, Savable { } renderProcessing(r, buff, mat); filter.postFilter(r, buff); + + if (wantsBilinear) { + tex.setMagFilter(Texture.MagFilter.Nearest); + tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps); + } } } } @@ -300,7 +312,7 @@ public class FilterPostProcessor implements SceneProcessor, Savable { public void postFrame(FrameBuffer out) { FrameBuffer sceneBuffer = renderFrameBuffer; - if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL31)) { + if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL32)) { renderer.copyFrameBuffer(renderFrameBufferMS, renderFrameBuffer, true); } else if (renderFrameBufferMS != null) { sceneBuffer = renderFrameBufferMS; @@ -443,7 +455,7 @@ public class FilterPostProcessor implements SceneProcessor, Savable { //antialiasing on filters only supported in opengl 3 due to depth read problem if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample)) { renderFrameBufferMS = new FrameBuffer(width, height, numSamples); - if (caps.contains(Caps.OpenGL31)) { + if (caps.contains(Caps.OpenGL32)) { Texture2D msColor = new Texture2D(width, height, numSamples, fbFormat); Texture2D msDepth = new Texture2D(width, height, numSamples, Format.Depth); renderFrameBufferMS.setDepthTexture(msDepth); @@ -456,7 +468,7 @@ public class FilterPostProcessor implements SceneProcessor, Savable { } } - if (numSamples <= 1 || !caps.contains(Caps.OpenGL31)) { + if (numSamples <= 1 || !caps.contains(Caps.OpenGL32)) { renderFrameBuffer = new FrameBuffer(width, height, 1); renderFrameBuffer.setDepthBuffer(Format.Depth); filterTexture = new Texture2D(width, height, fbFormat); diff --git a/jme3-core/src/main/java/com/jme3/renderer/Limits.java b/jme3-core/src/main/java/com/jme3/renderer/Limits.java index 86cddb178..81db88f5e 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Limits.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Limits.java @@ -77,4 +77,6 @@ public enum Limits { DepthTextureSamples, VertexUniformVectors, + + TextureAnisotropy, } diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java index 16c07dc71..8287a270e 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java @@ -241,12 +241,12 @@ public class RenderContext { public IDList attribIndexList = new IDList(); /** - * depth tets function + * depth test function */ - public RenderState.TestFunction depthFunc = RenderState.TestFunction.LessOrEqual; + public RenderState.TestFunction depthFunc = RenderState.TestFunction.Less; /** - * alpha tets function + * alpha test function */ public RenderState.TestFunction alphaFunc = RenderState.TestFunction.Greater; @@ -255,8 +255,6 @@ public class RenderContext { public ColorRGBA clearColor = new ColorRGBA(0,0,0,0); - public boolean seamlessCubemap = false; - /** * Reset the RenderContext to default GL state */ @@ -308,6 +306,5 @@ public class RenderContext { depthFunc = RenderState.TestFunction.LessOrEqual; alphaFunc = RenderState.TestFunction.Greater; clearColor.set(0,0,0,0); - seamlessCubemap = false; } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderManager.java b/jme3-core/src/main/java/com/jme3/renderer/RenderManager.java index b6ad6ace4..6d80d026f 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderManager.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderManager.java @@ -746,27 +746,43 @@ public class RenderManager { } /** - * Sets the light filter to use when rendering Lighted Geometries + * Sets the light filter to use when rendering lit Geometries. * * @see LightFilter - * @param lightFilter The light filter tose. Set it to null if you want all lights to be rendered + * @param lightFilter The light filter. Set it to null if you want all lights to be rendered. */ public void setLightFilter(LightFilter lightFilter) { this.lightFilter = lightFilter; } + /** + * Defines what light mode will be selected when a technique offers several light modes. + * @param preferredLightMode The light mode to use. + */ public void setPreferredLightMode(TechniqueDef.LightMode preferredLightMode) { this.preferredLightMode = preferredLightMode; } + /** + * returns the preferred light mode. + * @return the light mode. + */ public TechniqueDef.LightMode getPreferredLightMode() { return preferredLightMode; } + /** + * returns the number of lights used for each pass when the light mode is single pass. + * @return the number of lights. + */ public int getSinglePassLightBatchSize() { return singlePassLightBatchSize; } + /** + * Sets the number of lights to use for each pass when the light mode is single pass. + * @param singlePassLightBatchSize the number of lights. + */ public void setSinglePassLightBatchSize(int singlePassLightBatchSize) { this.singlePassLightBatchSize = singlePassLightBatchSize; } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index 4a9380cf4..1b9c3f94d 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -161,6 +161,7 @@ public interface GL { public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + public static final int GL_TEXTURE_BASE_LEVEL = 0x813C; public static final int GL_TEXTURE_MAG_FILTER = 0x2800; public static final int GL_TEXTURE_MAX_LEVEL = 0x813D; public static final int GL_TEXTURE_MIN_FILTER = 0x2801; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java index db09fdd02..abf6a77d7 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java @@ -44,7 +44,7 @@ public interface GL2 extends GL { public static final int GL_ALPHA_TEST = 0xBC0; public static final int GL_BGR = 0x80E0; public static final int GL_BGRA = 0x80E1; - public static final int GL_COMPARE_R_TO_TEXTURE = 0x884E; + public static final int GL_COMPARE_REF_TO_TEXTURE = 0x884E; public static final int GL_DEPTH_COMPONENT24 = 0x81A6; public static final int GL_DEPTH_COMPONENT32 = 0x81A7; public static final int GL_DEPTH_TEXTURE_MODE = 0x884B; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java index 27f0eb8bd..c77ff6449 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java @@ -68,6 +68,7 @@ public interface GLExt { public static final int GL_MAX_DEPTH_TEXTURE_SAMPLES = 0x910F; public static final int GL_MAX_DRAW_BUFFERS_ARB = 0x8824; public static final int GL_MAX_SAMPLES_EXT = 0x8D57; + public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF; public static final int GL_MULTISAMPLE_ARB = 0x809D; public static final int GL_NUM_PROGRAM_BINARY_FORMATS = 0x87FE; public static final int GL_PIXEL_PACK_BUFFER_ARB = 0x88EB; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 729f4e203..50e603d2f 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -51,7 +51,9 @@ import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer.RenderBuffer; import com.jme3.texture.Image; import com.jme3.texture.Texture; +import com.jme3.texture.Texture.ShadowCompareMode; import com.jme3.texture.Texture.WrapAxis; +import com.jme3.texture.image.LastTextureState; import com.jme3.util.BufferUtils; import com.jme3.util.ListMap; import com.jme3.util.MipMapGenerator; @@ -68,7 +70,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import jme3tools.shader.ShaderDebug; -public class GLRenderer implements Renderer { +public final class GLRenderer implements Renderer { private static final Logger logger = Logger.getLogger(GLRenderer.class.getName()); private static final boolean VALIDATE_SHADER = false; @@ -374,15 +376,18 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_EXT_texture_filter_anisotropic")) { caps.add(Caps.TextureFilterAnisotropic); + limits.put(Limits.TextureAnisotropy, getInteger(GLExt.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)); } - if (hasExtension("GL_EXT_framebuffer_object") || gl3 != null) { + if (hasExtension("GL_EXT_framebuffer_object") + || caps.contains(Caps.OpenGL30) + || caps.contains(Caps.OpenGLES20)) { caps.add(Caps.FrameBuffer); limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT)); limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT)); - if (hasExtension("GL_EXT_framebuffer_blit")) { + if (hasExtension("GL_EXT_framebuffer_blit") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.FrameBufferBlit); } @@ -401,7 +406,7 @@ public class GLRenderer implements Renderer { } } - if (hasExtension("GL_ARB_draw_buffers")) { + if (hasExtension("GL_ARB_draw_buffers") || caps.contains(Caps.OpenGL30)) { limits.put(Limits.FrameBufferMrtAttachments, getInteger(GLExt.GL_MAX_DRAW_BUFFERS_ARB)); if (limits.get(Limits.FrameBufferMrtAttachments) > 1) { caps.add(Caps.FrameBufferMRT); @@ -501,6 +506,11 @@ public class GLRenderer implements Renderer { // Initialize default state.. gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); + + if (caps.contains(Caps.SeamlessCubemap)) { + // Enable this globally. Should be OK. + gl.glEnable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS); + } if (caps.contains(Caps.CoreProfile)) { // Core Profile requires VAO to be bound. @@ -607,17 +617,16 @@ public class GLRenderer implements Renderer { if (state.isDepthTest() && !context.depthTestEnabled) { gl.glEnable(GL.GL_DEPTH_TEST); - gl.glDepthFunc(convertTestFunction(context.depthFunc)); context.depthTestEnabled = true; } else if (!state.isDepthTest() && context.depthTestEnabled) { gl.glDisable(GL.GL_DEPTH_TEST); context.depthTestEnabled = false; } - if (state.getDepthFunc() != context.depthFunc) { + if (state.isDepthTest() && state.getDepthFunc() != context.depthFunc) { gl.glDepthFunc(convertTestFunction(state.getDepthFunc())); context.depthFunc = state.getDepthFunc(); } - + if (state.isDepthWrite() && !context.depthWriteEnabled) { gl.glDepthMask(true); context.depthWriteEnabled = true; @@ -1064,6 +1073,9 @@ public class GLRenderer implements Renderer { stringBuf.append("\n"); } else { if (gles2) { + // request GLSL ES (1.00) when compiling under GLES2. + stringBuf.append("#version 100\n"); + if (source.getType() == ShaderType.Fragment) { // GLES2 requires precision qualifier. stringBuf.append("precision mediump float;\n"); @@ -1080,6 +1092,7 @@ public class GLRenderer implements Renderer { if (linearizeSrgbImages) { stringBuf.append("#define SRGB 1\n"); } + stringBuf.append("#define ").append(source.getType().name().toUpperCase()).append("_SHADER 1\n"); stringBuf.append(source.getDefines()); stringBuf.append(source.getSource()); @@ -1422,7 +1435,7 @@ public class GLRenderer implements Renderer { // NOTE: For depth textures, sets nearest/no-mips mode // Required to fix "framebuffer unsupported" // for old NVIDIA drivers! - setupTextureParams(tex); + setupTextureParams(0, tex); } glfbo.glFramebufferTexture2DEXT(GLFbo.GL_FRAMEBUFFER_EXT, @@ -1449,25 +1462,44 @@ public class GLRenderer implements Renderer { rb.getId()); } } + + private void bindFrameBuffer(FrameBuffer fb) { + if (fb == null) { + if (context.boundFBO != 0) { + glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0); + statistics.onFrameBufferUse(null, true); + context.boundFBO = 0; + context.boundFB = null; + } + } else { + assert fb.getId() != -1 && fb.getId() != 0; + if (context.boundFBO != fb.getId()) { + glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId()); + context.boundFBO = fb.getId(); + context.boundFB = fb; + statistics.onFrameBufferUse(fb, true); + } else { + statistics.onFrameBufferUse(fb, false); + } + } + } public void updateFrameBuffer(FrameBuffer fb) { + if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) { + throw new IllegalArgumentException("The framebuffer: " + fb + + "\nDoesn't have any color/depth buffers"); + } + int id = fb.getId(); if (id == -1) { - // create FBO glfbo.glGenFramebuffersEXT(intBuf1); id = intBuf1.get(0); fb.setId(id); objManager.registerObject(fb); - statistics.onNewFrameBuffer(); } - if (context.boundFBO != id) { - glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, id); - // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0 - context.boundDrawBuf = 0; - context.boundFBO = id; - } + bindFrameBuffer(fb); FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer(); if (depthBuf != null) { @@ -1478,7 +1510,8 @@ public class GLRenderer implements Renderer { FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i); updateFrameBufferAttachment(fb, colorBuf); } - + + setReadDrawBuffers(fb); checkFrameBufferError(); fb.clearUpdateNeeded(); @@ -1506,93 +1539,45 @@ public class GLRenderer implements Renderer { } public void setMainFrameBufferOverride(FrameBuffer fb) { + mainFbOverride = null; + if (context.boundFBO == 0) { + // Main FB is now set to fb, make sure its bound + setFrameBuffer(fb); + } mainFbOverride = fb; } - public void setFrameBuffer(FrameBuffer fb) { - if (fb == null && mainFbOverride != null) { - fb = mainFbOverride; - } - - if (context.boundFB == fb) { - if (fb == null || !fb.isUpdateNeeded()) { - return; - } - } - - if (!caps.contains(Caps.FrameBuffer)) { - throw new RendererException("Framebuffer objects are not supported" - + " by the video hardware"); - } - - // generate mipmaps for last FB if needed - if (context.boundFB != null) { - for (int i = 0; i < context.boundFB.getNumColorBuffers(); i++) { - RenderBuffer rb = context.boundFB.getColorBuffer(i); - Texture tex = rb.getTexture(); - if (tex != null - && tex.getMinFilter().usesMipMapLevels()) { - setTexture(0, rb.getTexture()); - - int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace()); - glfbo.glGenerateMipmapEXT(textureType); - } - } + public void setReadDrawBuffers(FrameBuffer fb) { + if (gl2 == null) { + return; } - + + final int NONE = -2; + final int INITIAL = -1; + final int MRT_OFF = 100; + if (fb == null) { - // unbind any fbos - if (context.boundFBO != 0) { - glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0); - statistics.onFrameBufferUse(null, true); - - context.boundFBO = 0; + // Set Read/Draw buffers to initial value. + if (context.boundDrawBuf != INITIAL) { + gl2.glDrawBuffer(context.initialDrawBuf); + context.boundDrawBuf = INITIAL; } - // select back buffer - if (gl2 != null) { - if (context.boundDrawBuf != -1) { - gl2.glDrawBuffer(context.initialDrawBuf); - context.boundDrawBuf = -1; - } - if (context.boundReadBuf != -1) { - gl2.glReadBuffer(context.initialReadBuf); - context.boundReadBuf = -1; - } + if (context.boundReadBuf != INITIAL) { + gl2.glReadBuffer(context.initialReadBuf); + context.boundReadBuf = INITIAL; } - - context.boundFB = null; } else { - if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) { - throw new IllegalArgumentException("The framebuffer: " + fb - + "\nDoesn't have any color/depth buffers"); - } - - if (fb.isUpdateNeeded()) { - updateFrameBuffer(fb); - } - - // update viewport to reflect framebuffer's resolution - setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - - if (context.boundFBO != fb.getId()) { - glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId()); - statistics.onFrameBufferUse(fb, true); - - context.boundFBO = fb.getId(); - } else { - statistics.onFrameBufferUse(fb, false); - } if (fb.getNumColorBuffers() == 0) { // make sure to select NONE as draw buf - // no color buffer attached. select NONE + // no color buffer attached. if (gl2 != null) { - if (context.boundDrawBuf != -2) { + if (context.boundDrawBuf != NONE) { gl2.glDrawBuffer(GL.GL_NONE); - context.boundDrawBuf = -2; + context.boundDrawBuf = NONE; } - if (context.boundReadBuf != -2) { + if (context.boundReadBuf != NONE) { gl2.glReadBuffer(GL.GL_NONE); - context.boundReadBuf = -2; + context.boundReadBuf = NONE; } } } else { @@ -1612,7 +1597,7 @@ public class GLRenderer implements Renderer { + " by the video hardware!"); } - if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) { + if (context.boundDrawBuf != MRT_OFF + fb.getNumColorBuffers()) { intBuf16.clear(); for (int i = 0; i < fb.getNumColorBuffers(); i++) { intBuf16.put(GLFbo.GL_COLOR_ATTACHMENT0_EXT + i); @@ -1620,7 +1605,7 @@ public class GLRenderer implements Renderer { intBuf16.flip(); glext.glDrawBuffers(intBuf16); - context.boundDrawBuf = 100 + fb.getNumColorBuffers(); + context.boundDrawBuf = MRT_OFF + fb.getNumColorBuffers(); } } else { RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex()); @@ -1633,8 +1618,56 @@ public class GLRenderer implements Renderer { } } } + } + + } + + public void setFrameBuffer(FrameBuffer fb) { + if (fb == null && mainFbOverride != null) { + fb = mainFbOverride; + } + + if (context.boundFB == fb) { + if (fb == null || !fb.isUpdateNeeded()) { + return; + } + } + + if (!caps.contains(Caps.FrameBuffer)) { + throw new RendererException("Framebuffer objects are not supported" + + " by the video hardware"); + } + + // generate mipmaps for last FB if needed + if (context.boundFB != null) { + for (int i = 0; i < context.boundFB.getNumColorBuffers(); i++) { + RenderBuffer rb = context.boundFB.getColorBuffer(i); + Texture tex = rb.getTexture(); + if (tex != null + && tex.getMinFilter().usesMipMapLevels()) { + setTexture(0, rb.getTexture()); + + int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace()); + glfbo.glGenerateMipmapEXT(textureType); + } + } + } + + if (fb == null) { + bindFrameBuffer(null); + setReadDrawBuffers(null); + } else { + if (fb.isUpdateNeeded()) { + updateFrameBuffer(fb); + } else { + bindFrameBuffer(fb); + setReadDrawBuffers(fb); + } + + // update viewport to reflect framebuffer's resolution + setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - assert fb.getId() >= 0; + assert fb.getId() > 0; assert context.boundFBO == fb.getId(); context.boundFB = fb; @@ -1806,87 +1839,80 @@ public class GLRenderer implements Renderer { } @SuppressWarnings("fallthrough") - private void setupTextureParams(Texture tex) { + private void setupTextureParams(int unit, Texture tex) { Image image = tex.getImage(); int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1); boolean haveMips = true; - if (image != null) { haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps(); } + + LastTextureState curState = image.getLastTextureState(); - // filter things - if (image.getLastTextureState().magFilter != tex.getMagFilter()) { - int magFilter = convertMagFilter(tex.getMagFilter()); - gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, magFilter); - image.getLastTextureState().magFilter = tex.getMagFilter(); + if (curState.magFilter != tex.getMagFilter()) { + bindTextureAndUnit(target, image, unit); + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, convertMagFilter(tex.getMagFilter())); + curState.magFilter = tex.getMagFilter(); } - if (image.getLastTextureState().minFilter != tex.getMinFilter()) { - int minFilter = convertMinFilter(tex.getMinFilter(), haveMips); - gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter); - image.getLastTextureState().minFilter = tex.getMinFilter(); + if (curState.minFilter != tex.getMinFilter()) { + bindTextureAndUnit(target, image, unit); + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, convertMinFilter(tex.getMinFilter(), haveMips)); + curState.minFilter = tex.getMinFilter(); } - if (caps.contains(Caps.SeamlessCubemap) && tex.getType() == Texture.Type.CubeMap) { - if (haveMips && !context.seamlessCubemap) { - // We can enable seamless cubemap filtering. - gl.glEnable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS); - context.seamlessCubemap = true; - } else if (!haveMips && context.seamlessCubemap) { - // For skyboxes (no mipmaps), disable seamless cubemap filtering. - gl.glDisable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS); - context.seamlessCubemap = false; - } + if (caps.contains(Caps.TextureFilterAnisotropic) + && curState.anisoFilter != tex.getAnisotropicFilter()) { + bindTextureAndUnit(target, image, unit); + gl.glTexParameterf(target, + GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT, + tex.getAnisotropicFilter()); + curState.anisoFilter = tex.getAnisotropicFilter(); } - if (tex.getAnisotropicFilter() > 1) { - if (caps.contains(Caps.TextureFilterAnisotropic)) { - gl.glTexParameterf(target, - GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT, - tex.getAnisotropicFilter()); - } - } - - // repeat modes switch (tex.getType()) { case ThreeDimensional: case CubeMap: // cubemaps use 3D coords - if (gl2 != null && image.getLastTextureState().rWrap != tex.getWrap(WrapAxis.R)) { + if (gl2 != null && curState.rWrap != tex.getWrap(WrapAxis.R)) { + bindTextureAndUnit(target, image, unit); gl2.glTexParameteri(target, GL2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R))); - image.getLastTextureState().rWrap = tex.getWrap(WrapAxis.R); + curState.rWrap = tex.getWrap(WrapAxis.R); } //There is no break statement on purpose here case TwoDimensional: case TwoDimensionalArray: - if (image.getLastTextureState().tWrap != tex.getWrap(WrapAxis.T)) { + if (curState.tWrap != tex.getWrap(WrapAxis.T)) { + bindTextureAndUnit(target, image, unit); gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T))); image.getLastTextureState().tWrap = tex.getWrap(WrapAxis.T); } - if (image.getLastTextureState().sWrap != tex.getWrap(WrapAxis.S)) { + if (curState.sWrap != tex.getWrap(WrapAxis.S)) { + bindTextureAndUnit(target, image, unit); gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S))); - image.getLastTextureState().sWrap = tex.getWrap(WrapAxis.S); + curState.sWrap = tex.getWrap(WrapAxis.S); } break; default: throw new UnsupportedOperationException("Unknown texture type: " + tex.getType()); } - if(tex.isNeedCompareModeUpdate() && gl2 != null){ - // R to Texture compare mode - if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { - gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE); - gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); - if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) { + ShadowCompareMode texCompareMode = tex.getShadowCompareMode(); + if (gl2 != null && curState.shadowCompareMode != texCompareMode) { + bindTextureAndUnit(target, image, unit); + if (texCompareMode != ShadowCompareMode.Off) { + gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_REF_TO_TEXTURE); + if (texCompareMode == ShadowCompareMode.GreaterOrEqual) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL); } else { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL); } - }else{ - //restoring default value + } else { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); } - tex.compareModeUpdated(); + curState.shadowCompareMode = texCompareMode; } + + // If at this point we didn't bind the texture, bind it now + bindTextureOnly(target, image, unit); } /** @@ -1944,6 +1970,50 @@ public class GLRenderer implements Renderer { } } + /** + * Ensures that the texture is bound to the given unit + * and that the unit is currently active (for modification). + * + * @param target The texture target, one of GL_TEXTURE_*** + * @param img The image texture to bind + * @param unit At what unit to bind the texture. + */ + private void bindTextureAndUnit(int target, Image img, int unit) { + if (context.boundTextureUnit != unit) { + gl.glActiveTexture(GL.GL_TEXTURE0 + unit); + context.boundTextureUnit = unit; + } + if (context.boundTextures[unit] != img) { + gl.glBindTexture(target, img.getId()); + context.boundTextures[unit] = img; + statistics.onTextureUse(img, true); + } else { + statistics.onTextureUse(img, false); + } + } + + /** + * Ensures that the texture is bound to the given unit, + * but does not care if the unit is active (for rendering). + * + * @param target The texture target, one of GL_TEXTURE_*** + * @param img The image texture to bind + * @param unit At what unit to bind the texture. + */ + private void bindTextureOnly(int target, Image img, int unit) { + if (context.boundTextures[unit] != img) { + if (context.boundTextureUnit != unit) { + gl.glActiveTexture(GL.GL_TEXTURE0 + unit); + context.boundTextureUnit = unit; + } + gl.glBindTexture(target, img.getId()); + context.boundTextures[unit] = img; + statistics.onTextureUse(img, true); + } else { + statistics.onTextureUse(img, false); + } + } + /** * Uploads the given image to the GL driver. * @@ -1965,19 +2035,9 @@ public class GLRenderer implements Renderer { statistics.onNewTexture(); } - // bind texture + // bind texture int target = convertTextureType(type, img.getMultiSamples(), -1); - if (context.boundTextures[unit] != img) { - if (context.boundTextureUnit != unit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + unit); - context.boundTextureUnit = unit; - } - - gl.glBindTexture(target, texId); - context.boundTextures[unit] = img; - - statistics.onTextureUse(img, true); - } + bindTextureAndUnit(target, img, unit); if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired()) { // Image does not have mipmaps, but they are required. @@ -2086,6 +2146,7 @@ public class GLRenderer implements Renderer { img.clearUpdateNeeded(); } + @Override public void setTexture(int unit, Texture tex) { Image image = tex.getImage(); if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) { @@ -2112,24 +2173,7 @@ public class GLRenderer implements Renderer { int texId = image.getId(); assert texId != -1; - Image[] textures = context.boundTextures; - - int type = convertTextureType(tex.getType(), image.getMultiSamples(), -1); - if (textures[unit] != image) { - if (context.boundTextureUnit != unit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + unit); - context.boundTextureUnit = unit; - } - - gl.glBindTexture(type, texId); - textures[unit] = image; - - statistics.onTextureUse(image, true); - } else { - statistics.onTextureUse(image, false); - } - - setupTextureParams(tex); + setupTextureParams(unit, tex); } public void modifyTexture(Texture tex, Image pixels, int x, int y) { @@ -2623,12 +2667,13 @@ public class GLRenderer implements Renderer { } } + clearVertexAttribs(); + if (indices != null) { drawTriangleList(indices, mesh, count); } else { drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount()); } - clearVertexAttribs(); } public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java index 1b0d70749..f252d22dc 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java @@ -36,8 +36,14 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.nio.Buffer; import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; import java.util.HashMap; /** @@ -51,6 +57,17 @@ public final class GLTracer implements InvocationHandler { private final IntMap constMap; private static final HashMap> nonEnumArgMap = new HashMap>(); + private static final String ANSI_RESET = "\u001B[0m"; + private static final String ANSI_BRIGHT = "\u001B[1m"; + private static final String ANSI_BLACK = "\u001B[30m"; + private static final String ANSI_RED = "\u001B[31m"; + private static final String ANSI_GREEN = "\u001B[32m"; + private static final String ANSI_YELLOW = "\u001B[33m"; + private static final String ANSI_BLUE = "\u001B[34m"; + private static final String ANSI_MAGENTA = "\u001B[35m"; + private static final String ANSI_CYAN = "\u001B[36m"; + private static final String ANSI_WHITE = "\u001B[37m"; + private static void noEnumArgs(String method, int... argSlots) { IntMap argSlotsMap = new IntMap(); for (int argSlot : argSlots) { @@ -174,100 +191,305 @@ public final class GLTracer implements InvocationHandler { new GLTracer(glInterface, constMap)); } - private String translateInteger(String method, int value, int argIndex) { - IntMap argSlotMap = nonEnumArgMap.get(method); - if (argSlotMap != null && argSlotMap.containsKey(argIndex)) { - return Integer.toString(value); - } + private void printStyle(String style, String string) { + System.out.print(style + string + ANSI_RESET); + } + + private void print(String string) { + System.out.print(string); + } + + private void printInt(int value) { + print(Integer.toString(value)); + } + + private void printEnum(int value) { String enumName = constMap.get(value); if (enumName != null) { - return enumName; + if (enumName.startsWith("GL_")) { + enumName = enumName.substring(3); + } + if (enumName.endsWith("_EXT") || enumName.endsWith("_ARB")) { + enumName = enumName.substring(0, enumName.length() - 4); + } + printStyle(ANSI_GREEN, enumName); } else { - return "GL_ENUM_" + Integer.toHexString(value); - //throw new IllegalStateException("Untranslatable enum encountered on " + method + - // " at argument " + argIndex + " with value " + value); + printStyle(ANSI_GREEN, "ENUM_" + Integer.toHexString(value)); } } - private String translateString(String value) { - return "\"" + value.replaceAll("\0", "\\\\0") + "\""; + private void printIntOrEnum(String method, int value, int argIndex) { + IntMap argSlotMap = nonEnumArgMap.get(method); + if (argSlotMap != null && argSlotMap.containsKey(argIndex)) { + printInt(value); + } else { + printEnum(value); + } } - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - Object result = method.invoke(obj, args); - String methodName = method.getName(); + private void printNewLine() { + System.out.println(); + } + + private void printString(String value) { + if (value.length() > 150) { + value = value.substring(0, 150) + "..."; + } + StringBuilder sb = new StringBuilder(); + sb.append(ANSI_YELLOW); + sb.append("\""); + sb.append(ANSI_RESET); + for (String line : value.split("\n")) { + sb.append(ANSI_YELLOW); + sb.append(line.replaceAll("\0", "\\\\0")); + sb.append(ANSI_RESET); + sb.append("\n"); + } + if (sb.length() > 1 && sb.charAt(sb.length() - 1) == '\n') { + sb.setLength(sb.length() - 1); + } + sb.append(ANSI_YELLOW); + sb.append("\""); + sb.append(ANSI_RESET); + print(sb.toString()); + } + + private void printBoolean(boolean bool) { + printStyle(ANSI_BLUE, bool ? "true" : "false"); + } + + private void printBuffer(Buffer buffer) { + StringBuilder sb = new StringBuilder(); + sb.append(ANSI_MAGENTA); + if (buffer instanceof ByteBuffer) { + sb.append("byte"); + } else if (buffer instanceof ShortBuffer) { + sb.append("short"); + } else if (buffer instanceof CharBuffer) { + sb.append("char"); + } else if (buffer instanceof FloatBuffer) { + sb.append("float"); + } else if (buffer instanceof IntBuffer) { + sb.append("int"); + } else if (buffer instanceof LongBuffer) { + sb.append("long"); + } else if (buffer instanceof DoubleBuffer) { + sb.append("double"); + } else { + throw new UnsupportedOperationException(); + } + sb.append(ANSI_RESET); + sb.append("["); + + if (buffer.position() == 0 + && buffer.limit() == buffer.capacity()) { + // Common case. Just print buffer size. + sb.append(buffer.capacity()); + } else { + sb.append("pos=").append(buffer.position()); + sb.append(" lim=").append(buffer.limit()); + sb.append(" cap=").append(buffer.capacity()); + } + + sb.append("]"); + print(sb.toString()); + } + + private void printMethodName(String methodName) { if (methodName.startsWith("gl")) { - System.out.print(methodName); - System.out.print("("); - if (args != null) { - Class[] paramTypes = method.getParameterTypes(); - for (int i = 0; i < args.length; i++) { - if (paramTypes[i] == int.class) { - int val = (Integer)args[i]; - System.out.print(translateInteger(methodName, val, i)); - } else if (paramTypes[i] == String.class) { - System.out.print(translateString((String)args[i])); - } else if (paramTypes[i] == String[].class) { - String[] arr = (String[]) args[i]; - if (arr.length == 1) { - if (arr[0].length() > 150) { - System.out.print("\"" + arr[0].substring(0, 150) + "...\""); - } else { - System.out.print("\"" + arr[0] + "\""); - } - } else { - System.out.print("String[" + arr.length + "]"); - } - } else if (args[i] instanceof IntBuffer) { - IntBuffer buf = (IntBuffer) args[i]; - if (buf.capacity() == 16) { - int val = buf.get(0); - System.out.print("out=" + translateInteger(methodName, val, i)); - } else if (buf.capacity() == 1) { - System.out.print("out=" + buf.get(0)); - } else { - System.out.print(args[i]); - } - } else if (args[i] instanceof ByteBuffer) { - ByteBuffer bb = (ByteBuffer)args[i]; - if (bb.capacity() == 250) { - if (bb.get(0) != 0) { - System.out.print("out=GL_TRUE"); - } else { - System.out.print("out=GL_FALSE"); - } - } else { - System.out.print(args[i]); - } - } else { - System.out.print(args[i]); - } - - if (i != args.length - 1) { - System.out.print(", "); - } + // GL calls which actually draw (as opposed to change state) + // will be printed in darker color + methodName = methodName.substring(2); + if (methodName.equals("Clear") + || methodName.equals("DrawRangeElements")) { + print(methodName); + } else { + if (methodName.endsWith("EXT")) { + methodName = methodName.substring(0, methodName.length() - 3); } + printStyle(ANSI_BRIGHT, methodName); + } + } else if (methodName.equals("resetStats")) { + printStyle(ANSI_RED, "-- frame boundary --"); + } + } + + private void printArgsClear(int mask) { + boolean needAPipe = false; + print("("); + if ((mask & GL.GL_COLOR_BUFFER_BIT) != 0) { + printStyle(ANSI_GREEN, "COLOR_BUFFER_BIT"); + needAPipe = true; + } + if ((mask & GL.GL_DEPTH_BUFFER_BIT) != 0) { + if (needAPipe) { + print(" | "); } + printStyle(ANSI_GREEN, "DEPTH_BUFFER_BIT"); + } + if ((mask & GL.GL_STENCIL_BUFFER_BIT) != 0) { + if (needAPipe) { + print(" | "); + } + printStyle(ANSI_GREEN, "STENCIL_BUFFER_BIT"); + } + print(")"); + } + + private void printArgsGetInteger(Object[] args) { + print("("); + int param = (Integer)args[0]; + IntBuffer ib = (IntBuffer) args[1]; + printEnum(param); + print(", "); + printOut(); + if (param == GL2.GL_DRAW_BUFFER || param == GL2.GL_READ_BUFFER) { + printEnum(ib.get(0)); + } else { + printInt(ib.get(0)); + } + print(")"); + } + + private void printArgsTexParameter(Object[] args) { + print("("); - System.out.print(")"); + int target = (Integer) args[0]; + int param = (Integer) args[1]; + int value = (Integer) args[2]; - if (method.getReturnType() != void.class) { - if (result instanceof String) { - System.out.println(" = " + translateString((String)result)); - } else if (method.getReturnType() == int.class) { - int val = (Integer)result; - System.out.println(" = " + translateInteger(methodName, val, -1)); - } else if (method.getReturnType() == boolean.class) { - boolean val = (Boolean)result; - if (val) System.out.println(" = GL_TRUE"); - else System.out.println(" = GL_FALSE"); + printEnum(target); + print(", "); + printEnum(param); + print(", "); + + if (param == GL.GL_TEXTURE_BASE_LEVEL + || param == GL.GL_TEXTURE_MAX_LEVEL) { + printInt(value); + } else { + printEnum(value); + } + + print(")"); + } + + private void printOut() { + printStyle(ANSI_CYAN, "out="); + } + + private void printResult(String methodName, Object result, Class returnType) { + if (returnType != void.class) { + print(" = "); + if (result instanceof String) { + printString((String) result); + } else if (returnType == int.class) { + int val = (Integer) result; + printIntOrEnum(methodName, val, -1); + } else if (returnType == boolean.class) { + printBoolean((Boolean)result); + } else { + print(" = ???"); + } + } + } + + private void printNull() { + printStyle(ANSI_BLUE, "null"); + } + + private void printArgs(String methodName, Object[] args, Class[] paramTypes) { + if (methodName.equals("glClear")) { + printArgsClear((Integer)args[0]); + return; + } else if (methodName.equals("glTexParameteri")) { + printArgsTexParameter(args); + return; + } else if (methodName.equals("glGetInteger")) { + printArgsGetInteger(args); + return; + } + + if (args == null) { + print("()"); + return; + } + + print("("); + for (int i = 0; i < args.length; i++) { + if (paramTypes[i] == int.class) { + int val = (Integer)args[i]; + printIntOrEnum(methodName, val, i); + } else if (paramTypes[i] == boolean.class) { + printBoolean((Boolean)args[i]); + } else if (paramTypes[i] == String.class) { + printString((String)args[i]); + } else if (paramTypes[i] == String[].class) { + String[] arr = (String[]) args[i]; + if (arr.length == 1) { + printString(arr[0]); } else { - System.out.println(" = ???"); + print("string[" + arr.length + "]"); } + } else if (args[i] instanceof IntBuffer) { + IntBuffer buf = (IntBuffer) args[i]; + if (buf.capacity() == 16) { + int val = buf.get(0); + printOut(); + printIntOrEnum(methodName, val, i); + } else if (buf.capacity() == 1) { + printOut(); + print(Integer.toString(buf.get(0))); + } else { + printBuffer(buf); + } + } else if (args[i] instanceof ByteBuffer) { + ByteBuffer bb = (ByteBuffer)args[i]; + if (bb.capacity() == 250) { + printOut(); + printBoolean(bb.get(0) != 0); + } else { + printBuffer(bb); + } + } else if (args[i] instanceof Buffer) { + printBuffer((Buffer)args[i]); + } else if (args[i] != null) { + print(args[i].toString()); } else { - System.out.println(); + printNull(); } + + if (i != args.length - 1) { + System.out.print(", "); + } + } + print(")"); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String methodName = method.getName(); + printMethodName(methodName); + + if (methodName.startsWith("gl")) { + try { + // Try to evaluate result first, so we can see output values. + Object result = method.invoke(obj, args); + printArgs(methodName, args, method.getParameterTypes()); + printResult(methodName, result, method.getReturnType()); + printNewLine(); + return result; + } catch (Throwable ex) { + // Execution failed, print args anyway + // but output values will be incorrect. + printArgs(methodName, args, method.getParameterTypes()); + printNewLine(); + System.out.println("\tException occurred!"); + System.out.println(ex.toString()); + throw ex; + } + } else { + printNewLine(); + return method.invoke(obj, args); } - return result; } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java index a2f21ceaa..fb6032393 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java @@ -90,9 +90,11 @@ final class TextureUtil { } public GLImageFormat getImageFormatWithError(Format fmt, boolean isSrgb) { + //if the passed format is one kind of depth there isno point in getting the srgb format; + isSrgb = isSrgb && fmt != Format.Depth && fmt != Format.Depth16 && fmt != Format.Depth24 && fmt != Format.Depth24Stencil8 && fmt != Format.Depth32 && fmt != Format.Depth32F; GLImageFormat glFmt = getImageFormat(fmt, isSrgb); if (glFmt == null && isSrgb) { - glFmt = getImageFormat(fmt, false); + glFmt = getImageFormat(fmt, false); logger.log(Level.WARNING, "No sRGB format available for ''{0}''. Failling back to linear.", fmt); } if (glFmt == null) { diff --git a/jme3-core/src/main/java/com/jme3/scene/BatchNode.java b/jme3-core/src/main/java/com/jme3/scene/BatchNode.java index 2d603ac2c..c3a0ab4bb 100644 --- a/jme3-core/src/main/java/com/jme3/scene/BatchNode.java +++ b/jme3-core/src/main/java/com/jme3/scene/BatchNode.java @@ -119,19 +119,6 @@ public class BatchNode extends GeometryGroupNode { setNeedsFullRebatch(true); } - @Override - public void updateGeometricState() { - if (!children.isEmpty()) { - for (Batch batch : batches.getArray()) { - if (batch.needMeshUpdate) { - batch.geometry.updateModelBound(); - batch.geometry.updateWorldBound(); - batch.needMeshUpdate = false; - } - } - } - super.updateGeometricState(); - } protected Matrix4f getTransformMatrix(Geometry g){ return g.cachedWorldMat; @@ -169,7 +156,7 @@ public class BatchNode extends GeometryGroupNode { nvb.updateData(normBuf); - batch.needMeshUpdate = true; + batch.geometry.updateModelBound(); } } @@ -234,7 +221,7 @@ public class BatchNode extends GeometryGroupNode { batch.geometry.setMesh(m); batch.geometry.getMesh().updateCounts(); - batch.geometry.getMesh().updateBound(); + batch.geometry.updateModelBound(); batches.add(batch); } if (batches.size() > 0) { @@ -457,6 +444,7 @@ public class BatchNode extends GeometryGroupNode { int maxWeights = -1; Mesh.Mode mode = null; + float lineWidth = 1f; for (Geometry geom : geometries) { totalVerts += geom.getVertexCount(); totalTris += geom.getTriangleCount(); @@ -465,6 +453,7 @@ public class BatchNode extends GeometryGroupNode { maxVertCount = geom.getVertexCount(); } Mesh.Mode listMode; + float listLineWidth = 1f; int components; switch (geom.getMesh().getMode()) { case Points: @@ -475,6 +464,7 @@ public class BatchNode extends GeometryGroupNode { case LineStrip: case Lines: listMode = Mesh.Mode.Lines; + listLineWidth = geom.getMesh().getLineWidth(); components = 2; break; case TriangleFan: @@ -504,13 +494,21 @@ public class BatchNode extends GeometryGroupNode { if (mode != null && mode != listMode) { throw new UnsupportedOperationException("Cannot combine different" + " primitive types: " + mode + " != " + listMode); - } + } mode = listMode; + if (mode == Mesh.Mode.Lines) { + if (lineWidth != 1f && listLineWidth != lineWidth) { + throw new UnsupportedOperationException("When using Mesh Line mode, cannot combine meshes with different line width " + + lineWidth + " != " + listLineWidth); + } + lineWidth = listLineWidth; + } compsForBuf[VertexBuffer.Type.Index.ordinal()] = components; } outMesh.setMaxNumWeights(maxWeights); outMesh.setMode(mode); + outMesh.setLineWidth(lineWidth); if (totalVerts >= 65536) { // make sure we create an UnsignedInt buffer so // we can fit all of the meshes @@ -747,8 +745,7 @@ public class BatchNode extends GeometryGroupNode { } } } - Geometry geometry; - boolean needMeshUpdate = false; + Geometry geometry; } protected void setNeedsFullRebatch(boolean needsFullRebatch) { diff --git a/jme3-core/src/main/java/com/jme3/scene/Node.java b/jme3-core/src/main/java/com/jme3/scene/Node.java index 5edfa021b..74b14188d 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Node.java +++ b/jme3-core/src/main/java/com/jme3/scene/Node.java @@ -195,7 +195,7 @@ public class Node extends Spatial { void invalidateUpdateList() { updateListValid = false; if ( parent != null ) { - parent.invalidateUpdateList(); + parent.invalidateUpdateList(); } } @@ -570,6 +570,35 @@ public class Node extends Spatial { // optimization: try collideWith BoundingVolume to avoid possibly redundant tests on children // number 4 in condition is somewhat arbitrary. When there is only one child, the boundingVolume test is redundant at all. // The idea is when there are few children, it can be too expensive to test boundingVolume first. + /* + I'm removing this change until some issues can be addressed and I really + think it needs to be implemented a better way anyway. + + First, it causes issues for anyone doing collideWith() with BoundingVolumes + and expecting it to trickle down to the children. For example, children + with BoundingSphere bounding volumes and collideWith(BoundingSphere). Doing + a collision check at the parent level then has to do a BoundingSphere to BoundingBox + collision which isn't resolved. (Having to come up with a collision point in that + case is tricky and the first sign that this is the wrong approach.) + + Second, the rippling changes this caused to 'optimize' collideWith() for this + special use-case are another sign that this approach was a bit dodgy. The whole + idea of calculating a full collision just to see if the two shapes collide at all + is very wasteful. + + A proper implementation should support a simpler boolean check that doesn't do + all of that calculation. For example, if 'other' is also a BoundingVolume (ie: 99.9% + of all non-Ray cases) then a direct BV to BV intersects() test can be done. So much + faster. And if 'other' _is_ a Ray then the BV.intersects(Ray) call can be done. + + I don't have time to do it right now but I'll at least un-break a bunch of peoples' + code until it can be 'optimized' properly. Hopefully it's not too late to back out + the other dodgy ripples this caused. -pspeed (hindsight-expert ;)) + + Note: the code itself is relatively simple to implement but I don't have time to + a) test it, and b) see if '> 4' is still a decent check for it. Could be it's fast + enough to do all the time for > 1. + if (children.size() > 4) { BoundingVolume bv = this.getWorldBound(); @@ -578,6 +607,7 @@ public class Node extends Spatial { // collideWith without CollisionResults parameter used to avoid allocation when possible if (bv.collideWith(other) == 0) return 0; } + */ for (Spatial child : children.getArray()){ total += child.collideWith(other, results); } diff --git a/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java b/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java index 5b6d0661e..563981804 100644 --- a/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java +++ b/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java @@ -99,6 +99,7 @@ public class Grid extends Mesh { updateBound(); updateCounts(); + setStatic(); } } diff --git a/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java b/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java index c050d1edb..4f5364753 100644 --- a/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java +++ b/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java @@ -35,6 +35,7 @@ import com.jme3.math.Vector3f; import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer.Type; +import com.jme3.scene.VertexBuffer.Usage; import com.jme3.util.BufferUtils; import java.nio.FloatBuffer; @@ -62,6 +63,7 @@ public class WireFrustum extends Mesh { 3, 7, } ); + getBuffer(Type.Index).setUsage(Usage.Static); setMode(Mode.Lines); } diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Curve.java b/jme3-core/src/main/java/com/jme3/scene/shape/Curve.java index 009b41c64..d6eb8dc20 100644 --- a/jme3-core/src/main/java/com/jme3/scene/shape/Curve.java +++ b/jme3-core/src/main/java/com/jme3/scene/shape/Curve.java @@ -198,35 +198,42 @@ public class Curve extends Mesh { * points */ private void createNurbMesh(int nbSubSegments) { - float minKnot = spline.getMinNurbKnot(); - float maxKnot = spline.getMaxNurbKnot(); - float deltaU = (maxKnot - minKnot) / nbSubSegments; + if(spline.getControlPoints() != null && spline.getControlPoints().size() > 0) { + if(nbSubSegments == 0) { + nbSubSegments = spline.getControlPoints().size() + 1; + } else { + nbSubSegments = spline.getControlPoints().size() * nbSubSegments + 1; + } + float minKnot = spline.getMinNurbKnot(); + float maxKnot = spline.getMaxNurbKnot(); + float deltaU = (maxKnot - minKnot) / nbSubSegments; - float[] array = new float[(nbSubSegments + 1) * 3]; + float[] array = new float[(nbSubSegments + 1) * 3]; - float u = minKnot; - Vector3f interpolationResult = new Vector3f(); - for (int i = 0; i < array.length; i += 3) { - spline.interpolate(u, 0, interpolationResult); - array[i] = interpolationResult.x; - array[i + 1] = interpolationResult.y; - array[i + 2] = interpolationResult.z; - u += deltaU; - } + float u = minKnot; + Vector3f interpolationResult = new Vector3f(); + for (int i = 0; i < array.length; i += 3) { + spline.interpolate(u, 0, interpolationResult); + array[i] = interpolationResult.x; + array[i + 1] = interpolationResult.y; + array[i + 2] = interpolationResult.z; + u += deltaU; + } - //calculating indexes - int i = 0; - short[] indices = new short[nbSubSegments << 1]; - for (int j = 0; j < nbSubSegments; ++j) { - indices[i++] = (short) j; - indices[i++] = (short) (j + 1); - } + //calculating indexes + int i = 0; + short[] indices = new short[nbSubSegments << 1]; + for (int j = 0; j < nbSubSegments; ++j) { + indices[i++] = (short) j; + indices[i++] = (short) (j + 1); + } - this.setMode(Mesh.Mode.Lines); - this.setBuffer(VertexBuffer.Type.Position, 3, array); - this.setBuffer(VertexBuffer.Type.Index, 2, indices); - this.updateBound(); - this.updateCounts(); + this.setMode(Mesh.Mode.Lines); + this.setBuffer(VertexBuffer.Type.Position, 3, array); + this.setBuffer(VertexBuffer.Type.Index, 2, indices); + this.updateBound(); + this.updateCounts(); + } } private void createLinearMesh() { diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java b/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java index f0966328f..1d215eb6b 100644 --- a/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java +++ b/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java @@ -389,6 +389,7 @@ public class Cylinder extends Mesh { } updateBound(); + setStatic(); } @Override diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java b/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java index 194535851..3e0c6ce7e 100644 --- a/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java +++ b/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java @@ -124,6 +124,7 @@ public class Quad extends Mesh { } updateBound(); + setStatic(); } diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java b/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java index 89db073a7..44aa41723 100644 --- a/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java +++ b/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java @@ -299,7 +299,6 @@ public class Sphere extends Mesh { } updateBound(); - setStatic(); } /** @@ -400,6 +399,7 @@ public class Sphere extends Mesh { this.interior = interior; setGeometryData(); setIndexData(); + setStatic(); } public void read(JmeImporter e) throws IOException { diff --git a/jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java index 5ff4ac8a7..bd70465cb 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java @@ -459,7 +459,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable debug = true; } - abstract void getReceivers(GeometryList lightReceivers); + protected abstract void getReceivers(GeometryList lightReceivers); public void postFrame(FrameBuffer out) { if (skipPostPass) { diff --git a/jme3-core/src/main/java/com/jme3/shadow/DirectionalLightShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/DirectionalLightShadowRenderer.java index d0189e854..acf8a9677 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/DirectionalLightShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/DirectionalLightShadowRenderer.java @@ -192,7 +192,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer { } @Override - void getReceivers(GeometryList lightReceivers) { + protected void getReceivers(GeometryList lightReceivers) { if (lightReceivers.size()==0) { for (Spatial scene : viewPort.getScenes()) { ShadowUtil.getGeometriesInCamFrustum(scene, viewPort.getCamera(), RenderQueue.ShadowMode.Receive, lightReceivers); diff --git a/jme3-core/src/main/java/com/jme3/shadow/PointLightShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/PointLightShadowRenderer.java index 2976a2460..f4a6455f1 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/PointLightShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/PointLightShadowRenderer.java @@ -139,7 +139,7 @@ public class PointLightShadowRenderer extends AbstractShadowRenderer { } @Override - void getReceivers(GeometryList lightReceivers) { + protected void getReceivers(GeometryList lightReceivers) { lightReceivers.clear(); for (Spatial scene : viewPort.getScenes()) { ShadowUtil.getLitGeometriesInViewPort(scene, viewPort.getCamera(), shadowCams, RenderQueue.ShadowMode.Receive, lightReceivers); diff --git a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java index dafd25ac4..b291e722e 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java @@ -151,7 +151,7 @@ public class SpotLightShadowRenderer extends AbstractShadowRenderer { } @Override - void getReceivers(GeometryList lightReceivers) { + protected void getReceivers(GeometryList lightReceivers) { lightReceivers.clear(); Camera[] cameras = new Camera[1]; cameras[0] = shadowCam; diff --git a/jme3-core/src/main/java/com/jme3/system/AppSettings.java b/jme3-core/src/main/java/com/jme3/system/AppSettings.java index 73b036f2f..2d7071c9c 100644 --- a/jme3-core/src/main/java/com/jme3/system/AppSettings.java +++ b/jme3-core/src/main/java/com/jme3/system/AppSettings.java @@ -54,6 +54,8 @@ import java.util.prefs.Preferences; */ public final class AppSettings extends HashMap { + private static final long serialVersionUID = 1L; + private static final AppSettings defaults = new AppSettings(false); /** @@ -108,6 +110,33 @@ public final class AppSettings extends HashMap { * @see AppSettings#setAudioRenderer(java.lang.String) */ public static final String ANDROID_OPENAL_SOFT = "OpenAL_SOFT"; + + /** + * Use JogAmp's JOGL as the display system, with the OpenGL forward compatible profile + *

    + * N.B: This backend is EXPERIMENTAL + * + * @see AppSettings#setRenderer(java.lang.String) + */ + public static final String JOGL_OPENGL_FORWARD_COMPATIBLE = "JOGL_OPENGL_FORWARD_COMPATIBLE"; + + /** + * Use JogAmp's JOGL as the display system with the backward compatible profile + *

    + * N.B: This backend is EXPERIMENTAL + * + * @see AppSettings#setRenderer(java.lang.String) + */ + public static final String JOGL_OPENGL_BACKWARD_COMPATIBLE = "JOGL_OPENGL_BACKWARD_COMPATIBLE"; + + /** + * Use JogAmp's JOAL as the display system + *

    + * N.B: This backend is EXPERIMENTAL + * + * @see AppSettings#setRenderer(java.lang.String) + */ + public static final String JOAL = "JOAL"; static { defaults.put("Width", 640); @@ -118,7 +147,7 @@ public final class AppSettings extends HashMap { defaults.put("StencilBits", 0); defaults.put("Samples", 0); defaults.put("Fullscreen", false); - defaults.put("Title", "jMonkey Engine 3.0"); + defaults.put("Title", JmeVersion.FULL_NAME); defaults.put("Renderer", LWJGL_OPENGL2); defaults.put("AudioRenderer", LWJGL_OPENAL); defaults.put("DisableJoysticks", true); diff --git a/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java b/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java index 150275d46..2134e0a7e 100644 --- a/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java +++ b/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java @@ -153,6 +153,10 @@ public abstract class JmeSystemDelegate { return false; } else if (arch.equals("universal")) { return false; + } else if (arch.equals("aarch32")) { + return false; + } else if (arch.equals("aarch64")) { + return true; } else if (arch.equals("arm")) { return false; } else { diff --git a/jme3-core/src/main/java/com/jme3/system/JmeVersion.java b/jme3-core/src/main/java/com/jme3/system/JmeVersion.java new file mode 100644 index 000000000..0492df950 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/system/JmeVersion.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009-2015 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.system; + +import java.io.IOException; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Pulls in version info from the version.properties file. + * + * @author Kirill Vainer + */ +public class JmeVersion { + + private static final Logger logger = Logger.getLogger(JmeVersion.class.getName()); + private static final Properties props = new Properties(); + + static { + try { + props.load(JmeVersion.class.getResourceAsStream("version.properties")); + } catch (IOException ex) { + logger.log(Level.WARNING, "Unable to read version info!", ex); + } + } + + public static final String BUILD_DATE = props.getProperty("build.date", "1900-01-01"); + public static final String BRANCH_NAME = props.getProperty("git.branch", "unknown"); + public static final String GIT_HASH = props.getProperty("git.hash", ""); + public static final String GIT_SHORT_HASH = props.getProperty("git.hash.short", ""); + public static final String GIT_TAG = props.getProperty("git.tag", ""); + public static final String VERSION_NUMBER = props.getProperty("version.number", ""); + public static final String VERSION_TAG = props.getProperty("version.tag", ""); + public static final String VERSION_FULL = props.getProperty("version.full", ""); + public static final String FULL_NAME = props.getProperty("name.full", "jMonkeyEngine (unknown version)"); +} diff --git a/jme3-core/src/main/java/com/jme3/system/Platform.java b/jme3-core/src/main/java/com/jme3/system/Platform.java index 8a30fff0c..f9206d33f 100644 --- a/jme3-core/src/main/java/com/jme3/system/Platform.java +++ b/jme3-core/src/main/java/com/jme3/system/Platform.java @@ -88,6 +88,11 @@ public enum Platform { */ Android_ARM7, + /** + * Android ARM8 + */ + Android_ARM8, + /** * Android x86 */ diff --git a/jme3-core/src/main/java/com/jme3/texture/Image.java b/jme3-core/src/main/java/com/jme3/texture/Image.java index ca9404720..91b80ad3e 100644 --- a/jme3-core/src/main/java/com/jme3/texture/Image.java +++ b/jme3-core/src/main/java/com/jme3/texture/Image.java @@ -1041,6 +1041,7 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ { capsule.write(mipMapSizes, "mipMapSizes", null); capsule.write(multiSamples, "multiSamples", 1); capsule.writeByteBufferArrayList(data, "data", null); + capsule.write(colorSpace, "colorSpace", null); } public void read(JmeImporter e) throws IOException { @@ -1052,6 +1053,7 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ { mipMapSizes = capsule.readIntArray("mipMapSizes", null); multiSamples = capsule.readInt("multiSamples", 1); data = (ArrayList) capsule.readByteBufferArrayList("data", null); + colorSpace = capsule.readEnum("colorSpace", ColorSpace.class, null); if (mipMapSizes != null) { needGeneratedMips = false; diff --git a/jme3-core/src/main/java/com/jme3/texture/Texture.java b/jme3-core/src/main/java/com/jme3/texture/Texture.java index 582d06565..6be00700b 100644 --- a/jme3-core/src/main/java/com/jme3/texture/Texture.java +++ b/jme3-core/src/main/java/com/jme3/texture/Texture.java @@ -316,7 +316,6 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable private MinFilter minificationFilter = MinFilter.BilinearNoMipMaps; private MagFilter magnificationFilter = MagFilter.Bilinear; private ShadowCompareMode shadowCompareMode = ShadowCompareMode.Off; - private boolean needCompareModeUpdate = false; private int anisotropicFilter; /** @@ -404,7 +403,6 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable "compareMode can not be null."); } this.shadowCompareMode = compareMode; - needCompareModeUpdate = true; } /** @@ -489,7 +487,7 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable /** * @return the anisotropic filtering level for this texture. Default value * is 0 (use value from config), - * 1 means 1x (no anisotrophy), 2 means x2, 4 is x4, etc. + * 1 means 1x (no anisotropy), 2 means x2, 4 is x4, etc. */ public int getAnisotropicFilter() { return anisotropicFilter; @@ -636,14 +634,4 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable magnificationFilter = capsule.readEnum("magnificationFilter", MagFilter.class, MagFilter.Bilinear); } - - public boolean isNeedCompareModeUpdate() { - return needCompareModeUpdate; - } - - public void compareModeUpdated() { - this.needCompareModeUpdate = false; - } - - } diff --git a/jme3-core/src/main/java/com/jme3/texture/image/DefaultImageRaster.java b/jme3-core/src/main/java/com/jme3/texture/image/DefaultImageRaster.java index c79a4675d..2d70d53d7 100644 --- a/jme3-core/src/main/java/com/jme3/texture/image/DefaultImageRaster.java +++ b/jme3-core/src/main/java/com/jme3/texture/image/DefaultImageRaster.java @@ -51,7 +51,8 @@ public class DefaultImageRaster extends ImageRaster { private void rangeCheck(int x, int y) { if (x < 0 || y < 0 || x >= width || y >= height) { - throw new IllegalArgumentException("x and y must be inside the image dimensions"); + throw new IllegalArgumentException("x and y must be inside the image dimensions:" + + x + ", " + y + " in:" + width + ", " + height); } } diff --git a/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java b/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java index e7f2a2a14..32c1b718b 100644 --- a/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java +++ b/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java @@ -45,9 +45,11 @@ public final class LastTextureState { public Texture.WrapMode sWrap, tWrap, rWrap; public Texture.MagFilter magFilter; public Texture.MinFilter minFilter; + public int anisoFilter; + public Texture.ShadowCompareMode shadowCompareMode; public LastTextureState() { - // All parameters initialized to null (meaning unset). + reset(); } public void reset() { @@ -56,5 +58,10 @@ public final class LastTextureState { rWrap = null; magFilter = null; minFilter = null; + anisoFilter = 0; + + // The default in OpenGL is OFF, so we avoid setting this per texture + // if its not used. + shadowCompareMode = Texture.ShadowCompareMode.Off; } } diff --git a/jme3-core/src/main/java/com/jme3/util/BufferUtils.java b/jme3-core/src/main/java/com/jme3/util/BufferUtils.java index 84c6f6743..6fc0c50f0 100644 --- a/jme3-core/src/main/java/com/jme3/util/BufferUtils.java +++ b/jme3-core/src/main/java/com/jme3/util/BufferUtils.java @@ -36,6 +36,7 @@ import com.jme3.math.Quaternion; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; import com.jme3.math.Vector4f; +import java.io.UnsupportedEncodingException; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; @@ -1010,11 +1011,15 @@ public final class BufferUtils { } public static ByteBuffer createByteBuffer(String data) { - byte[] bytes = data.getBytes(); - ByteBuffer bb = createByteBuffer(bytes.length); - bb.put(bytes); - bb.flip(); - return bb; + try { + byte[] bytes = data.getBytes("UTF-8"); + ByteBuffer bb = createByteBuffer(bytes.length); + bb.put(bytes); + bb.flip(); + return bb; + } catch (UnsupportedEncodingException ex) { + throw new UnsupportedOperationException(ex); + } } /** diff --git a/jme3-core/src/main/java/com/jme3/util/ListMap.java b/jme3-core/src/main/java/com/jme3/util/ListMap.java index 0de4d3f75..379fff741 100644 --- a/jme3-core/src/main/java/com/jme3/util/ListMap.java +++ b/jme3-core/src/main/java/com/jme3/util/ListMap.java @@ -43,21 +43,6 @@ import java.util.Map.Entry; */ public final class ListMap extends AbstractMap implements Cloneable, Serializable { - public static void main(String[] args){ - Map map = new ListMap(); - map.put( "bob", "hello"); - System.out.println(map.get("bob")); - map.remove("bob"); - System.out.println(map.size()); - - map.put("abc", "1"); - map.put("def", "2"); - map.put("ghi", "3"); - map.put("jkl", "4"); - map.put("mno", "5"); - System.out.println(map.get("ghi")); - } - private final static class ListMapEntry implements Map.Entry, Cloneable { private final K key; diff --git a/jme3-core/src/main/java/com/jme3/util/LittleEndien.java b/jme3-core/src/main/java/com/jme3/util/LittleEndien.java index 092f77018..6b15a7d45 100644 --- a/jme3-core/src/main/java/com/jme3/util/LittleEndien.java +++ b/jme3-core/src/main/java/com/jme3/util/LittleEndien.java @@ -42,7 +42,6 @@ import java.io.*; public class LittleEndien extends InputStream implements DataInput { protected BufferedInputStream in; - protected BufferedReader inRead; /** * Creates a new LittleEndien reader from the given input stream. The @@ -51,7 +50,6 @@ public class LittleEndien extends InputStream implements DataInput { */ public LittleEndien(InputStream in) { this.in = new BufferedInputStream(in); - inRead = new BufferedReader(new InputStreamReader(in)); } public int read() throws IOException { @@ -141,7 +139,7 @@ public class LittleEndien extends InputStream implements DataInput { } public String readLine() throws IOException { - return inRead.readLine(); + throw new IOException("Unsupported operation"); } public String readUTF() throws IOException { diff --git a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java index 0f9aac1fc..5e85378ff 100644 --- a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java +++ b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java @@ -612,9 +612,9 @@ public class TangentBinormalGenerator { normal.normalizeLocal(); return new TriangleData( - tangent, - binormal, - normal); + tangent.clone(), + binormal.clone(), + normal.clone()); } finally { tmp.release(); } diff --git a/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.frag b/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.frag index 619682ce0..4a4b433de 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.frag +++ b/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.frag @@ -1,3 +1,5 @@ +#import "Common/ShaderLib/GLSLCompat.glsllib" + #ifdef TEXTURE uniform sampler2D m_Texture; varying vec2 texCoord; diff --git a/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.j3md b/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.j3md index f37f6c979..23fbff826 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.j3md +++ b/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.j3md @@ -7,8 +7,8 @@ MaterialDef Default GUI { } Technique { - VertexShader GLSL100: Common/MatDefs/Gui/Gui.vert - FragmentShader GLSL100: Common/MatDefs/Gui/Gui.frag + VertexShader GLSL150: Common/MatDefs/Gui/Gui.vert + FragmentShader GLSL150: Common/MatDefs/Gui/Gui.frag WorldParameters { WorldViewProjectionMatrix @@ -21,6 +21,17 @@ MaterialDef Default GUI { } Technique { + VertexShader GLSL100: Common/MatDefs/Gui/Gui.vert + FragmentShader GLSL100: Common/MatDefs/Gui/Gui.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + TEXTURE : Texture + VERTEX_COLOR : VertexColor + } } } \ No newline at end of file diff --git a/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.vert b/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.vert index 7640573dc..f0c50f5be 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.vert +++ b/jme3-core/src/main/resources/Common/MatDefs/Gui/Gui.vert @@ -1,3 +1,5 @@ +#import "Common/ShaderLib/GLSLCompat.glsllib" + uniform mat4 g_WorldViewProjectionMatrix; uniform vec4 m_Color; diff --git a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag index 107597047..0aa4d3f36 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag +++ b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag @@ -37,6 +37,7 @@ varying vec3 SpecularSum; #endif #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING) uniform float m_ParallaxHeight; + varying vec3 vViewDirPrlx; #endif #ifdef LIGHTMAP @@ -78,18 +79,18 @@ void main(){ #ifdef STEEP_PARALLAX #ifdef NORMALMAP_PARALLAX //parallax map is stored in the alpha channel of the normal map - newTexCoord = steepParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight); + newTexCoord = steepParallaxOffset(m_NormalMap, vViewDirPrlx, texCoord, m_ParallaxHeight); #else //parallax map is a texture - newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight); + newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDirPrlx, texCoord, m_ParallaxHeight); #endif #else #ifdef NORMALMAP_PARALLAX //parallax map is stored in the alpha channel of the normal map - newTexCoord = classicParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight); + newTexCoord = classicParallaxOffset(m_NormalMap, vViewDirPrlx, texCoord, m_ParallaxHeight); #else //parallax map is a texture - newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight); + newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDirPrlx, texCoord, m_ParallaxHeight); #endif #endif #else @@ -153,8 +154,9 @@ void main(){ #ifdef VERTEX_LIGHTING vec2 light = vertexLightValues.xy; #ifdef COLORRAMP - light.x = texture2D(m_ColorRamp, vec2(light.x, 0.0)).r; - light.y = texture2D(m_ColorRamp, vec2(light.y, 0.0)).r; + diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb; + specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb; + light.xy = vec2(1.0); #endif gl_FragColor.rgb = AmbientSum * diffuseColor.rgb + @@ -182,8 +184,9 @@ void main(){ vec2 light = computeLighting(normal, viewDir, lightDir.xyz, lightDir.w * spotFallOff, m_Shininess) ; #ifdef COLORRAMP - diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb; - specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb; + diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb; + specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb; + light.xy = vec2(1.0); #endif // Workaround, since it is not possible to modify varying variables diff --git a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.vert b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.vert index f92b91fff..df441ed59 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.vert +++ b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.vert @@ -48,6 +48,10 @@ varying vec3 lightVec; uniform vec4 g_LightDirection; #endif +#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING) + varying vec3 vViewDirPrlx; +#endif + #ifdef USE_REFLECTION uniform vec3 g_CameraPosition; @@ -107,17 +111,25 @@ void main(){ wvLightPos.w = g_LightPosition.w; vec4 lightColor = g_LightColor; - #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING) + #if (defined(NORMALMAP) || defined(PARALLAXMAP)) && !defined(VERTEX_LIGHTING) vec3 wvTangent = normalize(TransformNormal(modelSpaceTan)); vec3 wvBinormal = cross(wvNormal, wvTangent); mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal); + #endif - vViewDir = -wvPosition * tbnMat; + #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING) + vViewDir = -wvPosition * tbnMat; + #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) + vViewDirPrlx = vViewDir; + #endif lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec); vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz; #elif !defined(VERTEX_LIGHTING) vNormal = wvNormal; vViewDir = viewDir; + #if defined(PARALLAXMAP) + vViewDirPrlx = -wvPosition * tbnMat; + #endif lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec); #endif diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/ColoredTextured.j3md b/jme3-core/src/main/resources/Common/MatDefs/Misc/ColoredTextured.j3md index 6b74c3074..497b7d0a7 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Misc/ColoredTextured.j3md +++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/ColoredTextured.j3md @@ -1,3 +1,4 @@ +Exception This material definition is deprecated. Please use Unshaded.j3md instead. MaterialDef Colored Textured { MaterialParameters { @@ -17,4 +18,4 @@ MaterialDef Colored Textured { Technique { } -} \ No newline at end of file +} diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.frag b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.frag index ce8219b6e..e615d8f1e 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.frag +++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.frag @@ -1,3 +1,5 @@ +#import "Common/ShaderLib/GLSLCompat.glsllib" + #if defined(HAS_GLOWMAP) || defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD)) #define NEED_TEXCOORD1 #endif diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md index aee284705..8dd6fc5ca 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md +++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md @@ -13,7 +13,7 @@ MaterialDef Unshaded { Color GlowColor // For instancing - Boolean UseInstancing + Boolean UseInstancing // For hardware skinning Int NumberOfBones @@ -54,8 +54,8 @@ MaterialDef Unshaded { } Technique { - VertexShader GLSL100: Common/MatDefs/Misc/Unshaded.vert - FragmentShader GLSL100: Common/MatDefs/Misc/Unshaded.frag + VertexShader GLSL150: Common/MatDefs/Misc/Unshaded.vert + FragmentShader GLSL150: Common/MatDefs/Misc/Unshaded.frag WorldParameters { WorldViewProjectionMatrix @@ -76,6 +76,25 @@ MaterialDef Unshaded { } Technique { + VertexShader GLSL100: Common/MatDefs/Misc/Unshaded.vert + FragmentShader GLSL100: Common/MatDefs/Misc/Unshaded.frag + + WorldParameters { + WorldViewProjectionMatrix + ViewProjectionMatrix + ViewMatrix + } + + Defines { + INSTANCING : UseInstancing + SEPARATE_TEXCOORD : SeparateTexCoord + HAS_COLORMAP : ColorMap + HAS_LIGHTMAP : LightMap + HAS_VERTEXCOLOR : VertexColor + HAS_COLOR : Color + NUM_BONES : NumberOfBones + DISCARD_ALPHA : AlphaDiscardThreshold + } } Technique PreNormalPass { diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.vert b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.vert index 63b05ef88..ba7899ca5 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.vert +++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.vert @@ -1,3 +1,4 @@ +#import "Common/ShaderLib/GLSLCompat.glsllib" #import "Common/ShaderLib/Skinning.glsllib" #import "Common/ShaderLib/Instancing.glsllib" diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/UnshadedNodes.j3md b/jme3-core/src/main/resources/Common/MatDefs/Misc/UnshadedNodes.j3md index f9fb05288..b35c17a9d 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Misc/UnshadedNodes.j3md +++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/UnshadedNodes.j3md @@ -1,97 +1,121 @@ -MaterialDef UnshadedNodes { - - MaterialParameters { - Texture2D ColorMap - Texture2D LightMap - Color Color (Color) - Boolean VertexColor (UseVertexColor) - Boolean SeparateTexCoord - - // Alpha threshold for fragment discarding - Float AlphaDiscardThreshold (AlphaTestFallOff) - - // For hardware skinning - Int NumberOfBones - Matrix4Array BoneMatrices - - } - - Technique { - - WorldParameters { - WorldViewProjectionMatrix - //used for fog - WorldViewMatrix - } - - VertexShaderNodes{ - ShaderNode GpuSkinning{ - Definition: BasicGPUSkinning : Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn - Condition : NumberOfBones - InputMapping{ - modelPosition = Global.position; - boneMatrices = MatParam.BoneMatrices - boneWeight = Attr.inHWBoneWeight - boneIndex = Attr.inHWBoneIndex - } - OutputMapping{ - Global.position = modModelPosition - } - } - ShaderNode UnshadedVert{ - Definition: CommonVert : Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn - InputMapping{ - worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix - modelPosition = Global.position.xyz - texCoord1 = Attr.inTexCoord: ColorMap || (LightMap && !SeparateTexCoord) - texCoord2 = Attr.inTexCoord2: SeparateTexCoord - vertColor = Attr.inColor: VertexColor - } - OutputMapping{ - Global.position = projPosition - } - } - } - FragmentShaderNodes{ - ShaderNode UnshadedFrag{ - Definition: Unshaded : Common/MatDefs/ShaderNodes/Common/Unshaded.j3sn - InputMapping{ - texCoord = UnshadedVert.texCoord1: ColorMap - vertColor = UnshadedVert.vertColor: VertexColor - matColor = MatParam.Color: Color - colorMap = MatParam.ColorMap: ColorMap - color = Global.outColor - } - OutputMapping{ - Global.outColor = color - } - } - - ShaderNode AlphaDiscardThreshold{ - Definition: AlphaDiscard : Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn - Condition : AlphaDiscardThreshold - InputMapping{ - alpha = Global.outColor.a - threshold = MatParam.AlphaDiscardThreshold - } - } - ShaderNode LightMap{ - Definition: LightMapping : Common/MatDefs/ShaderNodes/LightMapping/LightMapping.j3sn - Condition: LightMap - InputMapping{ - texCoord = UnshadedVert.texCoord1: !SeparateTexCoord - texCoord = UnshadedVert.texCoord2: SeparateTexCoord - lightMap = MatParam.LightMap - color = Global.outColor - } - OutputMapping{ - Global.outColor = color - } - } - - } - - } - - +MaterialDef UnshadedNodes { + MaterialParameters { + Texture2D ColorMap + Texture2D LightMap + Color Color (Color) + Boolean VertexColor (UseVertexColor) + Boolean SeparateTexCoord + Float AlphaDiscardThreshold (AlphaTestFallOff) + Int NumberOfBones + Matrix4Array BoneMatrices + } + Technique { + WorldParameters { + WorldViewProjectionMatrix + WorldViewMatrix + } + VertexShaderNodes { + ShaderNode GpuSkinning { + Definition : BasicGPUSkinning : Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn + Condition : NumberOfBones + InputMapping { + modelPosition = Global.position + boneMatrices = MatParam.BoneMatrices + boneWeight = Attr.inHWBoneWeight + boneIndex = Attr.inHWBoneIndex + } + OutputMapping { + Global.position = modModelPosition + } + } + ShaderNode UnshadedVert { + Definition : CommonVert : Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn + InputMapping { + worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix + modelPosition = Global.position.xyz + texCoord1 = Attr.inTexCoord : ColorMap || (LightMap && !SeparateTexCoord) + texCoord2 = Attr.inTexCoord2 : SeparateTexCoord + vertColor = Attr.inColor : VertexColor + } + OutputMapping { + Global.position = projPosition + } + } + } + FragmentShaderNodes { + ShaderNode MatColorMult { + Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn + InputMappings { + color1 = MatParam.Color + color2 = Global.outColor + } + OutputMappings { + Global.outColor = outColor + } + Condition : Color + } + ShaderNode VertColorMult { + Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn + InputMappings { + color1 = UnshadedVert.vertColor + color2 = Global.outColor + } + OutputMappings { + Global.outColor = outColor + } + Condition : VertexColor + } + ShaderNode ColorMapTF { + Definition : TextureFetch : Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn + InputMappings { + texCoord = UnshadedVert.texCoord1 + textureMap = MatParam.ColorMap + } + OutputMappings { + } + Condition : ColorMap + } + ShaderNode ColorMapMult { + Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn + InputMappings { + color1 = ColorMapTF.outColor + color2 = Global.outColor + } + OutputMappings { + Global.outColor = outColor + } + Condition : ColorMap + } + ShaderNode AlphaDiscardThreshold { + Definition : AlphaDiscard : Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn + Condition : AlphaDiscardThreshold + InputMapping { + alpha = Global.outColor.a + threshold = MatParam.AlphaDiscardThreshold + } + } + ShaderNode LightMapTF { + Definition : TextureFetch : Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn + InputMappings { + textureMap = MatParam.LightMap + texCoord = UnshadedVert.texCoord2 : SeparateTexCoord + texCoord = UnshadedVert.texCoord1 : !SeparateTexCoord + } + OutputMappings { + } + Condition : LightMap + } + ShaderNode LightMapMult { + Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn + OutputMappings { + Global.outColor = outColor + } + InputMappings { + color1 = LightMapTF.outColor + color2 = Global.outColor + } + Condition : LightMap + } + } + } } \ No newline at end of file diff --git a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn index b4ccd3640..034fcd116 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn +++ b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn @@ -2,14 +2,15 @@ ShaderNodeDefinitions{ ShaderNodeDefinition TextureFetch { Type: Fragment Shader GLSL100: Common/MatDefs/ShaderNodes/Basic/texture.frag + Shader GLSL150: Common/MatDefs/ShaderNodes/Basic/texture15.frag Documentation{ Fetches a color value in the given texture acording to given texture coordinates - @input texture the texture to read + @input textureMap the texture to read @input texCoord the texture coordinates @output outColor the fetched color } Input { - sampler2D texture + sampler2D textureMap vec2 texCoord } Output { diff --git a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/texture.frag b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/texture.frag index eb83a7b1f..163fbc123 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/texture.frag +++ b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/texture.frag @@ -1,3 +1,3 @@ void main(){ - outColor = texture2D(texture,texCoord); + outColor = texture2D(textureMap,texCoord); } \ No newline at end of file diff --git a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/texture15.frag b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/texture15.frag new file mode 100644 index 000000000..2ece0a646 --- /dev/null +++ b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Basic/texture15.frag @@ -0,0 +1,3 @@ +void main(){ + outColor = texture(textureMap,texCoord); +} \ No newline at end of file diff --git a/jme3-core/src/main/resources/Common/ShaderLib/GLSL150Compat.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/GLSL150Compat.glsllib deleted file mode 100644 index 336490696..000000000 --- a/jme3-core/src/main/resources/Common/ShaderLib/GLSL150Compat.glsllib +++ /dev/null @@ -1,14 +0,0 @@ -#if _VERSION_ >= 150 -out vec4 outFragColor; -# define texture1D texture -# define texture2D texture -# define texture3D texture -# define texture2DLod texture -# if defined VERTEX_SHADER -# define varying out -# define attribute in -# elif defined FRAGMENT_SHADER -# define varying in -# define gl_FragColor outFragColor -# endif -#endif \ No newline at end of file diff --git a/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib new file mode 100644 index 000000000..3d23b7915 --- /dev/null +++ b/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib @@ -0,0 +1,34 @@ +#if defined GL_ES +# define hfloat highp float +# define hvec2 highp vec2 +# define hvec3 highp vec3 +# define hvec4 highp vec4 +# define lfloat lowp float +# define lvec2 lowp vec2 +# define lvec3 lowp vec3 +# define lvec4 lowp vec4 +#else +# define hfloat float +# define hvec2 vec2 +# define hvec3 vec3 +# define hvec4 vec4 +# define lfloat float +# define lvec2 vec2 +# define lvec3 vec3 +# define lvec4 vec4 +#endif + +#if __VERSION__ >= 130 +out vec4 outFragColor; +# define texture1D texture +# define texture2D texture +# define texture3D texture +# define texture2DLod texture +# if defined VERTEX_SHADER +# define varying out +# define attribute in +# elif defined FRAGMENT_SHADER +# define varying in +# define gl_FragColor outFragColor +# endif +#endif \ No newline at end of file diff --git a/jme3-core/src/main/resources/com/jme3/system/version.properties b/jme3-core/src/main/resources/com/jme3/system/version.properties new file mode 100644 index 000000000..98168a14e --- /dev/null +++ b/jme3-core/src/main/resources/com/jme3/system/version.properties @@ -0,0 +1,11 @@ +# THIS IS AN AUTO-GENERATED FILE.. +# DO NOT MODIFY! +build.date=1900-01-01 +git.revision=0 +git.branch=unknown +git.hash= +git.hash.short= +git.tag= +name.full=jMonkeyEngine 3.1.0-UNKNOWN +version.number=3.1.0 +version.tag=SNAPSHOT \ No newline at end of file diff --git a/jme3-core/src/main/resources/joystick-mapping.properties b/jme3-core/src/main/resources/joystick-mapping.properties index d7ce2f50a..b4f1b77bd 100644 --- a/jme3-core/src/main/resources/joystick-mapping.properties +++ b/jme3-core/src/main/resources/joystick-mapping.properties @@ -63,3 +63,53 @@ Xbox\ 360\ Wireless\ Receiver.AXIS_RX=z Xbox\ 360\ Wireless\ Receiver.AXIS_RY=rz Xbox\ 360\ Wireless\ Receiver.z=AXIS_RX Xbox\ 360\ Wireless\ Receiver.rz=AXIS_RY + +# Microsoft PC-joystick driver +Microsoft\ PC-joystick\ driver.12=POV +Y +Microsoft\ PC-joystick\ driver.13=POV +X +Microsoft\ PC-joystick\ driver.14=POV -Y +Microsoft\ PC-joystick\ driver.15=POV -X + +# Logitech F310 gamepad with dip switch DirectInput +Logitech\ Dual\ Action.1=2 +Logitech\ Dual\ Action.2=1 +Logitech\ Dual\ Action.3=0 +Logitech\ Dual\ Action.0=3 + +# Logitech F310 gamepad with dip switch XInput +Gamepad\ F310\ (Controller).0=2 +Gamepad\ F310\ (Controller).1=1 +Gamepad\ F310\ (Controller).2=3 +Gamepad\ F310\ (Controller).3=0 + +Gamepad\ F310\ (Controller).6=8 +Gamepad\ F310\ (Controller).7=9 + +Gamepad\ F310\ (Controller).8=10 +Gamepad\ F310\ (Controller).9=11 + +Gamepad\ F310\ (Controller).rx=z +Gamepad\ F310\ (Controller).ry=rz + +# requires custom code to support trigger buttons but this +# keeps it from confusing the .rx mapping. +Gamepad\ F310\ (Controller).z=trigger + +# Alternate version of the XBOX 360 controller +XBOX\ 360\ For\ Windows\ (Controller).0=2 +XBOX\ 360\ For\ Windows\ (Controller).1=1 +XBOX\ 360\ For\ Windows\ (Controller).2=3 +XBOX\ 360\ For\ Windows\ (Controller).3=0 + +XBOX\ 360\ For\ Windows\ (Controller).6=8 +XBOX\ 360\ For\ Windows\ (Controller).7=9 + +XBOX\ 360\ For\ Windows\ (Controller).8=10 +XBOX\ 360\ For\ Windows\ (Controller).9=11 + +XBOX\ 360\ For\ Windows\ (Controller).rx=z +XBOX\ 360\ For\ Windows\ (Controller).ry=rz + +# requires custom code to support trigger buttons but this +# keeps it from confusing the .rx mapping. +XBOX\ 360\ For\ Windows\ (Controller).z=trigger diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 0c81c3e14..13a8e0232 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java @@ -43,7 +43,6 @@ import com.jme3.math.Vector3f; import com.jme3.shader.Shader; import com.jme3.shader.VarType; import com.jme3.texture.Texture; -import com.jme3.texture.Texture.WrapMode; import com.jme3.texture.Texture2D; import com.jme3.texture.image.ColorSpace; import com.jme3.util.PlaceholderAssets; @@ -52,10 +51,13 @@ import com.jme3.util.blockparser.Statement; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class J3MLoader implements AssetLoader { @@ -63,7 +65,7 @@ public class J3MLoader implements AssetLoader { // private ErrorLogger errors; private ShaderNodeLoaderDelegate nodesLoaderDelegate; boolean isUseNodes = false; - + private AssetManager assetManager; private AssetKey key; @@ -126,59 +128,146 @@ public class J3MLoader implements AssetLoader { technique.setShadowMode(sm); } - private Object readValue(VarType type, String value) throws IOException{ - if (type.isTextureType()){ -// String texturePath = readString("[\n;(//)(\\})]"); - String texturePath = value.trim(); - boolean flipY = false; - boolean repeat = false; - if (texturePath.startsWith("Flip Repeat ")){ - texturePath = texturePath.substring(12).trim(); - flipY = true; - repeat = true; - }else if (texturePath.startsWith("Flip ")){ - texturePath = texturePath.substring(5).trim(); - flipY = true; - }else if (texturePath.startsWith("Repeat ")){ - texturePath = texturePath.substring(7).trim(); - repeat = true; + private List tokenizeTextureValue(final String value) { + final List matchList = new ArrayList(); + final Pattern regex = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'"); + final Matcher regexMatcher = regex.matcher(value.trim()); + + while (regexMatcher.find()) { + if (regexMatcher.group(1) != null) { + matchList.add(regexMatcher.group(1)); + } else if (regexMatcher.group(2) != null) { + matchList.add(regexMatcher.group(2)); + } else { + matchList.add(regexMatcher.group()); } + } - TextureKey texKey = new TextureKey(texturePath, flipY); - switch (type) { - case Texture3D: - texKey.setTextureTypeHint(Texture.Type.ThreeDimensional); - break; - case TextureArray: - texKey.setTextureTypeHint(Texture.Type.TwoDimensionalArray); - break; - case TextureCubeMap: - texKey.setTextureTypeHint(Texture.Type.CubeMap); - break; + return matchList; + } + + private List parseTextureOptions(final List values) { + final List matchList = new ArrayList(); + + if (values.isEmpty() || values.size() == 1) { + return matchList; + } + + // Loop through all but the last value, the last one is going to be the path. + for (int i = 0; i < values.size() - 1; i++) { + final String value = values.get(i); + final TextureOption textureOption = TextureOption.getTextureOption(value); + + if (textureOption == null && !value.contains("\\") && !value.contains("/") && !values.get(0).equals("Flip") && !values.get(0).equals("Repeat")) { + logger.log(Level.WARNING, "Unknown texture option \"{0}\" encountered for \"{1}\" in material \"{2}\"", new Object[]{value, key, material.getKey().getName()}); + } else if (textureOption != null){ + final String option = textureOption.getOptionValue(value); + matchList.add(new TextureOptionValue(textureOption, option)); } - texKey.setGenerateMips(true); - - Texture tex; - try { - tex = assetManager.loadTexture(texKey); - } catch (AssetNotFoundException ex){ - logger.log(Level.WARNING, "Cannot locate {0} for material {1}", new Object[]{texKey, key}); - tex = null; + } + + return matchList; + } + + private boolean isTexturePathDeclaredTheTraditionalWay(final int numberOfValues, final int numberOfTextureOptions, final String texturePath) { + return (numberOfValues > 1 && (texturePath.startsWith("Flip Repeat ") || texturePath.startsWith("Flip ") || + texturePath.startsWith("Repeat ") || texturePath.startsWith("Repeat Flip "))) || numberOfTextureOptions == 0; + } + + private Texture parseTextureType(final VarType type, final String value) { + final List textureValues = tokenizeTextureValue(value); + final List textureOptionValues = parseTextureOptions(textureValues); + + TextureKey textureKey = null; + + // If there is only one token on the value, it must be the path to the texture. + if (textureValues.size() == 1) { + textureKey = new TextureKey(textureValues.get(0), false); + } else { + String texturePath = value.trim(); + + // If there are no valid "new" texture options specified but the path is split into several parts, lets parse the old way. + if (isTexturePathDeclaredTheTraditionalWay(textureValues.size(), textureOptionValues.size(), texturePath)) { + boolean flipY = false; + + if (texturePath.startsWith("Flip Repeat ") || texturePath.startsWith("Repeat Flip ")) { + texturePath = texturePath.substring(12).trim(); + flipY = true; + } else if (texturePath.startsWith("Flip ")) { + texturePath = texturePath.substring(5).trim(); + flipY = true; + } else if (texturePath.startsWith("Repeat ")) { + texturePath = texturePath.substring(7).trim(); + } + + // Support path starting with quotes (double and single) + if (texturePath.startsWith("\"") || texturePath.startsWith("'")) { + texturePath = texturePath.substring(1); + } + + // Support path ending with quotes (double and single) + if (texturePath.endsWith("\"") || texturePath.endsWith("'")) { + texturePath = texturePath.substring(0, texturePath.length() - 1); + } + + textureKey = new TextureKey(texturePath, flipY); } - if (tex != null){ - if (repeat){ - tex.setWrap(WrapMode.Repeat); - } - }else{ - tex = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager)); - if (repeat){ - tex.setWrap(WrapMode.Repeat); + + if (textureKey == null) { + textureKey = new TextureKey(textureValues.get(textureValues.size() - 1), false); + } + + // Apply texture options to the texture key + if (!textureOptionValues.isEmpty()) { + for (final TextureOptionValue textureOptionValue : textureOptionValues) { + textureOptionValue.applyToTextureKey(textureKey); } - tex.setKey(texKey); - tex.setName(texKey.getName()); - } - return tex; - }else{ + } + } + + switch (type) { + case Texture3D: + textureKey.setTextureTypeHint(Texture.Type.ThreeDimensional); + break; + case TextureArray: + textureKey.setTextureTypeHint(Texture.Type.TwoDimensionalArray); + break; + case TextureCubeMap: + textureKey.setTextureTypeHint(Texture.Type.CubeMap); + break; + } + + textureKey.setGenerateMips(true); + + Texture texture; + + try { + texture = assetManager.loadTexture(textureKey); + } catch (AssetNotFoundException ex){ + logger.log(Level.WARNING, "Cannot locate {0} for material {1}", new Object[]{textureKey, key}); + texture = null; + } + + if (texture == null){ + texture = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager)); + texture.setKey(textureKey); + texture.setName(textureKey.getName()); + } + + // Apply texture options to the texture + if (!textureOptionValues.isEmpty()) { + for (final TextureOptionValue textureOptionValue : textureOptionValues) { + textureOptionValue.applyToTexture(texture); + } + } + + return texture; + } + + private Object readValue(final VarType type, final String value) throws IOException{ + if (type.isTextureType()) { + return parseTextureType(type, value); + } else { String[] split = value.trim().split(whitespacePattern); switch (type){ case Float: @@ -222,15 +311,15 @@ public class J3MLoader implements AssetLoader { } } } - - // [ "(" ")" ] [-LINEAR] [ ":" ] + + // [ "(" ")" ] [-LINEAR] [ ":" ] private void readParam(String statement) throws IOException{ String name; String defaultVal = null; ColorSpace colorSpace = null; - + String[] split = statement.split(":"); - + // Parse default val if (split.length == 1){ // Doesn't contain default value @@ -239,14 +328,14 @@ public class J3MLoader implements AssetLoader { throw new IOException("Parameter statement syntax incorrect"); } statement = split[0].trim(); - defaultVal = split[1].trim(); + defaultVal = split[1].trim(); } - + if (statement.endsWith("-LINEAR")) { colorSpace = ColorSpace.Linear; statement = statement.substring(0, statement.length() - "-LINEAR".length()); } - + // Parse ffbinding int startParen = statement.indexOf("("); if (startParen != -1){ @@ -256,32 +345,32 @@ public class J3MLoader implements AssetLoader { // don't care about bindingStr statement = statement.substring(0, startParen); } - + // Parse type + name split = statement.split(whitespacePattern); if (split.length != 2){ throw new IOException("Parameter statement syntax incorrect"); } - + VarType type; if (split[0].equals("Color")){ type = VarType.Vector4; }else{ type = VarType.valueOf(split[0]); } - + name = split[1]; - + Object defaultValObj = null; - if (defaultVal != null){ + if (defaultVal != null){ defaultValObj = readValue(type, defaultVal); } if(type.isTextureType()){ - materialDef.addMaterialParamTexture(type, name, colorSpace); + materialDef.addMaterialParamTexture(type, name, colorSpace); }else{ materialDef.addMaterialParam(type, name, defaultValObj); } - + } private void readValueParam(String statement) throws IOException{ @@ -376,7 +465,7 @@ public class J3MLoader implements AssetLoader { technique.setRenderState(renderState); renderState = null; } - + private void readForcedRenderState(List renderStates) throws IOException{ renderState = new RenderState(); for (Statement statement : renderStates){ @@ -385,7 +474,7 @@ public class J3MLoader implements AssetLoader { technique.setForcedRenderState(renderState); renderState = null; } - + // [ ":" ] private void readDefine(String statement) throws IOException{ String[] split = statement.split(":"); @@ -405,9 +494,9 @@ public class J3MLoader implements AssetLoader { } } - + private void readTechniqueStatement(Statement statement) throws IOException{ - String[] split = statement.getLine().split("[ \\{]"); + String[] split = statement.getLine().split("[ \\{]"); if (split[0].equals("VertexShader") || split[0].equals("FragmentShader") || split[0].equals("GeometryShader") || @@ -420,12 +509,12 @@ public class J3MLoader implements AssetLoader { readShadowMode(statement.getLine()); }else if (split[0].equals("WorldParameters")){ readWorldParams(statement.getContents()); - }else if (split[0].equals("RenderState")){ + }else if (split[0].equals("RenderState")){ readRenderState(statement.getContents()); - }else if (split[0].equals("ForcedRenderState")){ + }else if (split[0].equals("ForcedRenderState")){ readForcedRenderState(statement.getContents()); - }else if (split[0].equals("Defines")){ - readDefines(statement.getContents()); + }else if (split[0].equals("Defines")){ + readDefines(statement.getContents()); } else if (split[0].equals("ShaderNodesDefinitions")) { initNodesLoader(); if (isUseNodes) { @@ -438,14 +527,16 @@ public class J3MLoader implements AssetLoader { } } else if (split[0].equals("FragmentShaderNodes")) { initNodesLoader(); - if (isUseNodes) { + if (isUseNodes) { nodesLoaderDelegate.readFragmentShaderNodes(statement.getContents()); } + } else if (split[0].equals("NoRender")) { + technique.setNoRender(true); } else { throw new MatParseException(null, split[0], statement); } } - + private void readTransparentStatement(String statement) throws IOException{ String[] split = statement.split(whitespacePattern); if (split.length != 2){ @@ -465,11 +556,11 @@ public class J3MLoader implements AssetLoader { } else { throw new IOException("Technique statement syntax incorrect"); } - + for (Statement statement : techStat.getContents()){ readTechniqueStatement(statement); } - + if(isUseNodes){ nodesLoaderDelegate.computeConditions(); //used for caching later, the shader here is not a file. @@ -479,14 +570,14 @@ public class J3MLoader implements AssetLoader { if (shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)) { technique.setShaderFile(shaderName, shaderLanguage); } - + materialDef.addTechniqueDef(technique); technique = null; shaderLanguage.clear(); shaderName.clear(); } - private void loadFromRoot(List roots) throws IOException{ + private void loadFromRoot(List roots) throws IOException{ if (roots.size() == 2){ Statement exception = roots.get(0); String line = exception.getLine(); @@ -498,7 +589,7 @@ public class J3MLoader implements AssetLoader { }else if (roots.size() != 1){ throw new IOException("Too many roots in J3M/J3MD file"); } - + boolean extending = false; Statement materialStat = roots.get(0); String materialName = materialStat.getLine(); @@ -511,16 +602,16 @@ public class J3MLoader implements AssetLoader { }else{ throw new IOException("Specified file is not a Material file"); } - + String[] split = materialName.split(":", 2); - + if (materialName.equals("")){ - throw new MatParseException("Material name cannot be empty", materialStat); + throw new MatParseException("Material name cannot be empty", materialStat); } if (split.length == 2){ if (!extending){ - throw new MatParseException("Must use 'Material' when extending.", materialStat); + throw new MatParseException("Must use 'Material' when extending.", materialStat); } String extendedMat = split[1].trim(); @@ -535,15 +626,15 @@ public class J3MLoader implements AssetLoader { // material.setAssetName(fileName); }else if (split.length == 1){ if (extending){ - throw new MatParseException("Expected ':', got '{'", materialStat); + throw new MatParseException("Expected ':', got '{'", materialStat); } materialDef = new MaterialDef(assetManager, materialName); // NOTE: pass file name for defs so they can be loaded later materialDef.setAssetName(key.getName()); }else{ - throw new MatParseException("Cannot use colon in material name/path", materialStat); + throw new MatParseException("Cannot use colon in material name/path", materialStat); } - + for (Statement statement : materialStat.getContents()){ split = statement.getLine().split("[ \\{]"); String statType = split[0]; @@ -561,16 +652,16 @@ public class J3MLoader implements AssetLoader { }else if (statType.equals("MaterialParameters")){ readMaterialParams(statement.getContents()); }else{ - throw new MatParseException("Expected material statement, got '"+statType+"'", statement); + throw new MatParseException("Expected material statement, got '"+statType+"'", statement); } } } } - public Object load(AssetInfo info) throws IOException { + public Object load(AssetInfo info) throws IOException { this.assetManager = info.getManager(); - - InputStream in = info.openStream(); + + InputStream in = info.openStream(); try { key = info.getKey(); if (key.getExtension().equals("j3m") && !(key instanceof MaterialKey)) { @@ -584,7 +675,7 @@ public class J3MLoader implements AssetLoader { in.close(); } } - + if (material != null){ // material implementation return material; @@ -593,7 +684,7 @@ public class J3MLoader implements AssetLoader { return materialDef; } } - + public MaterialDef loadMaterialDef(List roots, AssetManager manager, AssetKey key) throws IOException { this.key = key; this.assetManager = manager; @@ -615,6 +706,127 @@ public class J3MLoader implements AssetLoader { nodesLoaderDelegate.setAssetManager(assetManager); } } - } + } + /** + * Texture options allow you to specify how a texture should be initialized by including an option before + * the path to the texture in the .j3m file. + *

    + * Example: + *

    +     *     DiffuseMap: MinTrilinear MagBilinear WrapRepeat_S "some/path/to a/texture.png"
    +     *     
    + * This would apply a minification filter of "Trilinear", a magnification filter of "Bilinear" and set the wrap mode to "Repeat". + *

    + *

    + * Note: If several filters of the same type are added, eg. MinTrilinear MinNearestLinearMipMap, the last one will win. + *

    + */ + private enum TextureOption { + + /** + * Applies a {@link com.jme3.texture.Texture.MinFilter} to the texture. + */ + Min { + @Override + public void applyToTexture(final String option, final Texture texture) { + texture.setMinFilter(Texture.MinFilter.valueOf(option)); + } + }, + + /** + * Applies a {@link com.jme3.texture.Texture.MagFilter} to the texture. + */ + Mag { + @Override + public void applyToTexture(final String option, final Texture texture) { + texture.setMagFilter(Texture.MagFilter.valueOf(option)); + } + }, + + /** + * Applies a {@link com.jme3.texture.Texture.WrapMode} to the texture. This also supports {@link com.jme3.texture.Texture.WrapAxis} + * by adding "_AXIS" to the texture option. For instance if you wanted to repeat on the S (horizontal) axis, you + * would use
    WrapRepeat_S
    as a texture option. + */ + Wrap { + @Override + public void applyToTexture(final String option, final Texture texture) { + final int separatorPosition = option.indexOf("_"); + + if (separatorPosition >= option.length() - 2) { + final String axis = option.substring(separatorPosition + 1); + final String mode = option.substring(0, separatorPosition); + final Texture.WrapAxis wrapAxis = Texture.WrapAxis.valueOf(axis); + texture.setWrap(wrapAxis, Texture.WrapMode.valueOf(mode)); + } else { + texture.setWrap(Texture.WrapMode.valueOf(option)); + } + } + }, + + /** + * Applies a {@link com.jme3.texture.Texture.WrapMode#Repeat} to the texture. This is simply an alias for + * WrapRepeat, please use WrapRepeat instead if possible as this may become deprecated later on. + */ + Repeat { + @Override + public void applyToTexture(final String option, final Texture texture) { + Wrap.applyToTexture("Repeat", texture); + } + }, + + /** + * Applies flipping on the Y axis to the {@link TextureKey#setFlipY(boolean)}. + */ + Flip { + @Override + public void applyToTextureKey(final String option, final TextureKey textureKey) { + textureKey.setFlipY(true); + } + }; + + public String getOptionValue(final String option) { + return option.substring(name().length()); + } + + public void applyToTexture(final String option, final Texture texture) { + } + + public void applyToTextureKey(final String option, final TextureKey textureKey) { + } + + public static TextureOption getTextureOption(final String option) { + for(final TextureOption textureOption : TextureOption.values()) { + if (option.startsWith(textureOption.name())) { + return textureOption; + } + } + + return null; + } + } + + /** + * Internal object used for holding a {@link com.jme3.material.plugins.J3MLoader.TextureOption} and it's value. Also + * contains a couple of convenience methods for applying the TextureOption to either a TextureKey or a Texture. + */ + private static class TextureOptionValue { + + private final TextureOption textureOption; + private final String value; + + public TextureOptionValue(TextureOption textureOption, String value) { + this.textureOption = textureOption; + this.value = value; + } + + public void applyToTextureKey(final TextureKey textureKey) { + textureOption.applyToTextureKey(value, textureKey); + } + + public void applyToTexture(final Texture texture) { + textureOption.applyToTexture(value, texture); + } + } } diff --git a/jme3-core/src/plugins/java/com/jme3/texture/plugins/HDRLoader.java b/jme3-core/src/plugins/java/com/jme3/texture/plugins/HDRLoader.java index 611e208d4..315d71955 100644 --- a/jme3-core/src/plugins/java/com/jme3/texture/plugins/HDRLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/texture/plugins/HDRLoader.java @@ -308,8 +308,8 @@ public class HDRLoader implements AssetLoader { } in.close(); - dataStore.rewind(); - //TODO, HDR color space? considered linear here + dataStore.rewind(); + //HDR files color data is actually stored in linear space. return new Image(pixelFormat, width, height, dataStore, ColorSpace.Linear); } diff --git a/jme3-core/src/test/java/com/jme3/cinematic/CinematicTest.java b/jme3-core/src/test/java/com/jme3/cinematic/CinematicTest.java new file mode 100644 index 000000000..400dbaa9f --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/cinematic/CinematicTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009-2015 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.cinematic; + +import com.jme3.animation.AnimControl; +import com.jme3.animation.Animation; +import com.jme3.cinematic.events.AnimationEvent; +import com.jme3.scene.Node; +import org.junit.Test; + +/** + * + * @author davidB + */ +public class CinematicTest { + + /** + * No NPE or any exception when clear() a new Cinematic + */ + @Test + public void clearEmpty() { + Cinematic sut = new Cinematic(); + sut.clear(); + } + + /** + * No ClassCastException when clear() a Cinematic with AnimationEvent + */ + @Test + public void clearAnimationEvent() { + Cinematic sut = new Cinematic(); + Node model = new Node("model"); + AnimControl ac = new AnimControl(); + ac.addAnim(new Animation("animName", 1.0f)); + model.addControl(ac); + sut.enqueueCinematicEvent(new AnimationEvent(model, "animName")); + sut.initialize(null, null); + sut.clear(); + } +} diff --git a/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java b/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java new file mode 100644 index 000000000..506a1732d --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2009-2015 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.collision; + +import static com.jme3.collision.CollisionUtil.*; + +import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingSphere; +import com.jme3.math.FastMath; +import com.jme3.math.Ray; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Quad; +import org.junit.Test; + +/** + * Tests collision detection between bounding volumes. + * + * @author Kirill Vainer + */ +public class BoundingCollisionTest { + + @Test + public void testBoxBoxCollision() { + BoundingBox box1 = new BoundingBox(Vector3f.ZERO, 1, 1, 1); + BoundingBox box2 = new BoundingBox(Vector3f.ZERO, 1, 1, 1); + checkCollision(box1, box2, 1); + + // Put it at the very edge - should still intersect. + box2.setCenter(new Vector3f(2f, 0f, 0f)); + checkCollision(box1, box2, 1); + + // Put it a wee bit farther - no intersection expected + box2.setCenter(new Vector3f(2f + FastMath.ZERO_TOLERANCE, 0, 0)); + checkCollision(box1, box2, 0); + + // Check the corners. + box2.setCenter(new Vector3f(2f, 2f, 2f)); + checkCollision(box1, box2, 1); + + box2.setCenter(new Vector3f(2f, 2f, 2f + FastMath.ZERO_TOLERANCE)); + checkCollision(box1, box2, 0); + } + + @Test + public void testSphereSphereCollision() { + BoundingSphere sphere1 = new BoundingSphere(1, Vector3f.ZERO); + BoundingSphere sphere2 = new BoundingSphere(1, Vector3f.ZERO); + checkCollision(sphere1, sphere2, 1); + + // Put it at the very edge - should still intersect. + sphere2.setCenter(new Vector3f(2f, 0f, 0f)); + checkCollision(sphere1, sphere2, 1); + + // Put it a wee bit farther - no intersection expected + sphere2.setCenter(new Vector3f(2f + FastMath.ZERO_TOLERANCE, 0, 0)); + checkCollision(sphere1, sphere2, 0); + } + + @Test + public void testBoxSphereCollision() { + BoundingBox box1 = new BoundingBox(Vector3f.ZERO, 1, 1, 1); + BoundingSphere sphere2 = new BoundingSphere(1, Vector3f.ZERO); + checkCollision(box1, sphere2, 1); + + // Put it at the very edge - for sphere vs. box, it will not intersect + sphere2.setCenter(new Vector3f(2f, 0f, 0f)); + checkCollision(box1, sphere2, 0); + + // Put it a wee bit closer - should intersect. + sphere2.setCenter(new Vector3f(2f - FastMath.ZERO_TOLERANCE, 0, 0)); + checkCollision(box1, sphere2, 1); + + // Test if the algorithm converts the sphere + // to a box before testing the collision (incorrect) + float sqrt3 = FastMath.sqrt(3); + + sphere2.setCenter(Vector3f.UNIT_XYZ.mult(2)); + sphere2.setRadius(sqrt3); + checkCollision(box1, sphere2, 0); + + // Make it a wee bit larger. + sphere2.setRadius(sqrt3 + FastMath.ZERO_TOLERANCE); + checkCollision(box1, sphere2, 1); + } + + @Test + public void testBoxRayCollision() { + BoundingBox box = new BoundingBox(Vector3f.ZERO, 1, 1, 1); + Ray ray = new Ray(Vector3f.ZERO, Vector3f.UNIT_Z); + + // XXX: seems incorrect, ray inside box should only generate + // one result... + checkCollision(box, ray, 2); + + ray.setOrigin(new Vector3f(0, 0, -5)); + checkCollision(box, ray, 2); + + // XXX: is this right? the ray origin is on the box's side.. + ray.setOrigin(new Vector3f(0, 0, 2f)); + checkCollision(box, ray, 0); + + ray.setOrigin(new Vector3f(0, 0, -2f)); + checkCollision(box, ray, 2); + + // parallel to the edge, touching the side + ray.setOrigin(new Vector3f(0, 1f, -2f)); + checkCollision(box, ray, 2); + + // still parallel, but not touching the side + ray.setOrigin(new Vector3f(0, 1f + FastMath.ZERO_TOLERANCE, -2f)); + checkCollision(box, ray, 0); + } + + @Test + public void testBoxTriangleCollision() { + BoundingBox box = new BoundingBox(Vector3f.ZERO, 1, 1, 1); + Geometry geom = new Geometry("geom", new Quad(1, 1)); + checkCollision(box, geom, 2); // Both triangles intersect + + // The box touches the edges of the triangles. + box.setCenter(new Vector3f(-1f, 0, 0)); + checkCollision(box, geom, 2); + + // Move it slightly farther.. + box.setCenter(new Vector3f(-1f - FastMath.ZERO_TOLERANCE, 0, 0)); + checkCollision(box, geom, 0); + + // Parallel triangle / box side, touching + box.setCenter(new Vector3f(0, 0, -1f)); + checkCollision(box, geom, 2); + + // Not touching + box.setCenter(new Vector3f(0, 0, -1f - FastMath.ZERO_TOLERANCE)); + checkCollision(box, geom, 0); + + // Test collisions only against one of the triangles + box.setCenter(new Vector3f(-1f, 1.5f, 0f)); + checkCollision(box, geom, 1); + + box.setCenter(new Vector3f(1.5f, -1f, 0f)); + checkCollision(box, geom, 1); + } + + @Test + public void testSphereTriangleCollision() { + BoundingSphere sphere = new BoundingSphere(1, Vector3f.ZERO); + Geometry geom = new Geometry("geom", new Quad(1, 1)); + checkCollision(sphere, geom, 2); + + // The box touches the edges of the triangles. + sphere.setCenter(new Vector3f(-1f + FastMath.ZERO_TOLERANCE, 0, 0)); + checkCollision(sphere, geom, 2); + + // Move it slightly farther.. + sphere.setCenter(new Vector3f(-1f - FastMath.ZERO_TOLERANCE, 0, 0)); + checkCollision(sphere, geom, 0); + + // Parallel triangle / box side, touching + sphere.setCenter(new Vector3f(0, 0, -1f)); + checkCollision(sphere, geom, 2); + + // Not touching + sphere.setCenter(new Vector3f(0, 0, -1f - FastMath.ZERO_TOLERANCE)); + checkCollision(sphere, geom, 0); + + // Test collisions only against one of the triangles + sphere.setCenter(new Vector3f(-0.9f, 1.2f, 0f)); + checkCollision(sphere, geom, 1); + + sphere.setCenter(new Vector3f(1.2f, -0.9f, 0f)); + checkCollision(sphere, geom, 1); + } +} diff --git a/jme3-core/src/test/java/com/jme3/collision/CollisionUtil.java b/jme3-core/src/test/java/com/jme3/collision/CollisionUtil.java new file mode 100644 index 000000000..43d7b20f0 --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/collision/CollisionUtil.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009-2015 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.collision; + +import com.jme3.bounding.BoundingVolume; + +/** + * Utilities for testing collision. + * + * @author Kirill Vainer + */ +final class CollisionUtil { + + private static void checkCollisionBase(Collidable a, Collidable b, int expected) { + // Test bounding volume methods + if (a instanceof BoundingVolume && b instanceof BoundingVolume) { + BoundingVolume bv1 = (BoundingVolume) a; + BoundingVolume bv2 = (BoundingVolume) b; + assert bv1.intersects(bv2) == (expected != 0); + } + + // Test standard collideWith method + CollisionResults results = new CollisionResults(); + int numCollisions = a.collideWith(b, results); + assert results.size() == numCollisions; + assert numCollisions == expected; + + // force the results to be sorted here.. + results.getClosestCollision(); + + if (results.size() > 0) { + assert results.getCollision(0) == results.getClosestCollision(); + } + if (results.size() == 1) { + assert results.getClosestCollision() == results.getFarthestCollision(); + } + } + + /** + * Tests various collisions between the two collidables and + * the transitive property. + * + * @param a First collidable + * @param b Second collidable + * @param expect Number of expected results + */ + public static void checkCollision(Collidable a, Collidable b, int expected) { + checkCollisionBase(a, b, expected); + checkCollisionBase(b, a, expected); + } +} diff --git a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java new file mode 100644 index 000000000..447682964 --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2009-2015 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.light; + +import com.jme3.bounding.BoundingSphere; +import com.jme3.math.FastMath; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Box; +import com.jme3.util.TempVars; +import org.junit.Before; +import org.junit.Test; + +/** + * Test light filtering for various light types. + * + * @author Kirill Vainer + */ +public class LightFilterTest { + + private DefaultLightFilter filter; + private Camera cam; + private Geometry geom; + private LightList list; + + private void checkFilteredLights(int expected) { + geom.updateGeometricState(); + filter.setCamera(cam); // setCamera resets the intersection cache + list.clear(); + filter.filterLights(geom, list); + assert list.size() == expected; + } + + @Before + public void setUp() { + filter = new DefaultLightFilter(); + + cam = new Camera(512, 512); + cam.setFrustumPerspective(45, 1, 1, 1000); + cam.setLocation(Vector3f.ZERO); + cam.lookAtDirection(Vector3f.UNIT_Z, Vector3f.UNIT_Y); + filter.setCamera(cam); + + Box box = new Box(1, 1, 1); + geom = new Geometry("geom", box); + geom.setLocalTranslation(0, 0, 10); + geom.updateGeometricState(); + list = new LightList(geom); + } + + @Test + public void testAmbientFiltering() { + geom.addLight(new AmbientLight()); + checkFilteredLights(1); // Ambient lights must never be filtered + + // Test for bounding Sphere + geom.setModelBound(new BoundingSphere(0.5f, Vector3f.ZERO)); + checkFilteredLights(1); // Ambient lights must never be filtered + } + + @Test + public void testDirectionalFiltering() { + geom.addLight(new DirectionalLight(Vector3f.UNIT_Y)); + checkFilteredLights(1); // Directional lights must never be filtered + + // Test for bounding Sphere + geom.setModelBound(new BoundingSphere(0.5f, Vector3f.ZERO)); + checkFilteredLights(1); // Directional lights must never be filtered + } + + @Test + public void testPointFiltering() { + PointLight pl = new PointLight(Vector3f.ZERO); + geom.addLight(pl); + checkFilteredLights(1); // Infinite point lights must never be filtered + + // Light at origin does not intersect geom which is at Z=10 + pl.setRadius(1); + checkFilteredLights(0); + + // Put it closer to geom, the very edge of the sphere touches the box. + // Still not considered an intersection though. + pl.setPosition(new Vector3f(0, 0, 8f)); + checkFilteredLights(0); + + // And more close - now its an intersection. + pl.setPosition(new Vector3f(0, 0, 8f + FastMath.ZERO_TOLERANCE)); + checkFilteredLights(1); + + // Move the geometry away + geom.move(0, 0, FastMath.ZERO_TOLERANCE); + checkFilteredLights(0); + + // Test if the algorithm converts the sphere + // to a box before testing the collision (incorrect) + float sqrt3 = FastMath.sqrt(3); + + pl.setPosition(new Vector3f(2, 2, 8)); + pl.setRadius(sqrt3); + checkFilteredLights(0); + + // Make it a wee bit larger. + pl.setRadius(sqrt3 + FastMath.ZERO_TOLERANCE); + checkFilteredLights(1); + + // Rotate the camera so it is up, light is outside frustum. + cam.lookAtDirection(Vector3f.UNIT_Y, Vector3f.UNIT_Y); + checkFilteredLights(0); + + // ================================== + // Tests for bounding Sphere + geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO)); + geom.setLocalTranslation(0, 0, 2); + pl.setPosition(new Vector3f(0, 0, 2f)); + + // Infinite point lights must never be filtered + pl.setRadius(0); + checkFilteredLights(1); + + pl.setRadius(1f); + // Put the light at the very close to the geom, + // the very edge of the sphere touches the other bounding sphere + // Still not considered an intersection though. + pl.setPosition(new Vector3f(0, 0, 0)); + checkFilteredLights(0); + + // And more close - now its an intersection. + pl.setPosition(new Vector3f(0, 0, 0f + FastMath.ZERO_TOLERANCE)); + checkFilteredLights(1); + + geom.setLocalTranslation(0, 0, 0); + // In this case its an intersection for pointLight v. box + // But not for pointLight v. sphere + // Vector3f(0, 0.5f, 0.5f).normalize().mult(2) ~ >= (0.0, 1.4142135, 1.4142135) + //pl.setPosition(new Vector3f(0, 0.5f, 0.5f).normalizeLocal().multLocal(2 + FastMath.ZERO_TOLERANCE)); + pl.setPosition(new Vector3f(0f, 1.4142135f, 1.4142135f).multLocal(1+FastMath.ZERO_TOLERANCE)); + checkFilteredLights(0); + + // Make the distance a wee bit closer, now its an intersection + //pl.setPosition(new Vector3f(0, 0.5f, 0.5f).normalizeLocal().multLocal(2 - FastMath.ZERO_TOLERANCE)); + pl.setPosition(new Vector3f(0f, 1.4142135f, 1.4142135f).multLocal(1-FastMath.ZERO_TOLERANCE)); + checkFilteredLights(1); + + // it's a point light, also test for the other corner + pl.setPosition(new Vector3f(0f, -1.4142135f, -1.4142135f).multLocal(1-FastMath.ZERO_TOLERANCE)); + checkFilteredLights(0); + + } + + @Test + public void testSpotFiltering() { + SpotLight sl = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_Z); + sl.setSpotRange(0); + geom.addLight(sl); + checkFilteredLights(1); // Infinite spot lights are only filtered + // if the geometry is outside the infinite cone. + + TempVars vars = TempVars.get(); + try { + // The spot is not touching the near plane of the camera yet, + // should still be culled. + sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE); + assert !sl.intersectsFrustum(cam, vars); + // should be culled from the geometry's PoV + checkFilteredLights(0); + + // Now it touches the near plane. + sl.setSpotRange(1f); + // still culled from the geometry's PoV + checkFilteredLights(0); + assert sl.intersectsFrustum(cam, vars); + } finally { + vars.release(); + } + + // make it barely reach the geometry + sl.setSpotRange(9f); + checkFilteredLights(0); + + // make it reach the geometry (touching its bound) + sl.setSpotRange(9f + FastMath.ZERO_TOLERANCE); + checkFilteredLights(1); + + // rotate the cone a bit so it no longer faces the geom + sl.setDirection(new Vector3f(0.316f, 0, 0.948f).normalizeLocal()); + checkFilteredLights(0); + + // extent the range much farther + sl.setSpotRange(20); + checkFilteredLights(0); + + // Create box of size X=10 (double the extent) + // now, the spot will touch the box. + geom.setMesh(new Box(5, 1, 1)); + checkFilteredLights(1); + + // ================================== + // Tests for bounding sphere, with a radius of 1f (in the box geom) + sl.setPosition(Vector3f.ZERO); + sl.setDirection(Vector3f.UNIT_Z); + geom.setLocalTranslation(Vector3f.ZERO); + geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO)); + + // Infinit spot lights are only filtered + // if the geometry is outside the infinite cone. + sl.setSpotRange(0); + checkFilteredLights(1); + + //the geommetry is outside the infinit cone (cone direction going away from the geom) + sl.setPosition(Vector3f.UNIT_Z.mult(1+FastMath.ZERO_TOLERANCE)); + checkFilteredLights(0); + + //place the spote ligth in the corner of the box geom, (in order to test bounding sphere) + sl.setDirection(new Vector3f(1, 1, 0).normalizeLocal()); + geom.setLocalTranslation(0, 0, 10); + sl.setPosition(sl.getDirection().mult(-2f).add(geom.getLocalTranslation())); + + // make it barely reach the sphere, incorect with a box + sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE); + checkFilteredLights(0); + + // make it reach the sphere + sl.setSpotRange(1f + FastMath.ZERO_TOLERANCE); + checkFilteredLights(1); + + // extent the range + sl.setPosition(Vector3f.ZERO); + sl.setDirection(Vector3f.UNIT_Z); + sl.setSpotRange(20); + checkFilteredLights(1); + + // rotate the cone a bit so it no longer faces the geom + sl.setDirection(new Vector3f(0, 0.3f, 0.7f).normalizeLocal()); + checkFilteredLights(0); + + // Create sphere of size X=10 (double the radius) + // now, the spot will touch the sphere. + geom.setModelBound(new BoundingSphere(5f, Vector3f.ZERO)); + checkFilteredLights(1); + } +} diff --git a/jme3-core/src/test/java/com/jme3/light/LightSortTest.java b/jme3-core/src/test/java/com/jme3/light/LightSortTest.java new file mode 100644 index 000000000..593cc9d3e --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/light/LightSortTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2009-2015 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.light; + +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import org.junit.Test; + +/** + * Test light sorting (in the scene graph) for various light types. + * + * @author Kirill Vainer + */ +public class LightSortTest { + + @Test + public void testSimpleSort() { + Geometry g = new Geometry("test", new Mesh()); + LightList list = new LightList(g); + + list.add(new SpotLight(Vector3f.ZERO, Vector3f.UNIT_X)); + list.add(new PointLight(Vector3f.UNIT_X)); + list.add(new DirectionalLight(Vector3f.UNIT_X)); + list.add(new AmbientLight()); + + list.sort(true); + + assert list.get(0) instanceof AmbientLight; // Ambients always first + assert list.get(1) instanceof DirectionalLight; // .. then directionals + assert list.get(2) instanceof SpotLight; // Spot is 0 units away from geom + assert list.get(3) instanceof PointLight; // .. and point is 1 unit away. + } + + @Test + public void testSceneGraphSort() { + Node n = new Node("node"); + Geometry g = new Geometry("geom", new Mesh()); + SpotLight spot = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_X); + PointLight point = new PointLight(Vector3f.UNIT_X); + DirectionalLight directional = new DirectionalLight(Vector3f.UNIT_X); + AmbientLight ambient = new AmbientLight(); + + // Some lights are on the node + n.addLight(spot); + n.addLight(point); + + // .. and some on the geometry. + g.addLight(directional); + g.addLight(ambient); + + n.attachChild(g); + n.updateGeometricState(); + + LightList list = g.getWorldLightList(); + + // check the sorting (when geom is at 0,0,0) + assert list.get(0) instanceof AmbientLight; + assert list.get(1) instanceof DirectionalLight; + assert list.get(2) instanceof SpotLight; + assert list.get(3) instanceof PointLight; + + // move the geometry closer to the point light + g.setLocalTranslation(Vector3f.UNIT_X); + n.updateGeometricState(); + + assert list.get(0) instanceof AmbientLight; + assert list.get(1) instanceof DirectionalLight; + assert list.get(2) instanceof PointLight; + assert list.get(3) instanceof SpotLight; + + // now move the point light away from the geometry + // and the spot light closer + + // XXX: doesn't work! jME can't detect that the light moved! +// point.setPosition(Vector3f.ZERO); +// spot.setPosition(Vector3f.UNIT_X); +// n.updateGeometricState(); +// +// assert list.get(0) instanceof AmbientLight; +// assert list.get(1) instanceof DirectionalLight; +// assert list.get(2) instanceof SpotLight; +// assert list.get(3) instanceof PointLight; + } +} diff --git a/jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java b/jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java new file mode 100644 index 000000000..6438baaac --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java @@ -0,0 +1,117 @@ +package com.jme3.material.plugins; + +import com.jme3.asset.AssetInfo; +import com.jme3.asset.AssetKey; +import com.jme3.asset.AssetManager; +import com.jme3.asset.TextureKey; +import com.jme3.material.MatParamTexture; +import com.jme3.material.Material; +import com.jme3.material.MaterialDef; +import com.jme3.shader.VarType; +import com.jme3.texture.Texture; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author Daniel Johansson + * @since 2015-07-20 + */ +@RunWith(MockitoJUnitRunner.class) +public class J3MLoaderTest { + + private J3MLoader j3MLoader; + + @Mock + private AssetInfo assetInfo; + + @Mock + private AssetManager assetManager; + + @Mock + private AssetKey assetKey; + + @Mock + private MaterialDef materialDef; + + @Before + public void setUp() throws Exception { + when(assetKey.getExtension()).thenReturn(".j3m"); + when(assetInfo.getManager()).thenReturn(assetManager); + when(assetInfo.getKey()).thenReturn(assetKey); + when(assetManager.loadAsset(any(AssetKey.class))).thenReturn(materialDef); + + j3MLoader = new J3MLoader(); + } + + @Test + public void oldStyleTextureParameters_shouldBeSupported() throws Exception { + when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/texture-parameters-oldstyle.j3m")); + + final Texture textureOldStyle = Mockito.mock(Texture.class); + final Texture textureOldStyleUsingQuotes = Mockito.mock(Texture.class); + + final TextureKey textureKeyUsingQuotes = setupMockForTexture("OldStyleUsingQuotes", "old style using quotes/texture.png", true, textureOldStyleUsingQuotes); + final TextureKey textureKeyOldStyle = setupMockForTexture("OldStyle", "old style/texture.png", true, textureOldStyle); + + j3MLoader.load(assetInfo); + + verify(assetManager).loadTexture(textureKeyUsingQuotes); + verify(assetManager).loadTexture(textureKeyOldStyle); + verify(textureOldStyle).setWrap(Texture.WrapMode.Repeat); + verify(textureOldStyleUsingQuotes).setWrap(Texture.WrapMode.Repeat); + } + + @Test + public void newStyleTextureParameters_shouldBeSupported() throws Exception { + when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/texture-parameters-newstyle.j3m")); + + final Texture textureNoParameters = Mockito.mock(Texture.class); + final Texture textureFlip = Mockito.mock(Texture.class); + final Texture textureRepeat = Mockito.mock(Texture.class); + final Texture textureRepeatAxis = Mockito.mock(Texture.class); + final Texture textureMin = Mockito.mock(Texture.class); + final Texture textureMag = Mockito.mock(Texture.class); + final Texture textureCombined = Mockito.mock(Texture.class); + + final TextureKey textureKeyNoParameters = setupMockForTexture("Empty", "empty.png", false, textureNoParameters); + final TextureKey textureKeyFlip = setupMockForTexture("Flip", "flip.png", true, textureFlip); + setupMockForTexture("Repeat", "repeat.png", false, textureRepeat); + setupMockForTexture("RepeatAxis", "repeat-axis.png", false, textureRepeatAxis); + setupMockForTexture("Min", "min.png", false, textureMin); + setupMockForTexture("Mag", "mag.png", false, textureMag); + setupMockForTexture("Combined", "combined.png", true, textureCombined); + + j3MLoader.load(assetInfo); + + verify(assetManager).loadTexture(textureKeyNoParameters); + verify(assetManager).loadTexture(textureKeyFlip); + + verify(textureRepeat).setWrap(Texture.WrapMode.Repeat); + verify(textureRepeatAxis).setWrap(Texture.WrapAxis.T, Texture.WrapMode.Repeat); + verify(textureMin).setMinFilter(Texture.MinFilter.Trilinear); + verify(textureMag).setMagFilter(Texture.MagFilter.Bilinear); + + verify(textureCombined).setMagFilter(Texture.MagFilter.Nearest); + verify(textureCombined).setMinFilter(Texture.MinFilter.BilinearNoMipMaps); + verify(textureCombined).setWrap(Texture.WrapMode.Repeat); + } + + private TextureKey setupMockForTexture(final String paramName, final String path, final boolean flipY, final Texture texture) { + when(materialDef.getMaterialParam(paramName)).thenReturn(new MatParamTexture(VarType.Texture2D, paramName, texture, 0, null)); + + final TextureKey textureKey = new TextureKey(path, flipY); + textureKey.setGenerateMips(true); + + when(assetManager.loadTexture(textureKey)).thenReturn(texture); + + return textureKey; + } +} diff --git a/jme3-core/src/test/java/com/jme3/math/FastMathTest.java b/jme3-core/src/test/java/com/jme3/math/FastMathTest.java new file mode 100644 index 000000000..a74390d42 --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/math/FastMathTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009-2015 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.math; + +import org.junit.Test; + +/** + * Verifies that algorithms in {@link FastMath} are working correctly. + * + * @author Kirill Vainer + */ +public class FastMathTest { + + private int nearestPowerOfTwoSlow(int number) { + return (int) Math.pow(2, Math.ceil(Math.log(number) / Math.log(2))); + } + + @Test + public void testNearestPowerOfTwo() { + for (int i = -100; i < 1; i++) { + assert FastMath.nearestPowerOfTwo(i) == 1; + } + for (int i = 1; i < 10000; i++) { + int nextPowerOf2 = FastMath.nearestPowerOfTwo(i); + assert i <= nextPowerOf2; + assert FastMath.isPowerOfTwo(nextPowerOf2); + assert nextPowerOf2 == nearestPowerOfTwoSlow(i); + } + } +} diff --git a/jme3-core/src/test/java/com/jme3/util/ListMapTest.java b/jme3-core/src/test/java/com/jme3/util/ListMapTest.java new file mode 100644 index 000000000..5f4cf3eee --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/util/ListMapTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2009-2015 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.util; + +import java.util.Map.Entry; +import org.junit.Test; + +/** + * Check if the {@link ListMap} class is working correctly. + * + * @author Kirill Vainer + */ +public class ListMapTest { + + @Test + public void testListMap() { + ListMap listMap = new ListMap(); + listMap.put("bob", "hello"); + assert "hello".equals(listMap.get("bob")); + assert "hello".equals(listMap.remove("bob")); + assert listMap.size() == 0; + assert listMap.isEmpty(); + + listMap.put("abc", "1"); + listMap.put("def", "2"); + listMap.put("ghi", "3"); + listMap.put("jkl", "4"); + listMap.put("mno", "5"); + assert "3".equals(listMap.get("ghi")); + assert listMap.size() == 5; + assert !listMap.isEmpty(); + + // check iteration order, should be consistent + for (int i = 0; i < listMap.size(); i++) { + String expectedValue = Integer.toString(i + 1); + String key = listMap.getKey(i); + String value = listMap.getValue(i); + Entry entry = listMap.getEntry(i); + assert key.equals(entry.getKey()); + assert value.equals(entry.getValue()); + assert expectedValue.equals(value); + } + } +} diff --git a/jme3-core/src/test/resources/texture-parameters-newstyle.j3m b/jme3-core/src/test/resources/texture-parameters-newstyle.j3m new file mode 100644 index 000000000..a7619d948 --- /dev/null +++ b/jme3-core/src/test/resources/texture-parameters-newstyle.j3m @@ -0,0 +1,11 @@ +Material Test : matdef.j3md { + MaterialParameters { + Empty: "empty.png" + Flip: Flip "flip.png" + Repeat: WrapRepeat "repeat.png" + Min: MinTrilinear "min.png" + Mag: MagBilinear "mag.png" + RepeatAxis: WrapRepeat_T "repeat-axis.png" + Combined: MagNearest MinBilinearNoMipMaps Flip WrapRepeat "combined.png" + } +} \ No newline at end of file diff --git a/jme3-core/src/test/resources/texture-parameters-oldstyle.j3m b/jme3-core/src/test/resources/texture-parameters-oldstyle.j3m new file mode 100644 index 000000000..7f34af464 --- /dev/null +++ b/jme3-core/src/test/resources/texture-parameters-oldstyle.j3m @@ -0,0 +1,6 @@ +Material Test : matdef.j3md { + MaterialParameters { + OldStyle: Flip Repeat old style/texture.png + OldStyleUsingQuotes: Repeat Flip "old style using quotes/texture.png" + } +} \ No newline at end of file diff --git a/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java b/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java index 4c4cd6562..b3d751465 100644 --- a/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java +++ b/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java @@ -205,7 +205,6 @@ public class MjpegFileWriter { baos.write(fcc3); baos.write(intBytes(swapInt(listSize))); baos.write(fcc4); - baos.close(); return baos.toByteArray(); } @@ -275,7 +274,6 @@ public class MjpegFileWriter { baos.write(intBytes(swapInt(dwReserved[1]))); baos.write(intBytes(swapInt(dwReserved[2]))); baos.write(intBytes(swapInt(dwReserved[3]))); - baos.close(); return baos.toByteArray(); } @@ -295,7 +293,6 @@ public class MjpegFileWriter { baos.write(fcc); baos.write(intBytes(swapInt(size))); baos.write(fcc2); - baos.close(); return baos.toByteArray(); } @@ -365,7 +362,6 @@ public class MjpegFileWriter { baos.write(intBytes(swapInt(top))); baos.write(intBytes(swapInt(right))); baos.write(intBytes(swapInt(bottom))); - baos.close(); return baos.toByteArray(); } @@ -420,7 +416,6 @@ public class MjpegFileWriter { baos.write(intBytes(swapInt(biYPelsPerMeter))); baos.write(intBytes(swapInt(biClrUsed))); baos.write(intBytes(swapInt(biClrImportant))); - baos.close(); return baos.toByteArray(); } @@ -445,7 +440,6 @@ public class MjpegFileWriter { baos.write(fcc); baos.write(intBytes(swapInt(listSize))); baos.write(fcc2); - baos.close(); return baos.toByteArray(); } @@ -480,8 +474,6 @@ public class MjpegFileWriter { baos.write(in.toBytes()); } - baos.close(); - return baos.toByteArray(); } } @@ -504,7 +496,6 @@ public class MjpegFileWriter { baos.write(intBytes(swapInt(dwFlags))); baos.write(intBytes(swapInt(dwOffset))); baos.write(intBytes(swapInt(dwSize))); - baos.close(); return baos.toByteArray(); } @@ -525,7 +516,6 @@ public class MjpegFileWriter { baos.write(fcc); baos.write(intBytes(swapInt(size))); baos.write(data); - baos.close(); return baos.toByteArray(); } @@ -552,7 +542,6 @@ public class MjpegFileWriter { imgWrtr.write(null, new IIOImage(bi, null, null), jpgWrtPrm); imgOutStrm.close(); - baos.close(); return baos.toByteArray(); } } diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java index 2917350f6..707937e78 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java +++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java @@ -31,11 +31,7 @@ */ package com.jme3.system; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; @@ -48,9 +44,8 @@ import java.util.logging.Logger; /** * Utility class to register, extract, and load native libraries. *
    - * Register your own libraries via the - * {@link #registerNativeLibrary(java.lang.String, com.jme3.system.Platform, java.lang.String, boolean) } - * method, for each platform. + * Register your own libraries via the {@link #registerNativeLibrary(String, Platform, String, String)} method, for + * each platform. * You can then extract this library (depending on platform), by * using {@link #loadNativeLibrary(java.lang.String, boolean) }. *
    @@ -132,7 +127,7 @@ public final class NativeLibraryLoader { registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so"); registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); - + // OpenAL // For OSX: Need to add lib prefix when extracting registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll"); @@ -141,7 +136,40 @@ public final class NativeLibraryLoader { registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so"); registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); - + + // LWJGL 3.x + registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/lwjgl32.dll"); + registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/lwjgl.dll"); + registerNativeLibrary("lwjgl3", Platform.Linux32, "native/linux/liblwjgl32.so"); + registerNativeLibrary("lwjgl3", Platform.Linux64, "native/linux/liblwjgl.so"); + registerNativeLibrary("lwjgl3", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); + registerNativeLibrary("lwjgl3", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); + + // GLFW for LWJGL 3.x + registerNativeLibrary("glfw-lwjgl3", Platform.Windows32, "native/windows/glfw32.dll"); + registerNativeLibrary("glfw-lwjgl3", Platform.Windows64, "native/windows/glfw.dll"); + registerNativeLibrary("glfw-lwjgl3", Platform.Linux32, "native/linux/libglfw32.so"); + registerNativeLibrary("glfw-lwjgl3", Platform.Linux64, "native/linux/libglfw.so"); + registerNativeLibrary("glfw-lwjgl3", Platform.MacOSX32, "native/macosx/libglfw.dylib"); + registerNativeLibrary("glfw-lwjgl3", Platform.MacOSX64, "native/macosx/libglfw.dylib"); + + // jemalloc for LWJGL 3.x + registerNativeLibrary("jemalloc-lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll"); + registerNativeLibrary("jemalloc-lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll"); + registerNativeLibrary("jemalloc-lwjgl3", Platform.Linux32, "native/linux/libjemalloc32.so"); + registerNativeLibrary("jemalloc-lwjgl3", Platform.Linux64, "native/linux/libjemalloc.so"); + registerNativeLibrary("jemalloc-lwjgl3", Platform.MacOSX32, "native/macosx/libjemalloc.dylib"); + registerNativeLibrary("jemalloc-lwjgl3", Platform.MacOSX64, "native/macosx/libjemalloc.dylib"); + + // OpenAL for LWJGL 3.x + // For OSX: Need to add lib prefix when extracting + registerNativeLibrary("openal-lwjgl3", Platform.Windows32, "native/windows/OpenAL32.dll"); + registerNativeLibrary("openal-lwjgl3", Platform.Windows64, "native/windows/OpenAL.dll"); + registerNativeLibrary("openal-lwjgl3", Platform.Linux32, "native/linux/libopenal32.so"); + registerNativeLibrary("openal-lwjgl3", Platform.Linux64, "native/linux/libopenal.so"); + registerNativeLibrary("openal-lwjgl3", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); + registerNativeLibrary("openal-lwjgl3", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); + // BulletJme registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll"); registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll"); @@ -461,7 +489,7 @@ public final class NativeLibraryLoader { if (url == null) { return; } - + String loadedAsFileName; if (library.getExtractedAsName() != null) { loadedAsFileName = library.getExtractedAsName(); @@ -508,7 +536,7 @@ public final class NativeLibraryLoader { throw new UnsupportedOperationException("JVM is running under " + "reduced permissions. Cannot load native libraries."); } - + Platform platform = JmeSystem.getPlatform(); NativeLibrary library = nativeLibraryMap.get(new NativeLibrary.Key(name, platform)); @@ -526,27 +554,28 @@ public final class NativeLibraryLoader { } } - String pathInJar = library.getPathInNativesJar(); - + final String pathInJar = library.getPathInNativesJar(); + if (pathInJar == null) { // This platform does not require the native library to be loaded. return; } - String fileNameInJar; + final String fileNameInJar; + if (pathInJar.contains("/")) { fileNameInJar = pathInJar.substring(pathInJar.lastIndexOf("/") + 1); } else { fileNameInJar = pathInJar; } - + URL url = Thread.currentThread().getContextClassLoader().getResource(pathInJar); if (url == null) { // Try the root of the classpath as well. url = Thread.currentThread().getContextClassLoader().getResource(fileNameInJar); } - + if (url == null) { // Attempt to load it as a system library. String unmappedName = unmapLibraryName(fileNameInJar); @@ -642,7 +671,7 @@ public final class NativeLibraryLoader { } finally { // XXX: HACK. Vary loading method based on library name.. // lwjgl and jinput handle loading by themselves. - if (name.equals("lwjgl")) { + if (name.equals("lwjgl") || name.equals("lwjgl3")) { System.setProperty("org.lwjgl.librarypath", extactionDirectory.getAbsolutePath()); } else if (name.equals("jinput")) { diff --git a/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java b/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java index 7b1dfb37a..37fec3bcd 100644 --- a/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java +++ b/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java @@ -69,6 +69,12 @@ public class FXAAFilter extends Filter { protected Material getMaterial() { return material; } + + @Override + protected boolean isRequiresBilinear() { + // FXAA wants the input texture to be filtered. + return true; + } public void setSpanMax(float spanMax) { this.spanMax = spanMax; diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag index 8daa4f7fd..842484604 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag @@ -17,7 +17,9 @@ uniform float m_Luminance5; uniform float m_LineDistance; uniform float m_LineThickness; - + +out vec4 fragColor; + void main() { vec4 texVal = getColor(m_Texture, texCoord); float linePixel = 0; @@ -49,5 +51,5 @@ void main() { // Mix paper color with existing color information vec4 paperColor = mix(m_PaperColor, texVal, m_ColorInfluencePaper); - gl_FragColor = mix(paperColor, lineColor, linePixel); + fragColor = mix(paperColor, lineColor, linePixel); } \ No newline at end of file diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag index 80cf3c530..de3c586ae 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag @@ -11,6 +11,8 @@ uniform float m_YScale; vec2 m_NearFar = vec2( 0.1, 1000.0 ); +out vec4 fragColor; + void main() { vec4 texVal = getColor( m_Texture, texCoord ); @@ -44,7 +46,7 @@ void main() { if( unfocus < 0.2 ) { // If we are mostly in focus then don't bother with the // convolution filter - gl_FragColor = texVal; + fragColor = texVal; } else { // Perform a wide convolution filter and we scatter it // a bit to avoid some texture look-ups. Instead of @@ -83,7 +85,7 @@ void main() { sum = sum / 12.0; - gl_FragColor = mix( texVal, sum, unfocus ); + fragColor = mix( texVal, sum, unfocus ); // I used this for debugging the range // gl_FragColor.r = unfocus; diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag index c99de34ad..7bd2d4882 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag @@ -4,8 +4,9 @@ uniform COLORTEXTURE m_Texture; uniform float m_Value; in vec2 texCoord; +out vec4 fragColor; void main() { vec4 texVal = getColor(m_Texture, texCoord); - gl_FragColor = texVal * m_Value; + fragColor = texVal * m_Value; } \ No newline at end of file diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag index 65a340723..7a1f756be 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag @@ -8,6 +8,7 @@ uniform float m_FogDensity; uniform float m_FogDistance; in vec2 texCoord; +out vec4 fragColor; vec2 m_FrustumNearFar=vec2(1.0,m_FogDistance); const float LOG2 = 1.442695; @@ -19,6 +20,6 @@ void main() { float fogFactor = exp2( -m_FogDensity * m_FogDensity * depth * depth * LOG2 ); fogFactor = clamp(fogFactor, 0.0, 1.0); - gl_FragColor =mix(m_FogColor,texVal,fogFactor); + fragColor =mix(m_FogColor,texVal,fogFactor); } \ No newline at end of file diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag index 7dc4d1e4b..d6609f38f 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag @@ -3,9 +3,10 @@ uniform COLORTEXTURE m_Texture; uniform vec4 m_Color; in vec2 texCoord; +out vec4 fragColor; void main() { vec4 texVal = getColor(m_Texture, texCoord); - gl_FragColor = texVal * m_Color; + fragColor = texVal * m_Color; } diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag index f55ac5bf2..5d8d7072b 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag @@ -2,7 +2,8 @@ uniform COLORTEXTURE m_Texture; in vec2 texCoord; - +out vec4 fragColor; + uniform int m_NumColors; uniform float m_Gamma; uniform float m_Strength; @@ -16,5 +17,5 @@ void main() { texVal = texVal / m_NumColors; texVal = pow(texVal, vec4(1.0/m_Gamma)); - gl_FragColor = mix(getColor(m_Texture, texCoord), texVal, m_Strength); + fragColor = mix(getColor(m_Texture, texCoord), texVal, m_Strength); } \ No newline at end of file diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag index 34268c565..b8f322d11 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag @@ -6,10 +6,11 @@ uniform sampler2D m_BloomTex; uniform float m_BloomIntensity; in vec2 texCoord; +out vec4 fragColor; void main(){ vec4 colorRes = getColor(m_Texture,texCoord); vec4 bloom = texture2D(m_BloomTex, texCoord); - gl_FragColor = bloom * m_BloomIntensity + colorRes; + fragColor = bloom * m_BloomIntensity + colorRes; } diff --git a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag index c1112b23b..be2e6bcde 100644 --- a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag +++ b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag @@ -10,6 +10,7 @@ uniform float m_YScale; uniform vec2 m_FrustumNearFar; in vec2 texCoord; +out vec4 fragColor; vec4 getResult(vec4 color){ @@ -125,7 +126,7 @@ float readDepth(in vec2 uv){ void main(){ // float depth =texture2D(m_DepthTexture,uv).r; - gl_FragColor=getResult(convolutionFilter()); + fragColor=getResult(convolutionFilter()); // gl_FragColor=getResult(bilateralFilter()); // gl_FragColor=getColor(m_SSAOMap,texCoord); diff --git a/jme3-examples/build.gradle b/jme3-examples/build.gradle index de1c3931c..09e71997e 100644 --- a/jme3-examples/build.gradle +++ b/jme3-examples/build.gradle @@ -21,7 +21,7 @@ dependencies { // compile project(':jme3-bullet-native') compile project(':jme3-jbullet') compile project(':jme3-jogg') -// compile project(':jme3-jogl') + compile project(':jme3-jogl') compile project(':jme3-lwjgl') compile project(':jme3-networking') compile project(':jme3-niftygui') @@ -51,7 +51,9 @@ jar.doFirst{ } } -task dist (dependsOn: ['build', ':jme3-jogl:jar', ':jme3-bullet:jar', ':jme3-android:jar']) << { +task dist (dependsOn: ['build', ':jme3-jogl:jar', ':jme3-bullet:jar', ':jme3-android:jar', \ + ':jme3-android-native:jar', ':jme3-bullet-native-android:jar', \ + ':jme3-bullet-native:jar']) << { // Copy all dependencies to ../dist/lib, remove versions from jar files configurations.compile.resolvedConfiguration.resolvedArtifacts.each { artifact -> copy { @@ -97,23 +99,23 @@ task dist (dependsOn: ['build', ':jme3-jogl:jar', ':jme3-bullet:jar', ':jme3-and copy { from project(':jme3-bullet-native').jar.archivePath into '../dist/opt/native-bullet' - rename {"jme3-bullet-natives.jar"} + rename {project(':jme3-bullet-native').name+".jar"} } // Copy android packages, remove version copy { from project(':jme3-android').jar.archivePath into '../dist/opt/android' - rename { project(':jme3-android').name + ".jar" } + rename {project(':jme3-android').name+".jar"} } copy { from project(':jme3-android-native').jar.archivePath into '../dist/opt/android' - rename { project(':jme3-android-native').name + ".jar" } + rename {project(':jme3-android-native').name+".jar"} } copy { from project(':jme3-bullet-native-android').jar.archivePath into '../dist/opt/native-bullet' - rename {"jme3-bullet-native-android.jar"} + rename {project(':jme3-bullet-native-android').name+".jar"} } } diff --git a/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java b/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java index e12769cd8..036d9318c 100644 --- a/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java +++ b/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java @@ -36,10 +36,10 @@ import com.jme3.app.SimpleApplication; import com.jme3.asset.TextureKey; import com.jme3.asset.plugins.HttpZipLocator; import com.jme3.material.Material; -import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; import com.jme3.scene.shape.Quad; import com.jme3.texture.Texture; +import com.jme3.ui.Picture; /** * This tests loading a file from a jar stored online. @@ -59,22 +59,27 @@ public class TestOnlineJar extends SimpleApplication { quadMesh.updateGeometry(1, 1, true); Geometry quad = new Geometry("Textured Quad", quadMesh); - assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/town.zip", - HttpZipLocator.class); + + assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/town.zip", + HttpZipLocator.class); + assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/wildhouse.zip", + HttpZipLocator.class); - TextureKey key = new TextureKey("grass.jpg", false); - key.setGenerateMips(true); - Texture tex = assetManager.loadTexture(key); - - Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); - mat.setTexture("ColorMap", tex); - quad.setMaterial(mat); - - float aspect = tex.getImage().getWidth() / (float) tex.getImage().getHeight(); - quad.setLocalScale(new Vector3f(aspect * 1.5f, 1.5f, 1)); - quad.center(); - - rootNode.attachChild(quad); + Picture pic1 = new Picture("Picture1"); + pic1.move(0, 0, -1); + pic1.setPosition(0, 0); + pic1.setWidth(128); + pic1.setHeight(128); + pic1.setImage(assetManager, "grass.jpg", false); + guiNode.attachChild(pic1); + + Picture pic2 = new Picture("Picture1"); + pic2.move(0, 0, -1); + pic2.setPosition(128, 0); + pic2.setWidth(128); + pic2.setHeight(128); + pic2.setImage(assetManager, "glasstile2.png", false); + guiNode.attachChild(pic2); } } diff --git a/jme3-examples/src/main/java/jme3test/material/TestParallax.java b/jme3-examples/src/main/java/jme3test/material/TestParallax.java index 37b5e09b0..f5af57f1f 100644 --- a/jme3-examples/src/main/java/jme3test/material/TestParallax.java +++ b/jme3-examples/src/main/java/jme3test/material/TestParallax.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2015 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,20 +39,17 @@ import com.jme3.input.controls.KeyTrigger; import com.jme3.light.DirectionalLight; import com.jme3.material.Material; import com.jme3.math.*; -import com.jme3.post.FilterPostProcessor; -import com.jme3.post.filters.FXAAFilter; import com.jme3.renderer.queue.RenderQueue.ShadowMode; import com.jme3.scene.Geometry; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.scene.shape.Quad; -import com.jme3.texture.Texture.WrapMode; import com.jme3.util.SkyFactory; import com.jme3.util.TangentBinormalGenerator; public class TestParallax extends SimpleApplication { - private Vector3f lightDir = new Vector3f(-1, -1, .5f).normalizeLocal(); + private final Vector3f lightDir = new Vector3f(-1, -1, .5f).normalizeLocal(); public static void main(String[] args) { TestParallax app = new TestParallax(); @@ -60,7 +57,7 @@ public class TestParallax extends SimpleApplication { } public void setupSkyBox() { - rootNode.attachChild(SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false)); + rootNode.attachChild(SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", SkyFactory.EnvMapType.CubeMap)); } DirectionalLight dl; @@ -75,12 +72,7 @@ public class TestParallax extends SimpleApplication { public void setupFloor() { mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall2.j3m"); - mat.getTextureParam("DiffuseMap").getTextureValue().setWrap(WrapMode.Repeat); - mat.getTextureParam("NormalMap").getTextureValue().setWrap(WrapMode.Repeat); - - // Node floorGeom = (Node) assetManager.loadAsset("Models/WaterTest/WaterTest.mesh.xml"); - //Geometry g = ((Geometry) floorGeom.getChild(0)); - //g.getMesh().scaleTextureCoordinates(new Vector2f(10, 10)); + //mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall.j3m"); Node floorGeom = new Node("floorGeom"); Quad q = new Quad(100, 100); @@ -100,9 +92,9 @@ public class TestParallax extends SimpleApplication { public void setupSignpost() { Spatial signpost = assetManager.loadModel("Models/Sign Post/Sign Post.mesh.xml"); - Material mat = assetManager.loadMaterial("Models/Sign Post/Sign Post.j3m"); + Material matSp = assetManager.loadMaterial("Models/Sign Post/Sign Post.j3m"); TangentBinormalGenerator.generate(signpost); - signpost.setMaterial(mat); + signpost.setMaterial(matSp); signpost.rotate(0, FastMath.HALF_PI, 0); signpost.setLocalTranslation(12, 23.5f, 30); signpost.setLocalScale(4); @@ -116,7 +108,6 @@ public class TestParallax extends SimpleApplication { cam.setRotation(new Quaternion(0.05173137f, 0.92363626f, -0.13454558f, 0.35513034f)); flyCam.setMoveSpeed(30); - setupLighting(); setupSkyBox(); setupFloor(); @@ -124,13 +115,14 @@ public class TestParallax extends SimpleApplication { inputManager.addListener(new AnalogListener() { + @Override public void onAnalog(String name, float value, float tpf) { if ("heightUP".equals(name)) { - parallaxHeigh += 0.0001; + parallaxHeigh += 0.01; mat.setFloat("ParallaxHeight", parallaxHeigh); } if ("heightDown".equals(name)) { - parallaxHeigh -= 0.0001; + parallaxHeigh -= 0.01; parallaxHeigh = Math.max(parallaxHeigh, 0); mat.setFloat("ParallaxHeight", parallaxHeigh); } @@ -142,6 +134,7 @@ public class TestParallax extends SimpleApplication { inputManager.addListener(new ActionListener() { + @Override public void onAction(String name, boolean isPressed, float tpf) { if (isPressed && "toggleSteep".equals(name)) { steep = !steep; diff --git a/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java b/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java index e220eeb37..b5eeb5365 100644 --- a/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java +++ b/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java @@ -73,6 +73,13 @@ public class TestCustomAnim extends SimpleApplication { Box box = new Box(1, 1, 1); + VertexBuffer weightsHW = new VertexBuffer(Type.HWBoneWeight); + VertexBuffer indicesHW = new VertexBuffer(Type.HWBoneIndex); + indicesHW.setUsage(Usage.CpuOnly); + weightsHW.setUsage(Usage.CpuOnly); + box.setBuffer(weightsHW); + box.setBuffer(indicesHW); + // Setup bone weight buffer FloatBuffer weights = FloatBuffer.allocate( box.getVertexCount() * 4 ); VertexBuffer weightsBuf = new VertexBuffer(Type.BoneWeight); diff --git a/jme3-examples/src/main/java/jme3test/network/TestChatClient.java b/jme3-examples/src/main/java/jme3test/network/TestChatClient.java index fddb047c4..a36853913 100644 --- a/jme3-examples/src/main/java/jme3test/network/TestChatClient.java +++ b/jme3-examples/src/main/java/jme3test/network/TestChatClient.java @@ -32,6 +32,8 @@ package jme3test.network; import com.jme3.network.Client; +import com.jme3.network.ClientStateListener; +import com.jme3.network.ErrorListener; import com.jme3.network.Message; import com.jme3.network.MessageListener; import com.jme3.network.Network; @@ -51,11 +53,11 @@ import jme3test.network.TestChatServer.ChatMessage; */ public class TestChatClient extends JFrame { - private Client client; - private JEditorPane chatLog; - private StringBuilder chatMessages = new StringBuilder(); - private JTextField nameField; - private JTextField messageField; + private final Client client; + private final JEditorPane chatLog; + private final StringBuilder chatMessages = new StringBuilder(); + private final JTextField nameField; + private final JTextField messageField; public TestChatClient(String host) throws IOException { super("jME3 Test Chat Client - to:" + host); @@ -90,7 +92,20 @@ public class TestChatClient extends JFrame { client = Network.connectToServer(TestChatServer.NAME, TestChatServer.VERSION, host, TestChatServer.PORT, TestChatServer.UDP_PORT); client.addMessageListener(new ChatHandler(), ChatMessage.class); + client.addClientStateListener(new ChatClientStateListener()); + client.addErrorListener(new ChatErrorListener()); client.start(); + + System.out.println("Started client:" + client); + } + + @Override + public void dispose() { + System.out.println("Chat window closing."); + super.dispose(); + if( client.isConnected() ) { + client.close(); + } } public static String getString(Component owner, String title, String message, String initialValue) { @@ -99,7 +114,12 @@ public class TestChatClient extends JFrame { } public static void main(String... args) throws Exception { - TestChatServer.initializeClasses(); + + // Note: in JME 3.1 this is generally unnecessary as the server will + // send a message with all server-registered classes. + // TestChatServer.initializeClasses(); + // Leaving the call commented out to be illustrative regarding the + // common old pattern. // Grab a host string from the user String s = getString(null, "Host Info", "Enter chat host:", "localhost"); @@ -108,12 +128,23 @@ public class TestChatClient extends JFrame { return; } + // Register a shutdown hook to get a message on the console when the + // app actually finishes + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + System.out.println("Chat client is terminating."); + } + }); + + TestChatClient test = new TestChatClient(s); test.setVisible(true); } private class ChatHandler implements MessageListener { + @Override public void messageReceived(Client source, Message m) { ChatMessage chat = (ChatMessage) m; @@ -134,15 +165,50 @@ public class TestChatClient extends JFrame { } } + private class ChatClientStateListener implements ClientStateListener { + + @Override + public void clientConnected(Client c) { + System.out.println("clientConnected(" + c + ")"); + } + + @Override + public void clientDisconnected(Client c, DisconnectInfo info) { + System.out.println("clientDisconnected(" + c + "):" + info); + if( info != null ) { + // The connection was closed by the server + JOptionPane.showMessageDialog(rootPane, + info.reason, + "Connection Closed", + JOptionPane.INFORMATION_MESSAGE); + dispose(); + } + } + } + + private class ChatErrorListener implements ErrorListener { + + @Override + public void handleError( Client source, Throwable t ) { + System.out.println("handleError(" + source + ", " + t + ")"); + JOptionPane.showMessageDialog(rootPane, + String.valueOf(t), + "Connection Error", + JOptionPane.ERROR_MESSAGE); + } + + } + private class SendAction extends AbstractAction { - private boolean reliable; + private final boolean reliable; public SendAction(boolean reliable) { super(reliable ? "TCP" : "UDP"); this.reliable = reliable; } + @Override public void actionPerformed(ActionEvent evt) { String name = nameField.getText(); String message = messageField.getText(); diff --git a/jme3-examples/src/main/java/jme3test/network/TestChatClientAndServer.java b/jme3-examples/src/main/java/jme3test/network/TestChatClientAndServer.java new file mode 100644 index 000000000..ee08067ae --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/network/TestChatClientAndServer.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015 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 jme3test.network; + + +/** + * Combines the server instance and a client instance into the + * same JVM to show an example of, and to test, a pattern like + * self-hosted multiplayer games. + * + * @author Paul Speed + */ +public class TestChatClientAndServer { + + public static void main( String... args ) throws Exception { + + System.out.println("Starting chat server..."); + TestChatServer chatServer = new TestChatServer(); + chatServer.start(); + + System.out.println("Waiting for connections on port:" + TestChatServer.PORT); + + // Now launch a client + + TestChatClient test = new TestChatClient("localhost"); + test.setVisible(true); + + // Register a shutdown hook to get a message on the console when the + // app actually finishes + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + System.out.println("Client and server test is terminating."); + } + }); + + // Keep running basically forever or until the server + // shuts down + while( chatServer.isRunning() ) { + synchronized (chatServer) { + chatServer.wait(); + } + } + } +} diff --git a/jme3-examples/src/main/java/jme3test/network/TestChatServer.java b/jme3-examples/src/main/java/jme3test/network/TestChatServer.java index a2aa2ee1c..4d8642881 100644 --- a/jme3-examples/src/main/java/jme3test/network/TestChatServer.java +++ b/jme3-examples/src/main/java/jme3test/network/TestChatServer.java @@ -34,6 +34,7 @@ package jme3test.network; import com.jme3.network.*; import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializer; +import java.io.IOException; /** * A simple test chat server. When SM implements a set @@ -51,51 +52,134 @@ public class TestChatServer { public static final int PORT = 5110; public static final int UDP_PORT = 5110; - public static void initializeClasses() { - // Doing it here means that the client code only needs to - // call our initialize. - Serializer.registerClass(ChatMessage.class); - } - - public static void main(String... args) throws Exception { + private Server server; + private boolean isRunning; + + public TestChatServer() throws IOException { initializeClasses(); // Use this to test the client/server name version check - Server server = Network.createServer(NAME, VERSION, PORT, UDP_PORT); - server.start(); + this.server = Network.createServer(NAME, VERSION, PORT, UDP_PORT); ChatHandler handler = new ChatHandler(); server.addMessageListener(handler, ChatMessage.class); + + server.addConnectionListener(new ChatConnectionListener()); + } + + public boolean isRunning() { + return isRunning; + } + + public synchronized void start() { + if( isRunning ) { + return; + } + server.start(); + isRunning = true; + } + + public synchronized void close() { + if( !isRunning ) { + return; + } + + // Gracefully let any connections know that the server is + // going down. Without this, their connections will simply + // error out. + for( HostedConnection conn : server.getConnections() ) { + conn.close("Server is shutting down."); + } + try { + Thread.sleep(1000); // wait a couple beats to let the messages go out + } catch( InterruptedException e ) { + e.printStackTrace(); + } + + server.close(); + isRunning = false; + notifyAll(); + } + + protected void runCommand( HostedConnection conn, String user, String command ) { + if( "/shutdown".equals(command) ) { + server.broadcast(new ChatMessage("server", "Server is shutting down.")); + close(); + } else if( "/help".equals(command) ) { + StringBuilder sb = new StringBuilder(); + sb.append("Chat commands:\n"); + sb.append("/help - prints this message.\n"); + sb.append("/shutdown - shuts down the server."); + server.broadcast(new ChatMessage("server", sb.toString())); + } + } + + public static void initializeClasses() { + // Doing it here means that the client code only needs to + // call our initialize. + Serializer.registerClass(ChatMessage.class); + } + public static void main(String... args) throws Exception { + + TestChatServer chatServer = new TestChatServer(); + chatServer.start(); + + System.out.println("Waiting for connections on port:" + PORT); + // Keep running basically forever - synchronized (NAME) { - NAME.wait(); + while( chatServer.isRunning ) { + synchronized (chatServer) { + chatServer.wait(); + } } } - private static class ChatHandler implements MessageListener { + private class ChatHandler implements MessageListener { public ChatHandler() { } + @Override public void messageReceived(HostedConnection source, Message m) { if (m instanceof ChatMessage) { // Keep track of the name just in case we // want to know it for some other reason later and it's // a good example of session data - source.setAttribute("name", ((ChatMessage) m).getName()); + ChatMessage cm = (ChatMessage)m; + source.setAttribute("name", cm.getName()); + + // Check for a / command + if( cm.message.startsWith("/") ) { + runCommand(source, cm.name, cm.message); + return; + } System.out.println("Broadcasting:" + m + " reliable:" + m.isReliable()); // Just rebroadcast... the reliable flag will stay the // same so if it came in on UDP it will go out on that too - source.getServer().broadcast(m); + source.getServer().broadcast(cm); } else { System.err.println("Received odd message:" + m); } } } + private class ChatConnectionListener implements ConnectionListener { + + @Override + public void connectionAdded( Server server, HostedConnection conn ) { + System.out.println("connectionAdded(" + conn + ")"); + } + + @Override + public void connectionRemoved(Server server, HostedConnection conn) { + System.out.println("connectionRemoved(" + conn + ")"); + } + + } + @Serializable public static class ChatMessage extends AbstractMessage { @@ -126,6 +210,7 @@ public class TestChatServer { return message; } + @Override public String toString() { return name + ":" + message; } diff --git a/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java b/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java index a93a75c16..c1f99b35d 100644 --- a/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java +++ b/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java @@ -63,7 +63,7 @@ public class TestInconsistentCompareDetection extends SimpleApplication { cam.setLocation(new Vector3f(-11.674385f, 7.892636f, 33.133106f)); cam.setRotation(new Quaternion(0.06426433f, 0.90940624f, -0.15329266f, 0.38125014f)); - Material m = new Material(assetManager, "Common/MatDefs/Misc/ColoredTextured.j3md"); + Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); m.setColor("Color", ColorRGBA.White); t1 = assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"); diff --git a/jme3-examples/src/main/java/jme3test/stress/TestShaderNodesStress.java b/jme3-examples/src/main/java/jme3test/stress/TestShaderNodesStress.java new file mode 100644 index 000000000..3364f5feb --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/stress/TestShaderNodesStress.java @@ -0,0 +1,102 @@ +package jme3test.stress; + +import com.jme3.app.BasicProfilerState; +import com.jme3.app.SimpleApplication; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.profile.AppProfiler; +import com.jme3.profile.AppStep; +import com.jme3.profile.VpStep; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Quad; +import com.jme3.texture.Texture; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class TestShaderNodesStress extends SimpleApplication { + + public static void main(String[] args) { + TestShaderNodesStress app = new TestShaderNodesStress(); + app.start(); + } + + @Override + public void simpleInitApp() { + + Quad q = new Quad(1, 1); + Geometry g = new Geometry("quad", q); + g.setLocalTranslation(-500, -500, 0); + g.setLocalScale(1000); + + rootNode.attachChild(g); + cam.setLocation(new Vector3f(0.0f, 0.0f, 0.40647888f)); + cam.setRotation(new Quaternion(0.0f, 1.0f, 0.0f, 0.0f)); + + Texture tex = assetManager.loadTexture("Interface/Logo/Monkey.jpg"); + + Material mat = new Material(assetManager, "Common/MatDefs/Misc/UnshadedNodes.j3md"); + //Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + + mat.setColor("Color", ColorRGBA.Yellow); + mat.setTexture("ColorMap", tex); + g.setMaterial(mat); + //place the geoms in the transparent bucket so that they are rendered back to front for maximum overdraw + g.setQueueBucket(RenderQueue.Bucket.Transparent); + + for (int i = 0; i < 1000; i++) { + Geometry cl = g.clone(false); + cl.move(0, 0, -(i + 1)); + rootNode.attachChild(cl); + } + + flyCam.setMoveSpeed(20); + Logger.getLogger("com.jme3").setLevel(Level.WARNING); + + this.setAppProfiler(new Profiler()); + + } + + private class Profiler implements AppProfiler { + + private long startTime; + private long updateTime; + private long renderTime; + private long sum; + private int nbFrames; + + @Override + public void appStep(AppStep step) { + + switch (step) { + case BeginFrame: + startTime = System.nanoTime(); + break; + case RenderFrame: + updateTime = System.nanoTime(); + // System.err.println("Update time : " + (updateTime - startTime)); + break; + case EndFrame: + nbFrames++; + if (nbFrames >= 150) { + renderTime = System.nanoTime(); + sum += renderTime - updateTime; + System.err.println("render time : " + (renderTime - updateTime)); + System.err.println("Average render time : " + ((float)sum / (float)(nbFrames-150))); + } + break; + + } + + } + + @Override + public void vpStep(VpStep step, ViewPort vp, RenderQueue.Bucket bucket) { + + } + + } +} diff --git a/jme3-jbullet/build.gradle b/jme3-jbullet/build.gradle index bcf1660bc..0e3967ab2 100644 --- a/jme3-jbullet/build.gradle +++ b/jme3-jbullet/build.gradle @@ -16,4 +16,5 @@ dependencies { compile files('../lib/jbullet.jar', '../lib/stack-alloc.jar') compile project(':jme3-core') compile project(':jme3-terrain') +// compile project(':jme3-bullet') } diff --git a/jme3-jogl/build.gradle b/jme3-jogl/build.gradle index e82139729..df24c15ec 100644 --- a/jme3-jogl/build.gradle +++ b/jme3-jogl/build.gradle @@ -5,7 +5,7 @@ if (!hasProperty('mainClass')) { dependencies { compile project(':jme3-core') compile project(':jme3-desktop') - compile 'org.jogamp.gluegen:gluegen-rt-main:2.3.1' - compile 'org.jogamp.jogl:jogl-all-main:2.3.1' - compile 'org.jogamp.joal:joal-main:2.3.1' + compile 'org.jogamp.gluegen:gluegen-rt-main:2.3.2' + compile 'org.jogamp.jogl:jogl-all-main:2.3.2' + compile 'org.jogamp.joal:joal-main:2.3.2' } diff --git a/jme3-jogl/src/main/java/com/jme3/input/jogl/NewtMouseInput.java b/jme3-jogl/src/main/java/com/jme3/input/jogl/NewtMouseInput.java index 773f62b8a..d7dd905fd 100644 --- a/jme3-jogl/src/main/java/com/jme3/input/jogl/NewtMouseInput.java +++ b/jme3-jogl/src/main/java/com/jme3/input/jogl/NewtMouseInput.java @@ -50,6 +50,8 @@ import com.jogamp.nativewindow.util.DimensionImmutable; import com.jogamp.nativewindow.util.PixelFormat; import com.jogamp.nativewindow.util.PixelRectangle; import com.jogamp.nativewindow.util.Point; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; public class NewtMouseInput implements MouseInput, MouseListener { @@ -106,40 +108,67 @@ public class NewtMouseInput implements MouseInput, MouseListener { component = comp; component.addMouseListener(this); + component.addWindowListener(new WindowAdapter(){ + + @Override + public void windowGainedFocus(WindowEvent e) { + setCursorVisible(visible); + } + + @Override + public void windowLostFocus(WindowEvent e) { + //without those lines, + //on Linux (OpenBox) the mouse is not restored if invisible (eg via Alt-Tab) + component.setPointerVisible(true); + component.confinePointer(false); + } + + }); } + @Override public void initialize() { } + @Override public void destroy() { } + @Override public boolean isInitialized() { return true; } + @Override public void setInputListener(RawInputListener listener) { this.listener = listener; } + @Override public long getInputTimeNanos() { return System.nanoTime(); } + @Override public void setCursorVisible(boolean visible) { - if (this.visible != visible) { - lastKnownLocation.setX(0); - lastKnownLocation.setY(0); - - this.visible = visible; - component.setPointerVisible(visible); - if (!visible) { - recenterMouse(component); - } - } + lastKnownLocation.setX(0); + lastKnownLocation.setY(0); + + this.visible = visible; + component.setPointerVisible(visible); + component.confinePointer(!visible); + hack_confinePointer(); } + private void hack_confinePointer() { + if (component.hasFocus() && component.isPointerConfined() && !component.isPointerVisible()) { + recenterMouse(component); + } + } + + @Override public void update() { + if (!component.hasFocus()) return; if (cursorMoved) { int newX = location.getX(); int newY = location.getY(); @@ -147,7 +176,7 @@ public class NewtMouseInput implements MouseInput, MouseListener { // invert DY int actualX = lastKnownLocation.getX(); - int actualY = component.getHeight() - lastKnownLocation.getY(); + int actualY = component.getSurfaceHeight() - lastKnownLocation.getY(); MouseMotionEvent evt = new MouseMotionEvent(actualX, actualY, newX - lastEventX, lastEventY - newY, @@ -173,43 +202,46 @@ public class NewtMouseInput implements MouseInput, MouseListener { } } + @Override public int getButtonCount() { return 3; } + @Override public void mouseClicked(MouseEvent awtEvt) { // MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), false); // listener.onMouseButtonEvent(evt); } + @Override public void mousePressed(MouseEvent newtEvt) { - MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(newtEvt), true, newtEvt.getX(), newtEvt.getY()); + MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(newtEvt), true, newtEvt.getX(), component.getSurfaceHeight() - newtEvt.getY()); evt.setTime(newtEvt.getWhen()); synchronized (eventQueue) { eventQueue.add(evt); } } - public void mouseReleased(MouseEvent awtEvt) { - MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(awtEvt), false, awtEvt.getX(), awtEvt.getY()); + @Override + public void mouseReleased(MouseEvent awtEvt) { + MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(awtEvt), false, awtEvt.getX(), component.getSurfaceHeight() - awtEvt.getY()); evt.setTime(awtEvt.getWhen()); synchronized (eventQueue) { eventQueue.add(evt); } } + @Override public void mouseEntered(MouseEvent awtEvt) { - if (!visible) { - recenterMouse(component); - } + hack_confinePointer(); } + @Override public void mouseExited(MouseEvent awtEvt) { - if (!visible) { - recenterMouse(component); - } + hack_confinePointer(); } + @Override public void mouseWheelMoved(MouseEvent awtEvt) { //FIXME not sure this is the right way to handle this case // [0] should be used when the shift key is down @@ -218,10 +250,12 @@ public class NewtMouseInput implements MouseInput, MouseListener { cursorMoved = true; } + @Override public void mouseDragged(MouseEvent awtEvt) { mouseMoved(awtEvt); } + @Override public void mouseMoved(MouseEvent awtEvt) { if (isRecentering) { // MHenze (cylab) Fix Issue 35: @@ -239,22 +273,20 @@ public class NewtMouseInput implements MouseInput, MouseListener { int dy = awtEvt.getY() - lastKnownLocation.getY(); location.setX(location.getX() + dx); location.setY(location.getY() + dy); - if (!visible) { - recenterMouse(component); - } + hack_confinePointer(); lastKnownLocation.setX(awtEvt.getX()); lastKnownLocation.setY(awtEvt.getY()); cursorMoved = true; } } - + // MHenze (cylab) Fix Issue 35: A method to generate recenter the mouse to allow the InputSystem to "grab" the mouse private void recenterMouse(final GLWindow component) { eventsSinceRecenter = 0; isRecentering = true; - centerLocation.setX(component.getWidth() / 2); - centerLocation.setY(component.getHeight() / 2); + centerLocation.setX(component.getSurfaceWidth() / 2); + centerLocation.setY(component.getSurfaceHeight() / 2); centerLocationOnScreen.setX(centerLocation.getX()); centerLocationOnScreen.setY(centerLocation.getY()); @@ -287,12 +319,13 @@ public class NewtMouseInput implements MouseInput, MouseListener { return index; } + @Override public void setNativeCursor(JmeCursor cursor) { final ByteBuffer pixels = Buffers.copyIntBufferAsByteBuffer(cursor.getImagesData()); final DimensionImmutable size = new Dimension(cursor.getWidth(), cursor.getHeight()); final PixelFormat pixFormat = PixelFormat.RGBA8888; final PixelRectangle.GenericPixelRect rec = new PixelRectangle.GenericPixelRect(pixFormat, size, 0, true, pixels); - final PointerIcon joglCursor = component.getScreen().getDisplay().createPointerIcon(rec, cursor.getXHotSpot(), cursor.getYHotSpot()); + final PointerIcon joglCursor = component.getScreen().getDisplay().createPointerIcon(rec, cursor.getXHotSpot(), cursor.getHeight() - cursor.getYHotSpot()); component.setPointerIcon(joglCursor); } -} \ No newline at end of file +} diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java new file mode 100644 index 000000000..3da2ed49e --- /dev/null +++ b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java @@ -0,0 +1,603 @@ +package com.jme3.renderer.jogl; + +import com.jme3.renderer.RendererException; +import com.jme3.renderer.opengl.GL; +import com.jme3.renderer.opengl.GL2; +import com.jme3.renderer.opengl.GL3; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; + +import com.jme3.renderer.opengl.GL4; +import com.jogamp.opengl.GLContext; + +public class JoglGL implements GL, GL2, GL3, GL4 { + + private static int getLimitBytes(ByteBuffer buffer) { + checkLimit(buffer); + return buffer.limit(); + } + + private static int getLimitBytes(ShortBuffer buffer) { + checkLimit(buffer); + return buffer.limit() * 2; + } + + private static int getLimitBytes(FloatBuffer buffer) { + checkLimit(buffer); + return buffer.limit() * 4; + } + + private static int getLimitCount(Buffer buffer, int elementSize) { + checkLimit(buffer); + return buffer.limit() / elementSize; + } + + private static void checkLimit(Buffer buffer) { + if (buffer == null) { + return; + } + if (buffer.limit() == 0) { + throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error"); + } + if (buffer.remaining() == 0) { + throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); + } + } + + @Override + public void resetStats() { + } + + @Override + public void glActiveTexture(int param1) { + GLContext.getCurrentGL().glActiveTexture(param1); + } + + @Override + public void glAlphaFunc(int param1, float param2) { + GLContext.getCurrentGL().getGL2ES1().glAlphaFunc(param1, param2); + } + + @Override + public void glAttachShader(int param1, int param2) { + GLContext.getCurrentGL().getGL2ES2().glAttachShader(param1, param2); + } + + @Override + public void glBindBuffer(int param1, int param2) { + GLContext.getCurrentGL().glBindBuffer(param1, param2); + } + + @Override + public void glBindTexture(int param1, int param2) { + GLContext.getCurrentGL().glBindTexture(param1, param2); + } + + @Override + public void glBlendFunc(int param1, int param2) { + GLContext.getCurrentGL().glBlendFunc(param1, param2); + } + + @Override + public void glBufferData(int param1, long param2, int param3) { + GLContext.getCurrentGL().glBufferData(param1, param2, null, param3); + } + + @Override + public void glBufferData(int param1, FloatBuffer param2, int param3) { + checkLimit(param2); + GLContext.getCurrentGL().glBufferData(param1, getLimitBytes(param2), param2, param3); + } + + @Override + public void glBufferData(int param1, ShortBuffer param2, int param3) { + checkLimit(param2); + GLContext.getCurrentGL().glBufferData(param1, getLimitBytes(param2), param2, param3); + } + + @Override + public void glBufferData(int param1, ByteBuffer param2, int param3) { + checkLimit(param2); + GLContext.getCurrentGL().glBufferData(param1, getLimitBytes(param2), param2, param3); + } + + @Override + public void glBufferSubData(int param1, long param2, FloatBuffer param3) { + checkLimit(param3); + GLContext.getCurrentGL().glBufferSubData(param1, param2, getLimitBytes(param3), param3); + } + + @Override + public void glBufferSubData(int param1, long param2, ShortBuffer param3) { + checkLimit(param3); + GLContext.getCurrentGL().glBufferSubData(param1, param2, getLimitBytes(param3), param3); + } + + @Override + public void glBufferSubData(int param1, long param2, ByteBuffer param3) { + checkLimit(param3); + GLContext.getCurrentGL().glBufferSubData(param1, param2, getLimitBytes(param3), param3); + } + + @Override + public void glClear(int param1) { + GLContext.getCurrentGL().glClear(param1); + } + + @Override + public void glClearColor(float param1, float param2, float param3, float param4) { + GLContext.getCurrentGL().glClearColor(param1, param2, param3, param4); + } + + @Override + public void glColorMask(boolean param1, boolean param2, boolean param3, boolean param4) { + GLContext.getCurrentGL().glColorMask(param1, param2, param3, param4); + } + + @Override + public void glCompileShader(int param1) { + GLContext.getCurrentGL().getGL2ES2().glCompileShader(param1); + } + + @Override + public void glCompressedTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) { + checkLimit(param7); + GLContext.getCurrentGL().glCompressedTexImage2D(param1, param2, param3, param4, param5, param6, getLimitBytes(param7), param7); + } + + @Override + public void glCompressedTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) { + checkLimit(param8); + GLContext.getCurrentGL().getGL2ES2().glCompressedTexImage3D(param1, param2, param3, param4, param5, param6, param7, getLimitBytes(param8), param8); + } + + @Override + public void glCompressedTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) { + checkLimit(param8); + GLContext.getCurrentGL().glCompressedTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, getLimitBytes(param8), param8); + } + + @Override + public void glCompressedTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) { + checkLimit(param10); + GLContext.getCurrentGL().getGL2ES2().glCompressedTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, getLimitBytes(param10), param10); + } + + @Override + public int glCreateProgram() { + return GLContext.getCurrentGL().getGL2ES2().glCreateProgram(); + } + + @Override + public int glCreateShader(int param1) { + return GLContext.getCurrentGL().getGL2ES2().glCreateShader(param1); + } + + @Override + public void glCullFace(int param1) { + GLContext.getCurrentGL().glCullFace(param1); + } + + @Override + public void glDeleteBuffers(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glDeleteBuffers(param1.limit(), param1); + } + + @Override + public void glDeleteProgram(int param1) { + GLContext.getCurrentGL().getGL2ES2().glDeleteProgram(param1); + } + + @Override + public void glDeleteShader(int param1) { + GLContext.getCurrentGL().getGL2ES2().glDeleteShader(param1); + } + + @Override + public void glDeleteTextures(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glDeleteTextures(param1.limit() ,param1); + } + + @Override + public void glDepthFunc(int param1) { + GLContext.getCurrentGL().glDepthFunc(param1); + } + + @Override + public void glDepthMask(boolean param1) { + GLContext.getCurrentGL().glDepthMask(param1); + } + + @Override + public void glDepthRange(double param1, double param2) { + GLContext.getCurrentGL().glDepthRange(param1, param2); + } + + @Override + public void glDetachShader(int param1, int param2) { + GLContext.getCurrentGL().getGL2ES2().glDetachShader(param1, param2); + } + + @Override + public void glDisable(int param1) { + GLContext.getCurrentGL().glDisable(param1); + } + + @Override + public void glDisableVertexAttribArray(int param1) { + GLContext.getCurrentGL().getGL2ES2().glDisableVertexAttribArray(param1); + } + + @Override + public void glDrawArrays(int param1, int param2, int param3) { + GLContext.getCurrentGL().glDrawArrays(param1, param2, param3); + } + + @Override + public void glDrawBuffer(int param1) { + GLContext.getCurrentGL().getGL2GL3().glDrawBuffer(param1); + } + + @Override + public void glDrawRangeElements(int param1, int param2, int param3, int param4, int param5, long param6) { + GLContext.getCurrentGL().getGL2ES3().glDrawRangeElements(param1, param2, param3, param4, param5, param6); + } + + @Override + public void glEnable(int param1) { + GLContext.getCurrentGL().glEnable(param1); + } + + @Override + public void glEnableVertexAttribArray(int param1) { + GLContext.getCurrentGL().getGL2ES2().glEnableVertexAttribArray(param1); + } + + @Override + public void glGenBuffers(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glGenBuffers(param1.limit(), param1); + } + + @Override + public void glGenTextures(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glGenTextures(param1.limit(), param1); + } + + @Override + public void glGetBoolean(int param1, ByteBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().glGetBooleanv(param1, param2); + } + + @Override + public void glGetBufferSubData(int target, long offset, ByteBuffer data) { + checkLimit(data); + GLContext.getCurrentGL().getGL2GL3().glGetBufferSubData(target, offset, getLimitBytes(data), data); + } + + @Override + public int glGetError() { + return GLContext.getCurrentGL().glGetError(); + } + + @Override + public void glGetInteger(int param1, IntBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().glGetIntegerv(param1, param2); + } + + @Override + public void glGetProgram(int param1, int param2, IntBuffer param3) { + checkLimit(param3); + GLContext.getCurrentGL().getGL2ES2().glGetProgramiv(param1, param2, param3); + } + + @Override + public void glGetShader(int param1, int param2, IntBuffer param3) { + checkLimit(param3); + GLContext.getCurrentGL().getGL2ES2().glGetShaderiv(param1, param2, param3); + } + + @Override + public String glGetString(int param1) { + return GLContext.getCurrentGL().glGetString(param1); + } + + @Override + public String glGetString(int param1, int param2) { + return GLContext.getCurrentGL().getGL2ES3().glGetStringi(param1, param2); + } + + @Override + public boolean glIsEnabled(int param1) { + return GLContext.getCurrentGL().glIsEnabled(param1); + } + + @Override + public void glLineWidth(float param1) { + GLContext.getCurrentGL().glLineWidth(param1); + } + + @Override + public void glLinkProgram(int param1) { + GLContext.getCurrentGL().getGL2ES2().glLinkProgram(param1); + } + + @Override + public void glPixelStorei(int param1, int param2) { + GLContext.getCurrentGL().glPixelStorei(param1, param2); + } + + @Override + public void glPointSize(float param1) { + GLContext.getCurrentGL().getGL2ES1().glPointSize(param1); + } + + @Override + public void glPolygonMode(int param1, int param2) { + GLContext.getCurrentGL().getGL2().glPolygonMode(param1, param2); + } + + @Override + public void glPolygonOffset(float param1, float param2) { + GLContext.getCurrentGL().glPolygonOffset(param1, param2); + } + + @Override + public void glReadBuffer(int param1) { + GLContext.getCurrentGL().getGL2ES3().glReadBuffer(param1); + } + + @Override + public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) { + checkLimit(param7); + GLContext.getCurrentGL().glReadPixels(param1, param2, param3, param4, param5, param6, param7); + } + + @Override + public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, long param7) { + GLContext.getCurrentGL().glReadPixels(param1, param2, param3, param4, param5, param6, param7); + } + + @Override + public void glScissor(int param1, int param2, int param3, int param4) { + GLContext.getCurrentGL().glScissor(param1, param2, param3, param4); + } + + @Override + public void glStencilFuncSeparate(int param1, int param2, int param3, int param4) { + GLContext.getCurrentGL().getGL2ES2().glStencilFuncSeparate(param1, param2, param3, param4); + } + + @Override + public void glStencilOpSeparate(int param1, int param2, int param3, int param4) { + GLContext.getCurrentGL().getGL2ES2().glStencilOpSeparate(param1, param2, param3, param4); + } + + @Override + public void glTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) { + checkLimit(param9); + GLContext.getCurrentGL().glTexImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9); + } + + @Override + public void glTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) { + checkLimit(param10); + GLContext.getCurrentGL().getGL2ES2().glTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); + } + + @Override + public void glTexParameterf(int param1, int param2, float param3) { + GLContext.getCurrentGL().glTexParameterf(param1, param2, param3); + } + + @Override + public void glTexParameteri(int param1, int param2, int param3) { + GLContext.getCurrentGL().glTexParameteri(param1, param2, param3); + } + + @Override + public void glTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) { + checkLimit(param9); + GLContext.getCurrentGL().glTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9); + } + + @Override + public void glTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10, ByteBuffer param11) { + checkLimit(param11); + GLContext.getCurrentGL().getGL2ES2().glTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); + } + + @Override + public void glUniform1(int param1, FloatBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform1fv(param1, getLimitCount(param2, 1), param2); + } + + @Override + public void glUniform1(int param1, IntBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform1iv(param1, getLimitCount(param2, 1), param2); + } + + @Override + public void glUniform1f(int param1, float param2) { + GLContext.getCurrentGL().getGL2ES2().glUniform1f(param1, param2); + } + + @Override + public void glUniform1i(int param1, int param2) { + GLContext.getCurrentGL().getGL2ES2().glUniform1i(param1, param2); + } + + @Override + public void glUniform2(int param1, IntBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform2iv(param1, getLimitCount(param2, 2), param2); + } + + @Override + public void glUniform2(int param1, FloatBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform2fv(param1, getLimitCount(param2, 2), param2); + } + + @Override + public void glUniform2f(int param1, float param2, float param3) { + GLContext.getCurrentGL().getGL2ES2().glUniform2f(param1, param2, param3); + } + + @Override + public void glUniform3(int param1, IntBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform3iv(param1, getLimitCount(param2, 3), param2); + } + + @Override + public void glUniform3(int param1, FloatBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform3fv(param1, getLimitCount(param2, 3), param2); + } + + @Override + public void glUniform3f(int param1, float param2, float param3, float param4) { + GLContext.getCurrentGL().getGL2ES2().glUniform3f(param1, param2, param3, param4); + } + + @Override + public void glUniform4(int param1, FloatBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform4fv(param1, getLimitCount(param2, 4), param2); + } + + @Override + public void glUniform4(int param1, IntBuffer param2) { + checkLimit(param2); + GLContext.getCurrentGL().getGL2ES2().glUniform4iv(param1, getLimitCount(param2, 4), param2); + } + + @Override + public void glUniform4f(int param1, float param2, float param3, float param4, float param5) { + GLContext.getCurrentGL().getGL2ES2().glUniform4f(param1, param2, param3, param4, param5); + } + + @Override + public void glUniformMatrix3(int param1, boolean param2, FloatBuffer param3) { + checkLimit(param3); + GLContext.getCurrentGL().getGL2ES2().glUniformMatrix3fv(param1, getLimitCount(param3, 3 * 3), param2, param3); + } + + @Override + public void glUniformMatrix4(int param1, boolean param2, FloatBuffer param3) { + checkLimit(param3); + GLContext.getCurrentGL().getGL2ES2().glUniformMatrix4fv(param1, getLimitCount(param3, 4 * 4), param2, param3); + } + + @Override + public void glUseProgram(int param1) { + GLContext.getCurrentGL().getGL2ES2().glUseProgram(param1); + } + + @Override + public void glVertexAttribPointer(int param1, int param2, int param3, boolean param4, int param5, long param6) { + GLContext.getCurrentGL().getGL2ES2().glVertexAttribPointer(param1, param2, param3, param4, param5, param6); + } + + @Override + public void glViewport(int param1, int param2, int param3, int param4) { + GLContext.getCurrentGL().glViewport(param1, param2, param3, param4); + } + + @Override + public int glGetAttribLocation(int param1, String param2) { + // JOGL 2.0 doesn't need a null-terminated string + return GLContext.getCurrentGL().getGL2ES2().glGetAttribLocation(param1, param2); + } + + @Override + public int glGetUniformLocation(int param1, String param2) { + // JOGL 2.0 doesn't need a null-terminated string + return GLContext.getCurrentGL().getGL2ES2().glGetUniformLocation(param1, param2); + } + + @Override + public void glShaderSource(int param1, String[] param2, IntBuffer param3) { + checkLimit(param3); + + int param3pos = param3.position(); + try { + for (final String param2string : param2) { + param3.put(Math.max(param2string.length(), param2string.getBytes().length)); + } + } finally { + param3.position(param3pos); + } + GLContext.getCurrentGL().getGL2ES2().glShaderSource(param1, param2.length, param2, param3); + } + + @Override + public String glGetProgramInfoLog(int program, int maxSize) { + ByteBuffer buffer = ByteBuffer.allocateDirect(maxSize); + buffer.order(ByteOrder.nativeOrder()); + ByteBuffer tmp = ByteBuffer.allocateDirect(4); + tmp.order(ByteOrder.nativeOrder()); + IntBuffer intBuffer = tmp.asIntBuffer(); + + GLContext.getCurrentGL().getGL2ES2().glGetProgramInfoLog(program, maxSize, intBuffer, buffer); + int numBytes = intBuffer.get(0); + byte[] bytes = new byte[numBytes]; + buffer.get(bytes); + return new String(bytes); + } + + @Override + public String glGetShaderInfoLog(int shader, int maxSize) { + ByteBuffer buffer = ByteBuffer.allocateDirect(maxSize); + buffer.order(ByteOrder.nativeOrder()); + ByteBuffer tmp = ByteBuffer.allocateDirect(4); + tmp.order(ByteOrder.nativeOrder()); + IntBuffer intBuffer = tmp.asIntBuffer(); + + GLContext.getCurrentGL().getGL2ES2().glGetShaderInfoLog(shader, maxSize, intBuffer, buffer); + int numBytes = intBuffer.get(0); + byte[] bytes = new byte[numBytes]; + buffer.get(bytes); + return new String(bytes); + } + + @Override + public void glBindFragDataLocation(int param1, int param2, String param3) { + GLContext.getCurrentGL().getGL2GL3().glBindFragDataLocation(param1, param2, param3); + } + + @Override + public void glBindVertexArray(int param1) { + GLContext.getCurrentGL().getGL2ES3().glBindVertexArray(param1); + } + + @Override + public void glGenVertexArrays(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().getGL2ES3().glGenVertexArrays(param1.limit(), param1); + } + + @Override + public void glPatchParameter(int count) { + GLContext.getCurrentGL().getGL3().glPatchParameteri(com.jogamp.opengl.GL3.GL_PATCH_VERTICES, count); + } + + @Override + public void glDeleteVertexArrays(IntBuffer arrays) { + checkLimit(arrays); + GLContext.getCurrentGL().getGL2ES3().glDeleteVertexArrays(arrays.limit(), arrays); + } +} diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLExt.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLExt.java new file mode 100644 index 000000000..a87e8a035 --- /dev/null +++ b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLExt.java @@ -0,0 +1,88 @@ +package com.jme3.renderer.jogl; + +import com.jme3.renderer.RendererException; +import com.jme3.renderer.opengl.GLExt; +import com.jogamp.opengl.GLContext; + +import java.nio.Buffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +public class JoglGLExt implements GLExt { + + private static int getLimitBytes(IntBuffer buffer) { + checkLimit(buffer); + return buffer.limit() * 4; + } + + private static void checkLimit(Buffer buffer) { + if (buffer == null) { + return; + } + if (buffer.limit() == 0) { + throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error"); + } + if (buffer.remaining() == 0) { + throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); + } + } + + @Override + public void glBufferData(int target, IntBuffer data, int usage) { + checkLimit(data); + GLContext.getCurrentGL().glBufferData(target, getLimitBytes(data), data, usage); + } + + @Override + public void glBufferSubData(int target, long offset, IntBuffer data) { + checkLimit(data); + GLContext.getCurrentGL().glBufferSubData(target, getLimitBytes(data), offset, data); + } + + @Override + public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) { + GLContext.getCurrentGL().getGL2ES3().glDrawArraysInstanced(mode, first, count, primcount); + } + + @Override + public void glDrawBuffers(IntBuffer bufs) { + checkLimit(bufs); + GLContext.getCurrentGL().getGL2ES2().glDrawBuffers(bufs.limit(), bufs); + } + + @Override + public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) { + GLContext.getCurrentGL().getGL2ES3().glDrawElementsInstanced(mode, indices_count, type, indices_buffer_offset, primcount); + } + + @Override + public void glGetMultisample(int pname, int index, FloatBuffer val) { + checkLimit(val); + GLContext.getCurrentGL().getGL2ES2().glGetMultisamplefv(pname, index, val); + } + + @Override + public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) { + GLContext.getCurrentGL().getGL2ES2().glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); + } + + @Override + public void glVertexAttribDivisorARB(int index, int divisor) { + GLContext.getCurrentGL().getGL2ES3().glVertexAttribDivisor(index, divisor); + } + + @Override + public Object glFenceSync(int condition, int flags) { + return GLContext.getCurrentGL().getGL3ES3().glFenceSync(condition, flags); + } + + @Override + public int glClientWaitSync(Object sync, int flags, long timeout) { + return GLContext.getCurrentGL().getGL3ES3().glClientWaitSync(((Long) sync).longValue(), flags, timeout); + } + + @Override + public void glDeleteSync(Object sync) { + GLContext.getCurrentGL().getGL3ES3().glDeleteSync(((Long) sync).longValue()); + } +} diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLFbo.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLFbo.java new file mode 100644 index 000000000..2691d2e24 --- /dev/null +++ b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLFbo.java @@ -0,0 +1,97 @@ +package com.jme3.renderer.jogl; + +import com.jme3.renderer.RendererException; +import com.jme3.renderer.opengl.GLFbo; +import com.jogamp.opengl.GLContext; + +import java.nio.Buffer; +import java.nio.IntBuffer; + +/** + * Implements GLFbo + * + * @author Kirill Vainer + */ +public class JoglGLFbo implements GLFbo { + + private static void checkLimit(Buffer buffer) { + if (buffer == null) { + return; + } + if (buffer.limit() == 0) { + throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error"); + } + if (buffer.remaining() == 0) { + throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); + } + } + + @Override + public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { + GLContext.getCurrentGL().getGL2ES3().glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + } + + @Override + public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { + GLContext.getCurrentGL().glRenderbufferStorageMultisample(target, samples, internalformat, width, height); + } + + @Override + public void glBindFramebufferEXT(int param1, int param2) { + GLContext.getCurrentGL().glBindFramebuffer(param1, param2); + } + + @Override + public void glBindRenderbufferEXT(int param1, int param2) { + GLContext.getCurrentGL().glBindRenderbuffer(param1, param2); + } + + @Override + public int glCheckFramebufferStatusEXT(int param1) { + return GLContext.getCurrentGL().glCheckFramebufferStatus(param1); + } + + @Override + public void glDeleteFramebuffersEXT(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glDeleteFramebuffers(param1.limit(), param1); + } + + @Override + public void glDeleteRenderbuffersEXT(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glDeleteRenderbuffers(param1.limit(), param1); + } + + @Override + public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) { + GLContext.getCurrentGL().glFramebufferRenderbuffer(param1, param2, param3, param4); + } + + @Override + public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) { + GLContext.getCurrentGL().glFramebufferTexture2D(param1, param2, param3, param4, param5); + } + + @Override + public void glGenFramebuffersEXT(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glGenFramebuffers(param1.limit(), param1); + } + + @Override + public void glGenRenderbuffersEXT(IntBuffer param1) { + checkLimit(param1); + GLContext.getCurrentGL().glGenRenderbuffers(param1.limit(), param1); + } + + @Override + public void glGenerateMipmapEXT(int param1) { + GLContext.getCurrentGL().glGenerateMipmap(param1); + } + + @Override + public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) { + GLContext.getCurrentGL().glRenderbufferStorage(param1, param2, param3, param4); + } +} diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java deleted file mode 100644 index 111719265..000000000 --- a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java +++ /dev/null @@ -1,2699 +0,0 @@ -/* - * Copyright (c) 2009-2012 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.renderer.jogl; - -import com.jme3.light.LightList; -import com.jme3.material.RenderState; -import com.jme3.math.ColorRGBA; -import com.jme3.math.Matrix4f; -import com.jme3.math.Quaternion; -import com.jme3.math.Vector2f; -import com.jme3.math.Vector3f; -import com.jme3.math.Vector4f; -import com.jme3.renderer.Caps; -import com.jme3.renderer.IDList; -import com.jme3.renderer.RenderContext; -import com.jme3.renderer.Renderer; -import com.jme3.renderer.RendererException; -import com.jme3.renderer.Statistics; -import com.jme3.scene.Mesh; -import com.jme3.scene.Mesh.Mode; -import com.jme3.scene.VertexBuffer; -import com.jme3.scene.VertexBuffer.Type; -import com.jme3.scene.VertexBuffer.Usage; -import com.jme3.shader.Attribute; -import com.jme3.shader.Shader; -import com.jme3.shader.Shader.ShaderSource; -import com.jme3.shader.Uniform; -import com.jme3.texture.FrameBuffer; -import com.jme3.texture.FrameBuffer.RenderBuffer; -import com.jme3.texture.Image; -import com.jme3.texture.Texture; -import com.jme3.texture.Texture.WrapAxis; -import com.jme3.util.BufferUtils; -import com.jme3.util.ListMap; -import com.jme3.util.NativeObjectManager; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.util.EnumSet; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import com.jogamp.nativewindow.NativeWindowFactory; -import com.jogamp.opengl.GL; -import com.jogamp.opengl.GL2; -import com.jogamp.opengl.GL2ES1; -import com.jogamp.opengl.GL2ES2; -import com.jogamp.opengl.GL2ES3; -import com.jogamp.opengl.GL2GL3; -import com.jogamp.opengl.GL3; -import com.jogamp.opengl.GLContext; -import jme3tools.converters.MipMapGenerator; -import jme3tools.shader.ShaderDebug; - -public class JoglRenderer implements Renderer { - - private static final Logger logger = Logger.getLogger(JoglRenderer.class.getName()); - private static final boolean VALIDATE_SHADER = false; - private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); - private final StringBuilder stringBuf = new StringBuilder(250); - private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); - private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16); - protected FloatBuffer fb16 = BufferUtils.createFloatBuffer(16); - private RenderContext context = new RenderContext(); - private NativeObjectManager objManager = new NativeObjectManager(); - private EnumSet caps = EnumSet.noneOf(Caps.class); - //current state - private Shader boundShader; - private int initialDrawBuf, initialReadBuf; - private int glslVer; - private int vertexTextureUnits; - private int fragTextureUnits; - private int vertexUniforms; - private int fragUniforms; - private int vertexAttribs; - private int maxFBOSamples; - private int maxFBOAttachs; - private int maxMRTFBOAttachs; - private int maxRBSize; - private int maxTexSize; - private int maxCubeTexSize; - private int maxVertCount; - private int maxTriCount; - private int maxColorTexSamples; - private int maxDepthTexSamples; - private FrameBuffer lastFb = null; - private FrameBuffer mainFbOverride = null; - private final Statistics statistics = new Statistics(); - private int vpX, vpY, vpW, vpH; - private int clipX, clipY, clipW, clipH; - private boolean linearizeSrgbImages; - - public JoglRenderer() { - } - - protected void updateNameBuffer() { - int len = stringBuf.length(); - - nameBuf.position(0); - nameBuf.limit(len); - for (int i = 0; i < len; i++) { - nameBuf.put((byte) stringBuf.charAt(i)); - } - - nameBuf.rewind(); - } - - @Override - public Statistics getStatistics() { - return statistics; - } - - @Override - public EnumSet getCaps() { - return caps; - } - - public void initialize() { - GL gl = GLContext.getCurrentGL(); - //logger.log(Level.FINE, "Vendor: {0}", gl.glGetString(GL.GL_VENDOR)); - //logger.log(Level.FINE, "Renderer: {0}", gl.glGetString(GL.GL_RENDERER)); - //logger.log(Level.FINE, "Version: {0}", gl.glGetString(GL.GL_VERSION)); - if (gl.isExtensionAvailable("GL_VERSION_2_0")) { - caps.add(Caps.OpenGL20); - if (gl.isExtensionAvailable("GL_VERSION_2_1")) { - caps.add(Caps.OpenGL21); - if (gl.isExtensionAvailable("GL_VERSION_3_0")) { - caps.add(Caps.OpenGL30); - if (gl.isExtensionAvailable("GL_VERSION_3_1")) { - caps.add(Caps.OpenGL31); - if (gl.isExtensionAvailable("GL_VERSION_3_2")) { - caps.add(Caps.OpenGL32); - } - } - } - } - } - - //workaround, always assume we support GLSL100 - //some cards just don't report this correctly - caps.add(Caps.GLSL100); - - String versionStr = null; - if (caps.contains(Caps.OpenGL20) || gl.isGL2ES2()) { - versionStr = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION); - } - if (versionStr == null || versionStr.equals("")) { - glslVer = -1; - throw new UnsupportedOperationException("GLSL and OpenGL2 is " + - "required for the JOGL " + - "renderer!"); - } - - // Fix issue in TestRenderToMemory when GL_FRONT is the main - // buffer being used. - gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, intBuf1); - initialDrawBuf = intBuf1.get(0); - gl.glGetIntegerv(GL2GL3.GL_READ_BUFFER, intBuf1); - initialReadBuf = intBuf1.get(0); - - // XXX: This has to be GL_BACK for canvas on Mac - // Since initialDrawBuf is GL_FRONT for pbuffer, gotta - // change this value later on ... -// initialDrawBuf = GL_BACK; -// initialReadBuf = GL_BACK; - - int spaceIdx = versionStr.indexOf(" "); - if (spaceIdx >= 1) { - versionStr = versionStr.substring(0, spaceIdx); - } - - try { - float version = Float.parseFloat(versionStr); - glslVer = (int) (version * 100); - } catch (NumberFormatException e) { - // the parsing fails on Raspberry Pi - if (NativeWindowFactory.getNativeWindowType(false).equals(NativeWindowFactory.TYPE_BCM_VC_IV)) { - logger.warning("Failed parsing GLSL version assuming it's v1.00"); - glslVer = 100; - } - } - - switch (glslVer) { - default: - if (glslVer < 400) { - break; - } - - // so that future OpenGL revisions wont break jme3 - - // fall through intentional - case 400: - case 330: - case 150: - caps.add(Caps.GLSL150); - case 140: - caps.add(Caps.GLSL140); - case 130: - caps.add(Caps.GLSL130); - case 120: - caps.add(Caps.GLSL120); - case 110: - caps.add(Caps.GLSL110); - case 100: - caps.add(Caps.GLSL100); - break; - } - - if (!caps.contains(Caps.GLSL100)) { - logger.log(Level.WARNING, "Force-adding GLSL100 support, since OpenGL2 is supported."); - caps.add(Caps.GLSL100); - } - - gl.glGetIntegerv(GL2ES2.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16); - vertexTextureUnits = intBuf16.get(0); - logger.log(Level.FINER, "VTF Units: {0}", vertexTextureUnits); - if (vertexTextureUnits > 0) { - caps.add(Caps.VertexTextureFetch); - } - - gl.glGetIntegerv(GL2ES2.GL_MAX_TEXTURE_IMAGE_UNITS, intBuf16); - fragTextureUnits = intBuf16.get(0); - logger.log(Level.FINER, "Texture Units: {0}", fragTextureUnits); - - gl.glGetIntegerv(GL2GL3.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16); - vertexUniforms = intBuf16.get(0); - logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms); - - gl.glGetIntegerv(GL2GL3.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16); - fragUniforms = intBuf16.get(0); - logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); - - gl.glGetIntegerv(GL2ES2.GL_MAX_VERTEX_ATTRIBS, intBuf16); - vertexAttribs = intBuf16.get(0); - logger.log(Level.FINER, "Vertex Attributes: {0}", vertexAttribs); - - gl.glGetIntegerv(GL2GL3.GL_MAX_VARYING_FLOATS, intBuf16); - int varyingFloats = intBuf16.get(0); - logger.log(Level.FINER, "Varying Floats: {0}", varyingFloats); - - gl.glGetIntegerv(GL.GL_SUBPIXEL_BITS, intBuf16); - int subpixelBits = intBuf16.get(0); - logger.log(Level.FINER, "Subpixel Bits: {0}", subpixelBits); - - gl.glGetIntegerv(GL2GL3.GL_MAX_ELEMENTS_VERTICES, intBuf16); - maxVertCount = intBuf16.get(0); - logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount); - - gl.glGetIntegerv(GL2GL3.GL_MAX_ELEMENTS_INDICES, intBuf16); - maxTriCount = intBuf16.get(0); - logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount); - - gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, intBuf16); - maxTexSize = intBuf16.get(0); - logger.log(Level.FINER, "Maximum Texture Resolution: {0}", maxTexSize); - - gl.glGetIntegerv(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE, intBuf16); - maxCubeTexSize = intBuf16.get(0); - logger.log(Level.FINER, "Maximum CubeMap Resolution: {0}", maxCubeTexSize); - - if (gl.isExtensionAvailable("GL_ARB_color_buffer_float")) { - // XXX: Require both 16 and 32 bit float support for FloatColorBuffer. - if (gl.isExtensionAvailable("GL_ARB_half_float_pixel")) { - caps.add(Caps.FloatColorBuffer); - } - } - - if (gl.isExtensionAvailable("GL_ARB_depth_buffer_float")) { - caps.add(Caps.FloatDepthBuffer); - } - - if (caps.contains(Caps.OpenGL30)) { - caps.add(Caps.PackedDepthStencilBuffer); - } - - if (gl.isExtensionAvailable("GL_ARB_draw_instanced") || gl.isExtensionAvailable("GL_ARB_instanced_arrays")) { - caps.add(Caps.MeshInstancing); - } - - if (gl.isExtensionAvailable("GL_ARB_texture_buffer_object")) { - caps.add(Caps.TextureBuffer); - } - - if (gl.isExtensionAvailable("GL_ARB_texture_float")) { - if (gl.isExtensionAvailable("GL_ARB_half_float_pixel")) { - caps.add(Caps.FloatTexture); - } - } - - if (gl.isExtensionAvailable("GL_ARB_vertex_array_object")) { - caps.add(Caps.VertexBufferArray); - } - - if (gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two")) { - caps.add(Caps.NonPowerOfTwoTextures); - } - else { - logger.log(Level.WARNING, "Your graphics card does not " - + "support non-power-of-2 textures. " - + "Some features might not work."); - } - - if (gl.isExtensionAvailable("GL_EXT_packed_float") || gl.isExtensionAvailable("GL_VERSION_3_0")) { - // This format is part of the OGL3 specification - caps.add(Caps.PackedFloatColorBuffer); - if (gl.isExtensionAvailable("GL_ARB_half_float_pixel")) { - // because textures are usually uploaded as RGB16F - // need half-float pixel - caps.add(Caps.PackedFloatTexture); - } - } - - if (gl.isExtensionAvailable("GL_EXT_texture_array") || gl.isExtensionAvailable("GL_VERSION_3_0")) { - caps.add(Caps.TextureArray); - } - - if (gl.isExtensionAvailable("GL_EXT_texture_shared_exponent") || gl.isExtensionAvailable("GL_VERSION_3_0")) { - caps.add(Caps.SharedExponentTexture); - } - - if (gl.isExtensionAvailable("GL_EXT_framebuffer_object")) { - caps.add(Caps.FrameBuffer); - - gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, intBuf16); - maxRBSize = intBuf16.get(0); - logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize); - - gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, intBuf16); - maxFBOAttachs = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs); - - if (gl.isExtensionAvailable("GL_EXT_framebuffer_multisample")) { - caps.add(Caps.FrameBufferMultisample); - - gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, intBuf16); - maxFBOSamples = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples); - } - - if (gl.isExtensionAvailable("GL_ARB_texture_multisample")) { - caps.add(Caps.TextureMultisample); - - gl.glGetIntegerv(GL3.GL_MAX_COLOR_TEXTURE_SAMPLES, intBuf16); - maxColorTexSamples = intBuf16.get(0); - logger.log(Level.FINER, "Texture Multisample Color Samples: {0}", maxColorTexSamples); - - gl.glGetIntegerv(GL3.GL_MAX_DEPTH_TEXTURE_SAMPLES, intBuf16); - maxDepthTexSamples = intBuf16.get(0); - logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples); - } - - gl.glGetIntegerv(GL2ES2.GL_MAX_DRAW_BUFFERS, intBuf16); - maxMRTFBOAttachs = intBuf16.get(0); - if (maxMRTFBOAttachs > 1) { - caps.add(Caps.FrameBufferMRT); - logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs); - } - - //if (gl.isExtensionAvailable("GL_ARB_draw_buffers")) { - // caps.add(Caps.FrameBufferMRT); - // gl.glGetIntegerv(GL2GL3.GL_MAX_DRAW_BUFFERS, intBuf16); - // maxMRTFBOAttachs = intBuf16.get(0); - // logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs); - //} - } - - if (gl.isExtensionAvailable("GL_ARB_multisample")) { - gl.glGetIntegerv(GL.GL_SAMPLE_BUFFERS, intBuf16); - boolean available = intBuf16.get(0) != 0; - gl.glGetIntegerv(GL.GL_SAMPLES, intBuf16); - int samples = intBuf16.get(0); - logger.log(Level.FINER, "Samples: {0}", samples); - boolean enabled = gl.glIsEnabled(GL.GL_MULTISAMPLE); - if (samples > 0 && available && !enabled) { - gl.glEnable(GL.GL_MULTISAMPLE); - } - caps.add(Caps.Multisample); - } - - //supports sRGB pipeline - if ((gl.isExtensionAvailable("GL_ARB_framebuffer_sRGB") && gl.isExtensionAvailable("GL_EXT_texture_sRGB")) || gl.isExtensionAvailable("GL_VERSION_3_0")){ - caps.add(Caps.Srgb); - } - - logger.log(Level.FINE, "Caps: {0}", caps); - } - - @Override - public void invalidateState() { - context.reset(); - boundShader = null; - lastFb = null; - - GL gl = GLContext.getCurrentGL(); - gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, intBuf1); - initialDrawBuf = intBuf1.get(0); - gl.glGetIntegerv(GL2GL3.GL_READ_BUFFER, intBuf1); - initialReadBuf = intBuf1.get(0); - } - - @Override - public void resetGLObjects() { - logger.log(Level.FINE, "Reseting objects and invalidating state"); - objManager.resetObjects(); - statistics.clearMemory(); - invalidateState(); - } - - @Override - public void cleanup() { - logger.log(Level.FINE, "Deleting objects and invalidating state"); - objManager.deleteAllObjects(this); - statistics.clearMemory(); - invalidateState(); - } - -// private void checkCap(Caps cap) { -// if (!caps.contains(cap)) { -// throw new UnsupportedOperationException("Required capability missing: " + cap.name()); -// } -// } - - /*********************************************************************\ - |* Render State *| - \*********************************************************************/ - @Override - public void setDepthRange(float start, float end) { - GL gl = GLContext.getCurrentGL(); - gl.glDepthRange(start, end); - } - - @Override - public void clearBuffers(boolean color, boolean depth, boolean stencil) { - GL gl = GLContext.getCurrentGL(); - int bits = 0; - if (color) { - //See explanations of the depth below, we must enable color write to be able to clear the color buffer - if (context.colorWriteEnabled == false) { - gl.glColorMask(true, true, true, true); - context.colorWriteEnabled = true; - } - bits = GL.GL_COLOR_BUFFER_BIT; - } - if (depth) { - - //glClear(GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false - //here s some link on openl board - //http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223 - //if depth clear is requested, we enable the depthMask - if (context.depthWriteEnabled == false) { - gl.glDepthMask(true); - context.depthWriteEnabled = true; - } - bits |= GL.GL_DEPTH_BUFFER_BIT; - } - if (stencil) { - bits |= GL.GL_STENCIL_BUFFER_BIT; - } - if (bits != 0) { - gl.glClear(bits); - } - } - - @Override - public void setBackgroundColor(ColorRGBA color) { - GL gl = GLContext.getCurrentGL(); - gl.glClearColor(color.r, color.g, color.b, color.a); - } - - @Override - public void setAlphaToCoverage(boolean value) { - if (caps.contains(Caps.Multisample)) { - GL gl = GLContext.getCurrentGL(); - if (value) { - gl.glEnable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE); - } else { - gl.glDisable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE); - } - } - } - - @Override - public void applyRenderState(RenderState state) { - GL gl = GLContext.getCurrentGL(); - if (state.isWireframe() && !context.wireframe) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE); - } - context.wireframe = true; - } else if (!state.isWireframe() && context.wireframe) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL); - } - context.wireframe = false; - } - - if (state.isDepthTest() && !context.depthTestEnabled) { - gl.glEnable(GL.GL_DEPTH_TEST); - gl.glDepthFunc(convertTestFunction(context.depthFunc)); - context.depthTestEnabled = true; - } else if (!state.isDepthTest() && context.depthTestEnabled) { - gl.glDisable(GL.GL_DEPTH_TEST); - context.depthTestEnabled = false; - } - if (state.getDepthFunc() != context.depthFunc) { - gl.glDepthFunc(convertTestFunction(state.getDepthFunc())); - context.depthFunc = state.getDepthFunc(); - } - if (gl.isGL2ES1()) { - if (state.isAlphaTest() && !context.alphaTestEnabled) { - gl.glEnable(GL2ES1.GL_ALPHA_TEST); - gl.getGL2ES1().glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff); - context.alphaTestEnabled = true; - } else if (!state.isAlphaTest() && context.alphaTestEnabled) { - gl.glDisable(GL2ES1.GL_ALPHA_TEST); - context.alphaTestEnabled = false; - } - if (state.getAlphaFallOff() != context.alphaTestFallOff) { - gl.getGL2ES1().glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff); - context.alphaTestFallOff = state.getAlphaFallOff(); - } - if (state.getAlphaFunc() != context.alphaFunc) { - gl.getGL2ES1().glAlphaFunc(convertTestFunction(state.getAlphaFunc()), context.alphaTestFallOff); - context.alphaFunc = state.getAlphaFunc(); - } - } - - if (state.isDepthWrite() && !context.depthWriteEnabled) { - gl.glDepthMask(true); - context.depthWriteEnabled = true; - } else if (!state.isDepthWrite() && context.depthWriteEnabled) { - gl.glDepthMask(false); - context.depthWriteEnabled = false; - } - - if (state.isColorWrite() && !context.colorWriteEnabled) { - gl.glColorMask(true, true, true, true); - context.colorWriteEnabled = true; - } else if (!state.isColorWrite() && context.colorWriteEnabled) { - gl.glColorMask(false, false, false, false); - context.colorWriteEnabled = false; - } - - if (state.isPointSprite() && !context.pointSprite) { - // Only enable/disable sprite - if (context.boundTextures[0] != null) { - if (context.boundTextureUnit != 0) { - gl.glActiveTexture(GL.GL_TEXTURE0); - context.boundTextureUnit = 0; - } - if (gl.isGL2ES1()) { - gl.glEnable(GL2ES1.GL_POINT_SPRITE); - } - if (gl.isGL2GL3()) { - gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE); - } - } - context.pointSprite = true; - } else if (!state.isPointSprite() && context.pointSprite) { - if (context.boundTextures[0] != null) { - if (context.boundTextureUnit != 0) { - gl.glActiveTexture(GL.GL_TEXTURE0); - context.boundTextureUnit = 0; - } - if (gl.isGL2ES1()) { - gl.glDisable(GL2ES1.GL_POINT_SPRITE); - } - if (gl.isGL2GL3()) { - gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE); - } - context.pointSprite = false; - } - } - - if (state.isPolyOffset()) { - if (!context.polyOffsetEnabled) { - gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); - gl.glPolygonOffset(state.getPolyOffsetFactor(), - state.getPolyOffsetUnits()); - context.polyOffsetEnabled = true; - context.polyOffsetFactor = state.getPolyOffsetFactor(); - context.polyOffsetUnits = state.getPolyOffsetUnits(); - } else { - if (state.getPolyOffsetFactor() != context.polyOffsetFactor - || state.getPolyOffsetUnits() != context.polyOffsetUnits) { - gl.glPolygonOffset(state.getPolyOffsetFactor(), - state.getPolyOffsetUnits()); - context.polyOffsetFactor = state.getPolyOffsetFactor(); - context.polyOffsetUnits = state.getPolyOffsetUnits(); - } - } - } else { - if (context.polyOffsetEnabled) { - gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); - context.polyOffsetEnabled = false; - context.polyOffsetFactor = 0; - context.polyOffsetUnits = 0; - } - } - - if (state.getFaceCullMode() != context.cullMode) { - if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) { - gl.glDisable(GL.GL_CULL_FACE); - } else { - gl.glEnable(GL.GL_CULL_FACE); - } - - switch (state.getFaceCullMode()) { - case Off: - break; - case Back: - gl.glCullFace(GL.GL_BACK); - break; - case Front: - gl.glCullFace(GL.GL_FRONT); - break; - case FrontAndBack: - gl.glCullFace(GL.GL_FRONT_AND_BACK); - break; - default: - throw new UnsupportedOperationException("Unrecognized face cull mode: " - + state.getFaceCullMode()); - } - - context.cullMode = state.getFaceCullMode(); - } - - if (state.getBlendMode() != context.blendMode) { - if (state.getBlendMode() == RenderState.BlendMode.Off) { - gl.glDisable(GL.GL_BLEND); - } else { - gl.glEnable(GL.GL_BLEND); - switch (state.getBlendMode()) { - case Off: - break; - case Additive: - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE); - break; - case AlphaAdditive: - gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE); - break; - case Color: - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); - break; - case Alpha: - gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); - break; - case PremultAlpha: - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); - break; - case Modulate: - gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_ZERO); - break; - case ModulateX2: - gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_SRC_COLOR); - break; - case Screen: - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); - break; - case Exclusion: - gl.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR, GL.GL_ONE_MINUS_SRC_COLOR); - break; - default: - throw new UnsupportedOperationException("Unrecognized blend mode: " - + state.getBlendMode()); - } - } - - context.blendMode = state.getBlendMode(); - } - - if (context.stencilTest != state.isStencilTest() - || context.frontStencilStencilFailOperation != state.getFrontStencilStencilFailOperation() - || context.frontStencilDepthFailOperation != state.getFrontStencilDepthFailOperation() - || context.frontStencilDepthPassOperation != state.getFrontStencilDepthPassOperation() - || context.backStencilStencilFailOperation != state.getBackStencilStencilFailOperation() - || context.backStencilDepthFailOperation != state.getBackStencilDepthFailOperation() - || context.backStencilDepthPassOperation != state.getBackStencilDepthPassOperation() - || context.frontStencilFunction != state.getFrontStencilFunction() - || context.backStencilFunction != state.getBackStencilFunction()) { - - context.frontStencilStencilFailOperation = state.getFrontStencilStencilFailOperation(); //terrible looking, I know - context.frontStencilDepthFailOperation = state.getFrontStencilDepthFailOperation(); - context.frontStencilDepthPassOperation = state.getFrontStencilDepthPassOperation(); - context.backStencilStencilFailOperation = state.getBackStencilStencilFailOperation(); - context.backStencilDepthFailOperation = state.getBackStencilDepthFailOperation(); - context.backStencilDepthPassOperation = state.getBackStencilDepthPassOperation(); - context.frontStencilFunction = state.getFrontStencilFunction(); - context.backStencilFunction = state.getBackStencilFunction(); - - if (state.isStencilTest()) { - gl.glEnable(GL.GL_STENCIL_TEST); - gl.getGL2ES2().glStencilOpSeparate(GL.GL_FRONT, - convertStencilOperation(state.getFrontStencilStencilFailOperation()), - convertStencilOperation(state.getFrontStencilDepthFailOperation()), - convertStencilOperation(state.getFrontStencilDepthPassOperation())); - gl.getGL2ES2().glStencilOpSeparate(GL.GL_BACK, - convertStencilOperation(state.getBackStencilStencilFailOperation()), - convertStencilOperation(state.getBackStencilDepthFailOperation()), - convertStencilOperation(state.getBackStencilDepthPassOperation())); - gl.getGL2ES2().glStencilFuncSeparate(GL.GL_FRONT, - convertTestFunction(state.getFrontStencilFunction()), - 0, Integer.MAX_VALUE); - gl.getGL2ES2().glStencilFuncSeparate(GL.GL_BACK, - convertTestFunction(state.getBackStencilFunction()), - 0, Integer.MAX_VALUE); - } else { - gl.glDisable(GL.GL_STENCIL_TEST); - } - } - } - - private int convertStencilOperation(RenderState.StencilOperation stencilOp) { - switch (stencilOp) { - case Keep: - return GL.GL_KEEP; - case Zero: - return GL.GL_ZERO; - case Replace: - return GL.GL_REPLACE; - case Increment: - return GL.GL_INCR; - case IncrementWrap: - return GL.GL_INCR_WRAP; - case Decrement: - return GL.GL_DECR; - case DecrementWrap: - return GL.GL_DECR_WRAP; - case Invert: - return GL.GL_INVERT; - default: - throw new UnsupportedOperationException("Unrecognized stencil operation: " + stencilOp); - } - } - - private int convertTestFunction(RenderState.TestFunction testFunc) { - switch (testFunc) { - case Never: - return GL.GL_NEVER; - case Less: - return GL.GL_LESS; - case LessOrEqual: - return GL.GL_LEQUAL; - case Greater: - return GL.GL_GREATER; - case GreaterOrEqual: - return GL.GL_GEQUAL; - case Equal: - return GL.GL_EQUAL; - case NotEqual: - return GL.GL_NOTEQUAL; - case Always: - return GL.GL_ALWAYS; - default: - throw new UnsupportedOperationException("Unrecognized test function: " + testFunc); - } - } - - /*********************************************************************\ - |* Camera and World transforms *| - \*********************************************************************/ - @Override - public void setViewPort(int x, int y, int w, int h) { - if (x != vpX || vpY != y || vpW != w || vpH != h) { - GL gl = GLContext.getCurrentGL(); - gl.glViewport(x, y, w, h); - vpX = x; - vpY = y; - vpW = w; - vpH = h; - } - } - - @Override - public void setClipRect(int x, int y, int width, int height) { - GL gl = GLContext.getCurrentGL(); - if (!context.clipRectEnabled) { - gl.glEnable(GL.GL_SCISSOR_TEST); - context.clipRectEnabled = true; - } - if (clipX != x || clipY != y || clipW != width || clipH != height) { - gl.glScissor(x, y, width, height); - clipX = x; - clipY = y; - clipW = width; - clipH = height; - } - } - - @Override - public void clearClipRect() { - if (context.clipRectEnabled) { - GL gl = GLContext.getCurrentGL(); - gl.glDisable(GL.GL_SCISSOR_TEST); - context.clipRectEnabled = false; - - clipX = 0; - clipY = 0; - clipW = 0; - clipH = 0; - } - } - - @Override - public void postFrame() { - objManager.deleteUnused(this); - } - - /*********************************************************************\ - |* Shaders *| - \*********************************************************************/ - protected void updateUniformLocation(Shader shader, Uniform uniform) { - GL gl = GLContext.getCurrentGL(); - // passing a null terminated string is not necessary with JOGL 2.0 - int loc = gl.getGL2ES2().glGetUniformLocation(shader.getId(), uniform.getName()); - if (loc < 0) { - uniform.setLocation(-1); - // uniform is not declared in shader - logger.log(Level.FINE, "Uniform {0} is not declared in shader {1}.", new Object[]{uniform.getName(), shader.getSources()}); - - } else { - uniform.setLocation(loc); - } - } - - protected void bindProgram(Shader shader) { - int shaderId = shader.getId(); - if (context.boundShaderProgram != shaderId) { - GL gl = GLContext.getCurrentGL(); - gl.getGL2ES2().glUseProgram(shaderId); - statistics.onShaderUse(shader, true); - boundShader = shader; - context.boundShaderProgram = shaderId; - } else { - statistics.onShaderUse(shader, false); - } - } - - protected void updateUniform(Shader shader, Uniform uniform) { - int shaderId = shader.getId(); - - assert uniform.getName() != null; - assert shaderId > 0; - - bindProgram(shader); - - int loc = uniform.getLocation(); - if (loc == -1) { - return; - } - - if (loc == -2) { - // get uniform location - updateUniformLocation(shader, uniform); - if (uniform.getLocation() == -1) { - // not declared, ignore - uniform.clearUpdateNeeded(); - return; - } - loc = uniform.getLocation(); - } - - if (uniform.getVarType() == null) { - return; // value not set yet.. - } - statistics.onUniformSet(); - - uniform.clearUpdateNeeded(); - FloatBuffer fb; - IntBuffer ib; - GL gl = GLContext.getCurrentGL(); - switch (uniform.getVarType()) { - case Float: - Float f = (Float) uniform.getValue(); - gl.getGL2ES2().glUniform1f(loc, f.floatValue()); - break; - case Vector2: - Vector2f v2 = (Vector2f) uniform.getValue(); - gl.getGL2ES2().glUniform2f(loc, v2.getX(), v2.getY()); - break; - case Vector3: - Vector3f v3 = (Vector3f) uniform.getValue(); - gl.getGL2ES2().glUniform3f(loc, v3.getX(), v3.getY(), v3.getZ()); - break; - case Vector4: - Object val = uniform.getValue(); - if (val instanceof ColorRGBA) { - ColorRGBA c = (ColorRGBA) val; - gl.getGL2ES2().glUniform4f(loc, c.r, c.g, c.b, c.a); - } else if (val instanceof Vector4f) { - Vector4f c = (Vector4f) val; - gl.getGL2ES2().glUniform4f(loc, c.x, c.y, c.z, c.w); - } else { - Quaternion c = (Quaternion) uniform.getValue(); - gl.getGL2ES2().glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW()); - } - break; - case Boolean: - Boolean b = (Boolean) uniform.getValue(); - gl.getGL2ES2().glUniform1i(loc, b.booleanValue() ? GL.GL_TRUE : GL.GL_FALSE); - break; - case Matrix3: - fb = (FloatBuffer) uniform.getValue(); - assert fb.remaining() == 9; - gl.getGL2ES2().glUniformMatrix3fv(loc, 1, false, fb); - break; - case Matrix4: - fb = (FloatBuffer) uniform.getValue(); - assert fb.remaining() == 16; - gl.getGL2ES2().glUniformMatrix4fv(loc, 1, false, fb); - break; - case IntArray: - ib = (IntBuffer) uniform.getValue(); - gl.getGL2ES2().glUniform1iv(loc, ib.remaining(), ib); - break; - case FloatArray: - fb = (FloatBuffer) uniform.getValue(); - gl.getGL2ES2().glUniform1fv(loc, fb.remaining(), fb); - break; - case Vector2Array: - fb = (FloatBuffer) uniform.getValue(); - gl.getGL2ES2().glUniform2fv(loc, fb.remaining(), fb); - break; - case Vector3Array: - fb = (FloatBuffer) uniform.getValue(); - gl.getGL2ES2().glUniform3fv(loc, fb.remaining(), fb); - break; - case Vector4Array: - fb = (FloatBuffer) uniform.getValue(); - gl.getGL2ES2().glUniform4fv(loc, fb.remaining(), fb); - break; - case Matrix4Array: - fb = (FloatBuffer) uniform.getValue(); - gl.getGL2ES2().glUniformMatrix4fv(loc, 1, false, fb); - break; - case Int: - Integer i = (Integer) uniform.getValue(); - gl.getGL2ES2().glUniform1i(loc, i.intValue()); - break; - default: - throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType()); - } - } - - protected void updateShaderUniforms(Shader shader) { - ListMap uniforms = shader.getUniformMap(); - for (int i = 0; i < uniforms.size(); i++) { - Uniform uniform = uniforms.getValue(i); - if (uniform.isUpdateNeeded()) { - updateUniform(shader, uniform); - } - } - } - - protected void resetUniformLocations(Shader shader) { - ListMap uniforms = shader.getUniformMap(); - for (int i = 0; i < uniforms.size(); i++) { - Uniform uniform = uniforms.getValue(i); - uniform.reset(); // e.g check location again - } - } - - public int convertShaderType(Shader.ShaderType type) { - switch (type) { - case Fragment: - return GL2ES2.GL_FRAGMENT_SHADER; - case Vertex: - return GL2ES2.GL_VERTEX_SHADER; -// case Geometry: -// return GL3.GL_GEOMETRY_SHADER_ARB; - default: - throw new UnsupportedOperationException("Unrecognized shader type."); - } - } - - public void updateShaderSourceData(ShaderSource source) { - int id = source.getId(); - GL gl = GLContext.getCurrentGL(); - if (id == -1) { - // Create id -// if (gl.isGL2ES2()) { - id = gl.getGL2ES2().glCreateShader(convertShaderType(source.getType())); -// } -// else { -// if (gl.isGL2()) { -// id = gl.getGL2().glCreateShaderObjectARB(convertShaderType(source.getType())); -// } -// } - if (id <= 0) { - throw new RendererException("Invalid ID received when trying to create shader."); - } - - source.setId(id); - } else { - throw new RendererException("Cannot recompile shader source"); - } - - // Upload shader source. - // Merge the defines and source code. - String language = source.getLanguage(); - stringBuf.setLength(0); - if (language.startsWith("GLSL")) { - int version = Integer.parseInt(language.substring(4)); - if (version > 100) { - stringBuf.append("#version "); - stringBuf.append(language.substring(4)); - if (version >= 150) { - stringBuf.append(" core"); - } - stringBuf.append("\n"); - } - } - updateNameBuffer(); - - byte[] definesCodeData = source.getDefines().getBytes(); - byte[] sourceCodeData = source.getSource().getBytes(); - ByteBuffer codeBuf = BufferUtils.createByteBuffer(nameBuf.limit() - + definesCodeData.length - + sourceCodeData.length); - codeBuf.put(nameBuf); - codeBuf.put(definesCodeData); - codeBuf.put(sourceCodeData); - codeBuf.flip(); - - byte[] array = new byte[codeBuf.limit()]; - codeBuf.rewind(); - codeBuf.get(array); - codeBuf.rewind(); - - gl.getGL2ES2().glShaderSource(id, 1, new String[]{new String(array)}, new int[]{array.length}, 0); - gl.getGL2ES2().glCompileShader(id); - - gl.getGL2ES2().glGetShaderiv(id, GL2ES2.GL_COMPILE_STATUS, intBuf1); - - boolean compiledOK = intBuf1.get(0) == GL.GL_TRUE; - String infoLog = null; - - if (VALIDATE_SHADER || !compiledOK) { - // even if compile succeeded, check - // log for warnings - gl.getGL2ES2().glGetShaderiv(id, GL2ES2.GL_INFO_LOG_LENGTH, intBuf1); - int length = intBuf1.get(0); - if (length > 3) { - // get infos - ByteBuffer logBuf = BufferUtils.createByteBuffer(length); - gl.getGL2ES2().glGetShaderInfoLog(id, length, null, logBuf); - byte[] logBytes = new byte[length]; - logBuf.get(logBytes, 0, length); - // convert to string, etc - infoLog = new String(logBytes); - } - } - - if (compiledOK) { - if (infoLog != null) { - logger.log(Level.FINE, "{0} compile success\n{1}", - new Object[]{source.getName(), infoLog}); - } else { - logger.log(Level.FINE, "{0} compile success", source.getName()); - } - source.clearUpdateNeeded(); - } else { - logger.log(Level.WARNING, "Bad compile of:\n{0}", - new Object[]{ShaderDebug.formatShaderSource(stringBuf.toString() + source.getDefines() + source.getSource())}); - if (infoLog != null) { - throw new RendererException("compile error in: " + source + "\n" + infoLog); - } else { - throw new RendererException("compile error in: " + source + "\nerror: "); - } - } - } - - public void updateShaderData(Shader shader) { - GL gl = GLContext.getCurrentGL(); - int id = shader.getId(); - boolean needRegister = false; - if (id == -1) { - // create program - id = gl.getGL2ES2().glCreateProgram(); - if (id == 0) { - throw new RendererException("Invalid ID (" + id + ") received when trying to create shader program."); - } - - shader.setId(id); - needRegister = true; - } - - for (ShaderSource source : shader.getSources()) { - if (source.isUpdateNeeded()) { - updateShaderSourceData(source); - } - gl.getGL2ES2().glAttachShader(id, source.getId()); - } - - if (gl.isGL2GL3() && gl.isExtensionAvailable("GL_EXT_gpu_shader4")) { - // Check if GLSL version is 1.5 for shader - gl.getGL2GL3().glBindFragDataLocation(id, 0, "outFragColor"); - // For MRT - for (int i = 0; i < maxMRTFBOAttachs; i++) { - gl.getGL2GL3().glBindFragDataLocation(id, i, "outFragData[" + i + "]"); - } - } - - // Link shaders to program - gl.getGL2ES2().glLinkProgram(id); - - // Check link status - gl.getGL2ES2().glGetProgramiv(id, GL2ES2.GL_LINK_STATUS, intBuf1); - boolean linkOK = intBuf1.get(0) == GL.GL_TRUE; - String infoLog = null; - - if (VALIDATE_SHADER || !linkOK) { - gl.getGL2ES2().glGetProgramiv(id, GL2ES2.GL_INFO_LOG_LENGTH, intBuf1); - int length = intBuf1.get(0); - if (length > 3) { - // get infos - ByteBuffer logBuf = BufferUtils.createByteBuffer(length); - gl.getGL2ES2().glGetProgramInfoLog(id, length, null, logBuf); - - // convert to string, etc - byte[] logBytes = new byte[length]; - logBuf.get(logBytes, 0, length); - infoLog = new String(logBytes); - } - } - - if (linkOK) { - if (infoLog != null) { - logger.log(Level.FINE, "shader link success. \n{0}", infoLog); - } else { - logger.fine("shader link success"); - } - shader.clearUpdateNeeded(); - if (needRegister) { - // Register shader for clean up if it was created in this method. - objManager.registerObject(shader); - statistics.onNewShader(); - } else { - // OpenGL spec: uniform locations may change after re-link - resetUniformLocations(shader); - } - } else { - if (infoLog != null) { - throw new RendererException("Shader failed to link, shader:" + shader + "\n" + infoLog); - } else { - throw new RendererException("Shader failed to link, shader:" + shader + "\ninfo: "); - } - } - } - - @Override - public void setShader(Shader shader) { - if (shader == null) { - throw new IllegalArgumentException("Shader cannot be null"); - } else { - if (shader.isUpdateNeeded()) { - updateShaderData(shader); - } - - // NOTE: might want to check if any of the - // sources need an update? - - assert shader.getId() > 0; - - updateShaderUniforms(shader); - bindProgram(shader); - } - } - - @Override - public void deleteShaderSource(ShaderSource source) { - if (source.getId() < 0) { - logger.warning("Shader source is not uploaded to GPU, cannot delete."); - return; - } - source.clearUpdateNeeded(); - GL gl = GLContext.getCurrentGL(); - gl.getGL2ES2().glDeleteShader(source.getId()); - source.resetObject(); - } - - @Override - public void deleteShader(Shader shader) { - if (shader.getId() == -1) { - logger.warning("Shader is not uploaded to GPU, cannot delete."); - return; - } - - GL gl = GLContext.getCurrentGL(); - for (ShaderSource source : shader.getSources()) { - if (source.getId() != -1) { - gl.getGL2ES2().glDetachShader(shader.getId(), source.getId()); - deleteShaderSource(source); - } - } - - gl.getGL2ES2().glDeleteProgram(shader.getId()); - statistics.onDeleteShader(); - shader.resetObject(); - } - - /*********************************************************************\ - |* Framebuffers *| - \*********************************************************************/ - @Override - public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) { - GL gl = GLContext.getCurrentGL(); - if (gl.isExtensionAvailable("GL_EXT_framebuffer_blit") && gl.isGL2GL3()) { - int srcX0 = 0; - int srcY0 = 0; - int srcX1; - int srcY1; - - int dstX0 = 0; - int dstY0 = 0; - int dstX1; - int dstY1; - - int prevFBO = context.boundFBO; - - if (mainFbOverride != null) { - if (src == null) { - src = mainFbOverride; - } - if (dst == null) { - dst = mainFbOverride; - } - } - - if (src != null && src.isUpdateNeeded()) { - updateFrameBuffer(src); - } - - if (dst != null && dst.isUpdateNeeded()) { - updateFrameBuffer(dst); - } - - if (src == null) { - gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); - srcX0 = vpX; - srcY0 = vpY; - srcX1 = vpX + vpW; - srcY1 = vpY + vpH; - } else { - gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, src.getId()); - srcX1 = src.getWidth(); - srcY1 = src.getHeight(); - } - if (dst == null) { - gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); - dstX0 = vpX; - dstY0 = vpY; - dstX1 = vpX + vpW; - dstY1 = vpY + vpH; - } else { - gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, dst.getId()); - dstX1 = dst.getWidth(); - dstY1 = dst.getHeight(); - } - int mask = GL.GL_COLOR_BUFFER_BIT; - if (copyDepth) { - mask |= GL.GL_DEPTH_BUFFER_BIT; - } - gl.getGL2GL3().glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, - GL.GL_NEAREST); - gl.glBindFramebuffer(GL2GL3.GL_FRAMEBUFFER, prevFBO); - - - try { - checkFrameBufferError(); - } catch (IllegalStateException ex) { - logger.log(Level.SEVERE, "Source FBO:\n{0}", src); - logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst); - throw ex; - } - } else { - throw new RendererException("EXT_framebuffer_blit required."); - // TODO: support non-blit copies? - } - } - - private String getTargetBufferName(int buffer) { - switch (buffer) { - case GL.GL_NONE: - return "NONE"; - case GL.GL_FRONT: - return "GL_FRONT"; - case GL.GL_BACK: - return "GL_BACK"; - default: - if (buffer >= GL.GL_COLOR_ATTACHMENT0 - && buffer <= GL2ES2.GL_COLOR_ATTACHMENT15) { - return "GL_COLOR_ATTACHMENT" - + (buffer - GL.GL_COLOR_ATTACHMENT0); - } else { - return "UNKNOWN? " + buffer; - } - } - } - - private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name) { - GL gl = GLContext.getCurrentGL(); - System.out.println("== Renderbuffer " + name + " =="); - System.out.println("RB ID: " + rb.getId()); - System.out.println("Is proper? " + gl.glIsRenderbuffer(rb.getId())); - - int attachment = convertAttachmentSlot(rb.getSlot()); - - gl.glGetFramebufferAttachmentParameteriv(GL2GL3.GL_DRAW_FRAMEBUFFER, - attachment, - GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, intBuf16); - int type = intBuf16.get(0); - gl.glGetFramebufferAttachmentParameteriv(GL2GL3.GL_DRAW_FRAMEBUFFER, - attachment, - GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, intBuf16); - int rbName = intBuf16.get(0); - - switch (type) { - case GL.GL_NONE: - System.out.println("Type: None"); - break; - case GL.GL_TEXTURE: - System.out.println("Type: Texture"); - break; - case GL.GL_RENDERBUFFER: - System.out.println("Type: Buffer"); - System.out.println("RB ID: " + rbName); - break; - } - - - - } - - private void printRealFrameBufferInfo(FrameBuffer fb) { - GL gl = GLContext.getCurrentGL(); - final byte[] param = new byte[1]; - gl.glGetBooleanv(GL2GL3.GL_DOUBLEBUFFER, param, 0); - boolean doubleBuffer = param[0] != (byte) 0x00; - gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, intBuf16); - String drawBuf = getTargetBufferName(intBuf16.get(0)); - gl.glGetIntegerv(GL2GL3.GL_READ_BUFFER, intBuf16); - String readBuf = getTargetBufferName(intBuf16.get(0)); - - int fbId = fb.getId(); - gl.glGetIntegerv(GL2GL3.GL_DRAW_FRAMEBUFFER_BINDING, intBuf16); - int curDrawBinding = intBuf16.get(0); - gl.glGetIntegerv(GL2GL3.GL_READ_FRAMEBUFFER_BINDING, intBuf16); - int curReadBinding = intBuf16.get(0); - - System.out.println("=== OpenGL FBO State ==="); - System.out.println("Context doublebuffered? " + doubleBuffer); - System.out.println("FBO ID: " + fbId); - System.out.println("Is proper? " + gl.glIsFramebuffer(fbId)); - System.out.println("Is bound to draw? " + (fbId == curDrawBinding)); - System.out.println("Is bound to read? " + (fbId == curReadBinding)); - System.out.println("Draw buffer: " + drawBuf); - System.out.println("Read buffer: " + readBuf); - - if (context.boundFBO != fbId) { - gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, fbId); - context.boundFBO = fbId; - } - - if (fb.getDepthBuffer() != null) { - printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth"); - } - for (int i = 0; i < fb.getNumColorBuffers(); i++) { - printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i); - } - } - - private void checkFrameBufferError() { - GL gl = GLContext.getCurrentGL(); - int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); - switch (status) { - case GL.GL_FRAMEBUFFER_COMPLETE: - break; - case GL.GL_FRAMEBUFFER_UNSUPPORTED: - // Choose different formats - throw new IllegalStateException("Framebuffer object format is " - + "unsupported by the video hardware."); - case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - throw new IllegalStateException("Framebuffer has erronous attachment."); - case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - throw new IllegalStateException("Framebuffer is missing required attachment."); - case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - throw new IllegalStateException( - "Framebuffer attachments must have same dimensions."); - case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: - throw new IllegalStateException("Framebuffer attachments must have same formats."); - case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - throw new IllegalStateException("Incomplete draw buffer."); - case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - throw new IllegalStateException("Incomplete read buffer."); - case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - throw new IllegalStateException("Incomplete multisample buffer."); - default: - // Programming error; will fail on all hardware - throw new IllegalStateException("Some video driver error " - + "or programming error occured. " - + "Framebuffer object status is invalid. "); - } - } - - private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) { - GL gl = GLContext.getCurrentGL(); - int id = rb.getId(); - if (id == -1) { - gl.glGenRenderbuffers(1, intBuf1); - id = intBuf1.get(0); - rb.setId(id); - } - - if (context.boundRB != id) { - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, id); - context.boundRB = id; - } - - if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) { - throw new RendererException("Resolution " + fb.getWidth() - + ":" + fb.getHeight() + " is not supported."); - } - - TextureUtil.GLImageFormat glFmt = TextureUtil.getImageFormatWithError(rb.getFormat(), fb.isSrgb()); - - if (fb.getSamples() > 1 && gl.isExtensionAvailable("GL_EXT_framebuffer_multisample") - && gl.isGL2GL3()/*&& gl.isFunctionAvailable("glRenderbufferStorageMultisample")*/) { - int samples = fb.getSamples(); - if (maxFBOSamples < samples) { - samples = maxFBOSamples; - } - gl.getGL2GL3() - .glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, - glFmt.internalFormat, fb.getWidth(), - fb.getHeight()); - } else { - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, - glFmt.internalFormat, fb.getWidth(), fb.getHeight()); - } - } - - private int convertAttachmentSlot(int attachmentSlot) { - // can also add support for stencil here - if (attachmentSlot == FrameBuffer.SLOT_DEPTH) { - return GL.GL_DEPTH_ATTACHMENT; - } else if (attachmentSlot == FrameBuffer.SLOT_DEPTH_STENCIL) { - return GL2ES3.GL_DEPTH_STENCIL_ATTACHMENT; - } else if (attachmentSlot < 0 || attachmentSlot >= 16) { - throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot); - } - - return GL.GL_COLOR_ATTACHMENT0 + attachmentSlot; - } - - public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) { - GL gl = GLContext.getCurrentGL(); - Texture tex = rb.getTexture(); - Image image = tex.getImage(); - if (image.isUpdateNeeded()) { - updateTexImageData(image, tex.getType(), 0); - - // NOTE: For depth textures, sets nearest/no-mips mode - // Required to fix "framebuffer unsupported" - // for old NVIDIA drivers! - setupTextureParams(tex); - } - - gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, - convertAttachmentSlot(rb.getSlot()), - convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()), - image.getId(), - 0); - } - - public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) { - boolean needAttach; - if (rb.getTexture() == null) { - // if it hasn't been created yet, then attach is required. - needAttach = rb.getId() == -1; - updateRenderBuffer(fb, rb); - } else { - needAttach = false; - updateRenderTexture(fb, rb); - } - if (needAttach) { - GL gl = GLContext.getCurrentGL(); - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, convertAttachmentSlot(rb.getSlot()), - GL.GL_RENDERBUFFER, rb.getId()); - } - } - - public void updateFrameBuffer(FrameBuffer fb) { - GL gl = GLContext.getCurrentGL(); - int id = fb.getId(); - if (id == -1) { - // create FBO - gl.glGenFramebuffers(1, intBuf1); - id = intBuf1.get(0); - fb.setId(id); - objManager.registerObject(fb); - - statistics.onNewFrameBuffer(); - } - - if (context.boundFBO != id) { - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, id); - // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0 - context.boundDrawBuf = 0; - context.boundFBO = id; - } - - FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer(); - if (depthBuf != null) { - updateFrameBufferAttachment(fb, depthBuf); - } - - for (int i = 0; i < fb.getNumColorBuffers(); i++) { - FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i); - updateFrameBufferAttachment(fb, colorBuf); - } - - fb.clearUpdateNeeded(); - } - - public Vector2f[] getFrameBufferSamplePositions(FrameBuffer fb) { - if (fb.getSamples() <= 1) { - throw new IllegalArgumentException("Framebuffer must be multisampled"); - } - - setFrameBuffer(fb); - - Vector2f[] samplePositions = new Vector2f[fb.getSamples()]; - FloatBuffer samplePos = BufferUtils.createFloatBuffer(2); - GL gl = GLContext.getCurrentGL(); - if (gl.isGL2GL3()) { - for (int i = 0; i < samplePositions.length; i++) { - gl.getGL3().glGetMultisamplefv(GL3.GL_SAMPLE_POSITION, i, samplePos); - samplePos.clear(); - samplePositions[i] = new Vector2f(samplePos.get(0) - 0.5f, - samplePos.get(1) - 0.5f); - } - } - return samplePositions; - } - - @Override - public void setMainFrameBufferOverride(FrameBuffer fb) { - mainFbOverride = fb; - } - - @Override - public void setFrameBuffer(FrameBuffer fb) { - GL gl = GLContext.getCurrentGL(); - if (!gl.isExtensionAvailable("GL_EXT_framebuffer_object")) { - throw new RendererException("Framebuffer objects are not supported" + - " by the video hardware"); - } - - if (fb == null && mainFbOverride != null) { - fb = mainFbOverride; - } - - if (lastFb == fb) { - if (fb == null || !fb.isUpdateNeeded()) { - return; - } - } - - // generate mipmaps for last FB if needed - if (lastFb != null) { - for (int i = 0; i < lastFb.getNumColorBuffers(); i++) { - RenderBuffer rb = lastFb.getColorBuffer(i); - Texture tex = rb.getTexture(); - if (tex != null - && tex.getMinFilter().usesMipMapLevels()) { - setTexture(0, rb.getTexture()); - - int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace()); - gl.glEnable(textureType); - gl.glGenerateMipmap(textureType); - gl.glDisable(textureType); - } - } - } - - if (fb == null) { - // unbind any fbos - if (context.boundFBO != 0) { - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); - statistics.onFrameBufferUse(null, true); - - context.boundFBO = 0; - } - // select back buffer - if (context.boundDrawBuf != -1) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glDrawBuffer(initialDrawBuf); - } - context.boundDrawBuf = -1; - } - if (context.boundReadBuf != -1) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glReadBuffer(initialReadBuf); - } - context.boundReadBuf = -1; - } - - lastFb = null; - } else { - if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) { - throw new IllegalArgumentException("The framebuffer: " + fb - + "\nDoesn't have any color/depth buffers"); - } - - if (fb.isUpdateNeeded()) { - updateFrameBuffer(fb); - } - - if (context.boundFBO != fb.getId()) { - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb.getId()); - statistics.onFrameBufferUse(fb, true); - - // update viewport to reflect framebuffer's resolution - setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - - context.boundFBO = fb.getId(); - } else { - statistics.onFrameBufferUse(fb, false); - } - if (fb.getNumColorBuffers() == 0) { - // make sure to select NONE as draw buf - // no color buffer attached. select NONE - if (context.boundDrawBuf != -2) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glDrawBuffer(GL.GL_NONE); - } - context.boundDrawBuf = -2; - } - if (context.boundReadBuf != -2) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glReadBuffer(GL.GL_NONE); - } - context.boundReadBuf = -2; - } - } else { - if (fb.getNumColorBuffers() > maxFBOAttachs) { - throw new RendererException("Framebuffer has more color " - + "attachments than are supported" - + " by the video hardware!"); - } - if (fb.isMultiTarget()) { - if (fb.getNumColorBuffers() > maxMRTFBOAttachs) { - throw new RendererException("Framebuffer has more" - + " multi targets than are supported" - + " by the video hardware!"); - } - - if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) { - intBuf16.clear(); - for (int i = 0; i < fb.getNumColorBuffers(); i++) { - intBuf16.put(GL.GL_COLOR_ATTACHMENT0 + i); - } - - intBuf16.flip(); - if (gl.isGL2GL3()) { - gl.getGL2GL3().glDrawBuffers(intBuf16.limit(), intBuf16); - } - context.boundDrawBuf = 100 + fb.getNumColorBuffers(); - } - } else { - RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex()); - // select this draw buffer - if (context.boundDrawBuf != rb.getSlot()) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glDrawBuffer(GL.GL_COLOR_ATTACHMENT0 + rb.getSlot()); - } - context.boundDrawBuf = rb.getSlot(); - } - } - } - - assert fb.getId() >= 0; - assert context.boundFBO == fb.getId(); - lastFb = fb; - - try { - checkFrameBufferError(); - } catch (IllegalStateException ex) { - logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb); - printRealFrameBufferInfo(fb); - throw ex; - } - } - } - - @Override - public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { - GL gl = GLContext.getCurrentGL(); - if (fb != null) { - RenderBuffer rb = fb.getColorBuffer(); - if (rb == null) { - throw new IllegalArgumentException("Specified framebuffer" - + " does not have a colorbuffer"); - } - - setFrameBuffer(fb); - if (context.boundReadBuf != rb.getSlot()) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glReadBuffer(GL.GL_COLOR_ATTACHMENT0 + rb.getSlot()); - } - context.boundReadBuf = rb.getSlot(); - } - } else { - setFrameBuffer(null); - } - - gl.glReadPixels(vpX, vpY, vpW, vpH, /*GL.GL_RGBA*/ GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, byteBuf); - } - - private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) { - intBuf1.put(0, rb.getId()); - GL gl = GLContext.getCurrentGL(); - gl.glDeleteRenderbuffers(1, intBuf1); - } - - @Override - public void deleteFrameBuffer(FrameBuffer fb) { - if (fb.getId() != -1) { - GL gl = GLContext.getCurrentGL(); - if (context.boundFBO == fb.getId()) { - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); - context.boundFBO = 0; - } - - if (fb.getDepthBuffer() != null) { - deleteRenderBuffer(fb, fb.getDepthBuffer()); - } - if (fb.getColorBuffer() != null) { - deleteRenderBuffer(fb, fb.getColorBuffer()); - } - - intBuf1.put(0, fb.getId()); - gl.glDeleteFramebuffers(1, intBuf1); - fb.resetObject(); - - statistics.onDeleteFrameBuffer(); - } - } - - /*********************************************************************\ - |* Textures *| - \*********************************************************************/ - private int convertTextureType(Texture.Type type, int samples, int face) { - GL gl = GLContext.getCurrentGL(); - if (samples > 1 && !gl.isExtensionAvailable("GL_ARB_texture_multisample")) { - throw new RendererException("Multisample textures are not supported" + - " by the video hardware."); - } - - switch (type) { - case TwoDimensional: - if (samples > 1) { - return GL3.GL_TEXTURE_2D_MULTISAMPLE; - } else { - return GL.GL_TEXTURE_2D; - } - case TwoDimensionalArray: - if (samples > 1) { - return GL3.GL_TEXTURE_2D_MULTISAMPLE_ARRAY; - } else { - return GL2ES3.GL_TEXTURE_2D_ARRAY; - } - case ThreeDimensional: - return GL2ES2.GL_TEXTURE_3D; - case CubeMap: - if (face < 0) { - return GL.GL_TEXTURE_CUBE_MAP; - } else if (face < 6) { - return GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; - } else { - throw new UnsupportedOperationException("Invalid cube map face index: " + face); - } - default: - throw new UnsupportedOperationException("Unknown texture type: " + type); - } - } - - private int convertMagFilter(Texture.MagFilter filter) { - switch (filter) { - case Bilinear: - return GL.GL_LINEAR; - case Nearest: - return GL.GL_NEAREST; - default: - throw new UnsupportedOperationException("Unknown mag filter: " + filter); - } - } - - private int convertMinFilter(Texture.MinFilter filter) { - switch (filter) { - case Trilinear: - return GL.GL_LINEAR_MIPMAP_LINEAR; - case BilinearNearestMipMap: - return GL.GL_LINEAR_MIPMAP_NEAREST; - case NearestLinearMipMap: - return GL.GL_NEAREST_MIPMAP_LINEAR; - case NearestNearestMipMap: - return GL.GL_NEAREST_MIPMAP_NEAREST; - case BilinearNoMipMaps: - return GL.GL_LINEAR; - case NearestNoMipMaps: - return GL.GL_NEAREST; - default: - throw new UnsupportedOperationException("Unknown min filter: " + filter); - } - } - - private int convertWrapMode(Texture.WrapMode mode) { - switch (mode) { - case BorderClamp: - return GL2GL3.GL_CLAMP_TO_BORDER; - case Clamp: - // Falldown intentional. - case EdgeClamp: - return GL.GL_CLAMP_TO_EDGE; - case Repeat: - return GL.GL_REPEAT; - case MirroredRepeat: - return GL.GL_MIRRORED_REPEAT; - default: - throw new UnsupportedOperationException("Unknown wrap mode: " + mode); - } - } - - @SuppressWarnings("fallthrough") - private void setupTextureParams(Texture tex) { - GL gl = GLContext.getCurrentGL(); - Image image = tex.getImage(); - int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1); - - // filter things - int minFilter = convertMinFilter(tex.getMinFilter()); - int magFilter = convertMagFilter(tex.getMagFilter()); - gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter); - gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, magFilter); - - if (tex.getAnisotropicFilter() > 1) { - if (gl.isExtensionAvailable("GL_EXT_texture_filter_anisotropic")) { - gl.glTexParameterf(target, - GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, - tex.getAnisotropicFilter()); - } - } - - if (context.pointSprite) { - return; // Attempt to fix glTexParameter crash for some ATI GPUs - } - // repeat modes - switch (tex.getType()) { - case ThreeDimensional: - case CubeMap: // cubemaps use 3D coords - gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R))); - case TwoDimensional: - case TwoDimensionalArray: - gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T))); - // fall down here is intentional.. -// case OneDimensional: - gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S))); - break; - default: - throw new UnsupportedOperationException("Unknown texture type: " + tex.getType()); - } - - if (tex.isNeedCompareModeUpdate()) { - // R to Texture compare mode - if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { - gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE); - gl.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); - if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) { - gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL); - } else { - gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL); - } - } else { - //restoring default value - gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); - } - tex.compareModeUpdated(); - } - } - - /** - * Uploads the given image to the GL driver. - * - * @param img The image to upload - * @param type How the data in the image argument should be interpreted. - * @param unit The texture slot to be used to upload the image, not important - */ - public void updateTexImageData(Image img, Texture.Type type, int unit) { - int texId = img.getId(); - GL gl = GLContext.getCurrentGL(); - if (texId == -1) { - // create texture - gl.glGenTextures(1, intBuf1); - texId = intBuf1.get(0); - img.setId(texId); - objManager.registerObject(img); - - statistics.onNewTexture(); - } - - // bind texture - int target = convertTextureType(type, img.getMultiSamples(), -1); - if (context.boundTextureUnit != unit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + unit); - context.boundTextureUnit = unit; - } - if (context.boundTextures[unit] != img) { - gl.glBindTexture(target, texId); - context.boundTextures[unit] = img; - - statistics.onTextureUse(img, true); - } - - if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired()) { - // Image does not have mipmaps, but they are required. - // Generate from base level. - - if (!gl.isExtensionAvailable("GL_VERSION_3_0")) { - if (gl.isGL2ES1()) { - gl.glTexParameteri(target, GL2ES1.GL_GENERATE_MIPMAP, GL.GL_TRUE); - img.setMipmapsGenerated(true); - } - } else { - // For OpenGL3 and up. - // We'll generate mipmaps via glGenerateMipmapEXT (see below) - } - } else if (img.hasMipmaps()) { - // Image already has mipmaps, set the max level based on the - // number of mipmaps we have. - if (gl.isGL2GL3()) { - gl.glTexParameteri(target, GL2ES3.GL_TEXTURE_MAX_LEVEL, img.getMipMapSizes().length - 1); - } - } else { - // Image does not have mipmaps and they are not required. - // Specify that that the texture has no mipmaps. - gl.glTexParameteri(target, GL2ES3.GL_TEXTURE_MAX_LEVEL, 0); - } - - int imageSamples = img.getMultiSamples(); - if (imageSamples > 1) { - if (img.getFormat().isDepthFormat()) { - img.setMultiSamples(Math.min(maxDepthTexSamples, imageSamples)); - } else { - img.setMultiSamples(Math.min(maxColorTexSamples, imageSamples)); - } - } - - // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT. - if (!gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") && img.isNPOT()) { - if (img.getData(0) == null) { - throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware"); - } else { - MipMapGenerator.resizeToPowerOf2(img); - } - } - - // Check if graphics card doesn't support multisample textures - if (!gl.isExtensionAvailable("GL_ARB_texture_multisample")) { - if (img.getMultiSamples() > 1) { - throw new RendererException("Multisample textures not supported by graphics hardware"); - } - } - - if (target == GL.GL_TEXTURE_CUBE_MAP) { - List data = img.getData(); - if (data.size() != 6) { - logger.log(Level.WARNING, "Invalid texture: {0}\n" - + "Cubemap textures must contain 6 data units.", img); - return; - } - for (int i = 0; i < 6; i++) { - TextureUtil.uploadTexture(img, GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, linearizeSrgbImages); - } - } else if (target == GL2ES3.GL_TEXTURE_2D_ARRAY) { - if (!caps.contains(Caps.TextureArray)) { - throw new RendererException("Texture arrays not supported by graphics hardware"); - } - - List data = img.getData(); - - // -1 index specifies prepare data for 2D Array - TextureUtil.uploadTexture(img, target, -1, 0, linearizeSrgbImages); - - for (int i = 0; i < data.size(); i++) { - // upload each slice of 2D array in turn - // this time with the appropriate index - TextureUtil.uploadTexture(img, target, i, 0, linearizeSrgbImages); - } - } else { - TextureUtil.uploadTexture(img, target, 0, 0, linearizeSrgbImages); - } - - if (img.getMultiSamples() != imageSamples) { - img.setMultiSamples(imageSamples); - } - - if (gl.isExtensionAvailable("GL_VERSION_3_0")) { - if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired() && img.getData() != null) { - // XXX: Required for ATI - gl.glEnable(target); - gl.glGenerateMipmap(target); - gl.glDisable(target); - img.setMipmapsGenerated(true); - } - } - - img.clearUpdateNeeded(); - } - - @Override - public void setTexture(int unit, Texture tex) { - GL gl = GLContext.getCurrentGL(); - Image image = tex.getImage(); - if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) { - updateTexImageData(image, tex.getType(), unit); - } - - int texId = image.getId(); - assert texId != -1; - - Image[] textures = context.boundTextures; - - int type = convertTextureType(tex.getType(), image.getMultiSamples(), -1); -// if (!context.textureIndexList.moveToNew(unit)) { -// if (context.boundTextureUnit != unit){ -// gl.glActiveTexture(GL.GL_TEXTURE0 + unit); -// context.boundTextureUnit = unit; -// } -// gl.glEnable(type); -// } - - if (context.boundTextureUnit != unit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + unit); - context.boundTextureUnit = unit; - } - if (textures[unit] != image) { - gl.glBindTexture(type, texId); - textures[unit] = image; - - statistics.onTextureUse(image, true); - } else { - statistics.onTextureUse(image, false); - } - - setupTextureParams(tex); - } - - @Override - public void modifyTexture(Texture tex, Image pixels, int x, int y) { - setTexture(0, tex); - TextureUtil.uploadSubTexture(pixels, convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), -1), 0, x, y, linearizeSrgbImages); - } - - public void clearTextureUnits() { - /*GL gl = GLContext.getCurrentGL(); - IDList textureList = context.textureIndexList; - Texture[] textures = context.boundTextures; - for (int i = 0; i < textureList.oldLen; i++) { - int idx = textureList.oldList[i]; - - if (context.boundTextureUnit != idx) { - gl.glActiveTexture(GL.GL_TEXTURE0 + idx); - context.boundTextureUnit = idx; - } - gl.glDisable(convertTextureType(textures[idx].getType())); - textures[idx] = null; - } - context.textureIndexList.copyNewToOld();*/ - } - - @Override - public void deleteImage(Image image) { - int texId = image.getId(); - if (texId != -1) { - intBuf1.put(0, texId); - intBuf1.position(0).limit(1); - GL gl = GLContext.getCurrentGL(); - gl.glDeleteTextures(1, intBuf1); - image.resetObject(); - - statistics.onDeleteTexture(); - } - } - - /*********************************************************************\ - |* Vertex Buffers and Attributes *| - \*********************************************************************/ - private int convertUsage(Usage usage) { - switch (usage) { - case Static: - return GL.GL_STATIC_DRAW; - case Dynamic: - return GL.GL_DYNAMIC_DRAW; - case Stream: - return GL2ES2.GL_STREAM_DRAW; - default: - throw new RuntimeException("Unknown usage type: " + usage); - } - } - - private int convertFormat(VertexBuffer.Format format) { - switch (format) { - case Byte: - return GL.GL_BYTE; - case UnsignedByte: - return GL.GL_UNSIGNED_BYTE; - case Short: - return GL.GL_SHORT; - case UnsignedShort: - return GL.GL_UNSIGNED_SHORT; - case Int: - return GL2ES2.GL_INT; - case UnsignedInt: - return GL.GL_UNSIGNED_INT; - case Float: - return GL.GL_FLOAT; - case Double: - return GL2GL3.GL_DOUBLE; - default: - throw new UnsupportedOperationException("Unknown buffer format."); - - } - } - - @Override - public void updateBufferData(VertexBuffer vb) { - GL gl = GLContext.getCurrentGL(); - int bufId = vb.getId(); - boolean created = false; - if (bufId == -1) { - // create buffer - gl.glGenBuffers(1, intBuf1); - bufId = intBuf1.get(0); - vb.setId(bufId); - objManager.registerObject(vb); - - //statistics.onNewVertexBuffer(); - - created = true; - } - - // bind buffer - int target; - if (vb.getBufferType() == VertexBuffer.Type.Index) { - target = GL.GL_ELEMENT_ARRAY_BUFFER; - if (context.boundElementArrayVBO != bufId) { - gl.glBindBuffer(target, bufId); - context.boundElementArrayVBO = bufId; - //statistics.onVertexBufferUse(vb, true); - } else { - //statistics.onVertexBufferUse(vb, false); - } - } else { - target = GL.GL_ARRAY_BUFFER; - if (context.boundArrayVBO != bufId) { - gl.glBindBuffer(target, bufId); - context.boundArrayVBO = bufId; - //statistics.onVertexBufferUse(vb, true); - } else { - //statistics.onVertexBufferUse(vb, false); - } - } - - int usage = convertUsage(vb.getUsage()); - Buffer data = vb.getData(); - data.rewind(); - - if (created || vb.hasDataSizeChanged()) { - // upload data based on format - gl.glBufferData(target, data.capacity() * vb.getFormat().getComponentSize(), data, usage); - } else { - gl.glBufferSubData(target, 0, data.capacity() * vb.getFormat().getComponentSize(), data); - } - - vb.clearUpdateNeeded(); - } - - @Override - public void deleteBuffer(VertexBuffer vb) { - GL gl = GLContext.getCurrentGL(); - int bufId = vb.getId(); - if (bufId != -1) { - // delete buffer - intBuf1.put(0, bufId); - intBuf1.position(0).limit(1); - gl.glDeleteBuffers(1, intBuf1); - vb.resetObject(); - - //statistics.onDeleteVertexBuffer(); - } - } - - public void clearVertexAttribs() { - GL gl = GLContext.getCurrentGL(); - IDList attribList = context.attribIndexList; - for (int i = 0; i < attribList.oldLen; i++) { - int idx = attribList.oldList[i]; - gl.getGL2ES2().glDisableVertexAttribArray(idx); - if (context.boundAttribs[idx].isInstanced() && gl.isGL3ES3()) { - gl.getGL3ES3().glVertexAttribDivisor(idx, 0); - } - context.boundAttribs[idx] = null; - } - context.attribIndexList.copyNewToOld(); - } - - public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) { - if (vb.getBufferType() == VertexBuffer.Type.Index) { - throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib"); - } - - int programId = context.boundShaderProgram; - if (programId > 0) { - GL gl = GLContext.getCurrentGL(); - Attribute attrib = boundShader.getAttribute(vb.getBufferType()); - int loc = attrib.getLocation(); - if (loc == -1) { - return; // not defined - } - if (loc == -2) { - stringBuf.setLength(0); - // JOGL 2.0 doesn't need a null terminated string - stringBuf.append("in").append(vb.getBufferType().name()); - loc = gl.getGL2ES2().glGetAttribLocation(programId, stringBuf.toString()); - - // not really the name of it in the shader (inPosition\0) but - // the internal name of the enum (Position). - if (loc < 0) { - attrib.setLocation(-1); - return; // not available in shader. - } else { - attrib.setLocation(loc); - } - } - - if (vb.isInstanced()) { - if (!gl.isExtensionAvailable("GL_ARB_instanced_arrays") - || !gl.isExtensionAvailable("GL_ARB_draw_instanced")) { - throw new RendererException("Instancing is required, " - + "but not supported by the " - + "graphics hardware"); - } - } - int slotsRequired = 1; - if (vb.getNumComponents() > 4) { - if (vb.getNumComponents() % 4 != 0) { - throw new RendererException("Number of components in multi-slot " - + "buffers must be divisible by 4"); - } - slotsRequired = vb.getNumComponents() / 4; - } - - if (vb.isUpdateNeeded() && idb == null) { - updateBufferData(vb); - } - - VertexBuffer[] attribs = context.boundAttribs; - for (int i = 0; i < slotsRequired; i++) { - if (!context.attribIndexList.moveToNew(loc + i)) { - gl.getGL2ES2().glEnableVertexAttribArray(loc + i); - //System.out.println("Enabled ATTRIB IDX: "+loc + i); - } - } - if (attribs[loc] != vb) { - // NOTE: Use id from interleaved buffer if specified - int bufId = idb != null ? idb.getId() : vb.getId(); - assert bufId != -1; - if (context.boundArrayVBO != bufId) { - gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufId); - context.boundArrayVBO = bufId; - //statistics.onVertexBufferUse(vb, true); - } else { - //statistics.onVertexBufferUse(vb, false); - } - - if (slotsRequired == 1) { - gl.getGL2ES2().glVertexAttribPointer(loc, - vb.getNumComponents(), - convertFormat(vb.getFormat()), - vb.isNormalized(), - vb.getStride(), - vb.getOffset()); - } else { - for (int i = 0; i < slotsRequired; i++) { - // The pointer maps the next 4 floats in the slot. - // E.g. - // P1: XXXX____________XXXX____________ - // P2: ____XXXX____________XXXX________ - // P3: ________XXXX____________XXXX____ - // P4: ____________XXXX____________XXXX - // stride = 4 bytes in float * 4 floats in slot * num slots - // offset = 4 bytes in float * 4 floats in slot * slot index - gl.getGL2ES2().glVertexAttribPointer(loc + i, - 4, - convertFormat(vb.getFormat()), - vb.isNormalized(), - 4 * 4 * slotsRequired, - 4 * 4 * i); - } - } - - for (int i = 0; i < slotsRequired; i++) { - int slot = loc + i; - if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) { - // non-instanced -> instanced - gl.getGL3ES3().glVertexAttribDivisor(slot, vb.getInstanceSpan()); - } else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) { - // instanced -> non-instanced - gl.getGL3ES3().glVertexAttribDivisor(slot, 0); - } - attribs[slot] = vb; - } - } - } else { - throw new IllegalStateException("Cannot render mesh without shader bound"); - } - } - - public void setVertexAttrib(VertexBuffer vb) { - setVertexAttrib(vb, null); - } - - public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) { - boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); - GL gl = GLContext.getCurrentGL(); - if (useInstancing) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glDrawArraysInstanced(convertElementMode(mode), 0, - vertCount, count); - } - } else { - gl.glDrawArrays(convertElementMode(mode), 0, vertCount); - } - } - - public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) { - if (indexBuf.getBufferType() != VertexBuffer.Type.Index) { - throw new IllegalArgumentException("Only index buffers are allowed as triangle lists."); - } - - if (indexBuf.isUpdateNeeded()) { - updateBufferData(indexBuf); - } - - int bufId = indexBuf.getId(); - assert bufId != -1; - - GL gl = GLContext.getCurrentGL(); - - if (context.boundElementArrayVBO != bufId) { - gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, bufId); - context.boundElementArrayVBO = bufId; - //statistics.onVertexBufferUse(indexBuf, true); - } else { - //statistics.onVertexBufferUse(indexBuf, true); - } - - int vertCount = mesh.getVertexCount(); - boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); - - if (mesh.getMode() == Mode.Hybrid) { - int[] modeStart = mesh.getModeStart(); - int[] elementLengths = mesh.getElementLengths(); - - int elMode = convertElementMode(Mode.Triangles); - int fmt = convertFormat(indexBuf.getFormat()); - int elSize = indexBuf.getFormat().getComponentSize(); - int listStart = modeStart[0]; - int stripStart = modeStart[1]; - int fanStart = modeStart[2]; - int curOffset = 0; - for (int i = 0; i < elementLengths.length; i++) { - if (i == stripStart) { - elMode = convertElementMode(Mode.TriangleStrip); - } else if (i == fanStart) { - elMode = convertElementMode(Mode.TriangleStrip); - } - int elementLength = elementLengths[i]; - - if (useInstancing) { - if (gl.isGL2()) { - indexBuf.getData().position(curOffset); - indexBuf.getData().limit(curOffset + elementLength); - - gl.getGL2().glDrawElementsInstanced(elMode, - elementLength, - fmt, - indexBuf.getData(), - count); - } else { - throw new IllegalArgumentException( - "instancing is not supported."); - } - } else { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glDrawRangeElements(elMode, - 0, - vertCount, - elementLength, - fmt, - curOffset); - } else { - indexBuf.getData().position(curOffset); - gl.getGL2().glDrawElements(elMode, elementLength, fmt, - indexBuf.getData()); - } - } - - curOffset += elementLength * elSize; - } - } else { - if (useInstancing) { - if (gl.isGL2()) { - gl.getGL2().glDrawElementsInstanced(convertElementMode(mesh.getMode()), - indexBuf.getData().limit(), - convertFormat(indexBuf.getFormat()), - indexBuf.getData(), - count); - } else { - throw new IllegalArgumentException( - "instancing is not supported."); - } - } else { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glDrawRangeElements(convertElementMode(mesh.getMode()), - 0, - vertCount, - indexBuf.getData().limit(), - convertFormat(indexBuf.getFormat()), - 0); - } else { - indexBuf.getData().rewind(); - gl.glDrawElements(convertElementMode(mesh.getMode()), - indexBuf.getData().limit(), - convertFormat(indexBuf.getFormat()), 0); - } - } - } - } - - /** - * *******************************************************************\ |* - * Render Calls *| - \******************************************************************** - */ - private int convertElementMode(Mesh.Mode mode) { - switch (mode) { - case Points: - return GL.GL_POINTS; - case Lines: - return GL.GL_LINES; - case LineLoop: - return GL.GL_LINE_LOOP; - case LineStrip: - return GL.GL_LINE_STRIP; - case Triangles: - return GL.GL_TRIANGLES; - case TriangleFan: - return GL.GL_TRIANGLE_FAN; - case TriangleStrip: - return GL.GL_TRIANGLE_STRIP; - default: - throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode); - } - } - - public void updateVertexArray(Mesh mesh, VertexBuffer instanceData) { - int id = mesh.getId(); - GL gl = GLContext.getCurrentGL(); - - if (id == -1) { - IntBuffer temp = intBuf1; - if (gl.isGL2GL3()) { - gl.getGL2GL3().glGenVertexArrays(1, temp); - } - id = temp.get(0); - mesh.setId(id); - } - - if (context.boundVertexArray != id) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glBindVertexArray(id); - } - context.boundVertexArray = id; - } - - VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); - if (interleavedData != null && interleavedData.isUpdateNeeded()) { - updateBufferData(interleavedData); - } - - if (instanceData != null) { - setVertexAttrib(instanceData, null); - } - - for (VertexBuffer vb : mesh.getBufferList().getArray()) { - if (vb.getBufferType() == Type.InterleavedData - || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers - || vb.getBufferType() == Type.Index) { - continue; - } - - if (vb.getStride() == 0) { - // not interleaved - setVertexAttrib(vb); - } else { - // interleaved - setVertexAttrib(vb, interleavedData); - } - } - } - - private void renderMeshVertexArray(Mesh mesh, int lod, int count, VertexBuffer instanceData) { - if (mesh.getId() == -1) { - updateVertexArray(mesh, instanceData); - } else { - // TODO: Check if it was updated - } - - if (context.boundVertexArray != mesh.getId()) { - GL gl = GLContext.getCurrentGL(); - if (gl.isGL2GL3()) { - gl.getGL2GL3().glBindVertexArray(mesh.getId()); - } - context.boundVertexArray = mesh.getId(); - } - -// IntMap buffers = mesh.getBuffers(); - VertexBuffer indices; - if (mesh.getNumLodLevels() > 0) { - indices = mesh.getLodLevel(lod); - } else { - indices = mesh.getBuffer(Type.Index); - } - if (indices != null) { - drawTriangleList(indices, mesh, count); - } else { - drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount()); - } - clearVertexAttribs(); - clearTextureUnits(); - } - - private void renderMeshDefault(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { - - // Here while count is still passed in. Can be removed when/if - // the method is collapsed again. -pspeed - count = Math.max(mesh.getInstanceCount(), count); - - VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); - if (interleavedData != null && interleavedData.isUpdateNeeded()) { - updateBufferData(interleavedData); - } - - VertexBuffer indices; - if (mesh.getNumLodLevels() > 0) { - indices = mesh.getLodLevel(lod); - } else { - indices = mesh.getBuffer(Type.Index); - } - - if (instanceData != null) { - for (VertexBuffer vb : instanceData) { - setVertexAttrib(vb, null); - } - } - - for (VertexBuffer vb : mesh.getBufferList().getArray()) { - if (vb.getBufferType() == Type.InterleavedData - || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers - || vb.getBufferType() == Type.Index) { - continue; - } - - if (vb.getStride() == 0) { - // not interleaved - setVertexAttrib(vb); - } else { - // interleaved - setVertexAttrib(vb, interleavedData); - } - } - - if (indices != null) { - drawTriangleList(indices, mesh, count); - } else { - drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount()); - } - clearVertexAttribs(); - clearTextureUnits(); - } - - @Override - public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { - if (mesh.getVertexCount() == 0) { - return; - } - - GL gl = GLContext.getCurrentGL(); - if (context.pointSprite && mesh.getMode() != Mode.Points) { - // XXX: Hack, disable point sprite mode if mesh not in point mode - if (context.boundTextures[0] != null) { - if (context.boundTextureUnit != 0) { - gl.glActiveTexture(GL.GL_TEXTURE0); - context.boundTextureUnit = 0; - } - if (gl.isGL2ES1()) { - gl.glDisable(GL2ES1.GL_POINT_SPRITE); - } - if (gl.isGL2GL3()) { - gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE); - } - context.pointSprite = false; - } - } - - if (context.pointSize != mesh.getPointSize()) { - if (gl.isGL2GL3()) { - gl.getGL2GL3().glPointSize(mesh.getPointSize()); - } - context.pointSize = mesh.getPointSize(); - } - if (context.lineWidth != mesh.getLineWidth()) { - gl.glLineWidth(mesh.getLineWidth()); - context.lineWidth = mesh.getLineWidth(); - } - - statistics.onMeshDrawn(mesh, lod); -// if (gl.isExtensionAvailable("GL_ARB_vertex_array_object")){ -// renderMeshVertexArray(mesh, lod, count); -// }else{ - renderMeshDefault(mesh, lod, count, instanceData); -// } - } - - @Override - public void setMainFrameBufferSrgb(boolean srgb) { - //Gamma correction - if(srgb && caps.contains(Caps.Srgb)){ - GLContext.getCurrentGL().glEnable(GL3.GL_FRAMEBUFFER_SRGB); - logger.log(Level.FINER, "SRGB FrameBuffer enabled (Gamma Correction)"); - }else{ - GLContext.getCurrentGL().glDisable(GL3.GL_FRAMEBUFFER_SRGB); - } - - } - - @Override - public void setLinearizeSrgbImages(boolean linearize) { - linearizeSrgbImages = linearize; - } - - public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { - throw new UnsupportedOperationException("Not supported yet. URA will make that work seamlessly"); - } -} diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglAbstractDisplay.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglAbstractDisplay.java index a7f7fbfd7..3b468f1aa 100644 --- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglAbstractDisplay.java +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglAbstractDisplay.java @@ -37,22 +37,16 @@ import com.jme3.input.MouseInput; import com.jme3.input.TouchInput; import com.jme3.input.awt.AwtKeyInput; import com.jme3.input.awt.AwtMouseInput; -import com.jme3.renderer.jogl.JoglRenderer; +import com.jme3.system.AppSettings; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.util.FPSAnimator; + import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; -import com.jogamp.opengl.DebugGL2; -import com.jogamp.opengl.DebugGL3; -import com.jogamp.opengl.DebugGL3bc; -import com.jogamp.opengl.DebugGL4; -import com.jogamp.opengl.DebugGL4bc; -import com.jogamp.opengl.DebugGLES1; -import com.jogamp.opengl.DebugGLES2; -import com.jogamp.opengl.GL; + import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; @@ -87,9 +81,13 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); - //FIXME use the settings to know whether to use the max programmable profile - //then call GLProfile.getMaxProgrammable(true); - GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true)); + GLCapabilities caps; + if (settings.getRenderer().equals(AppSettings.JOGL_OPENGL_FORWARD_COMPATIBLE)) { + caps = new GLCapabilities(GLProfile.getMaxProgrammable(true)); + } else { + caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true)); + } + caps.setHardwareAccelerated(true); caps.setDoubleBuffered(true); caps.setStencilBits(settings.getStencilBits()); @@ -124,50 +122,9 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent canvas.setSize(settings.getWidth(), settings.getHeight()); canvas.setIgnoreRepaint(true); canvas.addGLEventListener(this); - - if (settings.getBoolean("GraphicsDebug")) { - canvas.invoke(false, new GLRunnable() { - public boolean run(GLAutoDrawable glad) { - GL gl = glad.getGL(); - if (gl.isGLES()) { - if (gl.isGLES1()) { - glad.setGL(new DebugGLES1(gl.getGLES1())); - } else { - if (gl.isGLES2()) { - glad.setGL(new DebugGLES2(gl.getGLES2())); - } else { - // TODO ES3 - } - } - } else { - if (gl.isGL4bc()) { - glad.setGL(new DebugGL4bc(gl.getGL4bc())); - } else { - if (gl.isGL4()) { - glad.setGL(new DebugGL4(gl.getGL4())); - } else { - if (gl.isGL3bc()) { - glad.setGL(new DebugGL3bc(gl.getGL3bc())); - } else { - if (gl.isGL3()) { - glad.setGL(new DebugGL3(gl.getGL3())); - } else { - if (gl.isGL2()) { - glad.setGL(new DebugGL2(gl.getGL2())); - } - } - } - } - } - } - return true; - } - }); - } - renderer = new JoglRenderer(); - - renderer.setMainFrameBufferSrgb(settings.getGammaCorrection()); + //FIXME not sure it is the best place to do that + renderable.set(true); } protected void startGLCanvas() { @@ -182,9 +139,6 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent animator.start(); wasAnimating = true; - - //FIXME not sure it is the best place to do that - renderable.set(true); } protected void onCanvasAdded() { diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglCanvas.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglCanvas.java index 9a409b85e..b56eb43c1 100644 --- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglCanvas.java +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglCanvas.java @@ -41,28 +41,34 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext private static final Logger logger = Logger.getLogger(JoglCanvas.class.getName()); private int width, height; + private boolean runningFirstTime = true; public JoglCanvas(){ super(); initGLCanvas(); } - public Type getType() { + @Override + public Type getType() { return Type.Canvas; } - public void setTitle(String title) { + @Override + public void setTitle(String title) { } - public void restart() { + @Override + public void restart() { } - public void create(boolean waitFor){ + @Override + public void create(boolean waitFor){ if (waitFor) waitFor(true); } - public void destroy(boolean waitFor){ + @Override + public void destroy(boolean waitFor){ if (waitFor) waitFor(false); if (animator.isAnimating()) @@ -81,13 +87,20 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext startGLCanvas(); } - public void init(GLAutoDrawable drawable) { + @Override + public void init(GLAutoDrawable drawable) { canvas.requestFocus(); super.internalCreate(); logger.fine("Display created."); - renderer.initialize(); + // At this point, the OpenGL context is active. + if (runningFirstTime){ + // THIS is the part that creates the renderer. + // It must always be called, now that we have the pbuffer workaround. + initContextFirstTime(); + runningFirstTime = false; + } listener.initialize(); } @@ -97,7 +110,8 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext super.startGLCanvas(); } - public void display(GLAutoDrawable glad) { + @Override + public void display(GLAutoDrawable glad) { if (!created.get() && renderer != null){ listener.destroy(); logger.fine("Canvas destroyed."); @@ -129,7 +143,8 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext } - public Canvas getCanvas() { + @Override + public Canvas getCanvas() { return canvas; } diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java index 5d687af8d..497fa8edb 100644 --- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java @@ -36,17 +36,32 @@ import com.jme3.input.JoyInput; import com.jme3.input.KeyInput; import com.jme3.input.MouseInput; import com.jme3.renderer.Renderer; -import com.jme3.renderer.jogl.JoglRenderer; +import com.jme3.renderer.RendererException; +import com.jme3.renderer.jogl.JoglGL; +import com.jme3.renderer.jogl.JoglGLExt; +import com.jme3.renderer.jogl.JoglGLFbo; +import com.jme3.renderer.opengl.GL2; +import com.jme3.renderer.opengl.GL3; +import com.jme3.renderer.opengl.GL4; +import com.jme3.renderer.opengl.GLDebugDesktop; +import com.jme3.renderer.opengl.GLExt; +import com.jme3.renderer.opengl.GLFbo; +import com.jme3.renderer.opengl.GLRenderer; +import com.jme3.renderer.opengl.GLTiming; +import com.jme3.renderer.opengl.GLTimingState; +import com.jme3.renderer.opengl.GLTracer; import com.jme3.system.AppSettings; import com.jme3.system.JmeContext; import com.jme3.system.NanoTimer; import com.jme3.system.NativeLibraryLoader; import com.jme3.system.SystemListener; import com.jme3.system.Timer; + import java.nio.IntBuffer; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; + import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2GL3; import com.jogamp.opengl.GLContext; @@ -62,7 +77,7 @@ public abstract class JoglContext implements JmeContext { protected final Object createdLock = new Object(); protected AppSettings settings = new AppSettings(true); - protected JoglRenderer renderer; + protected Renderer renderer; protected Timer timer; protected SystemListener listener; @@ -77,43 +92,53 @@ public abstract class JoglContext implements JmeContext { } } - public void setSystemListener(SystemListener listener){ + @Override + public void setSystemListener(SystemListener listener){ this.listener = listener; } - public void setSettings(AppSettings settings) { + @Override + public void setSettings(AppSettings settings) { this.settings.copyFrom(settings); } - public boolean isRenderable(){ + @Override + public boolean isRenderable(){ return renderable.get(); } - public AppSettings getSettings() { + @Override + public AppSettings getSettings() { return settings; } - public Renderer getRenderer() { + @Override + public Renderer getRenderer() { return renderer; } - public MouseInput getMouseInput() { + @Override + public MouseInput getMouseInput() { return mouseInput; } - public KeyInput getKeyInput() { + @Override + public KeyInput getKeyInput() { return keyInput; } - public JoyInput getJoyInput() { + @Override + public JoyInput getJoyInput() { return joyInput; } - public Timer getTimer() { + @Override + public Timer getTimer() { return timer; } - public boolean isCreated() { + @Override + public boolean isCreated() { return created.get(); } @@ -135,13 +160,76 @@ public abstract class JoglContext implements JmeContext { } } } + + protected void initContextFirstTime(){ + if (GLContext.getCurrent().getGLVersionNumber().getMajor() < 2) { + throw new RendererException("OpenGL 2.0 or higher is " + + "required for jMonkeyEngine"); + } + + if (settings.getRenderer().startsWith("JOGL")) { + com.jme3.renderer.opengl.GL gl = new JoglGL(); + GLExt glext = new JoglGLExt(); + GLFbo glfbo = new JoglGLFbo(); + + if (settings.getBoolean("GraphicsDebug")) { + gl = new GLDebugDesktop(gl, glext, glfbo); + glext = (GLExt) gl; + glfbo = (GLFbo) gl; + } + + if (settings.getBoolean("GraphicsTiming")) { + GLTimingState timingState = new GLTimingState(); + gl = (com.jme3.renderer.opengl.GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class); + glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class); + glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class); + } + + if (settings.getBoolean("GraphicsTrace")) { + gl = (com.jme3.renderer.opengl.GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class); + glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class); + glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class); + } + + renderer = new GLRenderer(gl, glext, glfbo); + renderer.initialize(); + } else { + throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer()); + } + + if (GLContext.getCurrentGL().isExtensionAvailable("GL_ARB_debug_output") && settings.getBoolean("GraphicsDebug")) { + GLContext.getCurrent().enableGLDebugMessage(true); + GLContext.getCurrent().addGLDebugListener(new JoglGLDebugOutputHandler()); + } + + renderer.setMainFrameBufferSrgb(settings.getGammaCorrection()); + renderer.setLinearizeSrgbImages(settings.getGammaCorrection()); - public void internalCreate() { + // Init input + if (keyInput != null) { + keyInput.initialize(); + } + + if (mouseInput != null) { + mouseInput.initialize(); + } + + if (joyInput != null) { + joyInput.initialize(); + } + } + + public void internalCreate() { timer = new NanoTimer(); synchronized (createdLock){ created.set(true); createdLock.notifyAll(); } + if (renderable.get()){ + initContextFirstTime(); + } else { + assert getType() == Type.Canvas; + } } protected void internalDestroy() { diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglGLDebugOutputHandler.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglGLDebugOutputHandler.java new file mode 100644 index 000000000..5a8b58715 --- /dev/null +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglGLDebugOutputHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009-2015 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.system.jogl; + +import java.util.HashMap; + +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLDebugListener; +import com.jogamp.opengl.GLDebugMessage; + +class JoglGLDebugOutputHandler implements GLDebugListener { + + private static final HashMap constMap = new HashMap(); + private static final String MESSAGE_FORMAT = + "[JME3] OpenGL debug message\r\n" + + " ID: %d\r\n" + + " Source: %s\r\n" + + " Type: %s\r\n" + + " Severity: %s\r\n" + + " Message: %s"; + + static { + constMap.put(GL2ES2.GL_DEBUG_SOURCE_API, "API"); + constMap.put(GL2ES2.GL_DEBUG_SOURCE_APPLICATION, "APPLICATION"); + constMap.put(GL2ES2.GL_DEBUG_SOURCE_OTHER, "OTHER"); + constMap.put(GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER, "SHADER_COMPILER"); + constMap.put(GL2ES2.GL_DEBUG_SOURCE_THIRD_PARTY, "THIRD_PARTY"); + constMap.put(GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM, "WINDOW_SYSTEM"); + + constMap.put(GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, "DEPRECATED_BEHAVIOR"); + constMap.put(GL2ES2.GL_DEBUG_TYPE_ERROR, "ERROR"); + constMap.put(GL2ES2.GL_DEBUG_TYPE_OTHER, "OTHER"); + constMap.put(GL2ES2.GL_DEBUG_TYPE_PERFORMANCE, "PERFORMANCE"); + constMap.put(GL2ES2.GL_DEBUG_TYPE_PORTABILITY, "PORTABILITY"); + constMap.put(GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, "UNDEFINED_BEHAVIOR"); + + constMap.put(GL2ES2.GL_DEBUG_SEVERITY_HIGH, "HIGH"); + constMap.put(GL2ES2.GL_DEBUG_SEVERITY_MEDIUM, "MEDIUM"); + constMap.put(GL2ES2.GL_DEBUG_SEVERITY_LOW, "LOW"); + } + + @Override + public void messageSent(GLDebugMessage event) { + String sourceStr = constMap.get(event.getDbgSource()); + String typeStr = constMap.get(event.getDbgType()); + String severityStr = constMap.get(event.getDbgSeverity()); + + System.err.println(String.format(MESSAGE_FORMAT, event.getDbgId(), sourceStr, typeStr, severityStr, event.getDbgMsg())); + } + +} diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtAbstractDisplay.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtAbstractDisplay.java index cb75d5d37..9c7a49d17 100644 --- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtAbstractDisplay.java +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtAbstractDisplay.java @@ -37,21 +37,15 @@ import com.jme3.input.MouseInput; import com.jme3.input.TouchInput; import com.jme3.input.jogl.NewtKeyInput; import com.jme3.input.jogl.NewtMouseInput; -import com.jme3.renderer.jogl.JoglRenderer; +import com.jme3.system.AppSettings; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.util.FPSAnimator; + import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; -import com.jogamp.opengl.DebugGL2; -import com.jogamp.opengl.DebugGL3; -import com.jogamp.opengl.DebugGL3bc; -import com.jogamp.opengl.DebugGL4; -import com.jogamp.opengl.DebugGL4bc; -import com.jogamp.opengl.DebugGLES1; -import com.jogamp.opengl.DebugGLES2; -import com.jogamp.opengl.GL; + import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; @@ -80,10 +74,12 @@ public abstract class JoglNewtAbstractDisplay extends JoglContext implements GLE protected void initGLCanvas() { loadNatives(); - //FIXME use the settings to know whether to use the max programmable profile - //then call GLProfile.getMaxProgrammable(true); - //FIXME use the default profile only on embedded devices - GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + GLCapabilities caps; + if (settings.getRenderer().equals(AppSettings.JOGL_OPENGL_FORWARD_COMPATIBLE)) { + caps = new GLCapabilities(GLProfile.getMaxProgrammable(true)); + } else { + caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true)); + } caps.setHardwareAccelerated(true); caps.setDoubleBuffered(true); caps.setStencilBits(settings.getStencilBits()); @@ -103,50 +99,9 @@ public abstract class JoglNewtAbstractDisplay extends JoglContext implements GLE canvas.requestFocus(); canvas.setSize(settings.getWidth(), settings.getHeight()); canvas.addGLEventListener(this); - - if (settings.getBoolean("GraphicsDebug")) { - canvas.invoke(false, new GLRunnable() { - public boolean run(GLAutoDrawable glad) { - GL gl = glad.getGL(); - if (gl.isGLES()) { - if (gl.isGLES1()) { - glad.setGL(new DebugGLES1(gl.getGLES1())); - } else { - if (gl.isGLES2()) { - glad.setGL(new DebugGLES2(gl.getGLES2())); - } else { - // TODO ES3 - } - } - } else { - if (gl.isGL4bc()) { - glad.setGL(new DebugGL4bc(gl.getGL4bc())); - } else { - if (gl.isGL4()) { - glad.setGL(new DebugGL4(gl.getGL4())); - } else { - if (gl.isGL3bc()) { - glad.setGL(new DebugGL3bc(gl.getGL3bc())); - } else { - if (gl.isGL3()) { - glad.setGL(new DebugGL3(gl.getGL3())); - } else { - if (gl.isGL2()) { - glad.setGL(new DebugGL2(gl.getGL2())); - } - } - } - } - } - } - return true; - } - }); - } - - renderer = new JoglRenderer(); - renderer.setMainFrameBufferSrgb(settings.getGammaCorrection()); + //FIXME not sure it is the best place to do that + renderable.set(true); } protected void startGLCanvas() { @@ -161,9 +116,6 @@ public abstract class JoglNewtAbstractDisplay extends JoglContext implements GLE animator.start(); wasAnimating = true; - - //FIXME not sure it is the best place to do that - renderable.set(true); } protected void onCanvasAdded() { diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtCanvas.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtCanvas.java index 3ed501580..e4e81a5df 100644 --- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtCanvas.java +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtCanvas.java @@ -41,6 +41,7 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas private static final Logger logger = Logger.getLogger(JoglNewtCanvas.class.getName()); private int width, height; + private boolean runningFirstTime = true; private NewtCanvasAWT newtAwtCanvas; @@ -53,7 +54,9 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas protected final void initGLCanvas() { super.initGLCanvas(); newtAwtCanvas = new NewtCanvasAWT(canvas) { - @Override + private static final long serialVersionUID = 1L; + + @Override public void addNotify() { super.addNotify(); onCanvasAdded(); @@ -67,22 +70,27 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas }; } - public Type getType() { + @Override + public Type getType() { return Type.Canvas; } - public void setTitle(String title) { + @Override + public void setTitle(String title) { } - public void restart() { + @Override + public void restart() { } - public void create(boolean waitFor){ + @Override + public void create(boolean waitFor){ if (waitFor) waitFor(true); } - public void destroy(boolean waitFor){ + @Override + public void destroy(boolean waitFor){ if (waitFor) waitFor(false); if (animator.isAnimating()) @@ -101,13 +109,20 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas startGLCanvas(); } - public void init(GLAutoDrawable drawable) { + @Override + public void init(GLAutoDrawable drawable) { canvas.requestFocus(); super.internalCreate(); logger.fine("Display created."); - renderer.initialize(); + // At this point, the OpenGL context is active. + if (runningFirstTime){ + // THIS is the part that creates the renderer. + // It must always be called, now that we have the pbuffer workaround. + initContextFirstTime(); + runningFirstTime = false; + } listener.initialize(); } @@ -117,7 +132,8 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas super.startGLCanvas(); } - public void display(GLAutoDrawable glad) { + @Override + public void display(GLAutoDrawable glad) { if (!created.get() && renderer != null){ listener.destroy(); logger.fine("Canvas destroyed."); diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java index 84a99e8d2..56eab406a 100644 --- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java @@ -173,6 +173,8 @@ public class JoglNewtDisplay extends JoglNewtAbstractDisplay { if (waitFor){ waitFor(false); } + if (animator.isAnimating()) + animator.stop(); } public void restart() { diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglOffscreenBuffer.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglOffscreenBuffer.java index cd2b84f73..56aa2d53f 100644 --- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglOffscreenBuffer.java +++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglOffscreenBuffer.java @@ -37,16 +37,18 @@ import com.jme3.input.MouseInput; import com.jme3.input.TouchInput; import com.jme3.input.dummy.DummyKeyInput; import com.jme3.input.dummy.DummyMouseInput; -import com.jogamp.newt.NewtVersion; + import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; + import com.jogamp.opengl.GL; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLDrawableFactory; import com.jogamp.opengl.GLOffscreenAutoDrawable; import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.JoglVersion; public class JoglOffscreenBuffer extends JoglContext implements Runnable { @@ -123,7 +125,7 @@ public class JoglOffscreenBuffer extends JoglContext implements Runnable { @Override public void run(){ loadNatives(); - logger.log(Level.FINE, "Using JOGL {0}", NewtVersion.getInstance().getImplementationVersion()); + logger.log(Level.FINE, "Using JOGL {0}", JoglVersion.getInstance().getImplementationVersion()); initInThread(); while (!needClose.get()){ runLoop(); diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index bf99c84eb..2b7df131a 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -13,7 +13,7 @@ import java.nio.ShortBuffer; import com.jme3.renderer.opengl.GL4; import org.lwjgl.opengl.*; -public class LwjglGL implements GL, GL2, GL3, GL4 { +public final class LwjglGL implements GL, GL2, GL3, GL4 { private static void checkLimit(Buffer buffer) { if (buffer == null) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java index 2c6a63fd7..e3b9e6c77 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java @@ -13,7 +13,7 @@ import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GLSync; -public class LwjglGLExt implements GLExt { +public final class LwjglGLExt implements GLExt { private static void checkLimit(Buffer buffer) { if (buffer == null) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java index 159000a6c..40571f5ed 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java @@ -13,7 +13,7 @@ import org.lwjgl.opengl.EXTFramebufferObject; * * @author Kirill Vainer */ -public class LwjglGLFboEXT implements GLFbo { +public final class LwjglGLFboEXT implements GLFbo { private static void checkLimit(Buffer buffer) { if (buffer == null) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java index acc540273..14e0cc9e6 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java @@ -11,7 +11,7 @@ import org.lwjgl.opengl.GL30; * * @author Kirill Vainer */ -public class LwjglGLFboGL3 implements GLFbo { +public final class LwjglGLFboGL3 implements GLFbo { private static void checkLimit(Buffer buffer) { if (buffer == null) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java index 7cdca0a57..802b12a0f 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java @@ -40,7 +40,6 @@ import com.jme3.input.lwjgl.JInputJoyInput; import com.jme3.input.lwjgl.LwjglKeyInput; import com.jme3.input.lwjgl.LwjglMouseInput; import com.jme3.system.AppSettings; -import com.jme3.system.JmeContext.Type; import com.jme3.system.JmeSystem; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java index c88f7b734..ee12d1fea 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -52,12 +52,8 @@ import com.jme3.renderer.opengl.GLRenderer; import com.jme3.renderer.opengl.GLTiming; import com.jme3.renderer.opengl.GLTimingState; import com.jme3.renderer.opengl.GLTracer; -import com.jme3.system.AppSettings; -import com.jme3.system.JmeContext; -import com.jme3.system.JmeSystem; -import com.jme3.system.NativeLibraryLoader; -import com.jme3.system.SystemListener; -import com.jme3.system.Timer; +import com.jme3.system.*; + import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; @@ -166,8 +162,7 @@ public abstract class LwjglContext implements JmeContext { } } } - - protected void loadNatives() { + protected void loadNatives() { if (JmeSystem.isLowPermissions()) { return; } diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java index c8f329f13..d943fe6ee 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java @@ -73,6 +73,7 @@ class LwjglGLDebugOutputHandler implements ARBDebugOutputCallback.Handler { String severityStr = constMap.get(severity); System.err.println(String.format(MESSAGE_FORMAT, id, sourceStr, typeStr, severityStr, message)); + Thread.dumpStack(); } } diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java index b06db1b29..ddfb8b62b 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java @@ -123,7 +123,7 @@ public class LwjglOffscreenBuffer extends LwjglContext implements Runnable { } listener.update(); - checkGLError(); + assert checkGLError(); renderer.postFrame(); diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle new file mode 100644 index 000000000..3ee3b0f65 --- /dev/null +++ b/jme3-lwjgl3/build.gradle @@ -0,0 +1,15 @@ +if (!hasProperty('mainClass')) { + ext.mainClass = '' +} + +repositories { + maven { + url "https://oss.sonatype.org/content/repositories/snapshots" + } +} + +dependencies { + compile project(':jme3-core') + compile project(':jme3-desktop') + compile files('lib/lwjgl-3.0.0b-35.jar', 'lib/lwjgl-3.0.0b-35-natives.jar') +} diff --git a/jme3-lwjgl3/lib/lwjgl-3.0.0b-35-natives.jar b/jme3-lwjgl3/lib/lwjgl-3.0.0b-35-natives.jar new file mode 100644 index 000000000..79b12bc5d Binary files /dev/null and b/jme3-lwjgl3/lib/lwjgl-3.0.0b-35-natives.jar differ diff --git a/jme3-lwjgl3/lib/lwjgl-3.0.0b-35.jar b/jme3-lwjgl3/lib/lwjgl-3.0.0b-35.jar new file mode 100644 index 000000000..d1466e8aa Binary files /dev/null and b/jme3-lwjgl3/lib/lwjgl-3.0.0b-35.jar differ diff --git a/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java new file mode 100644 index 000000000..313bdd5ee --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */package com.jme3.audio.lwjgl; + +import com.jme3.audio.openal.AL; +import com.jme3.system.NativeLibraryLoader; +import com.jme3.system.Platform; +import org.lwjgl.openal.AL10; +import org.lwjgl.openal.AL11; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +public final class LwjglAL implements AL { + + public LwjglAL() { + } + + public String alGetString(int parameter) { + return AL10.alGetString(parameter); + } + + public int alGenSources() { + return AL10.alGenSources(); + } + + public int alGetError() { + return AL10.alGetError(); + } + + public void alDeleteSources(int numSources, IntBuffer sources) { + if (sources.position() != 0) throw new AssertionError(); + if (sources.limit() != numSources) throw new AssertionError(); + AL10.alDeleteSources(sources); + } + + public void alGenBuffers(int numBuffers, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numBuffers) throw new AssertionError(); + AL10.alGenBuffers(buffers); + } + + public void alDeleteBuffers(int numBuffers, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numBuffers) throw new AssertionError(); + AL10.alDeleteBuffers(buffers); + } + + public void alSourceStop(int source) { + AL10.alSourceStop(source); + } + + public void alSourcei(int source, int param, int value) { + AL10.alSourcei(source, param, value); + } + + public void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency) { + if (data.position() != 0) throw new AssertionError(); + if (data.limit() != size) throw new AssertionError(); + AL10.alBufferData(buffer, format, data, frequency); + } + + public void alSourcePlay(int source) { + AL10.alSourcePlay(source); + } + + public void alSourcePause(int source) { + AL10.alSourcePause(source); + } + + public void alSourcef(int source, int param, float value) { + AL10.alSourcef(source, param, value); + } + + public void alSource3f(int source, int param, float value1, float value2, float value3) { + AL10.alSource3f(source, param, value1, value2, value3); + } + + public int alGetSourcei(int source, int param) { + return AL10.alGetSourcei(source, param); + } + + public void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numBuffers) throw new AssertionError(); + AL10.alSourceUnqueueBuffers(source, buffers); + } + + public void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numBuffers) throw new AssertionError(); + AL10.alSourceQueueBuffers(source, buffers); + } + + public void alListener(int param, FloatBuffer data) { + AL10.alListenerfv(param, data); + } + + public void alListenerf(int param, float value) { + AL10.alListenerf(param, value); + } + + public void alListener3f(int param, float value1, float value2, float value3) { + AL10.alListener3f(param, value1, value2, value3); + } + + public void alSource3i(int source, int param, int value1, int value2, int value3) { + AL11.alSource3i(source, param, value1, value2, value3); + } + +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java new file mode 100644 index 000000000..b99a939b8 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.audio.lwjgl; + +import com.jme3.audio.openal.ALC; +import org.lwjgl.openal.ALC10; +import org.lwjgl.openal.ALContext; +import org.lwjgl.openal.ALDevice; + +import java.nio.IntBuffer; + +import static org.lwjgl.openal.ALC10.alcGetContextsDevice; +import static org.lwjgl.openal.ALC10.alcGetCurrentContext; + +public class LwjglALC implements ALC { + + private ALDevice device; + private ALContext context; + + public void createALC() { + device = ALDevice.create(); + context = ALContext.create(device); + } + + public void destroyALC() { + if (context != null) { + context.destroy(); + } + + if (device != null) { + device.destroy(); + } + } + + public boolean isCreated() { + return context != null; + } + + public String alcGetString(final int parameter) { + final long context = alcGetCurrentContext(); + final long device = alcGetContextsDevice(context); + return ALC10.alcGetString(device, parameter); + } + + public boolean alcIsExtensionPresent(final String extension) { + final long context = alcGetCurrentContext(); + final long device = alcGetContextsDevice(context); + return ALC10.alcIsExtensionPresent(device, extension); + } + + public void alcGetInteger(final int param, final IntBuffer buffer, final int size) { + if (buffer.position() != 0) throw new AssertionError(); + if (buffer.limit() != size) throw new AssertionError(); + + final long context = alcGetCurrentContext(); + final long device = alcGetContextsDevice(context); + final int value = ALC10.alcGetInteger(device, param); + //buffer.put(value); + } + + public void alcDevicePauseSOFT() { + } + + public void alcDeviceResumeSOFT() { + } + +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java new file mode 100644 index 000000000..ecd67211f --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.audio.lwjgl; + +import com.jme3.audio.openal.EFX; +import org.lwjgl.openal.EXTEfx; + +import java.nio.IntBuffer; + +public class LwjglEFX implements EFX { + + public void alGenAuxiliaryEffectSlots(int numSlots, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numSlots) throw new AssertionError(); + EXTEfx.alGenAuxiliaryEffectSlots(buffers); + } + + public void alGenEffects(int numEffects, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numEffects) throw new AssertionError(); + EXTEfx.alGenEffects(buffers); + } + + public void alEffecti(int effect, int param, int value) { + EXTEfx.alEffecti(effect, param, value); + } + + public void alAuxiliaryEffectSloti(int effectSlot, int param, int value) { + EXTEfx.alAuxiliaryEffectSloti(effectSlot, param, value); + } + + public void alDeleteEffects(int numEffects, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numEffects) throw new AssertionError(); + EXTEfx.alDeleteEffects(buffers); + } + + public void alDeleteAuxiliaryEffectSlots(int numEffectSlots, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numEffectSlots) throw new AssertionError(); + EXTEfx.alDeleteAuxiliaryEffectSlots(buffers); + } + + public void alGenFilters(int numFilters, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numFilters) throw new AssertionError(); + EXTEfx.alGenFilters(buffers); + } + + public void alFilteri(int filter, int param, int value) { + EXTEfx.alFilteri(filter, param, value); + } + + public void alFilterf(int filter, int param, float value) { + EXTEfx.alFilterf(filter, param, value); + } + + public void alDeleteFilters(int numFilters, IntBuffer buffers) { + if (buffers.position() != 0) throw new AssertionError(); + if (buffers.limit() != numFilters) throw new AssertionError(); + EXTEfx.alDeleteFilters(buffers); + } + + public void alEffectf(int effect, int param, float value) { + EXTEfx.alEffectf(effect, param, value); + } + +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java new file mode 100644 index 000000000..b1063d6b9 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.input.lwjgl; + +import com.jme3.input.*; +import com.jme3.input.event.JoyAxisEvent; +import com.jme3.input.event.JoyButtonEvent; +import org.lwjgl.opengl.GL11; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import static org.lwjgl.glfw.GLFW.*; + +/** + * @author Daniel Johansson (dannyjo) + * @since 3.1 + */ +public class GlfwJoystickInput implements JoyInput { + + private static final Logger LOGGER = Logger.getLogger(InputManager.class.getName()); + + private boolean initialized = false; + private RawInputListener listener; + private Map joysticks = new HashMap(); + + public void setJoyRumble(int joyId, float amount) { + if (joyId >= joysticks.size()) { + throw new IllegalArgumentException(); + } + } + + @Override + public Joystick[] loadJoysticks(final InputManager inputManager) { + for (int i = 0; i < GLFW_JOYSTICK_LAST; i++) { + if (glfwJoystickPresent(i) == GL11.GL_TRUE) { + final String name = glfwGetJoystickName(i); + final GlfwJoystick joystick = new GlfwJoystick(inputManager, this, i, name); + joysticks.put(i, joystick); + + final FloatBuffer floatBuffer = glfwGetJoystickAxes(i); + + int axisIndex = 0; + while (floatBuffer.hasRemaining()) { + floatBuffer.get(); + + final String logicalId = JoystickCompatibilityMappings.remapComponent(joystick.getName(), convertAxisIndex(axisIndex)); + final JoystickAxis joystickAxis = new DefaultJoystickAxis(inputManager, joystick, axisIndex, convertAxisIndex(axisIndex), logicalId, true, false, 0.0f); + joystick.addAxis(axisIndex, joystickAxis); + axisIndex++; + } + + final ByteBuffer byteBuffer = glfwGetJoystickButtons(i); + + int buttonIndex = 0; + while (byteBuffer.hasRemaining()) { + byteBuffer.get(); + final String logicalId = JoystickCompatibilityMappings.remapComponent(joystick.getName(), String.valueOf(buttonIndex)); + joystick.addButton(new DefaultJoystickButton(inputManager, joystick, buttonIndex, String.valueOf(buttonIndex), logicalId)); + buttonIndex++; + } + } + } + + return joysticks.values().toArray(new GlfwJoystick[joysticks.size()]); + } + + private String convertAxisIndex(final int index) { + if (index == 0) { + return "pov_x"; + } else if (index == 1) { + return "pov_y"; + } else if (index == 2) { + return "z"; + } else if (index == 3) { + return "rz"; + } + + return String.valueOf(index); + } + + public void initialize() { + initialized = true; + } + + public void update() { + for (final Map.Entry entry : joysticks.entrySet()) { + // Axes + final FloatBuffer axisValues = glfwGetJoystickAxes(entry.getKey()); + + for (final JoystickAxis axis : entry.getValue().getAxes()) { + final float value = axisValues.get(axis.getAxisId()); + listener.onJoyAxisEvent(new JoyAxisEvent(axis, value)); + } + + // Buttons + final ByteBuffer byteBuffer = glfwGetJoystickButtons(entry.getKey()); + + for (final JoystickButton button : entry.getValue().getButtons()) { + final boolean pressed = byteBuffer.get(button.getButtonId()) == GLFW_PRESS; + listener.onJoyButtonEvent(new JoyButtonEvent(button, pressed)); + } + } + } + + public void destroy() { + initialized = false; + } + + public boolean isInitialized() { + return initialized; + } + + public void setInputListener(RawInputListener listener) { + this.listener = listener; + } + + public long getInputTimeNanos() { + return 0; + } + + protected class GlfwJoystick extends AbstractJoystick { + + private JoystickAxis povAxisX; + private JoystickAxis povAxisY; + + public GlfwJoystick(InputManager inputManager, JoyInput joyInput, int joyId, String name) { + super(inputManager, joyInput, joyId, name); + } + + public void addAxis(final int index, final JoystickAxis axis) { + super.addAxis(axis); + + if (index == 0) { + povAxisX = axis; + } else if (index == 1) { + povAxisY = axis; + } + } + + @Override + protected void addButton(JoystickButton button) { + super.addButton(button); + } + + @Override + public JoystickAxis getXAxis() { + return povAxisX; + } + + @Override + public JoystickAxis getYAxis() { + return povAxisY; + } + + @Override + public JoystickAxis getPovXAxis() { + return povAxisX; + } + + @Override + public JoystickAxis getPovYAxis() { + return povAxisY; + } + + @Override + public int getXAxisIndex() { + return povAxisX.getAxisId(); + } + + @Override + public int getYAxisIndex() { + return povAxisY.getAxisId(); + } + } +} + + + diff --git a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java new file mode 100644 index 000000000..20cd07672 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.input.lwjgl; + +import com.jme3.input.KeyInput; +import com.jme3.input.RawInputListener; +import com.jme3.input.event.KeyInputEvent; +import com.jme3.system.lwjgl.LwjglWindow; +import org.lwjgl.glfw.GLFWKeyCallback; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.logging.Logger; + +import static org.lwjgl.glfw.GLFW.*; + +public class GlfwKeyInput implements KeyInput { + + private static final Logger logger = Logger.getLogger(GlfwKeyInput.class.getName()); + + private LwjglWindow context; + private RawInputListener listener; + private boolean initialized; + private GLFWKeyCallback keyCallback; + private Queue keyInputEvents = new LinkedList(); + + public GlfwKeyInput(LwjglWindow context) { + this.context = context; + } + + public void initialize() { + if (!context.isRenderable()) { + return; + } + + glfwSetKeyCallback(context.getWindowHandle(), keyCallback = new GLFWKeyCallback() { + @Override + public void invoke(long window, int key, int scancode, int action, int mods) { + final KeyInputEvent evt = new KeyInputEvent(scancode, (char) key, GLFW_PRESS == action, GLFW_REPEAT == action); + evt.setTime(getInputTimeNanos()); + keyInputEvents.add(evt); + } + }); + + glfwSetInputMode(context.getWindowHandle(), GLFW_STICKY_KEYS, 1); + + initialized = true; + logger.fine("Keyboard created."); + } + + public int getKeyCount() { + // This might not be correct + return GLFW_KEY_LAST - GLFW_KEY_SPACE; + } + + public void update() { + if (!context.isRenderable()) { + return; + } + + while (!keyInputEvents.isEmpty()) { + listener.onKeyEvent(keyInputEvents.poll()); + } + } + + public void destroy() { + if (!context.isRenderable()) { + return; + } + + keyCallback.release(); + logger.fine("Keyboard destroyed."); + } + + public boolean isInitialized() { + return initialized; + } + + public void setInputListener(RawInputListener listener) { + this.listener = listener; + } + + public long getInputTimeNanos() { + return (long) (glfwGetTime() * 1000000000); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java new file mode 100644 index 000000000..05a2df5db --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.input.lwjgl; + +import com.jme3.cursors.plugins.JmeCursor; +import com.jme3.input.MouseInput; +import com.jme3.input.RawInputListener; +import com.jme3.input.event.MouseButtonEvent; +import com.jme3.input.event.MouseMotionEvent; +import com.jme3.system.lwjgl.LwjglWindow; +import org.lwjgl.glfw.GLFWCursorPosCallback; +import org.lwjgl.glfw.GLFWMouseButtonCallback; +import org.lwjgl.glfw.GLFWScrollCallback; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.Queue; +import java.util.logging.Logger; + +import static org.lwjgl.glfw.GLFW.*; + +/** + * Captures mouse input using GLFW callbacks. It then temporarily stores these in event queues which are processed in the + * {@link #update()} method. Due to some of the GLFW button id's there is a conversion method in this class which will + * convert the GLFW left, middle and right mouse button to JME3 left, middle and right button codes. + * + * @author Daniel Johansson (dannyjo) + * @since 3.1 + */ +public class GlfwMouseInput implements MouseInput { + + private static final Logger logger = Logger.getLogger(GlfwMouseInput.class.getName()); + + private LwjglWindow context; + private RawInputListener listener; + private boolean cursorVisible = true; + private int mouseX; + private int mouseY; + private int mouseWheel; + private boolean initialized; + private GLFWCursorPosCallback cursorPosCallback; + private GLFWScrollCallback scrollCallback; + private GLFWMouseButtonCallback mouseButtonCallback; + private Queue mouseMotionEvents = new LinkedList(); + private Queue mouseButtonEvents = new LinkedList(); + + public GlfwMouseInput(final LwjglWindow context) { + this.context = context; + } + + public void initialize() { + glfwSetCursorPosCallback(context.getWindowHandle(), cursorPosCallback = new GLFWCursorPosCallback() { + @Override + public void invoke(long window, double xpos, double ypos) { + int xDelta; + int yDelta; + int x = (int) Math.round(xpos); + int y = context.getSettings().getHeight() - (int) Math.round(ypos); + + if (mouseX == 0) { + mouseX = x; + } + + if (mouseY == 0) { + mouseY = y; + } + + xDelta = x - mouseX; + yDelta = y - mouseY; + mouseX = x; + mouseY = y; + + if (xDelta != 0 || yDelta != 0) { + final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(x, y, xDelta, yDelta, mouseWheel, 0); + mouseMotionEvent.setTime(getInputTimeNanos()); + mouseMotionEvents.add(mouseMotionEvent); + } + } + }); + + glfwSetScrollCallback(context.getWindowHandle(), scrollCallback = new GLFWScrollCallback() { + @Override + public void invoke(final long window, final double xOffset, final double yOffset) { + mouseWheel += yOffset; + + final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(mouseX, mouseY, 0, 0, mouseWheel, (int) Math.round(yOffset)); + mouseMotionEvent.setTime(getInputTimeNanos()); + mouseMotionEvents.add(mouseMotionEvent); + } + }); + + glfwSetMouseButtonCallback(context.getWindowHandle(), mouseButtonCallback = new GLFWMouseButtonCallback() { + @Override + public void invoke(final long window, final int button, final int action, final int mods) { + final MouseButtonEvent mouseButtonEvent = new MouseButtonEvent(convertButton(button), action == GLFW_PRESS, mouseX, mouseY); + mouseButtonEvent.setTime(getInputTimeNanos()); + mouseButtonEvents.add(mouseButtonEvent); + } + }); + + setCursorVisible(cursorVisible); + logger.fine("Mouse created."); + initialized = true; + } + + public boolean isInitialized() { + return initialized; + } + + public int getButtonCount() { + return GLFW_MOUSE_BUTTON_LAST + 1; + } + + public void update() { + while (!mouseMotionEvents.isEmpty()) { + listener.onMouseMotionEvent(mouseMotionEvents.poll()); + } + + while (!mouseButtonEvents.isEmpty()) { + listener.onMouseButtonEvent(mouseButtonEvents.poll()); + } + } + + public void destroy() { + if (!context.isRenderable()) { + return; + } + + cursorPosCallback.release(); + scrollCallback.release(); + mouseButtonCallback.release(); + + logger.fine("Mouse destroyed."); + } + + public void setCursorVisible(boolean visible) { + cursorVisible = visible; + + if (!context.isRenderable()) { + return; + } + + if (cursorVisible) { + glfwSetInputMode(context.getWindowHandle(), GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } else { + glfwSetInputMode(context.getWindowHandle(), GLFW_CURSOR, GLFW_CURSOR_DISABLED); + } + } + + public void setInputListener(RawInputListener listener) { + this.listener = listener; + } + + public long getInputTimeNanos() { + return (long) (glfwGetTime() * 1000000000); + } + + public void setNativeCursor(final JmeCursor jmeCursor) { + if (jmeCursor != null) { + final ByteBuffer byteBuffer = org.lwjgl.BufferUtils.createByteBuffer(jmeCursor.getImagesData().capacity()); + byteBuffer.asIntBuffer().put(jmeCursor.getImagesData().array()); + final long cursor = glfwCreateCursor(byteBuffer, jmeCursor.getXHotSpot(), jmeCursor.getYHotSpot()); + glfwSetCursor(context.getWindowHandle(), cursor); + } + } + + /** + * Simply converts the GLFW button code to a JME button code. If there is no match it just returns the GLFW button + * code. Bare in mind GLFW supports 8 different mouse buttons. + * + * @param glfwButton the raw GLFW button index. + * @return the mapped {@link MouseInput} button id. + */ + private int convertButton(final int glfwButton) { + if (glfwButton == GLFW_MOUSE_BUTTON_LEFT) { + return MouseInput.BUTTON_LEFT; + } else if(glfwButton == GLFW_MOUSE_BUTTON_MIDDLE) { + return MouseInput.BUTTON_MIDDLE; + } else if(glfwButton == GLFW_MOUSE_BUTTON_RIGHT) { + return MouseInput.BUTTON_RIGHT; + } + + return glfwButton; + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java new file mode 100644 index 000000000..187b232f2 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.renderer.lwjgl; + +import com.jme3.renderer.RendererException; +import com.jme3.renderer.opengl.GL; +import com.jme3.renderer.opengl.GL2; +import com.jme3.renderer.opengl.GL3; +import com.jme3.renderer.opengl.GL4; +import com.jme3.system.NativeLibraryLoader; +import com.jme3.system.Platform; +import org.lwjgl.opengl.*; + +import java.nio.*; + +public class LwjglGL implements GL, GL2, GL3, GL4 { + + private static void checkLimit(Buffer buffer) { + if (buffer == null) { + return; + } + if (buffer.limit() == 0) { + throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error"); + } + if (buffer.remaining() == 0) { + throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); + } + } + + public void resetStats() { + } + + public void glActiveTexture(int param1) { + GL13.glActiveTexture(param1); + } + + public void glAlphaFunc(int param1, float param2) { + GL11.glAlphaFunc(param1, param2); + } + + public void glAttachShader(int param1, int param2) { + GL20.glAttachShader(param1, param2); + } + + public void glBindBuffer(int param1, int param2) { + GL15.glBindBuffer(param1, param2); + } + + public void glBindTexture(int param1, int param2) { + GL11.glBindTexture(param1, param2); + } + + public void glBlendFunc(int param1, int param2) { + GL11.glBlendFunc(param1, param2); + } + + public void glBufferData(int param1, long param2, int param3) { + GL15.glBufferData(param1, param2, param3); + } + + public void glBufferData(int param1, FloatBuffer param2, int param3) { + checkLimit(param2); + GL15.glBufferData(param1, param2, param3); + } + + public void glBufferData(int param1, ShortBuffer param2, int param3) { + checkLimit(param2); + GL15.glBufferData(param1, param2, param3); + } + + public void glBufferData(int param1, ByteBuffer param2, int param3) { + checkLimit(param2); + GL15.glBufferData(param1, param2, param3); + } + + public void glBufferSubData(int param1, long param2, FloatBuffer param3) { + checkLimit(param3); + GL15.glBufferSubData(param1, param2, param3); + } + + public void glBufferSubData(int param1, long param2, ShortBuffer param3) { + checkLimit(param3); + GL15.glBufferSubData(param1, param2, param3); + } + + public void glBufferSubData(int param1, long param2, ByteBuffer param3) { + checkLimit(param3); + GL15.glBufferSubData(param1, param2, param3); + } + + public void glClear(int param1) { + GL11.glClear(param1); + } + + public void glClearColor(float param1, float param2, float param3, float param4) { + GL11.glClearColor(param1, param2, param3, param4); + } + + public void glColorMask(boolean param1, boolean param2, boolean param3, boolean param4) { + GL11.glColorMask(param1, param2, param3, param4); + } + + public void glCompileShader(int param1) { + GL20.glCompileShader(param1); + } + + public void glCompressedTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) { + checkLimit(param7); + GL13.glCompressedTexImage2D(param1, param2, param3, param4, param5, param6, param7); + } + + public void glCompressedTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) { + checkLimit(param8); + GL13.glCompressedTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8); + } + + public void glCompressedTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) { + checkLimit(param8); + GL13.glCompressedTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8); + } + + public void glCompressedTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) { + checkLimit(param10); + GL13.glCompressedTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); + } + + public int glCreateProgram() { + return GL20.glCreateProgram(); + } + + public int glCreateShader(int param1) { + return GL20.glCreateShader(param1); + } + + public void glCullFace(int param1) { + GL11.glCullFace(param1); + } + + public void glDeleteBuffers(IntBuffer param1) { + checkLimit(param1); + GL15.glDeleteBuffers(param1); + } + + public void glDeleteProgram(int param1) { + GL20.glDeleteProgram(param1); + } + + public void glDeleteShader(int param1) { + GL20.glDeleteShader(param1); + } + + public void glDeleteTextures(IntBuffer param1) { + checkLimit(param1); + GL11.glDeleteTextures(param1); + } + + public void glDepthFunc(int param1) { + GL11.glDepthFunc(param1); + } + + public void glDepthMask(boolean param1) { + GL11.glDepthMask(param1); + } + + public void glDepthRange(double param1, double param2) { + GL11.glDepthRange(param1, param2); + } + + public void glDetachShader(int param1, int param2) { + GL20.glDetachShader(param1, param2); + } + + public void glDisable(int param1) { + GL11.glDisable(param1); + } + + public void glDisableVertexAttribArray(int param1) { + GL20.glDisableVertexAttribArray(param1); + } + + public void glDrawArrays(int param1, int param2, int param3) { + GL11.glDrawArrays(param1, param2, param3); + } + + public void glDrawBuffer(int param1) { + GL11.glDrawBuffer(param1); + } + + public void glDrawRangeElements(int param1, int param2, int param3, int param4, int param5, long param6) { + GL12.glDrawRangeElements(param1, param2, param3, param4, param5, param6); + } + + public void glEnable(int param1) { + GL11.glEnable(param1); + } + + public void glEnableVertexAttribArray(int param1) { + GL20.glEnableVertexAttribArray(param1); + } + + public void glGenBuffers(IntBuffer param1) { + checkLimit(param1); + GL15.glGenBuffers(param1); + } + + public void glGenTextures(IntBuffer param1) { + checkLimit(param1); + GL11.glGenTextures(param1); + } + + public void glGetBoolean(int param1, ByteBuffer param2) { + checkLimit(param2); + GL11.glGetBooleanv(param1, param2); + } + + public void glGetBufferSubData(int target, long offset, ByteBuffer data) { + checkLimit(data); + GL15.glGetBufferSubData(target, offset, data); + } + + public int glGetError() { + return GL11.glGetError(); + } + + public void glGetInteger(int param1, IntBuffer param2) { + checkLimit(param2); + GL11.glGetIntegerv(param1, param2); + } + + public void glGetProgram(int param1, int param2, IntBuffer param3) { + checkLimit(param3); + GL20.glGetProgramiv(param1, param2, param3); + } + + public void glGetShader(int param1, int param2, IntBuffer param3) { + checkLimit(param3); + GL20.glGetShaderiv(param1, param2, param3); + } + + public String glGetString(int param1) { + return GL11.glGetString(param1); + } + + public String glGetString(int param1, int param2) { + return GL30.glGetStringi(param1, param2); + } + + public boolean glIsEnabled(int param1) { + return GL11.glIsEnabled(param1); + } + + public void glLineWidth(float param1) { + GL11.glLineWidth(param1); + } + + public void glLinkProgram(int param1) { + GL20.glLinkProgram(param1); + } + + public void glPixelStorei(int param1, int param2) { + GL11.glPixelStorei(param1, param2); + } + + public void glPointSize(float param1) { + GL11.glPointSize(param1); + } + + public void glPolygonMode(int param1, int param2) { + GL11.glPolygonMode(param1, param2); + } + + public void glPolygonOffset(float param1, float param2) { + GL11.glPolygonOffset(param1, param2); + } + + public void glReadBuffer(int param1) { + GL11.glReadBuffer(param1); + } + + public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) { + checkLimit(param7); + GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7); + } + + public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, long param7) { + GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7); + } + + public void glScissor(int param1, int param2, int param3, int param4) { + GL11.glScissor(param1, param2, param3, param4); + } + + public void glStencilFuncSeparate(int param1, int param2, int param3, int param4) { + GL20.glStencilFuncSeparate(param1, param2, param3, param4); + } + + public void glStencilOpSeparate(int param1, int param2, int param3, int param4) { + GL20.glStencilOpSeparate(param1, param2, param3, param4); + } + + public void glTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) { + checkLimit(param9); + GL11.glTexImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9); + } + + public void glTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) { + checkLimit(param10); + GL12.glTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); + } + + public void glTexParameterf(int param1, int param2, float param3) { + GL11.glTexParameterf(param1, param2, param3); + } + + public void glTexParameteri(int param1, int param2, int param3) { + GL11.glTexParameteri(param1, param2, param3); + } + + public void glTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) { + checkLimit(param9); + GL11.glTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9); + } + + public void glTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10, ByteBuffer param11) { + checkLimit(param11); + GL12.glTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); + } + + public void glUniform1(int param1, FloatBuffer param2) { + checkLimit(param2); + GL20.glUniform1fv(param1, param2); + } + + public void glUniform1(int param1, IntBuffer param2) { + checkLimit(param2); + GL20.glUniform1iv(param1, param2); + } + + public void glUniform1f(int param1, float param2) { + GL20.glUniform1f(param1, param2); + } + + public void glUniform1i(int param1, int param2) { + GL20.glUniform1i(param1, param2); + } + + public void glUniform2(int param1, IntBuffer param2) { + checkLimit(param2); + GL20.glUniform2iv(param1, param2); + } + + public void glUniform2(int param1, FloatBuffer param2) { + checkLimit(param2); + GL20.glUniform2fv(param1, param2); + } + + public void glUniform2f(int param1, float param2, float param3) { + GL20.glUniform2f(param1, param2, param3); + } + + public void glUniform3(int param1, IntBuffer param2) { + checkLimit(param2); + GL20.glUniform3iv(param1, param2); + } + + public void glUniform3(int param1, FloatBuffer param2) { + checkLimit(param2); + GL20.glUniform3fv(param1, param2); + } + + public void glUniform3f(int param1, float param2, float param3, float param4) { + GL20.glUniform3f(param1, param2, param3, param4); + } + + public void glUniform4(int param1, FloatBuffer param2) { + checkLimit(param2); + GL20.glUniform4fv(param1, param2); + } + + public void glUniform4(int param1, IntBuffer param2) { + checkLimit(param2); + GL20.glUniform4iv(param1, param2); + } + + public void glUniform4f(int param1, float param2, float param3, float param4, float param5) { + GL20.glUniform4f(param1, param2, param3, param4, param5); + } + + public void glUniformMatrix3(int param1, boolean param2, FloatBuffer param3) { + checkLimit(param3); + GL20.glUniformMatrix3fv(param1, param2, param3); + } + + public void glUniformMatrix4(int param1, boolean param2, FloatBuffer param3) { + checkLimit(param3); + GL20.glUniformMatrix4fv(param1, param2, param3); + } + + public void glUseProgram(int param1) { + GL20.glUseProgram(param1); + } + + public void glVertexAttribPointer(int param1, int param2, int param3, boolean param4, int param5, long param6) { + GL20.glVertexAttribPointer(param1, param2, param3, param4, param5, param6); + } + + public void glViewport(int param1, int param2, int param3, int param4) { + GL11.glViewport(param1, param2, param3, param4); + } + + public int glGetAttribLocation(int param1, String param2) { + // NOTE: LWJGL requires null-terminated strings + return GL20.glGetAttribLocation(param1, param2 + "\0"); + } + + public int glGetUniformLocation(int param1, String param2) { + // NOTE: LWJGL requires null-terminated strings + return GL20.glGetUniformLocation(param1, param2 + "\0"); + } + + public void glShaderSource(int param1, String[] param2, IntBuffer param3) { + checkLimit(param3); + GL20.glShaderSource(param1, param2); + } + + public String glGetProgramInfoLog(int program, int maxSize) { + return GL20.glGetProgramInfoLog(program, maxSize); + } + + public String glGetShaderInfoLog(int shader, int maxSize) { + return GL20.glGetShaderInfoLog(shader, maxSize); + } + + @Override + public void glBindFragDataLocation(int param1, int param2, String param3) { + GL30.glBindFragDataLocation(param1, param2, param3); + } + + @Override + public void glBindVertexArray(int param1) { + GL30.glBindVertexArray(param1); + } + + @Override + public void glGenVertexArrays(IntBuffer param1) { + checkLimit(param1); + GL30.glGenVertexArrays(param1); + } + + @Override + public void glPatchParameter(int count) { + GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count); + } + + @Override + public void glDeleteVertexArrays(IntBuffer arrays) { + checkLimit(arrays); + ARBVertexArrayObject.glDeleteVertexArrays(arrays); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java new file mode 100644 index 000000000..2ed2ec215 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.renderer.lwjgl; + +import com.jme3.renderer.RendererException; +import com.jme3.renderer.opengl.GLExt; +import org.lwjgl.opengl.*; + +import java.nio.Buffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +public class LwjglGLExt implements GLExt { + + private static void checkLimit(Buffer buffer) { + if (buffer == null) { + return; + } + if (buffer.limit() == 0) { + throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error"); + } + if (buffer.remaining() == 0) { + throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); + } + } + + @Override + public void glBufferData(int target, IntBuffer data, int usage) { + checkLimit(data); + GL15.glBufferData(target, data, usage); + } + + @Override + public void glBufferSubData(int target, long offset, IntBuffer data) { + checkLimit(data); + GL15.glBufferSubData(target, offset, data); + } + + @Override + public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) { + ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount); + } + + @Override + public void glDrawBuffers(IntBuffer bufs) { + checkLimit(bufs); + GL20.glDrawBuffers(bufs); + } + + @Override + public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) { + ARBDrawInstanced.glDrawElementsInstancedARB(mode, indices_count, type, indices_buffer_offset, primcount); + } + + @Override + public void glGetMultisample(int pname, int index, FloatBuffer val) { + checkLimit(val); + ARBTextureMultisample.glGetMultisamplefv(pname, index, val); + } + + @Override + public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) { + ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); + } + + @Override + public void glVertexAttribDivisorARB(int index, int divisor) { + ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor); + } + + @Override + public Object glFenceSync(int condition, int flags) { + return ARBSync.glFenceSync(condition, flags); + } + + @Override + public int glClientWaitSync(final Object sync, final int flags, final long timeout) { + return ARBSync.glClientWaitSync((Long) sync, flags, timeout); + } + + @Override + public void glDeleteSync(final Object sync) { + ARBSync.glDeleteSync((Long) sync); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java new file mode 100644 index 000000000..5d9fe8dc1 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.renderer.lwjgl; + +import com.jme3.renderer.RendererException; +import com.jme3.renderer.opengl.GLFbo; +import org.lwjgl.opengl.EXTFramebufferBlit; +import org.lwjgl.opengl.EXTFramebufferMultisample; +import org.lwjgl.opengl.EXTFramebufferObject; + +import java.nio.Buffer; +import java.nio.IntBuffer; + +/** + * Implements GLFbo via GL_EXT_framebuffer_object. + * + * @author Kirill Vainer + */ +public class LwjglGLFboEXT implements GLFbo { + + private static void checkLimit(Buffer buffer) { + if (buffer == null) { + return; + } + if (buffer.limit() == 0) { + throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error"); + } + if (buffer.remaining() == 0) { + throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); + } + } + + @Override + public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { + EXTFramebufferBlit.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + } + + @Override + public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { + EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); + } + + @Override + public void glBindFramebufferEXT(int param1, int param2) { + EXTFramebufferObject.glBindFramebufferEXT(param1, param2); + } + + @Override + public void glBindRenderbufferEXT(int param1, int param2) { + EXTFramebufferObject.glBindRenderbufferEXT(param1, param2); + } + + @Override + public int glCheckFramebufferStatusEXT(int param1) { + return EXTFramebufferObject.glCheckFramebufferStatusEXT(param1); + } + + @Override + public void glDeleteFramebuffersEXT(IntBuffer param1) { + checkLimit(param1); + EXTFramebufferObject.glDeleteFramebuffersEXT(param1); + } + + @Override + public void glDeleteRenderbuffersEXT(IntBuffer param1) { + checkLimit(param1); + EXTFramebufferObject.glDeleteRenderbuffersEXT(param1); + } + + @Override + public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) { + EXTFramebufferObject.glFramebufferRenderbufferEXT(param1, param2, param3, param4); + } + + @Override + public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) { + EXTFramebufferObject.glFramebufferTexture2DEXT(param1, param2, param3, param4, param5); + } + + @Override + public void glGenFramebuffersEXT(IntBuffer param1) { + checkLimit(param1); + EXTFramebufferObject.glGenFramebuffersEXT(param1); + } + + @Override + public void glGenRenderbuffersEXT(IntBuffer param1) { + checkLimit(param1); + EXTFramebufferObject.glGenRenderbuffersEXT(param1); + } + + @Override + public void glGenerateMipmapEXT(int param1) { + EXTFramebufferObject.glGenerateMipmapEXT(param1); + } + + @Override + public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) { + EXTFramebufferObject.glRenderbufferStorageEXT(param1, param2, param3, param4); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java new file mode 100644 index 000000000..5a7a9825e --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.renderer.lwjgl; + +import com.jme3.renderer.RendererException; +import com.jme3.renderer.opengl.GLFbo; +import org.lwjgl.opengl.GL30; + +import java.nio.Buffer; +import java.nio.IntBuffer; + +/** + * Implements GLFbo via OpenGL3+. + * + * @author Kirill Vainer + */ +public class LwjglGLFboGL3 implements GLFbo { + + private static void checkLimit(Buffer buffer) { + if (buffer == null) { + return; + } + if (buffer.limit() == 0) { + throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error"); + } + if (buffer.remaining() == 0) { + throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error"); + } + } + + @Override + public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { + GL30.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + } + + @Override + public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { + GL30.glRenderbufferStorageMultisample(target, samples, internalformat, width, height); + } + + @Override + public void glBindFramebufferEXT(int param1, int param2) { + GL30.glBindFramebuffer(param1, param2); + } + + @Override + public void glBindRenderbufferEXT(int param1, int param2) { + GL30.glBindRenderbuffer(param1, param2); + } + + @Override + public int glCheckFramebufferStatusEXT(int param1) { + return GL30.glCheckFramebufferStatus(param1); + } + + @Override + public void glDeleteFramebuffersEXT(IntBuffer param1) { + checkLimit(param1); + GL30.glDeleteFramebuffers(param1); + } + + @Override + public void glDeleteRenderbuffersEXT(IntBuffer param1) { + checkLimit(param1); + GL30.glDeleteRenderbuffers(param1); + } + + @Override + public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) { + GL30.glFramebufferRenderbuffer(param1, param2, param3, param4); + } + + @Override + public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) { + GL30.glFramebufferTexture2D(param1, param2, param3, param4, param5); + } + + @Override + public void glGenFramebuffersEXT(IntBuffer param1) { + checkLimit(param1); + GL30.glGenFramebuffers(param1); + } + + @Override + public void glGenRenderbuffersEXT(IntBuffer param1) { + checkLimit(param1); + GL30.glGenRenderbuffers(param1); + } + + @Override + public void glGenerateMipmapEXT(int param1) { + GL30.glGenerateMipmap(param1); + } + + @Override + public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) { + GL30.glRenderbufferStorage(param1, param2, param3, param4); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java new file mode 100644 index 000000000..61ea20b71 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.system.lwjgl; + +import com.jme3.input.lwjgl.GlfwJoystickInput; +import com.jme3.input.lwjgl.GlfwKeyInput; +import com.jme3.input.lwjgl.GlfwMouseInput; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.RendererException; +import com.jme3.renderer.lwjgl.LwjglGL; +import com.jme3.renderer.lwjgl.LwjglGLExt; +import com.jme3.renderer.lwjgl.LwjglGLFboEXT; +import com.jme3.renderer.lwjgl.LwjglGLFboGL3; +import com.jme3.renderer.opengl.*; +import com.jme3.system.*; +import org.lwjgl.Sys; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.ARBDebugOutput; +import org.lwjgl.opengl.ARBFramebufferObject; +import org.lwjgl.opengl.EXTFramebufferMultisample; +import org.lwjgl.opengl.GLCapabilities; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.lwjgl.opengl.GL.createCapabilities; +import static org.lwjgl.opengl.GL11.GL_TRUE; +import static org.lwjgl.opengl.GL11.glGetInteger; + +/** + * A LWJGL implementation of a graphics context. + */ +public abstract class LwjglContext implements JmeContext { + + private static final Logger logger = Logger.getLogger(LwjglContext.class.getName()); + + protected static final String THREAD_NAME = "jME3 Main"; + + protected AtomicBoolean created = new AtomicBoolean(false); + protected AtomicBoolean renderable = new AtomicBoolean(false); + protected final Object createdLock = new Object(); + + protected AppSettings settings = new AppSettings(true); + protected Renderer renderer; + protected GlfwKeyInput keyInput; + protected GlfwMouseInput mouseInput; + protected GlfwJoystickInput joyInput; + protected Timer timer; + protected SystemListener listener; + + public void setSystemListener(SystemListener listener) { + this.listener = listener; + } + + protected void printContextInitInfo() { + logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n" + + " * Graphics Adapter: GLFW {2}", + new Object[]{Sys.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()}); + } + + protected int determineMaxSamples() { + // If we already have a valid context, determine samples using current context. + if (GLFW.glfwExtensionSupported("GL_ARB_framebuffer_object") == GL_TRUE) { + return glGetInteger(ARBFramebufferObject.GL_MAX_SAMPLES); + } else if (GLFW.glfwExtensionSupported("GL_EXT_framebuffer_multisample") == GL_TRUE) { + return glGetInteger(EXTFramebufferMultisample.GL_MAX_SAMPLES_EXT); + } + + return Integer.MAX_VALUE; + } + + protected void loadNatives() { + if (JmeSystem.isLowPermissions()) { + return; + } + + if ("LWJGL".equals(settings.getAudioRenderer())) { + NativeLibraryLoader.loadNativeLibrary("openal-lwjgl3", true); + } + + if (NativeLibraryLoader.isUsingNativeBullet()) { + NativeLibraryLoader.loadNativeLibrary("bulletjme", true); + } + + NativeLibraryLoader.loadNativeLibrary("glfw-lwjgl3", true); + NativeLibraryLoader.loadNativeLibrary("jemalloc-lwjgl3", true); + NativeLibraryLoader.loadNativeLibrary("lwjgl3", true); + } + + protected int getNumSamplesToUse() { + int samples = 0; + if (settings.getSamples() > 1) { + samples = settings.getSamples(); + final int supportedSamples = determineMaxSamples(); + if (supportedSamples < samples) { + logger.log(Level.WARNING, + "Couldn't satisfy antialiasing samples requirement: x{0}. " + + "Video hardware only supports: x{1}", + new Object[]{samples, supportedSamples}); + + samples = supportedSamples; + } + } + return samples; + } + + protected void initContextFirstTime() { + final GLCapabilities capabilities = createCapabilities(settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)); + + if (!capabilities.OpenGL20) { + throw new RendererException("OpenGL 2.0 or higher is required for jMonkeyEngine"); + } + + if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2) + || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) { + GL gl = new LwjglGL(); + GLExt glext = new LwjglGLExt(); + GLFbo glfbo; + + if (capabilities.OpenGL30) { + glfbo = new LwjglGLFboGL3(); + } else { + glfbo = new LwjglGLFboEXT(); + } + + if (settings.getBoolean("GraphicsDebug")) { + gl = new GLDebugDesktop(gl, glext, glfbo); + glext = (GLExt) gl; + glfbo = (GLFbo) gl; + } + + if (settings.getBoolean("GraphicsTiming")) { + GLTimingState timingState = new GLTimingState(); + gl = (GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class); + glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class); + glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class); + } + + if (settings.getBoolean("GraphicsTrace")) { + gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class); + glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class); + glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class); + } + + renderer = new GLRenderer(gl, glext, glfbo); + renderer.initialize(); + } else { + throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer()); + } + + if (capabilities.GL_ARB_debug_output && settings.getBoolean("GraphicsDebug")) { + ARBDebugOutput.glDebugMessageCallbackARB(new LwjglGLDebugOutputHandler(), 0); // User param is zero. Not sure what we could use that for. + } + + renderer.setMainFrameBufferSrgb(settings.getGammaCorrection()); + renderer.setLinearizeSrgbImages(settings.getGammaCorrection()); + + // Init input + if (keyInput != null) { + keyInput.initialize(); + } + + if (mouseInput != null) { + mouseInput.initialize(); + } + + if (joyInput != null) { + joyInput.initialize(); + } + + renderable.set(true); + } + + public void internalDestroy() { + renderer = null; + timer = null; + renderable.set(false); + synchronized (createdLock) { + created.set(false); + createdLock.notifyAll(); + } + } + + public void internalCreate() { + synchronized (createdLock) { + created.set(true); + createdLock.notifyAll(); + } + + initContextFirstTime(); + } + + public void create() { + create(false); + } + + public void destroy() { + destroy(false); + } + + protected void waitFor(boolean createdVal) { + synchronized (createdLock) { + while (created.get() != createdVal) { + try { + createdLock.wait(); + } catch (InterruptedException ignored) { + } + } + } + } + + public boolean isCreated() { + return created.get(); + } + + public boolean isRenderable() { + return renderable.get(); + } + + public void setSettings(AppSettings settings) { + this.settings.copyFrom(settings); + } + + public AppSettings getSettings() { + return settings; + } + + public Renderer getRenderer() { + return renderer; + } + + public Timer getTimer() { + return timer; + } + +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java new file mode 100644 index 000000000..3eb749adc --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjgl; + +/** + * @author Daniel Johansson + */ +public class LwjglDisplay extends LwjglWindow { + + public LwjglDisplay() { + super(Type.Display); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java new file mode 100644 index 000000000..aa9c46511 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009-2015 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.system.lwjgl; + +import org.lwjgl.opengl.ARBDebugOutput; +import org.lwjgl.opengl.GLDebugMessageARBCallback; + +import java.util.HashMap; + +class LwjglGLDebugOutputHandler extends GLDebugMessageARBCallback { + + private static final HashMap constMap = new HashMap(); + private static final String MESSAGE_FORMAT = + "[JME3] OpenGL debug message\r\n" + + " ID: %d\r\n" + + " Source: %s\r\n" + + " Type: %s\r\n" + + " Severity: %s\r\n" + + " Message: %s"; + + static { + constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_API_ARB, "API"); + constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_APPLICATION_ARB, "APPLICATION"); + constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_OTHER_ARB, "OTHER"); + constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB, "SHADER_COMPILER"); + constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_THIRD_PARTY_ARB, "THIRD_PARTY"); + constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, "WINDOW_SYSTEM"); + + constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, "DEPRECATED_BEHAVIOR"); + constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_ERROR_ARB, "ERROR"); + constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_OTHER_ARB, "OTHER"); + constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_PERFORMANCE_ARB, "PERFORMANCE"); + constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_PORTABILITY_ARB, "PORTABILITY"); + constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB, "UNDEFINED_BEHAVIOR"); + + constMap.put(ARBDebugOutput.GL_DEBUG_SEVERITY_HIGH_ARB, "HIGH"); + constMap.put(ARBDebugOutput.GL_DEBUG_SEVERITY_MEDIUM_ARB, "MEDIUM"); + constMap.put(ARBDebugOutput.GL_DEBUG_SEVERITY_LOW_ARB, "LOW"); + } + + @Override + public void invoke(int source, int type, int id, int severity, int length, long message, long userParam) { + String sourceStr = constMap.get(source); + String typeStr = constMap.get(type); + String severityStr = constMap.get(severity); + + System.err.println(String.format(MESSAGE_FORMAT, id, sourceStr, typeStr, severityStr, message)); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java new file mode 100644 index 000000000..8fdde51af --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjgl; + +import com.jme3.system.JmeContext; + +/** + * @author Daniel Johansson + */ +public class LwjglOffscreenBuffer extends LwjglWindow { + + public LwjglOffscreenBuffer() { + super(JmeContext.Type.OffscreenSurface); + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java new file mode 100644 index 000000000..e1f4dcf73 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.system.lwjgl; + +import com.jme3.input.JoyInput; +import com.jme3.input.KeyInput; +import com.jme3.input.MouseInput; +import com.jme3.input.TouchInput; +import com.jme3.input.lwjgl.GlfwJoystickInput; +import com.jme3.input.lwjgl.GlfwKeyInput; +import com.jme3.input.lwjgl.GlfwMouseInput; +import com.jme3.system.AppSettings; +import com.jme3.system.JmeContext; +import com.jme3.system.JmeSystem; +import com.jme3.system.NanoTimer; +import org.lwjgl.Sys; +import org.lwjgl.glfw.*; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.lwjgl.glfw.GLFW.*; +import static org.lwjgl.opengl.GL11.GL_FALSE; +import static org.lwjgl.opengl.GL11.GL_TRUE; +import static org.lwjgl.system.MemoryUtil.NULL; + +/** + * A wrapper class over the GLFW framework in LWJGL 3. + * + * @author Daniel Johansson + */ +public abstract class LwjglWindow extends LwjglContext implements Runnable { + + private static final Logger LOGGER = Logger.getLogger(LwjglWindow.class.getName()); + + protected AtomicBoolean needClose = new AtomicBoolean(false); + protected final AtomicBoolean needRestart = new AtomicBoolean(false); + protected boolean wasActive = false; + protected boolean autoFlush = true; + protected boolean allowSwapBuffers = false; + private long window = -1; + private final JmeContext.Type type; + private int frameRateLimit = -1; + private double frameSleepTime; + + private GLFWErrorCallback errorCallback; + private GLFWWindowSizeCallback windowSizeCallback; + private GLFWWindowFocusCallback windowFocusCallback; + + public LwjglWindow(final JmeContext.Type type) { + if (!JmeContext.Type.Display.equals(type) && !JmeContext.Type.OffscreenSurface.equals(type) && !JmeContext.Type.Canvas.equals(type)) { + throw new IllegalArgumentException("Unsupported type '" + type.name() + "' provided"); + } + + this.type = type; + } + + /** + * @return Type.Display or Type.Canvas + */ + public JmeContext.Type getType() { + return type; + } + + /** + * Set the title if its a windowed display + * + * @param title the title to set + */ + public void setTitle(final String title) { + if (created.get() && window != -1) { + glfwSetWindowTitle(window, title); + } + } + + /** + * Restart if its a windowed or full-screen display. + */ + public void restart() { + if (created.get()) { + needRestart.set(true); + } else { + LOGGER.warning("Display is not created, cannot restart window."); + } + } + + /** + * Apply the settings, changing resolution, etc. + * + * @param settings the settings to apply when creating the context. + */ + protected void createContext(final AppSettings settings) { + glfwSetErrorCallback(errorCallback = new GLFWErrorCallback() { + @Override + public void invoke(int error, long description) { + final String message = Callbacks.errorCallbackDescriptionString(description); + listener.handleError(message, new Exception(message)); + } + }); + + if (glfwInit() != GL_TRUE) { + throw new IllegalStateException("Unable to initialize GLFW"); + } + + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_VISIBLE, GL_FALSE); + + // TODO: Add support for monitor selection + long monitor = NULL; + + if (settings.isFullscreen()) { + monitor = glfwGetPrimaryMonitor(); + } + + final ByteBuffer videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + + if (settings.getWidth() <= 0 || settings.getHeight() <= 0) { + settings.setResolution(GLFWvidmode.width(videoMode), GLFWvidmode.height(videoMode)); + } + + window = glfwCreateWindow(settings.getWidth(), settings.getHeight(), settings.getTitle(), monitor, NULL); + + if (window == NULL) { + throw new RuntimeException("Failed to create the GLFW window"); + } + + glfwWindowHint(GLFW_RESIZABLE, settings.isResizable() ? GL_TRUE : GL_FALSE); + glfwWindowHint(GLFW_DEPTH_BITS, settings.getDepthBits()); + glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits()); + glfwWindowHint(GLFW_SAMPLES, settings.getSamples()); + glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GL_TRUE : GL_FALSE); + glfwWindowHint(GLFW_REFRESH_RATE, settings.getFrequency()); + + // Not sure how else to support bits per pixel + if (settings.getBitsPerPixel() == 24) { + glfwWindowHint(GLFW_RED_BITS, 8); + glfwWindowHint(GLFW_GREEN_BITS, 8); + glfwWindowHint(GLFW_BLUE_BITS, 8); + } else if (settings.getBitsPerPixel() == 16) { + glfwWindowHint(GLFW_RED_BITS, 5); + glfwWindowHint(GLFW_GREEN_BITS, 6); + glfwWindowHint(GLFW_BLUE_BITS, 5); + } + + glfwWindowHint(GLFW_ALPHA_BITS, settings.getAlphaBits()); + + glfwSetWindowFocusCallback(window, windowFocusCallback = new GLFWWindowFocusCallback() { + @Override + public void invoke(final long window, final int focused) { + final boolean focus = (focused == GL_TRUE); + + if (wasActive != focus) { + if (!wasActive) { + listener.gainFocus(); + timer.reset(); + } else { + listener.loseFocus(); + } + + wasActive = !wasActive; + } + } + }); + + // Center the window + if (!settings.isFullscreen() && Type.Display.equals(type)) { + glfwSetWindowPos(window, (GLFWvidmode.width(videoMode) - settings.getWidth()) / 2, (GLFWvidmode.height(videoMode) - settings.getHeight()) / 2); + } + + // Make the OpenGL context current + glfwMakeContextCurrent(window); + + // Enable vsync + if (settings.isVSync()) { + glfwSwapInterval(1); + } else { + glfwSwapInterval(0); + } + + // Make the window visible + if (Type.Display.equals(type)) { + glfwShowWindow(window); + } + + // Add a resize callback which delegates to the listener + glfwSetWindowSizeCallback(window, windowSizeCallback = new GLFWWindowSizeCallback() { + @Override + public void invoke(final long window, final int width, final int height) { + settings.setResolution(width, height); + listener.reshape(width, height); + } + }); + + allowSwapBuffers = settings.isSwapBuffers(); + + // TODO: When GLFW 3.2 is released and included in LWJGL 3.x then we should hopefully be able to set the window icon. + } + + /** + * Destroy the context. + */ + protected void destroyContext() { + try { + if (renderer != null) { + renderer.cleanup(); + } + + errorCallback.release(); + windowSizeCallback.release(); + windowFocusCallback.release(); + + if (window != 0) { + glfwDestroyWindow(window); + } + } catch (Exception ex) { + listener.handleError("Failed to destroy context", ex); + } + } + + public void create(boolean waitFor) { + if (created.get()) { + LOGGER.warning("create() called when display is already created!"); + return; + } + + new Thread(this, THREAD_NAME).start(); + + if (waitFor) { + waitFor(true); + } + } + + /** + * Does LWJGL display initialization in the OpenGL thread + */ + protected boolean initInThread() { + try { + if (!JmeSystem.isLowPermissions()) { + // Enable uncaught exception handler only for current thread + Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread thread, Throwable thrown) { + listener.handleError("Uncaught exception thrown in " + thread.toString(), thrown); + if (needClose.get()) { + // listener.handleError() has requested the + // context to close. Satisfy request. + deinitInThread(); + } + } + }); + } + + timer = new NanoTimer(); + + // For canvas, this will create a pbuffer, + // allowing us to query information. + // When the canvas context becomes available, it will + // be replaced seamlessly. + createContext(settings); + printContextInitInfo(); + + created.set(true); + super.internalCreate(); + } catch (Exception ex) { + try { + if (window != -1) { + glfwDestroyWindow(window); + } + } catch (Exception ex2) { + LOGGER.log(Level.WARNING, null, ex2); + } + + listener.handleError("Failed to create display", ex); + return false; // if we failed to create display, do not continue + } + + listener.initialize(); + return true; + } + + /** + * execute one iteration of the render loop in the OpenGL thread + */ + protected void runLoop() { + // If a restart is required, lets recreate the context. + if (needRestart.getAndSet(false)) { + try { + createContext(settings); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "Failed to set display settings!", ex); + } + + LOGGER.fine("Display restarted."); + } + + if (!created.get()) { + throw new IllegalStateException(); + } + + listener.update(); + + // All this does is call swap buffers + // If the canvas is not active, there's no need to waste time + // doing that .. + if (renderable.get()) { + // calls swap buffers, etc. + try { + if (allowSwapBuffers && autoFlush) { + glfwSwapBuffers(window); + } + } catch (Throwable ex) { + listener.handleError("Error while swapping buffers", ex); + } + } + + glfwPollEvents(); + + // Subclasses just call GLObjectManager clean up objects here + // it is safe .. for now. + if (renderer != null) { + renderer.postFrame(); + } + + if (autoFlush) { + if (frameRateLimit != getSettings().getFrameRate()) { + setFrameRateLimit(getSettings().getFrameRate()); + } + } else if (frameRateLimit != 20) { + setFrameRateLimit(20); + } + + // If software frame rate limiting has been asked for, lets calculate sleep time based on a base value calculated + // from 1000 / frameRateLimit in milliseconds subtracting the time it has taken to render last frame. + // This gives an approximate limit within 3 fps of the given frame rate limit. + if (frameRateLimit > 0) { + final double sleep = frameSleepTime - (timer.getTimePerFrame() / 1000.0); + final long sleepMillis = (long) sleep; + final int additionalNanos = (int) ((sleep - sleepMillis) * 1000000.0); + + if (sleepMillis >= 0 && additionalNanos >= 0) { + try { + Thread.sleep(sleepMillis, additionalNanos); + } catch (InterruptedException ignored) { + } + } + } + } + + private void setFrameRateLimit(int frameRateLimit) { + this.frameRateLimit = frameRateLimit; + frameSleepTime = 1000.0 / this.frameRateLimit; + } + + /** + * De-initialize in the OpenGL thread. + */ + + protected void deinitInThread() { + destroyContext(); + + listener.destroy(); + LOGGER.fine("Display destroyed."); + super.internalDestroy(); + } + + public void run() { + if (listener == null) { + throw new IllegalStateException("SystemListener is not set on context!" + + "Must set with JmeContext.setSystemListener()."); + } + + loadNatives(); + LOGGER.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion()); + + if (!initInThread()) { + LOGGER.log(Level.SEVERE, "Display initialization failed. Cannot continue."); + return; + } + + while (true) { + if (glfwWindowShouldClose(window) == GL_TRUE) { + listener.requestClose(false); + } + + runLoop(); + + if (needClose.get()) { + break; + } + } + + deinitInThread(); + } + + public JoyInput getJoyInput() { + if (joyInput == null) { + joyInput = new GlfwJoystickInput(); + } + return joyInput; + } + + public MouseInput getMouseInput() { + if (mouseInput == null) { + mouseInput = new GlfwMouseInput(this); + } + return mouseInput; + } + + public KeyInput getKeyInput() { + if (keyInput == null) { + keyInput = new GlfwKeyInput(this); + } + + return keyInput; + } + + public TouchInput getTouchInput() { + return null; + } + + public void setAutoFlushFrames(boolean enabled) { + this.autoFlush = enabled; + } + + public void destroy(boolean waitFor) { + needClose.set(true); + + if (waitFor) { + waitFor(false); + } + } + + public long getWindowHandle() { + return window; + } + + + // TODO: Implement support for window icon when GLFW supports it. + + private ByteBuffer[] imagesToByteBuffers(Object[] images) { + ByteBuffer[] out = new ByteBuffer[images.length]; + for (int i = 0; i < images.length; i++) { + BufferedImage image = (BufferedImage) images[i]; + out[i] = imageToByteBuffer(image); + } + return out; + } + + private ByteBuffer imageToByteBuffer(BufferedImage image) { + if (image.getType() != BufferedImage.TYPE_INT_ARGB_PRE) { + BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE); + Graphics2D g = convertedImage.createGraphics(); + double width = image.getWidth() * (double) 1; + double height = image.getHeight() * (double) 1; + g.drawImage(image, (int) ((convertedImage.getWidth() - width) / 2), + (int) ((convertedImage.getHeight() - height) / 2), + (int) (width), (int) (height), null); + g.dispose(); + image = convertedImage; + } + + byte[] imageBuffer = new byte[image.getWidth() * image.getHeight() * 4]; + int counter = 0; + for (int i = 0; i < image.getHeight(); i++) { + for (int j = 0; j < image.getWidth(); j++) { + int colorSpace = image.getRGB(j, i); + imageBuffer[counter + 0] = (byte) ((colorSpace << 8) >> 24); + imageBuffer[counter + 1] = (byte) ((colorSpace << 16) >> 24); + imageBuffer[counter + 2] = (byte) ((colorSpace << 24) >> 24); + imageBuffer[counter + 3] = (byte) (colorSpace >> 24); + counter += 4; + } + } + return ByteBuffer.wrap(imageBuffer); + } +} diff --git a/jme3-networking/src/main/java/com/jme3/network/base/DefaultClient.java b/jme3-networking/src/main/java/com/jme3/network/base/DefaultClient.java index b297a933b..3e76f8be7 100644 --- a/jme3-networking/src/main/java/com/jme3/network/base/DefaultClient.java +++ b/jme3-networking/src/main/java/com/jme3/network/base/DefaultClient.java @@ -67,18 +67,18 @@ public class DefaultClient implements Client private static final int CH_UNRELIABLE = 1; private static final int CH_FIRST = 2; - private ThreadLocal dataBuffer = new ThreadLocal(); + private final ThreadLocal dataBuffer = new ThreadLocal(); private int id = -1; private boolean isRunning = false; - private CountDownLatch connecting = new CountDownLatch(1); + private final CountDownLatch connecting = new CountDownLatch(1); private String gameName; private int version; - private MessageListenerRegistry messageListeners = new MessageListenerRegistry(); - private List stateListeners = new CopyOnWriteArrayList(); - private List> errorListeners = new CopyOnWriteArrayList>(); - private Redispatch dispatcher = new Redispatch(); - private List channels = new ArrayList(); + private final MessageListenerRegistry messageListeners = new MessageListenerRegistry(); + private final List stateListeners = new CopyOnWriteArrayList(); + private final List> errorListeners = new CopyOnWriteArrayList>(); + private final Redispatch dispatcher = new Redispatch(); + private final List channels = new ArrayList(); private ConnectorFactory connectorFactory; @@ -100,6 +100,7 @@ public class DefaultClient implements Client } protected void addStandardServices() { + log.fine("Adding standard services..."); services.addService(new ClientSerializerRegistrationsService()); } @@ -128,6 +129,7 @@ public class DefaultClient implements Client throw new IllegalStateException( "Client is not started." ); } + @Override public void start() { if( isRunning ) @@ -179,6 +181,7 @@ public class DefaultClient implements Client } } + @Override public boolean isStarted() { return isRunning; } @@ -195,33 +198,42 @@ public class DefaultClient implements Client } } + @Override public boolean isConnected() { return id != -1 && isRunning; } + @Override public int getId() { return id; } + @Override public String getGameName() { return gameName; } + @Override public int getVersion() { return version; } + @Override public ClientServiceManager getServices() { return services; } + @Override public void send( Message message ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "send({0})", message); + } if( message.isReliable() || channels.get(CH_UNRELIABLE) == null ) { send(CH_RELIABLE, message, true); } else { @@ -229,8 +241,12 @@ public class DefaultClient implements Client } } + @Override public void send( int channel, Message message ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "send({0}, {1})", new Object[]{channel, message}); + } if( channel >= 0 ) { // Make sure we aren't still connecting. Channels // won't be valid until we are fully connected since @@ -275,6 +291,7 @@ public class DefaultClient implements Client channels.get(channel).write(buffer); } + @Override public void close() { checkRunning(); @@ -287,9 +304,11 @@ public class DefaultClient implements Client if( !isRunning ) return; - // Let the services get a chance to stop before we - // kill the connection. - services.stop(); + if( services.isStarted() ) { + // Let the services get a chance to stop before we + // kill the connection. + services.stop(); + } // Send a close message @@ -313,41 +332,49 @@ public class DefaultClient implements Client services.terminate(); } + @Override public void addClientStateListener( ClientStateListener listener ) { stateListeners.add( listener ); } + @Override public void removeClientStateListener( ClientStateListener listener ) { stateListeners.remove( listener ); } + @Override public void addMessageListener( MessageListener listener ) { messageListeners.addMessageListener( listener ); } + @Override public void addMessageListener( MessageListener listener, Class... classes ) { messageListeners.addMessageListener( listener, classes ); } + @Override public void removeMessageListener( MessageListener listener ) { messageListeners.removeMessageListener( listener ); } + @Override public void removeMessageListener( MessageListener listener, Class... classes ) { messageListeners.removeMessageListener( listener, classes ); } + @Override public void addErrorListener( ErrorListener listener ) { errorListeners.add( listener ); } + @Override public void removeErrorListener( ErrorListener listener ) { errorListeners.remove( listener ); @@ -362,6 +389,7 @@ public class DefaultClient implements Client protected void startServices() { + log.fine("Starting client services."); // Let the services know we are finally started services.start(); } @@ -420,6 +448,10 @@ public class DefaultClient implements Client protected void dispatch( Message m ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "{0} received:{1}", new Object[]{this, m}); + } + // Pull off the connection management messages we're // interested in and then pass on the rest. if( m instanceof ClientRegistrationMessage ) { @@ -461,11 +493,13 @@ public class DefaultClient implements Client protected class Redispatch implements MessageListener, ErrorListener { + @Override public void messageReceived( Object source, Message m ) { dispatch( m ); } + @Override public void handleError( Object source, Throwable t ) { // Only doing the DefaultClient.this to make the code diff --git a/jme3-networking/src/main/java/com/jme3/network/base/DefaultServer.java b/jme3-networking/src/main/java/com/jme3/network/base/DefaultServer.java index 2b9add2ef..e95c0f97f 100644 --- a/jme3-networking/src/main/java/com/jme3/network/base/DefaultServer.java +++ b/jme3-networking/src/main/java/com/jme3/network/base/DefaultServer.java @@ -66,26 +66,26 @@ public class DefaultServer implements Server private static final int CH_FIRST = 2; private boolean isRunning = false; - private AtomicInteger nextId = new AtomicInteger(0); + private final AtomicInteger nextId = new AtomicInteger(0); private String gameName; private int version; - private KernelFactory kernelFactory = KernelFactory.DEFAULT; + private final KernelFactory kernelFactory = KernelFactory.DEFAULT; private KernelAdapter reliableAdapter; private KernelAdapter fastAdapter; - private List channels = new ArrayList(); - private List alternatePorts = new ArrayList(); - private Redispatch dispatcher = new Redispatch(); - private Map connections = new ConcurrentHashMap(); - private Map endpointConnections + private final List channels = new ArrayList(); + private final List alternatePorts = new ArrayList(); + private final Redispatch dispatcher = new Redispatch(); + private final Map connections = new ConcurrentHashMap(); + private final Map endpointConnections = new ConcurrentHashMap(); // Keeps track of clients for whom we've only received the UDP // registration message - private Map connecting = new ConcurrentHashMap(); + private final Map connecting = new ConcurrentHashMap(); - private MessageListenerRegistry messageListeners + private final MessageListenerRegistry messageListeners = new MessageListenerRegistry(); - private List connectionListeners = new CopyOnWriteArrayList(); + private final List connectionListeners = new CopyOnWriteArrayList(); private HostedServiceManager services; @@ -108,24 +108,29 @@ public class DefaultServer implements Server } protected void addStandardServices() { + log.fine("Adding standard services..."); services.addService(new ServerSerializerRegistrationsService()); } + @Override public String getGameName() { return gameName; } + @Override public int getVersion() { return version; } + @Override public HostedServiceManager getServices() { return services; } + @Override public int addChannel( int port ) { if( isRunning ) @@ -164,6 +169,7 @@ public class DefaultServer implements Server } } + @Override public void start() { if( isRunning ) @@ -185,11 +191,13 @@ public class DefaultServer implements Server services.start(); } + @Override public boolean isRunning() { return isRunning; } + @Override public void close() { if( !isRunning ) @@ -214,13 +222,19 @@ public class DefaultServer implements Server } } + @Override public void broadcast( Message message ) { broadcast( null, message ); } + @Override public void broadcast( Filter filter, Message message ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "broadcast({0}, {1})", new Object[]{filter, message}); + } + if( connections.isEmpty() ) return; @@ -237,8 +251,13 @@ public class DefaultServer implements Server } } + @Override public void broadcast( int channel, Filter filter, Message message ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "broadcast({0}, {1}. {2})", new Object[]{channel, filter, message}); + } + if( connections.isEmpty() ) return; @@ -251,46 +270,55 @@ public class DefaultServer implements Server channels.get(channel+CH_FIRST).broadcast( adapter, buffer, true, false ); } + @Override public HostedConnection getConnection( int id ) { return connections.get(id); } + @Override public boolean hasConnections() { return !connections.isEmpty(); } + @Override public Collection getConnections() { return Collections.unmodifiableCollection((Collection)connections.values()); } + @Override public void addConnectionListener( ConnectionListener listener ) { connectionListeners.add(listener); } + @Override public void removeConnectionListener( ConnectionListener listener ) { connectionListeners.remove(listener); } + @Override public void addMessageListener( MessageListener listener ) { messageListeners.addMessageListener( listener ); } + @Override public void addMessageListener( MessageListener listener, Class... classes ) { messageListeners.addMessageListener( listener, classes ); } + @Override public void removeMessageListener( MessageListener listener ) { messageListeners.removeMessageListener( listener ); } + @Override public void removeMessageListener( MessageListener listener, Class... classes ) { messageListeners.removeMessageListener( listener, classes ); @@ -298,6 +326,10 @@ public class DefaultServer implements Server protected void dispatch( HostedConnection source, Message m ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "{0} received:{1}", new Object[]{source, m}); + } + if( source == null ) { messageListeners.messageReceived( source, m ); } else { @@ -484,12 +516,12 @@ public class DefaultServer implements Server protected class Connection implements HostedConnection { - private int id; + private final int id; private boolean closed; private Endpoint[] channels; private int setChannelCount = 0; - private Map sessionData = new ConcurrentHashMap(); + private final Map sessionData = new ConcurrentHashMap(); public Connection( int channelCount ) { @@ -523,23 +555,30 @@ public class DefaultServer implements Server return setChannelCount == channels.length; } + @Override public Server getServer() { return DefaultServer.this; } + @Override public int getId() { return id; } + @Override public String getAddress() { return channels[CH_RELIABLE] == null ? null : channels[CH_RELIABLE].getAddress(); } + @Override public void send( Message message ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "send({0})", message); + } ByteBuffer buffer = MessageProtocol.messageToBuffer(message, null); if( message.isReliable() || channels[CH_UNRELIABLE] == null ) { channels[CH_RELIABLE].send( buffer ); @@ -548,8 +587,12 @@ public class DefaultServer implements Server } } + @Override public void send( int channel, Message message ) { + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "send({0}, {1})", new Object[]{channel, message}); + } checkChannel(channel); ByteBuffer buffer = MessageProtocol.messageToBuffer(message, null); channels[channel+CH_FIRST].send(buffer); @@ -573,6 +616,7 @@ public class DefaultServer implements Server fireConnectionRemoved( this ); } + @Override public void close( String reason ) { // Send a reason @@ -593,6 +637,7 @@ public class DefaultServer implements Server } } + @Override public Object setAttribute( String name, Object value ) { if( value == null ) @@ -601,11 +646,13 @@ public class DefaultServer implements Server } @SuppressWarnings("unchecked") + @Override public T getAttribute( String name ) { return (T)sessionData.get(name); } + @Override public Set attributeNames() { return Collections.unmodifiableSet(sessionData.keySet()); @@ -621,6 +668,7 @@ public class DefaultServer implements Server protected class Redispatch implements MessageListener { + @Override public void messageReceived( HostedConnection source, Message m ) { dispatch( source, m ); @@ -629,13 +677,14 @@ public class DefaultServer implements Server protected class FilterAdapter implements Filter { - private Filter delegate; + private final Filter delegate; public FilterAdapter( Filter delegate ) { this.delegate = delegate; } + @Override public boolean apply( Endpoint input ) { HostedConnection conn = getConnection( input ); diff --git a/jme3-networking/src/main/java/com/jme3/network/base/MessageListenerRegistry.java b/jme3-networking/src/main/java/com/jme3/network/base/MessageListenerRegistry.java index f151e1c84..4a2e40491 100644 --- a/jme3-networking/src/main/java/com/jme3/network/base/MessageListenerRegistry.java +++ b/jme3-networking/src/main/java/com/jme3/network/base/MessageListenerRegistry.java @@ -50,26 +50,34 @@ import java.util.logging.Logger; */ public class MessageListenerRegistry implements MessageListener { - static Logger log = Logger.getLogger(MessageListenerRegistry.class.getName()); + static final Logger log = Logger.getLogger(MessageListenerRegistry.class.getName()); - private List> listeners = new CopyOnWriteArrayList>(); - private Map>> typeListeners + private final List> listeners = new CopyOnWriteArrayList>(); + private final Map>> typeListeners = new ConcurrentHashMap>>(); public MessageListenerRegistry() { } + @Override public void messageReceived( S source, Message m ) { boolean delivered = false; + boolean trace = log.isLoggable(Level.FINER); for( MessageListener l : listeners ) { + if( trace ) { + log.log(Level.FINER, "Delivering {0} to:{1}", new Object[]{m, l}); + } l.messageReceived( source, m ); delivered = true; } for( MessageListener l : getListeners(m.getClass(),false) ) { + if( trace ) { + log.log(Level.FINER, "Delivering {0} to:{1}", new Object[]{m, l}); + } l.messageReceived( source, m ); delivered = true; } diff --git a/jme3-networking/src/main/java/com/jme3/network/base/MessageProtocol.java b/jme3-networking/src/main/java/com/jme3/network/base/MessageProtocol.java index 6751ecc3f..bd85ececc 100644 --- a/jme3-networking/src/main/java/com/jme3/network/base/MessageProtocol.java +++ b/jme3-networking/src/main/java/com/jme3/network/base/MessageProtocol.java @@ -53,7 +53,7 @@ import java.util.LinkedList; */ public class MessageProtocol { - private LinkedList messages = new LinkedList(); + private final LinkedList messages = new LinkedList(); private ByteBuffer current; private int size; private Byte carry; diff --git a/jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java b/jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java index 9c3896475..4d1decc08 100644 --- a/jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java +++ b/jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java @@ -94,7 +94,7 @@ public class SerializerRegistrationsMessage extends AbstractMessage { public static Registration[] compiled; private static final Serializer fieldSerializer = new FieldSerializer(); - private Registration[] registrations; + private Registration[] registrations; public SerializerRegistrationsMessage() { setReliable(true); @@ -132,7 +132,25 @@ public class SerializerRegistrationsMessage extends AbstractMessage { Serializer.setReadOnly(true); } - public void registerAll() { + public void registerAll() { + + // See if we will have problems because our registry is locked + if( Serializer.isReadOnly() ) { + // Check to see if maybe we are executing this from the + // same JVM that sent the message, ie: client and server are running on + // the same JVM + // There could be more advanced checks than this but for now we'll + // assume that if the registry was compiled here then it means + // we are also the server process. Note that this wouldn't hold true + // under complicated examples where there are clients of one server + // that also run their own servers but realistically they would have + // to disable the ServerSerializerRegistrationsServer anyway. + if( compiled != null ) { + log.log( Level.INFO, "Skipping registration as registry is locked, presumably by a local server process."); + return; + } + } + for( Registration reg : registrations ) { log.log( Level.INFO, "Registering:{0}", reg); reg.register(); diff --git a/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java b/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java index d4c054403..7e6b18849 100644 --- a/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java +++ b/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java @@ -45,6 +45,7 @@ import java.nio.ByteBuffer; import java.util.*; import java.util.jar.Attributes; import java.util.logging.Level; +import java.util.logging.LogManager; import java.util.logging.Logger; /** @@ -403,6 +404,10 @@ public abstract class Serializer { if (reg == null) { throw new SerializerException( "Class not registered:" + type ); } + + if( log.isLoggable(Level.FINER) ) { + log.log(Level.FINER, "writing class:{0} with ID:{1}", new Object[]{type, reg.getId()}); + } buffer.putShort(reg.getId()); return reg; } diff --git a/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/GZIPSerializer.java b/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/GZIPSerializer.java index 01dbd1d41..7579e84c5 100644 --- a/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/GZIPSerializer.java +++ b/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/GZIPSerializer.java @@ -87,7 +87,8 @@ public class GZIPSerializer extends Serializer { ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream(); GZIPOutputStream gzipOutput = new GZIPOutputStream(byteArrayOutput); - gzipOutput.write(tempBuffer.array()); + tempBuffer.flip(); + gzipOutput.write(tempBuffer.array(), 0, tempBuffer.limit()); gzipOutput.flush(); gzipOutput.finish(); gzipOutput.close(); diff --git a/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/ZIPSerializer.java b/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/ZIPSerializer.java index 1241c1341..ad7d7162d 100644 --- a/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/ZIPSerializer.java +++ b/jme3-networking/src/main/java/com/jme3/network/serializing/serializers/ZIPSerializer.java @@ -98,7 +98,8 @@ public class ZIPSerializer extends Serializer { ZipEntry zipEntry = new ZipEntry("zip"); zipOutput.putNextEntry(zipEntry); - zipOutput.write(tempBuffer.array()); + tempBuffer.flip(); + zipOutput.write(tempBuffer.array(), 0, tempBuffer.limit()); zipOutput.flush(); zipOutput.closeEntry(); zipOutput.close(); diff --git a/jme3-networking/src/main/java/com/jme3/network/service/AbstractService.java b/jme3-networking/src/main/java/com/jme3/network/service/AbstractService.java index 370b1c5af..3123e8c82 100644 --- a/jme3-networking/src/main/java/com/jme3/network/service/AbstractService.java +++ b/jme3-networking/src/main/java/com/jme3/network/service/AbstractService.java @@ -106,6 +106,6 @@ public abstract class AbstractService implements Servi @Override public String toString() { - return getClass().getName() + "[serviceManager.class=" + serviceManager.getClass() + "]"; + return getClass().getName() + "[serviceManager.class=" + (serviceManager != null ? serviceManager.getClass() : "") + "]"; } } diff --git a/jme3-networking/src/main/java/com/jme3/network/service/ServiceManager.java b/jme3-networking/src/main/java/com/jme3/network/service/ServiceManager.java index b8ee7d3c4..afcfd73c2 100644 --- a/jme3-networking/src/main/java/com/jme3/network/service/ServiceManager.java +++ b/jme3-networking/src/main/java/com/jme3/network/service/ServiceManager.java @@ -34,6 +34,8 @@ package com.jme3.network.service; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; /** * The base service manager class from which the HostedServiceManager @@ -44,7 +46,9 @@ import java.util.concurrent.CopyOnWriteArrayList; */ public abstract class ServiceManager { - private List> services = new CopyOnWriteArrayList>(); + static final Logger log = Logger.getLogger(ServiceManager.class.getName()); + + private final List> services = new CopyOnWriteArrayList>(); private volatile boolean started = false; protected ServiceManager() { @@ -76,6 +80,9 @@ public abstract class ServiceManager { return; } for( Service s : services ) { + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "Starting service:{0}", s); + } s.start(); } started = true; @@ -96,6 +103,9 @@ public abstract class ServiceManager { throw new IllegalStateException(getClass().getSimpleName() + " not started."); } for( Service s : services ) { + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "Stopping service:{0}", s); + } s.stop(); } started = false; @@ -106,9 +116,18 @@ public abstract class ServiceManager { * has already been started then the service will also be started. */ public > void addService( S s ) { + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "addService({0})", s); + } services.add(s); + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "Initializing service:{0}", s); + } s.initialize(getParent()); if( started ) { + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "Starting service:{0}", s); + } s.start(); } } @@ -120,10 +139,19 @@ public abstract class ServiceManager { * the service will be terminated. */ public > void removeService( S s ) { + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "removeService({0})", s); + } if( started ) { + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "Stopping service:{0}", s); + } s.stop(); } services.remove(s); + if( log.isLoggable(Level.FINE) ) { + log.log(Level.FINE, "Terminating service:{0}", s); + } s.terminate(getParent()); } diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/Asynchronous.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/Asynchronous.java new file mode 100644 index 000000000..a26d09635 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/Asynchronous.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + + +/** + * Indicates that a given method should be executed asynchronously + * through the RMI service. This must annotate the method on the + * shared interface for it to have an effect. If reliable=false + * is specified then remote method invocation is done over UDP + * instead of TCP, ie: unreliably... but faster. + * + * @author Paul Speed + */ +@Retention(value=RUNTIME) +@Target(value=METHOD) +public @interface Asynchronous { + boolean reliable() default true; +} + + diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/CallType.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/CallType.java new file mode 100644 index 000000000..5167bd7eb --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/CallType.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + + +/** + * Internal type denoting the type of call to make when remotely + * invoking methods. + * + * @author Paul Speed + */ +public enum CallType { + /** + * Caller will block until a response is received and returned. + */ + Synchronous, + + /** + * Caller does not block or wait for a response. The other end + * of the connection will also not send one. + */ + Asynchronous, + + /** + * Similar to asynchronous in that no response is expected or sent + * but differs in that the call will be sent over UDP and so may + * not make it to the other end. + */ + Unreliable +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfo.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfo.java new file mode 100644 index 000000000..4f7f7de32 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfo.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import com.jme3.network.serializing.Serializable; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + + +/** + * Internal information about a shared class. This is the information + * that is sent over the wire for shared types. + * + * @author Paul Speed + */ +@Serializable +public final class ClassInfo { + private String name; + private short typeId; + private MethodInfo[] methods; + + /** + * For serialization only. + */ + public ClassInfo() { + } + + public ClassInfo( short typeId, Class type ) { + this.typeId = typeId; + this.name = type.getName(); + this.methods = toMethodInfo(type, type.getMethods()); + } + + public String getName() { + return name; + } + + public Class getType() { + try { + return Class.forName(name); + } catch( ClassNotFoundException e ) { + throw new RuntimeException("Error finding class for:" + this, e); + } + } + + public short getId() { + return typeId; + } + + public MethodInfo getMethod( short id ) { + return methods[id]; + } + + public MethodInfo getMethod( Method m ) { + for( MethodInfo mi : methods ) { + if( mi.matches(m) ) { + return mi; + } + } + return null; + } + + private MethodInfo[] toMethodInfo( Class type, Method[] methods ) { + List result = new ArrayList(); + short methodId = 0; + for( Method m : methods ) { + // Simple... add all methods exposed through the interface + result.add(new MethodInfo(methodId++, m)); + } + return result.toArray(new MethodInfo[result.size()]); + } + + public MethodInfo[] getMethods() { + return methods; + } + + @Override + public String toString() { + return "ClassInfo[" + name + "]"; + } +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfoRegistry.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfoRegistry.java new file mode 100644 index 000000000..addc03593 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfoRegistry.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + + +/** + * Internal registry of shared types and their ClassInfo and MethodInfo + * objects. + * + * @author Paul Speed + */ +public class ClassInfoRegistry { + + //private final LoadingCache cache; // Guava version + private final Map cache = new HashMap(); + private final AtomicInteger nextClassId = new AtomicInteger(); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + + public ClassInfoRegistry() { + //this.cache = CacheBuilder.newBuilder().build(new ClassInfoLoader()); // Guava version + } + + public ClassInfo getClassInfo( Class type ) { + //return cache.getUnchecked(type); // Guava version + + // More complicated without guava + lock.readLock().lock(); + try { + ClassInfo result = cache.get(type); + if( result != null ) { + return result; + } + // Else we need to create it and store it... so grab the write + // lock + lock.readLock().unlock(); + lock.writeLock().lock(); + try { + // Note: it's technically possible that a race with another thread + // asking for the same class already created one between our read unlock + // and our write lock. No matter as it's cheap to create one and does + // no harm. Code is simpler without the double-check. + result = new ClassInfo((short)nextClassId.getAndIncrement(), type); + cache.put(type, result); + + // Regrab the read lock before leaving... kind of unnecessary but + // it makes the method cleaner and widens the gap of lock races. + // Downgrading a write lock to read is ok. + lock.readLock().lock(); + + return result; + } finally { + // Unlock the write lock while still holding onto read + lock.writeLock().unlock(); + } + } finally { + lock.readLock().unlock(); + } + } + + /* + would be more straight-forward with guava Guava version + private class ClassInfoLoader extends CacheLoader { + @Override + public ClassInfo load( Class type ) { + return new ClassInfo((short)nextClassId.getAndIncrement(), type); + } + }*/ +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/MethodInfo.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/MethodInfo.java new file mode 100644 index 000000000..9b324a6c3 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/MethodInfo.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import com.jme3.network.serializing.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import javax.jws.Oneway; + + +/** + * Internal information about shared methods. This is part of the data that + * is passed over the wire when an object is shared. + * + * @author Paul Speed + */ +@Serializable +public final class MethodInfo { + + public static final MethodInfo NULL_INFO = new MethodInfo(); + + private String representation; + private short id; + private CallType callType; + private transient Method method; + + /** + * For serialization only. + */ + public MethodInfo() { + } + + public MethodInfo( short id, Method m ) { + this.id = id; + this.method = m; + this.representation = methodToString(m); + this.callType = getCallType(m); + } + + public Object invoke( Object target, Object... parms ) { + try { + return method.invoke(target, parms); + } catch (IllegalAccessException e) { + throw new RuntimeException("Error invoking:" + method + " on:" + target, e); + } catch (IllegalArgumentException e) { + throw new RuntimeException("Error invoking:" + method + " on:" + target, e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Error invoking:" + method + " on:" + target, e); + } + } + + public short getId() { + return id; + } + + public CallType getCallType() { + return callType; + } + + public boolean matches( Method m ) { + return representation.equals(methodToString(m)); + } + + public static String methodToString( Method m ) { + StringBuilder sb = new StringBuilder(); + for( Class t : m.getParameterTypes() ) { + if( sb.length() > 0 ) + sb.append(", "); + sb.append(t.getName()); + } + return m.getReturnType().getName() + " " + m.getName() + "(" + sb + ")"; + } + + public static CallType getCallType( Method m ) { + if( m.getReturnType() != Void.TYPE ) + return CallType.Synchronous; + if( m.getAnnotation(Oneway.class) != null ) + return CallType.Asynchronous; + if( m.getAnnotation(Asynchronous.class) == null ) + return CallType.Synchronous; + + Asynchronous async = m.getAnnotation(Asynchronous.class); + return async.reliable() ? CallType.Asynchronous : CallType.Unreliable; + } + + @Override + public int hashCode() { + return representation.hashCode(); + } + + @Override + public boolean equals( Object o ) { + if( o == this ) { + return true; + } + if( o == null || o.getClass() != getClass() ) { + return false; + } + MethodInfo other = (MethodInfo)o; + return representation.equals(other.representation); + } + + @Override + public String toString() { + return "MethodInfo[#" + getId() + ", callType=" + callType + ", " + representation + "]"; + } +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RemoteObjectHandler.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RemoteObjectHandler.java new file mode 100644 index 000000000..f42ada84f --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RemoteObjectHandler.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * Used internally to remotely invoke methods on RMI shared objects. + * + * @author Paul Speed + */ +public class RemoteObjectHandler implements InvocationHandler { + + private final RmiRegistry rmi; + private final byte channel; + private final short objectId; + private final ClassInfo typeInfo; + private final Map methodIndex = new ConcurrentHashMap(); + + public RemoteObjectHandler( RmiRegistry rmi, byte channel, short objectId, ClassInfo typeInfo ) { + this.rmi = rmi; + this.channel = channel; + this.objectId = objectId; + this.typeInfo = typeInfo; + } + + protected MethodInfo getMethodInfo( Method method ) { + MethodInfo mi = methodIndex.get(method); + if( mi == null ) { + mi = typeInfo.getMethod(method); + if( mi == null ) { + mi = MethodInfo.NULL_INFO; + } + methodIndex.put(method, mi); + } + return mi == MethodInfo.NULL_INFO ? null : mi; + } + + @Override + public Object invoke(Object o, Method method, Object[] os) throws Throwable { + MethodInfo mi = getMethodInfo(method); + if( mi == null ) { + // Try to invoke locally + return method.invoke(this, os); + } + return rmi.invokeRemote(channel, objectId, mi.getId(), mi.getCallType(), os); + } + + @Override + public String toString() { + return "RemoteObject[#" + objectId + ", " + typeInfo.getName() + "]"; + } +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiClientService.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiClientService.java new file mode 100644 index 000000000..ea1506f72 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiClientService.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import com.jme3.network.MessageConnection; +import com.jme3.network.service.AbstractClientService; +import com.jme3.network.service.ClientServiceManager; +import com.jme3.network.service.rpc.RpcClientService; +import java.util.ArrayList; +import java.util.List; + + +/** + * A service that can be added to the client to support a simple + * shared objects protocol. + * + *

    Objects are shared by adding them to the RmiRegistry with one of the + * share() methods. Shared objects must have a separate interface and implementation. + * The interface is what the other end of the connection will use to interact + * with the object and that interface class must be available on both ends of + * the connection. The implementing class need only be on the sharing end.

    + * + *

    Shared objects can be accessed on the other end of the connection by + * using one of the RmiRegistry's getRemoteObject() methods. These can be + * used to lookup an object by class if it is a shared singleton or by name + * if it was registered with a name.

    + * + *

    Note: This RMI implementation is not as advanced as Java's regular + * RMI as it won't marshall shared references, ie: you can't pass + * a shared objects as an argument to another shared object's method.

    + * + * @author Paul Speed + */ +public class RmiClientService extends AbstractClientService { + + private RpcClientService rpc; + private byte defaultChannel; + private short rmiObjectId; + private RmiRegistry rmi; + private volatile boolean isStarted = false; + + private final List pending = new ArrayList(); + + public RmiClientService() { + this((short)-1, (byte)MessageConnection.CHANNEL_DEFAULT_RELIABLE); + } + + public RmiClientService( short rmiObjectId, byte defaultChannel ) { + this.defaultChannel = defaultChannel; + this.rmiObjectId = rmiObjectId; + } + + /** + * Shares the specified object with the server and associates it with the + * specified type. Objects shared in this way are available in the connection-specific + * RMI registry on the server and are not available to other connections. + */ + public void share( T object, Class type ) { + share(defaultChannel, object, type); + } + + /** + * Shares the specified object with the server and associates it with the + * specified type. Objects shared in this way are available in the connection-specific + * RMI registry on the server and are not available to other connections. + * All object related communication will be done over the specified connection + * channel. + */ + public void share( byte channel, T object, Class type ) { + share(channel, type.getName(), object, type); + } + + /** + * Shares the specified object with the server and associates it with the + * specified name. Objects shared in this way are available in the connection-specific + * RMI registry on the server and are not available to other connections. + */ + public void share( String name, T object, Class type ) { + share(defaultChannel, name, object, type); + } + + /** + * Shares the specified object with the server and associates it with the + * specified name. Objects shared in this way are available in the connection-specific + * RMI registry on the server and are not available to other connections. + * All object related communication will be done over the specified connection + * channel. + */ + public void share( byte channel, String name, T object, Class type ) { + if( !isStarted ) { + synchronized(pending) { + if( !isStarted ) { + pending.add(new ObjectInfo(channel, name, object, type)); + return; + } + } + } + + // Else we can add it directly. + rmi.share(channel, name, object, type); + } + + /** + * Looks up a remote object on the server by type and returns a local proxy to the + * remote object that was shared on the other end of the network connection. + */ + public T getRemoteObject( Class type ) { + return rmi.getRemoteObject(type); + } + + /** + * Looks up a remote object on the server by name and returns a local proxy to the + * remote object that was shared on the other end of the network connection. + */ + public T getRemoteObject( String name, Class type ) { + return rmi.getRemoteObject(name, type); + } + + @Override + protected void onInitialize( ClientServiceManager s ) { + rpc = getService(RpcClientService.class); + if( rpc == null ) { + throw new RuntimeException("RmiClientService requires RpcClientService"); + } + + // Register it now so that it is available when the + // server starts to send us stuff. Waiting until start() + // is too late in this case. + rmi = new RmiRegistry(rpc.getRpcConnection(), rmiObjectId, defaultChannel); + } + + @Override + public void start() { + super.start(); + + // Register all of the classes that have been waiting. + synchronized(pending) { + for( ObjectInfo info : pending ) { + rmi.share(info.channel, info.name, info.object, info.type); + } + pending.clear(); + isStarted = true; + } + } + + private class ObjectInfo { + byte channel; + String name; + Object object; + Class type; + + public ObjectInfo( byte channel, String name, Object object, Class type ) { + this.channel = channel; + this.name = name; + this.object = object; + this.type = type; + } + + @Override + public String toString() { + return "ObjectInfo[" + channel + ", " + name + ", " + object + ", " + type + "]"; + } + } +} + diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiContext.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiContext.java new file mode 100644 index 000000000..547e83dd4 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiContext.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import com.jme3.network.HostedConnection; + + +/** + * Keeps track of the current connection performing a particular + * RMI call. RMI-based services can use this to find out which + * connection is calling a particular method without having to + * pass additional problematic data on the method calls. + * + * @author Paul Speed + */ +public class RmiContext { + private static final ThreadLocal connection = new ThreadLocal(); + + /** + * Returns the HostedConnection that is responsible for any + * RMI-related calls on this thread. + */ + public static HostedConnection getRmiConnection() { + return connection.get(); + } + + static void setRmiConnection( HostedConnection conn ) { + connection.set(conn); + } +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiHostedService.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiHostedService.java new file mode 100644 index 000000000..ebd0e5908 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiHostedService.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import com.jme3.network.HostedConnection; +import com.jme3.network.MessageConnection; +import com.jme3.network.Server; +import com.jme3.network.serializing.Serializer; +import com.jme3.network.service.AbstractHostedService; +import com.jme3.network.service.HostedServiceManager; +import com.jme3.network.service.rpc.RpcHostedService; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * A service that can be added to the host to support a simple + * shared objects protocol. + * + *

    Objects are shared by adding them to the RmiRegistry with one of the + * share() methods. Shared objects must have a separate interface and implementation. + * The interface is what the other end of the connection will use to interact + * with the object and that interface class must be available on both ends of + * the connection. The implementing class need only be on the sharing end.

    + * + *

    Shared objects can be accessed on the other end of the connection by + * using one of the RmiRegistry's getRemoteObject() methods. These can be + * used to lookup an object by class if it is a shared singleton or by name + * if it was registered with a name.

    + * + *

    On the hosting side, a special shardGlobal() method is provided that + * will register shared objects that will automatically be provided to every + * new joining client and they will all be calling the same server-side instance. + * Normally, shared objects themselves are connection specific and handled + * at the connection layer. The shareGlobal() space is a way to have global + * resources passed directly though the need is relatively rare.

    + * + *

    Note: This RMI implementation is not as advanced as Java's regular + * RMI as it won't marshall shared references, ie: you can't pass + * a shared objects as an argument to another shared object's method.

    + * + * @author Paul Speed + */ +public class RmiHostedService extends AbstractHostedService { + + static final Logger log = Logger.getLogger(RpcHostedService.class.getName()); + + public static final String ATTRIBUTE_NAME = "rmi"; + + private RpcHostedService rpcService; + private short rmiId; + private byte defaultChannel; + private boolean autoHost; + private final Map globalShares = new ConcurrentHashMap(); + + public RmiHostedService() { + this((short)-1, (byte)MessageConnection.CHANNEL_DEFAULT_RELIABLE, true); + } + + public RmiHostedService( byte defaultChannel ) { + this((short)-1, defaultChannel, true); + } + + public RmiHostedService( short rmiId, byte defaultChannel, boolean autoHost ) { + this.rmiId = rmiId; + this.defaultChannel = defaultChannel; + this.autoHost = autoHost; + + Serializer.registerClasses(ClassInfo.class, MethodInfo.class); + } + + /** + * Shares a server-wide object associated with the specified type. All connections + * with RMI hosting started will have access to this shared object as soon as they + * connect and they will all share the same instance. It is up to the shared object + * to handle any multithreading that might be required. + */ + public void shareGlobal( T object, Class type ) { + shareGlobal(defaultChannel, type.getName(), object, type); + } + + /** + * Shares a server-wide object associated with the specified name. All connections + * with RMI hosting started will have access to this shared object as soon as they + * connect and they will all share the same instance. It is up to the shared object + * to handle any multithreading that might be required. + */ + public void shareGlobal( String name, T object, Class type ) { + shareGlobal(defaultChannel, name, object, type); + } + + /** + * Shares a server-wide object associated with the specified name over the specified + * channel. All connections with RMI hosting started will have access to this shared + * object as soon as they connect and they will all share the same instance. It is up + * to the shared object to handle any multithreading that might be required. + * All network communcation associated with the shared object will be done over + * the specified channel. + */ + public void shareGlobal( byte channel, String name, T object, Class type ) { + GlobalShare share = new GlobalShare(channel, object, type); + GlobalShare existing = globalShares.put(name, share); + if( existing != null ) { + // Shouldn't need to do anything actually. + } + + // Go through all of the children + for( HostedConnection conn : getServer().getConnections() ) { + RmiRegistry child = getRmiRegistry(conn); + if( child == null ) { + continue; + } + child.share(channel, name, object, type); + } + } + + /** + * Set to true if all new connections should automatically have RMI hosting started. + * Set to false if the game-specific connection setup will call startHostingOnConnection() + * after some connection setup is done (for example, logging in). Note: generally + * is is safe to autohost RMI as long as callers are careful about what they've added + * using shareGlobal(). One reasonable use-case is to shareGlobal() some kind of login + * service and nothing else. All other shared objects would then be added as connection + * specific objects during successful login processing. + */ + public void setAutoHost( boolean b ) { + this.autoHost = b; + } + + /** + * Returns true if RMI hosting is automatically started for all new connections. + */ + public boolean getAutoHost() { + return autoHost; + } + + /** + * Returns the RMI registry for the specific HostedConection. Each connection + * has its own registry with its own connection-specific shared objects. + */ + public RmiRegistry getRmiRegistry( HostedConnection hc ) { + return hc.getAttribute(ATTRIBUTE_NAME); + } + + /** + * Sets up RMI hosting services for the hosted connection allowing + * getRmiRegistry() to return a valid RmiRegistry object. + * This method is called automatically for all new connections if + * autohost is set to true. + */ + public void startHostingOnConnection( HostedConnection hc ) { + if( log.isLoggable(Level.FINEST) ) { + log.log(Level.FINEST, "startHostingOnConnection:{0}", hc); + } + RmiRegistry rmi = new RmiRegistry(hc, rpcService.getRpcConnection(hc), + rmiId, defaultChannel); + hc.setAttribute(ATTRIBUTE_NAME, rmi); + + // Register any global shares + for( Map.Entry e : globalShares.entrySet() ) { + GlobalShare share = e.getValue(); + rmi.share(share.channel, e.getKey(), share.object, share.type); + } + } + + /** + * Removes any RMI hosting services associated with the specified + * connection. Calls to getRmiRegistry() will return null for + * this connection. + * This method is called automatically for all leaving connections if + * autohost is set to true. + */ + public void stopHostingOnConnection( HostedConnection hc ) { + RmiRegistry rmi = hc.getAttribute(ATTRIBUTE_NAME); + if( rmi == null ) { + return; + } + if( log.isLoggable(Level.FINEST) ) { + log.log(Level.FINEST, "stopHostingOnConnection:{0}", hc); + } + hc.setAttribute(ATTRIBUTE_NAME, null); + //rpc.close(); + } + + @Override + protected void onInitialize( HostedServiceManager s ) { + this.rpcService = getService(RpcHostedService.class); + if( rpcService == null ) { + throw new RuntimeException("RmiHostedService requires RpcHostedService"); + } + } + + /** + * Called internally when a new connection is detected for + * the server. If the current autoHost property is true then + * startHostingOnConnection(hc) is called. + */ + @Override + public void connectionAdded(Server server, HostedConnection hc) { + if( log.isLoggable(Level.FINEST) ) { + log.log(Level.FINEST, "connectionAdded({0}, {1})", new Object[]{server, hc}); + } + if( autoHost ) { + startHostingOnConnection(hc); + } + } + + /** + * Called internally when an existing connection is leaving + * the server. If the current autoHost property is true then + * stopHostingOnConnection(hc) is called. + */ + @Override + public void connectionRemoved(Server server, HostedConnection hc) { + if( log.isLoggable(Level.FINEST) ) { + log.log(Level.FINEST, "connectionRemoved({0}, {1})", new Object[]{server, hc}); + } + if( autoHost ) { + stopHostingOnConnection(hc); + } + } + + private class GlobalShare { + byte channel; + Object object; + Class type; + + public GlobalShare( byte channel, Object object, Class type ) { + this.channel = channel; + this.object = object; + this.type = type; + } + } +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiRegistry.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiRegistry.java new file mode 100644 index 000000000..c04a8c7b3 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiRegistry.java @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2015 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.network.service.rmi; + +import com.jme3.network.HostedConnection; +import com.jme3.network.MessageConnection; +import com.jme3.network.service.rpc.RpcConnection; +import com.jme3.network.service.rpc.RpcHandler; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * + * + * @author Paul Speed + */ +public class RmiRegistry { + + static final Logger log = Logger.getLogger(RmiRegistry.class.getName()); + + // RPC IDs for calling our remote endpoint + private static final short NEW_CLASS = 0; + private static final short ADD_OBJECT = 1; + private static final short REMOVE_OBJECT = 2; + + private RpcConnection rpc; + private short rmiId; + private byte defaultChannel; + private final RmiHandler rmiHandler = new RmiHandler(); + private final ClassInfoRegistry classCache = new ClassInfoRegistry(); + private final AtomicInteger nextObjectId = new AtomicInteger(); + + private final ObjectIndex local = new ObjectIndex(); + private final ObjectIndex remote = new ObjectIndex(); + + // Only used on the server to provide thread-local context for + // local RMI calls. + private HostedConnection context; + + public RmiRegistry( RpcConnection rpc, short rmiId, byte defaultChannel ) { + this(null, rpc, rmiId, defaultChannel); + } + + public RmiRegistry( HostedConnection context, RpcConnection rpc, short rmiId, byte defaultChannel ) { + this.context = context; + this.rpc = rpc; + this.rmiId = rmiId; + this.defaultChannel = defaultChannel; + rpc.registerHandler(rmiId, rmiHandler); + } + + /** + * Exposes the specified object to the other end of the connection as + * the specified interface type. The object can be looked up by type + * on the other end. + */ + public void share( T object, Class type ) { + share(defaultChannel, object, type); + } + + /** + * Exposes, through a specific connection channel, the specified object + * to the other end of the connection as the specified interface type. + * The object can be looked up by type on the other end. + * The specified channel will be used for all network communication + * specific to this object. + */ + public void share( byte channel, T object, Class type ) { + share(channel, type.getName(), object, type); + } + + /** + * Exposes the specified object to the other end of the connection as + * the specified interface type and associates it with the specified name. + * The object can be looked up by the associated name on the other end of + * the connection. + */ + public void share( String name, T object, Class type ) { + share(defaultChannel, name, object, type); + } + + /** + * Exposes, through a specific connection channel, the specified object to + * the other end of the connection as the specified interface type and associates + * it with the specified name. + * The object can be looked up by the associated name on the other end of + * the connection. + * The specified channel will be used for all network communication + * specific to this object. + */ + public void share( byte channel, String name, T object, Class type ) { + + ClassInfo typeInfo = classCache.getClassInfo(type); + + local.lock.writeLock().lock(); + try { + + // First see if we've told the remote end about this class + // before + if( local.classes.put(typeInfo.getId(), typeInfo) == null ) { + // It's new + rpc.callAsync(defaultChannel, rmiId, NEW_CLASS, typeInfo); + + // Because type info IDs are global to the class cache, + // we could in theory keep a global index that we broadcast + // on first connection setup... we need only prepopulate + // the index in that case. + } + + // See if we already shared an object under that name + SharedObject existing = local.byName.remove(name); + if( existing != null ) { + local.byId.remove(existing.objectId); + rpc.removeHandler(existing.objectId, rmiHandler); + + // Need to delete the old one from the remote end + rpc.callAsync(defaultChannel, rmiId, REMOVE_OBJECT, existing.objectId); + + // We don't reuse the ID because it's kind of dangerous. + // Churning through a new ID is our safety net for accidents. + } + + SharedObject newShare = new SharedObject(name, object, type, typeInfo); + local.byName.put(name, newShare); + local.byId.put(newShare.objectId, newShare); + + // Make sure we are setup to receive the remote method calls through + // the RPC service + rpc.registerHandler(newShare.objectId, rmiHandler); + + // Let the other end know + rpc.callAsync(defaultChannel, rmiId, ADD_OBJECT, channel, newShare.objectId, name, typeInfo.getId()); + + // We send the ADD_OBJECT to the other end before releasing the + // lock to avoid a potential inconsistency if two threads try to + // jam the same name at the same time. Otherwise, if the timing were + // right, the remove for one object could get there before its add. + + } finally { + local.lock.writeLock().unlock(); + } + } + + /** + * Returns a local object that was previously registered with share() using + * just type registration. + */ + public T getLocalObject( Class type ) { + return getLocalObject(type.getName(), type); + } + + /** + * Returns a local object that was previously registered with share() using + * name registration. + */ + public T getLocalObject( String name, Class type ) { + local.lock.readLock().lock(); + try { + return type.cast(local.byName.get(name)); + } finally { + local.lock.readLock().unlock(); + } + } + + /** + * Looks up a remote object by type and returns a local proxy to the remote object + * that was shared on the other end of the network connection. If this is called + * from a client then it is accessing a shared object registered on the server. + * If this is called from the server then it is accessing a shared object registered + * on the client. + */ + public T getRemoteObject( Class type ) { + return getRemoteObject(type.getName(), type); + } + + /** + * Looks up a remote object by name and returns a local proxy to the remote object + * that was shared on the other end of the network connection. If this is called + * from a client then it is accessing a shared object registered on the server. + * If this is called from the server then it is accessing a shared object registered + * on the client. + */ + public T getRemoteObject( String name, Class type ) { + remote.lock.readLock().lock(); + try { + return type.cast(remote.byName.get(name)); + } finally { + remote.lock.readLock().unlock(); + } + } + + protected void addRemoteClass( ClassInfo info ) { + if( remote.classes.put(info.getId(), info) != null ) { + throw new RuntimeException("Error class already exists for ID:" + info.getId()); + } + } + + protected void removeRemoteObject( short objectId ) { + if( log.isLoggable(Level.FINEST) ) { + log.log(Level.FINEST, "removeRemoteObject({0})", objectId); + } + throw new UnsupportedOperationException("Removal not yet implemented."); + } + + protected void addRemoteObject( byte channel, short objectId, String name, ClassInfo typeInfo ) { + if( log.isLoggable(Level.FINEST) ) { + log.finest("addRemoveObject(" + objectId + ", " + name + ", " + typeInfo + ")"); + } + remote.lock.writeLock().lock(); + try { + Object existing = remote.byName.get(name); + if( existing != null ) { + throw new RuntimeException("Object already registered for:" + name); + } + + RemoteObjectHandler remoteHandler = new RemoteObjectHandler(this, channel, objectId, typeInfo); + + Object remoteObject = Proxy.newProxyInstance(getClass().getClassLoader(), + new Class[] {typeInfo.getType()}, + remoteHandler); + + remote.byName.put(name, remoteObject); + remote.byId.put(objectId, remoteObject); + } finally { + remote.lock.writeLock().unlock(); + } + } + + protected Object invokeRemote( byte channel, short objectId, short procId, CallType callType, Object[] args ) { + if( log.isLoggable(Level.FINEST) ) { + log.finest("invokeRemote(" + channel + ", " + objectId + ", " + procId + ", " + + callType + ", " + (args == null ? "null" : Arrays.asList(args)) + ")"); + } + switch( callType ) { + case Asynchronous: + log.finest("Sending reliable asynchronous."); + rpc.callAsync(channel, objectId, procId, args); + return null; + case Unreliable: + log.finest("Sending unreliable asynchronous."); + rpc.callAsync((byte)MessageConnection.CHANNEL_DEFAULT_UNRELIABLE, objectId, procId, args); + return null; + default: + case Synchronous: + log.finest("Sending synchronous."); + Object result = rpc.callAndWait(channel, objectId, procId, args); + if( log.isLoggable(Level.FINEST) ) { + log.finest("->got:" + result); + } + return result; + } + } + + /** + * Handle remote object registry updates from the other end. + */ + protected void rmiUpdate( short procId, Object[] args ) { + if( log.isLoggable(Level.FINEST) ) { + log.finest("rmiUpdate(" + procId + ", " + Arrays.asList(args) + ")"); + } + switch( procId ) { + case NEW_CLASS: + addRemoteClass((ClassInfo)args[0]); + break; + case REMOVE_OBJECT: + removeRemoteObject((Short)args[0]); + break; + case ADD_OBJECT: + ClassInfo info = remote.classes.get((Short)args[3]); + addRemoteObject((Byte)args[0], (Short)args[1], (String)args[2], info); + break; + } + } + + /** + * Handle the actual remote object method calls. + */ + protected Object invokeLocal( short objectId, short procId, Object[] args ) { + // Actually could use a regular concurrent map for this + + // Only lock the local registry during lookup and + // not invocation. It prevents a deadlock if the invoked method + // tries to share an object. It should be safe. + SharedObject share = local.byId.get(objectId); + local.lock.readLock().lock(); + try { + share = local.byId.get(objectId); + } finally { + local.lock.readLock().unlock(); + } + + try { + RmiContext.setRmiConnection(context); + return share.invoke(procId, args); + } finally { + RmiContext.setRmiConnection(null); + } + } + + private class SharedObject { + private final short objectId; + private final String name; + private final Object object; + private final Class type; + private final ClassInfo classInfo; + + public SharedObject( String name, Object object, Class type, ClassInfo classInfo ) { + this.objectId = (short)nextObjectId.incrementAndGet(); + this.name = name; + this.object = object; + this.type = type; + this.classInfo = classInfo; + } + + public Object invoke( short procId, Object[] args ) { + return classInfo.getMethod(procId).invoke(object, args); + } + } + + private class RmiHandler implements RpcHandler { + @Override + public Object call( RpcConnection conn, short objectId, short procId, Object... args ) { + if( objectId == rmiId ) { + rmiUpdate(procId, args); + return null; + } else { + return invokeLocal(objectId, procId, args); + } + } + } + + /** + * Keeps a coincident index between short ID, name, and related class info. + * There will be one of these to track our local objects and one to track + * the remote objects and a lock that can guard them. + */ + private class ObjectIndex { + final Map byName = new HashMap(); + final Map byId = new HashMap(); + final Map classes = new HashMap(); + final ReadWriteLock lock = new ReentrantReadWriteLock(); + + public ObjectIndex() { + } + } + +} + + diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rpc/msg/RpcResponseMessage.java b/jme3-networking/src/main/java/com/jme3/network/service/rpc/msg/RpcResponseMessage.java index efb0def6a..c8ca8083a 100644 --- a/jme3-networking/src/main/java/com/jme3/network/service/rpc/msg/RpcResponseMessage.java +++ b/jme3-networking/src/main/java/com/jme3/network/service/rpc/msg/RpcResponseMessage.java @@ -84,6 +84,7 @@ public class RpcResponseMessage extends AbstractMessage { @Override public String toString() { return getClass().getSimpleName() + "[#" + msgId + ", result=" + result + + (error != null ? ", error=" + error : "") + "]"; } } diff --git a/jme3-networking/src/main/java/com/jme3/network/service/serializer/ClientSerializerRegistrationsService.java b/jme3-networking/src/main/java/com/jme3/network/service/serializer/ClientSerializerRegistrationsService.java index 911ce0fb1..61632282a 100644 --- a/jme3-networking/src/main/java/com/jme3/network/service/serializer/ClientSerializerRegistrationsService.java +++ b/jme3-networking/src/main/java/com/jme3/network/service/serializer/ClientSerializerRegistrationsService.java @@ -39,6 +39,8 @@ import com.jme3.network.message.SerializerRegistrationsMessage; import com.jme3.network.serializing.Serializer; import com.jme3.network.service.AbstractClientService; import com.jme3.network.service.ClientServiceManager; +import java.util.logging.Level; +import java.util.logging.Logger; /** @@ -48,19 +50,27 @@ import com.jme3.network.service.ClientServiceManager; */ public class ClientSerializerRegistrationsService extends AbstractClientService implements MessageListener { + + static final Logger log = Logger.getLogger(SerializerRegistrationsMessage.class.getName()); @Override protected void onInitialize( ClientServiceManager serviceManager ) { - // Make sure our message type is registered - // This is the minimum we'd need just to be able to register - // the rest... otherwise we can't even receive this message. - Serializer.registerClass(SerializerRegistrationsMessage.class); - Serializer.registerClass(SerializerRegistrationsMessage.Registration.class); + + // Make sure our message type is registered if it isn't already + if( Serializer.getExactSerializerRegistration(SerializerRegistrationsMessage.class) == null ) { + // This is the minimum we'd need just to be able to register + // the rest... otherwise we can't even receive this message. + Serializer.registerClass(SerializerRegistrationsMessage.class); + Serializer.registerClass(SerializerRegistrationsMessage.Registration.class); + } else { + log.log(Level.INFO, "Skipping registration of SerializerRegistrationsMessage."); + } // Add our listener for that message type serviceManager.getClient().addMessageListener(this, SerializerRegistrationsMessage.class); } + @Override public void messageReceived( Client source, Message m ) { // We only wait for one kind of message... SerializerRegistrationsMessage msg = (SerializerRegistrationsMessage)m; diff --git a/jme3-niftygui/build.gradle b/jme3-niftygui/build.gradle index abe25f6e4..fe4f46462 100644 --- a/jme3-niftygui/build.gradle +++ b/jme3-niftygui/build.gradle @@ -14,3 +14,16 @@ dependencies { compile 'lessvoid:nifty-default-controls:1.4.1' compile 'lessvoid:nifty-style-black:1.4.1' } + +uploadArchives { + repositories.mavenDeployer { + pom.project { + repositories { + repository { + id "nifty-maven-repo.sourceforge.net" + url "http://nifty-gui.sourceforge.net/nifty-maven-repo" + } + } + } + } +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall.j3m b/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall.j3m index 8b54f9e39..41af10431 100644 --- a/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall.j3m +++ b/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall.j3m @@ -1,8 +1,7 @@ Material Pong Rock : Common/MatDefs/Light/Lighting.j3md { MaterialParameters { Shininess: 2.0 - DiffuseMap : Textures/Terrain/BrickWall/BrickWall.jpg - NormalMap : Textures/Terrain/BrickWall/BrickWall_normal.jpg - ParallaxMap : Textures/Terrain/BrickWall/BrickWall_height.jpg + DiffuseMap : Repeat Textures/Terrain/BrickWall/BrickWall.jpg + ParallaxMap : Repeat Textures/Terrain/BrickWall/BrickWall_height.jpg } } \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall2.j3m b/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall2.j3m index 7db3ab893..8f90a9454 100644 --- a/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall2.j3m +++ b/jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWall2.j3m @@ -1,8 +1,8 @@ Material Pong Rock : Common/MatDefs/Light/Lighting.j3md { MaterialParameters { Shininess: 2.0 - DiffuseMap : Textures/Terrain/BrickWall/BrickWall.jpg - NormalMap : Textures/Terrain/BrickWall/BrickWall_normal_parallax.dds + DiffuseMap : Repeat Textures/Terrain/BrickWall/BrickWall.jpg + NormalMap : Repeat Textures/Terrain/BrickWall/BrickWall_normal_parallax.dds PackedNormalParallax: true } } \ No newline at end of file diff --git a/private/known_hosts b/private/known_hosts new file mode 100644 index 000000000..fdc45836f --- /dev/null +++ b/private/known_hosts @@ -0,0 +1 @@ +updates.jmonkeyengine.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5bNOiZwU5dF62nBllxkjiSIfn0k6RVfprvO1aUypRmARD3/MKJKg7cGLezlLKaHZtVs84VpEqpmg5IzPAXWEmxUw1oke70uYMli7JV+4oPAeQRFwUdldP98I5h9VHwSjBqMycRLkxYaHF8edIPt1Zsa2dM3qrufy71ndQoFF6g7QxmT7gsTxwcNufDxymIgiAna/Qp2fr0YCLCiB8RQ7JTHfqA3dOWw0wz7AwfBTwwDCHkVxB5B4nz5iZxFr0scvqcae8vMncq8xKS7OMrLbn6asVaF6dDu+5Jc0mqxma5Qg7VC1xQXZsvlRISfrTFhQMhEx+j9w5snzihrlFnZ35 diff --git a/private/www-updater.key.enc b/private/www-updater.key.enc new file mode 100644 index 000000000..63dcb3723 Binary files /dev/null and b/private/www-updater.key.enc differ diff --git a/sdk/BasicGameTemplate/nbproject/project.properties b/sdk/BasicGameTemplate/nbproject/project.properties index ac4b3d2a6..8f2414b51 100644 --- a/sdk/BasicGameTemplate/nbproject/project.properties +++ b/sdk/BasicGameTemplate/nbproject/project.properties @@ -50,8 +50,8 @@ javac.compilerargs= javac.deprecation=false javac.processorpath=\ ${javac.classpath} -javac.source=1.5 -javac.target=1.5 +javac.source=1.6 +javac.target=1.6 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/sdk/JME3TestsTemplate/build.xml b/sdk/JME3TestsTemplate/build.xml index c1f098b99..d39b505e6 100644 --- a/sdk/JME3TestsTemplate/build.xml +++ b/sdk/JME3TestsTemplate/build.xml @@ -51,8 +51,7 @@ -init-macrodef-junit: defines macro for junit execution -init-macrodef-debug: defines macro for class debugging -init-macrodef-java: defines macro for class execution - -do-jar-with-manifest: JAR building (if you are using a manifest) - -do-jar-without-manifest: JAR building (if you are not using a manifest) + -do-jar: JAR building run: execution of project -javadoc-build: Javadoc generation test-report: JUnit report generation diff --git a/sdk/JME3TestsTemplate/nbproject/genfiles.properties b/sdk/JME3TestsTemplate/nbproject/genfiles.properties index 6fb0f140e..eca6dafb7 100644 --- a/sdk/JME3TestsTemplate/nbproject/genfiles.properties +++ b/sdk/JME3TestsTemplate/nbproject/genfiles.properties @@ -1,8 +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=46d1a69a -nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45 +build.xml.data.CRC32=0f706f4a +build.xml.script.CRC32=82b8b23d +build.xml.stylesheet.CRC32=8064a381@1.75.2.48 +# 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=46d1a69a +nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45 diff --git a/sdk/JME3TestsTemplate/nbproject/project.properties b/sdk/JME3TestsTemplate/nbproject/project.properties index 2a8d46f22..489a9c7d9 100644 --- a/sdk/JME3TestsTemplate/nbproject/project.properties +++ b/sdk/JME3TestsTemplate/nbproject/project.properties @@ -25,20 +25,26 @@ excludes= includes=** jar.compress=false javac.classpath=\ - ${libs.jme3.classpath}:\ - ${libs.jme3-libraries.classpath}:\ - ${libs.jme3-libraries-blender.classpath}:\ + ${libs.jme3-jogg.classpath}:\ + ${libs.jme3-blender.classpath}:\ + ${libs.jme3-networking.classpath}:\ + ${libs.jme3-plugins.classpath}:\ + ${libs.jme3-core.classpath}:\ + ${libs.jme3-desktop.classpath}:\ + ${libs.jme3-lwjgl.classpath}:\ + ${libs.jme3-niftygui.classpath}:\ + ${libs.jme3-effects.classpath}:\ + ${libs.jme3-terrain.classpath}:\ + ${libs.jme3-jbullet.classpath}:\ ${libs.jme3-test-data.classpath} # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=false -javac.source=1.5 -javac.target=1.5 +javac.source=1.6 +javac.target=1.6 javac.test.classpath=\ ${javac.classpath}:\ - ${build.classes.dir}:\ - ${libs.junit.classpath}:\ - ${libs.junit_4.classpath} + ${build.classes.dir} javadoc.additionalparam= javadoc.author=false javadoc.encoding=${source.encoding} diff --git a/sdk/JME3TestsTemplateAndroid/nbproject/project.properties b/sdk/JME3TestsTemplateAndroid/nbproject/project.properties index e3a940489..f020f7d80 100644 --- a/sdk/JME3TestsTemplateAndroid/nbproject/project.properties +++ b/sdk/JME3TestsTemplateAndroid/nbproject/project.properties @@ -47,8 +47,8 @@ javac.compilerargs= javac.deprecation=false javac.processorpath=\ ${javac.classpath} -javac.source=1.5 -javac.target=1.5 +javac.source=1.6 +javac.target=1.6 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/sdk/ant-jme/nbproject/project.properties b/sdk/ant-jme/nbproject/project.properties index 80281cc3b..3a1490871 100644 --- a/sdk/ant-jme/nbproject/project.properties +++ b/sdk/ant-jme/nbproject/project.properties @@ -36,8 +36,8 @@ javac.compilerargs= javac.deprecation=false javac.processorpath=\ ${javac.classpath} -javac.source=1.5 -javac.target=1.5 +javac.source=1.6 +javac.target=1.6 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/sdk/build.gradle b/sdk/build.gradle index b70e80b13..99c850987 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -165,7 +165,7 @@ task createBaseXml(dependsOn: configurations.corelibs) <<{ "compile-dependency"{} "run-dependency"{ "release-version" "1" - "specification-version" "3.0.0" + "specification-version" jmeVersion } } } @@ -388,12 +388,14 @@ copyTestSources.outputs.dir "JME3TestsTemplate/src/" copyTestSources.outputs.dir "JME3TestsTemplateAndroid/src/" ant.properties['plugins.version'] = jmeVersion -ant.properties['app.version']= jmeMainVersion + "-" + jmeVersionTag +ant.properties['app.version']= jmeFullVersion +ant.properties['nbm.revision']= jmeNbmRevision task buildSdk(dependsOn: [copyBaseLibs, copyProjectLibs, createProjectXml, createBaseXml, copyTestSources]) <<{ ant.propertyfile(file: "nbproject/project.properties") { entry( key: "plugins.version", value: "${jmeVersion}") - entry( key: "app.version", value: "${jmeMainVersion + "-" + jmeVersionTag}") + entry( key: "app.version", value: "${jmeFullVersion}") + entry( key: "nbm.revision", value: "${jmeNbmRevision}") } ant.ant(dir: ".", antfile: "build.xml", target: "build") } @@ -416,7 +418,7 @@ task cleanSdk() <<{ file("JME3TestsTemplateAndroid/src/jmetest/").deleteDir() } -jar.dependsOn(buildSdk) -clean.dependsOn(cleanSdk); - +tasks.remove(uploadArchives) +jar.dependsOn(buildSdk) +clean.dependsOn(cleanSdk) diff --git a/sdk/build.xml b/sdk/build.xml index acc5c1d04..ffa0b8fe8 100644 --- a/sdk/build.xml +++ b/sdk/build.xml @@ -12,7 +12,6 @@ - @@ -157,7 +156,7 @@ replace="OpenIDE-Module-Specification-Version: ${plugins.version}" byline="true"/> @@ -167,7 +166,7 @@ replace="OpenIDE-Module-Implementation-Version: 0" byline="true"/> @@ -176,9 +175,6 @@ - - - @@ -191,105 +187,19 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Setting implementation version for ${module_dir} to revision: ${svn.LastChangedRev} - + Setting implementation version for ${module_dir} to revision: ${nbm.revision} + - Removing implementation version for ${module_dir} from revision: ${svn.LastChangedRev} - + Removing implementation version for ${module_dir} from revision: ${nbm.revision} + - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -298,7 +208,7 @@ - + @@ -311,6 +221,8 @@ + + @@ -339,7 +251,7 @@ section="devel" depends="sun-java6-jdk" maintainer="jMonkeyEngine" - homepage="http://www.jmonkeyengine.com" + homepage="http://www.jmonkeyengine.org" postrm="debscripts/postrm" > @@ -360,57 +272,4 @@ - - - - Upload windows installers to googlecode.. - - - Upload linux installers to googlecode.. - - - Upload mac installer to googlecode.. - - - - - - - - diff --git a/sdk/jdks/build-osx-zip.sh b/sdk/jdks/build-osx-zip.sh index cf1051901..db3c44e99 100755 --- a/sdk/jdks/build-osx-zip.sh +++ b/sdk/jdks/build-osx-zip.sh @@ -1,5 +1,5 @@ #!/bin/sh -#(c) jMonkeyEngine.com +#(c) jmonkeyengine.org #Author Normen Hansen set -e rm -rf jdk-macosx.zip diff --git a/sdk/jdks/build-package.sh b/sdk/jdks/build-package.sh index c11a8ff2f..6f9c53503 100755 --- a/sdk/jdks/build-package.sh +++ b/sdk/jdks/build-package.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e -#(c) jMonkeyEngine.com +#(c) jmonkeyengine.org #This script creates SFX binaries of the JDK for the specified platform #Author Normen Hansen diff --git a/sdk/jme3-android/nbproject/project.properties b/sdk/jme3-android/nbproject/project.properties index e2ab10b96..9b1b7cb61 100644 --- a/sdk/jme3-android/nbproject/project.properties +++ b/sdk/jme3-android/nbproject/project.properties @@ -3,7 +3,7 @@ javac.source=1.6 javac.compilerargs=-Xlint -Xlint:-serial license.file=../license-jme.txt -nbm.homepage=http://www.jmonkeyengine.com +nbm.homepage=http://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-angelfont/nbproject/project.properties b/sdk/jme3-angelfont/nbproject/project.properties index 44c34ecb9..2cf7a410b 100644 --- a/sdk/jme3-angelfont/nbproject/project.properties +++ b/sdk/jme3-angelfont/nbproject/project.properties @@ -1,4 +1,6 @@ #Thu, 25 Aug 2011 20:26:50 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial +nbm.homepage=http\://www.jmonkeyengine.org +nbm.module.author=Normen Hansen spec.version.base=3.1.0 diff --git a/sdk/jme3-assetpack-support/nbproject/project.properties b/sdk/jme3-assetpack-support/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-assetpack-support/nbproject/project.properties +++ b/sdk/jme3-assetpack-support/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-blender/nbproject/project.properties b/sdk/jme3-blender/nbproject/project.properties index 33a6b9205..b47098087 100644 --- a/sdk/jme3-blender/nbproject/project.properties +++ b/sdk/jme3-blender/nbproject/project.properties @@ -1,7 +1,8 @@ #Thu, 25 Aug 2011 20:26:50 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial -nbm.homepage=http\://www.jmonkeyengine.com +license.file=../license-jme.txt +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Kaelthas nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-blender/src/com/jme3/gde/blender/BlenderTool.java b/sdk/jme3-blender/src/com/jme3/gde/blender/BlenderTool.java index 0211cae7a..1d55a6b35 100644 --- a/sdk/jme3-blender/src/com/jme3/gde/blender/BlenderTool.java +++ b/sdk/jme3-blender/src/com/jme3/gde/blender/BlenderTool.java @@ -164,6 +164,14 @@ public class BlenderTool { return "../blender"; } } + + private static String getBlenderOsSettingsPath() { + if (Utilities.isMac()) { + return "../blender/blender.app/Contents/Resources"; + } else { + return "../blender"; + } + } private static boolean checkBlenderFolders() { String jmpDir = Places.getUserDirectory().getAbsolutePath(); @@ -251,9 +259,9 @@ public class BlenderTool { } private static File getBlenderSettingsFolder() { - File blender = InstalledFileLocator.getDefault().locate(getBlenderOsPath() + "/2.69", null, false); + File blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.75", null, false); if (blender == null) { - blender = InstalledFileLocator.getDefault().locate(getBlenderOsPath() + "/2.67", null, false); + blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.69", null, false); } if (blender == null) { DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender settings")); diff --git a/sdk/jme3-cinematics/nbproject/project.properties b/sdk/jme3-cinematics/nbproject/project.properties index 437a62d3a..4b4ae0191 100644 --- a/sdk/jme3-cinematics/nbproject/project.properties +++ b/sdk/jme3-cinematics/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:50 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=R\u00e9my Bouquet nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-code-check/nbproject/project.properties b/sdk/jme3-code-check/nbproject/project.properties index 0411b6ff9..6700898e0 100644 --- a/sdk/jme3-code-check/nbproject/project.properties +++ b/sdk/jme3-code-check/nbproject/project.properties @@ -1,4 +1,7 @@ #Thu, 25 Aug 2011 20:26:50 +0200 javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial +license.file=../license-jme.txt +nbm.homepage=http\://www.jmonkeyengine.org +nbm.module.author=Normen Hansen spec.version.base=3.1.0 diff --git a/sdk/jme3-codepalette/nbproject/project.properties b/sdk/jme3-codepalette/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-codepalette/nbproject/project.properties +++ b/sdk/jme3-codepalette/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-core-baselibs/nbproject/genfiles.properties b/sdk/jme3-core-baselibs/nbproject/genfiles.properties index 1b1c32b3b..c9714ad4e 100644 --- a/sdk/jme3-core-baselibs/nbproject/genfiles.properties +++ b/sdk/jme3-core-baselibs/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=278ea45d +build.xml.data.CRC32=d43b0890 build.xml.script.CRC32=cdae6a36 build.xml.stylesheet.CRC32=a56c6a5b@2.67.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=278ea45d +nbproject/build-impl.xml.data.CRC32=d43b0890 nbproject/build-impl.xml.script.CRC32=246f9b81 nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1 diff --git a/sdk/jme3-core-baselibs/nbproject/project.properties b/sdk/jme3-core-baselibs/nbproject/project.properties index 8bcd2222a..d4692bc80 100644 --- a/sdk/jme3-core-baselibs/nbproject/project.properties +++ b/sdk/jme3-core-baselibs/nbproject/project.properties @@ -1,7 +1,7 @@ -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=jMonkeyEngine nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-core-baselibs/nbproject/project.xml b/sdk/jme3-core-baselibs/nbproject/project.xml index df81e68ff..be7a3e038 100644 --- a/sdk/jme3-core-baselibs/nbproject/project.xml +++ b/sdk/jme3-core-baselibs/nbproject/project.xml @@ -1,15 +1,15 @@ - - + + org.netbeans.modules.apisupport.project - + com.jme3.gde.core.baselibs - + com.jme3.gde.core.libraries - - + + 1 3.1.0 @@ -19,133 +19,142 @@ com.jme3.asset com.jme3.scene.plugins.blender - com.jme3.scene.plugins.blender.animations - com.jme3.scene.plugins.blender.cameras + com.jme3.scene.plugins.blender.math com.jme3.scene.plugins.blender.constraints com.jme3.scene.plugins.blender.constraints.definitions com.jme3.scene.plugins.blender.curves - com.jme3.scene.plugins.blender.file - com.jme3.scene.plugins.blender.landscape - com.jme3.scene.plugins.blender.lights - com.jme3.scene.plugins.blender.materials - com.jme3.scene.plugins.blender.math com.jme3.scene.plugins.blender.meshes - com.jme3.scene.plugins.blender.modifiers - com.jme3.scene.plugins.blender.objects com.jme3.scene.plugins.blender.particles + com.jme3.scene.plugins.blender.cameras + com.jme3.scene.plugins.blender.objects + com.jme3.scene.plugins.blender.landscape + com.jme3.scene.plugins.blender.modifiers com.jme3.scene.plugins.blender.textures + com.jme3.scene.plugins.blender.textures.io com.jme3.scene.plugins.blender.textures.blending com.jme3.scene.plugins.blender.textures.generating - com.jme3.scene.plugins.blender.textures.io - checkers.quals - com.jme3.animation - com.jme3.app - com.jme3.app.state - com.jme3.asset.cache - com.jme3.asset.plugins - com.jme3.audio - com.jme3.audio.openal - com.jme3.audio.plugins - com.jme3.bounding - com.jme3.cinematic - com.jme3.cinematic.events - com.jme3.collision - com.jme3.collision.bih - com.jme3.cursors.plugins - com.jme3.effect - com.jme3.effect.influencers - com.jme3.effect.shapes + com.jme3.scene.plugins.blender.animations + com.jme3.scene.plugins.blender.materials + com.jme3.scene.plugins.blender.file + com.jme3.scene.plugins.blender.lights + jme3tools.shader + jme3tools.savegame + jme3tools.shadercheck + jme3tools.optimize + jme3tools.converters + com.jme3.shader + com.jme3.shader.plugins com.jme3.export com.jme3.export.binary - com.jme3.font - com.jme3.font.plugins + com.jme3.cinematic + com.jme3.cinematic.events + com.jme3.math + com.jme3.util + com.jme3.util.blockparser + com.jme3.util.xml + com.jme3.post com.jme3.input - com.jme3.input.controls com.jme3.input.dummy + com.jme3.input.controls com.jme3.input.event - com.jme3.light + com.jme3.profile + com.jme3.ui + com.jme3.audio + com.jme3.audio.openal + com.jme3.audio.plugins + com.jme3.cursors.plugins + com.jme3.bounding + com.jme3.shadow + com.jme3.texture + com.jme3.texture.image + com.jme3.texture.plugins + com.jme3.system com.jme3.material com.jme3.material.plugins - com.jme3.math - com.jme3.post - com.jme3.profile com.jme3.renderer - com.jme3.renderer.opengl com.jme3.renderer.queue + com.jme3.renderer.opengl + com.jme3.effect + com.jme3.effect.shapes + com.jme3.effect.influencers + com.jme3.app + com.jme3.app.state + com.jme3.asset.plugins + com.jme3.asset.cache + com.jme3.light + com.jme3.animation + com.jme3.collision + com.jme3.collision.bih com.jme3.scene - com.jme3.scene.control + com.jme3.scene.shape + com.jme3.scene.plugins com.jme3.scene.debug com.jme3.scene.instancing + com.jme3.scene.control com.jme3.scene.mesh - com.jme3.scene.plugins - com.jme3.scene.shape - com.jme3.shader - com.jme3.shader.plugins - com.jme3.shadow - com.jme3.system - com.jme3.texture - com.jme3.texture.image - com.jme3.texture.plugins - com.jme3.ui - com.jme3.util - com.jme3.util.blockparser - com.jme3.util.xml - jme3tools.converters - jme3tools.converters.model - jme3tools.converters.model.strip - jme3tools.optimize - jme3tools.savegame - jme3tools.shader - jme3tools.shadercheck + com.jme3.font + com.jme3.font.plugins + checkers.quals + jme3tools.navigation com.jme3.input.awt com.jme3.system.awt - jme3tools.navigation - com.jme3.post.filters com.jme3.post.ssao + com.jme3.post.filters com.jme3.water 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.control.ragdoll - com.jme3.bullet.debug + com.jme3.bullet.util com.jme3.bullet.joints com.jme3.bullet.joints.motors com.jme3.bullet.objects com.jme3.bullet.objects.infos - com.jme3.bullet.util - com.jme3.audio.lwjgl + com.jme3.bullet.debug + com.jme3.bullet.control + com.jme3.bullet.control.ragdoll + com.jme3.bullet.collision + com.jme3.bullet.collision.shapes + com.jme3.bullet.collision.shapes.infos com.jme3.input.lwjgl - com.jme3.renderer.lwjgl + com.jme3.audio.lwjgl com.jme3.system.lwjgl + com.jme3.renderer.lwjgl com.jme3.network - com.jme3.network.base com.jme3.network.kernel - com.jme3.network.kernel.tcp com.jme3.network.kernel.udp + com.jme3.network.kernel.tcp + com.jme3.network.util com.jme3.network.message com.jme3.network.rmi + com.jme3.network.base com.jme3.network.serializing com.jme3.network.serializing.serializers + com.jme3.network.service + com.jme3.network.service.rpc + com.jme3.network.service.rpc.msg + com.jme3.network.service.serializer com.jme3.niftygui com.jme3.export.xml com.jme3.scene.plugins.fbx + com.jme3.scene.plugins.fbx.obj + com.jme3.scene.plugins.fbx.anim + com.jme3.scene.plugins.fbx.node + com.jme3.scene.plugins.fbx.misc + com.jme3.scene.plugins.fbx.material com.jme3.scene.plugins.fbx.file + com.jme3.scene.plugins.fbx.mesh com.jme3.scene.plugins.ogre com.jme3.scene.plugins.ogre.matext com.jme3.terrain + com.jme3.terrain.heightmap com.jme3.terrain.geomipmap + com.jme3.terrain.geomipmap.picking com.jme3.terrain.geomipmap.grid com.jme3.terrain.geomipmap.lodcalc com.jme3.terrain.geomipmap.lodcalc.util - com.jme3.terrain.geomipmap.picking - com.jme3.terrain.heightmap com.jme3.terrain.noise - com.jme3.terrain.noise.basis com.jme3.terrain.noise.filter - com.jme3.terrain.noise.fractal com.jme3.terrain.noise.modulator + com.jme3.terrain.noise.fractal + com.jme3.terrain.noise.basis ext/jme3-blender-3.1.0-snapshot-github.jar @@ -193,4 +202,4 @@ - + \ No newline at end of file diff --git a/sdk/jme3-core-libraries/nbproject/project.properties b/sdk/jme3-core-libraries/nbproject/project.properties index 2e01f5d86..513fb20e4 100644 --- a/sdk/jme3-core-libraries/nbproject/project.properties +++ b/sdk/jme3-core-libraries/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:48 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=jMonkeyEngine nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-core-libraries/nbproject/project.xml b/sdk/jme3-core-libraries/nbproject/project.xml index 19469cf8a..c7b1f70f9 100644 --- a/sdk/jme3-core-libraries/nbproject/project.xml +++ b/sdk/jme3-core-libraries/nbproject/project.xml @@ -6,6 +6,44 @@ + org.ejml + org.ejml.interfaces.decomposition + org.ejml.interfaces.linsol + org.ejml.data + org.ejml.alg.dense.linsol + org.ejml.ops + org.ejml.factory + org.ejml.alg.fixed + org.ejml.alg.generic + org.ejml.alg.block + org.ejml.alg.block.decomposition.chol + org.ejml.alg.block.decomposition.qr + org.ejml.alg.block.decomposition.hessenberg + org.ejml.alg.block.decomposition.bidiagonal + org.ejml.alg.block.linsol.chol + org.ejml.alg.block.linsol.qr + org.ejml.alg.dense.decomposition + org.ejml.alg.dense.decomposition.chol + org.ejml.alg.dense.decomposition.lu + org.ejml.alg.dense.decomposition.qr + org.ejml.alg.dense.decomposition.hessenberg + org.ejml.alg.dense.decomposition.svd + org.ejml.alg.dense.decomposition.svd.implicitqr + org.ejml.alg.dense.decomposition.eig + org.ejml.alg.dense.decomposition.eig.watched + org.ejml.alg.dense.decomposition.eig.symm + org.ejml.alg.dense.decomposition.bidiagonal + org.ejml.alg.dense.mult + org.ejml.alg.dense.misc + org.ejml.alg.dense.linsol.chol + org.ejml.alg.dense.linsol.lu + org.ejml.alg.dense.linsol.qr + org.ejml.alg.dense.linsol.svd + org.ejml.simple + org.ejml.alg.dense.decompose + org.ejml.alg.dense.decompose.chol + org.ejml.alg.dense.decompose.lu + org.ejml.alg.dense.decompose.qr com.bulletphysics com.bulletphysics.collision.broadphase com.bulletphysics.collision.dispatch @@ -161,6 +199,22 @@ org.jglfont.impl.format.awt org.jglfont.impl + + ext/core-0.27.jar + release/modules/ext/core-0.27.jar + + + ext/dense64-0.27.jar + release/modules/ext/dense64-0.27.jar + + + ext/simple-0.27.jar + release/modules/ext/simple-0.27.jar + + + ext/denseC64-0.27.jar + release/modules/ext/denseC64-0.27.jar + ext/jbullet.jar release/modules/ext/jbullet.jar diff --git a/sdk/jme3-core-updatecenters/nbproject/genfiles.properties b/sdk/jme3-core-updatecenters/nbproject/genfiles.properties index 0dd897993..6b53da996 100644 --- a/sdk/jme3-core-updatecenters/nbproject/genfiles.properties +++ b/sdk/jme3-core-updatecenters/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=08468784 +build.xml.data.CRC32=e145fa2a build.xml.script.CRC32=cfa8d5c5 build.xml.stylesheet.CRC32=a56c6a5b@2.67.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=08468784 +nbproject/build-impl.xml.data.CRC32=e145fa2a nbproject/build-impl.xml.script.CRC32=270846fb nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1 diff --git a/sdk/jme3-core-updatecenters/nbproject/project.properties b/sdk/jme3-core-updatecenters/nbproject/project.properties index 9d2616783..98f519f77 100644 --- a/sdk/jme3-core-updatecenters/nbproject/project.properties +++ b/sdk/jme3-core-updatecenters/nbproject/project.properties @@ -1,4 +1,4 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial spec.version.base=3.1.0 diff --git a/sdk/jme3-core-updatecenters/nbproject/project.xml b/sdk/jme3-core-updatecenters/nbproject/project.xml index 3979d8b02..abc894aed 100644 --- a/sdk/jme3-core-updatecenters/nbproject/project.xml +++ b/sdk/jme3-core-updatecenters/nbproject/project.xml @@ -8,6 +8,8 @@ org.netbeans.modules.autoupdate.services + + 1.47.2 diff --git a/sdk/jme3-core-updatecenters/src/META-INF/services/org.netbeans.spi.autoupdate.KeyStoreProvider b/sdk/jme3-core-updatecenters/src/META-INF/services/org.netbeans.spi.autoupdate.KeyStoreProvider new file mode 100644 index 000000000..1af1a906c --- /dev/null +++ b/sdk/jme3-core-updatecenters/src/META-INF/services/org.netbeans.spi.autoupdate.KeyStoreProvider @@ -0,0 +1 @@ +com.jme3.gde.core.updatecenters.keystore.JmeKeyStoreProvider 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 index 5a898643f..eb84743c9 100644 --- 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 @@ -1,7 +1,7 @@ #jMP update centers -com_jme3_gde_core_update_center_nightly=http://updates.jmonkeyengine.org/nightly/3.0/plugins/updates.xml -com_jme3_gde_core_update_center_stable=http://updates.jmonkeyengine.org/stable/3.0/plugins/updates.xml -com_jme3_jmp_contributions_update_center=http://updates.jmonkeyengine.org/contributions/updates.xml +com_jme3_gde_core_update_center_nightly=http://updates.jmonkeyengine.org/nightly/3.1/plugins/updates.xml +com_jme3_gde_core_update_center_stable=http://updates.jmonkeyengine.org/stable/3.1/plugins/updates.xml +com_jme3_jmp_contributions_update_center=http://updates.jmonkeyengine.org/contrib/3.1/updates.xml #jMP update centers Services/AutoupdateType/com_jme3_gde_core_update_center_nightly.instance=jMonkeyEngine SDK Nightly (Breaks!) diff --git a/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/JmeKeyStoreProvider.java b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/JmeKeyStoreProvider.java new file mode 100644 index 000000000..d94e548bd --- /dev/null +++ b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/JmeKeyStoreProvider.java @@ -0,0 +1,47 @@ +package com.jme3.gde.core.updatecenters.keystore; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import org.netbeans.spi.autoupdate.KeyStoreProvider; +import org.openide.util.Exceptions; + +/** + * Loads the jMonkeyEngine SDK Plugins certificates into the AutoUpdate system. + * + * @author Kirill Vainer + */ +public class JmeKeyStoreProvider implements KeyStoreProvider { + + @Override + public KeyStore getKeyStore() { + InputStream in = null; + try { + in = JmeKeyStoreProvider.class.getResourceAsStream("trustedcerts.jks"); + KeyStore store = KeyStore.getInstance("JKS"); + store.load(in, "trustedcerts".toCharArray()); + return store; + } catch (KeyStoreException ex) { + Exceptions.printStackTrace(ex); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } catch (NoSuchAlgorithmException ex) { + Exceptions.printStackTrace(ex); + } catch (CertificateException ex) { + Exceptions.printStackTrace(ex); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } + return null; + } + +} diff --git a/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/trustedcerts.jks b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/trustedcerts.jks new file mode 100644 index 000000000..fef5a315c Binary files /dev/null and b/sdk/jme3-core-updatecenters/src/com/jme3/gde/core/updatecenters/keystore/trustedcerts.jks differ diff --git a/sdk/jme3-core/nbproject/project.properties b/sdk/jme3-core/nbproject/project.properties index 4206d1dff..88500da6c 100644 --- a/sdk/jme3-core/nbproject/project.properties +++ b/sdk/jme3-core/nbproject/project.properties @@ -1,10 +1,10 @@ #Thu, 25 Aug 2011 20:26:48 +0200 file.reference.DDSUtils.jar=release/modules/ext/DDSUtils.jar #Thu, 25 Aug 2011 19:32:54 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true project.license=jme diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.form b/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.form index 424078412..a5ad10fe2 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.form +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.form @@ -9,6 +9,7 @@ + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.java index c199fe39a..285ada07c 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/TextureBrowser.java @@ -31,9 +31,8 @@ */ package com.jme3.gde.core.properties; -import com.jme3.asset.TextureKey; import com.jme3.gde.core.assets.ProjectAssetManager; -import com.jme3.gde.core.properties.preview.DDSPreview; +import com.jme3.gde.core.properties.preview.TexturePreview; import com.jme3.gde.core.util.TreeUtil; import com.jme3.texture.Texture; import java.awt.event.MouseEvent; @@ -42,6 +41,7 @@ import java.awt.event.WindowListener; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; import javax.swing.DefaultListSelectionModel; @@ -52,8 +52,6 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; -import jme3tools.converters.ImageToAwt; -import org.openide.util.ImageUtilities; /** * Displays all textures in the ProjectAssetManager, @@ -68,7 +66,7 @@ public class TextureBrowser extends javax.swing.JDialog implements TreeSelection private ProjectAssetManager assetManager; private TexturePropertyEditor editor; - private DDSPreview ddsPreview; + private TexturePreview texPreview; private Preferences prefs; private static final String PREF_LAST_SELECTED = "lastSelectedTexture"; @@ -234,8 +232,8 @@ private void noTexturebuttonActionPerformed(java.awt.event.ActionEvent evt) {//G if (node != null && node.isLeaf()) { String selected = TreeUtil.getPath(node.getUserObjectPath()); selected = selected.substring(0, selected.lastIndexOf("/")); - Texture tex = assetManager.loadTexture(selected); - editor.setValue(tex); +// Texture tex = assetManager.loadTexture(selected); +// editor.setValue(tex); editor.setAsText(selected); return true; } @@ -270,7 +268,7 @@ private void noTexturebuttonActionPerformed(java.awt.event.ActionEvent evt) {//G private void setSelectedTexture(Texture texture) { if (texture != null) { - Logger.getLogger(TextureBrowser.class.getName()).finer("Looking for Texture: " + texture.getName()); + Logger.getLogger(TextureBrowser.class.getName()).log(Level.FINER, "Looking for Texture: {0}", texture.getName()); String[] path = ("/" + texture.getName()).split("/"); TreePath parent = new TreePath((TreeNode) jTree1.getModel().getRoot()); TreePath selectedTreePath = TreeUtil.buildTreePath(jTree1, parent, path, 0, true); @@ -287,6 +285,7 @@ private void noTexturebuttonActionPerformed(java.awt.event.ActionEvent evt) {//G } } + @Override public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree1.getLastSelectedPathComponent(); @@ -295,25 +294,14 @@ private void noTexturebuttonActionPerformed(java.awt.event.ActionEvent evt) {//G return; } - //Object nodeInfo = node.getUserObject(); if (node.isLeaf()) { String selected = TreeUtil.getPath(node.getUserObjectPath()); selected = selected.substring(0, selected.lastIndexOf("/")); Icon newicon = null; - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview(assetManager); - } - ddsPreview.requestPreview(selected, (String) node.getUserObject(), 450, 450, imagePreviewLabel, infoLabel); - - } else { - Texture tex = assetManager.loadTexture(selected); - newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - assetManager.deleteFromCache(new TextureKey(selected)); - imagePreviewLabel.setIcon(newicon); - infoLabel.setText(" " + node.getUserObject() + " w : " + newicon.getIconWidth() + " h : " + newicon.getIconHeight()); + if (texPreview == null) { + texPreview = new TexturePreview(assetManager); } - + texPreview.requestPreview(selected, (String) node.getUserObject(), 450, 450, imagePreviewLabel, infoLabel); prefs.put(PREF_LAST_SELECTED, selected); } else { imagePreviewLabel.setIcon(null); @@ -323,27 +311,34 @@ private void noTexturebuttonActionPerformed(java.awt.event.ActionEvent evt) {//G } + @Override public void windowOpened(WindowEvent e) { } + @Override public void windowClosing(WindowEvent e) { - if (ddsPreview != null) { - ddsPreview.cleanUp(); + if (texPreview != null) { + texPreview.cleanUp(); } } + @Override public void windowClosed(WindowEvent e) { } + @Override public void windowIconified(WindowEvent e) { } + @Override public void windowDeiconified(WindowEvent e) { } + @Override public void windowActivated(WindowEvent e) { } + @Override public void windowDeactivated(WindowEvent e) { } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/TexturePropertyEditor.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/TexturePropertyEditor.java index 9f4658e02..555fc5160 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/TexturePropertyEditor.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/TexturePropertyEditor.java @@ -80,7 +80,14 @@ public class TexturePropertyEditor implements PropertyEditor { } } + @Override public Object getValue() { + if(texture == null && assetKey != null){ + if (manager == null){ + manager = SceneApplication.getApplication().getAssetManager(); + } + texture = manager.loadTexture(assetKey); + } return texture; } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/DDSPreview.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/DDSPreview.java deleted file mode 100644 index c6597ff6a..000000000 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/DDSPreview.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.preview; - -import com.jme3.asset.TextureKey; -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.material.Material; -import com.jme3.math.Vector2f; -import com.jme3.math.Vector3f; -import com.jme3.scene.Geometry; -import com.jme3.scene.Spatial; -import com.jme3.scene.shape.Quad; -import com.jme3.texture.Texture; -import com.jme3.util.SkyFactory; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JLabel; - -/** - * - * @author Nehon - */ -public class DDSPreview implements SceneListener { - - private final ProjectAssetManager assetManager; - private JComponent picPreview; - private final Geometry quad; - private final Geometry quad3D; - private final Material material; - private final Material material3D; - - public DDSPreview(ProjectAssetManager assetManager) { - this.assetManager = assetManager; - - Quad quadMesh = new Quad(4.5f, 4.5f); - Quad quadMesh3D = new Quad(4.5f, 4.5f); - quadMesh3D.scaleTextureCoordinates(new Vector2f(4, 4)); - quad = new Geometry("previewQuad", quadMesh); - quad.setLocalTranslation(new Vector3f(-2.25f, -2.25f, 0)); - quad3D = new Geometry("previewQuad", quadMesh3D); - quad3D.setLocalTranslation(new Vector3f(-2.25f, -2.25f, 0)); - material3D = new Material(assetManager, "com/jme3/gde/core/properties/preview/tex3DThumb.j3md"); - material3D.setFloat("InvDepth", 1f / 16f); - material3D.setInt("Rows", 4); - material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); - SceneApplication.getApplication().addSceneListener(this); - } - - public void requestPreview(String textureName, String displayName, int width, int height, JComponent picLabel, JLabel infoLabel) { - TextureKey key = new TextureKey(textureName); - picPreview = picLabel; - assetManager.deleteFromCache(key); - Texture t = assetManager.loadTexture(key); - Spatial geom = quad; - if (key.getTextureTypeHint() == Texture.Type.TwoDimensional) { - material.setTexture("ColorMap", t); - geom.setMaterial(material); - if (infoLabel != null) { - infoLabel.setText(" " + displayName + " w : " + t.getImage().getWidth() + " h : " + t.getImage().getHeight()); - } - } else if (key.getTextureTypeHint() == Texture.Type.ThreeDimensional) { - geom = quad3D; - assetManager.deleteFromCache(key); - key.setTextureTypeHint(Texture.Type.ThreeDimensional); - t = assetManager.loadTexture(key); - material3D.setTexture("Texture", t); - geom.setMaterial(material3D); - if (infoLabel != null) { - infoLabel.setText(" " + displayName + " (Texture3D) w : " + t.getImage().getWidth() + " h : " + t.getImage().getHeight() + " d : " + t.getImage().getDepth()); - } - } else if (key.getTextureTypeHint() == Texture.Type.CubeMap) { - assetManager.deleteFromCache(key); - geom = SkyFactory.createSky(assetManager, textureName, SkyFactory.EnvMapType.CubeMap); - if (infoLabel != null) { - infoLabel.setText(" " + displayName + " (CubeMap) w : " + t.getImage().getWidth() + " h : " + t.getImage().getHeight()); - } - } - - PreviewRequest request = new PreviewRequest(this, geom, width, height); - request.getCameraRequest().setLocation(new Vector3f(0, 0, 5.3f)); - request.getCameraRequest().setLookAt(new Vector3f(0, 0, 0), Vector3f.UNIT_Y.mult(-1)); - SceneApplication.getApplication().createPreview(request); - } - - public void cleanUp() { - SceneApplication.getApplication().removeSceneListener(this); - } - - public void sceneOpened(SceneRequest request) { - } - - public void sceneClosed(SceneRequest request) { - } - - public void previewCreated(PreviewRequest request) { - if (request.getRequester() == this) { - final ImageIcon icon = new ImageIcon(request.getImage()); - if (picPreview instanceof JLabel) { - ((JLabel) picPreview).setIcon(icon); - } - if (picPreview instanceof JButton) { - ((JButton) picPreview).setIcon(icon); - } - } - } -} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/TexturePreview.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/TexturePreview.java new file mode 100644 index 000000000..337e3a34c --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/TexturePreview.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.properties.preview; + +import com.jme3.asset.TextureKey; +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.material.Material; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Spatial; +import com.jme3.scene.shape.Quad; +import com.jme3.texture.Texture; +import com.jme3.util.SkyFactory; +import java.util.concurrent.Callable; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; + +/** + * + * @author Nehon + */ +public class TexturePreview implements SceneListener { + + private final ProjectAssetManager assetManager; + private JComponent picPreview; + private final Geometry quad; + private final Geometry quad3D; + private final Material material; + private final Material material3D; + + public TexturePreview(ProjectAssetManager assetManager) { + this.assetManager = assetManager; + + Quad quadMesh = new Quad(4.5f, 4.5f); + Quad quadMesh3D = new Quad(4.5f, 4.5f); + quadMesh3D.scaleTextureCoordinates(new Vector2f(4, 4)); + quad = new Geometry("previewQuad", quadMesh); + quad.setLocalTranslation(new Vector3f(-2.25f, -2.25f, 0)); + quad3D = new Geometry("previewQuad", quadMesh3D); + quad3D.setLocalTranslation(new Vector3f(-2.25f, -2.25f, 0)); + material3D = new Material(assetManager, "com/jme3/gde/core/properties/preview/tex3DThumb.j3md"); + material3D.setFloat("InvDepth", 1f / 16f); + material3D.setInt("Rows", 4); + material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + SceneApplication.getApplication().addSceneListener(this); + } + + public void requestPreview(final String textureName, final String displayName, final int width, final int height, final JComponent picLabel, final JLabel infoLabel) { + + picPreview = picLabel; + clearPreview(); + if (infoLabel != null) { + infoLabel.setText(" Creating preview..."); + } + + SceneApplication.getApplication().enqueue(new Callable() { + + @Override + public Void call() throws Exception { + TextureKey key = new TextureKey(textureName); + Texture t = assetManager.loadTexture(key); + Spatial geom = quad; + if (key.getTextureTypeHint() == Texture.Type.TwoDimensional) { + material.setTexture("ColorMap", t); + geom.setMaterial(material); + setLabel(infoLabel, displayName, t.getImage().getWidth(), t.getImage().getHeight(), -1); + } else if (key.getTextureTypeHint() == Texture.Type.ThreeDimensional) { + geom = quad3D; + material3D.setTexture("Texture", t); + geom.setMaterial(material3D); + setLabel(infoLabel, displayName + " (Texture3D)", t.getImage().getWidth(), t.getImage().getHeight(), t.getImage().getDepth()); + + } else if (key.getTextureTypeHint() == Texture.Type.CubeMap) { + geom = SkyFactory.createSky(assetManager, textureName, SkyFactory.EnvMapType.CubeMap); + setLabel(infoLabel, displayName + " (CubeMap)", t.getImage().getWidth(), t.getImage().getHeight(), -1); + } + + PreviewRequest request = new PreviewRequest(TexturePreview.this, geom, width, height); + request.getCameraRequest().setLocation(new Vector3f(0, 0, 5.3f)); + request.getCameraRequest().setLookAt(new Vector3f(0, 0, 0), Vector3f.UNIT_Y.mult(-1)); + SceneApplication.getApplication().createPreview(request); + + return null; + } + + }); + } + + public void cleanUp() { + SceneApplication.getApplication().removeSceneListener(this); + } + + @Override + public void sceneOpened(SceneRequest request) { + } + + @Override + public void sceneClosed(SceneRequest request) { + } + + private void setLabel(final JLabel label, final String text, final int width, final int height, final int depth) { + + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + if (label != null) { + String labText = " " + text + " w : " + width + " h : " + height; + if (depth > 0) { + labText += " d : " + depth; + } + label.setText(labText); + } + } + }); + } + + private void clearPreview() { + if (picPreview instanceof JLabel) { + ((JLabel) picPreview).setIcon(null); + } + if (picPreview instanceof JButton) { + ((JButton) picPreview).setIcon(null); + } + } + + @Override + public void previewCreated(final PreviewRequest request) { + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + if (request.getRequester() == TexturePreview.this) { + final ImageIcon icon = new ImageIcon(request.getImage()); + if (picPreview instanceof JLabel) { + ((JLabel) picPreview).setIcon(icon); + } + if (picPreview instanceof JButton) { + ((JButton) picPreview).setIcon(icon); + } + } + } + }); + } +} diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.frag b/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.frag index f6eb25a3b..4ae52bd3f 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.frag +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.frag @@ -5,10 +5,9 @@ uniform float m_InvDepth; varying vec2 texCoord; void main(){ -float depthx=floor(texCoord.x); - float depthy=(m_Rows-1.0) - floor(texCoord.y); - //vec3 texC=vec3(texCoord.x,texCoord.y ,0.7);// + float depthx = floor(texCoord.x); + float depthy = (float(m_Rows) - 1.0) - floor(texCoord.y); - vec3 texC=vec3(fract(texCoord.x),fract(texCoord.y),(depthy*m_Rows+depthx)*m_InvDepth);// - gl_FragColor= texture3D(m_Texture,texC); + vec3 texC = vec3(fract(texCoord.x), fract(texCoord.y), (depthy * float(m_Rows) + depthx) * m_InvDepth);// + gl_FragColor = texture3D(m_Texture, texC); } \ No newline at end of file diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.vert b/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.vert index 6d27bc030..fd940682b 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.vert +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/preview/tex3DThumb.vert @@ -6,6 +6,6 @@ attribute vec3 inPosition; varying vec2 texCoord; void main(){ - gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition,1.0); - texCoord=inTexCoord; + gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0); + texCoord = inTexCoord; } \ No newline at end of file diff --git a/sdk/jme3-dark-laf/README.md b/sdk/jme3-dark-laf/README.md new file mode 100644 index 000000000..0dbb8d231 --- /dev/null +++ b/sdk/jme3-dark-laf/README.md @@ -0,0 +1,10 @@ +# DarkMonkey +Netbeans LAF and FAC combo - uses NimROD and Obsidian + +This is a plug-in for for Netbeans 8+ (well, the version it was developed for is 8.0.2). We wanted a dark theme variant for the jMonkeyEngine 3.1 sdk, so we made one. Enjoy! + +![DarkMonkey Screenshot](http://jme-hub-cdn.jmonkeyengineor.netdna-cdn.com/uploads/default/_optimized/fdd/136/87eb8a1efd_690x387.png) + +## Features +- Adds the DarkMonkey LaF to the Netbeans 8 environment under appearance - It's NimROD with a couple of tweaks. We've just adapted Nilo's wonderful project for the look we were going for. +- Adds the DarkMonkey FaC to the editor profile listing - It's Obsidian with some tweaks. DejaVu Sans Mono brings some sophistication to an otherwise courier world. diff --git a/sdk/jme3-dark-laf/build.xml b/sdk/jme3-dark-laf/build.xml new file mode 100644 index 000000000..6a5f08ba7 --- /dev/null +++ b/sdk/jme3-dark-laf/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project org.jme3.netbeans.plaf.darkmonkey. + + diff --git a/sdk/jme3-dark-laf/manifest.mf b/sdk/jme3-dark-laf/manifest.mf new file mode 100644 index 000000000..b1505dfad --- /dev/null +++ b/sdk/jme3-dark-laf/manifest.mf @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +OpenIDE-Module: org.jme3.netbeans.plaf.darkmonkey/1 +OpenIDE-Module-Implementation-Version: 0 +OpenIDE-Module-Install: org/jme3/netbeans/plaf/darkmonkey/Installer.class +OpenIDE-Module-Layer: org/jme3/netbeans/plaf/darkmonkey/layer.xml +OpenIDE-Module-Localizing-Bundle: org/jme3/netbeans/plaf/darkmonkey/Bundle.properties + diff --git a/sdk/jme3-dark-laf/nbproject/build-impl.xml b/sdk/jme3-dark-laf/nbproject/build-impl.xml new file mode 100644 index 000000000..2057e4b42 --- /dev/null +++ b/sdk/jme3-dark-laf/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-dark-laf/nbproject/genfiles.properties b/sdk/jme3-dark-laf/nbproject/genfiles.properties new file mode 100644 index 000000000..9adf50476 --- /dev/null +++ b/sdk/jme3-dark-laf/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=8f3042a8 +build.xml.script.CRC32=c15f5ee0 +build.xml.stylesheet.CRC32=a56c6a5b@2.67.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=8f3042a8 +nbproject/build-impl.xml.script.CRC32=4524e469 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1 diff --git a/sdk/jme3-dark-laf/nbproject/project.properties b/sdk/jme3-dark-laf/nbproject/project.properties new file mode 100644 index 000000000..c023595b6 --- /dev/null +++ b/sdk/jme3-dark-laf/nbproject/project.properties @@ -0,0 +1,8 @@ +file.reference.nimrodlf.jar=release/modules/ext/nimrodlf.jar +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial +license.file=../license-jme.txt +nbm.homepage=http://www.jmonkeyengine.org +nbm.module.author=Charles Anderson, R\u00e9my Bouquet +nbm.needs.restart=true +spec.version.base=3.1.0 diff --git a/sdk/jme3-dark-laf/nbproject/project.xml b/sdk/jme3-dark-laf/nbproject/project.xml new file mode 100644 index 000000000..9d6be0056 --- /dev/null +++ b/sdk/jme3-dark-laf/nbproject/project.xml @@ -0,0 +1,49 @@ + + + org.netbeans.modules.apisupport.project + + + org.jme3.netbeans.plaf.darkmonkey + + + + org.openide.awt + + + + 7.62.1 + + + + org.openide.modules + + + + 7.43.1 + + + + org.openide.util + + + + 8.39.1 + + + + org.openide.windows + + + + 6.71.1 + + + + + + ext/nimrodlf.jar + release/modules/ext/nimrodlf.jar + + + + diff --git a/sdk/jme3-dark-laf/nbproject/suite.properties b/sdk/jme3-dark-laf/nbproject/suite.properties new file mode 100644 index 000000000..29d7cc9bd --- /dev/null +++ b/sdk/jme3-dark-laf/nbproject/suite.properties @@ -0,0 +1 @@ +suite.dir=${basedir}/.. diff --git a/sdk/jme3-dark-laf/release/modules/ext/nimrodlf.jar b/sdk/jme3-dark-laf/release/modules/ext/nimrodlf.jar new file mode 100644 index 000000000..676f9b592 Binary files /dev/null and b/sdk/jme3-dark-laf/release/modules/ext/nimrodlf.jar differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/Bundle.properties b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/Bundle.properties new file mode 100644 index 000000000..1cc1695f7 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/Bundle.properties @@ -0,0 +1,10 @@ +OpenIDE-Module-Name=DarkMonkey +OpenIDE-Module-Display-Category=Appearance +OpenIDE-Module-Short-Description=Contains DarkMonkey theme for the JME3.1 stable release +OpenIDE-Module-Long-Description=\ +

    DarkMonkey Theme

    This is a Fonts/Colors and LookAndFeel combo that utilizes James McFadden's Obsidian Fonts/Colorsand Nilo Gonzalez's Nimrod LookAndFeel which isbased on the Metal LookAndFeel. \ + This module just checks and sees if the user already has the components, and if not, installs the theme and activates a few options:\n

    • under Tools - Options - Appearance - LookAndFeel it will have "DarkMonkey" , available.\ +
    • It also adds a Fonts/Colors Profile called "Dark Monkey".\ +

    We hope you like it!\ +

    For More Information visit: DarkMonkey Development Thread
    + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DMUtils.java b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DMUtils.java new file mode 100644 index 000000000..40470a535 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DMUtils.java @@ -0,0 +1,288 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.jme3.netbeans.plaf.darkmonkey; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.awt.image.BandedSampleModel; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferFloat; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import javax.imageio.ImageIO; + +/** + * I figured it would be best to have a Utilities type class to store the + * Methods I commonly use. Resources, registering stuff, resolving, transforming + * and so on... + * + * @author charles + */ +public class DMUtils { + + /** + *

    + * This method loads a picture from a relative path string. The relative + * path's root directory is understood to be inside of a jar... and in + * relation to the package of the referring Object instance. + *

    + *

    + * For example: if the object is an instance of + * org.jme3.netbeans.plaf.darkmonkey.DarkMonkeyIconFactory.class, and the + * string is "icons/MyCloseIcon.png", it will attempt to load + * org/jme3/netbeans/plaf/darkmonkey/icons/MyCloseIcon.png from + * DarkMonkeyIconFactory's jar file. + *

    + * It will print a stack trace if you get the relative path wrong. + * + * @param refObj - Reference Object(Object) - meant for a standard 'this' + * call, though any Instantiated class can be used. This is part of a + * workaround for Netbean's multiple class loader system. + * @param fileName - File Name(String) - the path to an image relative to + * the Reference Object's location in a jar file. + * @return BufferedImage - Freshly converted from the image file found at + * the location. + */ + public static BufferedImage loadImagefromJar(Object refObj, String fileName) { + BufferedImage bi = null; + try { + bi = ImageIO.read(refObj.getClass().getResourceAsStream(fileName)); + } catch (IOException e) { + // File is probably referenced wrong or "mispleled"... lol. + e.printStackTrace(); + } + return bi; + } + + /**

    + * This utility method is designed to Load OpenType/TrueType fonts into the + * current Runtime Environment without installing them to the OS. It takes + * the base path of the refObj and loads font files located relative to it. + * It checks to make sure that the fonts are not already installed in the system + * OS, first. If they are already installed, it does nothing more. + *

    + * Typical Usage - DMUtils.loadFontsFromJar(this, someFontFiles);
    + * and then someFontFiles[0] would contain something like "myfonts/DisFontPlain.ttf" + *

    + * @param refObj - Object - Usually just a *this*, but useful for a multiClassLoader + * type situation. + * @param fileNames - String[] - an array of {relative path + filename} strings for loading + * TrueType or OpenType fonts + */ + public static void loadFontsFromJar(Object refObj, String[] fileNames) { + //first, we grab ahold of what all fonts are in the JRE's system + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Font[] fontsListing = ge.getAllFonts(); + + /* // this can be uncommented if you want to see all the fonts in the JRE + for (Font fontInListing : fontsListing) { + System.out.println(fontInListing.getFontName() + " : " + fontInListing.getFamily()); + } + */ + + // Then we go and process the incoming streams + InputStream inStream; + Font checkFont; + try { + toNextFileName: + for (String fileName : fileNames) {// load up the fileName to process... + checkFont = Font.createFont(Font.TRUETYPE_FONT, refObj.getClass().getResourceAsStream(fileName)); + for (Font fontInListing : fontsListing) {// check if it's already on the list + if (fontInListing.getFontName().equals(checkFont.getFontName())) { + continue toNextFileName; //head to the next file if we find it... + } + } + ge.registerFont(checkFont);// and register it if we don't.... + } + } catch (FontFormatException | IOException e) { + // a File is probably referenced wrong or "mispleled"... lol. + // you can alternativly send a single String for debugging purposes + e.printStackTrace(); + } + + } + + /** + * This method transforms the inputed BufferedImage by the supplied Color[]. + * The behavior treats the Color[] as Ordered Passes A, R, G, B for .length + * 4 or more. It treats it as Ordered Passes R, G, B only for .length 3 or + * less. + * + * @param colorSet Color[] - that processes [1..4] up to four palette + * colors. 3 or less uses R,G,B passes only. 4 uses A,R,G,B and ignores + * anything more. + * @param clearToColorRequested - Color - A color to Blend with the First + * Translucent Pass - Optional + * @param argbMappedBufferedImage - BufferedImage - The image containing + * Channels as Alpha for the Palette + * @return BufferedImage - a new BufferedImage() transformed by the palette. + */ + public static BufferedImage paletteSwapARGB8(Color[] colorSet, Color clearToColorRequested, BufferedImage argbMappedBufferedImage) { + if (argbMappedBufferedImage == null) { + return null; //S.E.P. + } + final Color BLACK_NO_ALPHA = new Color(0x00000000); + final Color WHITE_NO_ALPHA = new Color(0x00FFFFFF); + final int ALPHA = 3; // this is some static mapping for... + final int RED = 0; // readability in the following... + final int GREEN = 1; // Magic code section of band processing. + final int BLUE = 2; + final int[] orderedBands = {ALPHA, RED, GREEN, BLUE}; + //first we prep a cmap with blank passes and + Color[] cMap = {BLACK_NO_ALPHA, BLACK_NO_ALPHA, BLACK_NO_ALPHA, BLACK_NO_ALPHA}; + boolean clearColorFound = false; + Color clearToColor = BLACK_NO_ALPHA; + if (colorSet != null) { //if we get a null colorSet... it's all mapped to clear. + if (colorSet.length > cMap.length) { // if colorSet is more than 4, we only proces up to 4 + for (int i = 0; i < cMap.length; i++) { + if (colorSet[i] != null) { + if (!clearColorFound) { + clearColorFound = true; + clearToColor = colorSet[i]; + } + cMap[orderedBands[i]] = colorSet[i]; // and finally, if any of the Colors are null... invisible pass... + } + } + } else { + int startOffset = 0; + if (colorSet.length < 4) // if less than standard size, assume RGB model + { + startOffset++; // and "blank" the alpha color pass. + } + for (int i = 0; i < colorSet.length; i++) { + if (colorSet[i] != null) { + if (!clearColorFound) { + clearColorFound = true; + clearToColor = colorSet[i]; + } + cMap[orderedBands[i + startOffset]] = colorSet[i]; + } + } + } + } + + // finally adjust the clearToColor if one was requested + if (clearToColorRequested != null) { + clearToColor = clearToColorRequested; + } + //Next we'll switch to Rasters to easily handle floating point precision + // operations upon the individual channels. + + WritableRaster outRaster, inRaster; + int w = argbMappedBufferedImage.getWidth(); + int h = argbMappedBufferedImage.getHeight(); + BandedSampleModel inSM = new BandedSampleModel(DataBuffer.TYPE_FLOAT, w, h, 4); + DataBufferFloat inDBF = new DataBufferFloat((w * h), 4);//4 banks, and total size + inRaster = Raster.createWritableRaster(inSM, inDBF, null); // that null just means point 0, 0 (top/left) + outRaster = inRaster.createCompatibleWritableRaster(w, h); + float[] cMaptoFlArray, outColortoFlArray, clearColortoFlArray; + float inBandAsAlpha; + Color paletteColor; + // now we convert from W/E the argbMappedBufferedImage's format to + // our normalized [0f..1f] RGBA raster + outColortoFlArray = new float[]{0f, 0f, 0f, 0f}; // or new float[4]... w/e + clearColortoFlArray = clearToColor.getRGBComponents(new float[4]); + clearColortoFlArray[ALPHA] = 0f; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int packedPixel = argbMappedBufferedImage.getRGB(x, y); + int testing; + float ftesting; + //outColortoFlArray[ALPHA] = (((packedPixel >> 24) & 0xFF) / 255); + testing = packedPixel; + testing = testing >> 24; + testing = testing & 0xFF; + ftesting = testing; + ftesting = ftesting / 255; + outColortoFlArray[ALPHA] = ftesting; + + //outColortoFlArray[RED] = (((packedPixel >> 16) & 0xFF) / 255); + testing = packedPixel; + testing = testing >> 16; + testing = testing & 0xFF; + ftesting = testing; + ftesting = ftesting / 255; + outColortoFlArray[RED] = ftesting; + + //outColortoFlArray[GREEN] = (((packedPixel >> 8) & 0xFF) / 255); + testing = packedPixel; + testing = testing >> 8; + testing = testing & 0xFF; + ftesting = testing; + ftesting = ftesting / 255; + outColortoFlArray[GREEN] = ftesting; + + //outColortoFlArray[BLUE] = ( (packedPixel & 0xFF) / 255); + testing = packedPixel; + testing = testing & 0xFF; + ftesting = testing; + ftesting = ftesting / 255; + outColortoFlArray[BLUE] = ftesting; + + inRaster.setPixel(x, y, outColortoFlArray); + outRaster.setPixel(x, y, clearColortoFlArray); + } + } + // next, we process all bands in order - a "band" being one channel of A,R,G,B. + // as each band is processed the outRaster keeps getting "resampled" to apply + // the next band properly. all values are considered normalized [0f..1f] + for (int band : orderedBands) { + paletteColor = cMap[band]; + cMaptoFlArray = paletteColor.getRGBComponents(new float[4]);// this nullifies translucency + if (paletteColor != BLACK_NO_ALPHA) { + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + //inBandAsAlpha = inRaster.getSample(x, y, band); + inBandAsAlpha = inRaster.getSampleFloat(x, y, band); + outColortoFlArray = outRaster.getPixel(x, y, new float[4]); + outColortoFlArray[RED] = (outColortoFlArray[RED] + * (1f - (inBandAsAlpha * cMaptoFlArray[ALPHA]))) + + (cMaptoFlArray[RED] * (inBandAsAlpha * cMaptoFlArray[ALPHA])); + outColortoFlArray[GREEN] = (outColortoFlArray[GREEN] + * (1f - (inBandAsAlpha * cMaptoFlArray[ALPHA]))) + + (cMaptoFlArray[GREEN] * (inBandAsAlpha * cMaptoFlArray[ALPHA])); + outColortoFlArray[BLUE] = (outColortoFlArray[BLUE] + * (1f - (inBandAsAlpha * cMaptoFlArray[ALPHA]))) + + (cMaptoFlArray[BLUE] * (inBandAsAlpha * cMaptoFlArray[ALPHA])); + + outColortoFlArray[ALPHA] = (outColortoFlArray[ALPHA] + * (1f - (inBandAsAlpha * cMaptoFlArray[ALPHA]))) + + (cMaptoFlArray[ALPHA] * (inBandAsAlpha * cMaptoFlArray[ALPHA])); + + outRaster.setPixel(x, y, outColortoFlArray); + } + } + } + } + + //then we convert n' ship + BufferedImage returnBI = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + outColortoFlArray = outRaster.getPixel(x, y, new float[4]); + int packedColor = ((int) (outColortoFlArray[ALPHA] * 255f) << 24) + | ((int) (outColortoFlArray[RED] * 255f) << 16) + | ((int) (outColortoFlArray[GREEN] * 255f) << 8) + | ((int) (outColortoFlArray[BLUE] * 255f)); + returnBI.setRGB(x, y, packedColor); + } + } + + return returnBI; + } + + public static BufferedImage paletteSwapARGB8(Color[] colorSet, BufferedImage argbMappedBufferedImage) { + + return paletteSwapARGB8(colorSet, null, argbMappedBufferedImage); + } + +} diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkey.theme b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkey.theme new file mode 100644 index 000000000..c16f368da --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkey.theme @@ -0,0 +1,11 @@ +nimrodlf.p1=#77411D +nimrodlf.p2=#9E5F28 +nimrodlf.p3=#948519 +nimrodlf.s1=#303030 +nimrodlf.s2=#3A3A3A +nimrodlf.s3=#515151 +nimrodlf.w=#262626 +nimrodlf.b=#E8EAE0 +nimrodlf.menuOpacity=219 +nimrodlf.frameOpacity=180 +nimrodlf.font=DejaVu Sans Condensed-BOLD-12 diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyIconFactory.java b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyIconFactory.java new file mode 100644 index 000000000..4c640851b --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyIconFactory.java @@ -0,0 +1,153 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.jme3.netbeans.plaf.darkmonkey; + +import com.nilo.plaf.nimrod.NimRODIconFactory; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BandedSampleModel; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferFloat; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.io.Serializable; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.plaf.UIResource; + +/** + * This class provides for overrides on the system Icons from the + * NimROD look and feel + * @author charles + */ +public class DarkMonkeyIconFactory extends NimRODIconFactory{ + private static Icon treeCollapsedIcon; + private static Icon treeExpandedIcon; + + public static Icon getTreeCollapsedIcon(){ + if(treeCollapsedIcon == null){ + treeCollapsedIcon = new TreeCollapsedIcon(); + } + + return treeCollapsedIcon; + } + public static Icon getTreeExpandedIcon(){ + if(treeExpandedIcon == null){ + treeExpandedIcon = new TreeExpandedIcon(); + } + + return treeExpandedIcon; + } + + + private static class TreeCollapsedIcon implements Icon, UIResource, Serializable{ + private int w, h; + ImageIcon preProcessed; + { + w = 18; + h = 18; + preProcessed = null; + } + + public TreeCollapsedIcon(){ //maybe THIS is all I need, eh? + w = 18; + h = 18; + preProcessed = null; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + if(preProcessed != null){ + preProcessed.paintIcon(c, g, x, y); + return; + } + + //process for first time, unless this gets "uninitialized" by + // UIResource calls; + BufferedImage bi = DMUtils.loadImagefromJar(this, "icons/nehonC2.png"); + // start the experiments! + + Color[] normColorSet = {null, DarkMonkeyLookAndFeel.getWhite(), + null, DarkMonkeyLookAndFeel.getPrimaryControl()}; + bi = DMUtils.paletteSwapARGB8(normColorSet, bi); + // end experiment, back to old code + ImageIcon ii = new ImageIcon(bi); + Image scaled = ii.getImage(); + ImageIcon preProcess = new ImageIcon(scaled.getScaledInstance(w, h, Image.SCALE_SMOOTH)); + preProcess.paintIcon(c, g, x, y); + preProcessed = preProcess; + } + + @Override + public int getIconWidth() { + return w; + } + + @Override + public int getIconHeight() { + return h; + } + + } + + private static class TreeExpandedIcon implements Icon, UIResource, Serializable{ + private int w, h; + ImageIcon preProcessed; + { + w = 18; + h = 18; + preProcessed = null; + } + + + public TreeExpandedIcon(){ //maybe THIS is all I need, eh? + w = 18; + h = 18; + preProcessed = null; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + if(preProcessed != null){ + preProcessed.paintIcon(c, g, x, y); + return; + } + + //process for first time, unless this gets "uninitialized" by + // UIResource calls; + + BufferedImage bi = DMUtils.loadImagefromJar(this, "icons/nehonE2.png"); + Color[] normColorSet = { DarkMonkeyLookAndFeel.getWhite(), + null, DarkMonkeyLookAndFeel.getPrimaryControl()}; + bi = DMUtils.paletteSwapARGB8(normColorSet, bi); + + ImageIcon ii = new ImageIcon(bi); + Image scaled = ii.getImage(); + + ImageIcon preProcess = new ImageIcon(scaled.getScaledInstance(w, h, Image.SCALE_DEFAULT)); + + preProcess.paintIcon(c, g, x, y); + preProcessed = preProcess; + } + + @Override + public int getIconWidth() { + return w; + } + + @Override + public int getIconHeight() { + return h; + } + + } + + + +} diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyLookAndFeel.java b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyLookAndFeel.java new file mode 100644 index 000000000..a923a911e --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyLookAndFeel.java @@ -0,0 +1,111 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.jme3.netbeans.plaf.darkmonkey; + +import com.nilo.plaf.nimrod.NimRODTheme; +import java.awt.Color; +import java.awt.Font; +import java.util.Enumeration; +import javax.swing.ImageIcon; +import javax.swing.UIDefaults; + +/** + * The DarkMonkey look and feel class Extends the Nimrod LAF, which in turn, + * extends Metal. The version of Nimrod used is 1.2b obtained from:
    + * + * http://nilogonzalez.es/nimrodlf/download-en.html + *

    A copy of the jar and source used for this project is in the ext/ folder. + *

    + * + * @author Charles Anderson + */ +public class DarkMonkeyLookAndFeel extends com.nilo.plaf.nimrod.NimRODLookAndFeel{ + + public static final String dmLAFDefault = "DarkMonkey.theme"; + protected static NimRODTheme nrTheme = new NimRODTheme(); + + public DarkMonkeyLookAndFeel(){ + super(); + // Todo: replace following code with proper loading + // From DarkMonkey.theme + NimRODTheme nt = new NimRODTheme(); + + nt.setBlack(Color.decode("#E8EAE0")); + nt.setWhite(Color.decode("#262626")); + nt.setPrimary1(Color.decode("#77411D")); + nt.setPrimary2(Color.decode("#9E5F28")); + nt.setPrimary3(Color.decode("#948519")); + nt.setSecondary1(Color.decode("#303030")); + nt.setSecondary2(Color.decode("#3A3A3A")); + nt.setSecondary3(Color.decode("#515151")); + nt.setFrameOpacity(180); + nt.setMenuOpacity(219); + nt.setFont(Font.decode("DejaVu Sans Condensed-PLAIN-12")); + + setCurrentTheme(nt); + + } + + /** + * This method override, getID() returns the String "DarkMonkey" for + * registering this Look And Feel with the UImanager. + * @return String "DarkMonkey" + */ + @Override + public String getID() { + return "DarkMonkey"; + } + + /** + * This method override, getName() returns the String "DarkMonkey" for + * its Look and Feel Name. I don't know that this is important, but is + * overridden anyway, for completion. + * @return String "DarkMonkey" + */ + @Override + public String getName() { + return "DarkMonkey"; + } + + /** + * This method override, getDescription() returns the String + * "Look and Feel DarkMonkey - 2015, based on NimROD 2007" for + * instances of future programming that might use it as a tool tip or + * small descriptor in their Look and Feel modules. + * @return String "Look and Feel DarkMonkey - 2015, based on NimROD 2007" + */ + @Override + public String getDescription() { + return "Look and Feel DarkMonkey - 2015, based on NimROD 2007"; + } + + + @Override + protected void initClassDefaults( UIDefaults table) { + super.initClassDefaults( table); + /* + for( Enumeration en = table.keys(); en.hasMoreElements(); ) { + System.out.println( "[" + en.nextElement() + "]"); + } + */ + } + + @Override + protected void initComponentDefaults( UIDefaults table) { + super.initComponentDefaults( table); + + table.put("Tree.collapsedIcon", DarkMonkeyIconFactory.getTreeCollapsedIcon()); + table.put("Tree.expandedIcon", DarkMonkeyIconFactory.getTreeExpandedIcon()); + // + /* + for( Enumeration en = table.keys(); en.hasMoreElements(); ) { + System.out.println( "[" + en.nextElement() + "]"); + } + */ + + } + +} diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyValidator.java b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyValidator.java new file mode 100644 index 000000000..cc5ef7c70 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/DarkMonkeyValidator.java @@ -0,0 +1,29 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.jme3.netbeans.plaf.darkmonkey; + +import java.awt.EventQueue; +import javax.swing.JOptionPane; +import javax.swing.UIManager; +import org.openide.modules.OnStart; +import org.openide.windows.OnShowing; + +/** + * This is something that would be used once the nbm format is no longer + * needed and is absorbed by SDK downloadable. + * @author charles + */ +@OnStart +public class DarkMonkeyValidator implements Runnable{ + + @Override + public void run() { + + //assert EventQueue.isDispatchThread(); // this is for @OnShowing + //JOptionPane.showMessageDialog(null,"Hello from the Validator"); + } + +} diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/Installer.java b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/Installer.java new file mode 100644 index 000000000..8ceda6a48 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/Installer.java @@ -0,0 +1,40 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.jme3.netbeans.plaf.darkmonkey; + +import java.awt.Font; +import java.awt.GraphicsEnvironment; +import java.io.File; +import javax.swing.UIManager; +import org.openide.modules.ModuleInstall; + +public class Installer extends ModuleInstall { + + @Override + public void restored() { + UIManager.installLookAndFeel(new UIManager.LookAndFeelInfo( + new DarkMonkeyLookAndFeel().getName(), + DarkMonkeyLookAndFeel.class.getName())); + // TODO + + String[] fontsToLoad = { + "fonts/DejaVuSans.ttf", + "fonts/DejaVuSans-Bold.ttf", + "fonts/DejaVuSans-Oblique.ttf", + "fonts/DejaVuSans-BoldOblique.ttf", + "fonts/DejaVuSansCondensed.ttf", + "fonts/DejaVuSansCondensed-Bold.ttf", + "fonts/DejaVuSansCondensed-Oblique.ttf", + "fonts/DejaVuSansCondensed-BoldOblique.ttf", + "fonts/DejaVuSansMono.ttf", + "fonts/DejaVuSansMono-Bold.ttf", + "fonts/DejaVuSansMono-Oblique.ttf", + "fonts/DejaVuSansMono-BoldOblique.ttf" + }; + DMUtils.loadFontsFromJar(this, fontsToLoad); + } + +} diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/JunkSnippet.txt b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/JunkSnippet.txt new file mode 100644 index 000000000..7bbdbc2a7 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/JunkSnippet.txt @@ -0,0 +1,144 @@ + public static void loadFontsFromJar(Object refObj, String relPath) { + //first, we grab ahold of what all fonts are in the JRE's system + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String[] fontFamilies = ge.getAvailableFontFamilyNames(); + //Next we get a listing of all of the fonts in the refObj's jar at relPath + ZipFile zipFile = new ZipFile("C:/test.zip"); + InputStream stream; + Enumeration entries = zipFile.entries(); + try { + bi = ImageIO.read(refObj.getClass().getResourceAsStream(fileName)); + } catch (IOException e) { + // File is probably referenced wrong or "mispleled"... lol. + e.printStackTrace(); + } + + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + stream = zipFile.getInputStream(entry); + stream.close(); + } + + ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File("A.ttf"))); + + } + + /** + * Note from Charles: DO NOT USE - Retain it though :) this method correctly + * does get the path... of Netbeans.. lol... ... Todo: adjust this to work + * with concepts from the LoadImagefromJar... ... and we can make it work + * for custom defined themes dynamically in conjunction with the + * functionality available from Nilo's NimROD base. END NOTE... + * + * @param relativePath + * @return + * @throws NoSuchFileException + */ + public static String relpath(String relativePath) { + //TODO fix the following statement and we can start having dynamic LaF adjustment - Charles + final File f = new File(DMUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + //END TODO - Charles + String returnString; + int i; + returnString = f.getPath(); + i = returnString.indexOf("org-jme3-netbeans"); // This would have to be adjusted as well - Charles + returnString = returnString.substring(0, i); + returnString = returnString.replace(File.separatorChar, '/') + relativePath; + File check = new File(returnString); + + return returnString; + + } + +This next bit is from the AnnotationType overrides in the layer.xml..... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/README.txt b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/README.txt new file mode 100644 index 000000000..109c25481 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/README.txt @@ -0,0 +1,42 @@ +- Note from Charles - +Ok, I think I have everything covered for community involvement: +If you contribute make sure to toss your name into the AUTHORS.txt file +for the proper directory. Make sure to toss in commenting and supply JavaDoc +for Methods / Classes. Otherwise, have fun with it! + +Structure: +-layer.xml contains the FAC side of this project. +-DarkMonkeyLookAndFeel contains the LAF side of this project. +-Installer is responsible for making sure LAF side and unregistered fonts are + available for each instance of netbeans. +-DMUtils contains resource/file methods for base IO or resource transformations +-DarkMonkeyValidator is a placeholder launchpoint snippet for conversion from + nbm format to a form that would integrate with an SDK downloadable build + (it is unnecessary as-is. Would replace Installer, functionally) +-DarkMonkey.theme is the desired way to use nimrodlf (unimplemented at current time) +-DarkMonkeyIconFactory produces images/icons for the small/fixed size level + -Tree.expandedIcon is overridden + -Tree.collapsedIcon is overridden + - more can be added +-Bundle.properties contains one of the cooler module description pages, ever*. + -* COOLEST. DESCRIPTION. EVER. (I'm cereal! / lol! /omg!) + +Directory Structure: +org.jme3.netbeans.plaf.darkmonkey is considered root for the relative path calls +that you will see in code. *Especially* if DMUtils is involved. + -ext/ or external, currently contains nimrodlf.jar and nimrodlf_src.zip + -fac/ or FontsColors, contains the FontsColors.xml files for layer.xml to + place into netbean's xmlfilesytem. + -fac/AnnotationTypes/ contains the Annotation.xml files for layer.xml to + place into netbean's xmlfilesytem. *Unimplemented* Only if the sidebar + icons for breakpoints and such should be replaced. + -fac/AnnotationTypes/icons *Unimplemented* *Does not exist yet* see above. + -fonts/ *unimplented* contains the physical .ttf fonts used by the LAF and FAC sides. + -icons/ contains image resources for LAF side. + + +Current Todo List: +-fix bug in src for nimrodlf.jar rebuild in ext/ + - Bug has to do with GridBagLayout and other such stuff where preferredSize + is derived. +-add font check/load code for fonts/. see JunkSnippet.txt for some proto work. \ No newline at end of file diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/.nbattrs b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/.nbattrs new file mode 100644 index 000000000..7ecdd8f3d --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/.nbattrs @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint.xml new file mode 100644 index 000000000..ab5cdb3a5 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint_broken.xml new file mode 100644 index 000000000..0c910da14 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint_broken.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint_stroke.xml new file mode 100644 index 000000000..b7f6e535f --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/Breakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CallSite.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CallSite.xml new file mode 100644 index 000000000..97f28c4ed --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CallSite.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/ClassBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/ClassBreakpoint.xml new file mode 100644 index 000000000..9f237ae65 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/ClassBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/ClassBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/ClassBreakpoint_stroke.xml new file mode 100644 index 000000000..d6d6f8e91 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/ClassBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint.xml new file mode 100644 index 000000000..8642294c0 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint_broken.xml new file mode 100644 index 000000000..19a2e232e --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint_broken.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint_stroke.xml new file mode 100644 index 000000000..eb206c4d3 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CondBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpression.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpression.xml new file mode 100644 index 000000000..fdec15548 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpression.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine.xml new file mode 100644 index 000000000..686a5e530 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_BP.xml new file mode 100644 index 000000000..30d316146 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_BP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_CBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_CBP.xml new file mode 100644 index 000000000..f0595e41a --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_CBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_DBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_DBP.xml new file mode 100644 index 000000000..8b1342b71 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_DBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_DCBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_DCBP.xml new file mode 100644 index 000000000..5a11a7c76 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentExpressionLine_DCBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC.xml new file mode 100644 index 000000000..93e5ef58f --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2.xml new file mode 100644 index 000000000..ece9b3616 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2LinePart.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2LinePart.xml new file mode 100644 index 000000000..99dd6d4aa --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2LinePart.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2_BP.xml new file mode 100644 index 000000000..b3ed82ba3 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2_BP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2_DBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2_DBP.xml new file mode 100644 index 000000000..30c6f72d6 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPC2_DBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPCLinePart.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPCLinePart.xml new file mode 100644 index 000000000..9b8feebab --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/CurrentPCLinePart.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledBreakpoint.xml new file mode 100644 index 000000000..75294be39 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledBreakpoint_stroke.xml new file mode 100644 index 000000000..9ba03221a --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledClassBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledClassBreakpoint.xml new file mode 100644 index 000000000..8d71638fa --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledClassBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledClassBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledClassBreakpoint_stroke.xml new file mode 100644 index 000000000..d858e4c28 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledClassBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledCondBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledCondBreakpoint.xml new file mode 100644 index 000000000..ce7ae7b9a --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledCondBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledCondBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledCondBreakpoint_stroke.xml new file mode 100644 index 000000000..d87175748 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledCondBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledFieldBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledFieldBreakpoint.xml new file mode 100644 index 000000000..730360695 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledFieldBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledFieldBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledFieldBreakpoint_stroke.xml new file mode 100644 index 000000000..9df689cdf --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledFieldBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledMethodBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledMethodBreakpoint.xml new file mode 100644 index 000000000..993af856e --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledMethodBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledMethodBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledMethodBreakpoint_stroke.xml new file mode 100644 index 000000000..1d6b5f09b --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/DisabledMethodBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/FieldBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/FieldBreakpoint.xml new file mode 100644 index 000000000..1c816c6c6 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/FieldBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/FieldBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/FieldBreakpoint_stroke.xml new file mode 100644 index 000000000..a30520f2d --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/FieldBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/MethodBreakpoint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/MethodBreakpoint.xml new file mode 100644 index 000000000..6bc43a6e4 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/MethodBreakpoint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/MethodBreakpoint_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/MethodBreakpoint_stroke.xml new file mode 100644 index 000000000..f235a9a32 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/MethodBreakpoint_stroke.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread.xml new file mode 100644 index 000000000..8b476a25d --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_BP.xml new file mode 100644 index 000000000..b37c17ca2 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_BP.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_BP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_BP_broken.xml new file mode 100644 index 000000000..8477ea95e --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_BP_broken.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_DBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_DBP.xml new file mode 100644 index 000000000..b3633a32a --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_DBP.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_PC.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_PC.xml new file mode 100644 index 000000000..b4ecab2ae --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_PC.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_PC_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_PC_BP.xml new file mode 100644 index 000000000..ea4733484 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThread_PC_BP.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads.xml new file mode 100644 index 000000000..fbc91baee --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_BP.xml new file mode 100644 index 000000000..939a55a8c --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_BP.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_BP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_BP_broken.xml new file mode 100644 index 000000000..417d2f742 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_BP_broken.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_DBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_DBP.xml new file mode 100644 index 000000000..5fce8a876 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_DBP.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_PC_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_PC_BP.xml new file mode 100644 index 000000000..cedc279dd --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/OtherThreads_PC_BP.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP.xml new file mode 100644 index 000000000..ce0a84fcf --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP_broken.xml new file mode 100644 index 000000000..bc39dc5f4 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP_broken.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP_stroke.xml new file mode 100644 index 000000000..97b4a7f80 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_BP_stroke.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP.xml new file mode 100644 index 000000000..2e03f914c --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP_broken.xml new file mode 100644 index 000000000..9578d867a --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP_broken.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP_stroke.xml new file mode 100644 index 000000000..6141bc1bd --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_CBP_stroke.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DBP.xml new file mode 100644 index 000000000..76951fef4 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DBP_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DBP_stroke.xml new file mode 100644 index 000000000..8b32f784c --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DBP_stroke.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DCBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DCBP.xml new file mode 100644 index 000000000..a768c78e9 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DCBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DCBP_stroke.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DCBP_stroke.xml new file mode 100644 index 000000000..1cc067b05 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_DCBP_stroke.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_mixedBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_mixedBP.xml new file mode 100644 index 000000000..118f47060 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_mixedBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_mixedBP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_mixedBP_broken.xml new file mode 100644 index 000000000..8d9de2b91 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_mixedBP_broken.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_BPCBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_BPCBP.xml new file mode 100644 index 000000000..7554b1a7f --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_BPCBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_BPCBP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_BPCBP_broken.xml new file mode 100644 index 000000000..7e728b15c --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_BPCBP_broken.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_DBPCBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_DBPCBP.xml new file mode 100644 index 000000000..92eaded02 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/PC_multi_DBPCBP.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/README.txt b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/README.txt new file mode 100644 index 000000000..8834bd0b0 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/README.txt @@ -0,0 +1,11 @@ +- Note from Charles - +Yeah, these are the full xml definitions for the +annotations types. I've retained them from Nehon's +conf.zip file, but these aren't added to the layer.xml. + +Yet... + +-Only if we want to override the various icons, n stuff. +or +-if these actually override the colors specified in +the annotations fonts/colors. \ No newline at end of file diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/bookmark.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/bookmark.xml new file mode 100644 index 000000000..1f03f9839 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/bookmark.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/implements-has-implementations-combined.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/implements-has-implementations-combined.xml new file mode 100644 index 000000000..83e049c8f --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/implements-has-implementations-combined.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/implements-is-overridden-combined.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/implements-is-overridden-combined.xml new file mode 100644 index 000000000..0c254dd51 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/implements-is-overridden-combined.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/mixed_BP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/mixed_BP.xml new file mode 100644 index 000000000..45914e713 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/mixed_BP.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/mixed_BP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/mixed_BP_broken.xml new file mode 100644 index 000000000..d99e90ee8 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/mixed_BP_broken.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_BPCBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_BPCBP.xml new file mode 100644 index 000000000..1c284b712 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_BPCBP.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_BPCBP_broken.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_BPCBP_broken.xml new file mode 100644 index 000000000..b759921be --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_BPCBP_broken.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_DBPCBP.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_DBPCBP.xml new file mode 100644 index 000000000..2e3beb577 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/multi_DBPCBP.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-has_implementations.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-has_implementations.xml new file mode 100644 index 000000000..468c18fc3 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-has_implementations.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-implements.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-implements.xml new file mode 100644 index 000000000..7fcb1b188 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-implements.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-is_overridden.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-is_overridden.xml new file mode 100644 index 000000000..655bcfb13 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-is_overridden.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-overrides.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-overrides.xml new file mode 100644 index 000000000..d028fde30 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-editor-annotations-overrides.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-git-Annotation.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-git-Annotation.xml new file mode 100644 index 000000000..0e34aca67 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-git-Annotation.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-subversion-Annotation.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-subversion-Annotation.xml new file mode 100644 index 000000000..5d71f4dc5 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-subversion-Annotation.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-versioning-annotate-Annotation.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-versioning-annotate-Annotation.xml new file mode 100644 index 000000000..e76379ae7 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-versioning-annotate-Annotation.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-xml-error.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-xml-error.xml new file mode 100644 index 000000000..3021fd1d3 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-modules-xml-error.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_err.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_err.xml new file mode 100644 index 000000000..55ac88c48 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_err.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_err_fixable.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_err_fixable.xml new file mode 100644 index 000000000..862814346 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_err_fixable.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_hint.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_hint.xml new file mode 100644 index 000000000..0220cfd4b --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_hint.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_hint_fixable.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_hint_fixable.xml new file mode 100644 index 000000000..c76fec170 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_hint_fixable.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_todo.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_todo.xml new file mode 100644 index 000000000..b37f74d96 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_todo.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_todo_fixable.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_todo_fixable.xml new file mode 100644 index 000000000..58ba23cd7 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_todo_fixable.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_verifier.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_verifier.xml new file mode 100644 index 000000000..4a8f56103 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_verifier.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_verifier_fixable.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_verifier_fixable.xml new file mode 100644 index 000000000..8601c8da9 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_verifier_fixable.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_warn.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_warn.xml new file mode 100644 index 000000000..16719bbd2 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_warn.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_warn_fixable.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_warn_fixable.xml new file mode 100644 index 000000000..3ff4011bc --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/org-netbeans-spi-java-parser_annotation_warn_fixable.xml @@ -0,0 +1,3 @@ + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/override-is-overridden-combined.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/override-is-overridden-combined.xml new file mode 100644 index 000000000..9d50207d5 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/AnnotationTypes/override-is-overridden-combined.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-annotation.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-annotation.xml new file mode 100644 index 000000000..5024f9e69 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-annotation.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-highlight.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-highlight.xml new file mode 100644 index 000000000..5800fe464 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-highlight.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-token.xml new file mode 100644 index 000000000..01a7f0cac --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-Editor-token.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-application-xml-dtd-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-application-xml-dtd-token.xml new file mode 100644 index 000000000..1b8368e1a --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-application-xml-dtd-token.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-css-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-css-token.xml new file mode 100644 index 000000000..651489eb2 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-css-token.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-html-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-html-token.xml new file mode 100644 index 000000000..e1b09178a --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-html-token.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-javascript-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-javascript-token.xml new file mode 100644 index 000000000..f318f02cd --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-javascript-token.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-plain-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-plain-token.xml new file mode 100644 index 000000000..2151022de --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-plain-token.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-diff-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-diff-token.xml new file mode 100644 index 000000000..3078cef90 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-diff-token.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-glsl-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-glsl-token.xml new file mode 100644 index 000000000..2b69657b7 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-glsl-token.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-groovy-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-groovy-token.xml new file mode 100644 index 000000000..f90545ccb --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-groovy-token.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-gsp-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-gsp-token.xml new file mode 100644 index 000000000..d0866faab --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-gsp-token.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-java-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-java-token.xml new file mode 100644 index 000000000..3ee9d08c9 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-java-token.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-json-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-json-token.xml new file mode 100644 index 000000000..a37fd1237 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-json-token.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-properties-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-properties-token.xml new file mode 100644 index 000000000..20704ac25 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-properties-token.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-yaml-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-yaml-token.xml new file mode 100644 index 000000000..7064a1f0e --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-x-yaml-token.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xhtml-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xhtml-token.xml new file mode 100644 index 000000000..55db420cc --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xhtml-token.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xml-external-parsed-entity-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xml-external-parsed-entity-token.xml new file mode 100644 index 000000000..5d81a5eaa --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xml-external-parsed-entity-token.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xml-token.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xml-token.xml new file mode 100644 index 000000000..5d81a5eaa --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/DarkMonkeyFAC-text-xml-token.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/EditorFontsColors-1_1dtd.txt b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/EditorFontsColors-1_1dtd.txt new file mode 100644 index 000000000..f456f9eff --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/EditorFontsColors-1_1dtd.txt @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/README.txt b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/README.txt new file mode 100644 index 000000000..6601e78fa --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fac/README.txt @@ -0,0 +1,36 @@ +- Note From Charles - +This "Directory" org.jme3.netbeans.plaf.darkmonkay.fac is similarly structured +to the way netbeans handles its Fonts and Colors internally. + +It is not really how Netbeans stores it. I have removed "/FontsColors/ThemeName" +from all directories... and the fac can be considered rooted at /Editor + +For the actual registration of all these colors... see the layer.xml +file at org.jme3.netbeans.plaf.darkmonkey + +That said: +-changing the values in the .xml files *will* affect the color values of the +"Dark Monkey" FAC default profile. + +and remember, the Fonts and Colors profile "Dark Monkey" side +of this module is only for the Editor module of Netbeans. Don't confuse this +with the Look and Feel "DarkMonkey" side. :) + +Together, they make the theme for DarkMonkey in Netbeans. + +Onwards! +Tips for learners: +- The syntax for these FAC .xml files is in EditorFontsColor-1_1dtd.txt + I've included the dtd as a txt so folks have a handy reference for knowing + what all options they have for including into the tags. +- Notice that the file names kind of look like the file folder structure of + one of those exported profile .zip files. Roll with that naming convention + if you notice the pattern. The last word is the same as the attr assigned + to the file in the layer.xml file... or the .nbattr file... +- It's all layered like css, so the more specific you get... the more values + that have to be overwritten when the user customizes. +- If in doubt, you can always refer to the Netbeans/Default code to see what + all "names" need to be covered for completion. (You can look at the + from layer.xml and see how the various FAC .xml files + work their way through to support the system.) +- There is a video on the DarkMonkey Dev Blog over at the jMonkeyEngine Forums \ No newline at end of file diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/AUTHORS b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/AUTHORS new file mode 100644 index 000000000..94df1e390 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/AUTHORS @@ -0,0 +1,54 @@ +abysta at yandex.ru +Adrian Schroeter +Aleksey Chalabyan +Andrey Valentinovich Panov +Ben Laenen +Besarion Gugushvili +Bhikkhu Pesala +Clayborne Arevalo +Dafydd Harries +Danilo Segan +Davide Viti +David Jez +David Lawrence Ramsey +Denis Jacquerye +Dwayne Bailey +Eugeniy Meshcheryakov +Gee Fung Sit +Heikki Lindroos +James Cloos +James Crippen +John Karp +Keenan Pepper +Lars Naesbye Christensen +Lior Halphon +MaEr +Mashrab Kuvatov +Max Berger +Mederic Boquien +Michael Everson +MihailJP +Misu Moldovan +Nguyen Thai Ngoc Duy +Nicolas Mailhot +Norayr Chilingarian +Ognyan Kulev +Ondrej Koala Vacha +Peter Cernak +Remy Oudompheng +Roozbeh Pournader +Rouben Hakobian +Sahak Petrosyan +Sander Vesik +Stepan Roh +Stephen Hartke +Steve Tinney +Tavmjong Bah +Thomas Henlich +Tim May +Valentin Stoykov +Vasek Stodulka +Wesley Transue +Yoshiki Ohshima + +$Id: AUTHORS 2495 2011-11-14 22:56:26Z noct_dreamer $ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-Bold.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-Bold.ttf new file mode 100644 index 000000000..08695f23a Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-Bold.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-BoldOblique.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-BoldOblique.ttf new file mode 100644 index 000000000..7e3bcc105 Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-BoldOblique.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-Oblique.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-Oblique.ttf new file mode 100644 index 000000000..e33ab144d Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans-Oblique.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans.ttf new file mode 100644 index 000000000..9d40c3256 Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSans.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-Bold.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-Bold.ttf new file mode 100644 index 000000000..4c40003d4 Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-Bold.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-BoldOblique.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-BoldOblique.ttf new file mode 100644 index 000000000..24b611b18 Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-BoldOblique.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-Oblique.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-Oblique.ttf new file mode 100644 index 000000000..1e0526f9a Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed-Oblique.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed.ttf new file mode 100644 index 000000000..7f168d13c Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansCondensed.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-Bold.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-Bold.ttf new file mode 100644 index 000000000..9c716794f Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-Bold.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-BoldOblique.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-BoldOblique.ttf new file mode 100644 index 000000000..d6536a5cc Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-BoldOblique.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-Oblique.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-Oblique.ttf new file mode 100644 index 000000000..e1af34130 Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono-Oblique.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono.ttf b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono.ttf new file mode 100644 index 000000000..8b7bb2a4e Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/DejaVuSansMono.ttf differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/LICENSE b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/LICENSE new file mode 100644 index 000000000..254e2cc42 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/LICENSE @@ -0,0 +1,99 @@ +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + +$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/README b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/README new file mode 100644 index 000000000..12e9e977c --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/fonts/README @@ -0,0 +1,77 @@ +-Note from Charles- +Though we are not extending anything and only using a part of their original +work, I am passing along their readme, authors, and License for proper +accreditation as that we are using: +DejaVu Sans Mono +DejaVu Sans Mono Bold +DejaVu Sans Mono Bold Oblique +DejaVu Sans Mono Oblique +DejaVu Sans +DejaVu Sans Bold +DejaVu Sans Bold Oblique +DejaVu Sans Oblique +from their wonderful font family + +Acquire their full Latest Version at: +http://dejavu-fonts.org +-End Note- + +DejaVu fonts 2.34 (c)2004-2013 DejaVu fonts team +------------------------------------------------ + +The DejaVu fonts are a font family based on the Bitstream Vera Fonts +(http://gnome.org/fonts/). Its purpose is to provide a wider range of +characters (see status.txt for more information) while maintaining the +original look and feel. + +DejaVu fonts are based on Bitstream Vera fonts version 1.10. + +Available fonts (Sans = sans serif, Mono = monospaced): + +DejaVu Sans Mono +DejaVu Sans Mono Bold +DejaVu Sans Mono Bold Oblique +DejaVu Sans Mono Oblique +DejaVu Sans +DejaVu Sans Bold +DejaVu Sans Bold Oblique +DejaVu Sans Oblique +DejaVu Sans ExtraLight (experimental) +DejaVu Serif +DejaVu Serif Bold +DejaVu Serif Bold Italic (experimental) +DejaVu Serif Italic (experimental) +DejaVu Sans Condensed (experimental) +DejaVu Sans Condensed Bold (experimental) +DejaVu Sans Condensed Bold Oblique (experimental) +DejaVu Sans Condensed Oblique (experimental) +DejaVu Serif Condensed (experimental) +DejaVu Serif Condensed Bold (experimental) +DejaVu Serif Condensed Bold Italic (experimental) +DejaVu Serif Condensed Italic (experimental) + +All fonts are also available as derivative called DejaVu LGC with support +only for Latin, Greek and Cyrillic scripts. + +For license information see LICENSE. What's new is described in NEWS. Known +bugs are in BUGS. All authors are mentioned in AUTHORS. + +Fonts are published in source form as SFD files (Spline Font Database from +FontForge - http://fontforge.sf.net/) and in compiled form as TTF files +(TrueType fonts). + +For more information go to http://dejavu.sourceforge.net/. + +Characters from Arev fonts, Copyright (c) 2006 by Tavmjong Bah: +--------------------------- +U+01BA, U+01BF, U+01F7, U+021C-U+021D, U+0220, U+0222-U+0223, +U+02B9, U+02BA, U+02BD, U+02C2-U+02C5, U+02d4-U+02D5, +U+02D7, U+02EC-U+02EE, U+0346-U+034E, U+0360, U+0362, +U+03E2-03EF, U+0460-0463, U+0466-U+0486, U+0488-U+0489, U+04A8-U+04A9, +U+0500-U+050F, U+2055-205E, U+20B0, U+20B2-U+20B3, U+2102, U+210D, U+210F, +U+2111, U+2113, U+2115, U+2118-U+211A, U+211C-U+211D, U+2124, U+2135, +U+213C-U+2140, U+2295-U+2298, U+2308-U+230B, U+26A2-U+26B1, U+2701-U+2704, +U+2706-U+2709, U+270C-U+274B, U+2758-U+275A, U+2761-U+2775, U+2780-U+2794, +U+2798-U+27AF, U+27B1-U+27BE, U+FB05-U+FB06 + +$Id: README 2535 2013-08-25 15:21:17Z moyogo $ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/icons/nehonC2.png b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/icons/nehonC2.png new file mode 100644 index 000000000..4c96a2bfe Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/icons/nehonC2.png differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/icons/nehonE2.png b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/icons/nehonE2.png new file mode 100644 index 000000000..3160f134c Binary files /dev/null and b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/icons/nehonE2.png differ diff --git a/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/layer.xml b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/layer.xml new file mode 100644 index 000000000..3c84a4094 --- /dev/null +++ b/sdk/jme3-dark-laf/src/org/jme3/netbeans/plaf/darkmonkey/layer.xml @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-desktop-executables/nbproject/project.properties b/sdk/jme3-desktop-executables/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-desktop-executables/nbproject/project.properties +++ b/sdk/jme3-desktop-executables/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-documentation/nbproject/project.properties b/sdk/jme3-documentation/nbproject/project.properties index 232d11645..39ff046d1 100644 --- a/sdk/jme3-documentation/nbproject/project.properties +++ b/sdk/jme3-documentation/nbproject/project.properties @@ -1,6 +1,6 @@ javac.source=1.6 javac.compilerargs=-Xlint -Xlint:-serial license.file=../license-jme.txt -nbm.homepage=http://www.jmonkeyengine.com +nbm.homepage=http://www.jmonkeyengine.org nbm.module.author=Normen Hansen, Ruth Kusterer, many others spec.version.base=3.1.0 diff --git a/sdk/jme3-gui/nbproject/project.properties b/sdk/jme3-gui/nbproject/project.properties index 291042fd5..9a27f3767 100644 --- a/sdk/jme3-gui/nbproject/project.properties +++ b/sdk/jme3-gui/nbproject/project.properties @@ -10,10 +10,10 @@ file.reference.slf4j-simple-1.7.7.jar=release/modules/ext/slf4j-simple-1.7.7.jar file.reference.swingtonifty.jar=release/modules/ext/swingtonifty.jar file.reference.xsom-20110101-SNAPSHOT.jar=release/modules/ext/xsom-20110101-SNAPSHOT.jar #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint:-serial license.file=../license-jme.txt -nbm.homepage=http://www.jmonkeyengine.com +nbm.homepage=http://www.jmonkeyengine.org nbm.module.author=Relucri nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-lwjgl-applet/nbproject/project.properties b/sdk/jme3-lwjgl-applet/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-lwjgl-applet/nbproject/project.properties +++ b/sdk/jme3-lwjgl-applet/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-materialeditor/nbproject/project.properties b/sdk/jme3-materialeditor/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-materialeditor/nbproject/project.properties +++ b/sdk/jme3-materialeditor/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionCurve.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionCurve.java index ec2f4aa98..7c225f745 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionCurve.java +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionCurve.java @@ -123,7 +123,7 @@ public class ConnectionCurve extends JPanel implements ComponentListener, MouseI g2.setStroke(new BasicStroke(4)); Path2D.Double path1 = new Path2D.Double(); - if (getDiagram().selectedItem == this) { + if (getDiagram().getSelectedItems().contains(this)) { g.setColor(SELECTED_COLOR); } else { g.setColor(VERY_DARK_GREY); @@ -162,7 +162,7 @@ public class ConnectionCurve extends JPanel implements ComponentListener, MouseI ((Graphics2D) g).draw(path1); g2.setStroke(new BasicStroke(2)); - if (getDiagram().selectedItem == this) { + if (getDiagram().getSelectedItems().contains(this)) { g.setColor(Color.WHITE); } else { g.setColor(LIGHT_GREY); @@ -385,7 +385,7 @@ public class ConnectionCurve extends JPanel implements ComponentListener, MouseI } if (selected) { - getDiagram().select(this); + getDiagram().select(this, e.isShiftDown() || e.isControlDown()); e.consume(); } } @@ -407,9 +407,7 @@ public class ConnectionCurve extends JPanel implements ComponentListener, MouseI if (e.getKeyCode() == KeyEvent.VK_DELETE) { Diagram diag = getDiagram(); - if (diag.selectedItem == this) { - diag.removeSelectedConnection(); - } + diag.removeSelected(); } } diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionStraight.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionStraight.java index 3eba66a23..fc4873bd8 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionStraight.java +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ConnectionStraight.java @@ -209,7 +209,7 @@ public class ConnectionStraight extends JPanel implements ComponentListener, Mou g.drawLine(p1.x, p1.y, p2.x, p2.y); - if (getDiagram().selectedItem == this) { + if (getDiagram().getSelectedItems().contains(this)) { g.setColor(Color.CYAN); } else { g.setColor(Color.GRAY); @@ -489,7 +489,7 @@ public class ConnectionStraight extends JPanel implements ComponentListener, Mou } if (selected) { - getDiagram().select(this); + getDiagram().select(this, e.isShiftDown() || e.isControlDown()); e.consume(); } } @@ -511,9 +511,7 @@ public class ConnectionStraight extends JPanel implements ComponentListener, Mou if (e.getKeyCode() == KeyEvent.VK_DELETE) { Diagram diag = getDiagram(); - if (diag.selectedItem == this) { - diag.removeSelectedConnection(); - } + diag.removeSelected(); } } diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/Diagram.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/Diagram.java index 9d344355e..88876f3e5 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/Diagram.java +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/Diagram.java @@ -55,7 +55,7 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene protected Dot draggedFrom; protected Dot draggedTo; - protected Selectable selectedItem; + protected List selectedItems = new ArrayList(); protected List connections = new ArrayList(); protected List nodes = new ArrayList(); protected List outBuses = new ArrayList(); @@ -63,6 +63,9 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene private MatDefEditorlElement parent; private String currentTechniqueName; private final BackdropPanel backDrop = new BackdropPanel(); + private final Cursor defCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); + private final Cursor hndCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); + private final Point pp = new Point(); @SuppressWarnings("LeakingThisInConstructor") public Diagram() { @@ -99,7 +102,7 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene } } - selectedItem = null; + selectedItems.clear(); repaint(); } else if (e.getButton() == MouseEvent.BUTTON2) { setCursor(hndCursor); @@ -204,13 +207,10 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene public void mouseExited(MouseEvent e) { } - protected void removeSelectedConnection() { - if (selectedItem instanceof Connection) { - Connection selectedConnection = (Connection) selectedItem; - removeConnection(selectedConnection); - selectedItem = null; - parent.notifyRemoveConnection(selectedConnection); - } + protected void removeSelectedConnection(Selectable selectedItem) { + Connection selectedConnection = (Connection) selectedItem; + removeConnection(selectedConnection); + parent.notifyRemoveConnection(selectedConnection); } private String fixNodeName(String name) { @@ -276,44 +276,58 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene np.revalidate(); repaint(); } - - protected void removeSelectedNode() { - if (selectedItem instanceof NodePanel) { - int result = JOptionPane.showConfirmDialog(null, "Delete this node and all its mappings?", "Delete Shader Node", JOptionPane.OK_CANCEL_OPTION); - if (result == JOptionPane.OK_OPTION) { - NodePanel selectedNode = (NodePanel) selectedItem; - nodes.remove(selectedNode); - for (Iterator it = connections.iterator(); it.hasNext();) { - Connection conn = it.next(); - if (conn.start.getNode() == selectedNode || conn.end.getNode() == selectedNode) { - it.remove(); - conn.end.disconnect(); - conn.start.disconnect(); - remove(conn); - } + + protected void removeSelected(){ + + int result = JOptionPane.showConfirmDialog(null, "Delete all selected items, nodes and mappings?", "Delete Selected", JOptionPane.OK_CANCEL_OPTION); + + if (result == JOptionPane.OK_OPTION) { + for (Selectable selectedItem : selectedItems) { + if (selectedItem instanceof NodePanel) { + removeSelectedNode(selectedItem); } + if (selectedItem instanceof Connection) { + removeSelectedConnection(selectedItem); + } + } + selectedItems.clear(); + } + } - selectedNode.cleanup(); - remove(selectedNode); - selectedItem = null; - repaint(); - parent.notifyRemoveNode(selectedNode); + private void removeSelectedNode(Selectable selectedItem) { + + NodePanel selectedNode = (NodePanel) selectedItem; + nodes.remove(selectedNode); + for (Iterator it = connections.iterator(); it.hasNext();) { + Connection conn = it.next(); + if (conn.start.getNode() == selectedNode || conn.end.getNode() == selectedNode) { + it.remove(); + conn.end.disconnect(); + conn.start.disconnect(); + remove(conn); } } + + selectedNode.cleanup(); + remove(selectedNode); + repaint(); + parent.notifyRemoveNode(selectedNode); } - private final Cursor defCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); - private final Cursor hndCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); - private final Point pp = new Point(); + public List getSelectedItems() { + return selectedItems; + } @Override public void mouseDragged(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { if (draggedFrom == null) { - if (selectedItem instanceof OutBusPanel) { - OutBusPanel bus = (OutBusPanel) selectedItem; - MouseEvent me = SwingUtilities.convertMouseEvent(this, e, bus); - bus.dispatchEvent(me); + for (Selectable selectedItem : selectedItems) { + if (selectedItem instanceof OutBusPanel) { + OutBusPanel bus = (OutBusPanel) selectedItem; + MouseEvent me = SwingUtilities.convertMouseEvent(this, e, bus); + bus.dispatchEvent(me); + } } } } else if (SwingUtilities.isMiddleMouseButton(e)) { @@ -373,22 +387,53 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene * * @param selectable */ - public void select(Selectable selectable) { - parent.selectionChanged(doSelect(selectable)); + public void select(Selectable selectable, boolean multi) { + parent.selectionChanged(doSelect(selectable, multi)); + } + + public void multiMove(DraggablePanel movedPanel ,int xOffset, int yOffset){ + + for (Selectable selectedItem : selectedItems) { + if(selectedItem != movedPanel){ + if(selectedItem instanceof DraggablePanel){ + ((DraggablePanel)selectedItem).movePanel(xOffset, yOffset); + } + } + } } + public void multiStartDrag(DraggablePanel movedPanel){ + for (Selectable selectedItem : selectedItems) { + if(selectedItem != movedPanel){ + if(selectedItem instanceof DraggablePanel){ + ((DraggablePanel)selectedItem).saveLocation(); + } + } + } + } + /** * do select the item and repaint the diagram * * @param selectable * @return */ - private Selectable doSelect(Selectable selectable) { - this.selectedItem = selectable; + private Selectable doSelect(Selectable selectable, boolean multi) { + + + if (!multi && !selectedItems.contains(selectable)) { + selectedItems.clear(); + } + + if (selectable != null) { + selectedItems.add(selectable); + } + if (selectable instanceof Component) { ((Component) selectable).requestFocusInWindow(); } repaint(); + return selectable; } @@ -403,23 +448,23 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene for (NodePanel nodePanel : nodes) { if (nodePanel.getKey().equals(key)) { - return doSelect(nodePanel); + return doSelect(nodePanel, false); } } for (Connection connection : connections) { if (connection.getKey().equals(key)) { - return doSelect(connection); + return doSelect(connection, false); } } for (OutBusPanel outBusPanel : outBuses) { if (outBusPanel.getKey().equals(key)) { - return doSelect(outBusPanel); + return doSelect(outBusPanel, false); } } - return doSelect(null); + return null; } @Override diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/DraggablePanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/DraggablePanel.java index e81d1d5b6..7941cb8d5 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/DraggablePanel.java +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/DraggablePanel.java @@ -37,16 +37,22 @@ public class DraggablePanel extends JPanel implements MouseListener, MouseMotion @Override public void mousePressed(MouseEvent e) { if (e.getButton() != MouseEvent.BUTTON2) { - svdx = getLocation().x; + if (!vertical) { svdex = e.getXOnScreen(); } - svdy = getLocation().y; svdey = e.getYOnScreen(); + saveLocation(); + diagram.multiStartDrag(this); e.consume(); } } + protected void saveLocation() { + svdy = getLocation().y; + svdx = getLocation().x; + } + @Override public void mouseReleased(MouseEvent e) { } @@ -71,11 +77,19 @@ public class DraggablePanel extends JPanel implements MouseListener, MouseMotion xoffset = e.getLocationOnScreen().x - svdex; } int yoffset = e.getLocationOnScreen().y - svdey; - setLocation(Math.max(0, svdx + xoffset), Math.max(0, svdy + yoffset)); + movePanel(xoffset, yoffset); + diagram.multiMove(this, xoffset, yoffset); e.consume(); } } + protected void movePanel(int xoffset, int yoffset) { + if (vertical) { + xoffset = 0; + } + setLocation(Math.max(0, svdx + xoffset), Math.max(0, svdy + yoffset)); + } + public Diagram getDiagram() { return diagram; } diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/NodePanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/NodePanel.java index 49e04170d..adfd9223d 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/NodePanel.java +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/NodePanel.java @@ -56,23 +56,6 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha protected List filePaths = new ArrayList(); protected Shader.ShaderType shaderType; -// private List listeners = Collections.synchronizedList(new LinkedList()); -// -// public void addPropertyChangeListener(PropertyChangeListener pcl) { -// listeners.add(pcl); -// } -// -// public void removePropertyChangeListener(PropertyChangeListener pcl) { -// listeners.remove(pcl); -// } -// -// protected void fire(String propertyName, Object old, Object nue) { -// //Passing 0 below on purpose, so you only synchronize for one atomic call: -// PropertyChangeListener[] pcls = (PropertyChangeListener[]) listeners.toArray(new PropertyChangeListener[0]); -// for (int i = 0; i < pcls.length; i++) { -// pcls[i].propertyChange(new PropertyChangeEvent(this, propertyName, old, nue)); -// } -// } public enum NodeType { Vertex(new Color(220, 220, 70)),//yellow @@ -186,9 +169,12 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha } private Dot getConnectPoint(List list, String varName, List listDot) { - if (varName.startsWith("m_") || varName.startsWith("g_")) { - varName = varName.substring(2); - } + //This has been commented out because it was causing issues when a variable name was explicitely starting with m_ or g_ in the j3md. + //I can't remember why it was done in the first place, but I can't see any case where the m_ should be stripped out. + //I'm letting this commented in case this comes to light some day, and something more clever will have to be done. +// if (varName.startsWith("m_") || varName.startsWith("g_")) { +// varName = varName.substring(2); +// } for (int i = 0; i < list.size(); i++) { if (list.get(i).getText().equals(varName)) { return listDot.get(i); @@ -201,13 +187,13 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha protected void paintComponent(Graphics g1) { Graphics2D g = (Graphics2D) g1; Color boderColor = Color.BLACK; - if (diagram.selectedItem == this) { + if (getDiagram().getSelectedItems().contains(this)) { boderColor = Color.WHITE; } g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // Anti-alias! RenderingHints.VALUE_ANTIALIAS_ON); // Color[] colors = {new Color(0, 0, 0, 0.7f), new Color(0, 0, 0, 0.15f)}; - if (diagram.selectedItem == this) { + if (getDiagram().getSelectedItems().contains(this)) { Color[] colors = new Color[]{new Color(0.6f, 0.6f, 1.0f, 0.8f), new Color(0.6f, 0.6f, 1.0f, 0.5f)}; float[] factors = {0f, 1f}; g.setPaint(new RadialGradientPaint(getWidth() / 2, getHeight() / 2, getWidth() / 2, factors, colors)); @@ -260,8 +246,8 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha @Override public void mousePressed(MouseEvent e) { - super.mousePressed(e); - diagram.select(this); + super.mousePressed(e); + diagram.select(this, e.isShiftDown() || e.isControlDown()); showToolBar(); } @@ -442,9 +428,7 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha public void delete() { Diagram diag = getDiagram(); - if (diag.selectedItem == this) { - diag.removeSelectedNode(); - } + diag.removeSelected(); } public void keyReleased(KeyEvent e) { diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/OutBusPanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/OutBusPanel.java index 521776dce..6a489dea6 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/OutBusPanel.java +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/OutBusPanel.java @@ -110,7 +110,7 @@ public class OutBusPanel extends DraggablePanel implements ComponentListener, Se Polygon p = new Polygon(xs, ys, 8); - if (diagram.selectedItem == this) { + if (getDiagram().getSelectedItems().contains(this)) { int[] xs2 = {0, width - 30, width - 30, width, width - 32, width - 32, 0, 0}; int[] ys2 = {10, 10, 0, getHeight() / 2 + 2, getHeight(), getHeight() - 8, getHeight() - 8, 10}; @@ -154,7 +154,7 @@ public class OutBusPanel extends DraggablePanel implements ComponentListener, Se return; } super.mousePressed(e); - diagram.select(this); + diagram.select(this, e.isShiftDown() || e.isControlDown()); } @Override 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 index b414a1126..1e5856fd1 100644 --- 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 @@ -10,15 +10,19 @@ */ package com.jme3.gde.materials.multiview.widgets; +import com.jme3.asset.AssetNotFoundException; import com.jme3.gde.core.assets.ProjectAssetManager; import com.jme3.gde.core.properties.TexturePropertyEditor; -import com.jme3.gde.core.properties.preview.DDSPreview; +import com.jme3.gde.core.properties.preview.TexturePreview; import com.jme3.gde.materials.MaterialProperty; +import com.jme3.gde.materials.multiview.MaterialEditorTopComponent; import com.jme3.texture.Texture; import java.awt.Component; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.Icon; import javax.swing.SwingUtilities; import jme3tools.converters.ImageToAwt; @@ -35,7 +39,7 @@ public class TexturePanel extends MaterialPropertyWidget { private boolean flip = false; private boolean repeat = false; private String textureName = null; - private DDSPreview ddsPreview; + private TexturePreview texPreview; private final ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); /** Creates new form SelectionPanel */ @@ -49,21 +53,15 @@ public class TexturePanel extends MaterialPropertyWidget { if (!"".equals(textureName)) { exec.execute(new Runnable() { + @Override public void run() { - - Texture tex = manager.loadTexture(textureName); - if (textureName.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview(manager); + try{ + if (texPreview == null) { + texPreview = new TexturePreview(manager); } - ddsPreview.requestPreview(textureName, "", 80, 80, texturePreview, null); - } else { - final Icon newicon = ImageUtilities.image2Icon(resizeImage(ImageToAwt.convert(tex.getImage(), false, true, 0))); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - texturePreview.setIcon(newicon); - } - }); + texPreview.requestPreview(textureName, "", 80, 25, texturePreview, null); + } catch (AssetNotFoundException a) { + Logger.getLogger(MaterialEditorTopComponent.class.getName()).log(Level.WARNING, "Could not load texture {0}", textureName); } } }); @@ -311,8 +309,8 @@ public class TexturePanel extends MaterialPropertyWidget { @Override public void cleanUp() { - if (ddsPreview != null) { - ddsPreview.cleanUp(); + if (texPreview != null) { + texPreview.cleanUp(); } exec.shutdownNow(); } diff --git a/sdk/jme3-model-importer/nbproject/project.properties b/sdk/jme3-model-importer/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-model-importer/nbproject/project.properties +++ b/sdk/jme3-model-importer/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-navmesh-gen/nbproject/project.properties b/sdk/jme3-navmesh-gen/nbproject/project.properties index 65d1fb700..78227c671 100644 --- a/sdk/jme3-navmesh-gen/nbproject/project.properties +++ b/sdk/jme3-navmesh-gen/nbproject/project.properties @@ -1,6 +1,6 @@ javac.source=1.6 javac.compilerargs=-Xlint -Xlint:-serial license.file=../license-jme.txt -nbm.homepage=http://www.jmonkeyengine.com +nbm.homepage=http://www.jmonkeyengine.org nbm.module.author=Brent Owens spec.version.base=3.1.0 diff --git a/sdk/jme3-obfuscate/nbproject/project.properties b/sdk/jme3-obfuscate/nbproject/project.properties index 61598fa7b..d16349a4f 100644 --- a/sdk/jme3-obfuscate/nbproject/project.properties +++ b/sdk/jme3-obfuscate/nbproject/project.properties @@ -1,6 +1,7 @@ #Thu, 25 Aug 2011 20:26:50 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial +license.file=../license-jme.txt nbm.homepage=http\://proguard.sourceforge.net/ nbm.module.author=Normen Hansen nbm.needs.restart=true diff --git a/sdk/jme3-ogretools/nbproject/project.properties b/sdk/jme3-ogretools/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-ogretools/nbproject/project.properties +++ b/sdk/jme3-ogretools/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-ogrexml/nbproject/project.properties b/sdk/jme3-ogrexml/nbproject/project.properties index 9b996acdd..4ad5ba7ab 100644 --- a/sdk/jme3-ogrexml/nbproject/project.properties +++ b/sdk/jme3-ogrexml/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:48 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-project-baselibs/nbproject/project.properties b/sdk/jme3-project-baselibs/nbproject/project.properties index 2e01f5d86..513fb20e4 100644 --- a/sdk/jme3-project-baselibs/nbproject/project.properties +++ b/sdk/jme3-project-baselibs/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:48 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=jMonkeyEngine nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-project-libraries/nbproject/project.properties b/sdk/jme3-project-libraries/nbproject/project.properties index 2e01f5d86..513fb20e4 100644 --- a/sdk/jme3-project-libraries/nbproject/project.properties +++ b/sdk/jme3-project-libraries/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:48 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=jMonkeyEngine nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-project-testdata/nbproject/project.properties b/sdk/jme3-project-testdata/nbproject/project.properties index 2e01f5d86..513fb20e4 100644 --- a/sdk/jme3-project-testdata/nbproject/project.properties +++ b/sdk/jme3-project-testdata/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:48 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=jMonkeyEngine nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-scenecomposer/nbproject/project.properties b/sdk/jme3-scenecomposer/nbproject/project.properties index e0b462857..eec6af9cd 100644 --- a/sdk/jme3-scenecomposer/nbproject/project.properties +++ b/sdk/jme3-scenecomposer/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java index 372984f8e..c2a4753c4 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java @@ -453,6 +453,9 @@ public abstract class SceneEditTool { Geometry arrowX = new Geometry("arrowX", new Arrow(new Vector3f(arrowSize, 0, 0))); Geometry arrowY = new Geometry("arrowY", new Arrow(new Vector3f(0, arrowSize, 0))); Geometry arrowZ = new Geometry("arrowZ", new Arrow(new Vector3f(0, 0, arrowSize))); + arrowX.getMesh().setLineWidth(2f); + arrowY.getMesh().setLineWidth(2f); + arrowZ.getMesh().setLineWidth(2f); axis.attachChild(arrowX); axis.attachChild(arrowY); axis.attachChild(arrowZ); diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java index 87f3c283f..013cfb492 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java @@ -10,6 +10,7 @@ import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent; import com.jme3.gde.scenecomposer.SceneEditTool; import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.terrain.Terrain; @@ -33,7 +34,7 @@ import org.openide.loaders.DataObject; */ public class SelectTool extends SceneEditTool { - private boolean wasDraggingR = false; + private boolean wasDraggingR, wasDraggingL = false; private boolean wasDownR = false; /** @@ -52,13 +53,24 @@ public class SelectTool extends SceneEditTool { */ @Override public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) { - + if (!pressed){ + if (!wasDraggingL) { + Vector3f result = pickWorldLocation(getCamera(), screenCoord, rootNode); + if (result != null) { + if (toolController.isSnapToGrid()) { + result.set(Math.round(result.x), result.y, Math.round(result.z)); + } + toolController.doSetCursorLocation(result); + } + } + wasDraggingL = false; + } } @Override public void actionSecondary(final Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) { if (pressed) { - Spatial selected = toolController.getSelectedSpatial(); + Spatial selected;// = toolController.getSelectedSpatial(); // mouse down if (!wasDraggingR && !wasDownR) { // wasn't dragging and was not down already @@ -137,6 +149,7 @@ public class SelectTool extends SceneEditTool { @Override public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { + wasDraggingL = pressed; } @Override diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java index cc13ece1d..d5dca8d14 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java @@ -29,7 +29,9 @@ public class DeleteShortcut extends ShortcutTool { @Override public boolean isActivableBy(KeyInputEvent kie) { if (kie.getKeyCode() == KeyInput.KEY_X && kie.isPressed()) { - if (Lookup.getDefault().lookup(ShortcutManager.class).isShiftDown()) { + ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); + if (!scm.isActive() && scm.isShiftDown()) { + // ^ can't be enable if an other shortcut is allready active return true; } } @@ -99,7 +101,7 @@ public class DeleteShortcut extends ShortcutTool { @Override public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { } - + private class DeleteUndo extends AbstractUndoableSceneEdit { private Spatial spatial; diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java index 6291ab932..e32e7183c 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java @@ -78,14 +78,16 @@ public class MoveShortcut extends ShortcutTool { if (kie.isPressed()) { Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie); - Vector3f axis = new Vector3f(); - boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis); + boolean axisChanged = ShortcutManager.isAxisKey(kie); if (axisChanged) { - currentAxis = axis; + currentAxis = ShortcutManager.getAxisKey(kie); } - boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder); - boolean enterHit = ShortcutManager.checkEnterHit(kie); - boolean escHit = ShortcutManager.checkEscHit(kie); + boolean numberChanged = ShortcutManager.isNumberKey(kie); + if(numberChanged){ + ShortcutManager.setNumberKey(kie, numberBuilder); + } + boolean enterHit = ShortcutManager.isEnterKey(kie); + boolean escHit = ShortcutManager.isEscKey(kie); if (escHit) { cancel(); diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java index 8b9ffe404..aec5b6928 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java @@ -77,14 +77,16 @@ public class RotateShortcut extends ShortcutTool { if (kie.isPressed()) { Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie); - Vector3f axis = new Vector3f(); - boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis); + boolean axisChanged = ShortcutManager.isAxisKey(kie); if (axisChanged) { - currentAxis = axis; + currentAxis = ShortcutManager.getAxisKey(kie); } - boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder); - boolean enterHit = ShortcutManager.checkEnterHit(kie); - boolean escHit = ShortcutManager.checkEscHit(kie); + boolean numberChanged = ShortcutManager.isNumberKey(kie); + if(numberChanged){ + ShortcutManager.setNumberKey(kie, numberBuilder); + } + boolean enterHit = ShortcutManager.isEnterKey(kie); + boolean escHit = ShortcutManager.isEscKey(kie); if (escHit) { cancel(); diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java index 8fa18858f..25266a676 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java @@ -77,14 +77,16 @@ public class ScaleShortcut extends ShortcutTool { if (kie.isPressed()) { Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie); - Vector3f axis = new Vector3f(); - boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis); + boolean axisChanged = ShortcutManager.isAxisKey(kie); if (axisChanged) { - currentAxis = axis; + currentAxis = ShortcutManager.getAxisKey(kie); } - boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder); - boolean enterHit = ShortcutManager.checkEnterHit(kie); - boolean escHit = ShortcutManager.checkEscHit(kie); + boolean numberChanged = ShortcutManager.isNumberKey(kie); + if(numberChanged){ + ShortcutManager.setNumberKey(kie, numberBuilder); + } + boolean enterHit = ShortcutManager.isEnterKey(kie); + boolean escHit = ShortcutManager.isEscKey(kie); if (escHit) { cancel(); diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java index 187293e92..c7d6f3721 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java @@ -157,13 +157,13 @@ public class ShortcutManager { } private boolean checkCommandeKey(KeyInputEvent kie) { - if (checkCtrlHit(kie)) { + if (isCtrlKey(kie)) { ctrlDown = kie.isPressed(); return true; - } else if (checkAltHit(kie)) { + } else if (isAltKey(kie)) { altDown = kie.isPressed(); return true; - } else if (checkShiftHit(kie)) { + } else if (isShiftKey(kie)) { shiftDown = kie.isPressed(); return true; } @@ -178,11 +178,8 @@ public class ShortcutManager { * @param kie * @return true if the given kie is KEY_RETURN */ - public static boolean checkEnterHit(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_RETURN) { - return true; - } - return false; + public static boolean isEnterKey(KeyInputEvent kie) { + return (kie.getKeyCode() == KeyInput.KEY_RETURN); } /** @@ -190,11 +187,8 @@ public class ShortcutManager { * @param kie * @return true if the given kie is KEY_ESCAPE */ - public static boolean checkEscHit(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_ESCAPE) { - return true; - } - return false; + public static boolean isEscKey(KeyInputEvent kie) { + return (kie.getKeyCode() == KeyInput.KEY_ESCAPE); } /** @@ -202,11 +196,8 @@ public class ShortcutManager { * @param kie * @return true if the given kie is KEY_LCONTROL || KEY_RCONTROL */ - public static boolean checkCtrlHit(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_LCONTROL || kie.getKeyCode() == KeyInput.KEY_RCONTROL) { - return true; - } - return false; + public static boolean isCtrlKey(KeyInputEvent kie) { + return (kie.getKeyCode() == KeyInput.KEY_LCONTROL || kie.getKeyCode() == KeyInput.KEY_RCONTROL); } /** @@ -214,11 +205,8 @@ public class ShortcutManager { * @param kie * @return true if the given kie is KEY_LSHIFT || KEY_RSHIFT */ - public static boolean checkShiftHit(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_LSHIFT || kie.getKeyCode() == KeyInput.KEY_RSHIFT) { - return true; - } - return false; + public static boolean isShiftKey(KeyInputEvent kie) { + return (kie.getKeyCode() == KeyInput.KEY_LSHIFT || kie.getKeyCode() == KeyInput.KEY_RSHIFT); } /** @@ -226,9 +214,40 @@ public class ShortcutManager { * @param kie * @return true if the given kie is KEY_LMENU || KEY_RMENU */ - public static boolean checkAltHit(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_LMENU || kie.getKeyCode() == KeyInput.KEY_RMENU) { - return true; + public static boolean isAltKey(KeyInputEvent kie) { + return (kie.getKeyCode() == KeyInput.KEY_LMENU || kie.getKeyCode() == KeyInput.KEY_RMENU); + } + + /** + * + * @param kie + * @return + */ + public static boolean isNumberKey(KeyInputEvent kie) { + switch (kie.getKeyCode()) { + case KeyInput.KEY_MINUS: + case KeyInput.KEY_0: + case KeyInput.KEY_1: + case KeyInput.KEY_2: + case KeyInput.KEY_3: + case KeyInput.KEY_4: + case KeyInput.KEY_5: + case KeyInput.KEY_6: + case KeyInput.KEY_7: + case KeyInput.KEY_8: + case KeyInput.KEY_9: + case KeyInput.KEY_NUMPAD0: + case KeyInput.KEY_NUMPAD1: + case KeyInput.KEY_NUMPAD2: + case KeyInput.KEY_NUMPAD3: + case KeyInput.KEY_NUMPAD4: + case KeyInput.KEY_NUMPAD5: + case KeyInput.KEY_NUMPAD6: + case KeyInput.KEY_NUMPAD7: + case KeyInput.KEY_NUMPAD8: + case KeyInput.KEY_NUMPAD9: + case KeyInput.KEY_PERIOD: + return true; } return false; } @@ -236,65 +255,55 @@ public class ShortcutManager { /** * store the number kie into the numberBuilder * - * @param kie - * @param numberBuilder - * @return true if the given kie is handled as a number key event + * @param kie the KeiInputEvent to be handled as a number. + * @param numberBuilder the number builder that will be modified ! */ - public static boolean checkNumberKey(KeyInputEvent kie, StringBuilder numberBuilder) { - if (kie.getKeyCode() == KeyInput.KEY_MINUS) { - if (numberBuilder.length() > 0) { - if (numberBuilder.charAt(0) == '-') { - numberBuilder.replace(0, 1, ""); + public static void setNumberKey(KeyInputEvent kie, StringBuilder numberBuilder) { + switch (kie.getKeyCode()) { + case KeyInput.KEY_MINUS: + if (numberBuilder.length() > 0) { + if (numberBuilder.charAt(0) == '-') { + numberBuilder.replace(0, 1, ""); + } else { + numberBuilder.insert(0, '-'); + } } else { - numberBuilder.insert(0, '-'); + numberBuilder.append('-'); } - } else { - numberBuilder.append('-'); - } - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_0 || kie.getKeyCode() == KeyInput.KEY_NUMPAD0) { - numberBuilder.append('0'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_1 || kie.getKeyCode() == KeyInput.KEY_NUMPAD1) { - numberBuilder.append('1'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_2 || kie.getKeyCode() == KeyInput.KEY_NUMPAD2) { - numberBuilder.append('2'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_3 || kie.getKeyCode() == KeyInput.KEY_NUMPAD3) { - numberBuilder.append('3'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_4 || kie.getKeyCode() == KeyInput.KEY_NUMPAD4) { - numberBuilder.append('4'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_5 || kie.getKeyCode() == KeyInput.KEY_NUMPAD5) { - numberBuilder.append('5'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_6 || kie.getKeyCode() == KeyInput.KEY_NUMPAD6) { - numberBuilder.append('6'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_7 || kie.getKeyCode() == KeyInput.KEY_NUMPAD7) { - numberBuilder.append('7'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_8 || kie.getKeyCode() == KeyInput.KEY_NUMPAD8) { - numberBuilder.append('8'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_9 || kie.getKeyCode() == KeyInput.KEY_NUMPAD9) { - numberBuilder.append('9'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_PERIOD) { - if (numberBuilder.indexOf(".") == -1) { // if it doesn't exist yet - if (numberBuilder.length() == 0 - || (numberBuilder.length() == 1 && numberBuilder.charAt(0) == '-')) { - numberBuilder.append("0."); - } else { - numberBuilder.append("."); + break; + case KeyInput.KEY_0: + case KeyInput.KEY_1: + case KeyInput.KEY_2: + case KeyInput.KEY_3: + case KeyInput.KEY_4: + case KeyInput.KEY_5: + case KeyInput.KEY_6: + case KeyInput.KEY_7: + case KeyInput.KEY_8: + case KeyInput.KEY_9: + case KeyInput.KEY_NUMPAD0: + case KeyInput.KEY_NUMPAD1: + case KeyInput.KEY_NUMPAD2: + case KeyInput.KEY_NUMPAD3: + case KeyInput.KEY_NUMPAD4: + case KeyInput.KEY_NUMPAD5: + case KeyInput.KEY_NUMPAD6: + case KeyInput.KEY_NUMPAD7: + case KeyInput.KEY_NUMPAD8: + case KeyInput.KEY_NUMPAD9: + numberBuilder.append(kie.getKeyChar()); + break; + case KeyInput.KEY_PERIOD: + if (numberBuilder.indexOf(".") == -1) { // if it doesn't exist yet + if (numberBuilder.length() == 0 + || (numberBuilder.length() == 1 && numberBuilder.charAt(0) == '-')) { + numberBuilder.append("0."); + } else { + numberBuilder.append("."); + } } - } - return true; + break; } - - return false; } /** @@ -311,25 +320,42 @@ public class ShortcutManager { } /** - * Check for axis input for key X,Y,Z and store the corresponding UNIT_ into - * the axisStore + * Test if the given kie can be handled as en axis input by the getAxisKey() + * method. * - * @param kie - * @param axisStore - * @return true if the given kie is handled as a Axis input + * @param kie the KeyInputEvent to test + * @return true is the kie can be handled as an axis input, else false */ - public static boolean checkAxisKey(KeyInputEvent kie, Vector3f axisStore) { - if (kie.getKeyCode() == KeyInput.KEY_X) { - axisStore.set(Vector3f.UNIT_X); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_Y) { - axisStore.set(Vector3f.UNIT_Y); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_Z) { - axisStore.set(Vector3f.UNIT_Z); - return true; + public static boolean isAxisKey(KeyInputEvent kie) { + switch (kie.getKeyCode()) { + case KeyInput.KEY_X: + case KeyInput.KEY_Y: + case KeyInput.KEY_Z: + return true; } return false; } + /** + * Handle the Kie as an axis input : return a Vector3f from the kie keyCode. + * + * @param kie the KeyInputEvent to handle as an Axis + * @return UNIT_X for 'x', UNIT_Y for 'y' and UNIT_Z for 'z' kie. + */ + public static Vector3f getAxisKey(KeyInputEvent kie) { + Vector3f result = Vector3f.ZERO; + switch (kie.getKeyCode()) { + case KeyInput.KEY_X: + result = Vector3f.UNIT_X; + break; + case KeyInput.KEY_Y: + result = Vector3f.UNIT_Y; + break; + case KeyInput.KEY_Z: + result = Vector3f.UNIT_Z; + break; + } + return result; + } + } diff --git a/sdk/jme3-templates/nbproject/project.properties b/sdk/jme3-templates/nbproject/project.properties index 2e01f5d86..513fb20e4 100644 --- a/sdk/jme3-templates/nbproject/project.properties +++ b/sdk/jme3-templates/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:48 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=jMonkeyEngine nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-terrain-editor/nbproject/project.properties b/sdk/jme3-terrain-editor/nbproject/project.properties index a0916a395..0ed16b7c1 100644 --- a/sdk/jme3-terrain-editor/nbproject/project.properties +++ b/sdk/jme3-terrain-editor/nbproject/project.properties @@ -1,7 +1,7 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Brent Owens, Normen Hansen spec.version.base=3.1.0 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 index 1f7cfa66f..69d691908 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties @@ -124,7 +124,7 @@ TerrainEditorTopComponent.AbsoluteCheckbox.tooltip=Define the height to adjust t TerrainEditorTopComponent.slopeLockCheckbox.tooltip=Contains the slope between the two slope nodes TerrainEditorTopComponent.borderDistanceLabel.tooltip=Distance means how far from the terrain's edge the border will be raised (thickness of the border). TerrainEditorTopComponent.borderHeightLAbel.tooltip=Height means how high the border will go (also accept negative values). -TerrainEditorTopComponent.paintButton.toolTipText=Erase a texture from the terrain +TerrainEditorTopComponent.paintButton.toolTipText=Paint a texture on the terrain. RMB to Erase. TerrainEditorTopComponent.paintButton.text= RenameTerrainVisualPanel1.ranemeLabel.text=Rename Terrain Alphamaps RenameTerrainVisualPanel1.renameField.text= 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 index 9e12371ea..b99a24274 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java @@ -34,7 +34,7 @@ package com.jme3.gde.terraineditor; import com.jme3.gde.core.assets.AssetDataObject; import com.jme3.gde.core.assets.ProjectAssetManager; import com.jme3.gde.core.properties.TexturePropertyEditor; -import com.jme3.gde.core.properties.preview.DDSPreview; +import com.jme3.gde.core.properties.preview.TexturePreview; import com.jme3.gde.core.scene.PreviewRequest; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.scene.SceneListener; @@ -122,7 +122,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce //private TerrainNodeListener terrainDeletedNodeListener; private boolean availableNormalTextures; private HelpCtx ctx = new HelpCtx("sdk.terrain_editor"); - private DDSPreview ddsPreview; + private TexturePreview texPreview; private Map buttons = new HashMap(); private JPanel insideToolSettings; @@ -153,35 +153,29 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce private float max = 0; private final Object lock = new Object(); + @Override public void incrementProgress(float f) { progress += f; progressHandle.progress((int) progress); } + @Override 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); } -// } -// } -// }); } + @Override public float getMonitorMax() { return max; } + @Override public void progressComplete() { -// SwingUtilities.invokeLater(new Runnable() { -// public void run() { progressHandle.finish(); -// } -// }); } } @@ -1631,6 +1625,13 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce protected abstract Texture getTextureFromModel(int index); protected abstract boolean supportsNullTexture(); + + private TexturePreview getTexturePreview(){ + if (texPreview == null) { + texPreview = new TexturePreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); + } + return texPreview; + } private JButton getButton(Object value, final int row, final int column) { @@ -1656,21 +1657,9 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce } Texture tex = getTextureFromModel(index); // delegate to sub-class - - //Texture tex = SceneApplication.getApplication().getAssetManager().loadTexture((String)value); if (tex != null) { String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, lbl, null); - - } else { - Icon icon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - lbl.setIcon(icon); - } + getTexturePreview().requestPreview(selected, "", 80, 80, lbl, null); } } @@ -1694,24 +1683,17 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce TexturePropertyEditor editor = new TexturePropertyEditor(selectedTex); Component view = editor.getCustomEditor(); view.setVisible(true); - Texture tex = (Texture) editor.getValue(); - if (editor.getValue() != null) { - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, lbl, null); - - } else { - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - lbl.setIcon(newicon); - } + + if (editor.getAsText() != null) { + + String selected = editor.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, lbl, null); + Texture tex = SceneApplication.getApplication().getAssetManager().loadTexture(selected); + setTextureInModel(row, tex); } else if (supportsNullTexture()) { lbl.setIcon(null); } - setTextureInModel(row, tex); + } finally { alreadyChoosing = false; } 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 index e89175b76..d0072d06a 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java @@ -260,8 +260,7 @@ public class TerrainToolController extends SceneToolController { * The action on the tool has ended (mouse button up), record the Undo (for painting only now) */ void doTerrainEditToolActionEnded() { - if (terrainTool != null) { - System.out.println("undo tagged"); + if (terrainTool != null) { terrainTool.actionEnded(jmeRootNode, editorController.getCurrentDataObject()); } } 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 index b92aed679..146f1eb17 100644 --- 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 @@ -69,14 +69,16 @@ public class AddSkyboxAction extends AbstractNewSpatialWizardAction { } else { Texture textureSingle = (Texture) wiz.getProperty("textureSingle"); Vector3f normalScale = (Vector3f) wiz.getProperty("normalScale"); - boolean useSpheremap = (Boolean) wiz.getProperty("useSpheremap"); + SkyFactory.EnvMapType type = (SkyFactory.EnvMapType) wiz.getProperty("envMapType"); boolean flipY = (Boolean) wiz.getProperty("flipY"); // reload the texture so we can use flipY TextureKey key = (TextureKey) textureSingle.getKey(); TextureKey newKey = new TextureKey(key.getName(), flipY); newKey.setGenerateMips(true); - newKey.setAsCube(!useSpheremap); - return SkyFactory.createSky(pm, pm.loadTexture(newKey), normalScale, useSpheremap); + if(type == SkyFactory.EnvMapType.CubeMap){ + newKey.setTextureTypeHint(Texture.Type.CubeMap); + } + return SkyFactory.createSky(pm, pm.loadTexture(newKey), normalScale, type); } } 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 index 794a01ca7..550d79478 100644 --- 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 @@ -17,7 +17,6 @@ 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 @@ -32,3 +31,4 @@ SkyboxVisualPanel2.topPic.text= SkyboxVisualPanel2.bottomPic.text= SkyboxVisualPanel2.singlePic.text= SkyboxVisualPanel2.flipYcheckBox.text=Flip Y +SkyboxVisualPanel2.jLabel10.text=Map type 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 index 291361d1e..26439c888 100644 --- 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 @@ -1,4 +1,4 @@ - +
    @@ -127,7 +127,7 @@ - + @@ -172,7 +172,7 @@ - + @@ -376,11 +376,17 @@ + - + + + + + + - + @@ -391,12 +397,8 @@ - - - - - + @@ -420,7 +422,10 @@ - + + + + @@ -474,24 +479,39 @@ - + - + - + - + - + + + + + + + + + + + + + + + + - + 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 index 7abe313dd..9e3cd0396 100644 --- 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 @@ -33,10 +33,12 @@ package com.jme3.gde.terraineditor.sky; import com.jme3.gde.core.assets.ProjectAssetManager; import com.jme3.gde.core.properties.TexturePropertyEditor; -import com.jme3.gde.core.properties.preview.DDSPreview; +import com.jme3.gde.core.properties.preview.TexturePreview; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.texture.Texture; +import com.jme3.util.SkyFactory; import java.awt.Component; +import javax.swing.DefaultComboBoxModel; import javax.swing.Icon; import javax.swing.JCheckBox; import javax.swing.JPanel; @@ -46,11 +48,17 @@ import org.openide.util.ImageUtilities; public final class SkyboxVisualPanel2 extends JPanel { - private DDSPreview ddsPreview; + private TexturePreview texPreview; /** Creates new form SkyboxVisualPanel2 */ public SkyboxVisualPanel2() { initComponents(); + + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (SkyFactory.EnvMapType value : SkyFactory.EnvMapType.values()) { + model.addElement(value); + } + mapTypeCombo.setModel(model); } @Override @@ -101,6 +109,14 @@ public final class SkyboxVisualPanel2 extends JPanel { return editorWest; } + + private TexturePreview getTexturePreview(){ + if (texPreview == null) { + texPreview = new TexturePreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); + } + return texPreview; + } + /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is @@ -140,11 +156,12 @@ public final class SkyboxVisualPanel2 extends JPanel { 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(); flipYcheckBox = new javax.swing.JCheckBox(); + mapTypeCombo = new javax.swing.JComboBox(); + jLabel10 = new javax.swing.JLabel(); - titleLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); + titleLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N 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 @@ -279,7 +296,7 @@ public final class SkyboxVisualPanel2 extends JPanel { .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)) + .addContainerGap(29, Short.MAX_VALUE)) ); multipleTexturePanelLayout.setVerticalGroup( multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -315,7 +332,7 @@ public final class SkyboxVisualPanel2 extends JPanel { .addGroup(multipleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel5) .addComponent(multipleTexTopLoadButton)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .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) @@ -346,12 +363,19 @@ public final class SkyboxVisualPanel2 extends JPanel { 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 org.openide.awt.Mnemonics.setLocalizedText(flipYcheckBox, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.flipYcheckBox.text")); // NOI18N + mapTypeCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + mapTypeCombo.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + mapTypeComboActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel10, org.openide.util.NbBundle.getMessage(SkyboxVisualPanel2.class, "SkyboxVisualPanel2.jLabel10.text")); // NOI18N + javax.swing.GroupLayout singleTexturePanelLayout = new javax.swing.GroupLayout(singleTexturePanel); singleTexturePanel.setLayout(singleTexturePanelLayout); singleTexturePanelLayout.setHorizontalGroup( @@ -359,11 +383,16 @@ public final class SkyboxVisualPanel2 extends JPanel { .addGroup(singleTexturePanelLayout.createSequentialGroup() .addContainerGap() .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(flipYcheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(singleTexturePanelLayout.createSequentialGroup() - .addComponent(jLabel8) + .addComponent(jLabel10) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(mapTypeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 166, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(singleTexturePanelLayout.createSequentialGroup() + .addComponent(jLabel8) + .addGap(21, 21, 21) .addComponent(singleTexLoadButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGap(2, 2, 2) .addComponent(singlePic, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(39, 39, 39) .addComponent(jLabel9) @@ -372,11 +401,8 @@ public final class SkyboxVisualPanel2 extends JPanel { .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)) - .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(flipYcheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(spheremapCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addContainerGap(31, Short.MAX_VALUE)) + .addComponent(normal2Z, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); singleTexturePanelLayout.setVerticalGroup( singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -394,7 +420,9 @@ public final class SkyboxVisualPanel2 extends JPanel { .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) + .addGroup(singleTexturePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(mapTypeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel10)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(flipYcheckBox) .addContainerGap(75, Short.MAX_VALUE)) @@ -428,148 +456,76 @@ public final class SkyboxVisualPanel2 extends JPanel { 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(); - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, southPic, null); - - } else { - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - southPic.setIcon(newicon); - } + if (editorSouth.getAsText()!= null) { + String selected = editorSouth.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, southPic, null); } }//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(); - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, northPic, null); - - } else { - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - northPic.setIcon(newicon); - } + if (editorNorth.getAsText() != null) { + String selected = editorNorth.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, northPic, null); } }//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(); - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, eastPic, null); - - } else { - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - eastPic.setIcon(newicon); - } + if (editorEast.getAsText() != null) { + String selected = editorEast.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, eastPic, null); } }//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(); - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, westPic, null); - - } else { - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - westPic.setIcon(newicon); - } + if (editorWest.getAsText() != null) { + String selected = editorWest.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, westPic, null); } }//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(); - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, topPic, null); - - } else { - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - topPic.setIcon(newicon); - } + if (editorTop.getAsText() != null) { + String selected = editorTop.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, topPic, null); } }//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(); - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, bottomPic, null); - - } else { - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - bottomPic.setIcon(newicon); - } + if (editorBottom.getAsText() != null) { + String selected = editorBottom.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, bottomPic, null); } }//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(); - String selected = tex.getKey().getName(); - - if (selected.toLowerCase().endsWith(".dds")) { - if (ddsPreview == null) { - ddsPreview = new DDSPreview((ProjectAssetManager) SceneApplication.getApplication().getAssetManager()); - } - ddsPreview.requestPreview(selected, "", 80, 80, singlePic, null); - - } else { - - Icon newicon = ImageUtilities.image2Icon(ImageToAwt.convert(tex.getImage(), false, true, 0)); - singlePic.setIcon(newicon); - } + if (editorSingle.getAsText()!= null) { + String selected = editorSingle.getAsText(); + getTexturePreview().requestPreview(selected, "", 80, 80, singlePic, null); } }//GEN-LAST:event_singleTexLoadButtonActionPerformed + + private void mapTypeComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mapTypeComboActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_mapTypeComboActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel bottomPic; private javax.swing.JLabel eastPic; private javax.swing.JCheckBox flipYcheckBox; private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel10; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; @@ -578,6 +534,7 @@ public final class SkyboxVisualPanel2 extends JPanel { private javax.swing.JLabel jLabel7; private javax.swing.JLabel jLabel8; private javax.swing.JLabel jLabel9; + private javax.swing.JComboBox mapTypeCombo; private javax.swing.JButton multipleTexBottomLoadButton; private javax.swing.JButton multipleTexEastLoadButton; private javax.swing.JButton multipleTexNorthLoadButton; @@ -596,7 +553,6 @@ public final class SkyboxVisualPanel2 extends JPanel { 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; @@ -626,10 +582,11 @@ public final class SkyboxVisualPanel2 extends JPanel { return normal2Z; } - public JCheckBox getSpheremapCheckBox() { - return spheremapCheckBox; + public SkyFactory.EnvMapType getEnvMapType(){ + return (SkyFactory.EnvMapType)mapTypeCombo.getSelectedItem(); } + public JCheckBox getFlipYCheckBox() { return flipYcheckBox; } 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 index 67ab8e0f7..267751ab4 100644 --- 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 @@ -123,6 +123,7 @@ public class SkyboxWizardPanel2 implements WizardDescriptor.Panel { } } + @Override public void storeSettings(Object settings) { WizardDescriptor wiz = (WizardDescriptor) settings; SkyboxVisualPanel2 comp = (SkyboxVisualPanel2) getComponent(); @@ -143,7 +144,7 @@ public class SkyboxWizardPanel2 implements WizardDescriptor.Panel { 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()); + wiz.putProperty("envMapType", comp.getEnvMapType()); wiz.putProperty("flipY", comp.getFlipYCheckBox().isSelected()); } } diff --git a/sdk/jme3-tests-template/nbproject/project.properties b/sdk/jme3-tests-template/nbproject/project.properties index 2e01f5d86..513fb20e4 100644 --- a/sdk/jme3-tests-template/nbproject/project.properties +++ b/sdk/jme3-tests-template/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:48 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=jMonkeyEngine nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/testsdesktop/Bundle.properties b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/testsdesktop/Bundle.properties index 189077573..c5264da33 100644 --- a/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/testsdesktop/Bundle.properties +++ b/sdk/jme3-tests-template/src/com/jme3/gde/templates/tests/testsdesktop/Bundle.properties @@ -1,7 +1,7 @@ # To change this license header, choose License Headers in Project Properties. # To change this template file, choose Tools | Templates # and open the template in the editor. - +LBL_CreateProjectStep=Name and Location JmeTestsPanelVisual.projectNameLabel.text=Project &Name: JmeTestsPanelVisual.projectLocationLabel.text=Project &Location: JmeTestsPanelVisual.browseButton.actionCommand=BROWSE diff --git a/sdk/jme3-texture-editor/nbproject/project.properties b/sdk/jme3-texture-editor/nbproject/project.properties index c4186f216..c3e2aa46a 100644 --- a/sdk/jme3-texture-editor/nbproject/project.properties +++ b/sdk/jme3-texture-editor/nbproject/project.properties @@ -1,8 +1,8 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=pgi nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jme3-vehicle-creator/nbproject/project.properties b/sdk/jme3-vehicle-creator/nbproject/project.properties index 44c34ecb9..0411b6ff9 100644 --- a/sdk/jme3-vehicle-creator/nbproject/project.properties +++ b/sdk/jme3-vehicle-creator/nbproject/project.properties @@ -1,4 +1,4 @@ #Thu, 25 Aug 2011 20:26:50 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial spec.version.base=3.1.0 diff --git a/sdk/jme3-wavefront/nbproject/project.properties b/sdk/jme3-wavefront/nbproject/project.properties index 9d2616783..98f519f77 100644 --- a/sdk/jme3-wavefront/nbproject/project.properties +++ b/sdk/jme3-wavefront/nbproject/project.properties @@ -1,4 +1,4 @@ #Thu, 25 Aug 2011 20:26:49 +0200 -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial spec.version.base=3.1.0 diff --git a/sdk/jme3-welcome-screen/nbproject/project.properties b/sdk/jme3-welcome-screen/nbproject/project.properties index 99dbdf441..ae558b0e0 100644 --- a/sdk/jme3-welcome-screen/nbproject/project.properties +++ b/sdk/jme3-welcome-screen/nbproject/project.properties @@ -1,7 +1,7 @@ -javac.source=1.5 +javac.source=1.6 javac.compilerargs=-Xlint -Xlint\:-serial license.file=../license-jme.txt -nbm.homepage=http\://www.jmonkeyengine.com +nbm.homepage=http\://www.jmonkeyengine.org nbm.module.author=Normen Hansen, jiyarza nbm.needs.restart=true spec.version.base=3.1.0 diff --git a/sdk/jmonkeyplatform.png b/sdk/jmonkeyplatform.png index eee01902f..36675de77 100644 Binary files a/sdk/jmonkeyplatform.png and b/sdk/jmonkeyplatform.png differ diff --git a/sdk/license-jme.txt b/sdk/license-jme.txt index 9f1503915..9c2661e5b 100644 --- a/sdk/license-jme.txt +++ b/sdk/license-jme.txt @@ -1,4 +1,4 @@ -Copyright (c) 2003-2012 jMonkeyEngine +Copyright (c) 2003-2015 jMonkeyEngine All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sdk/nbi/stub/ext/components/products/blender/nbproject/build-impl.xml b/sdk/nbi/stub/ext/components/products/blender/nbproject/build-impl.xml index 6b25635be..f15304e39 100644 --- a/sdk/nbi/stub/ext/components/products/blender/nbproject/build-impl.xml +++ b/sdk/nbi/stub/ext/components/products/blender/nbproject/build-impl.xml @@ -54,6 +54,7 @@ is divided into following sections: + @@ -71,16 +72,20 @@ is divided into following sections: - + - - + + + - - - + + + + + + @@ -91,12 +96,6 @@ is divided into following sections: - - - - - - @@ -115,24 +114,12 @@ is divided into following sections: - + - + - - - - - - - - - - - - @@ -186,7 +173,15 @@ is divided into following sections: - + + + + + + + + + @@ -275,6 +270,7 @@ is divided into following sections: + @@ -314,6 +310,7 @@ is divided into following sections: + @@ -370,6 +367,11 @@ is divided into following sections: + + + + + @@ -393,7 +395,7 @@ is divided into following sections: - + @@ -407,6 +409,9 @@ is divided into following sections: + + + @@ -438,7 +443,7 @@ is divided into following sections: - + @@ -534,7 +539,7 @@ is divided into following sections: - + @@ -548,6 +553,9 @@ is divided into following sections: + + + @@ -826,8 +834,8 @@ is divided into following sections: - - + + @@ -839,7 +847,7 @@ is divided into following sections: - + @@ -894,6 +902,7 @@ is divided into following sections: + @@ -927,7 +936,7 @@ is divided into following sections: - + @@ -962,41 +971,25 @@ is divided into following sections: - - - - - - - - - - - - - To run this application from the command line without Ant, try: - - - - - - - java -cp "${run.classpath.with.dist.jar}" ${main.class} - - + - + - + - + + + + + + @@ -1004,23 +997,41 @@ is divided into following sections: - + 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 -cp "${run.classpath.with.dist.jar}" ${main.class} - - + - + - + - + + + + + + @@ -1004,23 +997,41 @@ is divided into following sections: - + 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 -cp "${run.classpath.with.dist.jar}" ${main.class} - - + - + - + - + + + + + + @@ -1004,23 +997,41 @@ is divided into following sections: - + 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 -cp "${run.classpath.with.dist.jar}" ${main.class} - - + - + - + - + + + + + + @@ -1004,23 +997,41 @@ is divided into following sections: - + To run this application from the command line without Ant, try: java -jar "${dist.jar.resolved}" - + + + + + + + + + + + + + + + + + - + + - + + + + diff --git a/sdk/nbproject/platform.properties b/sdk/nbproject/platform.properties index 73f8590d7..65b38a709 100644 --- a/sdk/nbproject/platform.properties +++ b/sdk/nbproject/platform.properties @@ -1,4 +1,6 @@ branding.token=jmonkeyplatform +keystore=../nbproject/private/keystore.jks +nbm_alias=jmeupdates cluster.path=\ ${nbplatform.active.dir}/extide:\ ${nbplatform.active.dir}/harness:\ diff --git a/sdk/nbproject/project.properties b/sdk/nbproject/project.properties index dbcdb7343..64104ff3a 100644 --- a/sdk/nbproject/project.properties +++ b/sdk/nbproject/project.properties @@ -3,13 +3,16 @@ app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif #same as ${branding.token} app.name=jmonkeyplatform app.title=jMonkeyEngine SDK +app.description=A complete 3D game development suite written purely in Java. +app.categories=Development,Graphics,IDE,3DGraphics,Java app.icon.icns=jmonkeyplatform.icns #version name used for application and settings folder, no spaces! app.version=3.1-snapshot-github #version number used for plugins, only 3 numbers (e.g. 3.1.3) plugins.version=3.1.0 +nbm.revision=0 #command line args -run.args.extra=-J-Xmx512m -J-XX\:PermSize\=128m -J-XX\:MaxDirectMemorySize\=2048m -J-Dsun.zip.disableMemoryMapping\=true -J-Dapple.awt.graphics.UseQuartz\=true -J-Dsun.java2d.noddraw\=true +run.args.extra=-J-Dsun.java2d.dpiaware\=true -J-Dapple.laf.useScreenMenuBar\=true -J-Dawt.useSystemAAFontSettings\=lcd -J-Dswing.aatext\=true -J-Xmx512m -J-XX\:MaxDirectMemorySize\=2048m -J-Dsun.zip.disableMemoryMapping\=true -J-Dapple.awt.graphics.UseQuartz\=true -J-Dsun.java2d.noddraw\=true 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 @@ -48,7 +51,8 @@ modules=\ ${project.com.jme3.gde.angelfont}:\ ${project.com.jme3.gde.android}:\ ${project.com.jme3.gde.nmgen}:\ - ${project.com.jme3.gde.docs} + ${project.com.jme3.gde.docs}:\ + ${project.org.jme3.netbeans.plaf.darkmonkey} project.com.jme3.gde.android=jme3-android project.com.jme3.gde.angelfont=jme3-angelfont project.com.jme3.gde.blender=jme3-blender @@ -82,3 +86,4 @@ 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 +project.org.jme3.netbeans.plaf.darkmonkey=jme3-dark-laf diff --git a/settings.gradle b/settings.gradle index 89b8fc075..106a609bf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,6 +15,7 @@ include 'jme3-desktop' include 'jme3-blender' include 'jme3-jogl' include 'jme3-lwjgl' +include 'jme3-lwjgl3' // Other external dependencies include 'jme3-jbullet' @@ -36,7 +37,7 @@ include 'jme3-testdata' include 'jme3-examples' if(buildAndroidExamples == "true"){ - include 'jme3-android-examples' + include 'jme3-android-examples' } if(buildSdkProject == "true"){ diff --git a/upload.gradle b/upload.gradle new file mode 100644 index 000000000..e28f5f41b --- /dev/null +++ b/upload.gradle @@ -0,0 +1,6 @@ +task copySshKnownHosts(type: Copy) { + from 'private/known_hosts' + into System.properties['user.home'] + '/.ssh' +} + +uploadArchives.dependsOn copySshKnownHosts \ No newline at end of file diff --git a/version.gradle b/version.gradle new file mode 100644 index 000000000..40e934278 --- /dev/null +++ b/version.gradle @@ -0,0 +1,117 @@ +/* + Version Info Examples + ===================== + + Nightly Build Snapshot + * Full Version: 3.1-5124 + * POM Version: 3.1.0-SNAPSHOT + * NBM Revision: 5124 + * NBM UC Suffix: nightly/3.1/plugins + + Nightly Build Snapshot (PBRIsComing branch) + * Full Version: 3.1-PBRIsComing-5124 + * POM Version: 3.1.0-PBRIsComing-SNAPSHOT + * NBM Revision: 5124 + * NBM UC Suffix: PBRIsComing-nightly/3.1/plugins + + Alpha1 Release + * Full Version: 3.1-alpha1 + * POM Version: 3.1.0-alpha1 + * NBM Revision: 1 + * NBM UC Suffix: stable/3.1/plugins + + Final Release + * Full Version: 3.1 + * POM Version: 3.1.0 + * NBM Revision: 5 + * NBM UC Suffix: stable/3.1/plugins + */ + +import java.text.SimpleDateFormat +import org.ajoberstar.grgit.* + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'org.ajoberstar:gradle-git:1.2.0' + } +} + +ext { + jmeRevision = 0 + jmeNbmRevision = 0 + jmeGitHash = "" + jmeGitTag = "" + jmeShortGitHash = "" + jmeBuildDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + jmeBranchName = "unknown" + jmeFullVersion = "${jmeVersion}-UNKNOWN" + jmePomVersion = "unknown" + jmeNbmUcSuffix = "unknown" +} + +task configureVersionInfo { + try { + def grgit = Grgit.open(project.file('.')) + jmeRevision = grgit.log(includes:['HEAD']).size() + jmeGitHash = grgit.head().id + jmeShortGitHash = grgit.head().abbreviatedId + jmeBranchName = grgit.branch.current.name + jmeGitTag = grgit.describe() + if (jmeGitTag == null) jmeGitTag = "" + + if (System.env.TRAVIS_BRANCH != null) { + jmeBranchName = System.env.TRAVIS_BRANCH + } + if (System.env.TRAVIS_TAG != null) { + jmeGitTag = System.env.TRAVIS_TAG + } + if (System.env.TRAVIS_PULL_REQUEST != null && + System.env.TRAVIS_PULL_REQUEST != "false") { + jmeBranchName += "-pr-" + System.env.TRAVIS_PULL_REQUEST + } + + jmeFullVersion = jmeMainVersion + jmePomVersion = jmeVersion + + if (jmeBranchName != "master") { + jmeFullVersion += "-${jmeBranchName}" + jmePomVersion += "-${jmeBranchName}" + + jmeNbmUcSuffix = "${jmeBranchName}-" + } else { + jmeNbmUcSuffix = "" + } + + if (jmeVersionTag == "SNAPSHOT") { + jmeNbmUcSuffix += "nightly" + } else { + jmeNbmUcSuffix += "stable" + } + + jmeNbmUcSuffix += "/" + jmeMainVersion + "/plugins" + + if (jmeVersionTag == "SNAPSHOT") { + jmeFullVersion += "-${jmeRevision}" + jmePomVersion += "-SNAPSHOT" + jmeNbmRevision = jmeRevision + } else if (jmeVersionTag == "") { + jmeNbmRevision = jmeVersionTagID + } else { + jmeFullVersion += "-${jmeVersionTag}" + jmePomVersion += "-${jmeVersionTag}" + jmeNbmRevision = jmeVersionTagID + } + + logger.warn("Full Version: ${jmeFullVersion}") + logger.warn("POM Version: ${jmePomVersion}") + logger.warn("NBM Revision: ${jmeNbmRevision}") + logger.warn("NBM UC Suffix: ${jmeNbmUcSuffix}") + } catch (ex) { + // Failed to get repo info + logger.warn("Failed to get repository info: " + ex.message + ". " + \ + "Only partial build info will be generated.") + } +}