From 2a523f2ea20c4097465ebfe0e5f6a078b9487e6e Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Tue, 30 Jul 2019 16:50:40 -0400 Subject: [PATCH] v0.7.4b: Initial LibGDX commit! more details below: Large sections of game logic are now working through libgdx instead of android libraries. There is still work to do but this is the first major step. Big changes include: - Graphics code is now through LibGDX (except for text rendering) - Initialization and screen-handling logic is now mostly through LibGDX - Audio is now through LibGDX - Input handling is now through LibGDX - Most misc functions are now through LibGDX --- SPD-classes/build.gradle | 49 +++ SPD-classes/proguard-rules.pro | 19 ++ .../com/watabou/gltextures/BufferTexture.java | 26 +- .../com/watabou/gltextures/SmartTexture.java | 27 +- .../com/watabou/gltextures/TextureCache.java | 49 ++- .../java/com/watabou/glwrap/Attribute.java | 11 +- .../java/com/watabou/glwrap/Blending.java | 10 +- .../java/com/watabou/glwrap/Framebuffer.java | 23 +- .../main/java/com/watabou/glwrap/Matrix.java | 63 +++- .../main/java/com/watabou/glwrap/Program.java | 27 +- .../main/java/com/watabou/glwrap/Quad.java | 16 +- .../java/com/watabou/glwrap/Renderbuffer.java | 19 +- .../watabou/glwrap/ScreenConfigChooser.java | 183 ----------- .../main/java/com/watabou/glwrap/Shader.java | 27 +- .../main/java/com/watabou/glwrap/Texture.java | 80 ++--- .../main/java/com/watabou/glwrap/Uniform.java | 16 +- .../java/com/watabou/glwrap/Vertexbuffer.java | 16 +- .../java/com/watabou/input/InputHandler.java | 120 ++++++++ .../src/main/java/com/watabou/input/Keys.java | 28 +- .../java/com/watabou/input/Touchscreen.java | 102 ++---- .../java/com/watabou/noosa/BitmapText.java | 24 +- .../src/main/java/com/watabou/noosa/Game.java | 290 ++++++------------ .../src/main/java/com/watabou/noosa/Halo.java | 15 +- .../java/com/watabou/noosa/NoosaScript.java | 72 +++-- .../watabou/noosa/NoosaScriptNoLighting.java | 47 +-- .../java/com/watabou/noosa/RenderedText.java | 14 +- .../java/com/watabou/noosa/audio/Music.java | 79 ++--- .../java/com/watabou/noosa/audio/Sample.java | 105 ++----- .../java/com/watabou/utils/BitmapCache.java | 39 +-- .../java/com/watabou/utils/BitmapFilm.java | 11 +- .../java/com/watabou/utils/DeviceCompat.java | 30 +- .../java/com/watabou/utils/GameSettings.java | 24 +- .../main/java/com/watabou/utils/PointF.java | 3 - .../java/com/watabou/utils/SparseArray.java | 22 +- build.gradle | 2 + core/src/main/AndroidManifest.xml | 3 +- core/src/main/assets/shadow.png | Bin 79 -> 74 bytes core/src/main/assets/visual_grid.png | Bin 185 -> 186 bytes .../ShatteredPixelDungeon.java | 94 +++--- .../shatteredpixeldungeon/levels/Level.java | 6 +- .../scenes/GameScene.java | 5 +- .../tiles/DungeonTileSheet.java | 4 +- 42 files changed, 828 insertions(+), 972 deletions(-) create mode 100644 SPD-classes/proguard-rules.pro delete mode 100644 SPD-classes/src/main/java/com/watabou/glwrap/ScreenConfigChooser.java create mode 100644 SPD-classes/src/main/java/com/watabou/input/InputHandler.java diff --git a/SPD-classes/build.gradle b/SPD-classes/build.gradle index e1e326108..d5bd17844 100644 --- a/SPD-classes/build.gradle +++ b/SPD-classes/build.gradle @@ -6,5 +6,54 @@ android { defaultConfig { //noinspection MinSdkTooLow minSdkVersion appAndroidMinSDK + + consumerProguardFiles 'proguard-rules.pro' + } + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } } } + +configurations { natives } + +dependencies { + //TODO migrate this to implementation from api + //in order to do this I have to remove 100% of libGDX API access from core + api "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64" + implementation "com.badlogicgames.gdx:gdx-controllers:$gdxVersion" + implementation "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion" +} + +// called every time gradle gets executed, takes the native dependencies of +// the natives configuration, and extracts them to the proper libs/ folders +// so they get packed with the APK. +task copyAndroidNatives() { + file("libs/armeabi/").mkdirs() + file("libs/armeabi-v7a/").mkdirs() + file("libs/arm64-v8a/").mkdirs() + file("libs/x86_64/").mkdirs() + file("libs/x86/").mkdirs() + + configurations.natives.files.each { jar -> + def outputDir = null + if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a") + if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a") + if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi") + if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64") + if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86") + if(outputDir != null) { + copy { + from zipTree(jar) + into outputDir + include "*.so" + } + } + } +} \ No newline at end of file diff --git a/SPD-classes/proguard-rules.pro b/SPD-classes/proguard-rules.pro new file mode 100644 index 000000000..93b5492cd --- /dev/null +++ b/SPD-classes/proguard-rules.pro @@ -0,0 +1,19 @@ +-dontwarn android.support.** +-dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication +-dontwarn com.badlogic.gdx.utils.GdxBuild +-dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild +-dontwarn com.badlogic.gdx.jnigen.BuildTarget* + +-keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* { + (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration); +} + +-keepclassmembers class com.badlogic.gdx.physics.box2d.World { + boolean contactFilter(long, long); + void beginContact(long); + void endContact(long); + void preSolve(long, long); + void postSolve(long, long); + boolean reportFixture(long); + float reportRayFixture(long, float, float, float, float, float); +} \ No newline at end of file diff --git a/SPD-classes/src/main/java/com/watabou/gltextures/BufferTexture.java b/SPD-classes/src/main/java/com/watabou/gltextures/BufferTexture.java index cbe3f3998..9a88d4e19 100644 --- a/SPD-classes/src/main/java/com/watabou/gltextures/BufferTexture.java +++ b/SPD-classes/src/main/java/com/watabou/gltextures/BufferTexture.java @@ -21,15 +21,15 @@ package com.watabou.gltextures; -import android.opengl.GLES20; - +import com.badlogic.gdx.Gdx; import com.watabou.glwrap.Texture; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; -//provides a native intbuffer implementation because android.graphics.bitmap is too slow +//provides a native intbuffer implementation because pixmap is too slow +//TODO: should evaluate this again, seeing as I've moved to LibGDX public class BufferTexture extends SmartTexture { public IntBuffer pixels; @@ -46,9 +46,7 @@ public class BufferTexture extends SmartTexture { @Override protected void generate() { - int[] ids = new int[1]; - GLES20.glGenTextures( 1, ids, 0 ); - id = ids[0]; + id = Gdx.gl.glGenTexture(); } @Override @@ -62,15 +60,15 @@ public class BufferTexture extends SmartTexture { filter( Texture.LINEAR, Texture.LINEAR ); wrap( Texture.CLAMP, Texture.CLAMP); pixels.position(0); - GLES20.glTexImage2D( - GLES20.GL_TEXTURE_2D, + Gdx.gl.glTexImage2D( + Gdx.gl.GL_TEXTURE_2D, 0, - GLES20.GL_RGBA, + Gdx.gl.GL_RGBA, width, height, 0, - GLES20.GL_RGBA, - GLES20.GL_UNSIGNED_BYTE, + Gdx.gl.GL_RGBA, + Gdx.gl.GL_UNSIGNED_BYTE, pixels ); } @@ -80,14 +78,14 @@ public class BufferTexture extends SmartTexture { filter( Texture.LINEAR, Texture.LINEAR ); wrap( Texture.CLAMP, Texture.CLAMP); pixels.position(top*width); - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, + Gdx.gl.glTexSubImage2D(Gdx.gl.GL_TEXTURE_2D, 0, 0, top, width, bottom - top, - GLES20.GL_RGBA, - GLES20.GL_UNSIGNED_BYTE, + Gdx.gl.GL_RGBA, + Gdx.gl.GL_UNSIGNED_BYTE, pixels); } } diff --git a/SPD-classes/src/main/java/com/watabou/gltextures/SmartTexture.java b/SPD-classes/src/main/java/com/watabou/gltextures/SmartTexture.java index 637bf3552..9a3c6a27a 100644 --- a/SPD-classes/src/main/java/com/watabou/gltextures/SmartTexture.java +++ b/SPD-classes/src/main/java/com/watabou/gltextures/SmartTexture.java @@ -21,8 +21,7 @@ package com.watabou.gltextures; -import android.graphics.Bitmap; - +import com.badlogic.gdx.graphics.Pixmap; import com.watabou.glwrap.Texture; import com.watabou.utils.RectF; @@ -37,22 +36,22 @@ public class SmartTexture extends Texture { public int wModeH; public int wModeV; - public Bitmap bitmap; + public Pixmap bitmap; public Atlas atlas; protected SmartTexture( ) { //useful for subclasses which want to manage their own texture data - // in cases where android.graphics.bitmap isn't fast enough. + // in cases where pixmaps isn't fast enough. //subclasses which use this MUST also override some mix of reload/generate/bind } - public SmartTexture( Bitmap bitmap ) { + public SmartTexture( Pixmap bitmap ) { this( bitmap, NEAREST, CLAMP, false ); } - public SmartTexture( Bitmap bitmap, int filtering, int wrapping, boolean premultiplied ) { + public SmartTexture( Pixmap bitmap, int filtering, int wrapping, boolean premultiplied ) { this.bitmap = bitmap; width = bitmap.getWidth(); @@ -66,7 +65,7 @@ public class SmartTexture extends Texture { @Override protected void generate() { super.generate(); - bitmap( bitmap, premultiplied ); + bitmap( bitmap ); filter( fModeMin, fModeMax ); wrap( wModeH, wModeV ); } @@ -88,16 +87,8 @@ public class SmartTexture extends Texture { } @Override - public void bitmap( Bitmap bitmap ) { - bitmap( bitmap, false ); - } - - public void bitmap( Bitmap bitmap, boolean premultiplied ) { - if (premultiplied) { - super.bitmap( bitmap ); - } else { - handMade( bitmap, true ); - } + public void bitmap( Pixmap bitmap ) { + super.bitmap( bitmap ); this.bitmap = bitmap; width = bitmap.getWidth(); @@ -119,7 +110,7 @@ public class SmartTexture extends Texture { super.delete(); if (bitmap != null) - bitmap.recycle(); + bitmap.dispose(); bitmap = null; } diff --git a/SPD-classes/src/main/java/com/watabou/gltextures/TextureCache.java b/SPD-classes/src/main/java/com/watabou/gltextures/TextureCache.java index c1e00ad98..491311499 100644 --- a/SPD-classes/src/main/java/com/watabou/gltextures/TextureCache.java +++ b/SPD-classes/src/main/java/com/watabou/gltextures/TextureCache.java @@ -21,28 +21,16 @@ package com.watabou.gltextures; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; - +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Pixmap; import com.watabou.glwrap.Texture; import com.watabou.noosa.Game; import java.util.HashMap; public class TextureCache { - - public static Context context; private static HashMap all = new HashMap<>(); - - // No dithering, no scaling, 32 bits per pixel - private static BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); - static { - bitmapOptions.inScaled = false; - bitmapOptions.inDither = false; - bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; - } public synchronized static SmartTexture createSolid( int color ) { final String key = "1x1:" + color; @@ -52,11 +40,13 @@ public class TextureCache { return all.get( key ); } else { - - Bitmap bmp = Bitmap.createBitmap( 1, 1, Bitmap.Config.ARGB_8888 ); - bmp.eraseColor( color ); - SmartTexture tx = new SmartTexture( bmp ); + Pixmap pixmap =new Pixmap( 1, 1, Pixmap.Format.RGBA8888 ); + // In the rest of the code ARGB is used + pixmap.setColor( (color << 8) | (color >>> 24) ); + pixmap.fill(); + + SmartTexture tx = new SmartTexture( pixmap ); all.put( key, tx ); return tx; @@ -72,12 +62,13 @@ public class TextureCache { return all.get( key ); } else { - - Bitmap bmp = Bitmap.createBitmap( colors.length, 1, Bitmap.Config.ARGB_8888 ); + + Pixmap pixmap = new Pixmap( colors.length, 1, Pixmap.Format.RGBA8888); for (int i=0; i < colors.length; i++) { - bmp.setPixel( i, 0, colors[i] ); + // In the rest of the code ARGB is used + pixmap.drawPixel( i, 0, (colors[i] << 8) | (colors[i] >>> 24) ); } - SmartTexture tx = new SmartTexture( bmp ); + SmartTexture tx = new SmartTexture( pixmap ); tx.filter( Texture.LINEAR, Texture.LINEAR ); tx.wrap( Texture.CLAMP, Texture.CLAMP ); @@ -134,22 +125,22 @@ public class TextureCache { } } - public static Bitmap getBitmap( Object src ) { + public static Pixmap getBitmap( Object src ) { try { if (src instanceof Integer){ - return BitmapFactory.decodeResource( - context.getResources(), (Integer)src, bitmapOptions ); + //LibGDX does not support android resource integer handles, and they were + //never used by the game anyway, should probably remove this entirely + return null; } else if (src instanceof String) { - return BitmapFactory.decodeStream( - context.getAssets().open( (String)src ), null, bitmapOptions ); + return new Pixmap(Gdx.files.internal((String)src)); - } else if (src instanceof Bitmap) { + } else if (src instanceof Pixmap) { - return (Bitmap)src; + return (Pixmap)src; } else { diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java b/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java index bc1e06f3d..ecee8289f 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java @@ -21,8 +21,7 @@ package com.watabou.glwrap; -import android.opengl.GLES20; -import android.os.Build; +import com.badlogic.gdx.Gdx; import java.nio.FloatBuffer; @@ -39,18 +38,18 @@ public class Attribute { } public void enable() { - GLES20.glEnableVertexAttribArray( location ); + Gdx.gl.glEnableVertexAttribArray( location ); } public void disable() { - GLES20.glDisableVertexAttribArray( location ); + Gdx.gl.glDisableVertexAttribArray( location ); } public void vertexPointer( int size, int stride, FloatBuffer ptr ) { - GLES20.glVertexAttribPointer( location, size, GLES20.GL_FLOAT, false, stride * 4, ptr ); + Gdx.gl.glVertexAttribPointer( location, size, Gdx.gl.GL_FLOAT, false, stride * 4, ptr ); } public void vertexBuffer( int size, int stride, int offset) { - GLES20.glVertexAttribPointer(location, size, GLES20.GL_FLOAT, false, stride * 4, offset * 4); + Gdx.gl.glVertexAttribPointer(location, size, Gdx.gl.GL_FLOAT, false, stride * 4, offset * 4); } } diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Blending.java b/SPD-classes/src/main/java/com/watabou/glwrap/Blending.java index 2d0bb76c5..fdda54fba 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Blending.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Blending.java @@ -21,7 +21,7 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; import javax.microedition.khronos.opengles.GL10; @@ -33,21 +33,21 @@ public class Blending { } public static void enable(){ - GLES20.glEnable( GL10.GL_BLEND ); + Gdx.gl.glEnable( GL10.GL_BLEND ); } public static void disable(){ - GLES20.glDisable( GL10.GL_BLEND ); + Gdx.gl.glDisable( GL10.GL_BLEND ); } //in this mode colors overwrite eachother, based on alpha value public static void setNormalMode(){ - GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); + Gdx.gl.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); } //in this mode colors add to eachother, eventually reaching pure white public static void setLightMode(){ - GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE ); + Gdx.gl.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE ); } } diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Framebuffer.java b/SPD-classes/src/main/java/com/watabou/glwrap/Framebuffer.java index 3cf8836fe..991c856fa 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Framebuffer.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Framebuffer.java @@ -21,22 +21,20 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; public class Framebuffer { - public static final int COLOR = GLES20.GL_COLOR_ATTACHMENT0; - public static final int DEPTH = GLES20.GL_DEPTH_ATTACHMENT; - public static final int STENCIL = GLES20.GL_STENCIL_ATTACHMENT; + public static final int COLOR = Gdx.gl.GL_COLOR_ATTACHMENT0; + public static final int DEPTH = Gdx.gl.GL_DEPTH_ATTACHMENT; + public static final int STENCIL = Gdx.gl.GL_STENCIL_ATTACHMENT; public static final Framebuffer system = new Framebuffer( 0 ); private int id; public Framebuffer() { - int[] buffers = new int[1]; - GLES20.glGenBuffers( 1, buffers, 0 ); - id = buffers[0]; + id = Gdx.gl.glGenBuffer(); } private Framebuffer( int n ) { @@ -44,26 +42,25 @@ public class Framebuffer { } public void bind() { - GLES20.glBindFramebuffer( GLES20.GL_FRAMEBUFFER, id ); + Gdx.gl.glBindFramebuffer( Gdx.gl.GL_FRAMEBUFFER, id ); } public void delete() { - int[] buffers = {id}; - GLES20.glDeleteFramebuffers( 1, buffers, 0 ); + Gdx.gl.glDeleteBuffer(id); } public void attach( int point, Texture tex ) { bind(); - GLES20.glFramebufferTexture2D( GLES20.GL_FRAMEBUFFER, point, GLES20.GL_TEXTURE_2D, tex.id, 0 ); + Gdx.gl.glFramebufferTexture2D( Gdx.gl.GL_FRAMEBUFFER, point, Gdx.gl.GL_TEXTURE_2D, tex.id, 0 ); } public void attach( int point, Renderbuffer buffer ) { bind(); - GLES20.glFramebufferRenderbuffer( GLES20.GL_RENDERBUFFER, point, GLES20.GL_TEXTURE_2D, buffer.id() ); + Gdx.gl.glFramebufferRenderbuffer( Gdx.gl.GL_RENDERBUFFER, point, Gdx.gl.GL_TEXTURE_2D, buffer.id() ); } public boolean status() { bind(); - return GLES20.glCheckFramebufferStatus( GLES20.GL_FRAMEBUFFER ) == GLES20.GL_FRAMEBUFFER_COMPLETE; + return Gdx.gl.glCheckFramebufferStatus( Gdx.gl.GL_FRAMEBUFFER ) == Gdx.gl.GL_FRAMEBUFFER_COMPLETE; } } diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Matrix.java b/SPD-classes/src/main/java/com/watabou/glwrap/Matrix.java index 305a97422..d42dde440 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Matrix.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Matrix.java @@ -21,6 +21,8 @@ package com.watabou.glwrap; +//TODO LibGDX offer matrix classes as well, which might give better performance. +//should investigate using them public class Matrix { public static final float G2RAD = 0.01745329251994329576923690768489f; @@ -91,7 +93,6 @@ public class Matrix { m[5] *= y; m[6] *= y; m[7] *= y; - // android.opengl.Matrix.scaleM( m, 0, x, y, 1 ); } public static void translate( float[] m, float x, float y ) { @@ -100,6 +101,64 @@ public class Matrix { } public static void multiply( float[] left, float right[], float[] result ) { - android.opengl.Matrix.multiplyMM( result, 0, left, 0, right, 0 ); + final float ax1 = left[0]; + final float ay1 = left[1]; + final float az1 = left[2]; + final float aw1 = left[3]; + + final float ax2 = left[4]; + final float ay2 = left[5]; + final float az2 = left[6]; + final float aw2 = left[7]; + + final float ax3 = left[8]; + final float ay3 = left[9]; + final float az3 = left[10]; + final float aw3 = left[11]; + + final float ax4 = left[12]; + final float ay4 = left[13]; + final float az4 = left[14]; + final float aw4 = left[15]; + + final float bx1 = right[0]; + final float by1 = right[1]; + final float bz1 = right[2]; + final float bw1 = right[3]; + + final float bx2 = right[4]; + final float by2 = right[5]; + final float bz2 = right[6]; + final float bw2 = right[7]; + + final float bx3 = right[8]; + final float by3 = right[9]; + final float bz3 = right[10]; + final float bw3 = right[11]; + + final float bx4 = right[12]; + final float by4 = right[13]; + final float bz4 = right[14]; + final float bw4 = right[15]; + + result[0] = ax1 * bx1 + ax2 * by1 + ax3 * bz1 + ax4 * bw1; + result[1] = ay1 * bx1 + ay2 * by1 + ay3 * bz1 + ay4 * bw1; + result[2] = az1 * bx1 + az2 * by1 + az3 * bz1 + az4 * bw1; + result[3] = aw1 * bx1 + aw2 * by1 + aw3 * bz1 + aw4 * bw1; + + result[4] = ax1 * bx2 + ax2 * by2 + ax3 * bz2 + ax4 * bw2; + result[5] = ay1 * bx2 + ay2 * by2 + ay3 * bz2 + ay4 * bw2; + result[6] = az1 * bx2 + az2 * by2 + az3 * bz2 + az4 * bw2; + result[7] = aw1 * bx2 + aw2 * by2 + aw3 * bz2 + aw4 * bw2; + + result[8] = ax1 * bx3 + ax2 * by3 + ax3 * bz3 + ax4 * bw3; + result[9] = ay1 * bx3 + ay2 * by3 + ay3 * bz3 + ay4 * bw3; + result[10] = az1 * bx3 + az2 * by3 + az3 * bz3 + az4 * bw3; + result[11] = aw1 * bx3 + aw2 * by3 + aw3 * bz3 + aw4 * bw3; + + result[12] = ax1 * bx4 + ax2 * by4 + ax3 * bz4 + ax4 * bw4; + result[13] = ay1 * bx4 + ay2 * by4 + ay3 * bz4 + ay4 * bw4; + result[14] = az1 * bx4 + az2 * by4 + az3 * bz4 + az4 * bw4; + result[15] = aw1 * bx4 + aw2 * by4 + aw3 * bz4 + aw4 * bw4; } } \ No newline at end of file diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Program.java b/SPD-classes/src/main/java/com/watabou/glwrap/Program.java index feeb8eb0c..46ab2c4a4 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Program.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Program.java @@ -21,14 +21,17 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.utils.BufferUtils; + +import java.nio.IntBuffer; public class Program { private int handle; public Program() { - handle = GLES20.glCreateProgram(); + handle = Gdx.gl.glCreateProgram(); } public int handle() { @@ -36,33 +39,33 @@ public class Program { } public void attach( Shader shader ) { - GLES20.glAttachShader( handle, shader.handle() ); + Gdx.gl.glAttachShader( handle, shader.handle() ); } public void link() { - GLES20.glLinkProgram( handle ); + Gdx.gl.glLinkProgram( handle ); - int[] status = new int[1]; - GLES20.glGetProgramiv( handle, GLES20.GL_LINK_STATUS, status, 0 ); - if (status[0] == GLES20.GL_FALSE) { - throw new Error( GLES20.glGetProgramInfoLog( handle ) ); + IntBuffer status = BufferUtils.newIntBuffer(1); + Gdx.gl.glGetProgramiv( handle, Gdx.gl.GL_LINK_STATUS, status ); + if (status.get() == Gdx.gl.GL_FALSE) { + throw new Error( Gdx.gl.glGetProgramInfoLog( handle ) ); } } public Attribute attribute( String name ) { - return new Attribute( GLES20.glGetAttribLocation( handle, name ) ); + return new Attribute( Gdx.gl.glGetAttribLocation( handle, name ) ); } public Uniform uniform( String name ) { - return new Uniform( GLES20.glGetUniformLocation( handle, name ) ); + return new Uniform( Gdx.gl.glGetUniformLocation( handle, name ) ); } public void use() { - GLES20.glUseProgram( handle ); + Gdx.gl.glUseProgram( handle ); } public void delete() { - GLES20.glDeleteProgram( handle ); + Gdx.gl.glDeleteProgram( handle ); } public static Program create( Shader ...shaders ) { diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Quad.java b/SPD-classes/src/main/java/com/watabou/glwrap/Quad.java index ac62f8320..cc8333745 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Quad.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Quad.java @@ -21,7 +21,7 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -59,21 +59,19 @@ public class Quad { public static void setupIndices(){ ShortBuffer indices = getIndices( Short.MAX_VALUE ); if (bufferIndex == -1){ - int[] buf = new int[1]; - GLES20.glGenBuffers(1, buf, 0); - bufferIndex = buf[0]; + bufferIndex = Gdx.gl.glGenBuffer(); } - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, bufferIndex); - GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, (indices.capacity()*2), indices, GLES20.GL_STATIC_DRAW); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); + Gdx.gl.glBindBuffer(Gdx.gl.GL_ELEMENT_ARRAY_BUFFER, bufferIndex); + Gdx.gl.glBufferData(Gdx.gl.GL_ELEMENT_ARRAY_BUFFER, (indices.capacity()*2), indices, Gdx.gl.GL_STATIC_DRAW); + Gdx.gl.glBindBuffer(Gdx.gl.GL_ELEMENT_ARRAY_BUFFER, 0); } public static void bindIndices(){ - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, bufferIndex); + Gdx.gl.glBindBuffer(Gdx.gl.GL_ELEMENT_ARRAY_BUFFER, bufferIndex); } public static void releaseIndices(){ - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); + Gdx.gl.glBindBuffer(Gdx.gl.GL_ELEMENT_ARRAY_BUFFER, 0); } public static ShortBuffer getIndices( int size ) { diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Renderbuffer.java b/SPD-classes/src/main/java/com/watabou/glwrap/Renderbuffer.java index c78e6036c..f91befb3a 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Renderbuffer.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Renderbuffer.java @@ -21,20 +21,18 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; public class Renderbuffer { - public static final int RGBA8 = GLES20.GL_RGBA; // ? - public static final int DEPTH16 = GLES20.GL_DEPTH_COMPONENT16; - public static final int STENCIL8 = GLES20.GL_STENCIL_INDEX8; + public static final int RGBA8 = Gdx.gl.GL_RGBA; // ? + public static final int DEPTH16 = Gdx.gl.GL_DEPTH_COMPONENT16; + public static final int STENCIL8 = Gdx.gl.GL_STENCIL_INDEX8; private int id; public Renderbuffer() { - int[] buffers = new int[1]; - GLES20.glGenRenderbuffers( 1, buffers, 0 ); - id = buffers[0]; + id = Gdx.gl.glGenRenderbuffer(); } public int id() { @@ -42,15 +40,14 @@ public class Renderbuffer { } public void bind() { - GLES20.glBindRenderbuffer( GLES20.GL_RENDERBUFFER, id ); + Gdx.gl.glBindRenderbuffer( Gdx.gl.GL_RENDERBUFFER, id ); } public void delete() { - int[] buffers = {id}; - GLES20.glDeleteRenderbuffers( 1, buffers, 0 ); + Gdx.gl.glDeleteRenderbuffer( id ); } public void storage( int format, int width, int height ) { - GLES20.glRenderbufferStorage( GLES20.GL_RENDERBUFFER, format , width, height ); + Gdx.gl.glRenderbufferStorage( Gdx.gl.GL_RENDERBUFFER, format , width, height ); } } diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/ScreenConfigChooser.java b/SPD-classes/src/main/java/com/watabou/glwrap/ScreenConfigChooser.java deleted file mode 100644 index 861d65884..000000000 --- a/SPD-classes/src/main/java/com/watabou/glwrap/ScreenConfigChooser.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Pixel Dungeon - * Copyright (C) 2012-2015 Oleg Dolya - * - * Shattered Pixel Dungeon - * Copyright (C) 2014-2019 Evan Debenham - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - */ - -package com.watabou.glwrap; - -import android.opengl.GLSurfaceView; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLDisplay; - -public class ScreenConfigChooser implements GLSurfaceView.EGLConfigChooser { - - //array of corresponding EGL attributes for each array index - private int[] attribEGLconsts = new int[]{ - EGL10.EGL_RED_SIZE, - EGL10.EGL_GREEN_SIZE, - EGL10.EGL_BLUE_SIZE, - EGL10.EGL_ALPHA_SIZE, - EGL10.EGL_DEPTH_SIZE, - EGL10.EGL_STENCIL_SIZE - }; - - private int[] desiredAttribVals = new int[attribEGLconsts.length]; //desired attribute values - private int[] attribPrefs = new int[attribEGLconsts.length]; //attribute preferences types - private int[] prefWeights = new int[attribEGLconsts.length]; //weights for preferences - - //attributes with this preference are ignored - public static final int DONT_CARE = 0; - - //attributes with this preference must be present in the config at exactly the given value - public static final int EXACTLY = 1; - - //attributes with this preference must be present in the config with at least the given value - // In the case of multiple valid configs, chooser will prefer lower values for these attributes - public static final int PREF_LOW = 2; - - //attributes with this preference must be present in the config with at least the given value - // In the case of multiple valid configs, chooser will prefer higher values for these attributes - public static final int PREF_HIGH = 3; - - - private EGL10 egl; - private EGLDisplay display; - - public ScreenConfigChooser(){ - this( false ); - } - - public ScreenConfigChooser( boolean depth ){ - this( false, depth ); - } - - //helper constructor for a basic config with or without depth - //and whether or not to prefer RGB565 for performance reasons - //On many devices RGB565 gives slightly better performance for a minimal quality tradeoff. - public ScreenConfigChooser( boolean prefRGB565, boolean depth ){ - this( - new int[]{ 5 , 6 , 5 , 0 , depth ? 16 : 0, 0 } , - prefRGB565 ? - new int[]{ PREF_LOW , PREF_LOW , PREF_LOW , EXACTLY , PREF_LOW , PREF_LOW } : - new int[]{ PREF_HIGH, PREF_HIGH, PREF_HIGH, EXACTLY , PREF_LOW , PREF_LOW }, - new int[]{ 2 , 2 , 2 , 1 , 1 , 1 } - ); - } - - public ScreenConfigChooser( int[] vals, int[] prefs, int[] weights){ - if (vals.length != desiredAttribVals.length - || prefs.length != attribPrefs.length - || weights.length != prefWeights.length) - throw new IllegalArgumentException("incorrect array lengths!"); - - desiredAttribVals = vals; - attribPrefs = prefs; - prefWeights = weights; - } - - private int[] eglPrefs = new int[]{ - EGL10.EGL_RENDERABLE_TYPE, 4, //same as EGL_OPENGL_ES2_BIT. config must support GLES 2.0 - EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, - EGL10.EGL_NONE - }; - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - - this.egl = egl; - this.display = display; - - int[] num = new int[1]; - if (!egl.eglChooseConfig(display, eglPrefs, null, 0, num)) { - throw new IllegalArgumentException("eglChooseConfig failed"); - } - - EGLConfig[] configs = new EGLConfig[num[0]]; - if (!egl.eglChooseConfig(display, eglPrefs, configs, num[0], num)) { - throw new IllegalArgumentException("eglChooseConfig failed"); - } - - EGLConfig config = chooseConfig(configs); - if (config == null) { - throw new IllegalArgumentException("No config chosen"); - } - return config; - - } - - private EGLConfig chooseConfig( EGLConfig[] configs ){ - EGLConfig bestConfig = null; - int bestConfigValue = Integer.MIN_VALUE; - for (EGLConfig curConfig : configs){ - - int curConfigValue = 0; - - for (int i = 0; i < attribEGLconsts.length; i++){ - int val = findConfigAttrib(curConfig, attribEGLconsts[i]); - - if (attribPrefs[i] == EXACTLY) { - - if (desiredAttribVals[i] != val) { - curConfigValue = Integer.MIN_VALUE; - break; - } - - } else if (attribPrefs[i] == PREF_HIGH) { - - if (desiredAttribVals[i] > val) { - curConfigValue = Integer.MIN_VALUE; - break; - } else { - curConfigValue += prefWeights[i]*(val - desiredAttribVals[i]); - } - - } else if (attribPrefs[i] == PREF_LOW) { - - if (desiredAttribVals[i] > val) { - curConfigValue = Integer.MIN_VALUE; - break; - } else { - curConfigValue -= prefWeights[i]*(val - desiredAttribVals[i]); - } - - } - } - - if (curConfigValue > bestConfigValue){ - bestConfigValue = curConfigValue; - bestConfig = curConfig; - } - - } - return bestConfig; - } - - private int[] value = new int[1]; - - private int findConfigAttrib(EGLConfig config, int attribute) { - - if (egl.eglGetConfigAttrib(display, config, attribute, value)) { - return value[0]; - } else { - throw new IllegalArgumentException("eglGetConfigAttrib failed"); - } - } -} diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Shader.java b/SPD-classes/src/main/java/com/watabou/glwrap/Shader.java index 597e50c82..d64da4a54 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Shader.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Shader.java @@ -21,17 +21,20 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.utils.BufferUtils; + +import java.nio.IntBuffer; public class Shader { - public static final int VERTEX = GLES20.GL_VERTEX_SHADER; - public static final int FRAGMENT = GLES20.GL_FRAGMENT_SHADER; + public static final int VERTEX = Gdx.gl.GL_VERTEX_SHADER; + public static final int FRAGMENT = Gdx.gl.GL_FRAGMENT_SHADER; private int handle; public Shader( int type ) { - handle = GLES20.glCreateShader( type ); + handle = Gdx.gl.glCreateShader( type ); } public int handle() { @@ -39,21 +42,21 @@ public class Shader { } public void source( String src ) { - GLES20.glShaderSource( handle, src ); + Gdx.gl.glShaderSource( handle, src ); } public void compile() { - GLES20.glCompileShader( handle ); - - int[] status = new int[1]; - GLES20.glGetShaderiv( handle, GLES20.GL_COMPILE_STATUS, status, 0 ); - if (status[0] == GLES20.GL_FALSE) { - throw new Error( GLES20.glGetShaderInfoLog( handle ) ); + Gdx.gl.glCompileShader( handle ); + + IntBuffer status = BufferUtils.newIntBuffer(1); + Gdx.gl.glGetShaderiv( handle, Gdx.gl.GL_COMPILE_STATUS, status); + if (status.get() == Gdx.gl.GL_FALSE) { + throw new Error( Gdx.gl.glGetShaderInfoLog( handle ) ); } } public void delete() { - GLES20.glDeleteShader( handle ); + Gdx.gl.glDeleteShader( handle ); } public static Shader createCompiled( int type, String src ) { diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Texture.java b/SPD-classes/src/main/java/com/watabou/glwrap/Texture.java index a807fe4c6..0494e1910 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Texture.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Texture.java @@ -21,9 +21,8 @@ package com.watabou.glwrap; -import android.graphics.Bitmap; -import android.opengl.GLES20; -import android.opengl.GLUtils; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Pixmap; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -31,12 +30,12 @@ import java.nio.IntBuffer; public class Texture { - public static final int NEAREST = GLES20.GL_NEAREST; - public static final int LINEAR = GLES20.GL_LINEAR; + public static final int NEAREST = Gdx.gl.GL_NEAREST; + public static final int LINEAR = Gdx.gl.GL_LINEAR; - public static final int REPEAT = GLES20.GL_REPEAT; - public static final int MIRROR = GLES20.GL_MIRRORED_REPEAT; - public static final int CLAMP = GLES20.GL_CLAMP_TO_EDGE; + public static final int REPEAT = Gdx.gl.GL_REPEAT; + public static final int MIRROR = Gdx.gl.GL_MIRRORED_REPEAT; + public static final int CLAMP = Gdx.gl.GL_CLAMP_TO_EDGE; public int id = -1; private static int bound_id = 0; //id of the currently bound texture @@ -44,13 +43,11 @@ public class Texture { public boolean premultiplied = false; protected void generate(){ - int[] ids = new int[1]; - GLES20.glGenTextures( 1, ids, 0 ); - id = ids[0]; + id = Gdx.gl.glGenTexture(); } public static void activate( int index ) { - GLES20.glActiveTexture( GLES20.GL_TEXTURE0 + index ); + Gdx.gl.glActiveTexture( Gdx.gl.GL_TEXTURE0 + index ); } public void bind() { @@ -58,32 +55,42 @@ public class Texture { generate(); } if (id != bound_id) { - GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, id ); + Gdx.gl.glBindTexture( Gdx.gl.GL_TEXTURE_2D, id ); bound_id = id; } } public void filter( int minMode, int maxMode ) { bind(); - GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, minMode ); - GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, maxMode ); + Gdx.gl.glTexParameterf( Gdx.gl.GL_TEXTURE_2D, Gdx.gl.GL_TEXTURE_MIN_FILTER, minMode ); + Gdx.gl.glTexParameterf( Gdx.gl.GL_TEXTURE_2D, Gdx.gl.GL_TEXTURE_MAG_FILTER, maxMode ); } public void wrap( int s, int t ) { bind(); - GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, s ); - GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, t ); + Gdx.gl.glTexParameterf( Gdx.gl.GL_TEXTURE_2D, Gdx.gl.GL_TEXTURE_WRAP_S, s ); + Gdx.gl.glTexParameterf( Gdx.gl.GL_TEXTURE_2D, Gdx.gl.GL_TEXTURE_WRAP_T, t ); } public void delete() { if (bound_id == id) bound_id = 0; - int[] ids = {id}; - GLES20.glDeleteTextures( 1, ids, 0 ); + Gdx.gl.glDeleteTexture( id ); } - public void bitmap( Bitmap bitmap ) { + public void bitmap( Pixmap pixmap ) { bind(); - GLUtils.texImage2D( GLES20.GL_TEXTURE_2D, 0, bitmap, 0 ); + + Gdx.gl.glTexImage2D( + Gdx.gl.GL_TEXTURE_2D, + 0, + pixmap.getGLInternalFormat(), + pixmap.getWidth(), + pixmap.getHeight(), + 0, + pixmap.getGLFormat(), + pixmap.getGLType(), + pixmap.getPixels() + ); premultiplied = true; } @@ -99,15 +106,15 @@ public class Texture { imageBuffer.put( pixels ); imageBuffer.position( 0 ); - GLES20.glTexImage2D( - GLES20.GL_TEXTURE_2D, + Gdx.gl.glTexImage2D( + Gdx.gl.GL_TEXTURE_2D, 0, - GLES20.GL_RGBA, + Gdx.gl.GL_RGBA, w, h, 0, - GLES20.GL_RGBA, - GLES20.GL_UNSIGNED_BYTE, + Gdx.gl.GL_RGBA, + Gdx.gl.GL_UNSIGNED_BYTE, imageBuffer ); } @@ -121,23 +128,24 @@ public class Texture { imageBuffer.put( pixels ); imageBuffer.position( 0 ); - GLES20.glPixelStorei( GLES20.GL_UNPACK_ALIGNMENT, 1 ); + Gdx.gl.glPixelStorei( Gdx.gl.GL_UNPACK_ALIGNMENT, 1 ); - GLES20.glTexImage2D( - GLES20.GL_TEXTURE_2D, + Gdx.gl.glTexImage2D( + Gdx.gl.GL_TEXTURE_2D, 0, - GLES20.GL_ALPHA, + Gdx.gl.GL_ALPHA, w, h, 0, - GLES20.GL_ALPHA, - GLES20.GL_UNSIGNED_BYTE, + Gdx.gl.GL_ALPHA, + Gdx.gl.GL_UNSIGNED_BYTE, imageBuffer ); } // If getConfig returns null (unsupported format?), GLUtils.texImage2D works // incorrectly. In this case we need to load pixels manually - public void handMade( Bitmap bitmap, boolean recode ) { + //TODO this seems to be unused, and is dependant on android code, remove? + /*public void handMade( Bitmap bitmap, boolean recode ) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); @@ -159,11 +167,11 @@ public class Texture { pixels( w, h, pixels ); premultiplied = false; - } + }*/ - public static Texture create( Bitmap bmp ) { + public static Texture create( Pixmap pix ) { Texture tex = new Texture(); - tex.bitmap( bmp ); + tex.bitmap( pix ); return tex; } diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Uniform.java b/SPD-classes/src/main/java/com/watabou/glwrap/Uniform.java index f67727824..09e89de70 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Uniform.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Uniform.java @@ -21,7 +21,7 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; public class Uniform { @@ -36,30 +36,30 @@ public class Uniform { } public void enable() { - GLES20.glEnableVertexAttribArray(location); + Gdx.gl.glEnableVertexAttribArray(location); } public void disable() { - GLES20.glDisableVertexAttribArray(location); + Gdx.gl.glDisableVertexAttribArray(location); } public void value1f(float value) { - GLES20.glUniform1f(location, value); + Gdx.gl.glUniform1f(location, value); } public void value2f(float v1, float v2) { - GLES20.glUniform2f(location, v1, v2); + Gdx.gl.glUniform2f(location, v1, v2); } public void value4f(float v1, float v2, float v3, float v4) { - GLES20.glUniform4f(location, v1, v2, v3, v4); + Gdx.gl.glUniform4f(location, v1, v2, v3, v4); } public void valueM3(float[] value) { - GLES20.glUniformMatrix3fv(location, 1, false, value, 0); + Gdx.gl.glUniformMatrix3fv(location, 1, false, value, 0); } public void valueM4(float[] value) { - GLES20.glUniformMatrix4fv(location, 1, false, value, 0); + Gdx.gl.glUniformMatrix4fv(location, 1, false, value, 0); } } \ No newline at end of file diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Vertexbuffer.java b/SPD-classes/src/main/java/com/watabou/glwrap/Vertexbuffer.java index 7e743ccb6..cfff541bc 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Vertexbuffer.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Vertexbuffer.java @@ -21,7 +21,7 @@ package com.watabou.glwrap; -import android.opengl.GLES20; +import com.badlogic.gdx.Gdx; import java.nio.FloatBuffer; import java.util.ArrayList; @@ -36,9 +36,7 @@ public class Vertexbuffer { public Vertexbuffer( FloatBuffer vertices ) { synchronized (buffers) { - int[] ptr = new int[1]; - GLES20.glGenBuffers(1, ptr, 0); - id = ptr[0]; + id = Gdx.gl.glGenBuffer(); this.vertices = vertices; buffers.add(this); @@ -80,9 +78,9 @@ public class Vertexbuffer { bind(); if (updateStart == 0 && updateEnd == vertices.limit()){ - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.limit()*4, vertices, GLES20.GL_DYNAMIC_DRAW); + Gdx.gl.glBufferData(Gdx.gl.GL_ARRAY_BUFFER, vertices.limit()*4, vertices, Gdx.gl.GL_DYNAMIC_DRAW); } else { - GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, updateStart*4, (updateEnd - updateStart)*4, vertices); + Gdx.gl.glBufferSubData(Gdx.gl.GL_ARRAY_BUFFER, updateStart*4, (updateEnd - updateStart)*4, vertices); } release(); @@ -90,16 +88,16 @@ public class Vertexbuffer { } public void bind(){ - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, id); + Gdx.gl.glBindBuffer(Gdx.gl.GL_ARRAY_BUFFER, id); } public void release(){ - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); + Gdx.gl.glBindBuffer(Gdx.gl.GL_ARRAY_BUFFER, 0); } public void delete(){ synchronized (buffers) { - GLES20.glDeleteBuffers(1, new int[]{id}, 0); + Gdx.gl.glDeleteBuffer( id ); buffers.remove(this); } } diff --git a/SPD-classes/src/main/java/com/watabou/input/InputHandler.java b/SPD-classes/src/main/java/com/watabou/input/InputHandler.java new file mode 100644 index 000000000..1a7df7b40 --- /dev/null +++ b/SPD-classes/src/main/java/com/watabou/input/InputHandler.java @@ -0,0 +1,120 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.watabou.input; + +import com.badlogic.gdx.InputAdapter; +import com.watabou.noosa.Game; + +import java.util.ArrayList; + +public class InputHandler extends InputAdapter { + + // Accumulated touch events + protected ArrayList touchEvents = new ArrayList<>(); + + // Accumulated key events + protected ArrayList keyEvents = new ArrayList<>(); + + @Override + public boolean keyDown( int keyCode ) { + + if (keyCode != Keys.BACK && + keyCode != Keys.MENU) { + return false; + } + + synchronized (keyEvents) { + keyEvents.add( new Keys.Key(keyCode, true) ); + } + return true; + } + + @Override + public boolean keyUp( int keyCode ) { + + if (keyCode != Keys.BACK && + keyCode != Keys.MENU) { + return false; + } + + synchronized (keyEvents) { + keyEvents.add( new Keys.Key(keyCode, false) ); + } + return true; + } + + @Override + public boolean keyTyped(char character) { + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + screenX /= (Game.dispWidth / (float)Game.width); + screenY /= (Game.dispHeight / (float)Game.height); + synchronized (touchEvents) { + touchEvents.add(new Touchscreen.Touch(screenX, screenY, pointer, true)); + } + return true; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + screenX /= (Game.dispWidth / (float)Game.width); + screenY /= (Game.dispHeight / (float)Game.height); + synchronized (touchEvents) { + touchEvents.add(new Touchscreen.Touch(screenX, screenY, pointer, false)); + } + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + screenX /= (Game.dispWidth / (float)Game.width); + screenY /= (Game.dispHeight / (float)Game.height); + synchronized (touchEvents) { + touchEvents.add(new Touchscreen.Touch(screenX, screenY, pointer, true)); + } + return true; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + return false; + } + + @Override + public boolean scrolled(int amount) { + return false; + } + + public void processAllEvents(){ + synchronized (touchEvents) { + Touchscreen.processTouchEvents( touchEvents ); + touchEvents.clear(); + } + synchronized (keyEvents) { + Keys.processKeyEvents( keyEvents ); + keyEvents.clear(); + } + } +} diff --git a/SPD-classes/src/main/java/com/watabou/input/Keys.java b/SPD-classes/src/main/java/com/watabou/input/Keys.java index a078a3df3..f3a373e66 100644 --- a/SPD-classes/src/main/java/com/watabou/input/Keys.java +++ b/SPD-classes/src/main/java/com/watabou/input/Keys.java @@ -21,34 +21,22 @@ package com.watabou.input; -import android.view.KeyEvent; - +import com.badlogic.gdx.Input; import com.watabou.utils.Signal; import java.util.ArrayList; +//TODO probably want to merge this into a central input processor class public class Keys { - public static final int BACK = KeyEvent.KEYCODE_BACK; - public static final int MENU = KeyEvent.KEYCODE_MENU; + public static final int BACK = Input.Keys.BACK; + public static final int MENU = Input.Keys.MENU; - public static Signal event = new Signal( true ); + public static Signal event = new Signal<>( true ); - public static void processTouchEvents( ArrayList events ) { - - int size = events.size(); - for (int i=0; i < size; i++) { - - KeyEvent e = events.get( i ); - - switch (e.getAction()) { - case KeyEvent.ACTION_DOWN: - event.dispatch( new Key( e.getKeyCode(), true ) ); - break; - case KeyEvent.ACTION_UP: - event.dispatch( new Key( e.getKeyCode(), false ) ); - break; - } + public static void processKeyEvents( ArrayList events ){ + for (Key k : events){ + event.dispatch(k); } } diff --git a/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java b/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java index 64a136cff..c8101b513 100644 --- a/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java +++ b/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java @@ -21,71 +21,38 @@ package com.watabou.input; -import android.view.MotionEvent; - -import com.watabou.noosa.Game; import com.watabou.utils.PointF; import com.watabou.utils.Signal; import java.util.ArrayList; import java.util.HashMap; +//TODO integrate into a central input handler class public class Touchscreen { - public static Signal event = new Signal( true ); + public static Signal event = new Signal<>( true ); - public static HashMap pointers = new HashMap(); + public static HashMap pointers = new HashMap<>(); - public static float x; - public static float y; - public static boolean touched; - - public static void processTouchEvents( ArrayList events ) { - - int size = events.size(); - for (int i=0; i < size; i++) { - - MotionEvent e = events.get( i ); - Touch touch; - - switch (e.getAction() & MotionEvent.ACTION_MASK) { - - case MotionEvent.ACTION_DOWN: - touched = true; - touch = new Touch( e, 0 ); - pointers.put( e.getPointerId( 0 ), touch ); - event.dispatch( touch ); - break; - - case MotionEvent.ACTION_POINTER_DOWN: - int index = e.getActionIndex(); - touch = new Touch( e, index ); - pointers.put( e.getPointerId( index ), touch ); - event.dispatch( touch ); - break; - - case MotionEvent.ACTION_MOVE: - int count = e.getPointerCount(); - for (int j=0; j < count; j++) { - if (pointers.containsKey(e.getPointerId(j))) { - pointers.get(e.getPointerId(j)).update(e, j); - } + public static void processTouchEvents( ArrayList events ) { + for (Touch t : events){ + if (pointers.containsKey(t.id)){ + Touch existing = pointers.get(t.id); + existing.current = t.current; + if (existing.down == t.down){ + event.dispatch( null ); + } else if (t.down) { + event.dispatch( existing ); + } else { + pointers.remove(existing.id); + event.dispatch(existing.up()); } - event.dispatch( null ); - break; - - case MotionEvent.ACTION_POINTER_UP: - event.dispatch( pointers.remove( e.getPointerId( e.getActionIndex() ) ).up() ); - break; - - case MotionEvent.ACTION_UP: - touched = false; - event.dispatch( pointers.remove( e.getPointerId( 0 ) ).up() ); - break; - + } else { + if (t.down) { + pointers.put(t.id, t); + } + event.dispatch(t); } - - e.recycle(); } } @@ -93,29 +60,20 @@ public class Touchscreen { public PointF start; public PointF current; + public int id; public boolean down; - public Touch( MotionEvent e, int index ) { - - float x = e.getX( index ); - float y = e.getY( index ); - - x /= (Game.dispWidth / (float)Game.width); - y /= (Game.dispHeight / (float)Game.height); - - start = new PointF( x, y ); - current = new PointF( x, y ); - - down = true; + public Touch( int x, int y, int id, boolean down){ + start = current = new PointF(x, y); + this.id = id; + this.down = down; } - public void update( MotionEvent e, int index ) { - float x = e.getX( index ); - float y = e.getY( index ); - - x /= (Game.dispWidth / (float)Game.width); - y /= (Game.dispHeight / (float)Game.height); - + public void update( Touch other ){ + this.current = other.current; + } + + public void update( int x, int y ){ current.set( x, y ); } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java b/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java index 684a57bff..6306a9e8d 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java @@ -21,8 +21,7 @@ package com.watabou.noosa; -import android.graphics.Bitmap; - +import com.badlogic.gdx.graphics.Pixmap; import com.watabou.gltextures.SmartTexture; import com.watabou.gltextures.TextureCache; import com.watabou.glwrap.Matrix; @@ -264,8 +263,8 @@ public class BitmapText extends Visual { lineHeight = baseLine = height; } - protected void splitBy( Bitmap bitmap, int height, int color, String chars ) { - + protected void splitBy( Pixmap bitmap, int height, int color, String chars ) { + int length = chars.length(); int width = bitmap.getWidth(); @@ -302,7 +301,7 @@ public class BitmapText extends Visual { } found = false; for (int j=line; j < line + height; j++) { - if (bitmap.getPixel( separator, j ) != color) { + if (colorNotMatch( bitmap, separator, j, color)) { found = true; break; } @@ -320,7 +319,7 @@ public class BitmapText extends Visual { } found = true; for (int j=line; j < line + height; j++) { - if (bitmap.getPixel( separator, j ) != color) { + if (colorNotMatch( bitmap, separator, j, color)) { found = false; break; } @@ -335,13 +334,22 @@ public class BitmapText extends Visual { lineHeight = baseLine = height( frames.get( chars.charAt( 0 ) ) ); } - public static Font colorMarked( Bitmap bmp, int color, String chars ) { + //FIXME + private boolean colorNotMatch(Pixmap pixmap, int x, int y, int color) { + int pixel = pixmap.getPixel(x, y); + if ((pixel & 0xFF) == 0) { + return color != 0; + } + return pixel != color; + } + + public static Font colorMarked( Pixmap bmp, int color, String chars ) { Font font = new Font( TextureCache.get( bmp ) ); font.splitBy( bmp, bmp.getHeight(), color, chars ); return font; } - public static Font colorMarked( Bitmap bmp, int height, int color, String chars ) { + public static Font colorMarked( Pixmap bmp, int height, int color, String chars ) { Font font = new Font( TextureCache.get( bmp ) ); font.splitBy( bmp, height, color, chars ); return font; diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Game.java b/SPD-classes/src/main/java/com/watabou/noosa/Game.java index 1331477f7..36503d128 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Game.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Game.java @@ -21,42 +21,30 @@ package com.watabou.noosa; -import android.annotation.SuppressLint; -import android.app.Activity; import android.content.pm.PackageManager.NameNotFoundException; -import android.media.AudioManager; -import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; -import android.os.Vibrator; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.View; +import com.badlogic.gdx.ApplicationListener; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.backends.android.AndroidApplication; +import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; import com.watabou.glscripts.Script; import com.watabou.gltextures.TextureCache; import com.watabou.glwrap.Blending; -import com.watabou.glwrap.ScreenConfigChooser; import com.watabou.glwrap.Vertexbuffer; +import com.watabou.input.InputHandler; import com.watabou.input.Keys; -import com.watabou.input.Touchscreen; import com.watabou.noosa.audio.Music; -import com.watabou.noosa.audio.Sample; -import com.watabou.utils.BitmapCache; -import com.watabou.utils.DeviceCompat; import com.watabou.utils.SystemTime; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.ArrayList; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTouchListener { +public class Game extends AndroidApplication implements ApplicationListener { public static Game instance; @@ -95,13 +83,9 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou public static float timeTotal = 0f; protected GLSurfaceView view; - protected SurfaceHolder holder; + //protected SurfaceHolder holder; - // Accumulated touch events - protected ArrayList motionEvents = new ArrayList(); - - // Accumulated key events - protected ArrayList keysEvents = new ArrayList(); + protected InputHandler inputHandler; public Game( Class c ) { super(); @@ -112,17 +96,9 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou protected void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); - BitmapCache.context = TextureCache.context = instance = this; - - DisplayMetrics m = new DisplayMetrics(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) - getWindowManager().getDefaultDisplay().getRealMetrics( m ); - else - getWindowManager().getDefaultDisplay().getMetrics( m ); - density = m.density; - dispHeight = m.heightPixels; - dispWidth = m.widthPixels; - + instance = this; + + //FIXME this should be moved into a separate class, once we start to move to multiplatform try { version = getPackageManager().getPackageInfo( getPackageName(), 0 ).versionName; } catch (NameNotFoundException e) { @@ -134,20 +110,33 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou versionCode = 0; } - setVolumeControlStream( AudioManager.STREAM_MUSIC ); + AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); + config.depth = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + //use rgb888 on more modern devices for better visuals + config.r = config.g = config.b = 8; + } else { + //and rgb565 (default) on older ones for better performance + } - view = new GLSurfaceView( this ); - view.setEGLContextClientVersion( 2 ); - - //Older devices are forced to RGB 565 for performance reasons. - //Otherwise try to use RGB888 for best quality, but use RGB565 if it is what's available. - view.setEGLConfigChooser( new ScreenConfigChooser( - DeviceCompat.legacyDevice(), - false )); - - view.setRenderer( this ); - view.setOnTouchListener( this ); - setContentView( view ); + config.useCompass = false; + config.useAccelerometer = false; + //TODO consider the following additional options, might be better than setting manually + //config.hideStatusBar + //config.useImmersiveMode + + initialize(this, config); + + //FIXME shouldn't have a reference to the view here, remove things which access this + view = (GLSurfaceView)graphics.getView(); + + inputHandler = new InputHandler(); + Gdx.input.setInputProcessor(inputHandler); + Gdx.input.setCatchKey(Keys.BACK, true); + Gdx.input.setCatchKey(Keys.MENU, true); + + //FIXME this doesn't seem to work quite right. That might not be due to LibGDX though. + Music.setMuteListener(); //so first call to onstart/onresume calls correct logic. paused = true; @@ -155,138 +144,46 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou private boolean paused; - //Starting with honeycomb, android's lifecycle management changes slightly - - @Override - public void onStart() { - super.onStart(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ - resumeGame(); - } - } - - @Override - protected void onResume() { - super.onResume(); - - if (scene != null) { - scene.onResume(); - } - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB){ - resumeGame(); - } - } - - @Override - protected void onPause() { - super.onPause(); - - if (scene != null) { - scene.onPause(); - } - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB){ - pauseGame(); - } - } - - @Override - public void onStop() { - super.onStop(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ - pauseGame(); - } - } - - public void pauseGame(){ - if (paused) return; - - paused = true; - view.onPause(); - Script.reset(); - - Music.INSTANCE.pause(); - Sample.INSTANCE.pause(); - } - - public void resumeGame(){ - if (!paused) return; - - now = 0; - paused = false; - view.onResume(); - - Music.INSTANCE.resume(); - Sample.INSTANCE.resume(); - } - public boolean isPaused(){ return paused; } @Override - public void onDestroy() { - super.onDestroy(); - destroyGame(); + public void create() { + density = Gdx.graphics.getDensity(); + dispHeight = Gdx.graphics.getDisplayMode().height; + dispWidth = Gdx.graphics.getDisplayMode().width; - Music.INSTANCE.mute(); - Sample.INSTANCE.reset(); - } - - @SuppressLint({ "Recycle", "ClickableViewAccessibility" }) - @Override - public boolean onTouch( View view, MotionEvent event ) { - synchronized (motionEvents) { - motionEvents.add( MotionEvent.obtain( event ) ); - } - return true; + Blending.useDefault(); + + //refreshes texture and vertex data stored on the gpu + TextureCache.reload(); + RenderedText.reloadCache(); + Vertexbuffer.refreshAllBuffers(); } @Override - public boolean onKeyDown( int keyCode, KeyEvent event ) { + public void resize(int width, int height) { + Gdx.gl.glViewport(0, 0, width, height); - if (keyCode != Keys.BACK && - keyCode != Keys.MENU) { - return false; + if (height != Game.height || width != Game.width) { + + Game.width = width; + Game.height = height; + + resetScene(); } - - synchronized (motionEvents) { - keysEvents.add( event ); - } - return true; } @Override - public boolean onKeyUp( int keyCode, KeyEvent event ) { - - if (keyCode != Keys.BACK && - keyCode != Keys.MENU) { - return false; - } - - synchronized (motionEvents) { - keysEvents.add( event ); - } - return true; - } - - @Override - public void onDrawFrame( GL10 gl ) { - - if (width == 0 || height == 0) { - return; - } - + public void render() { NoosaScript.get().resetCamera(); NoosaScriptNoLighting.get().resetCamera(); - GLES20.glDisable(GLES20.GL_SCISSOR_TEST); - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + Gdx.gl.glDisable(Gdx.gl.GL_SCISSOR_TEST); + Gdx.gl.glClear(Gdx.gl.GL_COLOR_BUFFER_BIT); draw(); - GLES20.glFlush(); + Gdx.gl.glFlush(); SystemTime.tick(); long rightNow = SystemClock.elapsedRealtime(); @@ -295,29 +192,39 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou step(); } - + @Override - public void onSurfaceChanged( GL10 gl, int width, int height ) { - - GLES20.glViewport(0, 0, width, height); - - if (height != Game.height || width != Game.width) { - - Game.width = width; - Game.height = height; - - resetScene(); + public void pause() { + paused = true; + + if (scene != null) { + scene.onPause(); } + + //view.onPause(); + Script.reset(); + + //Music.INSTANCE.pause(); + //Sample.INSTANCE.pause(); } - + @Override - public void onSurfaceCreated( GL10 gl, EGLConfig config ) { - Blending.useDefault(); - - //refreshes texture and vertex data stored on the gpu - TextureCache.reload(); - RenderedText.reloadCache(); - Vertexbuffer.refreshAllBuffers(); + public void resume() { + paused = false; + + now = 0; + //view.onResume(); + + //Music.INSTANCE.resume(); + //Sample.INSTANCE.resume(); + } + + @Override + public void dispose() { + destroyGame(); + + //Music.INSTANCE.mute(); + //Sample.INSTANCE.reset(); } protected void destroyGame() { @@ -392,14 +299,7 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou Game.elapsed = Game.timeScale * step * 0.001f; Game.timeTotal += Game.elapsed; - synchronized (motionEvents) { - Touchscreen.processTouchEvents( motionEvents ); - motionEvents.clear(); - } - synchronized (keysEvents) { - Keys.processTouchEvents( keysEvents ); - keysEvents.clear(); - } + inputHandler.processAllEvents(); scene.update(); Camera.updateAll(); @@ -410,11 +310,15 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou } protected void logException( Throwable tr ){ - Log.e("GAME", Log.getStackTraceString(tr)); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + tr.printStackTrace(pw); + pw.flush(); + Gdx.app.error("GAME", sw.toString()); } public static void vibrate( int milliseconds ) { - ((Vibrator)instance.getSystemService( VIBRATOR_SERVICE )).vibrate( milliseconds ); + Gdx.input.vibrate(milliseconds); } public interface SceneChangeCallback{ diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Halo.java b/SPD-classes/src/main/java/com/watabou/noosa/Halo.java index 1e1da5974..57c6eb005 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Halo.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Halo.java @@ -21,10 +21,7 @@ package com.watabou.noosa; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; - +import com.badlogic.gdx.graphics.Pixmap; import com.watabou.gltextures.SmartTexture; import com.watabou.gltextures.TextureCache; @@ -41,14 +38,12 @@ public class Halo extends Image { super(); if (!TextureCache.contains( CACHE_KEY )) { - Bitmap bmp = Bitmap.createBitmap( RADIUS * 2, RADIUS * 2, Bitmap.Config.ARGB_8888 ); - Canvas canvas = new Canvas( bmp ); - Paint paint = new Paint(); - paint.setColor( 0x0AFFFFFF ); + Pixmap pixmap = new Pixmap(RADIUS * 2, RADIUS * 2, Pixmap.Format.RGBA8888); + pixmap.setColor( 0xFFFFFF0A ); for (int i = 0; i < 50; i++) { - canvas.drawCircle(RADIUS, RADIUS, RADIUS * (i+1)/50f, paint); + pixmap.fillCircle(RADIUS, RADIUS, (int)(RADIUS * (i+1)/50f)); } - TextureCache.add( CACHE_KEY, new SmartTexture( bmp ) ); + TextureCache.add( CACHE_KEY, new SmartTexture( pixmap ) ); } texture( CACHE_KEY ); diff --git a/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java b/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java index e36f883bc..d0b90758e 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java @@ -21,8 +21,7 @@ package com.watabou.noosa; -import android.opengl.GLES20; - +import com.badlogic.gdx.Gdx; import com.watabou.glscripts.Script; import com.watabou.glwrap.Attribute; import com.watabou.glwrap.Quad; @@ -81,7 +80,7 @@ public class NoosaScript extends Script { aUV.vertexPointer( 2, 4, vertices ); Quad.releaseIndices(); - GLES20.glDrawElements( GLES20.GL_TRIANGLES, size, GLES20.GL_UNSIGNED_SHORT, indices ); + Gdx.gl20.glDrawElements( Gdx.gl20.GL_TRIANGLES, size, Gdx.gl20.GL_UNSIGNED_SHORT, indices ); Quad.bindIndices(); } @@ -92,8 +91,8 @@ public class NoosaScript extends Script { vertices.position( 2 ); aUV.vertexPointer( 2, 4, vertices ); - - GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE, GLES20.GL_UNSIGNED_SHORT, 0 ); + + Gdx.gl20.glDrawElements( Gdx.gl20.GL_TRIANGLES, Quad.SIZE, Gdx.gl20.GL_UNSIGNED_SHORT, 0 ); } public void drawQuad( Vertexbuffer buffer ) { @@ -106,8 +105,8 @@ public class NoosaScript extends Script { aUV.vertexBuffer( 2, 4, 2 ); buffer.release(); - - GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE, GLES20.GL_UNSIGNED_SHORT, 0 ); + + Gdx.gl20.glDrawElements( Gdx.gl20.GL_TRIANGLES, Quad.SIZE, Gdx.gl20.GL_UNSIGNED_SHORT, 0 ); } public void drawQuadSet( FloatBuffer vertices, int size ) { @@ -121,8 +120,8 @@ public class NoosaScript extends Script { vertices.position( 2 ); aUV.vertexPointer( 2, 4, vertices ); - - GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE * size, GLES20.GL_UNSIGNED_SHORT, 0 ); + + Gdx.gl20.glDrawElements( Gdx.gl20.GL_TRIANGLES, Quad.SIZE * size, Gdx.gl20.GL_UNSIGNED_SHORT, 0 ); } public void drawQuadSet( Vertexbuffer buffer, int length, int offset ){ @@ -139,8 +138,8 @@ public class NoosaScript extends Script { aUV.vertexBuffer( 2, 4, 2 ); buffer.release(); - - GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE * length, GLES20.GL_UNSIGNED_SHORT, Quad.SIZE * Short.SIZE/8 * offset ); + + Gdx.gl20.glDrawElements( Gdx.gl20.GL_TRIANGLES, Quad.SIZE * length, Gdx.gl20.GL_UNSIGNED_SHORT, Quad.SIZE * Short.SIZE/8 * offset ); } public void lighting( float rm, float gm, float bm, float am, float ra, float ga, float ba, float aa ) { @@ -161,14 +160,14 @@ public class NoosaScript extends Script { uCamera.valueM4( camera.matrix ); if (!camera.fullScreen) { - GLES20.glEnable( GLES20.GL_SCISSOR_TEST ); - GLES20.glScissor( + Gdx.gl20.glEnable( Gdx.gl20.GL_SCISSOR_TEST ); + Gdx.gl20.glScissor( camera.x, Game.height - camera.screenHeight - camera.y, camera.screenWidth, camera.screenHeight); } else { - GLES20.glDisable( GLES20.GL_SCISSOR_TEST ); + Gdx.gl20.glDisable( Gdx.gl20.GL_SCISSOR_TEST ); } } } @@ -184,23 +183,34 @@ public class NoosaScript extends Script { private static final String SHADER = - "uniform mat4 uCamera;" + - "uniform mat4 uModel;" + - "attribute vec4 aXYZW;" + - "attribute vec2 aUV;" + - "varying vec2 vUV;" + - "void main() {" + - " gl_Position = uCamera * uModel * aXYZW;" + - " vUV = aUV;" + - "}" + + //vertex shader + "uniform mat4 uCamera;\n" + + "uniform mat4 uModel;\n" + + "attribute vec4 aXYZW;\n" + + "attribute vec2 aUV;\n" + + "varying vec2 vUV;\n" + + "void main() {\n" + + " gl_Position = uCamera * uModel * aXYZW;\n" + + " vUV = aUV;\n" + + "}\n" + + //this symbol separates the vertex and fragment shaders (see Script.compile) "//\n" + - - "varying mediump vec2 vUV;" + - "uniform lowp sampler2D uTex;" + - "uniform lowp vec4 uColorM;" + - "uniform lowp vec4 uColorA;" + - "void main() {" + - " gl_FragColor = texture2D( uTex, vUV ) * uColorM + uColorA;" + - "}"; + + //fragment shader + //preprocessor directives let us define precision on GLES platforms, and ignore it elsewhere + "#ifdef GL_ES\n" + + " #define LOW lowp\n" + + " #define MED mediump\n" + + "#else\n" + + " #define LOW\n" + + " #define MED\n" + + "#endif\n" + + "varying MED vec2 vUV;\n" + + "uniform LOW sampler2D uTex;\n" + + "uniform LOW vec4 uColorM;\n" + + "uniform LOW vec4 uColorA;\n" + + "void main() {\n" + + " gl_FragColor = texture2D( uTex, vUV ) * uColorM + uColorA;\n" + + "}\n"; } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/NoosaScriptNoLighting.java b/SPD-classes/src/main/java/com/watabou/noosa/NoosaScriptNoLighting.java index 802236adf..6349c67b2 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/NoosaScriptNoLighting.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/NoosaScriptNoLighting.java @@ -45,22 +45,33 @@ public class NoosaScriptNoLighting extends NoosaScript { } private static final String SHADER = - - "uniform mat4 uCamera;" + - "uniform mat4 uModel;" + - "attribute vec4 aXYZW;" + - "attribute vec2 aUV;" + - "varying vec2 vUV;" + - "void main() {" + - " gl_Position = uCamera * uModel * aXYZW;" + - " vUV = aUV;" + - "}" + - - "//\n" + - - "varying mediump vec2 vUV;" + - "uniform lowp sampler2D uTex;" + - "void main() {" + - " gl_FragColor = texture2D( uTex, vUV );" + - "}"; + + //vertex shader + "uniform mat4 uCamera;\n" + + "uniform mat4 uModel;\n" + + "attribute vec4 aXYZW;\n" + + "attribute vec2 aUV;\n" + + "varying vec2 vUV;\n" + + "void main() {\n" + + " gl_Position = uCamera * uModel * aXYZW;\n" + + " vUV = aUV;\n" + + "}\n" + + + //this symbol separates the vertex and fragment shaders (see Script.compile) + "//\n" + + + //fragment shader + //preprocessor directives let us define precision on GLES platforms, and ignore it elsewhere + "#ifdef GL_ES\n" + + " #define LOW lowp\n" + + " #define MED mediump\n" + + "#else\n" + + " #define LOW\n" + + " #define MED\n" + + "#endif\n" + + "varying MED vec2 vUV;\n" + + "uniform LOW sampler2D uTex;\n" + + "void main() {\n" + + " gl_FragColor = texture2D( uTex, vUV );\n" + + "}\n"; } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/RenderedText.java b/SPD-classes/src/main/java/com/watabou/noosa/RenderedText.java index e2bad0b3e..119ba1969 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/RenderedText.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/RenderedText.java @@ -26,6 +26,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; +import com.badlogic.gdx.graphics.Pixmap; import com.watabou.gltextures.SmartTexture; import com.watabou.glwrap.Matrix; import com.watabou.glwrap.Texture; @@ -169,7 +170,18 @@ public class RenderedText extends Image { canvas.drawText(r.text, (r.size/10f), r.size, painter); - r.texture = new SmartTexture(bitmap, Texture.NEAREST, Texture.CLAMP, true); + //FIXME really ugly and slow conversion between android bitmap and gdx pixmap + int[] pixels = new int[bitmap.getWidth()*bitmap.getHeight()]; + bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight()); + // Convert from ARGB to RGBA + for (int i = 0; i< pixels.length; i++) { + int pixel = pixels[i]; + pixels[i] = (pixel << 8) | ((pixel >> 24) & 0xFF); + } + Pixmap pixmap = new Pixmap(bitmap.getWidth(), bitmap.getHeight(), Pixmap.Format.RGBA8888); + pixmap.getPixels().asIntBuffer().put(pixels); + r.texture = new SmartTexture(pixmap, Texture.NEAREST, Texture.CLAMP, true); + bitmap.recycle(); RectF rect = r.texture.uvRect(0, 0, r.width, r.height); r.frame(rect); diff --git a/SPD-classes/src/main/java/com/watabou/noosa/audio/Music.java b/SPD-classes/src/main/java/com/watabou/noosa/audio/Music.java index b39cedd4e..b48553c5a 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/audio/Music.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/audio/Music.java @@ -22,20 +22,18 @@ package com.watabou.noosa.audio; import android.app.Activity; -import android.content.res.AssetFileDescriptor; -import android.media.AudioManager; -import android.media.MediaPlayer; import android.os.Build; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; +import com.badlogic.gdx.Gdx; import com.watabou.noosa.Game; public enum Music { INSTANCE; - private MediaPlayer player; + private com.badlogic.gdx.audio.Music player; private String lastPlayed; private boolean looping; @@ -58,25 +56,11 @@ public enum Music { return; } - try { - - AssetFileDescriptor afd = Game.instance.getAssets().openFd( assetName ); - - MediaPlayer mp = new MediaPlayer(); - mp.setAudioStreamType( AudioManager.STREAM_MUSIC ); - mp.setDataSource( afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength() ); - mp.prepare(); - player = mp; - player.start(); - player.setLooping(looping); - player.setVolume(volume, volume); - - } catch (Exception e) { - - Game.reportException(e); - player = null; - - } + player = Gdx.audio.newMusic(Gdx.files.internal(assetName)); + player.setLooping(looping); + player.setVolume(volume); + player.play(); + } public void mute() { @@ -92,19 +76,15 @@ public enum Music { public void resume() { if (player != null) { - player.start(); + player.play(); player.setLooping(looping); } } public void stop() { if (player != null) { - try { - player.stop(); - player.release(); - } catch ( Exception e ){ - Game.reportException(e); - } + player.stop(); + player.dispose(); player = null; } } @@ -112,7 +92,7 @@ public enum Music { public void volume( float value ) { volume = value; if (player != null) { - player.setVolume( value, value ); + player.setVolume( value ); } } @@ -134,30 +114,29 @@ public enum Music { return enabled; } - public static final PhoneStateListener callMute = new PhoneStateListener(){ - - @Override - public void onCallStateChanged(int state, String incomingNumber) - { - if( state == TelephonyManager.CALL_STATE_RINGING ) { - INSTANCE.pause(); - - } else if( state == TelephonyManager.CALL_STATE_IDLE ) { - if (!Game.instance.isPaused()) { - INSTANCE.resume(); - } - } - - super.onCallStateChanged(state, incomingNumber); - } - }; - + //FIXME android-specific code, that is also broken by being part of this class. public static void setMuteListener(){ //versions lower than this require READ_PHONE_STATE permission if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { TelephonyManager mgr = (TelephonyManager) Game.instance.getSystemService(Activity.TELEPHONY_SERVICE); - mgr.listen(Music.callMute, PhoneStateListener.LISTEN_CALL_STATE); + mgr.listen(new PhoneStateListener(){ + + @Override + public void onCallStateChanged(int state, String incomingNumber) + { + if( state == TelephonyManager.CALL_STATE_RINGING ) { + INSTANCE.pause(); + + } else if( state == TelephonyManager.CALL_STATE_IDLE ) { + if (!Game.instance.isPaused()) { + INSTANCE.resume(); + } + } + + super.onCallStateChanged(state, incomingNumber); + } + }, PhoneStateListener.LISTEN_CALL_STATE); } } } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/audio/Sample.java b/SPD-classes/src/main/java/com/watabou/noosa/audio/Sample.java index 6734db16b..032f91be7 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/audio/Sample.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/audio/Sample.java @@ -21,113 +21,79 @@ package com.watabou.noosa.audio; -import android.content.res.AssetFileDescriptor; -import android.content.res.AssetManager; -import android.media.AudioManager; -import android.media.SoundPool; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.audio.Sound; -import com.watabou.noosa.Game; - -import java.io.IOException; import java.util.HashMap; -import java.util.LinkedList; -public enum Sample implements SoundPool.OnLoadCompleteListener { +public enum Sample { INSTANCE; - public static final int MAX_STREAMS = 8; - - protected SoundPool pool = - new SoundPool( MAX_STREAMS, AudioManager.STREAM_MUSIC, 0 ); - - protected HashMap ids = - new HashMap<>(); + protected HashMap ids = new HashMap<>(); private boolean enabled = true; - private float volume = 1f; - - private LinkedList loadingQueue = new LinkedList<>(); + private float globalVolume = 1f; public void reset() { + for (Sound sound : ids.values()){ + sound.dispose(); + } + ids.clear(); - loadingQueue = new LinkedList<>(); - pool.release(); - - pool = new SoundPool( MAX_STREAMS, AudioManager.STREAM_MUSIC, 0 ); - pool.setOnLoadCompleteListener( this ); } public void pause() { - if (pool != null) { - pool.autoPause(); + for (Sound sound : ids.values()) { + sound.pause(); } } public void resume() { - if (pool != null) { - pool.autoResume(); + for (Sound sound : ids.values()) { + sound.resume(); } } public void load( String... assets ) { - for (String asset : assets) { - loadingQueue.add( asset ); - } - loadNext(); - } - - private void loadNext() { - final String asset = loadingQueue.poll(); - if (asset != null) { - if (!ids.containsKey( asset )) { - try { - pool.setOnLoadCompleteListener( new SoundPool.OnLoadCompleteListener() { - @Override - public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { - loadNext(); - } - } ); - - AssetManager manager = Game.instance.getAssets(); - AssetFileDescriptor fd = manager.openFd( asset ); - int streamID = pool.load( fd, 1 ) ; - ids.put( asset, streamID ); - fd.close(); - } catch (IOException e) { - loadNext(); - } catch (NullPointerException e) { - // Do nothing (stop loading sounds) - } - } else { - loadNext(); + //FIXME there used to be a queue here so that assets were loaded async. + //This was to prevent hanging on specific android versions (implement in vanilla v1.7.5) + //Maybe LibGDX already handles this? + for (String asset : assets){ + if (!ids.containsKey(asset)){ + ids.put(asset, Gdx.audio.newSound(Gdx.files.internal(asset))); } } + } public void unload( Object src ) { - if (ids.containsKey( src )) { - - pool.unload( ids.get( src ) ); + ids.get( src ).dispose(); ids.remove( src ); } } - public int play( Object id ) { + public long play( Object id ) { return play( id, 1 ); } - public int play( Object id, float volume ) { + public long play( Object id, float volume ) { return play( id, volume, volume, 1 ); } - - public int play( Object id, float leftVolume, float rightVolume, float rate ) { + + public long play( Object id, float volume, float pitch ) { + return play( id, volume, volume, pitch ); + } + + public long play( Object id, float leftVolume, float rightVolume, float pitch ) { + float volume = Math.max(leftVolume, rightVolume); + float pan = rightVolume - leftVolume; if (enabled && ids.containsKey( id )) { - return pool.play( ids.get( id ), leftVolume*volume, rightVolume*volume, 0, 0, rate ); + return ids.get(id).play( globalVolume*volume, pitch, pan ); } else { return -1; } @@ -138,14 +104,11 @@ public enum Sample implements SoundPool.OnLoadCompleteListener { } public void volume( float value ) { - this.volume = value; + globalVolume = value; } public boolean isEnabled() { return enabled; } - - @Override - public void onLoadComplete( SoundPool soundPool, int sampleId, int status ) { - } + } \ No newline at end of file diff --git a/SPD-classes/src/main/java/com/watabou/utils/BitmapCache.java b/SPD-classes/src/main/java/com/watabou/utils/BitmapCache.java index db4e92f0a..b9faa5062 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/BitmapCache.java +++ b/SPD-classes/src/main/java/com/watabou/utils/BitmapCache.java @@ -21,12 +21,10 @@ package com.watabou.utils; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Pixmap; +import com.watabou.noosa.Game; -import java.io.IOException; -import java.io.InputStream; import java.util.HashMap; public class BitmapCache { @@ -35,18 +33,11 @@ public class BitmapCache { private static HashMap layers = new HashMap(); - private static BitmapFactory.Options opts = new BitmapFactory.Options(); - static { - opts.inDither = false; - } - - public static Context context; - - public static Bitmap get( String assetName ) { + public static Pixmap get( String assetName ) { return get( DEFAULT, assetName ); } - public static Bitmap get( String layerName, String assetName ) { + public static Pixmap get( String layerName, String assetName ) { Layer layer; if (!layers.containsKey( layerName )) { @@ -61,22 +52,24 @@ public class BitmapCache { } else { try { - InputStream stream = context.getResources().getAssets().open( assetName ); - Bitmap bmp = BitmapFactory.decodeStream( stream, null, opts ); + Pixmap bmp = new Pixmap( Gdx.files.internal(assetName) ); layer.put( assetName, bmp ); return bmp; - } catch (IOException e) { + } catch (Exception e) { + Game.reportException( e ); return null; } } } - public static Bitmap get( int resID ) { + //Unused, LibGDX does not support resource Ids + /* + public static Pixmap get( int resID ) { return get( DEFAULT, resID ); } - public static Bitmap get( String layerName, int resID ) { + public static Pixmap get( String layerName, int resID ) { Layer layer; if (!layers.containsKey( layerName )) { @@ -95,7 +88,7 @@ public class BitmapCache { return bmp; } - } + }*/ public static void clear( String layerName ) { if (layers.containsKey( layerName )) { @@ -112,12 +105,12 @@ public class BitmapCache { } @SuppressWarnings("serial") - private static class Layer extends HashMap { + private static class Layer extends HashMap { @Override public void clear() { - for (Bitmap bmp:values()) { - bmp.recycle(); + for (Pixmap bmp:values()) { + bmp.dispose(); } super.clear(); } diff --git a/SPD-classes/src/main/java/com/watabou/utils/BitmapFilm.java b/SPD-classes/src/main/java/com/watabou/utils/BitmapFilm.java index 6da92e765..ed0847c32 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/BitmapFilm.java +++ b/SPD-classes/src/main/java/com/watabou/utils/BitmapFilm.java @@ -21,27 +21,26 @@ package com.watabou.utils; -import android.graphics.Bitmap; -import android.graphics.Rect; +import com.badlogic.gdx.graphics.Pixmap; import java.util.HashMap; public class BitmapFilm { - public Bitmap bitmap; + public Pixmap bitmap; protected HashMap frames = new HashMap(); - public BitmapFilm( Bitmap bitmap ) { + public BitmapFilm( Pixmap bitmap ) { this.bitmap = bitmap; add( null, new Rect( 0, 0, bitmap.getWidth(), bitmap.getHeight() ) ); } - public BitmapFilm( Bitmap bitmap, int width ) { + public BitmapFilm( Pixmap bitmap, int width ) { this( bitmap, width, bitmap.getHeight() ); } - public BitmapFilm( Bitmap bitmap, int width, int height ) { + public BitmapFilm( Pixmap bitmap, int width, int height ) { this.bitmap = bitmap; int cols = bitmap.getWidth() / width; int rows = bitmap.getHeight() / height; diff --git a/SPD-classes/src/main/java/com/watabou/utils/DeviceCompat.java b/SPD-classes/src/main/java/com/watabou/utils/DeviceCompat.java index d774b542c..d4aba8540 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/DeviceCompat.java +++ b/SPD-classes/src/main/java/com/watabou/utils/DeviceCompat.java @@ -21,22 +21,31 @@ package com.watabou.utils; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; -import android.util.Log; - +import com.badlogic.gdx.Gdx; import com.watabou.BuildConfig; -import com.watabou.noosa.Game; public class DeviceCompat { public static boolean supportsFullScreen(){ - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + switch (Gdx.app.getType()){ + case Android: + //Android 4.4 KitKat and later, this is for immersive mode + return Gdx.app.getVersion() >= 19; + default: + //TODO implement functionality for other platforms here + return false; + } } public static boolean legacyDevice(){ - return Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN; + switch (Gdx.app.getType()){ + case Android: + //Devices prior to Android 4.1 Jelly Bean + return Gdx.app.getVersion() < 16; + default: + //TODO implement functionality for other platforms here + return false; + } } public static boolean isDebug(){ @@ -44,12 +53,11 @@ public class DeviceCompat { } public static void openURI( String URI ){ - Intent intent = new Intent( Intent.ACTION_VIEW, Uri.parse( URI ) ); - Game.instance.startActivity( intent ); + Gdx.net.openURI( URI ); } public static void log( String tag, String message ){ - Log.i( tag, message ); + Gdx.app.log( tag, message ); } } diff --git a/SPD-classes/src/main/java/com/watabou/utils/GameSettings.java b/SPD-classes/src/main/java/com/watabou/utils/GameSettings.java index 911adad9e..0dfed0458 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/GameSettings.java +++ b/SPD-classes/src/main/java/com/watabou/utils/GameSettings.java @@ -21,18 +21,17 @@ package com.watabou.utils; -import android.content.SharedPreferences; -import android.os.Build; - -import com.watabou.noosa.Game; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Preferences; public class GameSettings { - private static SharedPreferences prefs; + private static Preferences prefs; - private static SharedPreferences get() { + private static Preferences get() { if (prefs == null) { - prefs = Game.instance.getPreferences( Game.MODE_PRIVATE ); + //TODO might want to rename this file. this is the auto-generated name for android atm + prefs = Gdx.app.getPreferences("ShatteredPixelDungeon"); } return prefs; } @@ -47,7 +46,7 @@ public class GameSettings { public static int getInt( String key, int defValue, int min, int max ) { try { - int i = get().getInt( key, defValue ); + int i = get().getInteger( key, defValue ); if (i < min || i > max){ int val = (int)GameMath.gate(min, i, max); put(key, val); @@ -93,15 +92,18 @@ public class GameSettings { } public static void put( String key, int value ) { - get().edit().putInt(key, value).apply(); + get().putInteger(key, value); + get().flush(); } public static void put( String key, boolean value ) { - get().edit().putBoolean(key, value).apply(); + get().putBoolean(key, value); + get().flush(); } public static void put( String key, String value ) { - get().edit().putString(key, value).apply(); + get().putString(key, value); + get().flush(); } } diff --git a/SPD-classes/src/main/java/com/watabou/utils/PointF.java b/SPD-classes/src/main/java/com/watabou/utils/PointF.java index a6db9cedc..0bf037f9d 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/PointF.java +++ b/SPD-classes/src/main/java/com/watabou/utils/PointF.java @@ -21,9 +21,6 @@ package com.watabou.utils; -import android.annotation.SuppressLint; - -@SuppressLint("FloatMath") public class PointF { public static final float PI = 3.1415926f; diff --git a/SPD-classes/src/main/java/com/watabou/utils/SparseArray.java b/SPD-classes/src/main/java/com/watabou/utils/SparseArray.java index ed0bf50aa..1d16cba4a 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/SparseArray.java +++ b/SPD-classes/src/main/java/com/watabou/utils/SparseArray.java @@ -21,26 +21,18 @@ package com.watabou.utils; -import java.util.ArrayList; +import com.badlogic.gdx.utils.IntMap; + +import java.util.Arrays; import java.util.List; -public class SparseArray extends android.util.SparseArray { +public class SparseArray extends IntMap { public int[] keyArray() { - int size = size(); - int[] array = new int[size]; - for (int i=0; i < size; i++) { - array[i] = keyAt( i ); - } - return array; + return keys().toArray().toArray(); } - public List values() { - int size = size(); - ArrayList list = new ArrayList( size ); - for (int i=0; i < size; i++) { - list.add( i, valueAt( i ) ); - } - return list; + public List toList() { + return Arrays.asList(values().toArray().toArray()); } } diff --git a/build.gradle b/build.gradle index 572e9c8a9..9f5a0e8cf 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,8 @@ allprojects { appAndroidCompileSDK = 28 appAndroidMinSDK = 9 appAndroidTargetSDK = 28 + + gdxVersion = '1.9.10' } version = appVersionName diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index e3c072529..22aca3a79 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -25,7 +25,8 @@ + android:screenOrientation="nosensor" + android:configChanges="keyboard|keyboardHidden|orientation"> diff --git a/core/src/main/assets/shadow.png b/core/src/main/assets/shadow.png index a8136567488ae6aa51f7cbf89381bc8c4237f688..71cb911d151657679ab7776b6dc7862e6b19d7c0 100644 GIT binary patch delta 43 xcmebGnxLX4=;`7ZQo)#ffc2lV!7>Il28PB%%zypajjb7gz|+;wWt~$(695%_41NFr delta 48 zcmebBpP-^G=IP=XQo)$~L}3dT5S&2VKnGBL`_CldVr?P(M7-DD zSB7+VLpEhgX7De-Lk7)2jeF1z+Ce*L$DkP~@<4jn0*tT+nBfSp!ucM2>X8~;kpCgN Th c){ switchNoFade(c, null); } @@ -231,14 +208,14 @@ public class ShatteredPixelDungeon extends Game { } @Override - public void onSurfaceChanged( GL10 gl, int width, int height ) { + public void resize( int width, int height ) { if (scene instanceof PixelScene && (height != Game.height || width != Game.width)) { ((PixelScene) scene).saveWindows(); } - super.onSurfaceChanged( gl, width, height ); + super.resize( width, height ); updateDisplaySize(); @@ -302,31 +279,42 @@ public class ShatteredPixelDungeon extends Game { } public static void updateSystemUI() { - - boolean fullscreen = Build.VERSION.SDK_INT < Build.VERSION_CODES.N - || !instance.isInMultiWindowMode(); - - if (fullscreen){ - instance.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - } else { - instance.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - } - - if (DeviceCompat.supportsFullScreen()){ - if (fullscreen && SPDSettings.fullscreen()) { - instance.getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION ); - } else { - instance.getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE ); + + instance.runOnUiThread(new Runnable() { + @SuppressLint("NewApi") + @Override + public void run() { + boolean fullscreen = Build.VERSION.SDK_INT < Build.VERSION_CODES.N + || !instance.isInMultiWindowMode(); + + if (fullscreen){ + instance.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } else { + instance.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } + + if (DeviceCompat.supportsFullScreen()){ + if (SPDSettings.fullscreen()) { + instance.getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION ); + } else { + instance.getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE ); + } + } } - } + }); } + @Override + public void resume() { + super.resume(); + updateSystemUI(); + } } \ No newline at end of file diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index 58278c3aa..c44e16016 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -398,9 +398,9 @@ public abstract class Level implements Bundlable { bundle.put( ENTRANCE, entrance ); bundle.put( EXIT, exit ); bundle.put( LOCKED, locked ); - bundle.put( HEAPS, heaps.values() ); - bundle.put( PLANTS, plants.values() ); - bundle.put( TRAPS, traps.values() ); + bundle.put( HEAPS, heaps.toList() ); + bundle.put( PLANTS, plants.toList() ); + bundle.put( TRAPS, traps.toList() ); bundle.put( CUSTOM_TILES, customTiles ); bundle.put( CUSTOM_WALLS, customWalls ); bundle.put( MOBS, mobs ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java index a01f55d5c..49f89bfdf 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -229,9 +229,8 @@ public class GameScene extends PixelScene { heaps = new Group(); add( heaps ); - int size = Dungeon.level.heaps.size(); - for (int i=0; i < size; i++) { - addHeapSprite( Dungeon.level.heaps.valueAt( i ) ); + for ( Heap heap : Dungeon.level.heaps.values() ) { + addHeapSprite( heap ); } emitters = new Group(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java index 220e783ef..4392b8c47 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java @@ -431,9 +431,9 @@ public class DungeonTileSheet { } public static int getVisualWithAlts(int visual, int pos){ - if (tileVariance[pos] >= 95 && rareAltVisuals.indexOfKey(visual) >= 0) + if (tileVariance[pos] >= 95 && rareAltVisuals.containsKey(visual)) return rareAltVisuals.get(visual); - else if (tileVariance[pos] >= 50 && commonAltVisuals.indexOfKey(visual) >= 0) + else if (tileVariance[pos] >= 50 && commonAltVisuals.containsKey(visual)) return commonAltVisuals.get(visual); else return visual;