diff --git a/.gitignore b/.gitignore index 8f5d0c5..09f66fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vs Debug Release -log.txt \ No newline at end of file +log.txt +build \ No newline at end of file diff --git a/proj.android-studio/app/.gitignore b/proj.android-studio/app/.gitignore deleted file mode 100755 index 796b96d..0000000 --- a/proj.android-studio/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/proj.android-studio/app/CMakeLists.txt b/proj.android-studio/app/CMakeLists.txt index 1659b89..f9ea7c9 100755 --- a/proj.android-studio/app/CMakeLists.txt +++ b/proj.android-studio/app/CMakeLists.txt @@ -20,7 +20,6 @@ include_directories(${LIBJPEG_PATH}/vc10) include_directories(${LUA_PATH}) include_directories(${EIGEN_PATH}) include_directories(${SOL2_PATH}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../) include_directories(${BOOST_PATH}) include_directories(${LIBPNG_PATH}) include_directories(${LIBJPEG_PATH}) diff --git a/proj.android-studio/app/build.gradle b/proj.android-studio/app/build.gradle index da141e3..68332a8 100755 --- a/proj.android-studio/app/build.gradle +++ b/proj.android-studio/app/build.gradle @@ -1,43 +1,75 @@ +/* + * Copyright 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' android { compileSdkVersion 28 - buildToolsVersion "28.0.0" + defaultConfig { applicationId "fishrungames.mountainwallpaper" minSdkVersion 19 targetSdkVersion 28 versionCode 2 versionName "1.1" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + externalNativeBuild { cmake { cppFlags "-std=c++11 -frtti -fexceptions -fsigned-char -Wno-c++11-narrowing" + abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86' } } } + buildTypes { release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), file('proguard-project.txt') } } + sourceSets { main { assets.srcDirs = ['../../assets/'] } } + + splits { + abi { + enable true + reset() + include 'arm64-v8a', 'armeabi-v7a', 'x86' + } + } + + externalNativeBuild { + cmake { + path 'CMakeLists.txt' + } + } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:28+' + implementation "com.android.support:appcompat-v7:$supportLibraryVersion" + implementation "com.android.support:preference-v7:$supportLibraryVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - compile project(':SalmonEngineAndroid') -} + implementation project(':SalmonEngineAndroid') +} \ No newline at end of file diff --git a/proj.android-studio/app/src/androidTest/java/fishrungames/salmonandroidtemplate/ExampleInstrumentedTest.java b/proj.android-studio/app/src/androidTest/java/fishrungames/salmonandroidtemplate/ExampleInstrumentedTest.java deleted file mode 100755 index c282df4..0000000 --- a/proj.android-studio/app/src/androidTest/java/fishrungames/salmonandroidtemplate/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package fishrungames.salmonandroidtemplate; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("fishrungames.salmonandroidtemplate", appContext.getPackageName()); - } -} diff --git a/proj.android-studio/app/src/main/AndroidManifest.xml b/proj.android-studio/app/src/main/AndroidManifest.xml index 42e214a..06c84e0 100755 --- a/proj.android-studio/app/src/main/AndroidManifest.xml +++ b/proj.android-studio/app/src/main/AndroidManifest.xml @@ -1,41 +1,90 @@ - + + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="fishrungames.mountainwallpaper"> - + + - + - - - - - - - + + - - - - - - + + - + + + + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/BaseConfigChooser.kt b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/BaseConfigChooser.kt new file mode 100755 index 0000000..25dac47 --- /dev/null +++ b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/BaseConfigChooser.kt @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fishrungames.mountainwallpaper + +import android.opengl.GLSurfaceView + +import javax.microedition.khronos.egl.EGL10 +import javax.microedition.khronos.egl.EGLConfig +import javax.microedition.khronos.egl.EGLDisplay + +/** + * Created by romannurik on 11/6/13. + */ +internal abstract class BaseConfigChooser(configSpec: IntArray, private val eglContextClientVersion: Int) : GLSurfaceView.EGLConfigChooser { + + protected var mConfigSpec: IntArray + + init { + mConfigSpec = filterConfigSpec(configSpec) + } + + override fun chooseConfig(egl: EGL10, display: EGLDisplay): EGLConfig { + val num_config = IntArray(1) + if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, + num_config)) { + throw IllegalArgumentException("eglChooseConfig failed") + } + + val numConfigs = num_config[0] + + if (numConfigs <= 0) { + throw IllegalArgumentException( + "No configs match configSpec") + } + + val configs = kotlin.arrayOfNulls(numConfigs) + if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, + num_config)) { + throw IllegalArgumentException("eglChooseConfig#2 failed") + } + return chooseConfig(egl, display, configs) + ?: throw IllegalArgumentException("No config chosen") + } + + internal abstract fun chooseConfig(egl: EGL10, display: EGLDisplay, + configs: Array): EGLConfig? + + private fun filterConfigSpec(configSpec: IntArray): IntArray { + if (eglContextClientVersion != 2) { + return configSpec + } + /* We know none of the subclasses define EGL_RENDERABLE_TYPE. + * And we know the configSpec is well formed. + */ + val len = configSpec.size + val newConfigSpec = IntArray(len + 2) + System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1) + newConfigSpec[len - 1] = EGL10.EGL_RENDERABLE_TYPE + newConfigSpec[len] = 4 /* EGL_OPENGL_ES2_BIT */ + newConfigSpec[len + 1] = EGL10.EGL_NONE + return newConfigSpec + } + + open class ComponentSizeChooser(// Subclasses can adjust these values: + protected var mRedSize: Int, protected var mGreenSize: Int, protected var mBlueSize: Int, protected var mAlphaSize: Int, protected var mDepthSize: Int, + protected var mStencilSize: Int, eglContextClientVersion: Int) : BaseConfigChooser(intArrayOf(EGL10.EGL_RED_SIZE, mRedSize, EGL10.EGL_GREEN_SIZE, mGreenSize, EGL10.EGL_BLUE_SIZE, mBlueSize, EGL10.EGL_ALPHA_SIZE, mAlphaSize, EGL10.EGL_DEPTH_SIZE, mDepthSize, EGL10.EGL_STENCIL_SIZE, mStencilSize, EGL10.EGL_NONE), eglContextClientVersion) { + + private val mValue: IntArray + + init { + mValue = IntArray(1) + } + + public override fun chooseConfig(egl: EGL10, display: EGLDisplay, configs: Array): EGLConfig? { + var closestConfig: EGLConfig? = null + var closestDistance = 1000 + for (config in configs) { + val d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE) + val s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE) + if (d >= mDepthSize && s >= mStencilSize) { + val r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE) + val g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE) + val b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE) + val a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE) + val distance = (Math.abs(r - mRedSize) + Math.abs(g - mGreenSize) + Math.abs(b - mBlueSize) + + Math.abs(a - mAlphaSize)) + if (distance < closestDistance) { + closestDistance = distance + closestConfig = config + } + } + } + return closestConfig + } + + private fun findConfigAttrib(egl: EGL10, display: EGLDisplay, config: EGLConfig?, attribute: Int): Int { + + return if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { + mValue[0] + } else 0 + } + } + + /** + * This class will choose a supported surface as close to RGB565 as possible, with or without a depth buffer. + */ + class SimpleEGLConfigChooser(withDepthBuffer: Boolean, eglContextClientVersion: Int) : ComponentSizeChooser(4, 4, 4, 0, if (withDepthBuffer) 16 else 0, 0, eglContextClientVersion) { + init { + // Adjust target values. This way we'll accept a 4444 or + // 555 buffer if there's no 565 buffer available. + mRedSize = 5 + mGreenSize = 6 + mBlueSize = 5 + } + } +} \ No newline at end of file diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/GLWallpaperService.java b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/GLWallpaperService.java deleted file mode 100755 index 45a91ad..0000000 --- a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/GLWallpaperService.java +++ /dev/null @@ -1,960 +0,0 @@ -package fishrungames.mountainwallpaper; - - -import fishrungames.mountainwallpaper.BaseConfigChooser.ComponentSizeChooser; -import fishrungames.mountainwallpaper.BaseConfigChooser.SimpleEGLConfigChooser; - -import java.util.ArrayList; -import java.util.Calendar; - -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.egl.EGLSurface; - - -import android.service.wallpaper.WallpaperService; -import android.util.Log; -import android.view.SurfaceHolder; - -import fishrungames.salmonengineandroid.EngineWrapper; - - -public class GLWallpaperService extends WallpaperService { - private static final String TAG = "GLWallpaperService"; - - @Override - public Engine onCreateEngine() { - return new GLEngine(); - } - - public class GLEngine extends Engine { - public final static int RENDERMODE_WHEN_DIRTY = 0; - public final static int RENDERMODE_CONTINUOUSLY = 1; - - private GLThread mGLThread; - private EGLConfigChooser mEGLConfigChooser; - private EGLContextFactory mEGLContextFactory; - private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; - - private int mDebugFlags; - - public GLEngine() { - super(); - } - - @Override - public void onVisibilityChanged(boolean visible) { - if (visible) { - onResume(); - } else { - onPause(); - } - super.onVisibilityChanged(visible); - } - - @Override - public void onCreate(SurfaceHolder surfaceHolder) { - super.onCreate(surfaceHolder); - // Log.d(TAG, "GLEngine.onCreate()"); - } - - @Override - public void onDestroy() { - super.onDestroy(); - // Log.d(TAG, "GLEngine.onDestroy()"); - mGLThread.requestExitAndWait(); - } - - @Override - public void onSurfaceChanged(SurfaceHolder holder, int format, - int width, int height) { - // Log.d(TAG, "onSurfaceChanged()"); - - - - mGLThread.onWindowResize(width, height); - - super.onSurfaceChanged(holder, format, width, height); - } - - @Override - public void onSurfaceCreated(SurfaceHolder holder) { - Log.d(TAG, "onSurfaceCreated()"); - mGLThread.surfaceCreated(holder); - super.onSurfaceCreated(holder); - } - - @Override - public void onSurfaceDestroyed(SurfaceHolder holder) { - Log.d(TAG, "onSurfaceDestroyed()"); - mGLThread.surfaceDestroyed(); - super.onSurfaceDestroyed(holder); - } - - - public void setDebugFlags(int debugFlags) { - mDebugFlags = debugFlags; - } - - public int getDebugFlags() { - return mDebugFlags; - } - - public void setRenderer() { - checkRenderThreadState(); - if (mEGLConfigChooser == null) { - mEGLConfigChooser = new SimpleEGLConfigChooser(true); - } - if (mEGLContextFactory == null) { - //mEGLContextFactory = new DefaultContextFactory(); - mEGLContextFactory = new ES20ContextFactory(); - } - if (mEGLWindowSurfaceFactory == null) { - mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); - } - mGLThread = new GLThread(mEGLConfigChooser, - mEGLContextFactory, mEGLWindowSurfaceFactory); - mGLThread.start(); - } - - public void setEGLContextFactory(EGLContextFactory factory) { - checkRenderThreadState(); - mEGLContextFactory = factory; - } - - public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { - checkRenderThreadState(); - mEGLWindowSurfaceFactory = factory; - } - - public void setEGLConfigChooser(EGLConfigChooser configChooser) { - checkRenderThreadState(); - mEGLConfigChooser = configChooser; - } - - public void setEGLConfigChooser(boolean needDepth) { - setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); - } - - public void setEGLConfigChooser(int redSize, int greenSize, - int blueSize, int alphaSize, int depthSize, int stencilSize) { - setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, - blueSize, alphaSize, depthSize, stencilSize)); - } - - public void setRenderMode(int renderMode) { - mGLThread.setRenderMode(renderMode); - } - - public int getRenderMode() { - return mGLThread.getRenderMode(); - } - - public void requestRender() { - mGLThread.requestRender(); - } - - public void onPause() { - mGLThread.onPause(); - } - - public void onResume() { - mGLThread.onResume(); - } - - public void queueEvent(Runnable r) { - mGLThread.queueEvent(r); - } - - private void checkRenderThreadState() { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - } - } -} - - -// ---------------------------------------------------------------------- - -/** - * An interface for customizing the eglCreateContext and eglDestroyContext - * calls. - * - * - * This interface must be implemented by clients wishing to call - * {@link GLWallpaperService.GLEngine#setEGLContextFactory(EGLContextFactory)} - */ -interface EGLContextFactory { - EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); - - void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); -} - -class DefaultContextFactory implements EGLContextFactory { - - public EGLContext createContext(EGL10 egl, EGLDisplay display, - EGLConfig config) { - return egl - .eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null); - } - - public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) { - egl.eglDestroyContext(display, context); - } -} - - -class ES20ContextFactory implements EGLContextFactory { - - private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - - public EGLContext createContext(EGL10 egl, EGLDisplay display, - EGLConfig config) { - - - int[] attrib_list = - { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; - - return egl - .eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, attrib_list); - } - - public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) { - egl.eglDestroyContext(display, context); - } -} - -/** - * An interface for customizing the eglCreateWindowSurface and eglDestroySurface - * calls. - * - * - * This interface must be implemented by clients wishing to call - * {@link GLWallpaperService.GLEngine#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} - */ -interface EGLWindowSurfaceFactory { - EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, - EGLConfig config, Object nativeWindow); - - void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); -} - -class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { - - public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, - EGLConfig config, Object nativeWindow) { - // this is a bit of a hack to work around Droid init problems - if you - // don't have this, it'll get hung up on orientation changes - EGLSurface eglSurface = null; - while (eglSurface == null) { - try { - eglSurface = egl.eglCreateWindowSurface(display, config, - nativeWindow, null); - } catch (Throwable t) { - } finally { - if (eglSurface == null) { - try { - Thread.sleep(10); - } catch (InterruptedException t) { - } - } - } - } - return eglSurface; - } - - public void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface) { - egl.eglDestroySurface(display, surface); - } -} - - -class EglHelper { - - private EGL10 mEgl; - private EGLDisplay mEglDisplay; - private EGLSurface mEglSurface; - private EGLContext mEglContext; - EGLConfig mEglConfig; - - private EGLConfigChooser mEGLConfigChooser; - private EGLContextFactory mEGLContextFactory; - private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; - - - public EglHelper(EGLConfigChooser chooser, - EGLContextFactory contextFactory, - EGLWindowSurfaceFactory surfaceFactory) { - this.mEGLConfigChooser = chooser; - this.mEGLContextFactory = contextFactory; - this.mEGLWindowSurfaceFactory = surfaceFactory; - - } - - /** - * Initialize EGL for a given configuration spec. - * - * configSpec - */ - public void start() { - String instanceId = ""; - Log.d("EglHelper" + instanceId, "start()"); - if (mEgl == null) { - Log.d("EglHelper" + instanceId, "getting new EGL"); - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - } else { - Log.d("EglHelper" + instanceId, "reusing EGL"); - } - - if (mEglDisplay == null) { - Log.d("EglHelper" + instanceId, "getting new display"); - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - } else { - Log.d("EglHelper" + instanceId, "reusing display"); - } - - if (mEglConfig == null) { - Log.d("EglHelper" + instanceId, "getting new config"); - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - mEgl.eglInitialize(mEglDisplay, version); - mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); - } else { - Log.d("EglHelper" + instanceId, "reusing config"); - } - - if (mEglContext == null) { - Log.d("EglHelper" + instanceId, "creating new context"); - /* - * Create an OpenGL ES context. This must be done only once, an - * OpenGL context is a somewhat heavy object. - */ - mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, - mEglConfig); - if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { - throw new RuntimeException("createContext failed"); - } - } else { - Log.d("EglHelper" + instanceId, "reusing context"); - } - - mEglSurface = null; - } - - /* - * React to the creation of a new surface by creating and returning an - * OpenGL interface that renders to that surface. - */ - - - public void createSurface(SurfaceHolder holder) { - - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - - - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, - mEglSurface); - } - - - mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, - mEglDisplay, mEglConfig, holder); - - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { - throw new RuntimeException("createWindowSurface failed"); - } - - - if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext)) { - //throw new RuntimeException("eglMakeCurrent failed."); - } - - - } - - /** - * Display the current render surface. - * - * @return false if the context has been lost. - */ - public boolean swap() { - try { - mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); - } catch (Exception e) { - return false; - } - - return true; - - - /* - * Always check for EGL_CONTEXT_LOST, which means the context and all - * associated data were lost (For instance because the device went to - * sleep). We need to sleep until we get a new surface. - */ - - } - - public void destroySurface() { - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, - mEglSurface); - mEglSurface = null; - } - } - - public void finish() { - if (mEglContext != null) { - mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } -} - -class GLThread extends Thread { - private final static boolean LOG_THREADS = false; - public final static int DEBUG_CHECK_GL_ERROR = 1; - public final static int DEBUG_LOG_GL_CALLS = 2; - - private final GLThreadManager sGLThreadManager = new GLThreadManager(); - private GLThread mEglOwner; - - private EGLConfigChooser mEGLConfigChooser; - private EGLContextFactory mEGLContextFactory; - private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; - - - public SurfaceHolder mHolder; - private boolean mSizeChanged = true; - - // Once the thread is started, all accesses to the following member - // variables are protected by the sGLThreadManager monitor - public boolean mDone; - private boolean mPaused; - private boolean mHasSurface; - private boolean mWaitingForSurface; - private boolean mHaveEgl; - private int mWidth; - private int mHeight; - private int mRenderMode; - private boolean mRequestRender; - private boolean mEventsWaiting; - // End of member variables protected by the sGLThreadManager monitor. - - //private GLWallpaperService.Renderer mRenderer; - - private ArrayList mEventQueue = new ArrayList(); - private EglHelper mEglHelper; - - - static long lastTimeStamp; - static boolean gameIsInited = false; - - GLThread(EGLConfigChooser chooser, - EGLContextFactory contextFactory, - EGLWindowSurfaceFactory surfaceFactory) { - super(); - mDone = false; - mWidth = 0; - mHeight = 0; - mRequestRender = true; - mRenderMode = GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY; - - this.mEGLConfigChooser = chooser; - this.mEGLContextFactory = contextFactory; - this.mEGLWindowSurfaceFactory = surfaceFactory; - - Calendar c = Calendar.getInstance(); - lastTimeStamp = c.getTimeInMillis(); - gameIsInited = true; - } - - @Override - public void run() { - setName("GLThread " + getId()); - if (LOG_THREADS) { - Log.i("GLThread", "starting tid=" + getId()); - } - - try { - guardedRun(); - } catch (InterruptedException e) { - // fall thru and exit normally - } finally { - sGLThreadManager.threadExiting(this); - } - } - - /* - * This private method should only be called inside a - * synchronized(sGLThreadManager) block. - */ - private void stopEglLocked() { - if (mHaveEgl) { - mHaveEgl = false; - mEglHelper.destroySurface(); - sGLThreadManager.releaseEglSurface(this); - } - } - - private void guardedRun() throws InterruptedException { - mEglHelper = new EglHelper(mEGLConfigChooser, mEGLContextFactory, - mEGLWindowSurfaceFactory/*, mGLWrapper*/); - try { - - boolean tellRendererSurfaceCreated = true; - boolean tellRendererSurfaceChanged = true; - - /* - * This is our main activity thread's loop, we go until asked to - * quit. - */ - while (!isDone()) { - /* - * Update the asynchronous state (window size) - */ - int w = 0; - int h = 0; - boolean changed = false; - boolean needStart = false; - boolean eventsWaiting = false; - - synchronized (sGLThreadManager) { - while (true) { - // Manage acquiring and releasing the SurfaceView - // surface and the EGL surface. - if (mPaused) { - stopEglLocked(); - } - if (!mHasSurface) { - if (!mWaitingForSurface) { - stopEglLocked(); - mWaitingForSurface = true; - sGLThreadManager.notifyAll(); - } - } else { - if (!mHaveEgl) { - if (sGLThreadManager.tryAcquireEglSurface(this)) { - mHaveEgl = true; - mEglHelper.start(); - mRequestRender = true; - needStart = true; - } - } - } - - // Check if we need to wait. If not, update any state - // that needs to be updated, copy any state that - // needs to be copied, and use "break" to exit the - // wait loop. - - if (mDone) { - return; - } - - if (mEventsWaiting) { - eventsWaiting = true; - mEventsWaiting = false; - break; - } - - if ((!mPaused) - && mHasSurface - && mHaveEgl - && (mWidth > 0) - && (mHeight > 0) - && (mRequestRender || (mRenderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) { - changed = mSizeChanged; - w = mWidth; - h = mHeight; - mSizeChanged = false; - mRequestRender = false; - if (mHasSurface && mWaitingForSurface) { - changed = true; - mWaitingForSurface = false; - sGLThreadManager.notifyAll(); - } - break; - } - - - - // By design, this is the only place where we wait(). - - if (LOG_THREADS) { - Log.i("GLThread", "waiting tid=" + getId()); - } - sGLThreadManager.wait(); - } - } // end of synchronized(sGLThreadManager) - - /* - * Handle queued events - */ - if (eventsWaiting) { - Runnable r; - while ((r = getEvent()) != null) { - r.run(); - if (isDone()) { - return; - } - } - // Go back and see if we need to wait to render. - continue; - } - - if (needStart) { - tellRendererSurfaceCreated = true; - changed = true; - } - if (changed) { - mEglHelper.createSurface(mHolder); - tellRendererSurfaceChanged = true; - } - if (tellRendererSurfaceCreated) { - - tellRendererSurfaceCreated = false; - } - - if (tellRendererSurfaceChanged) { - - - //Xperimental -- VLAD KHOREV - JniWrapper.Init(w, h); - - tellRendererSurfaceChanged = false; - } - - - if ((w > 0) && (h > 0)) { - /* draw a frame here */ - - if (gameIsInited) - { - Calendar c = Calendar.getInstance(); - - long currentTimeStamp = c.getTimeInMillis(); - - EngineWrapper.Update(currentTimeStamp - lastTimeStamp); - - lastTimeStamp = currentTimeStamp; - - } - - /* - * Once we're done with GL, we need to call swapBuffers() to - * instruct the system to display the rendered frame - */ - mEglHelper.swap(); - } - } - } finally { - /* - * clean-up everything... - */ - synchronized (sGLThreadManager) { - stopEglLocked(); - mEglHelper.finish(); - } - } - } - - private boolean isDone() { - synchronized (sGLThreadManager) { - return mDone; - } - } - - public void setRenderMode(int renderMode) { - if (!((GLWallpaperService.GLEngine.RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) { - throw new IllegalArgumentException("renderMode"); - } - synchronized (sGLThreadManager) { - mRenderMode = renderMode; - if (renderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY) { - sGLThreadManager.notifyAll(); - } - } - } - - public int getRenderMode() { - synchronized (sGLThreadManager) { - return mRenderMode; - } - } - - public void requestRender() { - synchronized (sGLThreadManager) { - mRequestRender = true; - sGLThreadManager.notifyAll(); - } - } - - public void surfaceCreated(SurfaceHolder holder) { - mHolder = holder; - synchronized (sGLThreadManager) { - if (LOG_THREADS) { - Log.i("GLThread", "surfaceCreated tid=" + getId()); - } - mHasSurface = true; - sGLThreadManager.notifyAll(); - } - } - - public void surfaceDestroyed() { - synchronized (sGLThreadManager) { - if (LOG_THREADS) { - Log.i("GLThread", "surfaceDestroyed tid=" + getId()); - } - mHasSurface = false; - sGLThreadManager.notifyAll(); - while (!mWaitingForSurface && isAlive() && !mDone) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onPause() { - synchronized (sGLThreadManager) { - mPaused = true; - sGLThreadManager.notifyAll(); - } - } - - public void onResume() { - synchronized (sGLThreadManager) { - mPaused = false; - mRequestRender = true; - sGLThreadManager.notifyAll(); - } - } - - public void onWindowResize(int w, int h) { - synchronized (sGLThreadManager) { - mWidth = w; - mHeight = h; - mSizeChanged = true; - sGLThreadManager.notifyAll(); - } - } - - public void requestExitAndWait() { - // don't call this from GLThread thread or it is a guaranteed - // deadlock! - synchronized (sGLThreadManager) { - mDone = true; - sGLThreadManager.notifyAll(); - } - try { - join(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - - /** - * Queue an "event" to be run on the GL rendering thread. - * - * @param r - * the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - synchronized (this) { - mEventQueue.add(r); - synchronized (sGLThreadManager) { - mEventsWaiting = true; - sGLThreadManager.notifyAll(); - } - } - } - - private Runnable getEvent() { - synchronized (this) { - if (mEventQueue.size() > 0) { - return (Runnable) mEventQueue.remove(0); - } - - } - return null; - } - - private class GLThreadManager { - - public synchronized void threadExiting(GLThread thread) { - if (LOG_THREADS) { - Log.i("GLThread", "exiting tid=" + thread.getId()); - } - thread.mDone = true; - if (mEglOwner == thread) { - mEglOwner = null; - } - notifyAll(); - } - - /* - * Tries once to acquire the right to use an EGL surface. Does not - * block. - * - * @return true if the right to use an EGL surface was acquired. - */ - public synchronized boolean tryAcquireEglSurface(GLThread thread) { - if (mEglOwner == thread || mEglOwner == null) { - mEglOwner = thread; - notifyAll(); - return true; - } - return false; - } - - public synchronized void releaseEglSurface(GLThread thread) { - if (mEglOwner == thread) { - mEglOwner = null; - } - notifyAll(); - } - } -} - -interface EGLConfigChooser { - EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); -} - -abstract class BaseConfigChooser implements EGLConfigChooser { - public BaseConfigChooser(int[] configSpec) { - mConfigSpec = configSpec; - } - - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - int[] num_config = new int[1]; - egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); - - int numConfigs = num_config[0]; - - if (numConfigs <= 0) { - throw new IllegalArgumentException("No configs match configSpec"); - } - - EGLConfig[] configs = new EGLConfig[numConfigs]; - egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, - num_config); - EGLConfig config = chooseConfig(egl, display, configs); - if (config == null) { - throw new IllegalArgumentException("No config chosen"); - } - return config; - } - - abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs); - - protected int[] mConfigSpec; - - public static class ComponentSizeChooser extends BaseConfigChooser { - public ComponentSizeChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - super(new int[] { EGL10.EGL_RED_SIZE, redSize, - EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE, - blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize, - EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE, - stencilSize, EGL10.EGL_NONE }); - mValue = new int[1]; - mRedSize = redSize; - mGreenSize = greenSize; - mBlueSize = blueSize; - mAlphaSize = alphaSize; - mDepthSize = depthSize; - mStencilSize = stencilSize; - } - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs) { - EGLConfig closestConfig = null; - int closestDistance = 1000; - 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); - if (d >= mDepthSize && s >= mStencilSize) { - 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); - int distance = Math.abs(r - mRedSize) - + Math.abs(g - mGreenSize) - + Math.abs(b - mBlueSize) - + Math.abs(a - mAlphaSize); - if (distance < closestDistance) { - closestDistance = distance; - closestConfig = config; - } - } - } - return closestConfig; - } - - 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 int[] mValue; - // Subclasses can adjust these values: - protected int mRedSize; - protected int mGreenSize; - protected int mBlueSize; - protected int mAlphaSize; - protected int mDepthSize; - protected int mStencilSize; - } - - /** - * This class will choose a supported surface as close to RGB565 as - * possible, with or without a depth buffer. - * - */ - public static class SimpleEGLConfigChooser extends ComponentSizeChooser { - public SimpleEGLConfigChooser(boolean withDepthBuffer) { - super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0); - // Adjust target values. This way we'll accept a 4444 or - // 555 buffer if there's no 565 buffer available. - mRedSize = 5; - mGreenSize = 6; - mBlueSize = 5; - } - } -} diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/GLWallpaperService.kt b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/GLWallpaperService.kt new file mode 100755 index 0000000..b5f6e09 --- /dev/null +++ b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/GLWallpaperService.kt @@ -0,0 +1,764 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fishrungames.mountainwallpaper + +import java.io.Writer +import java.util.ArrayList + +import javax.microedition.khronos.egl.EGL10 +import javax.microedition.khronos.egl.EGL11 +import javax.microedition.khronos.egl.EGLConfig +import javax.microedition.khronos.egl.EGLContext +import javax.microedition.khronos.egl.EGLDisplay +import javax.microedition.khronos.egl.EGLSurface +import javax.microedition.khronos.opengles.GL +import javax.microedition.khronos.opengles.GL10 + +import android.opengl.GLSurfaceView +import android.service.wallpaper.WallpaperService +import android.util.Log +import android.view.SurfaceHolder + +// Original code provided by Robert Green +// http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers + +open class GLWallpaperService : WallpaperService() { + + companion object { + private val TAG = "GLWallpaperService" + val RENDERMODE_WHEN_DIRTY = 0; + val RENDERMODE_CONTINUOUSLY = 1; + } + + override fun onCreateEngine(): WallpaperService.Engine { + return GLEngine() + } + + open inner class GLEngine : WallpaperService.Engine() { + + private var mGLThread: GLThread? = null + private var mEGLConfigChooser: GLSurfaceView.EGLConfigChooser? = null + private var mEGLContextFactory: GLSurfaceView.EGLContextFactory? = null + private var mEGLWindowSurfaceFactory: GLSurfaceView.EGLWindowSurfaceFactory? = null + private var mEGLContextClientVersion: Int = 0 + var renderMode: Int + get() = mGLThread!!.renderMode + set(renderMode) { + mGLThread!!.renderMode = renderMode + } + + override fun onVisibilityChanged(visible: Boolean) { + if (visible) { + onResume() + } else { + onPause() + } + super.onVisibilityChanged(visible) + } + + override fun onDestroy() { + super.onDestroy() + // Log.d(TAG, "GLEngine.onDestroy()"); + mGLThread!!.requestExitAndWait() + } + + override fun onSurfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + // Log.d(TAG, "onSurfaceChanged()"); + mGLThread!!.onWindowResize(width, height) + super.onSurfaceChanged(holder, format, width, height) + } + + override fun onSurfaceCreated(holder: SurfaceHolder) { + Log.d(TAG, "onSurfaceCreated()") + mGLThread!!.surfaceCreated(holder) + super.onSurfaceCreated(holder) + } + + override fun onSurfaceDestroyed(holder: SurfaceHolder) { + Log.d(TAG, "onSurfaceDestroyed()") + mGLThread!!.surfaceDestroyed() + super.onSurfaceDestroyed(holder) + } + + fun setRenderer(renderer: GLSurfaceView.Renderer) { + checkRenderThreadState() + + var mEGLConfigChooser = this.mEGLConfigChooser; + var mEGLContextFactory = this.mEGLContextFactory; + var mEGLWindowSurfaceFactory = this.mEGLWindowSurfaceFactory; + + if (mEGLConfigChooser == null) { + mEGLConfigChooser = BaseConfigChooser.SimpleEGLConfigChooser(true, mEGLContextClientVersion) + } + if (mEGLContextFactory == null) { + mEGLContextFactory = DefaultContextFactory(mEGLContextClientVersion) + } + if (mEGLWindowSurfaceFactory == null) { + mEGLWindowSurfaceFactory = DefaultWindowSurfaceFactory() + } + mGLThread = GLThread(renderer, mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory) + mGLThread!!.start() + } + + fun setEGLContextFactory(factory: GLSurfaceView.EGLContextFactory) { + checkRenderThreadState() + mEGLContextFactory = factory + } + + fun setEGLWindowSurfaceFactory(factory: GLSurfaceView.EGLWindowSurfaceFactory) { + checkRenderThreadState() + mEGLWindowSurfaceFactory = factory + } + + fun setEGLConfigChooser(configChooser: GLSurfaceView.EGLConfigChooser) { + checkRenderThreadState() + mEGLConfigChooser = configChooser + } + + fun setEGLConfigChooser(needDepth: Boolean) { + setEGLConfigChooser(BaseConfigChooser.SimpleEGLConfigChooser(needDepth, mEGLContextClientVersion)) + } + + fun setEGLConfigChooser(redSize: Int, greenSize: Int, blueSize: Int, alphaSize: Int, depthSize: Int, + stencilSize: Int) { + setEGLConfigChooser( + BaseConfigChooser.ComponentSizeChooser(redSize, greenSize, blueSize, alphaSize, + depthSize, + stencilSize, mEGLContextClientVersion)) + } + + fun setEGLContextClientVersion(version: Int) { + checkRenderThreadState() + mEGLContextClientVersion = version + } + + open fun requestRender() { + mGLThread!!.requestRender() + } + + fun onPause() { + mGLThread!!.onPause() + } + + fun onResume() { + mGLThread!!.onResume() + } + + fun queueEvent(r: Runnable) { + mGLThread!!.queueEvent(r) + } + + private fun checkRenderThreadState() { + if (mGLThread != null) { + throw IllegalStateException("setRenderer has already been called for this instance.") + } + } + } +} + +internal class LogWriter : Writer() { + private val mBuilder = StringBuilder() + + override fun close() { + flushBuilder() + } + + override fun flush() { + flushBuilder() + } + + override fun write(buf: CharArray, offset: Int, count: Int) { + for (i in 0 until count) { + val c = buf[offset + i] + if (c == '\n') { + flushBuilder() + } else { + mBuilder.append(c) + } + } + } + + private fun flushBuilder() { + if (mBuilder.length > 0) { + Log.v("GLSurfaceView", mBuilder.toString()) + mBuilder.delete(0, mBuilder.length) + } + } +} + +// ---------------------------------------------------------------------- + +internal class DefaultContextFactory(val eglContextClientVersion : Int) : GLSurfaceView.EGLContextFactory { + + private val EGL_CONTEXT_CLIENT_VERSION = 0x3098 + + override fun createContext(egl: EGL10, display: EGLDisplay, config: EGLConfig): EGLContext { + val attrib_list = intArrayOf(EGL_CONTEXT_CLIENT_VERSION, eglContextClientVersion, EGL10.EGL_NONE) + return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, + if (eglContextClientVersion != 0) attrib_list else null) + } + + override fun destroyContext(egl: EGL10, display: EGLDisplay, context: EGLContext) { + egl.eglDestroyContext(display, context) + } +} + +internal class DefaultWindowSurfaceFactory : GLSurfaceView.EGLWindowSurfaceFactory { + + override fun createWindowSurface(egl: EGL10, display: EGLDisplay, config: EGLConfig, nativeWindow: Any): EGLSurface { + // this is a bit of a hack to work around Droid init problems - if you don't have this, it'll get hung up on orientation changes + var eglSurface: EGLSurface? = null + while (eglSurface == null) { + try { + eglSurface = egl.eglCreateWindowSurface(display, + config, nativeWindow, null) + } catch (t: Throwable) { + } finally { + if (eglSurface == null) { + try { + Thread.sleep(10) + } catch (t: InterruptedException) { + } + + } + } + } + return eglSurface + } + + override fun destroySurface(egl: EGL10, display: EGLDisplay, surface: EGLSurface) { + egl.eglDestroySurface(display, surface) + } +} + +internal class EglHelper(private val mEGLConfigChooser: GLSurfaceView.EGLConfigChooser, private val mEGLContextFactory: GLSurfaceView.EGLContextFactory, + private val mEGLWindowSurfaceFactory: GLSurfaceView.EGLWindowSurfaceFactory) { + + private var mEgl: EGL10? = null + private var mEglDisplay: EGLDisplay? = null + private var mEglSurface: EGLSurface? = null + private var mEglContext: EGLContext? = null + var mEglConfig: EGLConfig? = null + + /** + * Initialize EGL for a given configuration spec. + * + * @param configSpec + */ + fun start() { + // Log.d("EglHelper" + instanceId, "start()"); + if (mEgl == null) { + // Log.d("EglHelper" + instanceId, "getting new EGL"); + /* + * Get an EGL instance + */ + mEgl = EGLContext.getEGL() as EGL10 + } else { + // Log.d("EglHelper" + instanceId, "reusing EGL"); + } + + if (mEglDisplay == null) { + // Log.d("EglHelper" + instanceId, "getting new display"); + /* + * Get to the default display. + */ + mEglDisplay = mEgl!!.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY) + } else { + // Log.d("EglHelper" + instanceId, "reusing display"); + } + + if (mEglConfig == null) { + // Log.d("EglHelper" + instanceId, "getting new config"); + /* + * We can now initialize EGL for that display + */ + val version = IntArray(2) + mEgl!!.eglInitialize(mEglDisplay, version) + mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay) + } else { + // Log.d("EglHelper" + instanceId, "reusing config"); + } + + if (mEglContext == null) { + // Log.d("EglHelper" + instanceId, "creating new context"); + /* + * Create an OpenGL ES context. This must be done only once, an OpenGL context is a somewhat heavy object. + */ + mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig) + if (mEglContext == null || mEglContext === EGL10.EGL_NO_CONTEXT) { + throw RuntimeException("createContext failed") + } + } else { + // Log.d("EglHelper" + instanceId, "reusing context"); + } + + mEglSurface = null + } + + /* + * React to the creation of a new surface by creating and returning an OpenGL interface that renders to that + * surface. + */ + fun createSurface(holder: SurfaceHolder): GL { + /* + * The window size has changed, so we need to create a new surface. + */ + if (mEglSurface != null && mEglSurface !== EGL10.EGL_NO_SURFACE) { + + /* + * Unbind and destroy the old EGL surface, if there is one. + */ + mEgl!!.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT) + mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface) + } + + /* + * Create an EGL surface we can render into. + */ + mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, holder) + + if (mEglSurface == null || mEglSurface === EGL10.EGL_NO_SURFACE) { + throw RuntimeException("createWindowSurface failed") + } + + /* + * Before we can issue GL commands, we need to make sure the context is current and bound to a surface. + */ + if (!mEgl!!.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + throw RuntimeException("eglMakeCurrent failed.") + } + + var gl = mEglContext!!.gl + + /* + * if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS))!= 0) { int configFlags = 0; Writer log = + * null; if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; } + * if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { log = new LogWriter(); } gl = GLDebugHelper.wrap(gl, + * configFlags, log); } + */ + + return gl + } + + /** + * Display the current render surface. + * + * @return false if the context has been lost. + */ + fun swap(): Boolean { + mEgl!!.eglSwapBuffers(mEglDisplay, mEglSurface) + + /* + * Always check for EGL_CONTEXT_LOST, which means the context and all associated data were lost (For instance + * because the device went to sleep). We need to sleep until we get a new surface. + */ + return mEgl!!.eglGetError() != EGL11.EGL_CONTEXT_LOST + } + + fun destroySurface() { + if (mEglSurface != null && mEglSurface !== EGL10.EGL_NO_SURFACE) { + mEgl!!.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT) + mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface) + mEglSurface = null + } + } + + fun finish() { + if (mEglContext != null) { + mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext) + mEglContext = null + } + if (mEglDisplay != null) { + mEgl!!.eglTerminate(mEglDisplay) + mEglDisplay = null + } + } +} + +internal class GLThread +( + // End of member variables protected by the sGLThreadManager monitor. + + private val mRenderer: GLSurfaceView.Renderer, private val mEGLConfigChooser: GLSurfaceView.EGLConfigChooser, private val mEGLContextFactory: GLSurfaceView.EGLContextFactory, + private val mEGLWindowSurfaceFactory: GLSurfaceView.EGLWindowSurfaceFactory) : Thread() { + + private val sGLThreadManager = GLThreadManager() + private var mEglOwner: GLThread? = null + + lateinit var mHolder: SurfaceHolder + private var mSizeChanged = true + + // Once the thread is started, all accesses to the following member + // variables are protected by the sGLThreadManager monitor + var mDone: Boolean = false + private var mPaused: Boolean = false + private var mHasSurface: Boolean = false + private var mWaitingForSurface: Boolean = false + private var mHaveEgl: Boolean = false + private var mWidth: Int = 0 + private var mHeight: Int = 0 + private var mRenderMode: Int = 0 + private var mRequestRender: Boolean = false + private var mEventsWaiting: Boolean = false + private val mEventQueue = ArrayList() + private var mEglHelper: EglHelper? = null + + private val isDone: Boolean + get() = synchronized(sGLThreadManager.lockObject) { + return mDone + } + + var renderMode: Int + get() = synchronized(sGLThreadManager.lockObject) { + return mRenderMode + } + set(renderMode) { + if (!(GLWallpaperService.RENDERMODE_WHEN_DIRTY <= renderMode && renderMode <= GLWallpaperService.RENDERMODE_CONTINUOUSLY)) { + throw IllegalArgumentException("renderMode") + } + synchronized(sGLThreadManager.lockObject) { + mRenderMode = renderMode + if (renderMode == GLWallpaperService.RENDERMODE_CONTINUOUSLY) { + sGLThreadManager.lockObject.notifyAll() + } + } + } + + private val event: Runnable? + get() { + synchronized(this) { + if (mEventQueue.size > 0) { + return mEventQueue.removeAt(0) + } + + } + return null + } + + init { + mDone = false + mWidth = 0 + mHeight = 0 + mRequestRender = true + mRenderMode = GLWallpaperService.RENDERMODE_CONTINUOUSLY + } + + override fun run() { + name = "GLThread $id" + if (LOG_THREADS) { + Log.i("GLThread", "starting tid=$id") + } + + try { + guardedRun() + } catch (e: InterruptedException) { + // fall thru and exit normally + } finally { + sGLThreadManager.threadExiting(this) + } + } + + /* + * This private method should only be called inside a synchronized(sGLThreadManager.lockObject) block. + */ + private fun stopEglLocked() { + if (mHaveEgl) { + mHaveEgl = false + mEglHelper!!.destroySurface() + sGLThreadManager.releaseEglSurface(this) + } + } + + @Throws(InterruptedException::class) + private fun guardedRun() { + mEglHelper = EglHelper(mEGLConfigChooser, mEGLContextFactory, mEGLWindowSurfaceFactory) + try { + var gl: GL10? = null + var tellRendererSurfaceCreated = true + var tellRendererSurfaceChanged = true + + /* + * This is our main activity thread's loop, we go until asked to quit. + */ + while (!isDone) { + /* + * Update the asynchronous state (window size) + */ + var w = 0 + var h = 0 + var changed = false + var needStart = false + var eventsWaiting = false + + synchronized(sGLThreadManager.lockObject) { + while (true) { + // Manage acquiring and releasing the SurfaceView + // surface and the EGL surface. + if (mPaused) { + stopEglLocked() + } + if (!mHasSurface) { + if (!mWaitingForSurface) { + stopEglLocked() + mWaitingForSurface = true + sGLThreadManager.lockObject.notifyAll() + } + } else { + if (!mHaveEgl) { + if (sGLThreadManager.tryAcquireEglSurface(this)) { + mHaveEgl = true + mEglHelper!!.start() + mRequestRender = true + needStart = true + } + } + } + + // Check if we need to wait. If not, update any state + // that needs to be updated, copy any state that + // needs to be copied, and use "break" to exit the + // wait loop. + + if (mDone) { + return + } + + if (mEventsWaiting) { + eventsWaiting = true + mEventsWaiting = false + break + } + + if (!mPaused && mHasSurface && mHaveEgl && mWidth > 0 && mHeight > 0 + && (mRequestRender || mRenderMode == GLWallpaperService.RENDERMODE_CONTINUOUSLY)) { + changed = mSizeChanged + w = mWidth + h = mHeight + mSizeChanged = false + mRequestRender = false + if (mHasSurface && mWaitingForSurface) { + changed = true + mWaitingForSurface = false + sGLThreadManager.lockObject.notifyAll() + } + break + } + + // By design, this is the only place where we wait(). + + if (LOG_THREADS) { + Log.i("GLThread", "waiting tid=$id") + } + sGLThreadManager.lockObject.wait() + } + } // end of synchronized(sGLThreadManager.lockObject) + + /* + * Handle queued events + */ + if (eventsWaiting) { + var r: Runnable? = event + while (r != null) { + r!!.run() + if (isDone) { + return + } + } + // Go back and see if we need to wait to render. + continue + } + + if (needStart) { + tellRendererSurfaceCreated = true + changed = true + } + if (changed) { + gl = mEglHelper!!.createSurface(mHolder) as GL10 + tellRendererSurfaceChanged = true + } + if (tellRendererSurfaceCreated) { + mRenderer.onSurfaceCreated(gl, mEglHelper!!.mEglConfig) + tellRendererSurfaceCreated = false + } + if (tellRendererSurfaceChanged) { + mRenderer.onSurfaceChanged(gl, w, h) + tellRendererSurfaceChanged = false + } + if (w > 0 && h > 0) { + /* draw a frame here */ + mRenderer.onDrawFrame(gl) + + /* + * Once we're done with GL, we need to call swapBuffers() to instruct the system to display the + * rendered frame + */ + mEglHelper!!.swap() + Thread.sleep(10) + } + } + } finally { + /* + * clean-up everything... + */ + synchronized(sGLThreadManager.lockObject) { + stopEglLocked() + mEglHelper!!.finish() + } + } + } + + fun requestRender() { + synchronized(sGLThreadManager.lockObject) { + mRequestRender = true + sGLThreadManager.lockObject.notifyAll() + } + } + + fun surfaceCreated(holder: SurfaceHolder) { + mHolder = holder + synchronized(sGLThreadManager.lockObject) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceCreated tid=$id") + } + mHasSurface = true + sGLThreadManager.lockObject.notifyAll() + } + } + + fun surfaceDestroyed() { + synchronized(sGLThreadManager.lockObject) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceDestroyed tid=$id") + } + mHasSurface = false + sGLThreadManager.lockObject.notifyAll() + while (!mWaitingForSurface && isAlive && !mDone) { + try { + sGLThreadManager.lockObject.wait() + } catch (e: InterruptedException) { + Thread.currentThread().interrupt() + } + + } + } + } + + fun onPause() { + synchronized(sGLThreadManager.lockObject) { + mPaused = true + sGLThreadManager.lockObject.notifyAll() + } + } + + fun onResume() { + synchronized(sGLThreadManager.lockObject) { + mPaused = false + mRequestRender = true + sGLThreadManager.lockObject.notifyAll() + } + } + + fun onWindowResize(w: Int, h: Int) { + synchronized(sGLThreadManager.lockObject) { + mWidth = w + mHeight = h + mSizeChanged = true + sGLThreadManager.lockObject.notifyAll() + } + } + + fun requestExitAndWait() { + // don't call this from GLThread thread or it is a guaranteed + // deadlock! + synchronized(sGLThreadManager.lockObject) { + mDone = true + sGLThreadManager.lockObject.notifyAll() + } + try { + join() + } catch (ex: InterruptedException) { + Thread.currentThread().interrupt() + } + + } + + /** + * Queue an "event" to be run on the GL rendering thread. + * + * @param r + * the runnable to be run on the GL rendering thread. + */ + fun queueEvent(r: Runnable) { + synchronized(this) { + mEventQueue.add(r) + synchronized(sGLThreadManager.lockObject) { + mEventsWaiting = true + sGLThreadManager.lockObject.notifyAll() + } + } + } + + private inner class GLThreadManager { + + val lockObject = Object() + + @Synchronized + fun threadExiting(thread: GLThread) { + synchronized(lockObject) + { + if (LOG_THREADS) { + Log.i("GLThread", "exiting tid=" + thread.id) + } + thread.mDone = true + if (mEglOwner === thread) { + mEglOwner = null + } + lockObject.notifyAll() + } + } + + /* + * Tries once to acquire the right to use an EGL surface. Does not block. + * + * @return true if the right to use an EGL surface was acquired. + */ + @Synchronized + fun tryAcquireEglSurface(thread: GLThread): Boolean { + if (mEglOwner === thread || mEglOwner == null) { + mEglOwner = thread + lockObject.notifyAll() + return true + } + return false + } + + @Synchronized + fun releaseEglSurface(thread: GLThread) { + if (mEglOwner === thread) { + mEglOwner = null + } + lockObject.notifyAll() + } + } + + companion object { + private val LOG_THREADS = false + val DEBUG_CHECK_GL_ERROR = 1 + val DEBUG_LOG_GL_CALLS = 2 + } +} + diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/JniWrapper.java b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/JniWrapper.java index a25670b..4e4933d 100755 --- a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/JniWrapper.java +++ b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/JniWrapper.java @@ -1,25 +1,17 @@ package fishrungames.mountainwallpaper; -public class JniWrapper +class JniWrapper { - static { System.loadLibrary("MountainWallpaper"); } - - public static void LoadLibrary() - { - //To force loading libraries - } - - public static native void SetTimeOfDayPref(int timeofday); - - public static native void SetSnowPref(boolean snow); - - - public static native void Init(int width, int height); - - public static native void SetOffset(float offsetX, float offsetY); + public static native void SetTimeOfDayPref(int timeofday); + + public static native void SetSnowPref(boolean snow); + + public static native void Init(int width, int height); + + public static native void SetOffset(float offsetX, float offsetY); } diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/MountainWallpaper.kt b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/MountainWallpaper.kt new file mode 100755 index 0000000..847500a --- /dev/null +++ b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/MountainWallpaper.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fishrungames.mountainwallpaper + +import android.content.* +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.preference.PreferenceManager +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.SurfaceHolder +import fishrungames.salmonengineandroid.EngineWrapper + +class MountainWallpaper : GLWallpaperService(), SharedPreferences.OnSharedPreferenceChangeListener { + + init + { + EngineWrapper.LoadSalmonEngineLibrary(); + //JniWrapper.LoadLibrary(); + } + + override fun onCreate() { + super.onCreate() + + PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this) + + EngineWrapper.SetActivityInstance(this) + EngineWrapper.SetupEnviroment() + + var apkFilePath: String? = null + var appInfo: ApplicationInfo? = null + val packMgmr = this.packageManager + try { + appInfo = packMgmr.getApplicationInfo("fishrungames.mountainwallpaper", 0) + } catch (e: PackageManager.NameNotFoundException) { + e.printStackTrace() + throw RuntimeException("Unable to locate assets, aborting...") + } + + apkFilePath = appInfo!!.sourceDir + + EngineWrapper.SetupApkFilePath(apkFilePath) + } + + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + return START_STICKY + } + + override fun onCreateEngine(): Engine { + return MuzeiWallpaperEngine() + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { + + if (key.compareTo("Timeofday", ignoreCase = true) == 0) { + val time = Integer.parseInt(sharedPreferences.getString("Timeofday", "0")!!) + JniWrapper.SetTimeOfDayPref(time) + } + + if (key.compareTo("Snow", ignoreCase = true) == 0) { + + JniWrapper.SetSnowPref(sharedPreferences.getBoolean("Snow", false)) + + } + } + + inner class MuzeiWallpaperEngine : GLWallpaperService.GLEngine() + { + + private lateinit var renderer: WallpaperRenderer + + private val gestureListener = object : GestureDetector.SimpleOnGestureListener() { + override fun onDown(e: MotionEvent): Boolean { + return true + } + } + private val gestureDetector: GestureDetector = GestureDetector(this@MountainWallpaper, + gestureListener) + + override fun onCreate(surfaceHolder: SurfaceHolder) { + super.onCreate(surfaceHolder) + + setEGLContextClientVersion(2) + setRenderer(WallpaperRenderer()) + renderMode = RENDERMODE_CONTINUOUSLY + requestRender() + + // Use the MuzeiWallpaperService's lifecycle to wait for the user to unlock + + setTouchEventsEnabled(true) + setOffsetNotificationsEnabled(true) + } + + override fun onOffsetsChanged( + xOffset: Float, + yOffset: Float, + xOffsetStep: Float, + yOffsetStep: Float, + xPixelOffset: Int, + yPixelOffset: Int + ) { + super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, + yPixelOffset) + + JniWrapper.SetOffset(xPixelOffset * xOffsetStep, yPixelOffset * yOffsetStep) + } + + override fun onTouchEvent(event: MotionEvent) { + super.onTouchEvent(event) + gestureDetector.onTouchEvent(event) + } + } +} diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/MountainWallpaperService.java b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/MountainWallpaperService.java deleted file mode 100755 index ad9577a..0000000 --- a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/MountainWallpaperService.java +++ /dev/null @@ -1,233 +0,0 @@ -package fishrungames.mountainwallpaper; - - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; - -import android.net.ConnectivityManager; - -import android.os.Handler; -import android.preference.PreferenceManager; - -import android.view.MotionEvent; -import android.view.SurfaceHolder; - -//import com.seb.SLWP.SLWP.GlEngine.DownloadTask; - -import fishrungames.salmonengineandroid.EngineWrapper; - -public class MountainWallpaperService extends GLWallpaperService implements - OnSharedPreferenceChangeListener { - /* - * (non-Javadoc) - * - * @see android.app.Service#onLowMemory() - */ - static - { - EngineWrapper.LoadSalmonEngineLibrary(); - JniWrapper.LoadLibrary(); - } - - - public static final long SLEEPTIME = 1000 * 60 * 30; // 30 minutes - private GlEngine mGle; - - public static Context mContext; - public static boolean ShowClouds; - public static boolean TouchRot; - - public static int Bg; - public static boolean Usebg; - public static int Tex; - - static long Synctime; - - public boolean Slidedir; - public boolean Slideplanet; - public boolean Syncrot; - public static boolean Randomtex = true; - public static boolean visible = false; - - public static boolean useCropper = true; - public static int Cropaspect; - public static boolean loading = false; - - public static final Handler mHandler = new Handler(); - public static final int RNDMAP = -1; - public static boolean destroyed; - public static String bgfile; - public ConnectivityManager cm; - public boolean needresume; - public boolean fstart; - public static String[] randlist; - public int curtexidx = -99; - - static final String ACTION_FOREGROUND = "fishrungames.mountainwallpaper.FOREGROUND"; - static final String ACTION_BACKGROUND = "fishrungames.mountainwallpaper.BACKGROUND"; - - - - @Override - public void onCreate() { - // TODO Auto-generated method stub - super.onCreate(); - - - PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); - - EngineWrapper.SetActivityInstance(this); - EngineWrapper.SetupEnviroment(); - - String apkFilePath = null; - ApplicationInfo appInfo = null; - PackageManager packMgmr = this.getPackageManager(); - try { - appInfo = packMgmr.getApplicationInfo("fishrungames.mountainwallpaper", 0); - } catch (NameNotFoundException e) { - - - - e.printStackTrace(); - throw new RuntimeException("Unable to locate assets, aborting..."); - } - apkFilePath = appInfo.sourceDir; - - EngineWrapper.SetupApkFilePath(apkFilePath); - - Init(); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - // handleCommand(intent); - // We want this service to continue running until it is explicitly - // stopped, so return sticky. - return START_STICKY; - } - - private void Init() { - try { - mContext = this; - cm = (ConnectivityManager) mContext - .getSystemService(Context.CONNECTIVITY_SERVICE); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - public void onDestroy() { - // TODO Auto-generated method stub - super.onDestroy(); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - - if (key.compareToIgnoreCase("Timeofday") == 0) - { - int time = Integer.parseInt(sharedPreferences.getString("Timeofday", "0")); - JniWrapper.SetTimeOfDayPref(time); - } - - if (key.compareToIgnoreCase("Snow") == 0) { - - JniWrapper.SetSnowPref(sharedPreferences.getBoolean("Snow", false)); - - } - } - - @Override - public Engine onCreateEngine() { - if (mGle != null) { - mGle = null; - } - try { - - mGle = new GlEngine(); - - } catch (Exception e) { - return null; - } - - return mGle; - } - - class GlEngine extends GLEngine { - - public Handler mHandler = new Handler(); - - long NOW; - - @Override - public void onCreate(SurfaceHolder surfaceHolder) { - super.onCreate(surfaceHolder); - try { - this.setTouchEventsEnabled(true); - fstart = true; - setRenderer(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - public void onTouchEvent(MotionEvent e) { - - return; - } - - @Override - public void onOffsetsChanged(float xOffset, float yOffset, - float xOffsetStep, float yOffsetStep, int xPixelOffset, - int yPixelOffset) { - - super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, - xPixelOffset, yPixelOffset); - - JniWrapper.SetOffset(xPixelOffset*xOffsetStep, yPixelOffset*yOffsetStep); - - } - - @Override - public void onVisibilityChanged(boolean visible) { - // TODO Auto-generated method stub - super.onVisibilityChanged(visible); - MountainWallpaperService.visible = visible; - if (visible) { - - } else { - - } - } - - @Override - public void onPause() { - super.onPause(); - } - - @Override - public void onResume() { - - super.onResume(); - } - - @Override - public void onSurfaceChanged(SurfaceHolder holder, int format, - int width, int height) { - // TODO Auto-generated method stub - super.onSurfaceChanged(holder, format, width, height); - fstart = true; - } - - } - -} \ No newline at end of file diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/Prefs.java b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/Prefs.java deleted file mode 100755 index 79c7c3e..0000000 --- a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/Prefs.java +++ /dev/null @@ -1,72 +0,0 @@ -package fishrungames.mountainwallpaper; - -import fishrungames.mountainwallpaper.R; -import fishrungames.mountainwallpaper.JniWrapper; - - -import android.content.Intent; - -import android.net.Uri; -import android.os.Bundle; -import android.preference.CheckBoxPreference; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceActivity; - -import android.preference.Preference.OnPreferenceChangeListener; - - -public class Prefs extends PreferenceActivity implements - OnPreferenceChangeListener { - - - private CheckBoxPreference snowPref; - private ListPreference timeOfDayPref; - - - public static Uri currImageURI; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.prefliste); - addPreferencesFromResource(R.xml.preferences); - - - snowPref = (CheckBoxPreference)this.getPreferenceManager().findPreference("Snow"); - timeOfDayPref = (ListPreference) findPreference("Timeofday"); - - if (timeOfDayPref.getKey().compareToIgnoreCase("Timeofday") == 0) - { - JniWrapper.SetTimeOfDayPref(Integer.parseInt((String) timeOfDayPref.getValue())); - - } - - if (snowPref.getKey().compareToIgnoreCase("Snow") == 0) { - if (!snowPref.isChecked()) - { - JniWrapper.SetSnowPref(false); - } - else - { - JniWrapper.SetSnowPref(true); - } - } - - } - - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - - return true; - - } - - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - - } - -} diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperPreferenceFragment.kt b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperPreferenceFragment.kt new file mode 100755 index 0000000..e2d1914 --- /dev/null +++ b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperPreferenceFragment.kt @@ -0,0 +1,11 @@ +package fishrungames.mountainwallpaper + +import android.support.v7.preference.PreferenceFragmentCompat +import android.os.Bundle + +class WallpaperPreferenceFragment : PreferenceFragmentCompat() +{ + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.preferences, rootKey) + } +} \ No newline at end of file diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperPreferences.kt b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperPreferences.kt new file mode 100755 index 0000000..ef21221 --- /dev/null +++ b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperPreferences.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fishrungames.mountainwallpaper + +import android.os.Bundle +import android.support.v4.app.FragmentActivity + +class WallpaperPreferences : FragmentActivity() +{ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.pref_activity) + } +} diff --git a/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperRenderer.kt b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperRenderer.kt new file mode 100755 index 0000000..f166731 --- /dev/null +++ b/proj.android-studio/app/src/main/java/fishrungames/mountainwallpaper/WallpaperRenderer.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fishrungames.mountainwallpaper + +import android.opengl.GLES20 +import android.opengl.GLSurfaceView +import android.util.Log +import fishrungames.salmonengineandroid.EngineWrapper +import java.util.* +import javax.microedition.khronos.egl.EGLConfig +import javax.microedition.khronos.opengles.GL10 + +class WallpaperRenderer() : GLSurfaceView.Renderer { + + private var surfaceCreated: Boolean = false + private var lastTimeStamp: Long = 0 + + override fun onSurfaceCreated(unused: GL10, config: EGLConfig) { + surfaceCreated = true + } + + override fun onSurfaceChanged(unused: GL10, width: Int, height: Int) { + JniWrapper.Init(width, height) + } + + override fun onDrawFrame(unused: GL10) { + val currentTimeStamp = Calendar.getInstance().timeInMillis + if (lastTimeStamp == 0L) + { + lastTimeStamp = currentTimeStamp + } + + EngineWrapper.Update(currentTimeStamp - lastTimeStamp) + + lastTimeStamp = currentTimeStamp + } +} diff --git a/proj.android-studio/app/src/main/res/drawable-nodpi/icon.png b/proj.android-studio/app/src/main/res/drawable-nodpi/icon.png new file mode 100755 index 0000000..71b697f Binary files /dev/null and b/proj.android-studio/app/src/main/res/drawable-nodpi/icon.png differ diff --git a/proj.android-studio/app/src/main/res/drawable/icon.png b/proj.android-studio/app/src/main/res/drawable/icon.png new file mode 100755 index 0000000..6d35977 Binary files /dev/null and b/proj.android-studio/app/src/main/res/drawable/icon.png differ diff --git a/proj.android-studio/app/src/main/res/drawable/notificon.png b/proj.android-studio/app/src/main/res/drawable/notificon.png deleted file mode 100755 index 656209b..0000000 Binary files a/proj.android-studio/app/src/main/res/drawable/notificon.png and /dev/null differ diff --git a/proj.android-studio/app/src/main/res/drawable/thumb.jpg b/proj.android-studio/app/src/main/res/drawable/thumb.jpg deleted file mode 100755 index cfe281b..0000000 Binary files a/proj.android-studio/app/src/main/res/drawable/thumb.jpg and /dev/null differ diff --git a/proj.android-studio/app/src/main/res/font/alegreya_black_italic.ttf b/proj.android-studio/app/src/main/res/font/alegreya_black_italic.ttf new file mode 100755 index 0000000..7cd03db Binary files /dev/null and b/proj.android-studio/app/src/main/res/font/alegreya_black_italic.ttf differ diff --git a/proj.android-studio/app/src/main/res/font/alegreya_italic.ttf b/proj.android-studio/app/src/main/res/font/alegreya_italic.ttf new file mode 100755 index 0000000..125edeb Binary files /dev/null and b/proj.android-studio/app/src/main/res/font/alegreya_italic.ttf differ diff --git a/proj.android-studio/app/src/main/res/font/alegreya_sans_black.ttf b/proj.android-studio/app/src/main/res/font/alegreya_sans_black.ttf new file mode 100755 index 0000000..1b29b38 Binary files /dev/null and b/proj.android-studio/app/src/main/res/font/alegreya_sans_black.ttf differ diff --git a/proj.android-studio/app/src/main/res/font/alegreya_sans_medium.ttf b/proj.android-studio/app/src/main/res/font/alegreya_sans_medium.ttf new file mode 100755 index 0000000..dfed9d2 Binary files /dev/null and b/proj.android-studio/app/src/main/res/font/alegreya_sans_medium.ttf differ diff --git a/proj.android-studio/app/src/main/res/layout/main.xml b/proj.android-studio/app/src/main/res/layout/main.xml deleted file mode 100755 index 4361cfe..0000000 --- a/proj.android-studio/app/src/main/res/layout/main.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/proj.android-studio/app/src/main/res/layout/pref_activity.xml b/proj.android-studio/app/src/main/res/layout/pref_activity.xml new file mode 100755 index 0000000..d050e6e --- /dev/null +++ b/proj.android-studio/app/src/main/res/layout/pref_activity.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/proj.android-studio/app/src/main/res/layout/prefliste.xml b/proj.android-studio/app/src/main/res/layout/prefliste.xml deleted file mode 100755 index 3c2ad7c..0000000 --- a/proj.android-studio/app/src/main/res/layout/prefliste.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/proj.android-studio/app/src/main/res/xml/preferences.xml b/proj.android-studio/app/src/main/res/xml/preferences.xml index 4917e51..5122a24 100755 --- a/proj.android-studio/app/src/main/res/xml/preferences.xml +++ b/proj.android-studio/app/src/main/res/xml/preferences.xml @@ -5,9 +5,11 @@ - + + android:summaryOff="@string/p_snow_off" android:defaultValue="false" + /> diff --git a/proj.android-studio/app/src/main/res/xml/wallpaper.xml b/proj.android-studio/app/src/main/res/xml/wallpaper.xml index 0a9c5da..e7a7b87 100755 --- a/proj.android-studio/app/src/main/res/xml/wallpaper.xml +++ b/proj.android-studio/app/src/main/res/xml/wallpaper.xml @@ -1,6 +1,8 @@ - \ No newline at end of file + android:settingsActivity="fishrungames.mountainwallpaper.WallpaperPreferences" + /> \ No newline at end of file diff --git a/proj.android-studio/app/src/test/java/fishrungames/salmonandroidtemplate/ExampleUnitTest.java b/proj.android-studio/app/src/test/java/fishrungames/salmonandroidtemplate/ExampleUnitTest.java deleted file mode 100755 index 49c0291..0000000 --- a/proj.android-studio/app/src/test/java/fishrungames/salmonandroidtemplate/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package fishrungames.salmonandroidtemplate; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/proj.android-studio/build.gradle b/proj.android-studio/build.gradle index 0a832c6..0e5c0fe 100755 --- a/proj.android-studio/build.gradle +++ b/proj.android-studio/build.gradle @@ -1,14 +1,20 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.2.70' + ext { + compileSdkVersion = 28 + targetSdkVersion = 28 + + kotlin_version = "1.3.10" + supportLibraryVersion = "28.0.0" + } repositories { jcenter() google() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.0-rc03' + classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong