1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-06 12:20:30 +00:00

GODOT IS OPEN SOURCE

This commit is contained in:
Juan Linietsky
2014-02-09 22:10:30 -03:00
parent 0e49da1687
commit 0b806ee0fc
3138 changed files with 1294441 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
/*************************************************************************/
/* Dictionary.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import java.util.HashMap;
import java.util.Set;
public class Dictionary extends HashMap<String, Object> {
protected String[] keys_cache;
public String[] get_keys() {
String[] ret = new String[size()];
int i=0;
Set<String> keys = keySet();
for (String key : keys) {
ret[i] = key;
i++;
};
return ret;
};
public Object[] get_values() {
Object[] ret = new Object[size()];
int i=0;
Set<String> keys = keySet();
for (String key : keys) {
ret[i] = get(key);
i++;
};
return ret;
};
public void set_keys(String[] keys) {
keys_cache = keys;
};
public void set_values(Object[] vals) {
int i=0;
for (String key : keys_cache) {
put(key, vals[i]);
i++;
};
keys_cache = null;
};
};

View File

@@ -0,0 +1,300 @@
/*************************************************************************/
/* Godot.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
import android.widget.LinearLayout;
import android.view.ViewGroup.LayoutParams;
import android.app.*;
import android.content.*;
import android.view.*;
import android.view.inputmethod.InputMethodManager;
import android.os.*;
import android.util.Log;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
import java.lang.reflect.Method;
import java.util.List;
import java.util.ArrayList;
import android.provider.Settings.Secure;
public class Godot extends Activity implements SensorEventListener
{
static public class SingletonBase {
protected void registerClass(String p_name, String[] p_methods) {
GodotLib.singleton(p_name,this);
Class clazz = getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
boolean found=false;
System.out.printf("METHOD: %s\n",method.getName());
for (String s : p_methods) {
System.out.printf("METHOD CMP WITH: %s\n",s);
if (s.equals(method.getName())) {
found=true;
System.out.printf("METHOD CMP VALID");
break;
}
}
if (!found)
continue;
System.out.printf("METHOD FOUND: %s\n",method.getName());
List<String> ptr = new ArrayList<String>();
Class[] paramTypes = method.getParameterTypes();
for (Class c : paramTypes) {
ptr.add(c.getName());
}
String[] pt = new String[ptr.size()];
ptr.toArray(pt);
GodotLib.method(p_name,method.getName(),method.getReturnType().getName(),pt);
}
}
public void registerMethods() {}
}
/*
protected List<SingletonBase> singletons = new ArrayList<SingletonBase>();
protected void instanceSingleton(SingletonBase s) {
s.registerMethods();
singletons.add(s);
}
*/
public GodotView mView;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
public RelativeLayout layout;
static public GodotIO io;
public static void setWindowTitle(String title) {
//setTitle(title);
}
public interface ResultCallback {
public void callback(int requestCode, int resultCode, Intent data);
};
public ResultCallback result_callback;
@Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if (result_callback != null) {
result_callback.callback(requestCode, resultCode, data);
result_callback = null;
};
};
public void onVideoInit(boolean use_gl2) {
// mView = new GodotView(getApplication(),io,use_gl2);
// setContentView(mView);
layout = new RelativeLayout(this);
layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
setContentView(layout);
mView = new GodotView(getApplication(),io,use_gl2, this);
layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
mView.setKeepScreenOn(true);
}
@Override protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
io = new GodotIO(this);
io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
GodotLib.io=io;
GodotLib.initialize(this,io.needsReloadHooks());
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
result_callback = null;
// instanceSingleton( new GodotFacebook(this) );
}
@Override protected void onPause() {
super.onPause();
mView.onPause();
mSensorManager.unregisterListener(this);
GodotLib.focusout();
}
@Override protected void onResume() {
super.onResume();
mView.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
GodotLib.focusin();
}
@Override public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
GodotLib.accelerometer(x,y,z);
}
@Override public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
}
/*
@Override public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
System.out.printf("** BACK REQUEST!\n");
GodotLib.quit();
return true;
}
System.out.printf("** OTHER KEY!\n");
return false;
}
*/
@Override public void onBackPressed() {
GodotLib.quit();
}
public void forceQuit() {
System.exit(0);
}
//@Override public boolean dispatchTouchEvent (MotionEvent event) {
public boolean gotTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
int evcount=event.getPointerCount();
if (evcount==0)
return true;
int[] arr = new int[event.getPointerCount()*3];
for(int i=0;i<event.getPointerCount();i++) {
arr[i*3+0]=(int)event.getPointerId(i);
arr[i*3+1]=(int)event.getX(i);
arr[i*3+2]=(int)event.getY(i);
}
//System.out.printf("gaction: %d\n",event.getAction());
switch(event.getAction()&MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
GodotLib.touch(0,0,evcount,arr);
//System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
} break;
case MotionEvent.ACTION_MOVE: {
GodotLib.touch(1,0,evcount,arr);
//for(int i=0;i<event.getPointerCount();i++) {
// System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
//}
} break;
case MotionEvent.ACTION_POINTER_UP: {
int pointer_idx = event.getActionIndex();
GodotLib.touch(4,pointer_idx,evcount,arr);
//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_POINTER_DOWN: {
int pointer_idx = event.getActionIndex();
GodotLib.touch(3,pointer_idx,evcount,arr);
//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
GodotLib.touch(2,0,evcount,arr);
//for(int i=0;i<event.getPointerCount();i++) {
// System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
//}
} break;
}
return true;
}
@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
GodotLib.key(event.getUnicodeChar(0), false);
return super.onKeyUp(keyCode, event);
};
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
GodotLib.key(event.getUnicodeChar(0), true);
return super.onKeyDown(keyCode, event);
};
// Audio
}

View File

@@ -0,0 +1,514 @@
/*************************************************************************/
/* GodotIO.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import java.util.HashMap;
import java.util.Locale;
import android.net.Uri;
import android.content.Intent;
import android.content.res.AssetManager;
import java.io.InputStream;
import java.io.IOException;
import android.app.*;
import android.content.*;
import android.view.*;
import android.view.inputmethod.InputMethodManager;
import android.os.*;
import android.util.Log;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
import android.content.pm.ActivityInfo;
//android.os.Build
// Wrapper for native library
public class GodotIO {
AssetManager am;
Activity activity;
final int SCREEN_LANDSCAPE=0;
final int SCREEN_PORTRAIT=1;
final int SCREEN_REVERSE_LANDSCAPE=2;
final int SCREEN_REVERSE_PORTRAIT=3;
final int SCREEN_SENSOR_LANDSCAPE=4;
final int SCREEN_SENSOR_PORTRAIT=5;
final int SCREEN_SENSOR=6;
/////////////////////////
/// FILES
/////////////////////////
public int last_file_id=1;
class AssetData {
public boolean eof=false;
public String path;
public InputStream is;
public int len;
public int pos;
}
HashMap<Integer,AssetData> streams;
public int file_open(String path,boolean write) {
//System.out.printf("file_open: Attempt to Open %s\n",path);
if (write)
return -1;
AssetData ad = new AssetData();
try {
ad.is = am.open(path);
} catch (Exception e) {
//System.out.printf("Exception on file_open: %s\n",e);
return -1;
}
try {
ad.len=ad.is.available();
} catch (Exception e) {
System.out.printf("Exception availabling on file_open: %s\n",e);
return -1;
}
ad.path=path;
ad.pos=0;
++last_file_id;
streams.put(last_file_id,ad);
return last_file_id;
}
public int file_get_size(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_get_size: Invalid file id: %d\n",id);
return -1;
}
return streams.get(id).len;
}
public void file_seek(int id,int bytes) {
if (!streams.containsKey(id)) {
System.out.printf("file_get_size: Invalid file id: %d\n",id);
return;
}
//seek sucks
AssetData ad = streams.get(id);
if (bytes>ad.len)
bytes=ad.len;
if (bytes<0)
bytes=0;
try {
if (bytes > (int)ad.pos) {
int todo=bytes-(int)ad.pos;
while(todo>0) {
todo-=ad.is.skip(todo);
}
ad.pos=bytes;
} else if (bytes<(int)ad.pos) {
ad.is=am.open(ad.path);
ad.pos=bytes;
int todo=bytes;
while(todo>0) {
todo-=ad.is.skip(todo);
}
}
ad.eof=false;
} catch (IOException e) {
System.out.printf("Exception on file_seek: %s\n",e);
return;
}
}
public int file_tell(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_read: Can't tell eof for invalid file id: %d\n",id);
return 0;
}
AssetData ad = streams.get(id);
return ad.pos;
}
public boolean file_eof(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_read: Can't check eof for invalid file id: %d\n",id);
return false;
}
AssetData ad = streams.get(id);
return ad.eof;
}
public byte[] file_read(int id, int bytes) {
if (!streams.containsKey(id)) {
System.out.printf("file_read: Can't read invalid file id: %d\n",id);
return new byte[0];
}
AssetData ad = streams.get(id);
if (ad.pos + bytes > ad.len) {
bytes=ad.len-ad.pos;
ad.eof=true;
}
if (bytes==0) {
return new byte[0];
}
byte[] buf1=new byte[bytes];
int r=0;
try {
r = ad.is.read(buf1);
} catch (IOException e) {
System.out.printf("Exception on file_read: %s\n",e);
return new byte[bytes];
}
if (r==0) {
return new byte[0];
}
ad.pos+=r;
if (r<bytes) {
byte[] buf2=new byte[r];
for(int i=0;i<r;i++)
buf2[i]=buf1[i];
return buf2;
} else {
return buf1;
}
}
public void file_close(int id) {
if (!streams.containsKey(id)) {
System.out.printf("file_close: Can't close invalid file id: %d\n",id);
return;
}
streams.remove(id);
}
/////////////////////////
/// DIRECTORIES
/////////////////////////
class AssetDir {
public String[] files;
public int current;
}
public int last_dir_id=1;
HashMap<Integer,AssetDir> dirs;
public int dir_open(String path) {
AssetDir ad = new AssetDir();
ad.current=0;
try {
ad.files = am.list(path);
} catch (IOException e) {
System.out.printf("Exception on dir_open: %s\n",e);
return -1;
}
++last_dir_id;
dirs.put(last_dir_id,ad);
return last_dir_id;
}
public String dir_next(int id) {
if (!dirs.containsKey(id)) {
System.out.printf("dir_next: invalid dir id: %d\n",id);
return "";
}
AssetDir ad = dirs.get(id);
if (ad.current>=ad.files.length)
return "";
String r = ad.files[ad.current];
ad.current++;
return r;
}
public void dir_close(int id) {
if (!dirs.containsKey(id)) {
System.out.printf("dir_close: invalid dir id: %d\n",id);
return;
}
dirs.remove(id);
}
GodotIO(Activity p_activity) {
am=p_activity.getAssets();
activity=p_activity;
streams=new HashMap<Integer,AssetData>();
dirs=new HashMap<Integer,AssetDir>();
}
/////////////////////////
// AUDIO
/////////////////////////
private Object buf;
private Thread mAudioThread;
private AudioTrack mAudioTrack;
public Object audioInit(int sampleRate, int desiredFrames) {
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int frameSize = 4;
System.out.printf("audioInit: initializing audio:\n");
//Log.v("Godot", "Godot audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
// Let the user pick a larger buffer if they really want -- but ye
// gods they probably shouldn't, the minimums are horrifyingly high
// latency already
desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
audioStartThread();
//Log.v("Godot", "Godot audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
buf = new short[desiredFrames * 2];
return buf;
}
public void audioStartThread() {
mAudioThread = new Thread(new Runnable() {
public void run() {
mAudioTrack.play();
GodotLib.audio();
}
});
// I'd take REALTIME if I could get it!
mAudioThread.setPriority(Thread.MAX_PRIORITY);
mAudioThread.start();
}
public void audioWriteShortBuffer(short[] buffer) {
for (int i = 0; i < buffer.length; ) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
Thread.sleep(1);
} catch(InterruptedException e) {
// Nom nom
}
} else {
Log.w("Godot", "Godot audio: error return from write(short)");
return;
}
}
}
public void audioQuit() {
if (mAudioThread != null) {
try {
mAudioThread.join();
} catch(Exception e) {
Log.v("Godot", "Problem stopping audio thread: " + e);
}
mAudioThread = null;
//Log.v("Godot", "Finished waiting for audio thread");
}
if (mAudioTrack != null) {
mAudioTrack.stop();
mAudioTrack = null;
}
}
public void audioPause(boolean p_pause) {
if (p_pause)
mAudioTrack.pause();
else
mAudioTrack.play();
}
/////////////////////////
// MISCELANEOUS OS IO
/////////////////////////
public int openURI(String p_uri) {
try {
Log.v("MyApp", "TRYING TO OPEN URI: " + p_uri);
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(p_uri));
activity.startActivity(myIntent);
return 0;
} catch (ActivityNotFoundException e) {
return 1;
}
}
public String getDataDir() {
return activity.getFilesDir().getAbsolutePath();
}
public String getLocale() {
return Locale.getDefault().toString();
}
public String getModel() {
return Build.MODEL;
}
public boolean needsReloadHooks() {
return android.os.Build.VERSION.SDK_INT < 11;
}
public void showKeyboard(String p_existing_text) {
InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
};
public void hideKeyboard() {
InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMgr.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
};
public void setScreenOrientation(int p_orientation) {
switch(p_orientation) {
case SCREEN_LANDSCAPE: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} break;
case SCREEN_PORTRAIT: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} break;
case SCREEN_REVERSE_LANDSCAPE: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
} break;
case SCREEN_REVERSE_PORTRAIT: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} break;
case SCREEN_SENSOR_LANDSCAPE: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
} break;
case SCREEN_SENSOR_PORTRAIT: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
} break;
case SCREEN_SENSOR: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
} break;
}
};
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
public static String unique_id="";
public String getUniqueID() {
return unique_id;
}
}

View File

@@ -0,0 +1,63 @@
/*************************************************************************/
/* GodotLib.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
// Wrapper for native library
public class GodotLib {
public static GodotIO io;
static {
System.loadLibrary("godot_android");
}
/**
* @param width the current view width
* @param height the current view height
*/
public static native void initialize(Godot p_instance,boolean need_reload_hook);
public static native void resize(int width, int height,boolean reload);
public static native void newcontext();
public static native void quit();
public static native void step();
public static native void touch(int what,int pointer,int howmany, int[] arr);
public static native void accelerometer(float x, float y, float z);
public static native void key(int p_unicode_char, boolean p_pressed);
public static native void focusin();
public static native void focusout();
public static native void audio();
public static native void singleton(String p_name,Object p_object);
public static native void method(String p_sname,String p_name,String p_ret,String[] p_params);
public static native String getGlobal(String p_key);
public static native void callobject(int p_ID, String p_method, Object[] p_params);
}

View File

@@ -0,0 +1,378 @@
/*************************************************************************/
/* GodotView.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
package com.android.godot;
import android.content.Context;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.content.ContextWrapper;
import java.io.File;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
/**
* A simple GLSurfaceView sub-class that demonstrate how to perform
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
* details:
*
* - The class must use a custom context factory to enable 2.0 rendering.
* See ContextFactory class definition below.
*
* - The class must use a custom EGLConfigChooser to be able to select
* an EGLConfig that supports 2.0. This is done by providing a config
* specification to eglChooseConfig() that has the attribute
* EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag
* set. See ConfigChooser class definition below.
*
* - The class must select the surface's format, then choose an EGLConfig
* that matches it exactly (with regards to red/green/blue/alpha channels
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
class GodotView extends GLSurfaceView {
private static String TAG = "GodotView";
private static final boolean DEBUG = false;
private static Context ctx;
private static GodotIO io;
private static boolean firsttime=true;
private static boolean use_gl2=false;
private Godot activity;
public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, Godot p_activity) {
super(context);
ctx=context;
io=p_io;
use_gl2=p_use_gl2;
activity = p_activity;
if (!p_io.needsReloadHooks()) {
//will only work on SDK 11+!!
setPreserveEGLContextOnPause(true);
}
init(false, 16, 0);
}
public GodotView(Context context, boolean translucent, int depth, int stencil) {
super(context);
init(translucent, depth, stencil);
}
@Override public boolean onTouchEvent (MotionEvent event) {
return activity.gotTouchEvent(event);
};
private void init(boolean translucent, int depth, int stencil) {
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
* If we want a translucent one, we should change the surface's
* format here, using PixelFormat.TRANSLUCENT for GL Surfaces
* is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
*/
if (translucent) {
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
/* Setup the context factory for 2.0 rendering.
* See ContextFactory class definition below
*/
setEGLContextFactory(new ContextFactory());
/* We need to choose an EGLConfig that matches the format of
* our surface exactly. This is going to be done in our
* custom config chooser. See ConfigChooser class definition
* below.
*/
setEGLConfigChooser( translucent ?
new ConfigChooser(8, 8, 8, 8, depth, stencil) :
new ConfigChooser(5, 6, 5, 0, depth, stencil) );
/* Set the renderer responsible for frame rendering */
setRenderer(new Renderer());
}
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
if (use_gl2)
Log.w(TAG, "creating OpenGL ES 2.0 context :");
else
Log.w(TAG, "creating OpenGL ES 1.1 context :");
checkEglError("Before eglCreateContext", egl);
int[] attrib_list2 = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl2?attrib_list2:null);
checkEglError("After eglCreateContext", egl);
return context;
}
public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
egl.eglDestroyContext(display, context);
}
}
private static void checkEglError(String prompt, EGL10 egl) {
int error;
while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
}
}
private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
mRedSize = r;
mGreenSize = g;
mBlueSize = b;
mAlphaSize = a;
mDepthSize = depth;
mStencilSize = stencil;
}
/* This EGL config specification is used to specify 2.0 rendering.
* We use a minimum size of 4 bits for red/green/blue, but will
* perform actual matching in chooseConfig() below.
*/
private static int EGL_OPENGL_ES2_BIT = 4;
private static int[] s_configAttribs2 =
{
EGL10.EGL_RED_SIZE, 4,
EGL10.EGL_GREEN_SIZE, 4,
EGL10.EGL_BLUE_SIZE, 4,
// EGL10.EGL_DEPTH_SIZE, 16,
// EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL10.EGL_NONE
};
private static int[] s_configAttribs =
{
EGL10.EGL_RED_SIZE, 4,
EGL10.EGL_GREEN_SIZE, 4,
EGL10.EGL_BLUE_SIZE, 4,
// EGL10.EGL_DEPTH_SIZE, 16,
// EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
EGL10.EGL_NONE
};
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
/* Get the number of minimally matching EGL configurations
*/
int[] num_config = new int[1];
egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, null, 0, num_config);
int numConfigs = num_config[0];
if (numConfigs <= 0) {
throw new IllegalArgumentException("No configs match configSpec");
}
/* Allocate then read the array of minimally matching EGL configs
*/
EGLConfig[] configs = new EGLConfig[numConfigs];
egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, configs, numConfigs, num_config);
if (DEBUG) {
printConfigs(egl, display, configs);
}
/* Now return the "best" one
*/
return chooseConfig(egl, display, configs);
}
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
EGLConfig[] configs) {
for(EGLConfig config : configs) {
int d = findConfigAttrib(egl, display, config,
EGL10.EGL_DEPTH_SIZE, 0);
int s = findConfigAttrib(egl, display, config,
EGL10.EGL_STENCIL_SIZE, 0);
// We need at least mDepthSize and mStencilSize bits
if (d < mDepthSize || s < mStencilSize)
continue;
// We want an *exact* match for red/green/blue/alpha
int r = findConfigAttrib(egl, display, config,
EGL10.EGL_RED_SIZE, 0);
int g = findConfigAttrib(egl, display, config,
EGL10.EGL_GREEN_SIZE, 0);
int b = findConfigAttrib(egl, display, config,
EGL10.EGL_BLUE_SIZE, 0);
int a = findConfigAttrib(egl, display, config,
EGL10.EGL_ALPHA_SIZE, 0);
if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
return config;
}
return null;
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
EGLConfig config, int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0];
}
return defaultValue;
}
private void printConfigs(EGL10 egl, EGLDisplay display,
EGLConfig[] configs) {
int numConfigs = configs.length;
Log.w(TAG, String.format("%d configurations", numConfigs));
for (int i = 0; i < numConfigs; i++) {
Log.w(TAG, String.format("Configuration %d:\n", i));
printConfig(egl, display, configs[i]);
}
}
private void printConfig(EGL10 egl, EGLDisplay display,
EGLConfig config) {
int[] attributes = {
EGL10.EGL_BUFFER_SIZE,
EGL10.EGL_ALPHA_SIZE,
EGL10.EGL_BLUE_SIZE,
EGL10.EGL_GREEN_SIZE,
EGL10.EGL_RED_SIZE,
EGL10.EGL_DEPTH_SIZE,
EGL10.EGL_STENCIL_SIZE,
EGL10.EGL_CONFIG_CAVEAT,
EGL10.EGL_CONFIG_ID,
EGL10.EGL_LEVEL,
EGL10.EGL_MAX_PBUFFER_HEIGHT,
EGL10.EGL_MAX_PBUFFER_PIXELS,
EGL10.EGL_MAX_PBUFFER_WIDTH,
EGL10.EGL_NATIVE_RENDERABLE,
EGL10.EGL_NATIVE_VISUAL_ID,
EGL10.EGL_NATIVE_VISUAL_TYPE,
0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
EGL10.EGL_SAMPLES,
EGL10.EGL_SAMPLE_BUFFERS,
EGL10.EGL_SURFACE_TYPE,
EGL10.EGL_TRANSPARENT_TYPE,
EGL10.EGL_TRANSPARENT_RED_VALUE,
EGL10.EGL_TRANSPARENT_GREEN_VALUE,
EGL10.EGL_TRANSPARENT_BLUE_VALUE,
0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
EGL10.EGL_LUMINANCE_SIZE,
EGL10.EGL_ALPHA_MASK_SIZE,
EGL10.EGL_COLOR_BUFFER_TYPE,
EGL10.EGL_RENDERABLE_TYPE,
0x3042 // EGL10.EGL_CONFORMANT
};
String[] names = {
"EGL_BUFFER_SIZE",
"EGL_ALPHA_SIZE",
"EGL_BLUE_SIZE",
"EGL_GREEN_SIZE",
"EGL_RED_SIZE",
"EGL_DEPTH_SIZE",
"EGL_STENCIL_SIZE",
"EGL_CONFIG_CAVEAT",
"EGL_CONFIG_ID",
"EGL_LEVEL",
"EGL_MAX_PBUFFER_HEIGHT",
"EGL_MAX_PBUFFER_PIXELS",
"EGL_MAX_PBUFFER_WIDTH",
"EGL_NATIVE_RENDERABLE",
"EGL_NATIVE_VISUAL_ID",
"EGL_NATIVE_VISUAL_TYPE",
"EGL_PRESERVED_RESOURCES",
"EGL_SAMPLES",
"EGL_SAMPLE_BUFFERS",
"EGL_SURFACE_TYPE",
"EGL_TRANSPARENT_TYPE",
"EGL_TRANSPARENT_RED_VALUE",
"EGL_TRANSPARENT_GREEN_VALUE",
"EGL_TRANSPARENT_BLUE_VALUE",
"EGL_BIND_TO_TEXTURE_RGB",
"EGL_BIND_TO_TEXTURE_RGBA",
"EGL_MIN_SWAP_INTERVAL",
"EGL_MAX_SWAP_INTERVAL",
"EGL_LUMINANCE_SIZE",
"EGL_ALPHA_MASK_SIZE",
"EGL_COLOR_BUFFER_TYPE",
"EGL_RENDERABLE_TYPE",
"EGL_CONFORMANT"
};
int[] value = new int[1];
for (int i = 0; i < attributes.length; i++) {
int attribute = attributes[i];
String name = names[i];
if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
} else {
// Log.w(TAG, String.format(" %s: failed\n", name));
while (egl.eglGetError() != EGL10.EGL_SUCCESS);
}
}
}
// Subclasses can adjust these values:
protected int mRedSize;
protected int mGreenSize;
protected int mBlueSize;
protected int mAlphaSize;
protected int mDepthSize;
protected int mStencilSize;
private int[] mValue = new int[1];
}
private static class Renderer implements GLSurfaceView.Renderer {
public void onDrawFrame(GL10 gl) {
GodotLib.step();
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GodotLib.resize(width, height,!firsttime);
firsttime=false;
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GodotLib.newcontext();
}
}
}