diff --git a/build/android/AndroidManifest.xml b/build/android/AndroidManifest.xml
new file mode 100644
index 00000000..3f20b30b
--- /dev/null
+++ b/build/android/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/android/LolActivity.java b/build/android/LolActivity.java
new file mode 100644
index 00000000..a7f7f1d3
--- /dev/null
+++ b/build/android/LolActivity.java
@@ -0,0 +1,247 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2013 Sam Hocevar
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the Do What The Fuck You Want To
+// Public License, Version 2, as published by Sam Hocevar. See
+// http://www.wtfpl.net/ for more details.
+//
+
+package net.lolengine;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.AssetManager; /* getAssets() */
+import android.content.res.Resources; /* getResources() */
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.Window;
+
+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;
+
+/* FIXME: this needs to have a different name for each project */
+public class LolActivity extends Activity
+{
+ @Override protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ nativeInit();
+
+ mView = new LolView(getApplication());
+ setContentView(mView);
+ }
+
+ @Override protected void onPause()
+ {
+ super.onPause();
+ mView.onPause();
+ }
+
+ @Override protected void onResume()
+ {
+ super.onResume();
+ mView.onResume();
+ }
+
+ private LolView mView;
+
+ static
+ {
+ System.loadLibrary("stlport_shared");
+ System.loadLibrary("@PROGRAM@");
+ }
+
+ public Bitmap openImage(String name)
+ {
+ try
+ {
+ return BitmapFactory.decodeStream(getAssets().open(name));
+ }
+ catch (Exception e) { }
+ return null;
+ }
+
+ public int getWidth(Bitmap bmp) { return bmp.getWidth(); }
+ public int getHeight(Bitmap bmp) { return bmp.getHeight(); }
+
+ public void getPixels(Bitmap bmp, int[] pixels)
+ {
+ int w = bmp.getWidth();
+ int h = bmp.getHeight();
+ bmp.getPixels(pixels, 0, w, 0, 0, w, h);
+ }
+
+ public void closeImage(Bitmap bmp)
+ {
+ bmp.recycle();
+ }
+
+ private native void nativeInit();
+}
+
+class LolView extends GLSurfaceView
+{
+ public LolView(Context context)
+ {
+ super(context);
+ setEGLContextFactory(new ContextFactory());
+ //setEGLConfigChooser(new ConfigChooser(4, 4, 4, 0, 8, 0));
+ setEGLConfigChooser(new ConfigChooser(4, 4, 4, 4, 8, 0));
+ setRenderer(new LolRenderer());
+ }
+
+ private static class ContextFactory implements GLSurfaceView.EGLContextFactory
+ {
+ private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ public EGLContext createContext(EGL10 egl, EGLDisplay dpy, EGLConfig cfg)
+ {
+ Log.w("LOL", "creating OpenGL ES 2.0 context");
+ int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+ EGLContext ctx = egl.eglCreateContext(dpy, cfg, EGL10.EGL_NO_CONTEXT, attrib_list);
+ return ctx;
+ }
+
+ public void destroyContext(EGL10 egl, EGLDisplay dpy, EGLContext ctx)
+ {
+ egl.eglDestroyContext(dpy, ctx);
+ }
+ }
+
+ private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser
+ {
+ public ConfigChooser(int r, int g, int b, int a, int depth, int stencil)
+ {
+ mRed = r;
+ mGreen = g;
+ mBlue = b;
+ mAlpha = a;
+ mDepth = depth;
+ mStencil = stencil;
+ }
+
+ private static int EGL_OPENGL_ES2_BIT = 4;
+ private static int[] s_configAttribs2 =
+ {
+// EGL10.EGL_BUFFER_SIZE, 16,
+ EGL10.EGL_DEPTH_SIZE, 8,
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+// EGL10.EGL_ALPHA_SIZE, 4,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_NONE
+ };
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay dpy)
+ {
+ int[] num_config = new int[1];
+ egl.eglChooseConfig(dpy, s_configAttribs2, null, 0, num_config);
+
+ int n = num_config[0];
+ if (n <= 0)
+ throw new IllegalArgumentException("No GLES configs");
+
+ EGLConfig[] configs = new EGLConfig[n];
+ egl.eglChooseConfig(dpy, s_configAttribs2, configs, n, num_config);
+ return choose(egl, dpy, configs);
+ }
+
+ public EGLConfig choose(EGL10 egl, EGLDisplay dpy, EGLConfig[] configs)
+ {
+ for(EGLConfig cfg : configs)
+ {
+ /* Do not complain if we get more bits than we asked. */
+ if (get(egl, dpy, cfg, EGL10.EGL_STENCIL_SIZE, 0) >= mStencil
+ && get(egl, dpy, cfg, EGL10.EGL_DEPTH_SIZE, 0) >= mDepth
+ && get(egl, dpy, cfg, EGL10.EGL_RED_SIZE, 0) >= mRed
+ && get(egl, dpy, cfg, EGL10.EGL_GREEN_SIZE, 0) >= mGreen
+ && get(egl, dpy, cfg, EGL10.EGL_BLUE_SIZE, 0) >= mBlue
+ && get(egl, dpy, cfg, EGL10.EGL_ALPHA_SIZE, 0) >= mAlpha)
+ return cfg;
+ }
+ return null;
+ }
+
+ private int get(EGL10 egl, EGLDisplay dpy, EGLConfig cfg,
+ int attr, int defval)
+ {
+ int[] value = new int[1];
+
+ if (egl.eglGetConfigAttrib(dpy, cfg, attr, value))
+ return value[0];
+ return defval;
+ }
+
+ protected int mRed, mGreen, mBlue, mAlpha, mDepth, mStencil;
+ }
+
+ public boolean onTouchEvent(final MotionEvent ev)
+ {
+ final int action = ev.getAction();
+ switch (action)
+ {
+ case MotionEvent.ACTION_DOWN:
+ nativeMove((int)ev.getX(), (int)ev.getY());
+ nativeDown();
+ break;
+ case MotionEvent.ACTION_UP:
+ nativeMove((int)ev.getX(), (int)ev.getY());
+ nativeUp();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ nativeMove((int)ev.getX(), (int)ev.getY());
+ break;
+ }
+
+ return true;
+ }
+
+ private static native void nativePause();
+ private static native void nativeDown();
+ private static native void nativeUp();
+ private static native void nativeMove(int x, int y);
+}
+
+class LolRenderer implements GLSurfaceView.Renderer
+{
+ public void onSurfaceCreated(GL10 gl, EGLConfig config)
+ {
+ nativeInit();
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h)
+ {
+ Log.w("LOL", String.format("resizing to %dx%d", w, h));
+ nativeResize(w, h);
+ }
+
+ public void onDrawFrame(GL10 gl)
+ {
+ nativeRender();
+ }
+
+ private static native void nativeInit();
+ private static native void nativeResize(int w, int h);
+ private static native void nativeRender();
+ private static native void nativeDone();
+}
+
diff --git a/build/android/icon.png b/build/android/icon.png
new file mode 100644
index 00000000..b04184c3
Binary files /dev/null and b/build/android/icon.png differ
diff --git a/build/android/strings.xml b/build/android/strings.xml
new file mode 100644
index 00000000..69e4c338
--- /dev/null
+++ b/build/android/strings.xml
@@ -0,0 +1,4 @@
+
+
+ @PROGRAM@
+
diff --git a/build/autotools/common.am b/build/autotools/common.am
index 96ee22f3..01e913ed 100644
--- a/build/autotools/common.am
+++ b/build/autotools/common.am
@@ -101,12 +101,43 @@ CLEANFILES += $(PROGRAMS:%$(EXEEXT)=%.exe) \
$(noinst_PROGRAMS:%$(EXEEXT)=%.exe)
+#
+# Android rules
+#
+
+all-local: all-local-android
+clean-local: clean-local-android
+if USE_ANDROID
+all-local-android: $(foreach p, $(PROGRAMS:%$(EXEEXT)=%), $($(p)_DATA))
+ $(foreach p, $(PROGRAMS:%$(EXEEXT)=%), \
+ rm -rf "android-$(p)"; \
+ $(MKDIR_P) "android-$(p)" $(sort $(foreach f, $($(p)_DATA), "android-$(p)/assets/$(dir $(f))")); \
+ $(foreach f, $($(p)_DATA), $(LN_S) "$(abs_srcdir)/$(f)" "android-$(p)/assets/$(f)";) \
+ $(SED) -e 's,@PROGRAM@,$(p),' "$(top_srcdir)/build/android/AndroidManifest.xml" > "android-$(p)/AndroidManifest.xml"; \
+ $(MKDIR_P) "android-$(p)/src/net/lolengine"; \
+ $(SED) -e 's,@PROGRAM@,$(p),' "$(top_srcdir)/build/android/LolActivity.java" > "android-$(p)/src/net/lolengine/LolActivity.java"; \
+ $(MKDIR_P) "android-$(p)/res/values"; \
+ $(SED) -e 's,@PROGRAM@,$(p),' "$(top_srcdir)/build/android/strings.xml" > "android-$(p)/res/values/strings.xml"; \
+ $(MKDIR_P) "android-$(p)/res/drawable"; \
+ cp "$(top_srcdir)/build/android/icon.png" "android-$(p)/res/drawable/"; \
+ $(MKDIR_P) "android-$(p)/libs/armeabi"; \
+ $(LN_S) "$(abs_builddir)/$(p).so" "android-$(p)/libs/armeabi/lib$(p).so"; \
+ $(LN_S) "$${ANDROID_NDK_ROOT}/sources/cxx-stl/stlport/libs/armeabi/libstlport_shared.so" "android-$(p)/libs/armeabi"; \
+ android update project -t android-8 -p "android-$(p)"; \
+ ant debug -f "android-$(p)/build.xml"; \
+ )
+else
+all-local-android:
+endif
+clean-local-android:
+ $(foreach p, $(PROGRAMS:%$(EXEEXT)=%), rm -rf "android-$(p)";)
+
+
#
# Additional rules
#
-EXTRA_DIST += $(foreach p, $(noinst_PROGRAMS), $($(p)_DATA))
-EXTRA_DIST += $(foreach p, $(bin_PROGRAMS), $($(p)_DATA))
+EXTRA_DIST += $(foreach p, $(PROGRAMS), $($(p)_DATA))
.PHONY: bench lolcheck generated
diff --git a/src/lua/llex.c b/src/lua/llex.c
index 6119f70f..e33bec62 100644
--- a/src/lua/llex.c
+++ b/src/lua/llex.c
@@ -11,6 +11,10 @@
#include
#include
+#if defined __ANDROID__ // LOL BEGIN
+# define getlocaledecpoint() '.'
+#endif // LOL END
+
#define llex_c
#define LUA_CORE
diff --git a/src/platform/android/androidapp.cpp b/src/platform/android/androidapp.cpp
index 866ceb41..8e9eb361 100644
--- a/src/platform/android/androidapp.cpp
+++ b/src/platform/android/androidapp.cpp
@@ -95,7 +95,7 @@ JNI_OnLoad(JavaVM* vm, void* reserved)
}
extern "C" void
-Java_org_zoy_LolEngine_LolActivity_nativeInit(JNIEnv* env, jobject thiz)
+Java_net_lolengine_LolActivity_nativeInit(JNIEnv* env, jobject thiz)
{
Log::Info("Java layer initialising activity 0x%08lx", (long)thiz);
env->NewGlobalRef(thiz); /* FIXME: never released! */
@@ -103,7 +103,7 @@ Java_org_zoy_LolEngine_LolActivity_nativeInit(JNIEnv* env, jobject thiz)
}
extern "C" void
-Java_org_zoy_LolEngine_LolRenderer_nativeInit(JNIEnv* env)
+Java_net_lolengine_LolRenderer_nativeInit(JNIEnv* env)
{
/* Initialise app thread and wait for it to be ready, ie. set
* the FPS value at least. */
@@ -120,7 +120,7 @@ Java_org_zoy_LolEngine_LolRenderer_nativeInit(JNIEnv* env)
}
extern "C" void
-Java_org_zoy_LolEngine_LolRenderer_nativeResize(JNIEnv* env, jobject thiz,
+Java_net_lolengine_LolRenderer_nativeResize(JNIEnv* env, jobject thiz,
jint w, jint h)
{
Log::Info("Java layer resizing to %i x %i", w, h);
@@ -128,32 +128,32 @@ Java_org_zoy_LolEngine_LolRenderer_nativeResize(JNIEnv* env, jobject thiz,
}
extern "C" void
-Java_org_zoy_LolEngine_LolRenderer_nativeDone(JNIEnv* env)
+Java_net_lolengine_LolRenderer_nativeDone(JNIEnv* env)
{
/* FIXME: clean up */
delete g_main_thread;
}
extern "C" void
-Java_org_zoy_LolEngine_LolView_nativePause(JNIEnv* env)
+Java_net_lolengine_LolView_nativePause(JNIEnv* env)
{
/* TODO: unimplemented */
}
extern "C" void
-Java_org_zoy_LolEngine_LolView_nativeDown(JNIEnv* env)
+Java_net_lolengine_LolView_nativeDown(JNIEnv* env)
{
Input::SetMouseButton(0);
}
extern "C" void
-Java_org_zoy_LolEngine_LolView_nativeUp(JNIEnv* env)
+Java_net_lolengine_LolView_nativeUp(JNIEnv* env)
{
Input::UnsetMouseButton(0);
}
extern "C" void
-Java_org_zoy_LolEngine_LolView_nativeMove(JNIEnv* env, jobject thiz,
+Java_net_lolengine_LolView_nativeMove(JNIEnv* env, jobject thiz,
jint x, jint y)
{
Input::SetMousePos(ivec2(x, y));
@@ -161,7 +161,7 @@ Java_org_zoy_LolEngine_LolView_nativeMove(JNIEnv* env, jobject thiz,
/* Call to render the next GL frame */
extern "C" void
-Java_org_zoy_LolEngine_LolRenderer_nativeRender(JNIEnv* env)
+Java_net_lolengine_LolRenderer_nativeRender(JNIEnv* env)
{
Ticker::TickDraw();
}