From: Jean Privat Date: Wed, 28 Jun 2017 19:58:50 +0000 (-0400) Subject: Merge: gtksourceview: Rewrite the language definition X-Git-Url: http://nitlanguage.org?hp=f384647e4bf4d8995767c1213ee9fc7272a02d7b Merge: gtksourceview: Rewrite the language definition The new definition includes: * A more accurate and up-to-date grammar * A more accurate style list * A list of built-in annotations * Heuristics for embedded languages * Spell-checking only enabled for comments * Styles for operators and lower-case identifiers available if needed (but not highlighted by default) ## Previews Here are the PDF outputs of various black-on-white style schemes for `examples/syntax.nit`: * [Classic](https://github.com/nitlang/nit/files/1109793/gtksourceview-classic.pdf) * [Kate](https://github.com/nitlang/nit/files/1109794/gtksourceview-kate.pdf) * [Solarized Clear](https://github.com/nitlang/nit/files/1109795/gtksourceview-solarized-clear.pdf) * [Tango](https://github.com/nitlang/nit/files/1109796/gtksourceview-tango.pdf) Signed-off-by: Jean-Christophe Beaupré Pull-Request: #2515 Reviewed-by: Jean Privat Reviewed-by: Lucas Bajolet Reviewed-by: Alexis Laferrière --- diff --git a/contrib/action_nitro/Makefile b/contrib/action_nitro/Makefile index b3fcebc..81db63b 100644 --- a/contrib/action_nitro/Makefile +++ b/contrib/action_nitro/Makefile @@ -1,14 +1,14 @@ -NITC=nitc -NITLS=nitls - all: bin/action_nitro -bin/action_nitro: $(shell ${NITLS} -M src/action_nitro.nit -m linux) pre-build - ${NITC} src/action_nitro.nit -m linux -o $@ +bin/action_nitro: $(shell nitls -M src/action_nitro.nit -m linux) pre-build + nitc src/action_nitro.nit -m linux -o $@ + +android: bin/action_nitro.apk +bin/action_nitro.apk: $(shell nitls -M src/action_nitro.nit -m gamnit::android19 -m src/touch_ui.nit) pre-build android/res/ + nitc src/action_nitro.nit -m gamnit::android19 -m src/touch_ui.nit -o $@ -android: -bin/action_nitro.apk: $(shell ${NITLS} -M src/action_nitro.nit -m android -m src/touch_ui.nit) pre-build android/res/ - ${NITC} src/action_nitro.nit -m android -m src/touch_ui.nit -o $@ +android-release: $(shell nitls -M src/action_nitro.nit -m gamnit::android19 -m src/touch_ui.nit) pre-build android/res/ + nitc src/action_nitro.nit -m gamnit::android19 -m src/touch_ui.nit -o bin/action_nitro.apk --release src/gen/texts.nit: art/texts.svg make -C ../inkscape_tools/ diff --git a/contrib/action_nitro/art/icon.svg b/contrib/action_nitro/art/icon.svg index 7383208..a0701e1 100644 --- a/contrib/action_nitro/art/icon.svg +++ b/contrib/action_nitro/art/icon.svg @@ -60,8 +60,8 @@ id="layer1" transform="translate(-286.05811,81.477047)"> image/svg+xml \ No newline at end of file + id="path3452-8-7" /> \ No newline at end of file diff --git a/contrib/action_nitro/assets/particles/blood07.png b/contrib/action_nitro/assets/particles/blood07.png index 584e6d1..4c590d5 100644 Binary files a/contrib/action_nitro/assets/particles/blood07.png and b/contrib/action_nitro/assets/particles/blood07.png differ diff --git a/contrib/action_nitro/assets/particles/explosion00.png b/contrib/action_nitro/assets/particles/explosion00.png index 22529ca..16a484f 100644 Binary files a/contrib/action_nitro/assets/particles/explosion00.png and b/contrib/action_nitro/assets/particles/explosion00.png differ diff --git a/contrib/action_nitro/assets/textures/player.png b/contrib/action_nitro/assets/textures/player.png new file mode 100644 index 0000000..bbd402f Binary files /dev/null and b/contrib/action_nitro/assets/textures/player.png differ diff --git a/contrib/action_nitro/assets/textures/player/frame_01.png b/contrib/action_nitro/assets/textures/player/frame_01.png deleted file mode 100644 index eb6f0ac..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_01.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_02.png b/contrib/action_nitro/assets/textures/player/frame_02.png deleted file mode 100644 index e4c1311..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_02.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_03.png b/contrib/action_nitro/assets/textures/player/frame_03.png deleted file mode 100644 index 1d63a6e..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_03.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_04.png b/contrib/action_nitro/assets/textures/player/frame_04.png deleted file mode 100644 index 9c331fd..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_04.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_05.png b/contrib/action_nitro/assets/textures/player/frame_05.png deleted file mode 100644 index 8948eb1..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_05.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_06.png b/contrib/action_nitro/assets/textures/player/frame_06.png deleted file mode 100644 index 84e30d9..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_06.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_07.png b/contrib/action_nitro/assets/textures/player/frame_07.png deleted file mode 100644 index a9cd3e5..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_07.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_08.png b/contrib/action_nitro/assets/textures/player/frame_08.png deleted file mode 100644 index 2cdbbeb..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_08.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_09.png b/contrib/action_nitro/assets/textures/player/frame_09.png deleted file mode 100644 index 5f70296..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_09.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_10.png b/contrib/action_nitro/assets/textures/player/frame_10.png deleted file mode 100644 index a122246..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_10.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_11.png b/contrib/action_nitro/assets/textures/player/frame_11.png deleted file mode 100644 index 231eef8..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_11.png and /dev/null differ diff --git a/contrib/action_nitro/assets/textures/player/frame_12.png b/contrib/action_nitro/assets/textures/player/frame_12.png deleted file mode 100644 index ccf5003..0000000 Binary files a/contrib/action_nitro/assets/textures/player/frame_12.png and /dev/null differ diff --git a/contrib/action_nitro/package.ini b/contrib/action_nitro/package.ini index b9ae919..bcd9ef0 100644 --- a/contrib/action_nitro/package.ini +++ b/contrib/action_nitro/package.ini @@ -9,3 +9,4 @@ git=https://github.com/nitlang/nit.git git.directory=contrib/action_nitro/ homepage=http://nitlanguage.org issues=https://github.com/nitlang/nit/issues +apk=http://nitlanguage.org/fdroid/apk/action_nitro.apk diff --git a/contrib/action_nitro/src/action_nitro.nit b/contrib/action_nitro/src/action_nitro.nit index 5a2c3bc..2c6afdc 100644 --- a/contrib/action_nitro/src/action_nitro.nit +++ b/contrib/action_nitro/src/action_nitro.nit @@ -18,7 +18,6 @@ module action_nitro is app_version(1, 0, git_revision) android_manifest_activity """android:screenOrientation="sensorLandscape"""" - android_api_target 10 end import gamnit::depth @@ -41,9 +40,12 @@ redef class App # Textures of the biplane, jet, helicopter, parachute and powerups var planes_sheet = new PlanesImages + # Animation when opening the parachute + var parachute_animation = new Animation(planes_sheet.parachute, 16.0) + # Animation for the player movement - private var player_textures: Array[Texture] = - [for f in [1..12] do new Texture("textures/player/frame_{f.pad(2)}.png")] + private var running_texture = new Texture("textures/player.png") + private var running_animation: Animation = running_texture.to_animation(10.0, 12, 0) # Boss 3D model private var iss_model = new Model("models/iss.obj") @@ -77,11 +79,11 @@ redef class App # Particle effects # Explosion particles - var explosions = new ParticleSystem(20, explosion_program, + var explosions = new ParticleSystem(100, explosion_program, new Texture("particles/explosion00.png")) # Blood explosion particles - var blood = new ParticleSystem(20, explosion_program, + var blood = new ParticleSystem(100, explosion_program, new Texture("particles/blood07.png")) # Smoke for the background @@ -134,6 +136,9 @@ redef class App redef fun on_create do + blood.texture.as(RootTexture).premultiply_alpha = false + explosions.texture.as(RootTexture).premultiply_alpha = false + super show_splash_screen new Texture("textures/splash.jpg") @@ -147,10 +152,10 @@ redef class App ui_camera.reset_height 1080.0 # Register particle systems - particle_systems.add explosions - particle_systems.add blood particle_systems.add smoke particle_systems.add clouds + particle_systems.add blood + particle_systems.add explosions # Stars background sprites.add stars @@ -276,7 +281,6 @@ redef class App player.moving = 0.0 if pressed_keys.has("left") then player.moving -= 1.0 if pressed_keys.has("right") then player.moving += 1.0 - player.sprite.as(PlayerSprite).update end # Try to fire as long as a key is pressed @@ -404,16 +408,12 @@ redef class App if event.name == "left" then var mod = if event.is_down then -1.0 else 1.0 player.moving += mod - end - - if event.name == "right" then + player.animate_move + else if event.name == "right" then var mod = if event.is_down then 1.0 else -1.0 player.moving += mod + player.animate_move end - - if player.moving == 0.0 then - player.sprite.as(PlayerSprite).stop_running - else player.sprite.as(PlayerSprite).start_running end end end @@ -470,12 +470,12 @@ redef class Human # Show death animation (explosion) fun death_animation do - var force = 4.0 + var force = 2.0 health = 0.0 - for i in 32.times do + for i in 16.times do app.blood.add( new Point3d[Float](center.x & force, center.y & force, center.z & force), - (2048.0 & 4096.0) * force, 0.3 & 0.1) + (4096.0 & 2048.0) * force, 0.3 & 0.1) end end end @@ -525,19 +525,31 @@ redef class Boss end redef class Enemy - redef var sprite = new Sprite(app.player_textures.rand, center) is lazy + redef var sprite = new Sprite(app.running_animation.frames.rand, center) is lazy init do sprite.scale = width/sprite.texture.width * 2.0 end redef class Parachute - redef var sprite = new Sprite(app.planes_sheet.parachute, center) is lazy - init do sprite.scale = width / sprite.texture.width + redef var sprite = new Sprite(app.planes_sheet.parachute_open, center) is lazy + init + do + sprite.scale = width / sprite.texture.width + sprite.animate app.parachute_animation + end end redef class Player - redef var sprite = new PlayerSprite(app.player_textures[1], center, app.player_textures, 0.08) is lazy + redef var sprite = new Sprite(app.running_animation.frames.last, center) is lazy init do sprite.scale = width/sprite.texture.width * 2.0 + # Update current animation + fun animate_move + do + if moving == 0.0 then + sprite.animate_stop + else sprite.animate(app.running_animation, -1.0) + end + redef fun update(dt, world) do super @@ -612,60 +624,12 @@ redef class World super # Particles - app.explosions.add(center, 8192.0 * force, 0.3) - for i in (4.0*force).to_i.times do + var range = 0.5 * force + app.explosions.add(center, 4096.0 * force, 0.3) + for i in (2.0*force).to_i.times do app.explosions.add( - new Point3d[Float](center.x & force, center.y & force/2.0, center.z & force), - (4096.0 & 2048.0) * force, 0.3 & 0.3, 0.5.rand) - end - end -end - -redef class Int - # Pad a number with `0`s on the left side to reach `size` digits - private fun pad(size: Int): String - do - var s = to_s - var d = size - s.length - if d > 0 then s = "0"*d + s - return s - end -end - -# Special `Sprite` for the player character which is animated -class PlayerSprite - super Sprite - - # Animation of the running character - var running_animation: Array[Texture] - - # Seconds per frame of the animations - var time_per_frame: Float - - # Currently playing animation - private var current_animation: nullable Array[Texture] = null - - # Second at witch `current_animation` started - private var anim_ot = 0.0 - - # Start the running animation - fun start_running - do - anim_ot = app.world.t - current_animation = running_animation - end - - # Stop the running animation - fun stop_running do current_animation = null - - # Update `texture` from `current_animation` - fun update - do - var anim = current_animation - if anim != null then - var dt = app.world.t - anim_ot - var i = (dt / time_per_frame).to_i+2 - texture = anim.modulo(i) + new Point3d[Float](center.x & range, center.y & range, center.z & range), + (2048.0 & 1024.0) * force, 0.3 & 0.3, 0.5.rand) end end end @@ -722,8 +686,8 @@ redef class SmokeProgram gl_PointSize = scale / gl_Position.z * (pt+0.1); if (pt < 0.1) - v_color.a = pt / 0.1; + v_color *= pt / 0.1; else - v_color.a = 1.0 - pt*0.9; + v_color *= 1.0 - pt*0.9; """ end diff --git a/contrib/asteronits/assets/sounds/fire.mp3 b/contrib/asteronits/assets/sounds/fire.mp3 deleted file mode 100644 index d1f2ba2..0000000 Binary files a/contrib/asteronits/assets/sounds/fire.mp3 and /dev/null differ diff --git a/contrib/asteronits/assets/sounds/fire.ogg b/contrib/asteronits/assets/sounds/fire.ogg new file mode 100644 index 0000000..a56e01a Binary files /dev/null and b/contrib/asteronits/assets/sounds/fire.ogg differ diff --git a/contrib/asteronits/src/asteronits.nit b/contrib/asteronits/src/asteronits.nit index 006d1e1..02cb3f4 100644 --- a/contrib/asteronits/src/asteronits.nit +++ b/contrib/asteronits/src/asteronits.nit @@ -61,7 +61,7 @@ redef class App var world = new World(12, 2, display.aspect_ratio) is lazy # Sound effects - private var fx_fire = new Sound("sounds/fire.mp3") + private var fx_fire = new Sound("sounds/fire.ogg") private var fx_explosion_ship = new Sound("sounds/explosion_ship.wav") private var fx_explosion_asteroids = new Sound("sounds/explosion_asteroids.wav") diff --git a/contrib/model_viewer/src/globe.nit b/contrib/model_viewer/src/globe.nit index a5a9a62..12c6ffc 100644 --- a/contrib/model_viewer/src/globe.nit +++ b/contrib/model_viewer/src/globe.nit @@ -91,10 +91,12 @@ class GlobeMaterial init surface do init(0, true, [1.0, 1.0, 1.0, 1.0]) # Create and configure a material for the cloud layer - init clouds do init(4, false, [1.0, 1.0, 1.0, 0.5]) + init clouds do init(4, false, [1.0*clouds_a, 1.0*clouds_a, 1.0*clouds_a, clouds_a]) + private var clouds_a = 0.5 # Create and configure a material for the visible atmosphere - init atmo do init(null, false, [0.0, 0.8, 1.0, 0.05]) + init atmo do init(null, false, [0.0, 0.8*atmo_a, 1.0*atmo_a, atmo_a]) + private var atmo_a = 0.05 redef fun draw(actor, model) do @@ -228,7 +230,6 @@ class GlobeProgram s += 0.05 * texture2D(tex_displace, tex_coord).r; gl_Position = (vec4(coord.xyz * s, 1.0) * rotation + translation) * mvp; - } """ @ glsl_vertex_shader diff --git a/lib/gamnit/android19.nit b/lib/gamnit/android19.nit new file mode 100644 index 0000000..3325ece --- /dev/null +++ b/lib/gamnit/android19.nit @@ -0,0 +1,55 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Variation using features from Android API 19 +# +# Add support for `TextureAsset::premultiply_alpha = false` on Android. +module android19 is + android_api_min 19 + android_api_target 22 +end + +import android +intrude import display_android +intrude import android::load_image + +in "Java" `{ + import android.graphics.Bitmap; + import android.graphics.BitmapFactory; +`} + +redef class TextureAsset + + redef fun load_bitmap(asset_manager, path) + do + var stream = asset_manager.native_assets_manager.open(path.to_java_string) + return new NativeBitmap.from_stream_ex(stream, premultiply_alpha) + end +end + +redef class NativeCByteArray + + # The data was not premultiplied, don't unmultiply it + redef fun unmultiply(w, h) do end +end + +redef class NativeBitmap + + # Load from `input_stream` with optional `premultiply_alpha` + new from_stream_ex(input_stream: NativeInputStream, premultiply_alpha: Bool) in "Java" `{ + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inPremultiplied = premultiply_alpha; // API 19 + return BitmapFactory.decodeStream(input_stream, null, opts); + `} +end diff --git a/lib/gamnit/depth/more_materials.nit b/lib/gamnit/depth/more_materials.nit index 746a952..3b320f9 100644 --- a/lib/gamnit/depth/more_materials.nit +++ b/lib/gamnit/depth/more_materials.nit @@ -31,12 +31,18 @@ class SmoothMaterial super Material # Ambient color, always visible + # + # The RGB values should be premultiplied by the alpha value. var ambient_color: Array[Float] is writable # Diffuse color when covered by a light source + # + # The RGB values should be premultiplied by the alpha value. var diffuse_color: Array[Float] is writable # Specular color affecting reflections + # + # The RGB values should be premultiplied by the alpha value. var specular_color: Array[Float] is writable redef fun draw(actor, model) @@ -71,9 +77,13 @@ class SmoothMaterial program.camera.uniform(app.world_camera.position.x, app.world_camera.position.y, app.world_camera.position.z) # Colors from the material - program.ambient_color.uniform(ambient_color[0], ambient_color[1], ambient_color[2], ambient_color[3]*actor.alpha) - program.diffuse_color.uniform(diffuse_color[0], diffuse_color[1], diffuse_color[2], diffuse_color[3]*actor.alpha) - program.specular_color.uniform(specular_color[0], specular_color[1], specular_color[2], specular_color[3]*actor.alpha) + var a = actor.alpha + program.ambient_color.uniform(ambient_color[0]*a, ambient_color[1]*a, + ambient_color[2]*a, ambient_color[3]*a) + program.diffuse_color.uniform(diffuse_color[0]*a, diffuse_color[1]*a, + diffuse_color[2]*a, diffuse_color[3]*a) + program.specular_color.uniform(specular_color[0]*a, specular_color[1]*a, + specular_color[2]*a, specular_color[3]*a) # Execute draw if mesh.indices.is_empty then @@ -188,9 +198,13 @@ class TexturedMaterial program.rotation.uniform new Matrix.gamnit_euler_rotation(actor.pitch, actor.yaw, actor.roll) - program.ambient_color.uniform(ambient_color[0], ambient_color[1], ambient_color[2], ambient_color[3]*actor.alpha) - program.diffuse_color.uniform(diffuse_color[0], diffuse_color[1], diffuse_color[2], diffuse_color[3]*actor.alpha) - program.specular_color.uniform(specular_color[0], specular_color[1], specular_color[2], specular_color[3]*actor.alpha) + var a = actor.alpha + program.ambient_color.uniform(ambient_color[0]*a, ambient_color[1]*a, + ambient_color[2]*a, ambient_color[3]*a) + program.diffuse_color.uniform(diffuse_color[0]*a, diffuse_color[1]*a, + diffuse_color[2]*a, diffuse_color[3]*a) + program.specular_color.uniform(specular_color[0]*a, specular_color[1]*a, + specular_color[2]*a, specular_color[3]*a) program.normal.array_enabled = true program.normal.array(mesh.normals, 3) diff --git a/lib/gamnit/depth/particles.nit b/lib/gamnit/depth/particles.nit index 3c40ac1..bfe3392 100644 --- a/lib/gamnit/depth/particles.nit +++ b/lib/gamnit/depth/particles.nit @@ -258,7 +258,6 @@ class ParticleProgram { if (use_texture) { gl_FragColor = texture2D(texture0, gl_PointCoord) * v_color; - if (gl_FragColor.a <= 0.01) discard; } else { gl_FragColor = v_color; } @@ -301,7 +300,7 @@ class ExplosionProgram gl_Position = center * mvp; gl_PointSize = scale / gl_Position.z * pt; - if (pt > 0.8) v_color.a = (1.0-pt)/0.2; + if (pt > 0.8) v_color *= (1.0-pt)/0.2; """ end @@ -318,8 +317,8 @@ class SmokeProgram gl_PointSize = scale / gl_Position.z * (pt+0.1); if (pt < 0.1) - v_color.a = pt / 0.1; + v_color *= pt / 0.1; else - v_color.a = 1.0 - pt*0.9; + v_color *= 1.0 - pt*0.9; """ end diff --git a/lib/gamnit/display_android.nit b/lib/gamnit/display_android.nit index e9d1b4a..8e5566c 100644 --- a/lib/gamnit/display_android.nit +++ b/lib/gamnit/display_android.nit @@ -50,19 +50,24 @@ end redef class TextureAsset + private fun load_bitmap(asset_manager: AssetManager, path: String): NativeBitmap + do + return asset_manager.bitmap(path) + end + redef fun load_from_platform do jni_env.push_local_frame 4 var asset_manager = app.asset_manager - var bmp = asset_manager.bitmap(path) + var bmp = load_bitmap(asset_manager, path) if bmp.is_java_null then error = new Error("Failed to load texture at '{path}'") jni_env.pop_local_frame return end - var buf = bmp.copy_pixels + var buf = bmp.copy_pixels(unmultiply=not premultiply_alpha) loaded = true width = bmp.width.to_f height = bmp.height.to_f diff --git a/lib/gamnit/flat.nit b/lib/gamnit/flat.nit index b278029..3911092 100644 --- a/lib/gamnit/flat.nit +++ b/lib/gamnit/flat.nit @@ -123,6 +123,55 @@ class Sprite center_direct = value end + # Last animation set with `animate` + var animation: nullable Animation = null + + # Animation on the shader, if this changes it `needs_remap` + private var shader_animation: nullable Animation = null + + # Animation start time, relative to `sprite_set.time` + # + # At -1.0 if animation started before being assigned a `sprite_set`. + private var animation_start = 0.0 + + # Number of loops to show `animation` + private var animation_loops = 0.0 + + # Start the `animation` for `n_loops`, replacing the static `texture` + # + # By default, if `n_loops` is not set, the animation plays once. + # If `n_loops == -1.0` then the animation loops infinitely. + # Otherwise, the animation repeats, e.g. it repeats twice and a half + # if `n_loops == 2.5`. + # + # The animation can be stopped using `animate_stop`. + fun animate(animation: Animation, n_loops: nullable Float) + do + if not animation.valid then print_error "{class_name}::animate: invalid animation {animation}" + + var shader_animation = shader_animation + if shader_animation == null or animation.frames.first.root != shader_animation.frames.first.root then + # Resort with the new animation texture + needs_remap + else + needs_update + end + + var sprite_set = sprite_set + animation_start = if sprite_set != null then sprite_set.time else -1.0 + animation_loops = n_loops or else 1.0 + self.shader_animation = animation + self.animation = animation + end + + # Stop any active `animation` to display the static `texture` + fun animate_stop + do + if animation == null then return + needs_update + animation = null + end + # Rotation on the Z axis, positive values turn counterclockwise var rotation = 0.0 is writable(rotation_direct=) @@ -235,7 +284,10 @@ class Sprite fun needs_update do var c = context - if c != null then c.sprites_to_update.add self + if c == null then return + if c.last_sprite_to_update == self then return + c.sprites_to_update.add self + c.last_sprite_to_update = self end # Request a resorting of this sprite in its sprite list @@ -253,10 +305,51 @@ class Sprite # Current context to which `self` was sorted private var context: nullable SpriteContext = null + # Index in `context` + private var context_index: Int = -1 + # Current context to which `self` belongs private var sprite_set: nullable SpriteSet = null end +# Animation for sprites, set with `Sprite.animate` +# +# Two main services create animations: +# * The constructors accepts an array of textures and the number of frames per +# seconds: `new Animation(array_of_subtextures, 10.0)` +# * The method `Texture::to_animation` uses the whole texture +# dividing it in frames either on X or Y: +# `new Texture("path/in/assets.png").to_animation(30.0, 0, 12)` +class Animation + + # Frames composing this animation + # + # All frames must share the same `Texture::root`, be on a vertical or + # horizontal line, be spaced equally and share the same dimensions. + var frames: SequenceRead[Texture] + + # Frames per seconds, a higher value makes this animation faster + # + # The animation speed is also affected by `SpriteSet::time_mod`. + var fps: Float + + # Are the `frames` valid for an animation? (see the requirements in `frames`) + var valid: Bool is lazy do + var r: nullable RootTexture = null + for f in frames do + if r == null then + r = f.root + else + if r != f.root then return false + end + end + + # TODO check for line, constant distance, and same aspect ratio. + + return true + end +end + redef class App # Default graphic program to draw `sprites` private var simple_2d_program = new Simple2dProgram is lazy @@ -337,7 +430,7 @@ redef class App # Enable blending gl.capabilities.blend.enable - glBlendFunc(gl_SRC_ALPHA, gl_ONE_MINUS_SRC_ALPHA) + glBlendFunc(gl_ONE, gl_ONE_MINUS_SRC_ALPHA) # Enable depth test gl.capabilities.depth_test.enable @@ -393,6 +486,7 @@ redef class App perf_clock_main.lapse var dt = clock.lapse.to_f update dt + frame_dt = dt sys.perfs["gamnit flat update client"].add perf_clock_main.lapse # Draw and flip screen @@ -404,6 +498,8 @@ redef class App assert gl_error == gl_NO_ERROR else print_error gl_error end + private var frame_dt = 0.0 + # Draw the whole screen, all `glDraw...` calls should be executed here protected fun frame_core_draw(display: GamnitDisplay) do @@ -425,6 +521,9 @@ redef class App simple_2d_program.use simple_2d_program.mvp.uniform camera.mvp_matrix + sprite_set.time += frame_dt*sprite_set.time_mod + simple_2d_program.time.uniform sprite_set.time + # draw sprite_set.draw end @@ -482,6 +581,34 @@ redef class Texture r, b, l, b] end + + # Convert to a sprite animation at `fps` speed with `x` or `y` frames + # + # The arguments `x` and `y` set the number of frames in the texture. + # Use `x` for an horizontal arrangement or `y` for vertical. + # One and only one of the arguments must be different than 0, + # as an animation can only be on a line and cannot wrap. + fun to_animation(fps: Float, x, y: Int): Animation + do + assert (x == 0) != (y == 0) + + var n_frames = x.max(y) + var frames = new Array[Texture] + + var dx = (x/n_frames).to_f/n_frames.to_f + var dy = (y/n_frames).to_f/n_frames.to_f + var w = if x == 0 then 1.0 else dx + var h = if y == 0 then 1.0 else dy + var left = 0.0 + var top = 0.0 + for i in n_frames.times do + frames.add new RelativeSubtexture(root, left, top, left+w, top+h) + left += dx + top += dy + end + + return new Animation(frames, fps) + end end # Graphic program to display simple models with a texture, translation, rotation and scale @@ -507,12 +634,36 @@ private class Simple2dProgram // Model view projection matrix uniform mat4 mvp; + // Current world time, in seconds + uniform float time; + // Rotation matrix attribute vec4 rotation_row0; attribute vec4 rotation_row1; attribute vec4 rotation_row2; attribute vec4 rotation_row3; + // Animation speed, frames per seconds + attribute float a_fps; + + // Number of frames in the animation + attribute float a_n_frames; + + // World coordinate of the animation (for aspect ratio) + attribute vec2 a_coord; + + // Animation texture coordinates of the first frame + attribute vec2 a_tex_coord; + + // Animation texture coordinates difference between frames + attribute vec2 a_tex_diff; + + // Animation start time, in reference to `time` + attribute float a_start; + + // Number of loops to play of the animation + attribute float a_loops; + mat4 rotation() { return mat4(rotation_row0, rotation_row1, rotation_row2, rotation_row3); @@ -522,11 +673,29 @@ private class Simple2dProgram varying vec4 v_color; varying vec2 v_coord; + // Is there an active animation? + varying float v_animated; + void main() { - gl_Position = (vec4(coord.xyz * scale, 1.0) * rotation() + translation)* mvp; - v_color = color; - v_coord = tex_coord; + vec3 c; // coords + + float end = a_start + a_loops/a_fps*a_n_frames; + if (a_loops == -1.0 || time < end) { + // in animation + float frame = mod(floor((time-a_start)*a_fps), a_n_frames); + v_coord = a_tex_coord + a_tex_diff*frame; + c = vec3(a_coord, coord.z); + v_animated = 1.0; + } else { + // static + v_coord = tex_coord; + c = coord.xyz; + v_animated = 0.0; + } + + gl_Position = (vec4(c * scale, 1.0) * rotation() + translation)* mvp; + v_color = vec4(color.rgb*color.a, color.a); } """ @ glsl_vertex_shader @@ -539,13 +708,20 @@ private class Simple2dProgram // Texture to apply on this object uniform sampler2D texture0; + // Texture to apply on this object + uniform sampler2D animation; + // Input from the vertex shader varying vec4 v_color; varying vec2 v_coord; + varying float v_animated; void main() { - if(use_texture) { + if (v_animated > 0.5) { + gl_FragColor = v_color * texture2D(animation, v_coord); + if (gl_FragColor.a <= 0.01) discard; + } else if (use_texture) { gl_FragColor = v_color * texture2D(texture0, v_coord); if (gl_FragColor.a <= 0.01) discard; } else { @@ -589,6 +765,36 @@ private class Simple2dProgram # Model view projection matrix var mvp = uniforms["mvp"].as(UniformMat4) is lazy + + # World time, in seconds + var time = uniforms["time"].as(UniformFloat) is lazy + + # --- + # Animations + + # Texture of all the frames of the animation + var animation_texture = uniforms["animation"].as(UniformSampler2D) is lazy + + # Frame per second of the animation + var animation_fps = attributes["a_fps"].as(AttributeFloat) is lazy + + # Number of frames in the animation + var animation_n_frames = attributes["a_n_frames"].as(AttributeFloat) is lazy + + # Coordinates of each frame (mush be shared by all frames) + var animation_coord = attributes["a_coord"].as(AttributeVec2) is lazy + + # Texture coordinates of the first frame + var animation_tex_coord = attributes["a_tex_coord"].as(AttributeVec2) is lazy + + # Coordinate difference between each frame + var animation_tex_diff = attributes["a_tex_diff"].as(AttributeVec2) is lazy + + # Animation start time, in seconds and in reference to `dt` + var animation_start = attributes["a_start"].as(AttributeFloat) is lazy + + # Number of loops of the animation, -1 for infinite + var animation_loops = attributes["a_loops"].as(AttributeFloat) is lazy end redef class Point3d[N] @@ -667,7 +873,7 @@ private class SpriteSet super HashSet[Sprite] # Map texture then static vs dynamic to a `SpriteContext` - var contexts_map = new HashMap2[RootTexture, Bool, SpriteContext] + var contexts_map = new HashMap3[RootTexture, nullable RootTexture, Bool, Array[SpriteContext]] # Contexts in `contexts_map` var contexts_items = new Array[SpriteContext] @@ -675,27 +881,59 @@ private class SpriteSet # Sprites needing resorting in `contexts_map` var sprites_to_remap = new Array[Sprite] + # Animation speed multiplier (0.0 to pause, 1.0 for normal speed, etc.) + var time_mod = 1.0 is writable + + # Seconds elapsed since the launch of the program, in world time responding to `time_mod` + var time = 0.0 + # Add a sprite to the appropriate context fun map_sprite(sprite: Sprite) do assert sprite.context == null else print_error "Sprite {sprite} belongs to another SpriteSet" + # Sort by texture and animation texture var texture = sprite.texture.root - var context = contexts_map[texture, sprite.static] + var animation = sprite.animation + var animation_texture = if animation != null then + animation.frames.first.root else null + var contexts = contexts_map[texture, animation_texture, sprite.static] + + var context = null + if contexts != null then + for c in contexts.reverse_iterator do + var size = c.sprites.length + 1 + if size * 4 <= 0xffff then + context = c + break + end + end + end if context == null then var usage = if sprite.static then gl_STATIC_DRAW else gl_DYNAMIC_DRAW - context = new SpriteContext(texture, usage) + context = new SpriteContext(texture, animation_texture, usage) - contexts_map[texture, sprite.static] = context + if contexts == null then + contexts = new Array[SpriteContext] + contexts_map[texture, animation_texture, sprite.static] = contexts + end + + contexts.add context contexts_items.add context end context.sprites.add sprite context.sprites_to_update.add sprite + context.last_sprite_to_update = sprite sprite.context = context sprite.sprite_set = self + + if animation != null and sprite.animation_start == -1.0 then + # Start animation + sprite.animation_start = time + end end # Remove a sprite from its context @@ -764,15 +1002,21 @@ private class SpriteContext # Only root texture drawn by this context var texture: nullable RootTexture + # Only animation texture drawn by this context + var animation_texture: nullable RootTexture + # OpenGL ES usage of `buffer_array` and `buffer_element` var usage: GLBufferUsage # Sprites drawn by this context - var sprites = new GroupedArray[Sprite] + var sprites = new GroupedSprites # Sprites to update since last `draw` var sprites_to_update = new Set[Sprite] + # Cache of the last `Sprite` added to `sprites_to_update` since the last call to `draw` + var last_sprite_to_update: nullable Sprite = null + # Sprites that have been update and for which `needs_update` can be set to false var updated_sprites = new Array[Sprite] @@ -802,10 +1046,11 @@ private class SpriteContext # Number of GL_FLOAT per vertex of `Simple2dProgram` var float_per_vertex: Int is lazy do - # vec4 translation, vec4 color, vec4 coord, - # float scale, vec2 tex_coord, vec4 rotation_row* - return 4 + 4 + 4 + - 1 + 2 + 4*4 + return 4 + 4 + 4 + # vec4 translation, vec4 color, vec4 coord, + 1 + 2 + 4*4 + # float scale, vec2 tex_coord, vec4 rotation_row*, + 1 + 1 + # float a_fps, float a_n_frames, + 2 + 2 + 2 + # vec2 a_coord, vec2 a_tex_coord, vec2 a_tex_diff, + 1 + 1 # float a_start, float a_loops end # Number of bytes per vertex of `Simple2dProgram` @@ -878,8 +1123,11 @@ private class SpriteContext # Update GPU data of `sprite` fun update_sprite(sprite: Sprite) do - var sprite_index = sprites.index_of(sprite) - if sprite_index == -1 then return + var context = sprite.context + if context != self then return + + var sprite_index = sprite.context_index + assert sprite_index != -1 # Vertices data @@ -927,6 +1175,40 @@ private class SpriteContext end data.fill_from_matrix(rot, o+15) + var animation = sprite.animation + if animation == null then + for i in [31..40] do data[o+i] = 0.0 + else + # a_fps + data[o+31] = animation.fps + + # a_n_frames + data[o+32] = animation.frames.length.to_f + + # a_coord + data[o+33] = animation.frames.first.vertices[v*3+0] + data[o+34] = animation.frames.first.vertices[v*3+1] + + # a_tex_coord + var tc = if sprite.invert_x then + animation.frames.first.texture_coords_invert_x + else animation.frames.first.texture_coords + data[o+35] = tc[v*2] + data[o+36] = tc[v*2+1] + + # a_tex_diff + var dx = animation.frames[1].texture_coords[0] - animation.frames[0].texture_coords[0] + var dy = animation.frames[1].texture_coords[1] - animation.frames[0].texture_coords[1] + data[o+37] = dx + data[o+38] = dy + + # a_start + data[o+39] = sprite.animation_start + + # a_loops + data[o+40] = sprite.animation_loops + end + o += float_per_vertex end @@ -977,6 +1259,7 @@ private class SpriteContext glBindBuffer(gl_ELEMENT_ARRAY_BUFFER, buffer_element) # Resize GPU buffers? + var update_everything = false if sprites.capacity > buffer_capacity then # Try to defragment first var moved = sprites.defragment @@ -986,6 +1269,7 @@ private class SpriteContext resize # We must update everything + update_everything = true for s in sprites.items do if s != null then sprites_to_update.add s else # Just update the moved sprites @@ -999,11 +1283,19 @@ private class SpriteContext end # Update GPU sprites data - if sprites_to_update.not_empty then + if sprites_to_update.not_empty or update_everything then app.perf_clock_sprites.lapse - for sprite in sprites_to_update do update_sprite(sprite) + if update_everything then + for sprite in sprites.items do if sprite != null then + update_sprite(sprite) + end + else + for sprite in sprites_to_update do update_sprite(sprite) + end + sprites_to_update.clear + last_sprite_to_update = null sys.perfs["gamnit flat gpu update"].add app.perf_clock_sprites.lapse end @@ -1019,8 +1311,19 @@ private class SpriteContext var gl_error = glGetError assert gl_error == gl_NO_ERROR else print_error gl_error + var animation = animation_texture + if animation != null then + glActiveTexture gl_TEXTURE1 + glBindTexture(gl_TEXTURE_2D, animation.gl_texture) + app.simple_2d_program.animation_texture.uniform 1 + end + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + # Configure attributes, in order: - # vec4 translation, vec4 color, float scale, vec4 coord, vec2 tex_coord, vec4 rotation_row* + # vec4 translation, vec4 color, float scale, vec4 coord, vec2 tex_coord, vec4 rotation_row*, + # a_fps, a_n_frames, a_coord, a_tex_coord, a_tex_diff, a_start, a_loops + var offset = 0 var p = app.simple_2d_program var sizeof_gl_float = 4 # sizeof(GL_FLOAT) @@ -1071,6 +1374,55 @@ private class SpriteContext assert gl_error == gl_NO_ERROR else print_error gl_error end + size = 1 + glEnableVertexAttribArray p.animation_fps.location + glVertexAttribPointeri(p.animation_fps.location, size, gl_FLOAT, false, bytes_per_vertex, offset) + offset += size * sizeof_gl_float + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + + size = 1 + glEnableVertexAttribArray p.animation_n_frames.location + glVertexAttribPointeri(p.animation_n_frames.location, size, gl_FLOAT, false, bytes_per_vertex, offset) + offset += size * sizeof_gl_float + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + + size = 2 + glEnableVertexAttribArray p.animation_coord.location + glVertexAttribPointeri(p.animation_coord.location, size, gl_FLOAT, false, bytes_per_vertex, offset) + offset += size * sizeof_gl_float + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + + size = 2 + glEnableVertexAttribArray p.animation_tex_coord.location + glVertexAttribPointeri(p.animation_tex_coord.location, size, gl_FLOAT, false, bytes_per_vertex, offset) + offset += size * sizeof_gl_float + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + + size = 2 + glEnableVertexAttribArray p.animation_tex_diff.location + glVertexAttribPointeri(p.animation_tex_diff.location, size, gl_FLOAT, false, bytes_per_vertex, offset) + offset += size * sizeof_gl_float + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + + size = 1 + glEnableVertexAttribArray p.animation_start.location + glVertexAttribPointeri(p.animation_start.location, size, gl_FLOAT, false, bytes_per_vertex, offset) + offset += size * sizeof_gl_float + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + + size = 1 + glEnableVertexAttribArray p.animation_loops.location + glVertexAttribPointeri(p.animation_loops.location, size, gl_FLOAT, false, bytes_per_vertex, offset) + offset += size * sizeof_gl_float + gl_error = glGetError + assert gl_error == gl_NO_ERROR else print_error gl_error + # Actual draw for s in sprites.starts, e in sprites.ends do var l = e-s @@ -1169,9 +1521,6 @@ private class GroupedArray[E] # Number of item slots in the array fun capacity: Int do return items.length - # Index of `item` - fun index_of(item: E): Int do return items.index_of(item) - # List of available slots var available = new MinHeap[Int].default @@ -1181,8 +1530,8 @@ private class GroupedArray[E] # Index of the spots after filled chunks var ends = new List[Int] - # Add `item` to the first available slot - fun add(item: E) + # Add `item` to the first available slot and return its index + fun add(item: E): Int do length += 1 @@ -1207,7 +1556,7 @@ private class GroupedArray[E] # at end of first chunk ends.first += 1 end - return + return i end items.add item @@ -1215,13 +1564,20 @@ private class GroupedArray[E] starts.add 0 ends.add 1 else ends.last += 1 + return ends.last - 1 end # Remove the first instance of `item` fun remove(item: E) do - var i = items.index_of(item) - assert i != -1 + var index = items.index_of(item) + remove_at(item, index) + end + + # Remove `item` at `index` + fun remove_at(item: E, index: Int) + do + var i = index length -= 1 items[i] = null @@ -1296,6 +1652,7 @@ private class GroupedArray[E] while max > 0 and (starts.length > 1 or starts.first != 0) do var i = ends.last - 1 var e = items[i] + assert e != null remove e add e moved.add e @@ -1328,6 +1685,20 @@ private class GroupedArray[E] end end +# Optimized `GroupedArray` to use `Sprite::context_index` and avoid using `index_of` +private class GroupedSprites + super GroupedArray[Sprite] + + redef fun add(item) + do + var index = super + item.context_index = index + return index + end + + redef fun remove(item) do remove_at(item, item.context_index) +end + redef class GLfloatArray private fun fill_from_matrix(matrix: Matrix, dst_offset: nullable Int) do diff --git a/lib/gamnit/textures.nit b/lib/gamnit/textures.nit index 4bc95cb..4fb98ac 100644 --- a/lib/gamnit/textures.nit +++ b/lib/gamnit/textures.nit @@ -80,9 +80,7 @@ abstract class Texture # Prepare a subtexture from this texture, from the given pixel offsets fun subtexture(left, top, width, height: Numeric): Subtexture do - # Setup the subtexture - var subtex = new Subtexture(root, self, left.to_f, top.to_f, width.to_f, height.to_f) - return subtex + return new AbsoluteSubtexture(self, left.to_f, top.to_f, width.to_f, height.to_f) end # Offset of the left border on `root` from 0.0 to 1.0 @@ -210,7 +208,7 @@ class CustomTexture end end -# Texture with its own pixels +# Texture with its own pixel data class RootTexture super Texture @@ -223,6 +221,18 @@ class RootTexture init do all_root_textures.add self + # Should the pixels RGB values be premultiplied by their alpha value at loading? + # + # All gamnit textures must have premultiplied alpha, it provides a better + # alpha blending, avoids artifacts and allows for additive blending. + # + # When at `true`, the default, pixels RGB values are premultiplied + # at loading. Set to `false` if pixels RGB values are already + # premultiplied in the source data. + # + # This value must be set before calling `load`. + var premultiply_alpha = true is writable + private fun load_from_pixels(pixels: Pointer, width, height: Int, format: GLPixelFormat) do var max_texture_size = glGetIntegerv(gl_MAX_TEXTURE_SIZE, 0) @@ -231,6 +241,11 @@ class RootTexture return end + # Premultiply alpha? + if premultiply_alpha and format == gl_RGBA then + pixels.premultiply_alpha(width, height) + end + glPixelStorei(gl_UNPACK_ALIGNEMENT, 1) var tex = glGenTextures(1)[0] gl_texture = tex @@ -240,6 +255,9 @@ class RootTexture glHint(gl_GENERATE_MIPMAP_HINT, gl_NICEST) glGenerateMipmap(gl_TEXTURE_2D) + glTexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, gl_LINEAR_MIPMAP_LINEAR) + + glBindTexture(gl_TEXTURE_2D, 0) end private fun load_checker(size: Int) @@ -309,18 +327,25 @@ class TextureAsset end # Texture derived from another texture, does not own its pixels -class Subtexture +abstract class Subtexture super Texture - redef var root - # Parent texture, from which this texture was created var parent: Texture - # Left border of this texture compared to `parent` + redef var root = parent.root is lateinit + + redef fun load(force) do root.load(force) +end + +# Subtexture created from pixel coordinates within `parent` +class AbsoluteSubtexture + super Subtexture + + # Left border of this texture relative to `parent` var left: Float - # Top border of this texture compared to `parent` + # Top border of this texture relative to `parent` var top: Float private fun set_wh(width, height: Float) @@ -329,14 +354,25 @@ class Subtexture self.height = height end - redef fun load(force) do root.load(force) - redef var offset_left = parent.offset_left + left / root.width is lazy redef var offset_top = parent.offset_top + top / root.height is lazy redef var offset_right = offset_left + width / root.width is lazy redef var offset_bottom = offset_top + height / root.height is lazy end +# Subtexture created from relative coordinates ([0..1]) out of the `root` texture +class RelativeSubtexture + super Subtexture + + redef var offset_left + redef var offset_top + redef var offset_right + redef var offset_bottom + + redef fun width do return root.width * (offset_right - offset_left) + redef fun height do return root.height * (offset_bottom - offset_top) +end + redef class Sys # All declared root textures var all_root_textures = new TextureSet @@ -349,3 +385,20 @@ class TextureSet # Load all texture of this set fun load_all do for t in self do t.load end + +redef class Pointer + # Multiply RBG values by their alpha value + private fun premultiply_alpha(width, height: Int) `{ + uint8_t *bytes = (uint8_t *)self; + int x, y, i = 0; + for(y = 0; y < height; y ++) { + for(x = 0; x < width; x ++) { + int a = bytes[i+3]; + bytes[i ] = bytes[i ] * a / 255; + bytes[i+1] = bytes[i+1] * a / 255; + bytes[i+2] = bytes[i+2] * a / 255; + i += 4; + } + } + `} +end diff --git a/lib/neo4j/neo4j.nit b/lib/neo4j/neo4j.nit index d512462..665ecdb 100644 --- a/lib/neo4j/neo4j.nit +++ b/lib/neo4j/neo4j.nit @@ -290,7 +290,7 @@ class Neo4jClient # Build the query. var buffer = new Buffer - buffer.append "match n where \{label_0\} in labels(n)" + buffer.append "match (n) where \{label_0\} in labels(n)" for i in [1..labels.length[ do buffer.append " and \{label_{i}\} in labels(n)" end diff --git a/misc/docker/Dockerfile b/misc/docker/Dockerfile index ee34149..3d795c2 100644 --- a/misc/docker/Dockerfile +++ b/misc/docker/Dockerfile @@ -1,6 +1,6 @@ # This is a basic install of Nit on a debian base. -FROM debian:jessie +FROM debian:stretch MAINTAINER Jean Privat # Install dependencies diff --git a/misc/docker/full/Dockerfile b/misc/docker/full/Dockerfile index e6bfe66..eb7f26d 100644 --- a/misc/docker/full/Dockerfile +++ b/misc/docker/full/Dockerfile @@ -14,8 +14,10 @@ RUN dpkg --add-architecture i386 \ libgles1-mesa-dev \ libgles2-mesa-dev \ libgtk-3-dev \ + libgmp-dev \ libncurses5-dev \ libpq-dev \ + libreadline-dev \ libsdl-image1.2-dev \ libsdl-ttf2.0-dev \ libsdl1.2-dev \ @@ -29,6 +31,7 @@ RUN dpkg --add-architecture i386 \ # Packages needed for contrib, platforms and FFI ant \ clang \ + cmake \ default-jdk \ file \ inkscape \ @@ -50,15 +53,27 @@ RUN mkdir -p /opt \ && rm android-sdk-linux.tgz \ && echo y | android-sdk-linux/tools/android update sdk -a --no-ui --filter \ # Hardcode minimal known working things - platform-tools,build-tools-22.0.1,android-22,android-10 \ + platform-tools,build-tools-22.0.1,android-22,android-21,android-19,android-16,android-15,android-10 \ # Android NDK && curl http://dl.google.com/android/repository/android-ndk-r11c-linux-x86_64.zip -o android-ndk.zip \ && unzip -q android-ndk.zip \ + && chmod -R a+X /opt \ && ln -s android-ndk-r11c android-ndk \ && rm android-ndk.zip \ && printf "PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_NDK\nexport PATH\n" >> "/etc/profile.d/android.sh" +# Install OpenGL validator +RUN git clone https://github.com/KhronosGroup/glslang.git \ + && mkdir -p glslang/build \ + && cd glslang/build \ + && cmake .. \ + && make \ + && make + # Setup environment variables ENV ANDROID_HOME /opt/android-sdk-linux ENV ANDROID_NDK /opt/android-ndk ENV PATH $PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_NDK +ENV JAVA_HOME=/usr/lib/jvm/default-java/ +ENV JNI_LIB_PATH=$JAVA_HOME/jre/lib/amd64/server/ +ENV LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64/server/