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(); }