src/android patchset: changes AndroidAssetManager, AndroidInput, OGLESContext, JmeSystem, TextureLoader
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7502 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
0ec3bb6dba
commit
a8e9d803dc
287
engine/src/android/com/jme3/app/android/AndroidApplication.java
Normal file
287
engine/src/android/com/jme3/app/android/AndroidApplication.java
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.jme3.app.android;
|
||||||
|
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import com.jme3.app.Application;
|
||||||
|
import com.jme3.font.BitmapFont;
|
||||||
|
import com.jme3.font.BitmapText;
|
||||||
|
import com.jme3.input.android.AndroidInput;
|
||||||
|
import com.jme3.renderer.RenderManager;
|
||||||
|
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial.CullHint;
|
||||||
|
import com.jme3.system.AppSettings;
|
||||||
|
import com.jme3.system.JmeSystem;
|
||||||
|
import com.jme3.util.FastInteger;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>AndroidApplication</code> extends the {@link com.jme3.app.Application}
|
||||||
|
* class to provide default functionality like a first-person camera,
|
||||||
|
* and an accessible root node that is updated and rendered regularly.
|
||||||
|
* It will display the current frames-per-second value on-screen.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class AndroidApplication extends Application implements DialogInterface.OnClickListener
|
||||||
|
{
|
||||||
|
|
||||||
|
protected Node rootNode = new Node("Root Node");
|
||||||
|
protected Node guiNode = new Node("Gui Node");
|
||||||
|
protected float secondCounter = 0.0f;
|
||||||
|
protected BitmapText fpsText;
|
||||||
|
protected CharBuffer textBuf = CharBuffer.allocate(50);
|
||||||
|
protected char[] fpsBuf = new char[16];
|
||||||
|
protected BitmapFont guiFont;
|
||||||
|
|
||||||
|
protected Activity activity;
|
||||||
|
protected AndroidInput input;
|
||||||
|
protected final AtomicBoolean loadingFinished;
|
||||||
|
|
||||||
|
public AndroidApplication()
|
||||||
|
{
|
||||||
|
this(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AndroidApplication(Activity activity, AndroidInput input)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.activity = activity;
|
||||||
|
this.input = input;
|
||||||
|
|
||||||
|
loadingFinished = new AtomicBoolean(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
// Set the correct xml parser driver for android
|
||||||
|
System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");
|
||||||
|
|
||||||
|
if (settings == null)
|
||||||
|
{
|
||||||
|
settings = new AppSettings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use vertex arrays for rendering
|
||||||
|
settings.putBoolean("USE_VA", true);
|
||||||
|
// Verbose logging off
|
||||||
|
settings.putBoolean("VERBOSE_LOGGING", false);
|
||||||
|
|
||||||
|
//re-setting settings they can have been merged from the registry.
|
||||||
|
setSettings(settings);
|
||||||
|
super.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves guiNode
|
||||||
|
* @return guiNode Node object
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public Node getGuiNode() {
|
||||||
|
return guiNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves rootNode
|
||||||
|
* @return rootNode Node object
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public Node getRootNode() {
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches FPS statistics to guiNode and displays it on the screen.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void loadFPSText() {
|
||||||
|
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
|
||||||
|
fpsText = new BitmapText(guiFont, false);
|
||||||
|
fpsText.setLocalTranslation(0, fpsText.getLineHeight(), 0);
|
||||||
|
fpsText.setText("Frames per second");
|
||||||
|
guiNode.attachChild(fpsText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
// Create a default Android assetmanager before Application can create one in super.initialize();
|
||||||
|
assetManager = JmeSystem.newAssetManager(null);
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
guiNode.setQueueBucket(Bucket.Gui);
|
||||||
|
guiNode.setCullHint(CullHint.Never);
|
||||||
|
loadFPSText();
|
||||||
|
viewPort.attachScene(rootNode);
|
||||||
|
guiViewPort.attachScene(guiNode);
|
||||||
|
|
||||||
|
// call user code
|
||||||
|
init();
|
||||||
|
|
||||||
|
// Start thread for async load
|
||||||
|
Thread t = new Thread(new Runnable()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run ()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// call user code
|
||||||
|
asyncload();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
handleError("AsyncLoad failed", e);
|
||||||
|
}
|
||||||
|
loadingFinished.set(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
super.update(); // makes sure to execute AppTasks
|
||||||
|
if (speed == 0 || paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float tpf = timer.getTimePerFrame() * speed;
|
||||||
|
|
||||||
|
secondCounter += timer.getTimePerFrame();
|
||||||
|
int fps = (int) timer.getFrameRate();
|
||||||
|
if (secondCounter >= 5.0f) {
|
||||||
|
textBuf.clear();
|
||||||
|
textBuf.put("Frames per second: ");
|
||||||
|
FastInteger.toCharArray(fps, fpsBuf);
|
||||||
|
textBuf.put(fpsBuf);
|
||||||
|
textBuf.flip();
|
||||||
|
fpsText.setText(textBuf);
|
||||||
|
secondCounter = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update states
|
||||||
|
stateManager.update(tpf);
|
||||||
|
|
||||||
|
// simple update and root node
|
||||||
|
update(tpf);
|
||||||
|
rootNode.updateLogicalState(tpf);
|
||||||
|
guiNode.updateLogicalState(tpf);
|
||||||
|
rootNode.updateGeometricState();
|
||||||
|
guiNode.updateGeometricState();
|
||||||
|
|
||||||
|
// render states
|
||||||
|
stateManager.render(renderManager);
|
||||||
|
renderManager.render(tpf);
|
||||||
|
render(renderManager);
|
||||||
|
stateManager.postRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void init();
|
||||||
|
|
||||||
|
public void update(float tpf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(RenderManager rm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets called by a different thread to allow
|
||||||
|
* async loading of assets.
|
||||||
|
*
|
||||||
|
* This means that update and rendering can already
|
||||||
|
* happen while some assets are still loading.
|
||||||
|
*/
|
||||||
|
public void asyncload()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an error has occured. This is typically
|
||||||
|
* invoked when an uncought exception is thrown in the render thread.
|
||||||
|
* @param errorMsg The error message, if any, or null.
|
||||||
|
* @param t Throwable object, or null.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleError(final String errorMsg, final Throwable t)
|
||||||
|
{
|
||||||
|
|
||||||
|
String s = "";
|
||||||
|
if (t != null && t.getStackTrace() != null)
|
||||||
|
{
|
||||||
|
for (StackTraceElement ste: t.getStackTrace())
|
||||||
|
{
|
||||||
|
s += ste.getClassName() + "." + ste.getMethodName() + "(" + + ste.getLineNumber() + ") ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final String sTrace = s;
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
AlertDialog dialog = new AlertDialog.Builder(activity)
|
||||||
|
// .setIcon(R.drawable.alert_dialog_icon)
|
||||||
|
.setTitle(t != null ? t.toString() : "Failed")
|
||||||
|
.setPositiveButton("Kill", AndroidApplication.this)
|
||||||
|
.setMessage((errorMsg != null ? errorMsg + ": " : "") + sTrace)
|
||||||
|
.create();
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the android alert dialog, terminate the activity and OpenGL rendering
|
||||||
|
* @param dialog
|
||||||
|
* @param whichButton
|
||||||
|
*/
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton)
|
||||||
|
{
|
||||||
|
this.stop();
|
||||||
|
activity.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,147 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.jme3.asset;
|
package com.jme3.asset;
|
||||||
|
|
||||||
import com.jme3.asset.plugins.AndroidLocator;
|
|
||||||
import com.jme3.audio.AudioData;
|
|
||||||
import com.jme3.audio.AudioKey;
|
|
||||||
import com.jme3.export.binary.BinaryExporter;
|
|
||||||
import com.jme3.export.binary.BinaryImporter;
|
|
||||||
import com.jme3.font.BitmapFont;
|
|
||||||
import com.jme3.font.plugins.BitmapFontLoader;
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.material.plugins.J3MLoader;
|
|
||||||
import com.jme3.scene.Spatial;
|
|
||||||
import com.jme3.shader.Shader;
|
|
||||||
import com.jme3.shader.ShaderKey;
|
|
||||||
import com.jme3.shader.plugins.GLSLLoader;
|
|
||||||
import com.jme3.texture.Image;
|
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
import com.jme3.texture.plugins.AndroidImageLoader;
|
import com.jme3.texture.plugins.AndroidImageLoader;
|
||||||
import java.io.File;
|
import java.net.URL;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import com.jme3.asset.plugins.AndroidLocator;
|
||||||
|
import com.jme3.asset.plugins.ClasspathLocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AssetManager for Android
|
* <code>AndroidAssetManager</code> is an implementation of DesktopAssetManager for Android
|
||||||
*
|
*
|
||||||
* @author Kirill Vainer
|
* @author larynx
|
||||||
*/
|
*/
|
||||||
public final class AndroidAssetManager implements AssetManager {
|
public class AndroidAssetManager extends DesktopAssetManager {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(AndroidAssetManager.class.getName());
|
private static final Logger logger = Logger.getLogger(AndroidAssetManager.class.getName());
|
||||||
|
|
||||||
private final AndroidLocator locator = new AndroidLocator();
|
|
||||||
private final AndroidImageLoader imageLoader = new AndroidImageLoader();
|
|
||||||
private final BinaryImporter modelLoader = new BinaryImporter();
|
|
||||||
private final BitmapFontLoader fontLoader = new BitmapFontLoader();
|
|
||||||
private final J3MLoader j3mLoader = new J3MLoader();
|
|
||||||
private final J3MLoader j3mdLoader = new J3MLoader();
|
|
||||||
private final GLSLLoader glslLoader = new GLSLLoader();
|
|
||||||
|
|
||||||
private final BinaryExporter exporter = new BinaryExporter();
|
|
||||||
private final HashMap<AssetKey, Object> cache = new HashMap<AssetKey, Object>();
|
|
||||||
|
|
||||||
public AndroidAssetManager(){
|
public AndroidAssetManager(){
|
||||||
this(false);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public AndroidAssetManager(boolean loadDefaults){
|
public AndroidAssetManager(boolean loadDefaults){
|
||||||
if (loadDefaults){
|
//this(Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Android.cfg"));
|
||||||
// AssetConfig cfg = new AssetConfig(this);
|
this(null);
|
||||||
// InputStream stream = AssetManager.class.getResourceAsStream("Desktop.cfg");
|
|
||||||
// try{
|
|
||||||
// cfg.loadText(stream);
|
|
||||||
// }catch (IOException ex){
|
|
||||||
// logger.log(Level.SEVERE, "Failed to load asset config", ex);
|
|
||||||
// }finally{
|
|
||||||
// if (stream != null)
|
|
||||||
// try{
|
|
||||||
// stream.close();
|
|
||||||
// }catch (IOException ex){
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AndroidAssetManager constructor
|
||||||
|
* If URL == null then a default list of locators and loaders for android is set
|
||||||
|
* @param configFile
|
||||||
|
*/
|
||||||
|
public AndroidAssetManager(URL configFile)
|
||||||
|
{
|
||||||
|
super(configFile);
|
||||||
|
System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");
|
||||||
|
|
||||||
|
if (configFile == null)
|
||||||
|
{
|
||||||
|
// Set Default
|
||||||
|
this.registerLocator("", AndroidLocator.class);
|
||||||
|
this.registerLocator("", ClasspathLocator.class);
|
||||||
|
this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
|
||||||
|
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m");
|
||||||
|
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md");
|
||||||
|
this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt");
|
||||||
|
this.registerLoader(com.jme3.texture.plugins.DDSLoader.class, "dds");
|
||||||
|
this.registerLoader(com.jme3.texture.plugins.PFMLoader.class, "pfm");
|
||||||
|
this.registerLoader(com.jme3.texture.plugins.HDRLoader.class, "hdr");
|
||||||
|
this.registerLoader(com.jme3.texture.plugins.TGALoader.class, "tga");
|
||||||
|
this.registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o");
|
||||||
|
this.registerLoader(com.jme3.scene.plugins.OBJLoader.class, "obj");
|
||||||
|
this.registerLoader(com.jme3.scene.plugins.MTLLoader.class, "mtl");
|
||||||
|
this.registerLoader(com.jme3.scene.plugins.ogre.MeshLoader.class, "meshxml", "mesh.xml");
|
||||||
|
this.registerLoader(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeletonxml", "skeleton.xml");
|
||||||
|
this.registerLoader(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material");
|
||||||
|
this.registerLoader(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene");
|
||||||
|
this.registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib");
|
||||||
|
}
|
||||||
|
|
||||||
logger.info("AndroidAssetManager created.");
|
logger.info("AndroidAssetManager created.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerLoader(String loaderClass, String ... extensions){
|
/**
|
||||||
}
|
* Loads a texture.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Texture loadTexture(TextureKey key){
|
||||||
|
Texture tex = (Texture) loadAsset(key);
|
||||||
|
|
||||||
public void registerLocator(String rootPath, String locatorClass, String ... extensions){
|
// Needed for Android
|
||||||
}
|
|
||||||
|
|
||||||
private Object tryLoadFromHD(AssetKey key){
|
|
||||||
if (!key.getExtension().equals("fnt"))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
File f = new File("/sdcard/" + key.getName() + ".opt");
|
|
||||||
if (!f.exists())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
InputStream stream = new FileInputStream(f);
|
|
||||||
BitmapFont font = (BitmapFont) modelLoader.load(stream, null, null);
|
|
||||||
stream.close();
|
|
||||||
return font;
|
|
||||||
} catch (IOException ex){
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryPutToHD(AssetKey key, Object data){
|
|
||||||
if (!key.getExtension().equals("fnt"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
File f = new File("/sdcard/" + key.getName() + ".opt");
|
|
||||||
|
|
||||||
try {
|
|
||||||
BitmapFont font = (BitmapFont) data;
|
|
||||||
OutputStream stream = new FileOutputStream(f);
|
|
||||||
exporter.save(font, stream);
|
|
||||||
stream.close();
|
|
||||||
} catch (IOException ex){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object loadAsset(AssetKey key){
|
|
||||||
logger.info("loadAsset(" + key + ")");
|
|
||||||
Object asset;
|
|
||||||
// Object asset = tryLoadFromHD(key);
|
|
||||||
// if (asset != null)
|
|
||||||
// return asset;
|
|
||||||
|
|
||||||
if (key.shouldCache()){
|
|
||||||
asset = cache.get(key);
|
|
||||||
if (asset != null)
|
|
||||||
return key.createClonedInstance(asset);
|
|
||||||
}
|
|
||||||
// find resource
|
|
||||||
AssetInfo info = locator.locate(this, key);
|
|
||||||
if (info == null){
|
|
||||||
logger.log(Level.WARNING, "Cannot locate resource: "+key.getName());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String ex = key.getExtension();
|
|
||||||
logger.log(Level.INFO, "Loading asset: "+key.getName());
|
|
||||||
try{
|
|
||||||
if (ex.equals("png") || ex.equals("jpg")
|
|
||||||
|| ex.equals("jpeg") || ex.equals("j3i")){
|
|
||||||
Image image;
|
|
||||||
if (ex.equals("j3i")){
|
|
||||||
image = (Image) modelLoader.load(info);
|
|
||||||
}else{
|
|
||||||
image = (Image) imageLoader.load(info);
|
|
||||||
}
|
|
||||||
TextureKey tkey = (TextureKey) key;
|
|
||||||
asset = image;
|
|
||||||
Texture tex = (Texture) tkey.postProcess(asset);
|
|
||||||
tex.setMagFilter(Texture.MagFilter.Nearest);
|
tex.setMagFilter(Texture.MagFilter.Nearest);
|
||||||
tex.setAnisotropicFilter(0);
|
tex.setAnisotropicFilter(0);
|
||||||
if (tex.getMinFilter().usesMipMapLevels()){
|
if (tex.getMinFilter().usesMipMapLevels()){
|
||||||
@ -149,121 +112,7 @@ public final class AndroidAssetManager implements AssetManager {
|
|||||||
}else{
|
}else{
|
||||||
tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
|
tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
|
||||||
}
|
}
|
||||||
asset = tex;
|
return tex;
|
||||||
}else if (ex.equals("j3o")){
|
|
||||||
asset = modelLoader.load(info);
|
|
||||||
}else if (ex.equals("fnt")){
|
|
||||||
asset = fontLoader.load(info);
|
|
||||||
}else if (ex.equals("j3md")){
|
|
||||||
asset = j3mdLoader.load(info);
|
|
||||||
}else if (ex.equals("j3m")){
|
|
||||||
asset = j3mLoader.load(info);
|
|
||||||
}else{
|
|
||||||
logger.info("loading asset as glsl shader ...");
|
|
||||||
asset = glslLoader.load(info);
|
|
||||||
// logger.log(Level.WARNING, "No loader registered for type: "+ex);
|
|
||||||
// return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.shouldCache())
|
|
||||||
cache.put(key, asset);
|
|
||||||
|
|
||||||
// tryPutToHD(key, asset);
|
|
||||||
|
|
||||||
return key.createClonedInstance(asset);
|
|
||||||
} catch (Exception e){
|
|
||||||
logger.log(Level.WARNING, "Failed to load resource: "+key.getName(), e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssetInfo locateAsset(AssetKey<?> key){
|
|
||||||
AssetInfo info = locator.locate(this, key);
|
|
||||||
if (info == null){
|
|
||||||
logger.log(Level.WARNING, "Cannot locate resource: "+key.getName());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Object loadAsset(String name) {
|
|
||||||
return loadAsset(new AssetKey(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Spatial loadModel(String name) {
|
|
||||||
return (Spatial) loadAsset(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Material loadMaterial(String name) {
|
|
||||||
return (Material) loadAsset(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitmapFont loadFont(String name){
|
|
||||||
return (BitmapFont) loadAsset(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Texture loadTexture(TextureKey key){
|
|
||||||
return (Texture) loadAsset(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Texture loadTexture(String name){
|
|
||||||
return loadTexture(new TextureKey(name, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Shader loadShader(ShaderKey key){
|
|
||||||
logger.info("loadShader(" + key + ")");
|
|
||||||
|
|
||||||
String vertName = key.getVertName();
|
|
||||||
String fragName = key.getFragName();
|
|
||||||
|
|
||||||
String vertSource = (String) loadAsset(new AssetKey(vertName));
|
|
||||||
String fragSource = (String) loadAsset(new AssetKey(fragName));
|
|
||||||
|
|
||||||
Shader s = new Shader(key.getLanguage());
|
|
||||||
s.addSource(Shader.ShaderType.Vertex, vertName, vertSource, key.getDefines().getCompiled());
|
|
||||||
s.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled());
|
|
||||||
|
|
||||||
logger.info("returing shader: [" + s + "]");
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void registerLocator(String rootPath, String locatorClassName) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public AudioData loadAudio(AudioKey key) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public AudioData loadAudio(String name) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Spatial loadModel(ModelKey key) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* new */
|
|
||||||
|
|
||||||
private AssetEventListener eventListener = null;
|
|
||||||
|
|
||||||
public void setAssetEventListener(AssetEventListener listener){
|
|
||||||
eventListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerLocator(String rootPath, Class<? extends AssetLocator> locatorClass){
|
|
||||||
logger.warning("not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerLoader(Class<? extends AssetLoader> loader, String ... extensions){
|
|
||||||
logger.warning("not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.jme3.asset.plugins;
|
package com.jme3.asset.plugins;
|
||||||
|
|
||||||
import android.content.res.AssetManager;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import com.jme3.asset.AssetInfo;
|
import com.jme3.asset.AssetInfo;
|
||||||
import com.jme3.asset.AssetKey;
|
import com.jme3.asset.AssetKey;
|
||||||
@ -8,20 +7,22 @@ import com.jme3.asset.AssetLocator;
|
|||||||
import com.jme3.system.JmeSystem;
|
import com.jme3.system.JmeSystem;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class AndroidLocator implements AssetLocator {
|
public class AndroidLocator implements AssetLocator {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(AndroidLocator.class.getName());
|
private static final Logger logger = Logger.getLogger(AndroidLocator.class.getName());
|
||||||
private Resources resources;
|
private Resources resources;
|
||||||
private AssetManager androidManager;
|
private android.content.res.AssetManager androidManager;
|
||||||
|
private String rootPath = "";
|
||||||
|
|
||||||
private class AndroidAssetInfo extends AssetInfo {
|
private class AndroidAssetInfo extends AssetInfo {
|
||||||
|
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
|
|
||||||
public AndroidAssetInfo(com.jme3.asset.AssetManager manager, AssetKey key,
|
public AndroidAssetInfo(com.jme3.asset.AssetManager manager, AssetKey<?> key, InputStream in)
|
||||||
InputStream in){
|
{
|
||||||
super(manager, key);
|
super(manager, key);
|
||||||
this.in = in;
|
this.in = in;
|
||||||
}
|
}
|
||||||
@ -33,28 +34,40 @@ public class AndroidLocator implements AssetLocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AndroidLocator(){
|
public AndroidLocator()
|
||||||
|
{
|
||||||
resources = JmeSystem.getResources();
|
resources = JmeSystem.getResources();
|
||||||
androidManager = resources.getAssets();
|
androidManager = resources.getAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRootPath(String rootPath) {
|
public void setRootPath(String rootPath)
|
||||||
|
{
|
||||||
|
this.rootPath = rootPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssetInfo locate(com.jme3.asset.AssetManager manager, AssetKey key) {
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public AssetInfo locate(com.jme3.asset.AssetManager manager, AssetKey key)
|
||||||
|
{
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
|
String sAssetPath = rootPath + key.getName();
|
||||||
|
// Fix path issues
|
||||||
|
if (sAssetPath.startsWith("/"))
|
||||||
|
{
|
||||||
|
// Remove leading /
|
||||||
|
sAssetPath = sAssetPath.substring(1);
|
||||||
|
}
|
||||||
|
sAssetPath = sAssetPath.replace("//", "/");
|
||||||
try {
|
try {
|
||||||
in = androidManager.open(key.getName());
|
in = androidManager.open(sAssetPath);
|
||||||
if (in == null)
|
if (in == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new AndroidAssetInfo(manager, key, in);
|
return new AndroidAssetInfo(manager, key, in);
|
||||||
} catch (IOException ex) {
|
|
||||||
if (in != null)
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ex1) {
|
|
||||||
}
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
logger.log(Level.WARNING, "Failed to locate {0} ", sAssetPath);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -2,123 +2,44 @@ package com.jme3.input.android;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.GestureDetector;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ScaleGestureDetector;
|
||||||
|
import com.jme3.input.android.TouchEvent;
|
||||||
import com.jme3.input.KeyInput;
|
import com.jme3.input.KeyInput;
|
||||||
import com.jme3.input.MouseInput;
|
import com.jme3.input.MouseInput;
|
||||||
import com.jme3.input.RawInputListener;
|
import com.jme3.input.RawInputListener;
|
||||||
import com.jme3.input.event.KeyInputEvent;
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
import com.jme3.input.event.MouseButtonEvent;
|
import com.jme3.input.event.MouseButtonEvent;
|
||||||
import com.jme3.input.event.MouseMotionEvent;
|
import com.jme3.input.event.MouseMotionEvent;
|
||||||
|
import com.jme3.math.Vector2f;
|
||||||
|
|
||||||
public class AndroidInput extends GLSurfaceView implements KeyInput, MouseInput {
|
|
||||||
|
|
||||||
private RawInputListener listener;
|
public class AndroidInput extends GLSurfaceView implements KeyInput, MouseInput,
|
||||||
private int lastX = -1, lastY = -1;
|
GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener
|
||||||
|
{
|
||||||
|
private final static Logger logger = Logger.getLogger(AndroidInput.class.getName());
|
||||||
|
|
||||||
private static final char[] ANDROID_TO_JME_CHR = {
|
private RawInputListener listenerRaw = null;
|
||||||
0x0,// unknown
|
private AndroidTouchInputListener listenerTouch = null;
|
||||||
0x0,// soft left
|
private ScaleGestureDetector scaledetector;
|
||||||
0x0,// soft right
|
private GestureDetector detector;
|
||||||
0x0,// home
|
private Vector2f lastPos = new Vector2f();
|
||||||
0x0,// back
|
private boolean dragging = false;
|
||||||
0x0,// call
|
|
||||||
0x0,// endcall
|
|
||||||
'0',
|
|
||||||
'1',
|
|
||||||
'2',
|
|
||||||
'3',
|
|
||||||
'4',
|
|
||||||
'5',
|
|
||||||
'6',
|
|
||||||
'7',
|
|
||||||
'8',
|
|
||||||
'9',
|
|
||||||
'*',
|
|
||||||
'#',
|
|
||||||
0x0,//dpad_up
|
|
||||||
0x0,//dpad_down
|
|
||||||
0x0,//dpad_left
|
|
||||||
0x0,//dpad_right
|
|
||||||
0x0,//dpad_center
|
|
||||||
0x0,//volume up
|
|
||||||
0x0,//volume down
|
|
||||||
0x0,//power
|
|
||||||
0x0,//camera
|
|
||||||
0x0,//clear
|
|
||||||
'a',
|
|
||||||
'b',
|
|
||||||
'c',
|
|
||||||
'd',
|
|
||||||
'e',
|
|
||||||
'f',
|
|
||||||
'g',
|
|
||||||
'h',
|
|
||||||
'i',
|
|
||||||
'j',
|
|
||||||
'k',
|
|
||||||
'l',
|
|
||||||
'm',
|
|
||||||
'n',
|
|
||||||
'o',
|
|
||||||
'p',
|
|
||||||
'q',
|
|
||||||
'r',
|
|
||||||
's',
|
|
||||||
't',
|
|
||||||
'u',
|
|
||||||
'v',
|
|
||||||
'w',
|
|
||||||
'x',
|
|
||||||
'y',
|
|
||||||
'z',
|
|
||||||
',',
|
|
||||||
'.',
|
|
||||||
|
|
||||||
0x0,//left alt
|
private List<Object> currentEvents = new ArrayList<Object>();
|
||||||
0x0,//right alt
|
|
||||||
0x0,//left ctrl
|
|
||||||
0x0,//right ctrl
|
|
||||||
|
|
||||||
// 0x0,//fn
|
private final static int MAX_EVENTS = 1024;
|
||||||
// 0x0,//cap
|
|
||||||
|
|
||||||
|
private boolean FIRE_MOUSE_EVENTS = true;
|
||||||
|
|
||||||
'\t',
|
|
||||||
' ',
|
|
||||||
0x0,//sym(bol)
|
|
||||||
0x0,//explorer
|
|
||||||
0x0,//envelope
|
|
||||||
'\n',//newline
|
|
||||||
0x0,//delete
|
|
||||||
'`',
|
|
||||||
'-',
|
|
||||||
'=',
|
|
||||||
'[',
|
|
||||||
']',
|
|
||||||
'\\',//backslash
|
|
||||||
';',
|
|
||||||
'\'',//apostrophe
|
|
||||||
'/',//slash
|
|
||||||
'@',//at
|
|
||||||
0x0,//num
|
|
||||||
0x0,//headset hook
|
|
||||||
0x0,//focus
|
|
||||||
0x0,
|
|
||||||
0x0,//menu
|
|
||||||
0x0,//notification
|
|
||||||
0x0,//search
|
|
||||||
0x0,//media play/pause
|
|
||||||
0x0,//media stop
|
|
||||||
0x0,//media next
|
|
||||||
0x0,//media previous
|
|
||||||
0x0,//media rewind
|
|
||||||
0x0,//media fastforward
|
|
||||||
0x0,//mute
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final int[] ANDROID_TO_JME = {
|
private static final int[] ANDROID_TO_JME = {
|
||||||
0x0, // unknown
|
0x0, // unknown
|
||||||
@ -223,170 +144,170 @@ public class AndroidInput extends GLSurfaceView implements KeyInput, MouseInput
|
|||||||
0x0,//mute
|
0x0,//mute
|
||||||
};
|
};
|
||||||
|
|
||||||
// private int[] keyMap = {
|
public AndroidInput(Context ctx, AttributeSet attribs)
|
||||||
// 0x0,
|
{
|
||||||
// KeyEvent.KEYCODE_BACK, // ESC key
|
|
||||||
//
|
|
||||||
// KeyEvent.KEYCODE_1,
|
|
||||||
// KeyEvent.KEYCODE_2,
|
|
||||||
// KeyEvent.KEYCODE_3,
|
|
||||||
// KeyEvent.KEYCODE_4,
|
|
||||||
// KeyEvent.KEYCODE_5,
|
|
||||||
// KeyEvent.KEYCODE_6,
|
|
||||||
// KeyEvent.KEYCODE_7,
|
|
||||||
// KeyEvent.KEYCODE_8,
|
|
||||||
// KeyEvent.KEYCODE_9,
|
|
||||||
// KeyEvent.KEYCODE_0,
|
|
||||||
// KeyEvent.KEYCODE_MINUS,
|
|
||||||
// KeyEvent.KEYCODE_EQUALS,
|
|
||||||
// KeyEvent.KEYCODE_BACK,
|
|
||||||
// KeyEvent.KEYCODE_TAB,
|
|
||||||
// KeyEvent.KEYCODE_Q,
|
|
||||||
// KeyEvent.KEYCODE_W,
|
|
||||||
// KeyEvent.KEYCODE_E,
|
|
||||||
// KeyEvent.KEYCODE_R,
|
|
||||||
// KeyEvent.KEYCODE_T,
|
|
||||||
// KeyEvent.KEYCODE_Y,
|
|
||||||
// KeyEvent.KEYCODE_U,
|
|
||||||
// KeyEvent.KEYCODE_I,
|
|
||||||
// KeyEvent.KEYCODE_O,
|
|
||||||
// KeyEvent.KEYCODE_P,
|
|
||||||
// KeyEvent.KEYCODE_LEFT_BRACKET,
|
|
||||||
// KeyEvent.KEYCODE_RIGHT_BRACKET,
|
|
||||||
// KeyEvent.KEYCODE_ENTER,
|
|
||||||
// KeyEvent.KEYCODE_SOFT_LEFT, // Left Ctrl
|
|
||||||
// KeyEvent.KEYCODE_A,
|
|
||||||
// KeyEvent.KEYCODE_S,
|
|
||||||
// KeyEvent.KEYCODE_D,
|
|
||||||
// KeyEvent.KEYCODE_F,
|
|
||||||
// KeyEvent.KEYCODE_G,
|
|
||||||
// KeyEvent.KEYCODE_H,
|
|
||||||
// KeyEvent.KEYCODE_J,
|
|
||||||
// KeyEvent.KEYCODE_K,
|
|
||||||
// KeyEvent.KEYCODE_L,
|
|
||||||
// KeyEvent.KEYCODE_SEMICOLON,
|
|
||||||
// KeyEvent.KEYCODE_APOSTROPHE,
|
|
||||||
// KeyEvent.KEYCODE_GRAVE,
|
|
||||||
// KeyEvent.KEYCODE_SHIFT_LEFT,
|
|
||||||
// KeyEvent.KEYCODE_BACKSLASH,
|
|
||||||
// KeyEvent.KEYCODE_Z,
|
|
||||||
// KeyEvent.KEYCODE_X,
|
|
||||||
// KeyEvent.KEYCODE_C,
|
|
||||||
// KeyEvent.KEYCODE_V,
|
|
||||||
// KeyEvent.KEYCODE_B,
|
|
||||||
// KeyEvent.KEYCODE_N,
|
|
||||||
// KeyEvent.KEYCODE_M,
|
|
||||||
//
|
|
||||||
// KeyEvent.KEYCODE_COMMA,
|
|
||||||
// KeyEvent.KEYCODE_PERIOD,
|
|
||||||
// KeyEvent.KEYCODE_SLASH,
|
|
||||||
// KeyEvent.KEYCODE_SHIFT_RIGHT,
|
|
||||||
// KeyEvent.KEYCODE_STAR,
|
|
||||||
//
|
|
||||||
// KeyEvent.KEYCODE_ALT_LEFT,
|
|
||||||
// KeyEvent.KEYCODE_SPACE,
|
|
||||||
//
|
|
||||||
// 0x0, // no caps lock
|
|
||||||
//
|
|
||||||
// 0x0, // F1
|
|
||||||
// 0x0, // F2
|
|
||||||
// 0x0, // F3
|
|
||||||
// 0x0, // F4
|
|
||||||
// 0x0, // F5
|
|
||||||
// 0x0, // F6
|
|
||||||
// 0x0, // F7
|
|
||||||
// 0x0, // F8
|
|
||||||
// 0x0, // F9
|
|
||||||
// 0x0, // F10
|
|
||||||
//
|
|
||||||
// KeyEvent.KEYCODE_NUM,
|
|
||||||
// 0x0, // scroll lock
|
|
||||||
//
|
|
||||||
// 0x0, // numpad7
|
|
||||||
// 0x0, // numpad8
|
|
||||||
// 0x0, // numpad9
|
|
||||||
//
|
|
||||||
// KeyEvent.
|
|
||||||
// }
|
|
||||||
|
|
||||||
public AndroidInput(Context ctx, AttributeSet attribs){
|
|
||||||
super(ctx, attribs);
|
super(ctx, attribs);
|
||||||
|
detector=new GestureDetector(this);
|
||||||
|
scaledetector=new ScaleGestureDetector(ctx, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidInput(Context ctx){
|
public AndroidInput(Context ctx)
|
||||||
|
{
|
||||||
super(ctx);
|
super(ctx);
|
||||||
|
detector=new GestureDetector(this);
|
||||||
|
scaledetector=new ScaleGestureDetector(ctx, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onTouchEvent gets called from android thread on touchpad events
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent motionEvent){
|
public boolean onTouchEvent(MotionEvent event)
|
||||||
int newX = getWidth() - (int) motionEvent.getX();
|
{
|
||||||
int newY = (int) motionEvent.getY();
|
boolean bWasHandled = false;
|
||||||
|
MouseButtonEvent btn;
|
||||||
|
TouchEvent touch;
|
||||||
|
|
||||||
|
// Send the raw event
|
||||||
|
processEvent(event);
|
||||||
|
|
||||||
|
// Try to detect gestures
|
||||||
|
this.detector.onTouchEvent(event);
|
||||||
|
this.scaledetector.onTouchEvent(event);
|
||||||
|
|
||||||
|
|
||||||
switch (motionEvent.getAction()){
|
switch (event.getAction())
|
||||||
|
{
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
MouseButtonEvent btn = new MouseButtonEvent(0, true, newX, newY);
|
|
||||||
btn.setTime(motionEvent.getEventTime());
|
// Store current pos
|
||||||
|
lastPos.set(event.getX(),event.getY());
|
||||||
|
|
||||||
|
if (FIRE_MOUSE_EVENTS)
|
||||||
|
{
|
||||||
|
// Handle mouse events
|
||||||
|
btn = new MouseButtonEvent(0, true, (int)lastPos.getX(), (int)lastPos.getY());
|
||||||
|
btn.setTime(event.getEventTime());
|
||||||
processEvent(btn);
|
processEvent(btn);
|
||||||
// listener.onMouseButtonEvent(btn);
|
}
|
||||||
lastX = -1;
|
|
||||||
lastY = -1;
|
// Handle gesture events
|
||||||
return true;
|
touch = new TouchEvent(TouchEvent.Type.GRABBED, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
|
||||||
|
processEvent(touch);
|
||||||
|
|
||||||
|
bWasHandled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
MouseButtonEvent btn2 = new MouseButtonEvent(0, false, newX, newY);
|
|
||||||
btn2.setTime(motionEvent.getEventTime());
|
if (FIRE_MOUSE_EVENTS)
|
||||||
processEvent(btn2);
|
{
|
||||||
// listener.onMouseButtonEvent(btn2);
|
// Handle mouse events
|
||||||
lastX = -1;
|
btn = new MouseButtonEvent(0, false, (int)event.getX(), (int)event.getY());
|
||||||
lastY = -1;
|
btn.setTime(event.getEventTime());
|
||||||
return true;
|
processEvent(btn);
|
||||||
|
}
|
||||||
|
// Handle gesture events
|
||||||
|
if(dragging)
|
||||||
|
{
|
||||||
|
touch = new TouchEvent(TouchEvent.Type.DRAGGED, TouchEvent.Operation.STOPPED,event.getX(),event.getY(),event.getX()-lastPos.getX(),event.getY()-lastPos.getY(),null);
|
||||||
|
processEvent(touch);
|
||||||
|
}
|
||||||
|
touch = new TouchEvent(TouchEvent.Type.RELEASED, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
|
||||||
|
processEvent(touch);
|
||||||
|
dragging=false;
|
||||||
|
bWasHandled = true;
|
||||||
|
break;
|
||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE:
|
||||||
// int newX = getWidth() - (int) motionEvent.getX();
|
if(!scaledetector.isInProgress())
|
||||||
// int newY = (int) motionEvent.getY();
|
{
|
||||||
|
if(!dragging)
|
||||||
|
touch = new TouchEvent(TouchEvent.Type.DRAGGED, TouchEvent.Operation.STARTED,event.getX(),event.getY(),event.getX()-lastPos.getX(),event.getY()-lastPos.getY(),null);
|
||||||
|
else
|
||||||
|
touch = new TouchEvent(TouchEvent.Type.DRAGGED, TouchEvent.Operation.RUNNING,event.getX(),event.getY(),event.getX()-lastPos.getX(),event.getY()-lastPos.getY(),null);
|
||||||
|
|
||||||
|
processEvent(touch);
|
||||||
|
dragging=true;
|
||||||
|
}
|
||||||
|
if (FIRE_MOUSE_EVENTS)
|
||||||
|
{
|
||||||
|
int newX = getWidth() - (int) event.getX();
|
||||||
|
int newY = (int) event.getY();
|
||||||
int dx;
|
int dx;
|
||||||
int dy;
|
int dy;
|
||||||
if (lastX != -1){
|
if (lastPos.getX() != -1){
|
||||||
dx = newX - lastX;
|
dx = newX - (int)lastPos.getX();
|
||||||
dy = newY - lastY;
|
dy = newY - (int)lastPos.getY();
|
||||||
}else{
|
}else{
|
||||||
dx = 0;
|
dx = 0;
|
||||||
dy = 0;
|
dy = 0;
|
||||||
}
|
}
|
||||||
lastX = newX;
|
|
||||||
lastY = newY;
|
|
||||||
MouseMotionEvent mot = new MouseMotionEvent(newX, newY, dx, dy, 0, 0);
|
MouseMotionEvent mot = new MouseMotionEvent(newX, newY, dx, dy, 0, 0);
|
||||||
mot.setTime(motionEvent.getEventTime());
|
mot.setTime(event.getEventTime());
|
||||||
processEvent(mot);
|
processEvent(mot);
|
||||||
//listener.onMouseMotionEvent(mot);
|
|
||||||
try{
|
|
||||||
Thread.sleep(15);
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
}
|
}
|
||||||
return true;
|
bWasHandled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// TODO: implement motion events
|
||||||
|
case MotionEvent.ACTION_POINTER_UP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_POINTER_DOWN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_OUTSIDE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_CANCEL:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return bWasHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown (int keyCode, KeyEvent event) {
|
public boolean onKeyDown (int keyCode, KeyEvent event) {
|
||||||
|
|
||||||
|
// Send the raw event
|
||||||
|
processEvent(event);
|
||||||
|
|
||||||
int jmeCode = ANDROID_TO_JME[keyCode];
|
int jmeCode = ANDROID_TO_JME[keyCode];
|
||||||
|
if (jmeCode != 0)
|
||||||
|
{
|
||||||
String str = event.getCharacters();
|
String str = event.getCharacters();
|
||||||
char c = str != null && str.length() > 0 ? str.charAt(0) : 0x0;
|
char c = str != null && str.length() > 0 ? str.charAt(0) : 0x0;
|
||||||
KeyInputEvent evt = new KeyInputEvent(jmeCode, c, true, false);
|
KeyInputEvent evt = new KeyInputEvent(jmeCode, c, true, false);
|
||||||
|
logger.info("onKeyDown " + evt);
|
||||||
processEvent(evt);
|
processEvent(evt);
|
||||||
// listener.onKeyEvent(evt);
|
}
|
||||||
|
// Handle all keys ourself, except the back button (4)
|
||||||
|
if (keyCode == 4)
|
||||||
return false;
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp (int keyCode, KeyEvent event) {
|
public boolean onKeyUp (int keyCode, KeyEvent event) {
|
||||||
|
|
||||||
|
// Send the raw event
|
||||||
|
processEvent(event);
|
||||||
|
|
||||||
int jmeCode = ANDROID_TO_JME[keyCode];
|
int jmeCode = ANDROID_TO_JME[keyCode];
|
||||||
|
if (jmeCode != 0)
|
||||||
|
{
|
||||||
String str = event.getCharacters();
|
String str = event.getCharacters();
|
||||||
char c = str != null && str.length() > 0 ? str.charAt(0) : 0x0;
|
char c = str != null && str.length() > 0 ? str.charAt(0) : 0x0;
|
||||||
KeyInputEvent evt = new KeyInputEvent(jmeCode, c, false, false);
|
KeyInputEvent evt = new KeyInputEvent(jmeCode, c, false, false);
|
||||||
|
logger.info("onKeyUp " + evt);
|
||||||
processEvent(evt);
|
processEvent(evt);
|
||||||
//listener.onKeyEvent(evt);
|
}
|
||||||
|
|
||||||
|
// Handle all keys ourself, except the back button (4)
|
||||||
|
if (keyCode == 4)
|
||||||
return false;
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCursorVisible(boolean visible){
|
public void setCursorVisible(boolean visible){
|
||||||
@ -410,39 +331,130 @@ public class AndroidInput extends GLSurfaceView implements KeyInput, MouseInput
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: android does not have an Event interface?
|
|
||||||
private List<Object> currentEvents = new ArrayList<Object>();
|
|
||||||
|
|
||||||
private final static int MAX_EVENTS = 1024;
|
|
||||||
|
|
||||||
private void processEvent(Object event) {
|
private void processEvent(Object event)
|
||||||
|
{
|
||||||
synchronized (currentEvents) {
|
synchronized (currentEvents) {
|
||||||
if (currentEvents.size() < MAX_EVENTS)
|
if (currentEvents.size() < MAX_EVENTS)
|
||||||
currentEvents.add(event);
|
currentEvents.add(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object event;
|
||||||
private void generateEvents() {
|
private void generateEvents() {
|
||||||
|
if (listenerRaw != null)
|
||||||
|
{
|
||||||
synchronized (currentEvents) {
|
synchronized (currentEvents) {
|
||||||
for (Object event: currentEvents) {
|
//for (Object event: currentEvents) {
|
||||||
|
for (int i = 0; i < currentEvents.size(); i++) {
|
||||||
|
event = currentEvents.get(i);
|
||||||
if (event instanceof MouseButtonEvent) {
|
if (event instanceof MouseButtonEvent) {
|
||||||
listener.onMouseButtonEvent((MouseButtonEvent) event);
|
listenerRaw.onMouseButtonEvent((MouseButtonEvent) event);
|
||||||
} else if (event instanceof MouseMotionEvent) {
|
} else if (event instanceof MouseMotionEvent) {
|
||||||
listener.onMouseMotionEvent((MouseMotionEvent) event);
|
listenerRaw.onMouseMotionEvent((MouseMotionEvent) event);
|
||||||
} else if (event instanceof KeyInputEvent) {
|
} else if (event instanceof KeyInputEvent) {
|
||||||
listener.onKeyEvent((KeyInputEvent) event);
|
listenerRaw.onKeyEvent((KeyInputEvent) event);
|
||||||
|
} else if (event instanceof TouchEvent) {
|
||||||
|
if (listenerTouch != null)
|
||||||
|
listenerTouch.onTouchEvent((TouchEvent) event);
|
||||||
|
} else if (event instanceof MotionEvent) {
|
||||||
|
if (listenerTouch != null)
|
||||||
|
listenerTouch.onMotionEvent((MotionEvent) event);
|
||||||
|
} else if (event instanceof KeyEvent) {
|
||||||
|
if (listenerTouch != null)
|
||||||
|
listenerTouch.onAndroidKeyEvent((KeyEvent) event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentEvents.clear();
|
currentEvents.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setInputListener(RawInputListener listener) {
|
public void setInputListener(RawInputListener listener) {
|
||||||
this.listener = listener;
|
this.listenerRaw = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputListener(AndroidTouchInputListener listener) {
|
||||||
|
this.listenerRaw = listener;
|
||||||
|
this.listenerTouch = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getInputTimeNanos() {
|
public long getInputTimeNanos() {
|
||||||
return System.nanoTime();
|
return System.nanoTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------- Gesture detected callback events ----------------------------------
|
||||||
|
|
||||||
|
public boolean onDown(MotionEvent event)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onLongPress(MotionEvent event)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.LONGPRESSED, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
|
||||||
|
processEvent(touch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onFling(MotionEvent event, MotionEvent event2, float vx, float vy)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.FLING, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
|
||||||
|
processEvent(touch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onSingleTapConfirmed(MotionEvent event)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.TAP, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
|
||||||
|
processEvent(touch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onDoubleTap(MotionEvent event)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.DOUBLETAP, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
|
||||||
|
processEvent(touch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.SCALE, TouchEvent.Operation.STARTED,scaleGestureDetector.getFocusX(),scaleGestureDetector.getFocusY(),0,0,new float[]{scaleGestureDetector.getCurrentSpan(),scaleGestureDetector.getScaleFactor()});
|
||||||
|
processEvent(touch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onScale(ScaleGestureDetector scaleGestureDetector)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.SCALE, TouchEvent.Operation.RUNNING,scaleGestureDetector.getFocusX(),scaleGestureDetector.getFocusY(),0,0,new float[]{scaleGestureDetector.getCurrentSpan(),scaleGestureDetector.getScaleFactor()});
|
||||||
|
processEvent(touch);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.SCALE, TouchEvent.Operation.STOPPED,scaleGestureDetector.getFocusX(),scaleGestureDetector.getFocusY(),0,0,new float[]{scaleGestureDetector.getCurrentSpan(),scaleGestureDetector.getScaleFactor()});
|
||||||
|
processEvent(touch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
|
||||||
|
float distanceY) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onShowPress(MotionEvent e) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onSingleTapUp(MotionEvent event)
|
||||||
|
{
|
||||||
|
TouchEvent touch = new TouchEvent(TouchEvent.Type.TAP, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
|
||||||
|
processEvent(touch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.jme3.input.android;
|
||||||
|
|
||||||
|
import com.jme3.input.RawInputListener;
|
||||||
|
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AndroidTouchInputListener is an inputlistener interface which defines callbacks/events for android touch screens
|
||||||
|
* For use with class AndroidInput
|
||||||
|
* @author larynx
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface AndroidTouchInputListener extends RawInputListener
|
||||||
|
{
|
||||||
|
public void onTouchEvent(TouchEvent evt);
|
||||||
|
public void onMotionEvent(MotionEvent evt);
|
||||||
|
public void onAndroidKeyEvent(KeyEvent evt);
|
||||||
|
}
|
@ -76,53 +76,10 @@ import java.util.EnumSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/*
|
|
||||||
//import org.lwjgl.opengl.ARBGeometryShader4;
|
|
||||||
//import org.lwjgl.opengl.ARBHalfFloatVertex;
|
|
||||||
//import org.lwjgl.opengl.ARBVertexArrayObject;
|
|
||||||
//import org.lwjgl.opengl.ARBHalfFloatVertex;
|
|
||||||
//import org.lwjgl.opengl.ARBVertexArrayObject;
|
|
||||||
import org.lwjgl.opengl.ARBDrawBuffers;
|
|
||||||
//import org.lwjgl.opengl.ARBDrawInstanced;
|
|
||||||
import org.lwjgl.opengl.ARBDrawInstanced;
|
|
||||||
import org.lwjgl.opengl.ARBMultisample;
|
|
||||||
import org.lwjgl.opengl.ContextCapabilities;
|
|
||||||
import org.lwjgl.opengl.EXTTextureArray;
|
|
||||||
import org.lwjgl.opengl.EXTTextureFilterAnisotropic;
|
|
||||||
import org.lwjgl.opengl.GLContext;
|
|
||||||
import org.lwjgl.opengl.NVHalfFloat;
|
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL11.*;
|
|
||||||
import static org.lwjgl.opengl.GL12.*;
|
|
||||||
import static org.lwjgl.opengl.GL13.*;
|
|
||||||
import static org.lwjgl.opengl.GL14.*;
|
|
||||||
import static org.lwjgl.opengl.GL15.*;
|
|
||||||
import static org.lwjgl.opengl.GL20.*;
|
|
||||||
|
|
||||||
import static org.lwjgl.opengl.EXTFramebufferObject.*;
|
|
||||||
import static org.lwjgl.opengl.EXTFramebufferMultisample.*;
|
|
||||||
import static org.lwjgl.opengl.EXTFramebufferBlit.*;
|
|
||||||
import org.lwjgl.opengl.ARBShaderObjects.*;
|
|
||||||
import org.lwjgl.opengl.ARBVertexArrayObject;
|
|
||||||
//import static org.lwjgl.opengl.ARBDrawInstanced.*;
|
|
||||||
*/
|
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
|
||||||
import javax.microedition.khronos.egl.EGLContext;
|
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.opengl.GLES10;
|
import android.opengl.GLES10;
|
||||||
import android.opengl.GLES11;
|
import android.opengl.GLES11;
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
import android.opengl.GLUtils;
|
|
||||||
import android.opengl.Matrix;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -168,14 +125,14 @@ public class OGLESShaderRenderer implements Renderer {
|
|||||||
private int clipX, clipY, clipW, clipH;
|
private int clipX, clipY, clipW, clipH;
|
||||||
|
|
||||||
|
|
||||||
private final GL10 gl;
|
//private final GL10 gl;
|
||||||
private boolean powerOf2 = false;
|
private boolean powerOf2 = false;
|
||||||
private boolean verboseLogging = false;
|
private boolean verboseLogging = false;
|
||||||
private boolean useVBO = true;
|
private boolean useVBO = false;
|
||||||
|
|
||||||
|
|
||||||
public OGLESShaderRenderer(GL10 gl) {
|
public OGLESShaderRenderer() {
|
||||||
this.gl = gl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseVA(boolean value) {
|
public void setUseVA(boolean value) {
|
||||||
@ -1869,7 +1826,7 @@ public class OGLESShaderRenderer implements Renderer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 6; i++){
|
for (int i = 0; i < 6; i++){
|
||||||
TextureUtil.uploadTexture(gl, img, GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc, true, powerOf2);
|
TextureUtil.uploadTexture(img, GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc, true, powerOf2);
|
||||||
}
|
}
|
||||||
}/*else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT){
|
}/*else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT){
|
||||||
List<ByteBuffer> data = img.getData();
|
List<ByteBuffer> data = img.getData();
|
||||||
@ -1881,7 +1838,7 @@ public class OGLESShaderRenderer implements Renderer {
|
|||||||
TextureUtil.uploadTexture(img, target, i, 0, tdc);
|
TextureUtil.uploadTexture(img, target, i, 0, tdc);
|
||||||
}
|
}
|
||||||
}*/else{
|
}*/else{
|
||||||
TextureUtil.uploadTexture(gl, img, target, 0, 0, tdc, true, powerOf2);
|
TextureUtil.uploadTexture(img, target, 0, 0, tdc, true, powerOf2);
|
||||||
|
|
||||||
if (verboseLogging)
|
if (verboseLogging)
|
||||||
logger.info("GLES20.glTexParameteri(" + target + "GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)");
|
logger.info("GLES20.glTexParameteri(" + target + "GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)");
|
||||||
@ -2843,11 +2800,18 @@ public class OGLESShaderRenderer implements Renderer {
|
|||||||
|
|
||||||
public void setAlphaToCoverage(boolean value)
|
public void setAlphaToCoverage(boolean value)
|
||||||
{
|
{
|
||||||
// TODO Auto-generated method stub
|
if (value) {
|
||||||
|
GLES20.glEnable(GLES20.GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
} else {
|
||||||
|
GLES20.glDisable(GLES20.GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidateState(){
|
@Override
|
||||||
// TODO invalidateState
|
public void invalidateState()
|
||||||
|
{
|
||||||
|
context.reset();
|
||||||
|
boundShader = null;
|
||||||
|
lastFb = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.jme3.renderer.android;
|
package com.jme3.renderer.android;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLUtils;
|
import android.opengl.GLUtils;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.texture.Image;
|
import com.jme3.texture.Image;
|
||||||
@ -36,7 +37,7 @@ public class TextureUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void buildMipmap(GL10 gl, Bitmap bitmap) {
|
private static void buildMipmap(Bitmap bitmap) {
|
||||||
int level = 0;
|
int level = 0;
|
||||||
int height = bitmap.getHeight();
|
int height = bitmap.getHeight();
|
||||||
int width = bitmap.getWidth();
|
int width = bitmap.getWidth();
|
||||||
@ -61,7 +62,7 @@ public class TextureUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void uploadTextureBitmap(GL10 gl, Bitmap bitmap, boolean generateMips, boolean powerOf2){
|
private static void uploadTextureBitmap(Bitmap bitmap, boolean generateMips, boolean powerOf2){
|
||||||
if (!powerOf2){
|
if (!powerOf2){
|
||||||
int width = bitmap.getWidth();
|
int width = bitmap.getWidth();
|
||||||
int height = bitmap.getHeight();
|
int height = bitmap.getHeight();
|
||||||
@ -76,7 +77,7 @@ public class TextureUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (generateMips){
|
if (generateMips){
|
||||||
buildMipmap(gl, bitmap);
|
buildMipmap(bitmap);
|
||||||
}else{
|
}else{
|
||||||
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
|
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
|
||||||
bitmap.recycle();
|
bitmap.recycle();
|
||||||
@ -84,7 +85,6 @@ public class TextureUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void uploadTexture(
|
public static void uploadTexture(
|
||||||
GL10 gl,
|
|
||||||
Image img,
|
Image img,
|
||||||
int target,
|
int target,
|
||||||
int index,
|
int index,
|
||||||
@ -95,7 +95,7 @@ public class TextureUtil {
|
|||||||
|
|
||||||
if (img.getEfficentData() instanceof Bitmap){
|
if (img.getEfficentData() instanceof Bitmap){
|
||||||
Bitmap bitmap = (Bitmap) img.getEfficentData();
|
Bitmap bitmap = (Bitmap) img.getEfficentData();
|
||||||
uploadTextureBitmap(gl, bitmap, generateMips, powerOf2);
|
uploadTextureBitmap(bitmap, generateMips, powerOf2);
|
||||||
// img.setEfficentData(null);
|
// img.setEfficentData(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -118,71 +118,71 @@ public class TextureUtil {
|
|||||||
|
|
||||||
switch (fmt){
|
switch (fmt){
|
||||||
case Alpha16:
|
case Alpha16:
|
||||||
format = gl.GL_ALPHA;
|
format = GL10.GL_ALPHA;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case Alpha8:
|
case Alpha8:
|
||||||
format = gl.GL_ALPHA;
|
format = GL10.GL_ALPHA;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case Luminance8:
|
case Luminance8:
|
||||||
format = gl.GL_LUMINANCE;
|
format = GL10.GL_LUMINANCE;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case Luminance8Alpha8:
|
case Luminance8Alpha8:
|
||||||
format = gl.GL_LUMINANCE_ALPHA;
|
format = GL10.GL_LUMINANCE_ALPHA;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case Luminance16Alpha16:
|
case Luminance16Alpha16:
|
||||||
format = gl.GL_LUMINANCE_ALPHA;
|
format = GL10.GL_LUMINANCE_ALPHA;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case Luminance16:
|
case Luminance16:
|
||||||
format = gl.GL_LUMINANCE;
|
format = GL10.GL_LUMINANCE;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case RGB565:
|
case RGB565:
|
||||||
format = gl.GL_RGB;
|
format = GL10.GL_RGB;
|
||||||
dataType = gl.GL_UNSIGNED_SHORT_5_6_5;
|
dataType = GL10.GL_UNSIGNED_SHORT_5_6_5;
|
||||||
break;
|
break;
|
||||||
case ARGB4444:
|
case ARGB4444:
|
||||||
format = gl.GL_RGBA;
|
format = GL10.GL_RGBA;
|
||||||
dataType = gl.GL_UNSIGNED_SHORT_4_4_4_4;
|
dataType = GL10.GL_UNSIGNED_SHORT_4_4_4_4;
|
||||||
break;
|
break;
|
||||||
case RGB10:
|
case RGB10:
|
||||||
format = gl.GL_RGB;
|
format = GL10.GL_RGB;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case RGB16:
|
case RGB16:
|
||||||
format = gl.GL_RGB;
|
format = GL10.GL_RGB;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case RGB5A1:
|
case RGB5A1:
|
||||||
format = gl.GL_RGBA;
|
format = GL10.GL_RGBA;
|
||||||
dataType = gl.GL_UNSIGNED_SHORT_5_5_5_1;
|
dataType = GL10.GL_UNSIGNED_SHORT_5_5_5_1;
|
||||||
break;
|
break;
|
||||||
case RGB8:
|
case RGB8:
|
||||||
format = gl.GL_RGB;
|
format = GL10.GL_RGB;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case BGR8:
|
case BGR8:
|
||||||
format = gl.GL_RGB;
|
format = GL10.GL_RGB;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case RGBA16:
|
case RGBA16:
|
||||||
format = gl.GL_RGBA;
|
format = GL10.GL_RGBA;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
case RGBA8:
|
case RGBA8:
|
||||||
format = gl.GL_RGBA;
|
format = GL10.GL_RGBA;
|
||||||
dataType = gl.GL_UNSIGNED_BYTE;
|
dataType = GL10.GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unrecognized format: "+fmt);
|
throw new UnsupportedOperationException("Unrecognized format: "+fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data != null)
|
if (data != null)
|
||||||
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1);
|
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
int[] mipSizes = img.getMipMapSizes();
|
int[] mipSizes = img.getMipMapSizes();
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
@ -197,7 +197,7 @@ public class TextureUtil {
|
|||||||
// of more than paletted compressions is added..
|
// of more than paletted compressions is added..
|
||||||
if (compress){
|
if (compress){
|
||||||
data.clear();
|
data.clear();
|
||||||
gl.glCompressedTexImage2D(gl.GL_TEXTURE_2D,
|
GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
|
||||||
1 - mipSizes.length,
|
1 - mipSizes.length,
|
||||||
format,
|
format,
|
||||||
width,
|
width,
|
||||||
@ -219,7 +219,7 @@ public class TextureUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compress && data != null){
|
if (compress && data != null){
|
||||||
gl.glCompressedTexImage2D(gl.GL_TEXTURE_2D,
|
GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
|
||||||
i,
|
i,
|
||||||
format,
|
format,
|
||||||
mipWidth,
|
mipWidth,
|
||||||
@ -228,7 +228,7 @@ public class TextureUtil {
|
|||||||
data.remaining(),
|
data.remaining(),
|
||||||
data);
|
data);
|
||||||
}else{
|
}else{
|
||||||
gl.glTexImage2D(gl.GL_TEXTURE_2D,
|
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,
|
||||||
i,
|
i,
|
||||||
format,
|
format,
|
||||||
mipWidth,
|
mipWidth,
|
||||||
|
@ -6,8 +6,8 @@ import com.jme3.asset.AndroidAssetManager;
|
|||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
import com.jme3.audio.AudioNode;
|
import com.jme3.audio.AudioNode;
|
||||||
import com.jme3.audio.AudioData;
|
import com.jme3.audio.AudioData;
|
||||||
import com.jme3.audio.AudioRenderer;
|
|
||||||
import com.jme3.audio.AudioParam;
|
import com.jme3.audio.AudioParam;
|
||||||
|
import com.jme3.audio.AudioRenderer;
|
||||||
import com.jme3.audio.Environment;
|
import com.jme3.audio.Environment;
|
||||||
import com.jme3.audio.Listener;
|
import com.jme3.audio.Listener;
|
||||||
import com.jme3.audio.ListenerParam;
|
import com.jme3.audio.ListenerParam;
|
||||||
@ -28,6 +28,7 @@ public class JmeSystem {
|
|||||||
private static final Logger logger = Logger.getLogger(JmeSystem.class.getName());
|
private static final Logger logger = Logger.getLogger(JmeSystem.class.getName());
|
||||||
|
|
||||||
private static boolean initialized = false;
|
private static boolean initialized = false;
|
||||||
|
private static boolean lowPermissions = false;
|
||||||
private static Resources res;
|
private static Resources res;
|
||||||
|
|
||||||
public static void initialize(AppSettings settings){
|
public static void initialize(AppSettings settings){
|
||||||
@ -51,7 +52,15 @@ public class JmeSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getFullName(){
|
public static String getFullName(){
|
||||||
return "jMonkey Engine 3 ALPHA 0.50";
|
return "jMonkey Engine 3 ALPHA 0.50 Android";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setLowPermissions(boolean lowPerm){
|
||||||
|
lowPermissions = lowPerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLowPermissions() {
|
||||||
|
return lowPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JmeContext newContext(AppSettings settings, Type contextType) {
|
public static JmeContext newContext(AppSettings settings, Type contextType) {
|
||||||
@ -71,8 +80,15 @@ public class JmeSystem {
|
|||||||
public void initialize() {}
|
public void initialize() {}
|
||||||
public void update(float tpf) {}
|
public void update(float tpf) {}
|
||||||
public void cleanup() {}
|
public void cleanup() {}
|
||||||
public void updateListenerParam(Listener listener, ListenerParam parameter) {}
|
public void updateListenerParam(Listener listener,
|
||||||
public void updateSourceParam(AudioNode node, AudioParam parameter) {}
|
ListenerParam param) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
public void updateSourceParam(AudioNode src, AudioParam param) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,15 +102,15 @@ public class JmeSystem {
|
|||||||
|
|
||||||
public static AssetManager newAssetManager(){
|
public static AssetManager newAssetManager(){
|
||||||
logger.info("newAssetManager()");
|
logger.info("newAssetManager()");
|
||||||
return new AndroidAssetManager(true);
|
return new AndroidAssetManager(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AssetManager newAssetManager(URL url){
|
public static AssetManager newAssetManager(URL url){
|
||||||
logger.info("newAssetManager(" + url + ")");
|
logger.info("newAssetManager(" + url + ")");
|
||||||
return new AndroidAssetManager(true);
|
return new AndroidAssetManager(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean showSettingsDialog(AppSettings settings) {
|
public static boolean showSettingsDialog(AppSettings settings, boolean loadSettings) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,15 +35,14 @@ package com.jme3.system.android;
|
|||||||
import com.jme3.system.Timer;
|
import com.jme3.system.Timer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>NanoTimer</code> is a System.nanoTime implementation of <code>Timer</code>.
|
* <code>AndroidTimer</code> is a System.nanoTime implementation of <code>Timer</code>.
|
||||||
* This is primarily useful for headless applications running on a server.
|
|
||||||
*
|
|
||||||
* @author Matthew D. Hicks
|
|
||||||
*/
|
*/
|
||||||
public class AndroidTimer extends Timer {
|
public class AndroidTimer extends Timer {
|
||||||
|
|
||||||
private static final long TIMER_RESOLUTION = 1000L;
|
//private static final long TIMER_RESOLUTION = 1000L;
|
||||||
private static final float INVERSE_TIMER_RESOLUTION = 1f/1000L;
|
//private static final float INVERSE_TIMER_RESOLUTION = 1f/1000L;
|
||||||
|
private static final long TIMER_RESOLUTION = 1000000000L;
|
||||||
|
private static final float INVERSE_TIMER_RESOLUTION = 1f/1000000000L;
|
||||||
|
|
||||||
private long startTime;
|
private long startTime;
|
||||||
private long previousTime;
|
private long previousTime;
|
||||||
@ -51,7 +50,8 @@ public class AndroidTimer extends Timer {
|
|||||||
private float fps;
|
private float fps;
|
||||||
|
|
||||||
public AndroidTimer() {
|
public AndroidTimer() {
|
||||||
startTime = System.currentTimeMillis();
|
//startTime = System.currentTimeMillis();
|
||||||
|
startTime = System.nanoTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,7 +66,8 @@ public class AndroidTimer extends Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getTime() {
|
public long getTime() {
|
||||||
return System.currentTimeMillis() - startTime;
|
//return System.currentTimeMillis() - startTime;
|
||||||
|
return System.nanoTime() - startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getResolution() {
|
public long getResolution() {
|
||||||
@ -88,7 +89,8 @@ public class AndroidTimer extends Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
startTime = System.currentTimeMillis();
|
//startTime = System.currentTimeMillis();
|
||||||
|
startTime = System.nanoTime();
|
||||||
previousTime = getTime();
|
previousTime = getTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ import com.jme3.input.JoyInput;
|
|||||||
import com.jme3.input.KeyInput;
|
import com.jme3.input.KeyInput;
|
||||||
import com.jme3.input.MouseInput;
|
import com.jme3.input.MouseInput;
|
||||||
import com.jme3.input.android.AndroidInput;
|
import com.jme3.input.android.AndroidInput;
|
||||||
//import com.jme3.renderer.android.OGLESRenderer;
|
|
||||||
import com.jme3.renderer.android.OGLESShaderRenderer;
|
import com.jme3.renderer.android.OGLESShaderRenderer;
|
||||||
import com.jme3.system.AppSettings;
|
import com.jme3.system.AppSettings;
|
||||||
import com.jme3.system.JmeContext;
|
import com.jme3.system.JmeContext;
|
||||||
@ -51,47 +50,59 @@ import javax.microedition.khronos.egl.EGLConfig;
|
|||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
|
|
||||||
public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
|
public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
|
||||||
|
{
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(OGLESContext.class.getName());
|
private static final Logger logger = Logger.getLogger(OGLESContext.class.getName());
|
||||||
|
|
||||||
protected AtomicBoolean created = new AtomicBoolean(false);
|
protected final AtomicBoolean created = new AtomicBoolean(false);
|
||||||
protected AppSettings settings = new AppSettings(true);
|
protected final AtomicBoolean renderable = new AtomicBoolean(false);
|
||||||
|
protected final AtomicBoolean needClose = new AtomicBoolean(false);
|
||||||
|
protected final Object createdLock = new Object();
|
||||||
|
protected final AppSettings settings = new AppSettings(true);
|
||||||
|
|
||||||
/* < OpenGL ES 2.0 * */
|
|
||||||
//protected OGLESRenderer renderer;
|
|
||||||
/* >= OpenGL ES 2.0 (Android 2.2+) */
|
/* >= OpenGL ES 2.0 (Android 2.2+) */
|
||||||
protected OGLESShaderRenderer renderer;
|
protected OGLESShaderRenderer renderer;
|
||||||
|
|
||||||
protected Timer timer;
|
protected Timer timer;
|
||||||
protected SystemListener listener;
|
protected SystemListener listener;
|
||||||
|
|
||||||
protected AtomicBoolean needClose = new AtomicBoolean(false);
|
|
||||||
protected boolean wasActive = false;
|
protected boolean wasActive = false;
|
||||||
protected int frameRate = 0;
|
|
||||||
protected boolean autoFlush = true;
|
protected boolean autoFlush = true;
|
||||||
|
|
||||||
protected AndroidInput view;
|
protected AndroidInput view;
|
||||||
|
|
||||||
public OGLESContext(){
|
private long milliStart;
|
||||||
}
|
private long milliDelta;
|
||||||
|
protected int frameRate = 33;
|
||||||
|
//protected int minFrameDuration = 1000 / frameRate; // Set a max FPS of 33
|
||||||
|
protected int minFrameDuration = 0; // No FPS cap
|
||||||
|
|
||||||
public Type getType() {
|
public OGLESContext() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType()
|
||||||
|
{
|
||||||
return Type.Display;
|
return Type.Display;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GLSurfaceView createView(Activity activity){
|
public GLSurfaceView createView(Activity activity)
|
||||||
view = new AndroidInput(activity);
|
{
|
||||||
|
return createView(new AndroidInput(activity));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public GLSurfaceView createView(AndroidInput view)
|
||||||
|
{
|
||||||
|
this.view = view;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Requesting client version from GLSurfaceView which is extended by
|
* Requesting client version from GLSurfaceView which is extended by
|
||||||
* AndroidInput.
|
* AndroidInput.
|
||||||
* This is required to get OpenGL ES 2.0
|
* This is required to get OpenGL ES 2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
logger.info("setEGLContextClientVersion(2)");
|
|
||||||
view.setEGLContextClientVersion(2);
|
view.setEGLContextClientVersion(2);
|
||||||
logger.info("setEGLContextClientVersion(2) ... done.");
|
|
||||||
|
|
||||||
//RGB565, Depth16
|
//RGB565, Depth16
|
||||||
view.setEGLConfigChooser(5, 6, 5, 0, 16, 0);
|
view.setEGLConfigChooser(5, 6, 5, 0, 16, 0);
|
||||||
@ -105,11 +116,10 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applySettings(AppSettings setting){
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initInThread(GL10 gl){
|
protected void initInThread()
|
||||||
logger.info("Display created.");
|
{
|
||||||
|
logger.info("OGLESContext create");
|
||||||
logger.fine("Running on thread: "+Thread.currentThread().getName());
|
logger.fine("Running on thread: "+Thread.currentThread().getName());
|
||||||
|
|
||||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
@ -118,174 +128,219 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
created.set(true);
|
|
||||||
|
|
||||||
timer = new AndroidTimer();
|
timer = new AndroidTimer();
|
||||||
|
|
||||||
renderer = new OGLESShaderRenderer(gl);
|
renderer = new OGLESShaderRenderer();
|
||||||
applySettingsToRenderer(renderer, settings);
|
|
||||||
|
renderer.setUseVA(true);
|
||||||
|
renderer.setVerboseLogging(false);
|
||||||
|
|
||||||
renderer.initialize();
|
renderer.initialize();
|
||||||
listener.initialize();
|
listener.initialize();
|
||||||
|
created.set(true);
|
||||||
|
|
||||||
// OGLESShaderRenderer does not support guiView yet
|
needClose.set(false);
|
||||||
// forcefully remove all gui nodes
|
|
||||||
|
|
||||||
if (listener instanceof com.jme3.app.SimpleApplication) {
|
|
||||||
((com.jme3.app.SimpleApplication) listener).getGuiNode().detachAllChildren();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* De-initialize in the OpenGL thread.
|
* De-initialize in the OpenGL thread.
|
||||||
*/
|
*/
|
||||||
protected void deinitInThread(){
|
protected void deinitInThread()
|
||||||
listener.destroy();
|
{
|
||||||
if (renderer != null) {
|
if (renderer != null)
|
||||||
renderer.cleanup();
|
renderer.cleanup();
|
||||||
// do android specific cleaning here
|
|
||||||
|
|
||||||
|
listener.destroy();
|
||||||
|
|
||||||
|
// do android specific cleaning here
|
||||||
logger.info("Display destroyed.");
|
logger.info("Display destroyed.");
|
||||||
|
renderable.set(false);
|
||||||
created.set(false);
|
created.set(false);
|
||||||
renderer = null;
|
renderer = null;
|
||||||
timer = null;
|
timer = null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings)
|
||||||
protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings) {
|
{
|
||||||
logger.warning("setSettings.USE_VA: [" + settings.getBoolean("USE_VA") + "]");
|
logger.warning("setSettings.USE_VA: [" + settings.getBoolean("USE_VA") + "]");
|
||||||
logger.warning("setSettings.VERBOSE_LOGGING: [" + settings.getBoolean("VERBOSE_LOGGING") + "]");
|
logger.warning("setSettings.VERBOSE_LOGGING: [" + settings.getBoolean("VERBOSE_LOGGING") + "]");
|
||||||
renderer.setUseVA(settings.getBoolean("USE_VA"));
|
renderer.setUseVA(settings.getBoolean("USE_VA"));
|
||||||
renderer.setVerboseLogging(settings.getBoolean("VERBOSE_LOGGING"));
|
renderer.setVerboseLogging(settings.getBoolean("VERBOSE_LOGGING"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void applySettings(AppSettings setting)
|
||||||
public void setSettings(AppSettings settings) {
|
{
|
||||||
this.settings.copyFrom(settings);
|
|
||||||
|
|
||||||
// XXX This code should be somewhere else
|
|
||||||
if (renderer != null)
|
if (renderer != null)
|
||||||
applySettingsToRenderer(renderer, this.settings);
|
applySettingsToRenderer(renderer, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSettings(AppSettings settings)
|
||||||
|
{
|
||||||
|
this.settings.copyFrom(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setSystemListener(SystemListener listener){
|
public void setSystemListener(SystemListener listener){
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public AppSettings getSettings() {
|
public AppSettings getSettings() {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public com.jme3.renderer.Renderer getRenderer() {
|
public com.jme3.renderer.Renderer getRenderer() {
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public MouseInput getMouseInput() {
|
public MouseInput getMouseInput() {
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public KeyInput getKeyInput() {
|
public KeyInput getKeyInput() {
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public JoyInput getJoyInput() {
|
public JoyInput getJoyInput() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Timer getTimer() {
|
@Override
|
||||||
|
public Timer getTimer()
|
||||||
|
{
|
||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTitle(String title) {
|
@Override
|
||||||
|
public void setTitle(String title)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCreated(){
|
@Override
|
||||||
|
public boolean isCreated()
|
||||||
|
{
|
||||||
return created.get();
|
return created.get();
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void setAutoFlushFrames(boolean enabled){
|
public void setAutoFlushFrames(boolean enabled)
|
||||||
|
{
|
||||||
this.autoFlush = enabled;
|
this.autoFlush = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderer:initialize
|
// renderer:initialize
|
||||||
public void onSurfaceCreated(GL10 gl, EGLConfig cfg) {
|
@Override
|
||||||
logger.info("Using Android");
|
public void onSurfaceCreated(GL10 gl, EGLConfig cfg)
|
||||||
initInThread(gl);
|
{
|
||||||
|
logger.info("GL Surface created");
|
||||||
|
initInThread();
|
||||||
|
renderable.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SystemListener:reshape
|
// SystemListener:reshape
|
||||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
@Override
|
||||||
|
public void onSurfaceChanged(GL10 gl, int width, int height)
|
||||||
|
{
|
||||||
settings.setResolution(width, height);
|
settings.setResolution(width, height);
|
||||||
listener.reshape(width, height);
|
listener.reshape(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SystemListener:update
|
// SystemListener:update
|
||||||
public void onDrawFrame(GL10 gl) {
|
@Override
|
||||||
if (needClose.get()){
|
public void onDrawFrame(GL10 gl)
|
||||||
deinitInThread(); // ???
|
{
|
||||||
|
|
||||||
|
if (!created.get())
|
||||||
|
throw new IllegalStateException("onDrawFrame without create");
|
||||||
|
|
||||||
|
if (needClose.get())
|
||||||
|
{
|
||||||
|
deinitInThread();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (wasActive != Display.isActive()){
|
if (renderable.get())
|
||||||
// if (!wasActive){
|
{
|
||||||
// listener.gainFocus();
|
milliStart = System.currentTimeMillis();
|
||||||
// wasActive = true;
|
|
||||||
// }else{
|
|
||||||
// listener.loseFocus();
|
|
||||||
// wasActive = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!created.get())
|
|
||||||
throw new IllegalStateException();
|
|
||||||
|
|
||||||
listener.update();
|
listener.update();
|
||||||
|
|
||||||
// swap buffers
|
|
||||||
|
|
||||||
if (frameRate > 0){
|
|
||||||
// Display.sync(frameRate);
|
|
||||||
// synchronzie to framerate
|
|
||||||
}
|
|
||||||
|
|
||||||
if (autoFlush)
|
if (autoFlush)
|
||||||
|
{
|
||||||
renderer.onFrame();
|
renderer.onFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
milliDelta = System.currentTimeMillis() - milliStart;
|
||||||
* TODO: get these methods to follow the spec
|
|
||||||
* @param waitFor
|
// Enforce a FPS cap
|
||||||
*/
|
if (milliDelta < minFrameDuration)
|
||||||
public void create(boolean waitFor) {
|
{
|
||||||
if (created.get()){
|
//logger.log(Level.INFO, "Time per frame {0}", milliDelta);
|
||||||
logger.warning("create() called when display is already created!");
|
try {
|
||||||
return;
|
Thread.sleep(minFrameDuration - milliDelta);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create(){
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRenderable()
|
||||||
|
{
|
||||||
|
return renderable.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create(boolean waitFor)
|
||||||
|
{
|
||||||
|
if (waitFor)
|
||||||
|
waitFor(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void create()
|
||||||
|
{
|
||||||
create(false);
|
create(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restart() {
|
@Override
|
||||||
|
public void restart()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRenderable() {
|
@Override
|
||||||
// TODO isRenderable
|
public void destroy(boolean waitFor)
|
||||||
return true;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: get these methods to follow the spec
|
|
||||||
* @param waitFor
|
|
||||||
*/
|
|
||||||
public void destroy(boolean waitFor) {
|
|
||||||
needClose.set(true);
|
needClose.set(true);
|
||||||
|
if (waitFor)
|
||||||
|
waitFor(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy(){
|
public void destroy()
|
||||||
|
{
|
||||||
destroy(false);
|
destroy(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void waitFor(boolean createdVal)
|
||||||
|
{
|
||||||
|
synchronized (createdLock){
|
||||||
|
while (created.get() != createdVal){
|
||||||
|
try {
|
||||||
|
createdLock.wait();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,11 @@ package com.jme3.texture.plugins;
|
|||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
|
||||||
import com.jme3.asset.AssetInfo;
|
import com.jme3.asset.AssetInfo;
|
||||||
import com.jme3.asset.AssetLoader;
|
import com.jme3.asset.AssetLoader;
|
||||||
|
import com.jme3.asset.TextureKey;
|
||||||
import com.jme3.texture.Image;
|
import com.jme3.texture.Image;
|
||||||
import com.jme3.texture.Image.Format;
|
import com.jme3.texture.Image.Format;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
@ -11,16 +14,19 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public class AndroidImageLoader implements AssetLoader {
|
public class AndroidImageLoader implements AssetLoader
|
||||||
|
{
|
||||||
|
|
||||||
public Object load2(AssetInfo info) throws IOException {
|
public Object load2(AssetInfo info) throws IOException
|
||||||
|
{
|
||||||
ByteBuffer bb = BufferUtils.createByteBuffer(1 * 1 * 2);
|
ByteBuffer bb = BufferUtils.createByteBuffer(1 * 1 * 2);
|
||||||
bb.put( (byte) 0xff ).put( (byte) 0xff );
|
bb.put( (byte) 0xff ).put( (byte) 0xff );
|
||||||
bb.clear();
|
bb.clear();
|
||||||
return new Image(Format.RGB5A1, 1, 1, bb);
|
return new Image(Format.RGB5A1, 1, 1, bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object load(AssetInfo info) throws IOException {
|
public Object load(AssetInfo info) throws IOException
|
||||||
|
{
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
Bitmap bitmap = null;
|
Bitmap bitmap = null;
|
||||||
try {
|
try {
|
||||||
@ -36,56 +42,38 @@ public class AndroidImageLoader implements AssetLoader {
|
|||||||
|
|
||||||
int width = bitmap.getWidth();
|
int width = bitmap.getWidth();
|
||||||
int height = bitmap.getHeight();
|
int height = bitmap.getHeight();
|
||||||
int bytesPerPixel = -1;
|
|
||||||
Format fmt;
|
Format fmt;
|
||||||
|
|
||||||
switch (bitmap.getConfig()){
|
switch (bitmap.getConfig()){
|
||||||
case ALPHA_8:
|
case ALPHA_8:
|
||||||
bytesPerPixel = 1;
|
|
||||||
fmt = Format.Alpha8;
|
fmt = Format.Alpha8;
|
||||||
break;
|
break;
|
||||||
case ARGB_4444:
|
case ARGB_4444:
|
||||||
bytesPerPixel = 2;
|
|
||||||
fmt = Format.ARGB4444;
|
fmt = Format.ARGB4444;
|
||||||
break;
|
break;
|
||||||
case ARGB_8888:
|
case ARGB_8888:
|
||||||
bytesPerPixel = 4;
|
|
||||||
fmt = Format.RGBA8;
|
fmt = Format.RGBA8;
|
||||||
break;
|
break;
|
||||||
case RGB_565:
|
case RGB_565:
|
||||||
bytesPerPixel = 2;
|
|
||||||
fmt = Format.RGB565;
|
fmt = Format.RGB565;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (width > 128 || height > 128){
|
if ( ((TextureKey)info.getKey()).isFlipY() )
|
||||||
// if (width > height){
|
{
|
||||||
// float aspect = (float) height / width;
|
Bitmap newBitmap = null;
|
||||||
// width = 128;
|
Matrix flipMat = new Matrix();
|
||||||
// height = (int) (128 * aspect);
|
flipMat.preScale(1.0f, -1.0f);
|
||||||
//
|
newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
|
||||||
// }else{
|
bitmap.recycle();
|
||||||
// float aspect = (float) width / height;
|
bitmap = newBitmap;
|
||||||
// width = (int) (128 * aspect);
|
|
||||||
// height = 128;
|
|
||||||
// }
|
|
||||||
// bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if ( ((TextureKey)info.getKey()).isFlipY() ){
|
if (bitmap == null){
|
||||||
// Bitmap newBitmap = null;
|
throw new IOException("Failed to flip image: "+info.getKey().getName());
|
||||||
// Matrix flipMat = new Matrix();
|
}
|
||||||
// flipMat.preScale(1.0f, -1.0f);
|
}
|
||||||
// newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
|
|
||||||
// bitmap.recycle();
|
|
||||||
// bitmap = newBitmap;
|
|
||||||
//
|
|
||||||
// if (bitmap == null){
|
|
||||||
// throw new IOException("Failed to load image2: "+info.getKey().getName());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
Image image = new Image(fmt, width, height, null);
|
Image image = new Image(fmt, width, height, null);
|
||||||
image.setEfficentData(bitmap);
|
image.setEfficentData(bitmap);
|
||||||
|
359
engine/src/android/com/jme3/util/FastInteger.java
Normal file
359
engine/src/android/com/jme3/util/FastInteger.java
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
package com.jme3.util;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The wrapper for the primitive type {@code int}.
|
||||||
|
* <p>
|
||||||
|
* As with the specification, this implementation relies on code laid out in <a
|
||||||
|
* href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's
|
||||||
|
* Delight, (Addison Wesley, 2002)</a> as well as <a
|
||||||
|
* href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>.
|
||||||
|
*
|
||||||
|
* @see java.lang.Number
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
|
public final class FastInteger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for the maximum {@code int} value, 2<sup>31</sup>-1.
|
||||||
|
*/
|
||||||
|
public static final int MAX_VALUE = 0x7FFFFFFF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for the minimum {@code int} value, -2<sup>31</sup>.
|
||||||
|
*/
|
||||||
|
public static final int MIN_VALUE = 0x80000000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for the number of bits needed to represent an {@code int} in
|
||||||
|
* two's complement form.
|
||||||
|
*
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static final int SIZE = 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Progressively smaller decimal order of magnitude that can be represented
|
||||||
|
* by an instance of Integer. Used to help compute the String
|
||||||
|
* representation.
|
||||||
|
*/
|
||||||
|
private static final int[] decimalScale = new int[] { 1000000000, 100000000,
|
||||||
|
10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified integer into its decimal string representation.
|
||||||
|
* The returned string is a concatenation of a minus sign if the number is
|
||||||
|
* negative and characters from '0' to '9'.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the integer to convert.
|
||||||
|
* @return the decimal string representation of {@code value}.
|
||||||
|
*/
|
||||||
|
public static boolean toCharArray(int value, char[] output) {
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
output[0] = '0';
|
||||||
|
output[1] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Faster algorithm for smaller Integers
|
||||||
|
if (value < 1000 && value > -1000) {
|
||||||
|
|
||||||
|
int positive_value = value < 0 ? -value : value;
|
||||||
|
int first_digit = 0;
|
||||||
|
if (value < 0) {
|
||||||
|
output[0] = '-';
|
||||||
|
first_digit++;
|
||||||
|
}
|
||||||
|
int last_digit = first_digit;
|
||||||
|
int quot = positive_value;
|
||||||
|
do {
|
||||||
|
int res = quot / 10;
|
||||||
|
int digit_value = quot - ((res << 3) + (res << 1));
|
||||||
|
digit_value += '0';
|
||||||
|
output[last_digit++] = (char) digit_value;
|
||||||
|
quot = res;
|
||||||
|
} while (quot != 0);
|
||||||
|
|
||||||
|
int count = last_digit--;
|
||||||
|
do {
|
||||||
|
char tmp = output[last_digit];
|
||||||
|
output[last_digit--] = output[first_digit];
|
||||||
|
output[first_digit++] = tmp;
|
||||||
|
} while (first_digit < last_digit);
|
||||||
|
output[count] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (value == MIN_VALUE) {
|
||||||
|
System.arraycopy("-2147483648".toCharArray(), 0, output, 0, 12);
|
||||||
|
output[12] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int positive_value = value < 0 ? -value : value;
|
||||||
|
byte first_digit = 0;
|
||||||
|
if (value < 0) {
|
||||||
|
output[0] = '-';
|
||||||
|
first_digit++;
|
||||||
|
}
|
||||||
|
byte last_digit = first_digit;
|
||||||
|
byte count;
|
||||||
|
int number;
|
||||||
|
boolean start = false;
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
count = 0;
|
||||||
|
if (positive_value < (number = decimalScale[i])) {
|
||||||
|
if (start) {
|
||||||
|
output[last_digit++] = '0';
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
number = (decimalScale[i] << 3);
|
||||||
|
if (positive_value >= number) {
|
||||||
|
positive_value -= number;
|
||||||
|
count += 8;
|
||||||
|
}
|
||||||
|
number = (decimalScale[i] << 2);
|
||||||
|
if (positive_value >= number) {
|
||||||
|
positive_value -= number;
|
||||||
|
count += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
number = (decimalScale[i] << 1);
|
||||||
|
if (positive_value >= number) {
|
||||||
|
positive_value -= number;
|
||||||
|
count += 2;
|
||||||
|
}
|
||||||
|
if (positive_value >= decimalScale[i]) {
|
||||||
|
positive_value -= decimalScale[i];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count > 0 && !start) {
|
||||||
|
start = true;
|
||||||
|
}
|
||||||
|
if (start) {
|
||||||
|
output[last_digit++] = (char) (count + '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output[last_digit++] = (char) (positive_value + '0');
|
||||||
|
output[last_digit] = 0;
|
||||||
|
count = last_digit--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the highest (leftmost) bit of the specified integer that is 1
|
||||||
|
* and returns the bit mask value for that bit. This is also referred to as
|
||||||
|
* the Most Significant 1 Bit. Returns zero if the specified integer is
|
||||||
|
* zero.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer to examine.
|
||||||
|
* @return the bit mask indicating the highest 1 bit in {@code i}.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int highestOneBit(int i) {
|
||||||
|
i |= (i >> 1);
|
||||||
|
i |= (i >> 2);
|
||||||
|
i |= (i >> 4);
|
||||||
|
i |= (i >> 8);
|
||||||
|
i |= (i >> 16);
|
||||||
|
return (i & ~(i >>> 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the lowest (rightmost) bit of the specified integer that is 1
|
||||||
|
* and returns the bit mask value for that bit. This is also referred
|
||||||
|
* to as the Least Significant 1 Bit. Returns zero if the specified integer
|
||||||
|
* is zero.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer to examine.
|
||||||
|
* @return the bit mask indicating the lowest 1 bit in {@code i}.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int lowestOneBit(int i) {
|
||||||
|
return (i & (-i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the number of leading zeros in the specified integer prior to
|
||||||
|
* the {@link #highestOneBit(int) highest one bit}.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer to examine.
|
||||||
|
* @return the number of leading zeros in {@code i}.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int numberOfLeadingZeros(int i) {
|
||||||
|
i |= i >> 1;
|
||||||
|
i |= i >> 2;
|
||||||
|
i |= i >> 4;
|
||||||
|
i |= i >> 8;
|
||||||
|
i |= i >> 16;
|
||||||
|
return bitCount(~i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the number of trailing zeros in the specified integer after
|
||||||
|
* the {@link #lowestOneBit(int) lowest one bit}.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer to examine.
|
||||||
|
* @return the number of trailing zeros in {@code i}.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int numberOfTrailingZeros(int i) {
|
||||||
|
return bitCount((i & -i) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the number of 1 bits in the specified integer; this is also
|
||||||
|
* referred to as population count.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer to examine.
|
||||||
|
* @return the number of 1 bits in {@code i}.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int bitCount(int i) {
|
||||||
|
i -= ((i >> 1) & 0x55555555);
|
||||||
|
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
|
||||||
|
i = (((i >> 4) + i) & 0x0F0F0F0F);
|
||||||
|
i += (i >> 8);
|
||||||
|
i += (i >> 16);
|
||||||
|
return (i & 0x0000003F);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the bits of the specified integer to the left by the specified
|
||||||
|
* number of bits.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer value to rotate left.
|
||||||
|
* @param distance
|
||||||
|
* the number of bits to rotate.
|
||||||
|
* @return the rotated value.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int rotateLeft(int i, int distance) {
|
||||||
|
if (distance == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* According to JLS3, 15.19, the right operand of a shift is always
|
||||||
|
* implicitly masked with 0x1F, which the negation of 'distance' is
|
||||||
|
* taking advantage of.
|
||||||
|
*/
|
||||||
|
return ((i << distance) | (i >>> (-distance)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the bits of the specified integer to the right by the specified
|
||||||
|
* number of bits.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer value to rotate right.
|
||||||
|
* @param distance
|
||||||
|
* the number of bits to rotate.
|
||||||
|
* @return the rotated value.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int rotateRight(int i, int distance) {
|
||||||
|
if (distance == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* According to JLS3, 15.19, the right operand of a shift is always
|
||||||
|
* implicitly masked with 0x1F, which the negation of 'distance' is
|
||||||
|
* taking advantage of.
|
||||||
|
*/
|
||||||
|
return ((i >>> distance) | (i << (-distance)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverses the order of the bytes of the specified integer.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer value for which to reverse the byte order.
|
||||||
|
* @return the reversed value.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int reverseBytes(int i) {
|
||||||
|
int b3 = i >>> 24;
|
||||||
|
int b2 = (i >>> 8) & 0xFF00;
|
||||||
|
int b1 = (i & 0xFF00) << 8;
|
||||||
|
int b0 = i << 24;
|
||||||
|
return (b0 | b1 | b2 | b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverses the order of the bits of the specified integer.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer value for which to reverse the bit order.
|
||||||
|
* @return the reversed value.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int reverse(int i) {
|
||||||
|
// From Hacker's Delight, 7-1, Figure 7-1
|
||||||
|
i = (i & 0x55555555) << 1 | (i >> 1) & 0x55555555;
|
||||||
|
i = (i & 0x33333333) << 2 | (i >> 2) & 0x33333333;
|
||||||
|
i = (i & 0x0F0F0F0F) << 4 | (i >> 4) & 0x0F0F0F0F;
|
||||||
|
return reverseBytes(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the {@code signum} function for the specified
|
||||||
|
* integer.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer value to check.
|
||||||
|
* @return -1 if {@code i} is negative, 1 if {@code i} is positive, 0 if
|
||||||
|
* {@code i} is zero.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static int signum(int i) {
|
||||||
|
return (i == 0 ? 0 : (i < 0 ? -1 : 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Integer} instance for the specified integer value.
|
||||||
|
* <p>
|
||||||
|
* If it is not necessary to get a new {@code Integer} instance, it is
|
||||||
|
* recommended to use this method instead of the constructor, since it
|
||||||
|
* maintains a cache of instances which may result in better performance.
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* the integer value to store in the instance.
|
||||||
|
* @return a {@code Integer} instance containing {@code i}.
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public static Integer valueOf(int i) {
|
||||||
|
if (i < -128 || i > 127) {
|
||||||
|
return new Integer(i);
|
||||||
|
}
|
||||||
|
return valueOfCache.CACHE [i+128];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class valueOfCache {
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing.
|
||||||
|
*/
|
||||||
|
static final Integer[] CACHE = new Integer[256];
|
||||||
|
|
||||||
|
static {
|
||||||
|
for(int i=-128; i<=127; i++) {
|
||||||
|
CACHE[i+128] = new Integer(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user