Merge branch 'master' into PBRisComing

define_list_fix
Nehon 10 years ago
commit c50f0426bf
  1. 1
      .gitignore
  2. 37
      build.gradle
  3. 13
      common-android-app.gradle
  4. 1
      gradle.properties
  5. 40
      jme3-android-examples/build.gradle
  6. 20
      jme3-android-examples/src/main/AndroidManifest.xml
  7. 12
      jme3-android-examples/src/main/java/jme3test/android/TestChooserAndroid.java
  8. 6
      jme3-android-examples/src/main/res/values/strings.xml
  9. 2549
      jme3-android/src/main/java/com/jme3/renderer/android/OGLESShaderRenderer.java
  10. 25
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/FileBlockHeader.java
  11. BIN
      jme3-bullet-native/libs/native/windows/x86/bulletjme.dll
  12. BIN
      jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll
  13. 22
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  14. 2
      jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java
  15. 2
      jme3-core/src/main/java/com/jme3/shadow/BasicShadowRenderer.java
  16. 2
      jme3-core/src/main/java/com/jme3/shadow/PssmShadowRenderer.java
  17. 39
      jme3-core/src/main/resources/Common/ShaderLib/MultiSample.glsllib
  18. 5
      jme3-examples/build.gradle
  19. 5
      jme3-examples/gradle.properties
  20. 2695
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglRenderer.java
  21. 514
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/TextureUtil.java
  22. 2
      jme3-networking/src/main/java/com/jme3/network/service/rpc/msg/RpcCallMessage.java
  23. 1
      local.properties
  24. 53
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java
  25. 204
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveManager.java
  26. 12
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/PickManager.java
  27. 11
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/RotateTool.java
  28. 694
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java
  29. 123
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java
  30. 141
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DuplicateShortcut.java
  31. 227
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java
  32. 189
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java
  33. 199
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java
  34. 335
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java
  35. 29
      sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutTool.java
  36. 4
      settings.gradle

1
.gitignore vendored

@ -10,6 +10,7 @@
/jme3-desktop/build/
/jme3-android-native/build/
/jme3-android/build/
/jme3-android-examples/build/
/jme3-blender/build/
/jme3-effects/build/
/jme3-bullet/build/

@ -1,14 +1,23 @@
import org.gradle.api.artifacts.*
apply plugin: 'base' // To add "clean" task to the root project.
//apply plugin: 'java-library-distribution'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
}
}
apply plugin: 'base'
// This is applied to all sub projects
subprojects {
// Don't add to native builds
// if(!project.name.endsWith('native')){
apply from: rootProject.file('common.gradle')
// }
if(!project.name.equals('jme3-android-examples')) {
apply from: rootProject.file('common.gradle')
} else {
apply from: rootProject.file('common-android-app.gradle')
}
}
task run(dependsOn: ':jme3-examples:run') {
@ -166,11 +175,11 @@ ext {
// }
//}
allprojects {
tasks.withType(JavaExec) {
enableAssertions = true // false by default
}
tasks.withType(Test) {
enableAssertions = true // true by default
}
}
//allprojects {
// tasks.withType(JavaExec) {
// enableAssertions = true // false by default
// }
// tasks.withType(Test) {
// enableAssertions = true // true by default
// }
//}

@ -0,0 +1,13 @@
apply plugin: 'com.android.application'
group = 'com.jme3'
version = jmeVersion + '-' + jmeVersionTag
sourceCompatibility = '1.6'
repositories {
mavenCentral()
maven {
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
}
}

@ -11,6 +11,7 @@ buildJavaDoc = true
# specify if SDK and Native libraries get built
buildSdkProject = true
buildNativeProjects = false
buildAndroidExamples = false
# Path to android NDK for building native libraries
#ndkPath=/Users/normenhansen/Documents/Code-Import/android-ndk-r7

@ -0,0 +1,40 @@
dependencies {
compile project(':jme3-core')
compile project(':jme3-android')
compile project(':jme3-effects')
compile project(':jme3-bullet')
compile project(':jme3-bullet-native-android')
compile project(':jme3-networking')
compile project(':jme3-niftygui')
compile project(':jme3-plugins')
compile project(':jme3-terrain')
compile project(':jme3-testdata')
}
android {
compileSdkVersion 10
buildToolsVersion "22.0.1"
lintOptions {
// Fix nifty gui referencing "java.awt" package.
disable 'InvalidPackage'
}
defaultConfig {
applicationId "com.jme3.android"
minSdkVersion 10 // Android 2.3 GINGERBREAD
targetSdkVersion 22 // Android 5.1 LOLLIPOP
versionCode 1
versionName "1.0" // TODO: from settings.gradle
}
buildTypes {
release {
minifyEnabled false
}
debug {
applicationIdSuffix ".debug"
debuggable true
}
}
}

@ -0,0 +1,20 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jme3.android">
<!-- Tell the system that you need ES 2.0. -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<!-- Tell the system that you need distinct touches (for the zoom gesture). -->
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="true" />
<application android:label="@string/app_name" android:allowBackup="true">
<activity android:name="jme3test.android.TestChooserAndroid"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

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

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">JMEAndroidTest</string>
<string name="about">About</string>
<string name="quit">Quit</string>
</resources>

@ -31,6 +31,7 @@
*/
package com.jme3.scene.plugins.blender.file;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.scene.plugins.blender.BlenderContext;
@ -171,8 +172,21 @@ public class FileBlockHeader {
BLOCK_IP00('I' << 24 | 'P' << 16), // ipo
BLOCK_AC00('A' << 24 | 'C' << 16), // action
BLOCK_IM00('I' << 24 | 'M' << 16), // image
BLOCK_TE00('T' << 24 | 'E' << 16), BLOCK_WM00('W' << 24 | 'M' << 16), BLOCK_SR00('S' << 24 | 'R' << 16), BLOCK_SN00('S' << 24 | 'N' << 16), BLOCK_BR00('B' << 24 | 'R' << 16), BLOCK_LS00('L' << 24 | 'S' << 16), BLOCK_GLOB('G' << 24 | 'L' << 16 | 'O' << 8 | 'B'), BLOCK_REND('R' << 24 | 'E' << 16 | 'N' << 8 | 'D'), BLOCK_DATA('D' << 24 | 'A' << 16 | 'T' << 8 | 'A'), BLOCK_DNA1('D' << 24 | 'N' << 16 | 'A' << 8 | '1'), BLOCK_ENDB('E' << 24 | 'N' << 16 | 'D' << 8 | 'B'), BLOCK_TEST('T' << 24 | 'E' << 16
| 'S' << 8 | 'T'), BLOCK_UNKN(0);
BLOCK_TE00('T' << 24 | 'E' << 16),
BLOCK_WM00('W' << 24 | 'M' << 16),
BLOCK_SR00('S' << 24 | 'R' << 16),
BLOCK_SN00('S' << 24 | 'N' << 16),
BLOCK_BR00('B' << 24 | 'R' << 16),
BLOCK_LS00('L' << 24 | 'S' << 16),
BLOCK_GR00('G' << 24 | 'R' << 16),
BLOCK_AR00('A' << 24 | 'R' << 16),
BLOCK_GLOB('G' << 24 | 'L' << 16 | 'O' << 8 | 'B'),
BLOCK_REND('R' << 24 | 'E' << 16 | 'N' << 8 | 'D'),
BLOCK_DATA('D' << 24 | 'A' << 16 | 'T' << 8 | 'A'),
BLOCK_DNA1('D' << 24 | 'N' << 16 | 'A' << 8 | '1'),
BLOCK_ENDB('E' << 24 | 'N' << 16 | 'D' << 8 | 'B'),
BLOCK_TEST('T' << 24 | 'E' << 16 | 'S' << 8 | 'T'),
BLOCK_UNKN(0);
private int code;
@ -187,7 +201,12 @@ public class FileBlockHeader {
}
}
byte[] codeBytes = new byte[] { (byte) (code >> 24 & 0xFF), (byte) (code >> 16 & 0xFF), (byte) (code >> 8 & 0xFF), (byte) (code & 0xFF) };
LOGGER.warning("Unknown block header: " + new String(codeBytes));
for (int i = 0; i < codeBytes.length; ++i) {
if (codeBytes[i] == 0) {
codeBytes[i] = '0';
}
}
LOGGER.log(Level.WARNING, "Unknown block header: {0}", new String(codeBytes));
return BLOCK_UNKN;
}
}

@ -84,21 +84,6 @@ public class GLRenderer implements Renderer {
private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
private final EnumMap<Limits, Integer> limits = new EnumMap<Limits, Integer>(Limits.class);
// 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 mainFbOverride = null;
private final Statistics statistics = new Statistics();
private int vpX, vpY, vpW, vpH;
@ -366,7 +351,6 @@ public class GLRenderer implements Renderer {
if (hasExtension("GL_ARB_texture_non_power_of_two") ||
hasExtension("GL_OES_texture_npot") ||
hasExtension("GL_APPLE_texture_2D_limited_npot") ||
caps.contains(Caps.OpenGL30)) {
caps.add(Caps.NonPowerOfTwoTextures);
} else {
@ -1859,10 +1843,6 @@ public class GLRenderer implements Renderer {
}
}
if (context.pointSprite) {
return; // Attempt to fix glTexParameter crash for some ATI GPUs
}
// repeat modes
switch (tex.getType()) {
case ThreeDimensional:
@ -2671,7 +2651,7 @@ public class GLRenderer implements Renderer {
public void setMainFrameBufferSrgb(boolean enableSrgb) {
// Gamma correction
if (!caps.contains(Caps.Srgb)) {
if (!caps.contains(Caps.Srgb) && enableSrgb) {
// Not supported, sorry.
logger.warning("sRGB framebuffer is not supported " +
"by video hardware, but was requested.");

@ -424,7 +424,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
renderManager.setCamera(shadowCam, false);
renderManager.getRenderer().setFrameBuffer(shadowFB[shadowMapIndex]);
renderManager.getRenderer().clearBuffers(false, true, false);
renderManager.getRenderer().clearBuffers(true, true, true);
// render shadow casters to shadow map
viewPort.getQueue().renderShadowQueue(shadowMapOccluders, renderManager, shadowCam, true);

@ -190,7 +190,7 @@ public class BasicShadowRenderer implements SceneProcessor {
renderManager.setForcedMaterial(preshadowMat);
r.setFrameBuffer(shadowFB);
r.clearBuffers(false, true, false);
r.clearBuffers(true, true, true);
viewPort.getQueue().renderShadowQueue(shadowOccluders, renderManager, shadowCam, true);
r.setFrameBuffer(viewPort.getOutputFrameBuffer());

@ -450,7 +450,7 @@ public class PssmShadowRenderer implements SceneProcessor {
}
r.setFrameBuffer(shadowFB[i]);
r.clearBuffers(false, true, false);
r.clearBuffers(true, true, true);
// render shadow casters to shadow map
viewPort.getQueue().renderShadowQueue(splitOccluders, renderManager, shadowCam, true);

@ -15,8 +15,14 @@ uniform int m_NumSamplesDepth;
#define DEPTHTEXTURE sampler2D
#endif
// NOTE: Only define multisample functions if multisample is available and is being used!
#if defined(GL_ARB_texture_multisample) && (defined(RESOLVE_MS) || defined(RESOLVE_DEPTH_MS))
#if __VERSION__ >= 150
#define TEXTURE texture
#else
#define TEXTURE texture2D
#endif
// NOTE: Only define multisample functions if multisample is available
#if defined(GL_ARB_texture_multisample)
vec4 textureFetch(in sampler2DMS tex,in vec2 texC, in int numSamples){
ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
vec4 color = vec4(0.0);
@ -44,40 +50,21 @@ vec4 getDepth(in sampler2DMS tex,in vec2 texC){
return textureFetch(tex,texC,m_NumSamplesDepth);
}
#elif __VERSION__ >= 150
vec4 fetchTextureSample(in sampler2D tex,in vec2 texC,in int sample){
return texture(tex,texC);
}
vec4 getColor(in sampler2D tex, in vec2 texC){
return texture(tex,texC);
}
vec4 getColorSingle(in sampler2D tex, in vec2 texC){
return texture(tex, texC);
}
vec4 getDepth(in sampler2D tex,in vec2 texC){
return texture(tex,texC);
}
#else
#endif
vec4 fetchTextureSample(in sampler2D tex,in vec2 texC,in int sample){
return texture2D(tex,texC);
return TEXTURE(tex,texC);
}
vec4 getColor(in sampler2D tex, in vec2 texC){
return texture2D(tex,texC);
return TEXTURE(tex,texC);
}
vec4 getColorSingle(in sampler2D tex, in vec2 texC){
return texture2D(tex, texC);
return TEXTURE(tex, texC);
}
vec4 getDepth(in sampler2D tex,in vec2 texC){
return texture2D(tex,texC);
return TEXTURE(tex,texC);
}
#endif

@ -6,7 +6,10 @@ if (!hasProperty('mainClass')) {
task run(dependsOn: 'build', type:JavaExec) {
main = mainClass
classpath = sourceSets.main.runtimeClasspath
classpath = sourceSets.main.runtimeClasspath
if( assertions == "true" ){
enableAssertions = true;
}
}
dependencies {

@ -0,0 +1,5 @@
# When running this project we don't need javadoc to be built.
buildJavaDoc = false
# We want assertions, because this is the test project.
assertions = true

@ -1,514 +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.lwjgl;
import com.jme3.renderer.Caps;
import com.jme3.renderer.RendererException;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.texture.image.ColorSpace;
import java.nio.ByteBuffer;
import java.util.EnumSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.lwjgl.opengl.ARBDepthBufferFloat.*;
import static org.lwjgl.opengl.ARBES3Compatibility.*;
import static org.lwjgl.opengl.ARBHalfFloatPixel.*;
import static org.lwjgl.opengl.ARBTextureFloat.*;
import static org.lwjgl.opengl.ARBTextureMultisample.*;
import static org.lwjgl.opengl.EXTPackedDepthStencil.*;
import static org.lwjgl.opengl.EXTPackedFloat.*;
import static org.lwjgl.opengl.EXTTextureArray.*;
import static org.lwjgl.opengl.EXTTextureCompressionS3TC.*;
import static org.lwjgl.opengl.EXTTextureSRGB.*;
import static org.lwjgl.opengl.EXTTextureSharedExponent.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*;
/**
*
* Should not be used, has been replaced by Unified Rendering Architechture.
* @deprecated
*/
@Deprecated
class TextureUtil {
static class GLImageFormat {
int internalFormat;
int format;
int dataType;
boolean compressed;
public GLImageFormat(int internalFormat, int format, int dataType, boolean compressed) {
this.internalFormat = internalFormat;
this.format = format;
this.dataType = dataType;
this.compressed = compressed;
}
}
private static final GLImageFormat[] formatToGL = new GLImageFormat[Format.values().length];
private static void setFormat(Format format, int glInternalFormat, int glFormat, int glDataType, boolean glCompressed){
formatToGL[format.ordinal()] = new GLImageFormat(glInternalFormat, glFormat, glDataType, glCompressed);
}
static {
// Alpha formats
setFormat(Format.Alpha8, GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE, false);
// Luminance formats
setFormat(Format.Luminance8, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, false);
setFormat(Format.Luminance16F, GL_LUMINANCE16F_ARB, GL_LUMINANCE, GL_HALF_FLOAT_ARB, false);
setFormat(Format.Luminance32F, GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT, false);
// Luminance alpha formats
setFormat(Format.Luminance8Alpha8, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, false);
setFormat(Format.Luminance16FAlpha16F, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_ARB, false);
// Depth formats
setFormat(Format.Depth, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, false);
setFormat(Format.Depth16, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false);
setFormat(Format.Depth24, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false);
setFormat(Format.Depth32, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false);
setFormat(Format.Depth32F, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false);
// Depth stencil formats
setFormat(Format.Depth24Stencil8, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, false);
// RGB formats
setFormat(Format.BGR8, GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE, false);
setFormat(Format.ARGB8, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, false);
setFormat(Format.BGRA8, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, false);
setFormat(Format.RGB8, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, false);
setFormat(Format.RGB16F, GL_RGB16F_ARB, GL_RGB, GL_HALF_FLOAT_ARB, false);
setFormat(Format.RGB32F, GL_RGB32F_ARB, GL_RGB, GL_FLOAT, false);
// Special RGB formats
setFormat(Format.RGB111110F, GL_R11F_G11F_B10F_EXT, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV_EXT, false);
setFormat(Format.RGB9E5, GL_RGB9_E5_EXT, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV_EXT, false);
setFormat(Format.RGB16F_to_RGB111110F, GL_R11F_G11F_B10F_EXT, GL_RGB, GL_HALF_FLOAT_ARB, false);
setFormat(Format.RGB16F_to_RGB9E5, GL_RGB9_E5_EXT, GL_RGB, GL_HALF_FLOAT_ARB, false);
// RGBA formats
setFormat(Format.ABGR8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false);
setFormat(Format.RGB5A1, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, false);
setFormat(Format.RGBA8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false);
setFormat(Format.RGBA16F, GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT_ARB, false);
setFormat(Format.RGBA32F, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, false);
// DXT formats
setFormat(Format.DXT1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT1A, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
// ETC1 support on regular OpenGL requires ES3 compatibility extension.
// NOTE: ETC2 is backwards compatible with ETC1, so we can
// upload ETC1 textures as ETC2.
setFormat(Format.ETC1, GL_COMPRESSED_RGB8_ETC2, GL_RGB, GL_UNSIGNED_BYTE, true);
}
//sRGB formats
private static final GLImageFormat sRGB_RGB8 = new GLImageFormat(GL_SRGB8_EXT, GL_RGB, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_RGBA8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_RGBA, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_Luminance8 = new GLImageFormat(GL_SLUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_LuminanceAlpha8 = new GLImageFormat(GL_SLUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_BGR8 = new GLImageFormat(GL_SRGB8_EXT, GL_BGR, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_ABGR8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false);
private static final GLImageFormat sRGB_ARGB8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, false);
private static final GLImageFormat sRGB_BGRA8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_BGRA, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_DXT1 = new GLImageFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,GL_RGB, GL_UNSIGNED_BYTE, true);
private static final GLImageFormat sRGB_DXT1A = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
private static final GLImageFormat sRGB_DXT3 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
private static final GLImageFormat sRGB_DXT5 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
public static GLImageFormat getImageFormat(EnumSet<Caps> caps, Format fmt, boolean isSrgb){
switch (fmt){
case ETC1:
if (!caps.contains(Caps.TextureCompressionETC1)) {
return null;
}
break;
case DXT1:
case DXT1A:
case DXT3:
case DXT5:
if (!caps.contains(Caps.TextureCompressionS3TC)) {
return null;
}
break;
case Depth24Stencil8:
if (!caps.contains(Caps.PackedDepthStencilBuffer)){
return null;
}
break;
case Luminance16F:
case Luminance16FAlpha16F:
case Luminance32F:
case RGB16F:
case RGB32F:
case RGBA16F:
case RGBA32F:
if (!caps.contains(Caps.FloatTexture)){
return null;
}
break;
case Depth32F:
if (!caps.contains(Caps.FloatDepthBuffer)){
return null;
}
break;
case RGB9E5:
case RGB16F_to_RGB9E5:
if (!caps.contains(Caps.SharedExponentTexture)){
return null;
}
break;
case RGB111110F:
case RGB16F_to_RGB111110F:
if (!caps.contains(Caps.PackedFloatTexture)){
return null;
}
break;
}
if (isSrgb) {
return getSrgbFormat(fmt);
} else {
return formatToGL[fmt.ordinal()];
}
}
public static GLImageFormat getImageFormatWithError(EnumSet<Caps> caps, Format fmt, boolean isSrgb) {
GLImageFormat glFmt = getImageFormat(caps, fmt, isSrgb);
if (glFmt == null) {
throw new RendererException("Image format '" + fmt + "' is unsupported by the video hardware.");
}
return glFmt;
}
private static GLImageFormat getSrgbFormat(Format fmt){
switch (fmt) {
case RGB8:
return sRGB_RGB8;
case RGBA8:
return sRGB_RGBA8;
case BGR8:
return sRGB_BGR8;
case ABGR8:
return sRGB_ABGR8;
case ARGB8:
return sRGB_ARGB8;
case BGRA8:
return sRGB_BGRA8;
case Luminance8:
return sRGB_Luminance8;
case Luminance8Alpha8:
return sRGB_LuminanceAlpha8;
case DXT1:
return sRGB_DXT1;
case DXT1A:
return sRGB_DXT1A;
case DXT3:
return sRGB_DXT3;
case DXT5:
return sRGB_DXT5;
default:
Logger.getLogger(TextureUtil.class.getName()).log(Level.WARNING, "Format {0} has no sRGB equivalent, using linear format.", fmt.toString());
return formatToGL[fmt.ordinal()];
}
}
public static void uploadTexture(EnumSet<Caps> caps,
Image image,
int target,
int index,
int border,
boolean linearizeSrgb){
Image.Format fmt = image.getFormat();
GLImageFormat glFmt = getImageFormatWithError(caps, fmt, image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb);
ByteBuffer data;
if (index >= 0 && image.getData() != null && image.getData().size() > 0){
data = image.getData(index);
}else{
data = null;
}
int width = image.getWidth();
int height = image.getHeight();
int depth = image.getDepth();
if (data != null) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
int[] mipSizes = image.getMipMapSizes();
int pos = 0;
// TODO: Remove unneccessary allocation
if (mipSizes == null){
if (data != null)
mipSizes = new int[]{ data.capacity() };
else
mipSizes = new int[]{ width * height * fmt.getBitsPerPixel() / 8 };
}
boolean subtex = false;
int samples = image.getMultiSamples();
for (int i = 0; i < mipSizes.length; i++){
int mipWidth = Math.max(1, width >> i);
int mipHeight = Math.max(1, height >> i);
int mipDepth = Math.max(1, depth >> i);
if (data != null){
data.position(pos);
data.limit(pos + mipSizes[i]);
}
if (glFmt.compressed && data != null){
if (target == GL_TEXTURE_3D){
glCompressedTexImage3D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
mipDepth,
border,
data);
} else if (target == GL_TEXTURE_2D_ARRAY_EXT) {
// Upload compressed texture array slice
glCompressedTexSubImage3D(target,
i,
0,
0,
index,
mipWidth,
mipHeight,
1,
glFmt.internalFormat,
data);
}else{
//all other targets use 2D: array, cubemap, 2d
glCompressedTexImage2D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
border,
data);
}
}else{
if (target == GL_TEXTURE_3D){
glTexImage3D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
mipDepth,
border,
glFmt.format,
glFmt.dataType,
data);
}else if (target == GL_TEXTURE_2D_ARRAY_EXT){
// prepare data for 2D array
// or upload slice
if (index == -1){
glTexImage3D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
image.getData().size(), //# of slices
border,
glFmt.format,
glFmt.dataType,
data);
}else{
glTexSubImage3D(target,
i, // level
0, // xoffset
0, // yoffset
index, // zoffset
mipWidth, // width
mipHeight, // height
1, // depth
glFmt.format,
glFmt.dataType,
data);
}
}else{
if (subtex){
if (samples > 1){
throw new IllegalStateException("Cannot update multisample textures");
}
glTexSubImage2D(target,
i,
0, 0,
mipWidth, mipHeight,
glFmt.format,
glFmt.dataType,
data);
}else{
if (samples > 1){
glTexImage2DMultisample(target,
samples,
glFmt.internalFormat,
mipWidth,
mipHeight,
true);
}else{
glTexImage2D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
border,
glFmt.format,
glFmt.dataType,
data);
}
}
}
}
pos += mipSizes[i];
}
}
/**
* Update the texture currently bound to target at with data from the given Image at position x and y. The parameter
* index is used as the zoffset in case a 3d texture or texture 2d array is being updated.
*
* @param image Image with the source data (this data will be put into the texture)
* @param target the target texture
* @param index the mipmap level to update
* @param x the x position where to put the image in the texture
* @param y the y position where to put the image in the texture
*/
public static void uploadSubTexture(
EnumSet<Caps> caps,
Image image,
int target,
int index,
int x,
int y,
boolean linearizeSrgb) {
Image.Format fmt = image.getFormat();
GLImageFormat glFmt = getImageFormatWithError(caps, fmt, image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb);
ByteBuffer data = null;
if (index >= 0 && image.getData() != null && image.getData().size() > 0) {
data = image.getData(index);
}
int width = image.getWidth();
int height = image.getHeight();
int depth = image.getDepth();
if (data != null) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
int[] mipSizes = image.getMipMapSizes();
int pos = 0;
// TODO: Remove unneccessary allocation
if (mipSizes == null){
if (data != null) {
mipSizes = new int[]{ data.capacity() };
} else {
mipSizes = new int[]{ width * height * fmt.getBitsPerPixel() / 8 };
}
}
int samples = image.getMultiSamples();
for (int i = 0; i < mipSizes.length; i++){
int mipWidth = Math.max(1, width >> i);
int mipHeight = Math.max(1, height >> i);
int mipDepth = Math.max(1, depth >> i);
if (data != null){
data.position(pos);
data.limit(pos + mipSizes[i]);
}
// to remove the cumbersome if/then/else stuff below we'll update the pos right here and use continue after each
// gl*Image call in an attempt to unclutter things a bit
pos += mipSizes[i];
int glFmtInternal = glFmt.internalFormat;
int glFmtFormat = glFmt.format;
int glFmtDataType = glFmt.dataType;
if (glFmt.compressed && data != null){
if (target == GL_TEXTURE_3D){
glCompressedTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtInternal, data);
continue;
}
// all other targets use 2D: array, cubemap, 2d
glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtInternal, data);
continue;
}
if (target == GL_TEXTURE_3D){
glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data);
continue;
}
if (target == GL_TEXTURE_2D_ARRAY_EXT){
// prepare data for 2D array or upload slice
if (index == -1){
glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data);
continue;
}
glTexSubImage3D(target, i, x, y, index, width, height, 1, glFmtFormat, glFmtDataType, data);
continue;
}
if (samples > 1){
throw new IllegalStateException("Cannot update multisample textures");
}
glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtFormat, glFmtDataType, data);
}
}
}

@ -92,7 +92,7 @@ public class RpcCallMessage extends AbstractMessage {
+ (isAsync() ? ", async" : ", sync")
+ ", objId=" + objId
+ ", procId=" + procId
+ ", args.length=" + args.length
+ ", args.length=" + (args == null ? 0 : args.length)
+ "]";
}
}

@ -0,0 +1 @@
sdk.dir=C:\\AndroidSDK

@ -11,6 +11,7 @@ import com.jme3.gde.core.scene.controller.SceneToolController;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.scenecomposer.tools.PickManager;
import com.jme3.gde.scenecomposer.tools.shortcuts.ShortcutManager;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.light.Light;
import com.jme3.light.PointLight;
@ -31,6 +32,7 @@ import com.jme3.scene.control.Control;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;
import java.util.concurrent.Callable;
import org.openide.util.Lookup;
/**
*
@ -184,7 +186,12 @@ public class SceneComposerToolController extends SceneToolController {
* @param camera
*/
public void doEditToolActivatedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) {
if (editTool != null) {
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
if (scm.isActive()) {
scm.getActiveShortcut().setCamera(camera);
scm.getActiveShortcut().actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
} else if (editTool != null) {
editTool.setCamera(camera);
editTool.actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
}
@ -198,36 +205,66 @@ public class SceneComposerToolController extends SceneToolController {
* @param camera
*/
public void doEditToolActivatedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) {
if (editTool != null) {
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
if (scm.isActive()) {
scm.getActiveShortcut().setCamera(camera);
scm.getActiveShortcut().actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
} else if (editTool != null) {
editTool.setCamera(camera);
editTool.actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
}
}
public void doEditToolMoved(Vector2f mouseLoc, Camera camera) {
if (editTool != null) {
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
if (scm.isActive()) {
scm.getActiveShortcut().setCamera(camera);
scm.getActiveShortcut().mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial);
} else if (editTool != null) {
editTool.setCamera(camera);
editTool.mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial);
}
}
public void doEditToolDraggedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) {
if (editTool != null) {
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
if (scm.isActive()) {
scm.getActiveShortcut().setCamera(camera);
scm.getActiveShortcut().draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
} else if (editTool != null) {
editTool.setCamera(camera);
editTool.draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
}
}
public void doEditToolDraggedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) {
if (editTool != null) {
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
if (scm.isActive()) {
scm.getActiveShortcut().setCamera(null);
scm.getActiveShortcut().draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
} else if (editTool != null) {
editTool.setCamera(camera);
editTool.draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
}
}
void doKeyPressed(KeyInputEvent kie) {
if (editTool != null) {
editTool.keyPressed(kie);
public void doKeyPressed(KeyInputEvent kie) {
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
if (scm.isActive()) {
scm.doKeyPressed(kie);
} else {
if (scm.activateShortcut(kie)) {
scm.getActiveShortcut().activate(manager, toolsNode, onTopToolsNode, selected, this);
} else {
if (editTool != null) {
editTool.keyPressed(kie);
}
}
}
}

@ -1,204 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.gde.scenecomposer.tools;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.scenecomposer.SceneEditTool;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Quad;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author Nehon
*/
@ServiceProvider(service = MoveManager.class)
public class MoveManager {
private Vector3f startLoc;
private Vector3f startWorldLoc;
private Vector3f lastLoc;
private Vector3f offset;
private Node alternativePickTarget = null;
private Node plane;
private Spatial spatial;
protected static final Quaternion XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0));
protected static final Quaternion YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));
protected static final Quaternion XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0));
//temp vars
private Quaternion rot = new Quaternion();
private Vector3f newPos = new Vector3f();
public MoveManager() {
float size = 1000;
Geometry g = new Geometry("plane", new Quad(size, size));
g.setLocalTranslation(-size / 2, -size / 2, 0);
plane = new Node();
plane.attachChild(g);
}
public Vector3f getOffset() {
return offset;
}
public void reset() {
offset = null;
startLoc = null;
startWorldLoc = null;
lastLoc = null;
spatial = null;
alternativePickTarget = null;
}
public void initiateMove(Spatial selectedSpatial, Quaternion planeRotation, boolean local) {
spatial = selectedSpatial;
startLoc = selectedSpatial.getLocalTranslation().clone();
startWorldLoc = selectedSpatial.getWorldTranslation().clone();
if (local) {
rot.set(selectedSpatial.getWorldRotation());
plane.setLocalRotation(rot.multLocal(planeRotation));
} else {
rot.set(planeRotation);
}
plane.setLocalRotation(rot);
plane.setLocalTranslation(startWorldLoc);
}
public void updatePlaneRotation(Quaternion planeRotation) {
plane.setLocalRotation(rot);
}
public boolean move(Camera camera, Vector2f screenCoord) {
return move(camera, screenCoord, Vector3f.UNIT_XYZ, false);
}
public boolean move(Camera camera, Vector2f screenCoord, Vector3f constraintAxis, boolean gridSnap) {
Node toPick = alternativePickTarget == null ? plane : alternativePickTarget;
Vector3f planeHit = SceneEditTool.pickWorldLocation(camera, screenCoord, toPick, alternativePickTarget == null ? null : spatial);
if (planeHit == null) {
return false;
}
Spatial parent = spatial.getParent();
//we are moving the root node, there is a slight chance that something went wrong.
if (parent == null) {
return false;
}
//offset in world space
if (offset == null) {
offset = planeHit.subtract(spatial.getWorldTranslation()); // get the offset when we start so it doesn't jump
}
newPos.set(planeHit).subtractLocal(offset);
//constraining the translation with the contraintAxis.
Vector3f tmp = startWorldLoc.mult(Vector3f.UNIT_XYZ.subtract(constraintAxis));
newPos.multLocal(constraintAxis).addLocal(tmp);
worldToLocalMove(gridSnap);
return true;
}
private void worldToLocalMove(boolean gridSnap) {
//snap to grid (grid is assumed 1 WU per cell)
if (gridSnap) {
newPos.set(Math.round(newPos.x), Math.round(newPos.y), Math.round(newPos.z));
}
//computing the inverse world transform to get the new localtranslation
newPos.subtractLocal(spatial.getParent().getWorldTranslation());
newPos = spatial.getParent().getWorldRotation().inverse().normalizeLocal().multLocal(newPos);
newPos.divideLocal(spatial.getParent().getWorldScale());
lastLoc = newPos;
spatial.setLocalTranslation(newPos);
RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
if (control != null) {
control.setPhysicsLocation(spatial.getWorldTranslation());
}
CharacterControl character = spatial.getControl(CharacterControl.class);
if (character != null) {
character.setPhysicsLocation(spatial.getWorldTranslation());
}
}
public boolean moveAcross(Vector3f constraintAxis, float value, boolean gridSnap) {
newPos.set(startWorldLoc).addLocal(constraintAxis.mult(value));
Spatial parent = spatial.getParent();
//we are moving the root node, there is a slight chance that something went wrong.
if (parent == null) {
return false;
}
worldToLocalMove(gridSnap);
return true;
}
public MoveUndo makeUndo() {
return new MoveUndo(spatial, startLoc, lastLoc);
}
public void setAlternativePickTarget(Node alternativePickTarget) {
this.alternativePickTarget = alternativePickTarget;
}
protected class MoveUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Vector3f before = new Vector3f(), after = new Vector3f();
MoveUndo(Spatial spatial, Vector3f before, Vector3f after) {
this.spatial = spatial;
this.before.set(before);
if (after != null) {
this.after.set(after);
}
}
@Override
public void sceneUndo() {
spatial.setLocalTranslation(before);
RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
if (control != null) {
control.setPhysicsLocation(spatial.getWorldTranslation());
}
CharacterControl character = spatial.getControl(CharacterControl.class);
if (character != null) {
character.setPhysicsLocation(spatial.getWorldTranslation());
}
// toolController.selectedSpatialTransformed();
}
@Override
public void sceneRedo() {
spatial.setLocalTranslation(after);
RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
if (control != null) {
control.setPhysicsLocation(spatial.getWorldTranslation());
}
CharacterControl character = spatial.getControl(CharacterControl.class);
if (character != null) {
character.setPhysicsLocation(spatial.getWorldTranslation());
}
//toolController.selectedSpatialTransformed();
}
public void setAfter(Vector3f after) {
this.after.set(after);
}
}
}

@ -33,9 +33,9 @@ public class PickManager {
private Spatial spatial;
private SceneComposerToolController.TransformationType transformationType;
protected static final Quaternion PLANE_XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0));
protected static final Quaternion PLANE_YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));//YAW090
protected static final Quaternion PLANE_XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0)); //PITCH090
public static final Quaternion PLANE_XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0));
public static final Quaternion PLANE_YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));//YAW090
public static final Quaternion PLANE_XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0)); //PITCH090
public PickManager() {
@ -75,7 +75,7 @@ public class PickManager {
origineRotation = new Quaternion(Quaternion.IDENTITY);
} else if (transformationType == SceneComposerToolController.TransformationType.camera) {
rot.set(camera.getRotation());
origineRotation = camera.getRotation().clone();
origineRotation = camera.getRotation();
}
plane.setLocalRotation(rot);
}
@ -87,10 +87,6 @@ public class PickManager {
* @return true if the the new picked location is set, else return false.
*/
public boolean updatePick(Camera camera, Vector2f screenCoord) {
if(transformationType == SceneComposerToolController.TransformationType.camera){
origineRotation = camera.getRotation();
plane.setLocalRotation(camera.getRotation());
}
finalPickLoc = SceneEditTool.pickWorldLocation(camera, screenCoord, plane, null);
return finalPickLoc != null;
}

@ -25,7 +25,6 @@ import org.openide.util.Lookup;
public class RotateTool extends SceneEditTool {
private Vector3f pickedMarker;
private Vector2f lastScreenCoord;
private Quaternion startRotate;
private Quaternion lastRotate;
private boolean wasDragging = false;
@ -48,9 +47,8 @@ public class RotateTool extends SceneEditTool {
if (!pressed) {
setDefaultAxisMarkerColors();
pickedMarker = null; // mouse released, reset selection
lastScreenCoord = null;
if (wasDragging) {
actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
wasDragging = false;
}
pickManager.reset();
@ -100,10 +98,9 @@ public class RotateTool extends SceneEditTool {
if (!pressed) {
setDefaultAxisMarkerColors();
pickedMarker = null; // mouse released, reset selection
lastScreenCoord = null;
if (wasDragging) {
actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
wasDragging = false;
}
pickManager.reset();
@ -138,12 +135,12 @@ public class RotateTool extends SceneEditTool {
}
}
private class ScaleUndo extends AbstractUndoableSceneEdit {
private class RotateUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Quaternion before, after;
ScaleUndo(Spatial spatial, Quaternion before, Quaternion after) {
RotateUndo(Spatial spatial, Quaternion before, Quaternion after) {
this.spatial = spatial;
this.before = before;
this.after = after;

@ -8,425 +8,51 @@ import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.scenecomposer.SceneEditTool;
import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
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;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
/**
* This duplicates the Blender manipulate tool.
* It supports quick access to Grab, Rotate, and Scale operations
* by typing one of the following keys: 'g', 'r', or 's'
* Those keys can be followed by an axis key to specify what axis
* to perform the transformation: x, y, z
* Then, after the operation and axis are selected, you can type in a
* number and then hit 'enter' to complete the transformation.
*
* Ctrl+Shift+D will duplicate an object
* X will delete an object
*
* ITEMS TO FINISH:
* 1) fixed scale and rotation values by holding Ctrl and dragging mouse
* BUGS:
* 1) window always needs focus from primary click when it should focus from secondary and middle mouse
*
* This duplicates the Blender manipulate tool. It supports quick access to
* Grab, Rotate, and Scale operations by typing one of the following keys: 'g',
* 'r', or 's' Those keys can be followed by an axis key to specify what axis to
* perform the transformation: x, y, z Then, after the operation and axis are
* selected, you can type in a number and then hit 'enter' to complete the
* transformation.
*
* Ctrl+Shift+D will duplicate an object X will delete an object
*
* ITEMS TO FINISH: 1) fixed scale and rotation values by holding Ctrl and
* dragging mouse BUGS: 1) window always needs focus from primary click when it
* should focus from secondary and middle mouse
*
* @author Brent Owens
*/
public class SelectTool extends SceneEditTool {
private enum State {
translate, rotate, scale
};
private State currentState = null;
private Vector3f currentAxis = Vector3f.UNIT_XYZ;
private StringBuilder numberBuilder = new StringBuilder(); // gets appended with numbers
private Quaternion startRot;
private Vector3f startTrans;
private Vector3f startScale;
private boolean wasDraggingL = false;
private boolean wasDraggingR = false;
private boolean wasDownR = false;
private boolean ctrlDown = false;
private boolean shiftDown = false;
private boolean altDown = false;
private MoveManager.MoveUndo moving;
private ScaleUndo scaling;
private RotateUndo rotating;
private Vector2f startMouseCoord; // for scaling and rotation
private Vector2f startSelectedCoord; // for scaling and rotation
private float lastRotAngle; // used for rotation
/**
* This is stateful:
* First it checks for a command (rotate, translate, delete, etc..)
* Then it checks for an axis (x,y,z)
* Then it checks for a number (user typed a number
* Then, finally, it checks if Enter was hit.
*
* This is stateful: First it checks for a command (rotate, translate,
* delete, etc..) Then it checks for an axis (x,y,z) Then it checks for a
* number (user typed a number Then, finally, it checks if Enter was hit.
*
* If either of the commands was actioned, the preceeding states/axis/amount
* will be reset. For example if the user types: G Y 2 R
* Then it will:
* 1) Set state as 'Translate' for the G (grab)
* 2) Set the axis as 'Y'; it will translate along the Y axis
* 3) Distance will be 2, when the 2 key is hit
* 4) Distance, Axis, and state are then reset because a new state was set: Rotate
* it won't actually translate because 'Enter' was not hit and 'R' reset the state.
*
* will be reset. For example if the user types: G Y 2 R Then it will: 1)
* Set state as 'Translate' for the G (grab) 2) Set the axis as 'Y'; it will
* translate along the Y axis 3) Distance will be 2, when the 2 key is hit
* 4) Distance, Axis, and state are then reset because a new state was set:
* Rotate it won't actually translate because 'Enter' was not hit and 'R'
* reset the state.
*
*/
@Override
public void keyPressed(KeyInputEvent kie) {
checkModificatorKeys(kie); // alt,shift,ctrl
Spatial selected = toolController.getSelectedSpatial();
if (selected == null) {
return; // only do anything if a spatial is selected
}
// key released
if (kie.isPressed()) {
boolean commandUsed = checkCommandKey(kie);
boolean stateChange = checkStateKey(kie);
boolean axisChange = checkAxisKey(kie);
boolean numberChange = checkNumberKey(kie);
boolean enterHit = checkEnterHit(kie);
boolean escHit = checkEscHit(kie);
if (commandUsed) {
return; // commands take priority
}
if (stateChange) {
currentAxis = Vector3f.UNIT_XYZ;
numberBuilder = new StringBuilder();
recordInitialState(selected);
} else if (axisChange) {
} else if (numberChange) {
} else if (enterHit) {
if (currentState != null && numberBuilder.length() > 0) {
applyKeyedChangeState(selected);
clearState(false);
}
}
// -----------------------
// reset conditions below:
if (escHit) {
if (moving != null) {
moving.sceneUndo();
}
moving = null;
clearState();
}
if (!stateChange && !axisChange && !numberChange && !enterHit && !escHit) {
// nothing valid was hit, reset the state
//clearState(); // this will be
}
}
}
/**
* Abort any manipulations
*/
private void clearState() {
clearState(true);
}
private void clearState(boolean resetSelected) {
Spatial selected = toolController.getSelectedSpatial();
if (resetSelected && selected != null) {
// reset the transforms
if (startRot != null) {
selected.setLocalRotation(startRot);
}
if (startTrans != null) {
selected.setLocalTranslation(startTrans);
}
if (startScale != null) {
selected.setLocalScale(startScale);
}
}
currentState = null;
currentAxis = Vector3f.UNIT_XYZ;
numberBuilder = new StringBuilder();
startRot = null;
startTrans = null;
startScale = null;
startMouseCoord = null;
startSelectedCoord = null;
lastRotAngle = 0;
}
private void recordInitialState(Spatial selected) {
startRot = selected.getLocalRotation().clone();
startTrans = selected.getLocalTranslation().clone();
startScale = selected.getLocalScale().clone();
}
/**
* Applies the changes entered by a number, not by mouse.
* Translate: adds the value to the current local translation
* Rotate: rotates by X degrees
* Scale: scale the current scale by X amount
*/
private void applyKeyedChangeState(Spatial selected) {
Float value = null;
try {
value = new Float(numberBuilder.toString());
} catch (NumberFormatException e) {
return;
}
if (currentState == State.translate) {
MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
moveManager.moveAcross(currentAxis, value, toolController.isSnapToGrid());
moving.setAfter(selected.getLocalTranslation());
actionPerformed(moving);
moving = null;
} else if (currentState == State.scale) {
float x = 1, y = 1, z = 1;
if (currentAxis == Vector3f.UNIT_X) {
x = value;
} else if (currentAxis == Vector3f.UNIT_Y) {
y = value;
} else if (currentAxis == Vector3f.UNIT_Z) {
z = value;
} else if (currentAxis == Vector3f.UNIT_XYZ) {
x = value;
y = value;
z = value;
}
Vector3f before = selected.getLocalScale().clone();
Vector3f after = selected.getLocalScale().multLocal(x, y, z);
selected.setLocalScale(after);
actionPerformed(new ScaleUndo(selected, before, after));
} else if (currentState == State.rotate) {
float x = 0, y = 0, z = 0;
if (currentAxis == Vector3f.UNIT_X) {
x = 1;
} else if (currentAxis == Vector3f.UNIT_Y) {
y = 1;
} else if (currentAxis == Vector3f.UNIT_Z) {
z = 1;
}
Vector3f axis = new Vector3f(x, y, z);
Quaternion initialRot = selected.getLocalRotation().clone();
Quaternion rot = new Quaternion();
rot = rot.fromAngleAxis(value * FastMath.DEG_TO_RAD, axis);
selected.setLocalRotation(selected.getLocalRotation().mult(rot));
RotateUndo undo = new RotateUndo(selected, initialRot, rot);
actionPerformed(undo);
toolController.updateSelection(null);// force a re-draw of the bbox shape
toolController.updateSelection(selected);
}
clearState(false);
}
private void checkModificatorKeys(KeyInputEvent kie) {
if (kie.getKeyCode() == KeyInput.KEY_LCONTROL || kie.getKeyCode() == KeyInput.KEY_RCONTROL) {
ctrlDown = kie.isPressed();
}
if (kie.getKeyCode() == KeyInput.KEY_LSHIFT || kie.getKeyCode() == KeyInput.KEY_RSHIFT) {
shiftDown = kie.isPressed();
}
if (kie.getKeyCode() == KeyInput.KEY_LMENU || kie.getKeyCode() == KeyInput.KEY_RMENU) {
altDown = kie.isPressed();
}
}
private boolean checkCommandKey(KeyInputEvent kie) {
if (kie.getKeyCode() == KeyInput.KEY_D) {
if (shiftDown) {
duplicateSelected();
return true;
}
}
// X will only delete if the user isn't already transforming
if (currentState == null && kie.getKeyCode() == KeyInput.KEY_X) {
if (!ctrlDown && !shiftDown) {
deleteSelected();
return true;
}
}
return false;
}
private boolean checkStateKey(KeyInputEvent kie) {
Spatial selected = toolController.getSelectedSpatial();
if (kie.getKeyCode() == KeyInput.KEY_G && !ctrlDown) {
currentState = State.translate;
MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
moveManager.reset();
Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y));
moveManager.initiateMove(selected, rot, false);
moving = moveManager.makeUndo();
return true;
} else if (kie.getKeyCode() == KeyInput.KEY_R && !ctrlDown) {
currentState = State.rotate;
return true;
} else if (kie.getKeyCode() == KeyInput.KEY_S && !ctrlDown) {
currentState = State.scale;
return true;
}
return false;
}
private boolean checkAxisKey(KeyInputEvent kie) {
if (kie.getKeyCode() == KeyInput.KEY_X) {
currentAxis = Vector3f.UNIT_X;
checkMovePlane(MoveManager.XY, MoveManager.XZ);
return true;
} else if (kie.getKeyCode() == KeyInput.KEY_Y) {
currentAxis = Vector3f.UNIT_Y;
checkMovePlane(MoveManager.XY, MoveManager.YZ);
return true;
} else if (kie.getKeyCode() == KeyInput.KEY_Z) {
currentAxis = Vector3f.UNIT_Z;
checkMovePlane(MoveManager.XZ, MoveManager.YZ);
return true;
}
return false;
}
private void checkMovePlane(Quaternion rot1, Quaternion rot2) {
if (currentState == State.translate) {
MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y));
Quaternion planRot = null;
if (rot.dot(rot1) < rot.dot(rot2)) {
planRot = rot1;
} else {
planRot = rot2;
}
moveManager.updatePlaneRotation(planRot);
}
}
private boolean checkNumberKey(KeyInputEvent kie) {
if (kie.getKeyCode() == KeyInput.KEY_MINUS) {
if (numberBuilder.length() > 0) {
if (numberBuilder.charAt(0) == '-') {
numberBuilder.replace(0, 1, "");
} else {
numberBuilder.insert(0, '-');
}
} 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(".");
}
}
return true;
}
return false;
}
private boolean checkEnterHit(KeyInputEvent kie) {
if (kie.getKeyCode() == KeyInput.KEY_RETURN) {
return true;
}
return false;
}
private boolean checkEscHit(KeyInputEvent kie) {
if (kie.getKeyCode() == KeyInput.KEY_ESCAPE) {
return true;
}
return false;
}
@Override
public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) {
if (!pressed) {
Spatial selected = toolController.getSelectedSpatial();
// left mouse released
if (!wasDraggingL) {
// left mouse pressed
if (currentState != null) {
// finish manipulating the spatial
if (moving != null) {
moving.setAfter(selected.getLocalTranslation());
actionPerformed(moving);
moving = null;
clearState(false);
} else if (scaling != null) {
scaling.after = selected.getLocalScale().clone();
actionPerformed(scaling);
scaling = null;
clearState(false);
toolController.rebuildSelectionBox();
} else if (rotating != null) {
rotating.after = selected.getLocalRotation().clone();
actionPerformed(rotating);
rotating = null;
clearState(false);
}
} else {
// mouse released and wasn't dragging, place cursor
final 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.setCursorLocation(result);
}
}
}
wasDraggingL = false;
}
}
@Override
@ -435,19 +61,7 @@ public class SelectTool extends SceneEditTool {
Spatial selected = toolController.getSelectedSpatial();
// mouse down
if (moving != null) {
moving.sceneUndo();
moving = null;
clearState();
} else if (scaling != null) {
scaling.sceneUndo();
scaling = null;
clearState();
} else if (rotating != null) {
rotating.sceneUndo();
rotating = null;
clearState();
} else if (!wasDraggingR && !wasDownR) { // wasn't dragging and was not down already
if (!wasDraggingR && !wasDownR) { // wasn't dragging and was not down already
// pick on the spot
Spatial s = pickWorldSpatial(camera, screenCoord, rootNode);
if (!toolController.selectTerrain() && isTerrain(s)) {
@ -498,8 +112,8 @@ public class SelectTool extends SceneEditTool {
}
/**
* Climb up the spatial until we find the first node parent.
* TODO: use userData to determine the actual model's parent.
* Climb up the spatial until we find the first node parent. TODO: use
* userData to determine the actual model's parent.
*/
private Spatial findModelNodeParent(Spatial child) {
if (child == null) {
@ -519,14 +133,10 @@ public class SelectTool extends SceneEditTool {
@Override
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
if (currentState != null) {
handleMouseManipulate(screenCoord, currentState, currentAxis, rootNode, currentDataObject, selectedSpatial);
}
}
@Override
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
wasDraggingL = pressed;
}
@Override
@ -535,252 +145,8 @@ public class SelectTool extends SceneEditTool {
}
/**
* Manipulate the spatial
*/
private void handleMouseManipulate(Vector2f screenCoord,
State state,
Vector3f axis,
JmeNode rootNode,
DataObject currentDataObject,
JmeSpatial selectedSpatial) {
if (state == State.translate) {
doMouseTranslate(axis, screenCoord, rootNode, selectedSpatial);
} else if (state == State.scale) {
doMouseScale(axis, screenCoord, rootNode, selectedSpatial);
} else if (state == State.rotate) {
doMouseRotate(axis, screenCoord, rootNode, selectedSpatial);
}
}
private void doMouseTranslate(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
if (toolController.isSnapToScene()) {
moveManager.setAlternativePickTarget(rootNode.getLookup().lookup(Node.class));
}
// free form translation
moveManager.move(camera, screenCoord, axis, toolController.isSnapToGrid());
}
private void doMouseScale(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
Spatial selected = toolController.getSelectedSpatial();
// scale based on the original mouse position and original model-to-screen position
// and compare that to the distance from the new mouse position and the original distance
if (startMouseCoord == null) {
startMouseCoord = screenCoord.clone();
}
if (startSelectedCoord == null) {
Vector3f screen = getCamera().getScreenCoordinates(selected.getWorldTranslation());
startSelectedCoord = new Vector2f(screen.x, screen.y);
}
if (scaling == null) {
scaling = new ScaleUndo(selected, selected.getLocalScale().clone(), null);
}
float origDist = startMouseCoord.distanceSquared(startSelectedCoord);
float newDist = screenCoord.distanceSquared(startSelectedCoord);
if (origDist == 0) {
origDist = 1;
}
float ratio = newDist / origDist;
Vector3f prev = selected.getLocalScale();
if (axis == Vector3f.UNIT_X) {
selected.setLocalScale(ratio, prev.y, prev.z);
} else if (axis == Vector3f.UNIT_Y) {
selected.setLocalScale(prev.x, ratio, prev.z);
} else if (axis == Vector3f.UNIT_Z) {
selected.setLocalScale(prev.x, prev.y, ratio);
} else {
selected.setLocalScale(ratio, ratio, ratio);
}
}
private void doMouseRotate(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
Spatial selected = toolController.getSelectedSpatial();
if (startMouseCoord == null) {
startMouseCoord = screenCoord.clone();
}
if (startSelectedCoord == null) {
Vector3f screen = getCamera().getScreenCoordinates(selected.getWorldTranslation());
startSelectedCoord = new Vector2f(screen.x, screen.y);
}
if (rotating == null) {
rotating = new RotateUndo(selected, selected.getLocalRotation().clone(), null);
}
Vector2f origRot = startMouseCoord.subtract(startSelectedCoord);
Vector2f newRot = screenCoord.subtract(startSelectedCoord);
float newRotAngle = origRot.angleBetween(newRot);
float temp = newRotAngle;
if (lastRotAngle != 0) {
newRotAngle -= lastRotAngle;
}
lastRotAngle = temp;
Quaternion rotate = new Quaternion();
if (axis != Vector3f.UNIT_XYZ) {
rotate = rotate.fromAngleAxis(newRotAngle, selected.getWorldRotation().inverse().mult(axis));
} else {
rotate = rotate.fromAngleAxis(newRotAngle, selected.getWorldRotation().inverse().mult(getCamera().getDirection().mult(-1).normalizeLocal()));
}
selected.setLocalRotation(selected.getLocalRotation().mult(rotate));
}
private void duplicateSelected() {
Spatial selected = toolController.getSelectedSpatial();
if (selected == null) {
return;
}
Spatial clone = selected.clone();
clone.move(1, 0, 1);
selected.getParent().attachChild(clone);
actionPerformed(new DuplicateUndo(clone, selected.getParent()));
selected = clone;
final Spatial cloned = clone;
final JmeNode rootNode = toolController.getRootNode();
refreshSelected(rootNode, selected.getParent());
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (cloned != null) {
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(cloned)});
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(cloned));
}
}
});
// set to automatically 'grab'/'translate' the new cloned model
toolController.updateSelection(selected);
currentState = State.translate;
currentAxis = Vector3f.UNIT_XYZ;
}
private void deleteSelected() {
Spatial selected = toolController.getSelectedSpatial();
if (selected == null) {
return;
}
Node parent = selected.getParent();
selected.removeFromParent();
actionPerformed(new DeleteUndo(selected, parent));
selected = null;
toolController.updateSelection(selected);
final JmeNode rootNode = toolController.getRootNode();
refreshSelected(rootNode, parent);
}
private void refreshSelected(final JmeNode jmeRootNode, final Node parent) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
jmeRootNode.getChild(parent).refresh(false);
}
});
}
private class ScaleUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Vector3f before, after;
ScaleUndo(Spatial spatial, Vector3f before, Vector3f after) {
this.spatial = spatial;
this.before = before;
this.after = after;
}
@Override
public void sceneUndo() {
spatial.setLocalScale(before);
}
@Override
public void sceneRedo() {
spatial.setLocalScale(after);
}
}
private class RotateUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Quaternion before, after;
RotateUndo(Spatial spatial, Quaternion before, Quaternion after) {
this.spatial = spatial;
this.before = before;
this.after = after;
}
@Override
public void sceneUndo() {
spatial.setLocalRotation(before);
}
@Override
public void sceneRedo() {
spatial.setLocalRotation(after);
}
}
private class DeleteUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Node parent;
DeleteUndo(Spatial spatial, Node parent) {
this.spatial = spatial;
this.parent = parent;
}
@Override
public void sceneUndo() {
parent.attachChild(spatial);
}
@Override
public void sceneRedo() {
spatial.removeFromParent();
}
}
private class DuplicateUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Node parent;
DuplicateUndo(Spatial spatial, Node parent) {
this.spatial = spatial;
this.parent = parent;
}
@Override
public void sceneUndo() {
spatial.removeFromParent();
}
@Override
public void sceneRedo() {
parent.attachChild(spatial);
}
}
/**
* Check if the selected item is a Terrain
* It will climb up the parent tree to see if
* a parent is terrain too.
* Recursive call.
* Check if the selected item is a Terrain It will climb up the parent tree
* to see if a parent is terrain too. Recursive call.
*/
protected boolean isTerrain(Spatial s) {
if (s == null) {

@ -0,0 +1,123 @@
/*
* 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 com.jme3.gde.scenecomposer.tools.shortcuts;
import com.jme3.asset.AssetManager;
import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.scenecomposer.SceneComposerToolController;
import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.math.Vector2f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
/**
*
* @author dokthar
*/
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()) {
return true;
}
}
return false;
}
@Override
public void cancel() {
terminate();
}
@Override
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
hideMarker();
if (selectedSpatial != null) {
delete();
}
terminate();
}
private void delete() {
Spatial selected = toolController.getSelectedSpatial();
Node parent = selected.getParent();
selected.removeFromParent();
actionPerformed(new DeleteUndo(selected, parent));
selected = null;
toolController.updateSelection(selected);
final JmeNode rootNode = toolController.getRootNode();
refreshSelected(rootNode, parent);
}
private void refreshSelected(final JmeNode jmeRootNode, final Node parent) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
jmeRootNode.getChild(parent).refresh(false);
}
});
}
@Override
public void keyPressed(KeyInputEvent kie) {
}
@Override
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
}
@Override
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
}
@Override
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
}
@Override
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
}
@Override
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
}
private class DeleteUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Node parent;
DeleteUndo(Spatial spatial, Node parent) {
this.spatial = spatial;
this.parent = parent;
}
@Override
public void sceneUndo() {
parent.attachChild(spatial);
}
@Override
public void sceneRedo() {
spatial.removeFromParent();
}
}
}

@ -0,0 +1,141 @@
/*
* 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 com.jme3.gde.scenecomposer.tools.shortcuts;
import com.jme3.asset.AssetManager;
import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.scenecomposer.SceneComposerToolController;
import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.math.Vector2f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
/**
*
* @author dokthar
*/
public class DuplicateShortcut extends ShortcutTool {
@Override
public boolean isActivableBy(KeyInputEvent kie) {
if (kie.getKeyCode() == KeyInput.KEY_D && kie.isPressed()) {
if (Lookup.getDefault().lookup(ShortcutManager.class).isShiftDown()) {
return true;
}
}
return false;
}
@Override
public void cancel() {
terminate();
}
@Override
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
hideMarker();
if (selectedSpatial != null) {
duplicate();
terminate();
//then enable move shortcut
toolController.doKeyPressed(new KeyInputEvent(KeyInput.KEY_G, 'g', true, false));
} else {
terminate();
}
}
private void duplicate() {
Spatial selected = toolController.getSelectedSpatial();
Spatial clone = selected.clone();
clone.move(1, 0, 1);
selected.getParent().attachChild(clone);
actionPerformed(new DuplicateUndo(clone, selected.getParent()));
selected = clone;
final Spatial cloned = clone;
final JmeNode rootNode = toolController.getRootNode();
refreshSelected(rootNode, selected.getParent());
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (cloned != null) {
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(cloned)});
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(cloned));
}
}
});
toolController.updateSelection(selected);
}
private void refreshSelected(final JmeNode jmeRootNode, final Node parent) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
jmeRootNode.getChild(parent).refresh(false);
}
});
}
@Override
public void keyPressed(KeyInputEvent kie) {
}
@Override
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
}
@Override
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
}
@Override
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
}
@Override
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
}
@Override
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
}
private class DuplicateUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Node parent;
DuplicateUndo(Spatial spatial, Node parent) {
this.spatial = spatial;
this.parent = parent;
}
@Override
public void sceneUndo() {
spatial.removeFromParent();
}
@Override
public void sceneRedo() {
parent.attachChild(spatial);
}
}
}

@ -0,0 +1,227 @@
/*
* 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 com.jme3.gde.scenecomposer.tools.shortcuts;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.scenecomposer.SceneComposerToolController;
import com.jme3.gde.scenecomposer.tools.PickManager;
import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
/**
*
* @author dokthar
*/
public class MoveShortcut extends ShortcutTool {
private Vector3f currentAxis;
private StringBuilder numberBuilder;
private Spatial spatial;
private PickManager pickManager;
private boolean pickEnabled;
private Vector3f startPosition;
private Vector3f finalPosition;
@Override
public boolean isActivableBy(KeyInputEvent kie) {
return kie.getKeyCode() == KeyInput.KEY_G;
}
@Override
public void cancel() {
spatial.setLocalTranslation(startPosition);
terminate();
}
private void apply() {
actionPerformed(new MoveUndo(toolController.getSelectedSpatial(), startPosition, finalPosition));
terminate();
}
private void init(Spatial selectedSpatial) {
spatial = selectedSpatial;
startPosition = spatial.getLocalTranslation().clone();
currentAxis = Vector3f.UNIT_XYZ;
pickManager = Lookup.getDefault().lookup(PickManager.class);
pickEnabled = false;
}
@Override
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
hideMarker();
numberBuilder = new StringBuilder();
if (selectedSpatial == null) {
terminate();
} else {
init(selectedSpatial);
}
}
@Override
public void keyPressed(KeyInputEvent kie) {
if (kie.isPressed()) {
Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie);
Vector3f axis = new Vector3f();
boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis);
if (axisChanged) {
currentAxis = axis;
}
boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder);
boolean enterHit = ShortcutManager.checkEnterHit(kie);
boolean escHit = ShortcutManager.checkEscHit(kie);
if (escHit) {
cancel();
} else if (enterHit) {
apply();
} else if (axisChanged && pickEnabled) {
//update pick manager
if (currentAxis.equals(Vector3f.UNIT_X)) {
pickManager.setTransformation(PickManager.PLANE_XY, getTransformType(), camera);
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
pickManager.setTransformation(PickManager.PLANE_YZ, getTransformType(), camera);
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
pickManager.setTransformation(PickManager.PLANE_XZ, getTransformType(), camera);
}
} else if (axisChanged || numberChanged) {
//update transformation
float number = ShortcutManager.getNumberKey(numberBuilder);
Vector3f translation = currentAxis.mult(number);
finalPosition = startPosition.add(translation);
spatial.setLocalTranslation(finalPosition);
}
}
}
@Override
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
if (pressed) {
apply();
}
}
@Override
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
if (pressed) {
cancel();
}
}
@Override
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
if (!pickEnabled) {
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), SceneComposerToolController.TransformationType.camera, camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_X)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else {
return;
}
}
if (pickManager.updatePick(camera, screenCoord)) {
//pick update success
Vector3f diff;
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
diff = pickManager.getTranslation();
} else {
diff = pickManager.getTranslation(currentAxis);
}
Vector3f position = startPosition.add(diff);
finalPosition = position;
toolController.getSelectedSpatial().setLocalTranslation(position);
updateToolsTransformation();
}
}
@Override
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
if (pressed) {
apply();
}
}
@Override
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
if (pressed) {
cancel();
}
}
private class MoveUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Vector3f before = new Vector3f(), after = new Vector3f();
MoveUndo(Spatial spatial, Vector3f before, Vector3f after) {
this.spatial = spatial;
this.before.set(before);
if (after != null) {
this.after.set(after);
}
}
@Override
public void sceneUndo() {
spatial.setLocalTranslation(before);
RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
if (control != null) {
control.setPhysicsLocation(spatial.getWorldTranslation());
}
CharacterControl character = spatial.getControl(CharacterControl.class);
if (character != null) {
character.setPhysicsLocation(spatial.getWorldTranslation());
}
// toolController.selectedSpatialTransformed();
}
@Override
public void sceneRedo() {
spatial.setLocalTranslation(after);
RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
if (control != null) {
control.setPhysicsLocation(spatial.getWorldTranslation());
}
CharacterControl character = spatial.getControl(CharacterControl.class);
if (character != null) {
character.setPhysicsLocation(spatial.getWorldTranslation());
}
//toolController.selectedSpatialTransformed();
}
public void setAfter(Vector3f after) {
this.after.set(after);
}
}
}

@ -0,0 +1,189 @@
/*
* 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 com.jme3.gde.scenecomposer.tools.shortcuts;
import com.jme3.asset.AssetManager;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.scenecomposer.SceneComposerToolController;
import com.jme3.gde.scenecomposer.tools.PickManager;
import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
/**
*
* @author dokthar
*/
public class RotateShortcut extends ShortcutTool {
private Vector3f currentAxis;
private StringBuilder numberBuilder;
private Spatial spatial;
private PickManager pickManager;
private boolean pickEnabled;
private Quaternion startRotation;
private Quaternion finalRotation;
@Override
public boolean isActivableBy(KeyInputEvent kie) {
return kie.getKeyCode() == KeyInput.KEY_R;
}
@Override
public void cancel() {
spatial.setLocalRotation(startRotation);
terminate();
}
private void apply() {
actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotation, finalRotation));
terminate();
}
private void init(Spatial selectedSpatial) {
spatial = selectedSpatial;
startRotation = spatial.getLocalRotation().clone();
currentAxis = Vector3f.UNIT_XYZ;
pickManager = Lookup.getDefault().lookup(PickManager.class);
pickEnabled = false;
}
@Override
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
hideMarker();
numberBuilder = new StringBuilder();
if (selectedSpatial == null) {
terminate();
} else {
init(selectedSpatial);
}
}
@Override
public void keyPressed(KeyInputEvent kie) {
if (kie.isPressed()) {
Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie);
Vector3f axis = new Vector3f();
boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis);
if (axisChanged) {
currentAxis = axis;
}
boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder);
boolean enterHit = ShortcutManager.checkEnterHit(kie);
boolean escHit = ShortcutManager.checkEscHit(kie);
if (escHit) {
cancel();
} else if (enterHit) {
apply();
} else if (axisChanged && pickEnabled) {
pickEnabled = false;
spatial.setLocalRotation(startRotation.clone());
} else if (axisChanged || numberChanged) {
//update transformation
/* float number = ShortcutManager.getNumberKey(numberBuilder);
Vector3f translation = currentAxis.mult(number);
finalPosition = startPosition.add(translation);
spatial.setLocalTranslation(finalPosition);
*/
}
}
}
@Override
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
if (pressed) {
apply();
}
}
@Override
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
if (pressed) {
cancel();
}
}
@Override
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
if (!pickEnabled) {
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), SceneComposerToolController.TransformationType.camera, camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_X)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else {
return;
}
}
if (pickManager.updatePick(camera, screenCoord)) {
Quaternion rotation = startRotation.mult(pickManager.getRotation(startRotation.inverse()));
toolController.getSelectedSpatial().setLocalRotation(rotation);
finalRotation = rotation;
updateToolsTransformation();
}
}
@Override
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
if (pressed) {
apply();
}
}
@Override
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
if (pressed) {
cancel();
}
}
private class RotateUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Quaternion before, after;
RotateUndo(Spatial spatial, Quaternion before, Quaternion after) {
this.spatial = spatial;
this.before = before;
this.after = after;
}
@Override
public void sceneUndo() {
spatial.setLocalRotation(before);
toolController.selectedSpatialTransformed();
}
@Override
public void sceneRedo() {
spatial.setLocalRotation(after);
toolController.selectedSpatialTransformed();
}
}
}

@ -0,0 +1,199 @@
/*
* 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 com.jme3.gde.scenecomposer.tools.shortcuts;
import com.jme3.asset.AssetManager;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.scenecomposer.SceneComposerToolController;
import com.jme3.gde.scenecomposer.tools.PickManager;
import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
/**
*
* @author dokthar
*/
public class ScaleShortcut extends ShortcutTool {
private Vector3f currentAxis;
private StringBuilder numberBuilder;
private Spatial spatial;
private PickManager pickManager;
private boolean pickEnabled;
private Vector3f startScale;
private Vector3f finalScale;
@Override
public boolean isActivableBy(KeyInputEvent kie) {
return kie.getKeyCode() == KeyInput.KEY_S;
}
@Override
public void cancel() {
spatial.setLocalScale(startScale);
terminate();
}
private void apply() {
actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startScale, finalScale));
terminate();
}
private void init(Spatial selectedSpatial) {
spatial = selectedSpatial;
startScale = spatial.getLocalScale().clone();
currentAxis = Vector3f.UNIT_XYZ;
pickManager = Lookup.getDefault().lookup(PickManager.class);
pickEnabled = false;
}
@Override
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
hideMarker();
numberBuilder = new StringBuilder();
if (selectedSpatial == null) {
terminate();
} else {
init(selectedSpatial);
}
}
@Override
public void keyPressed(KeyInputEvent kie) {
if (kie.isPressed()) {
Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie);
Vector3f axis = new Vector3f();
boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis);
if (axisChanged) {
currentAxis = axis;
}
boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder);
boolean enterHit = ShortcutManager.checkEnterHit(kie);
boolean escHit = ShortcutManager.checkEscHit(kie);
if (escHit) {
cancel();
} else if (enterHit) {
apply();
} else if (axisChanged && pickEnabled) {
pickEnabled = false;
} else if (axisChanged || numberChanged) {
//update transformation
/* float number = ShortcutManager.getNumberKey(numberBuilder);
Vector3f translation = currentAxis.mult(number);
finalPosition = startPosition.add(translation);
spatial.setLocalTranslation(finalPosition);
*/
}
}
}
@Override
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
if (pressed) {
apply();
}
}
@Override
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
if (pressed) {
cancel();
}
}
@Override
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
if (!pickEnabled) {
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), SceneComposerToolController.TransformationType.camera, camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_X)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord);
pickEnabled = true;
} else {
return;
}
}
if (pickManager.updatePick(camera, screenCoord)) {
Vector3f scale = startScale;
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
Vector3f constraintAxis = pickManager.getStartOffset().normalize();
float diff = pickManager.getTranslation(constraintAxis).dot(constraintAxis);
diff *= 0.5f;
scale = startScale.add(new Vector3f(diff, diff, diff));
} else {
// Get the translation in the spatial Space
Quaternion worldToSpatial = toolController.getSelectedSpatial().getWorldRotation().inverse();
Vector3f diff = pickManager.getTranslation(worldToSpatial.mult(currentAxis));
diff.multLocal(0.5f);
scale = startScale.add(diff);
}
finalScale = scale;
toolController.getSelectedSpatial().setLocalScale(scale);
updateToolsTransformation();
}
}
@Override
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
if (pressed) {
apply();
}
}
@Override
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
if (pressed) {
cancel();
}
}
private class ScaleUndo extends AbstractUndoableSceneEdit {
private Spatial spatial;
private Vector3f before, after;
ScaleUndo(Spatial spatial, Vector3f before, Vector3f after) {
this.spatial = spatial;
this.before = before;
this.after = after;
}
@Override
public void sceneUndo() {
spatial.setLocalScale(before);
toolController.selectedSpatialTransformed();
}
@Override
public void sceneRedo() {
spatial.setLocalScale(after);
toolController.selectedSpatialTransformed();
}
}
}

@ -0,0 +1,335 @@
/*
* 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 com.jme3.gde.scenecomposer.tools.shortcuts;
import com.jme3.gde.scenecomposer.SceneEditTool;
import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.math.Vector3f;
import java.util.ArrayList;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author dokthar
*/
@ServiceProvider(service = ShortcutManager.class)
public class ShortcutManager {
private ShortcutTool currentShortcut;
private ArrayList<ShortcutTool> shortcutList;
private boolean ctrlDown = false;
private boolean shiftDown = false;
private boolean altDown = false;
public ShortcutManager() {
shortcutList = new ArrayList<ShortcutTool>();
shortcutList.add(new MoveShortcut());
shortcutList.add(new RotateShortcut());
shortcutList.add(new ScaleShortcut());
shortcutList.add(new DuplicateShortcut());
shortcutList.add(new DeleteShortcut());
}
/*
Methodes
*/
/**
* This MUST be called by the shortcut tool once the modifications are done.
*/
public void terminate() {
currentShortcut = null;
}
/**
*
* @return true if a shortCutTool is active, else return false.
*/
public boolean isActive() {
return currentShortcut != null;
}
/**
* @return the ctrlDown
*/
public boolean isCtrlDown() {
return ctrlDown;
}
/**
* @return the shiftDown
*/
public boolean isShiftDown() {
return shiftDown;
}
/**
* @return the altDown
*/
public boolean isAltDown() {
return altDown;
}
/**
* Set the current shortcut to <code>shortcut</code>. cancel the current
* shortcut if it was still active
*
* @param shortcut the ShortCutTool to set
*/
public void setShortCut(ShortcutTool shortcut) {
if (isActive()) {
currentShortcut.cancel();
}
currentShortcut = shortcut;
}
/**
* Get the shortcut that can be enable with the given kei, the current
* shortcut cannot be enable twice. This also check for command key used to
* provide isCtrlDown(), isShiftDown() and isAltDown().
*
* @param kie the KeyInputEvent
* @return the activable shortcut else return null
*/
public ShortcutTool getActivableShortcut(KeyInputEvent kie) {
if (checkCommandeKey(kie)) {
return null;
}
for (ShortcutTool s : shortcutList) {
if (s != currentShortcut) {
if (s.isActivableBy(kie)) {
return s;
}
}
}
return null;
}
/**
*
* @return the current active shortcut
*/
public ShortcutTool getActiveShortcut() {
return currentShortcut;
}
/**
*
* @param kie the KeyInputEvent
* @return true if the given Kei can enable a sortcut, else false
*/
public boolean canActivateShortcut(KeyInputEvent kie) {
return getActivableShortcut(kie) != null;
}
/**
* Set the current shortcut with the shortcut one that can be enable with
* the given key
*
* @param kie the KeyInputEvent
* @return true is the shortcut changed, else false
*/
public boolean activateShortcut(KeyInputEvent kie) {
ShortcutTool newShortcut = getActivableShortcut(kie);
if (newShortcut != null) {
currentShortcut = newShortcut;
}
return newShortcut != null;
}
/**
* This should be called to trigger the currentShortcut.keyPressed() method.
* This also check for command key used to provide isCtrlDown(),
* isShiftDown() and isAltDown().
*
* @param kie
*/
public void doKeyPressed(KeyInputEvent kie) {
if (checkCommandeKey(kie)) {
//return;
} else if (isActive()) {
currentShortcut.keyPressed(kie);
}
}
private boolean checkCommandeKey(KeyInputEvent kie) {
if (checkCtrlHit(kie)) {
ctrlDown = kie.isPressed();
return true;
} else if (checkAltHit(kie)) {
altDown = kie.isPressed();
return true;
} else if (checkShiftHit(kie)) {
shiftDown = kie.isPressed();
return true;
}
return false;
}
/*
STATIC
*/
/**
*
* @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;
}
/**
*
* @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;
}
/**
*
* @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;
}
/**
*
* @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;
}
/**
*
* @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;
}
return false;
}
/**
* store the number kie into the numberBuilder
*
* @param kie
* @param numberBuilder
* @return true if the given kie is handled as a number key event
*/
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, "");
} else {
numberBuilder.insert(0, '-');
}
} 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(".");
}
}
return true;
}
return false;
}
/**
*
* @param numberBuilder the StringBuilder storing the float number
* @return the float value created from the given StringBuilder
*/
public static float getNumberKey(StringBuilder numberBuilder) {
if (numberBuilder.length() == 0) {
return 0;
} else {
return new Float(numberBuilder.toString());
}
}
/**
* Check for axis input for key X,Y,Z and store the corresponding UNIT_ into
* the axisStore
*
* @param kie
* @param axisStore
* @return true if the given kie is handled as a Axis input
*/
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;
}
return false;
}
}

@ -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 com.jme3.gde.scenecomposer.tools.shortcuts;
import com.jme3.gde.scenecomposer.SceneEditTool;
import com.jme3.input.event.KeyInputEvent;
import org.openide.util.Lookup;
/**
*
* @author dokthar
*/
public abstract class ShortcutTool extends SceneEditTool {
public abstract boolean isActivableBy(KeyInputEvent kie);
public abstract void cancel();
protected final void terminate() {
Lookup.getDefault().lookup(ShortcutManager.class).terminate();
}
@Override
public abstract void keyPressed(KeyInputEvent kie);
}

@ -35,6 +35,10 @@ include 'jme3-testdata'
// Example projects
include 'jme3-examples'
if(buildAndroidExamples == "true"){
include 'jme3-android-examples'
}
if(buildSdkProject == "true"){
include 'sdk'
}

Loading…
Cancel
Save