From: Jean Privat Date: Thu, 10 Sep 2015 18:54:54 +0000 (-0400) Subject: Merge: jwrapper: prevent nitls to parse the generated files X-Git-Tag: v0.7.8~31 X-Git-Url: http://nitlanguage.org?hp=e3ecf255dd27927aed176efb92b644f5f03a9759 Merge: jwrapper: prevent nitls to parse the generated files Prevent nitls to parse the generated files by adding an empty `packages.ini` file to the examples folder. This slowed down calls to `make` as nitls is used to detect the dependancies of Nit programs and it took a while to parse the huge generated files. Pull-Request: #1702 Reviewed-by: Jean Privat Reviewed-by: Romain Chanoir Reviewed-by: Lucas Bajolet --- diff --git a/contrib/nitiwiki/examples/nitiwiki/config.ini b/contrib/nitiwiki/examples/nitiwiki/config.ini index 315462d..bc96f38 100644 --- a/contrib/nitiwiki/examples/nitiwiki/config.ini +++ b/contrib/nitiwiki/examples/nitiwiki/config.ini @@ -3,3 +3,4 @@ wiki.desc=proudly powered by nit wiki.logo=assets/logo.png wiki.root_dir=. wiki.rsync_dir=moz-code.org:nitiwiki/ +wiki.highlighter=./highlighter.sh "$1" diff --git a/contrib/nitiwiki/examples/nitiwiki/highlighter.sh b/contrib/nitiwiki/examples/nitiwiki/highlighter.sh new file mode 100755 index 0000000..57aaf45 --- /dev/null +++ b/contrib/nitiwiki/examples/nitiwiki/highlighter.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# 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. + +# Example of an external highlighter that dispatch on various command +# according to the argument + +# meta is the argument +meta=$1 + +# raw is a synonym of txt +test "$meta" = "raw" && meta=txt + +# if `pandoc` then process through the `pandoc` command. +if test "$meta" = "pandoc"; then + exec pandoc -t html +fi + +# Else, try `highlight` +highlight --fragment -S "$meta" --inline-css --enclose-pre || + # Or `source-highlight` + source-highlight -s "$meta" +out=$? +exit $out diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/block.md b/contrib/nitiwiki/examples/nitiwiki/pages/block.md new file mode 100644 index 0000000..d0daaba --- /dev/null +++ b/contrib/nitiwiki/examples/nitiwiki/pages/block.md @@ -0,0 +1,36 @@ +# Test of code highlighting + +A basic block. + + print(["hello", "world"].join(", ")) + +A fenced block. + +~~~ +print(["hello", "world"].join(", ")) +~~~ + +A fenced block with metainfo, so it can be highlighted with an external tool. + +~~~html + + + +
HelloWorld
+~~~ + +A special block where the rendering is delegated to pandoc. +For instance, to render tables. + +~~~pandoc +what how +------ ----- +hello 10 +world 9001 +~~~ + +This try some exploit +~~~raw'"; echo pwned >&2 # +Hello
+World +~~~ diff --git a/contrib/nitiwiki/src/markdown_highlight.nit b/contrib/nitiwiki/src/markdown_highlight.nit new file mode 100644 index 0000000..08751b0 --- /dev/null +++ b/contrib/nitiwiki/src/markdown_highlight.nit @@ -0,0 +1,99 @@ +# 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. + +# Extends the wiki with an external highlighter (or any processor) for code blocks +module markdown_highlight +import wiki_links + +redef class WikiConfig + # External highlighter command called to process block code. + # + # * key: `wiki.highlighter` + # * default: empty string, that means no external highlighter + # * example: `highlight --fragment -S "$1" --inline-css --enclose-pre` + # + # The external highlighter is a shell command invoked with `sh -c`. + # The meta information of the fence is passed as `$1`. + # *Important*: `$1` is given as is, thus is tainted. You SHOULD protect it with quotes in the command. + # + # By default, the highlighter is only called on fenced block code with a meta information. + # See `wiki.highlighter.default` to force the invocation of the highlighter on any code block. + # + # The output of the command will be inserted as is in the generated document. + # Therefore it is expected that the command returns a valid, complete and balanced HTML fragment. + # If the highlighter returns nothing (empty output), the internal rendering is used as a fall-back + # (as if the option was not set). + # + # Advanced usages can invoke a custom shell script instead of a standard command to + # check the argument, filter it, dispatch to various advanced commands, implement ad-hoc behaviors, etc. + var highlighter: String is lazy do + return value_or_default("wiki.highlighter", "") + end + + # Default meta (i.e. language) to use to call the external highlighter. + # + # * key: `wiki.highlighter.default` + # * default: empty string, that means no default meta information. + # * example: `nit` + # + # When set, this configuration forces the external highlighter (see `wiki.highlighter`) + # to be called also on basic code block (with the indentation) and plain fenced code + # blocks (without meta information). + # + # The value is used as the `$1` argument of the configured highlighter command. + # + # Note: has no effect if `wiki.highlighter` is not set. + var highlighter_default: String is lazy do + return value_or_default("wiki.highlighter.default", "") + end +end + +redef class NitiwikiDecorator + # Extends special cases for meta in fences + redef fun add_code(v, block) do + var highlighter = wiki.config.highlighter + + # No highlighter, then defaults + if highlighter.is_empty then + super + return + end + + var code = block.raw_content + var meta = block.meta or else wiki.config.highlighter_default + + # No meta nor forced meta, then defaults + if meta.is_empty then + super + return + end + + # Execute the command + wiki.message("Executing `{highlighter}` `{meta}` (in {context.src_path.as(not null)})", 2) + var proc = new ProcessDuplex("sh", "-c", highlighter, "", meta.to_s) + var res = proc.write_and_read(code) + if proc.status != 0 then + wiki.message("Warning: `{highlighter}` `{meta}` returned {proc.status} (in {context.src_path.as(not null)})", 0) + end + + # Check the result + if res.is_empty then + # No result, then defaults + wiki.message(" `{highlighter}` produced nothing, process internally instead (in {context.src_path.as(not null)})", 2) + super + return + end + v.add(res) + end +end diff --git a/contrib/nitiwiki/src/nitiwiki.nit b/contrib/nitiwiki/src/nitiwiki.nit index 71ab129..c5c6ebe 100644 --- a/contrib/nitiwiki/src/nitiwiki.nit +++ b/contrib/nitiwiki/src/nitiwiki.nit @@ -16,6 +16,7 @@ module nitiwiki import wiki_html +import markdown_highlight # Locate nit directory private fun compute_nit_dir(opt_nit_dir: OptionString): String do diff --git a/contrib/nitiwiki/src/wiki_base.nit b/contrib/nitiwiki/src/wiki_base.nit index 5f093a0..70cf35f 100644 --- a/contrib/nitiwiki/src/wiki_base.nit +++ b/contrib/nitiwiki/src/wiki_base.nit @@ -615,7 +615,7 @@ class WikiConfig super ConfigTree # Returns the config value at `key` or return `default` if no key was found. - private fun value_or_default(key: String, default: String): String do + protected fun value_or_default(key: String, default: String): String do return self[key] or else default end diff --git a/contrib/nitiwiki/src/wiki_links.nit b/contrib/nitiwiki/src/wiki_links.nit index 340ec74..efb9f78 100644 --- a/contrib/nitiwiki/src/wiki_links.nit +++ b/contrib/nitiwiki/src/wiki_links.nit @@ -214,7 +214,8 @@ class NitiwikiMdProcessor end end -private class NitiwikiDecorator +# The decorator associated to `MarkdownProcessor`. +class NitiwikiDecorator super HTMLDecorator # Wiki used to resolve links. diff --git a/examples/mnit_ballz/Makefile b/examples/mnit_ballz/Makefile index 337c69a..4120b52 100644 --- a/examples/mnit_ballz/Makefile +++ b/examples/mnit_ballz/Makefile @@ -1,4 +1,4 @@ -default: android +default: linux ../../contrib/inkscape_tools/bin/svg_to_icons: $(MAKE) -C ../../contrib/inkscape_tools @@ -7,6 +7,10 @@ android: icon mkdir -p bin ../../bin/nitc -o bin/ballz.apk src/ballz_android.nit +linux: + mkdir -p bin + ../../bin/nitc -o bin/ballz src/ballz_linux.nit + icon: ../../contrib/inkscape_tools/bin/svg_to_icons mkdir -p res ../../contrib/inkscape_tools/bin/svg_to_icons art/ball.svg --android --out res/ diff --git a/examples/mnit_ballz/assets/images/horizontal_wall.png b/examples/mnit_ballz/assets/images/horizontal_wall.png new file mode 100644 index 0000000..7ba6c68 Binary files /dev/null and b/examples/mnit_ballz/assets/images/horizontal_wall.png differ diff --git a/examples/mnit_ballz/assets/images/vertical_wall.png b/examples/mnit_ballz/assets/images/vertical_wall.png new file mode 100644 index 0000000..da42302 Binary files /dev/null and b/examples/mnit_ballz/assets/images/vertical_wall.png differ diff --git a/examples/mnit_ballz/res/raw/bounce.ogg b/examples/mnit_ballz/res/raw/bounce.ogg new file mode 100644 index 0000000..bcd66dd Binary files /dev/null and b/examples/mnit_ballz/res/raw/bounce.ogg differ diff --git a/examples/mnit_ballz/res/raw/walld.wav b/examples/mnit_ballz/res/raw/walld.wav new file mode 100644 index 0000000..f61d065 Binary files /dev/null and b/examples/mnit_ballz/res/raw/walld.wav differ diff --git a/examples/mnit_ballz/src/assets.nit b/examples/mnit_ballz/src/assets.nit new file mode 100644 index 0000000..e823284 --- /dev/null +++ b/examples/mnit_ballz/src/assets.nit @@ -0,0 +1,49 @@ +# 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. + + +# All the assets needed by the appplication, regrouped in one class +module assets + +import app::audio +import mnit::assets + + +# Contains all the assets +class Assets + + # Sound for the wall destruction + var wall_destruction = new Sound("walld.wav") + + # Sound when the ball bounce + var bounce = new Sound("bounce.ogg") + + # Image of the ball + var ball: Image is noinit + + # Image for the horizontal walls + var horizontal_wall: Image is noinit + + # Image for the vertical walls + var vertical_wall: Image is noinit + + # Loads all the assets + fun load do + ball = app.load_image("images/ball.png") + horizontal_wall = app.load_image("images/horizontal_wall.png") + vertical_wall = app.load_image("images/vertical_wall.png") + wall_destruction.load + bounce.load + end +end diff --git a/examples/mnit_ballz/src/ballz_android.nit b/examples/mnit_ballz/src/ballz_android.nit index 249ee68..dc934e7 100644 --- a/examples/mnit_ballz/src/ballz_android.nit +++ b/examples/mnit_ballz/src/ballz_android.nit @@ -1,7 +1,5 @@ # this file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2014 Romain Chanoir -# # 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 @@ -14,22 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. + +# Android part of mnit_ballz module ballz_android is - app_version(1, 0, git_revision) + app_version(0, 2, git_revision) app_name("Ballz") + app_namespace "org.nitlanguage.ballz" + android_api_target 19 end import android::portrait - -import game_logic +import android::sensors +import display +import mnit::android redef class App - var screen: nullable Screen + # The game + var game: nullable Game is noautoinit - redef fun run - do - sensors_support_enabled = true + redef fun run do accelerometer.enabled = true accelerometer.event_rate = 10000 magnetic_field.enabled = true @@ -37,33 +39,72 @@ redef class App light.enabled = true proximity.enabled = true maximum_fps = 50 - + sensors_support_enabled = true super end redef fun on_create do super - screen = new Screen(self, display.as(Display)) + game = new Game(display.width.to_f, display.height.to_f) end redef fun frame_core(display) do - var screen = self.screen - if screen != null then - screen.game.do_turn - screen.do_frame(display) + var game = game + if game != null then + game.do_turn + game.draw(display, assets) end end redef fun input(ie) - do - if ie isa QuitEvent then + do + if paused then return false + if ie isa QuitEvent then quit = true return true end - if screen != null then - return screen.input(ie) + var game = game + if game != null then + return game.input(ie) + end + return false + end +end + +redef class Ball + + redef fun intercepts(event) + do + if event isa ASensorAccelerometer then + acceleration(event.x, event.y) + else if event isa ASensorMagneticField then + #deal with Magnetic field sensor + #print "ASensorMagneticField : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s + else if event isa ASensorGyroscope then + #deal with Gyroscope sensor + #print "ASensorGyroscope : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s + else if event isa ASensorLight then + #deal with light sensor + #print "ASensorLight : light = " + event.light.to_s + else if event isa ASensorProximity then + #deal with proximity sensor + #print "ASensorProximity : distance = " + event.distance.to_s + else if event isa MotionEvent then + end + return true + end +end + + +redef class Game + + redef fun input(ie) + do + if ie isa ASensorAccelerometer or ie isa MotionEvent then + ball.intercepts(ie) + return true end return false end diff --git a/examples/mnit_ballz/src/ballz_linux.nit b/examples/mnit_ballz/src/ballz_linux.nit new file mode 100644 index 0000000..6f089a8 --- /dev/null +++ b/examples/mnit_ballz/src/ballz_linux.nit @@ -0,0 +1,104 @@ +# 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. + +# Linux part of mnit_ballz +module ballz_linux + +import mnit::linux +import display + + +redef class App + + private var up_arrow_down = false + private var down_arrow_down = false + private var left_arrow_down = false + private var right_arrow_down = false + private var game: nullable Game is noautoinit + + redef fun run + do + maximum_fps = 50 + super + end + + redef fun on_create + do + super + game = new Game(display.width.to_f, display.height.to_f) + end + + redef fun frame_core(display) + do + if up_arrow_down then input(new SDLKeyEvent("up", true)) + if down_arrow_down then input(new SDLKeyEvent("down", true)) + if left_arrow_down then input(new SDLKeyEvent("left", true)) + if right_arrow_down then input(new SDLKeyEvent("right", true)) + + var game = game + if game != null then + game.do_turn + game.draw(display, assets) + end + end + + redef fun input(ie) + do + if ie isa QuitEvent then + quit = true + return true + end + var game = game + if game != null then + return game.input(ie) + end + return false + end +end + +redef class Ball + + redef fun intercepts(event) + do + var value = 5.0 + if event isa SDLKeyEvent then + if event.is_arrow_left then + acceleration(value, 0.0) + app.left_arrow_down = event.is_down + end + if event.is_arrow_right then + acceleration(-value, 0.0) + app.right_arrow_down = event.is_down + end + if event.is_arrow_up then + acceleration(0.0, -value) + app.up_arrow_down = event.is_down + end + if event.is_arrow_down then + acceleration(0.0, value) + app.down_arrow_down = event.is_down + end + end + return false + end +end + +redef class Game + + redef fun input(ie) + do + ball.intercepts(ie) + return false + end +end diff --git a/examples/mnit_ballz/src/collision.nit b/examples/mnit_ballz/src/collision.nit new file mode 100644 index 0000000..825cedc --- /dev/null +++ b/examples/mnit_ballz/src/collision.nit @@ -0,0 +1,87 @@ +# 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. + +# Geometric computations around vectors and points for collision detection +module collision + +import geometry + +# trigonometry + +# Get the distance between `p1` and `p2` +fun distance(p1, p2: Point[Float]): Float +do + var x = p1.x - p2.x + var y = p1.y - p2.y + return ( x * x + y * y ).sqrt +end + +# Get the magnitude (length) of `vector` +fun magnitude(vector: Point[Float]): Float do return ( vector.x * vector.x + vector.y * vector.y ).sqrt + +# Get the unit vector of `vector` +fun unit_vector(vector: Point[Float]): Point[Float] do return new Point[Float](vector.x / magnitude(vector), vector.y / magnitude(vector)) + +# Get the dot product of vectors `v1` and `v2` +fun dot_product(v1, v2: Point[Float]): Float do return v1.x * v2.x + v1.y * v2.y + +# Get the vector between `start_point` and `end_point` +fun vector_between(start_point, end_point: Point[Float]): Point[Float] do return new Point[Float](end_point.x - start_point.x, end_point.y - start_point.y) + +# Returns the point on a line with endpoints `l1` and `l2` closest to `center` +fun point_closest_to_line(center, l1, l2: Point[Float]): Point[Float] +do + var luvector = unit_vector(vector_between(l1, l2)) + var l_to_ball = vector_between(l1, center) + + var projection = dot_product(l_to_ball, luvector) + + if projection <= 0.0 then return l1 + if projection >= distance(l1, l2) then return l2 + return new Point[Float](l1.x + luvector.x * projection, l1.y + luvector.y * projection) +end + +# Is the ball with the `center` and `radius` intersecting the line with the endpoints `l1` and `l2`? +fun is_intersecting(center, l1, l2: Point[Float], radius: Float): Bool +do + var closest = point_closest_to_line(center, l1, l2) + var distance = distance(center, closest) + return distance < radius +end + +# Bouncing function, returns the new point of the center of the ball +fun bounce(center, l1, l2, offset: Point[Float]): Point[Float] +do + var bln = bounce_line_normal(center, l1, l2) + var dot = dot_product(offset, bln) + return new Point[Float](offset.x - (2.0 * dot * bln.x), offset.y - (2.0 * dot * bln.y)) +end + +private fun bounce_line_normal(center, l1, l2: Point[Float]): Point[Float] +do + var p = point_closest_to_line(center, l1, l2) + var v = vector_between(p, center) + return unit_vector(v) +end + +# Rotate `p` around `center` through `angle` +fun rotate_point(p, center: Point[Float], angle: Float): Point[Float] +do + var s = angle.sin + var c = angle.cos + + var nx = c * (p.x - center.x) - s * (p.y - center.y) + center.x + var ny = s * (p.x - center.x) + c * (p.y - center.y) + center.y + return new Point[Float](nx, ny) +end diff --git a/examples/mnit_ballz/src/display.nit b/examples/mnit_ballz/src/display.nit new file mode 100644 index 0000000..1d63189 --- /dev/null +++ b/examples/mnit_ballz/src/display.nit @@ -0,0 +1,47 @@ +# 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. + +# Handles the drawing of all the game +module display + +import game_logic + +redef class Ball + + # Draw `self` onto `display` with image from `assets` + fun draw(display: Display, assets: Assets) + do + display.blit_centered(assets.ball, center.x, center.y) + end +end + +redef class Wall + + # Draw `self` onto `display` with image from `assets` + fun draw(display: Display, assets: Assets) + do + display.blit_rotated(assets.vertical_wall, center.x, center.y, angle) + end +end + +redef class Game + + # Draw all the entities onto `display` + fun draw(display: Display, assets: Assets) + do + display.clear (0.0, 0.0, 0.0) + ball.draw(display, assets) + for wall in walls do wall.draw(display, assets) + end +end diff --git a/examples/mnit_ballz/src/game_logic.nit b/examples/mnit_ballz/src/game_logic.nit index 7ece167..38d7682 100644 --- a/examples/mnit_ballz/src/game_logic.nit +++ b/examples/mnit_ballz/src/game_logic.nit @@ -1,7 +1,5 @@ #this file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2014 Romain Chanoir -# # 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 @@ -14,167 +12,172 @@ # See the License for the specific language governing permissions and # limitations under the License. +# All the logic of the game module game_logic -import mnit::android -import android::sensors +import assets +import objects +import geometry::quadtree +import collision -class Ball - var x: Float - var y: Float - var dim: Int - var walls_activated: Bool - var offset_x = 0.0 - var offset_y = 0.0 - var going_left: Bool - var going_down: Bool +redef class Ball - var game: Game + # Scale for drawing the image of `self` + var scale = 1.0 - init(game: Game, x,y: Float, walls: Bool) - do - self.x = x - self.y = y - self.dim = 20 - self.game = game - self.walls_activated = walls - end + # ASensorProximity value for modifying `scale` + # Not used yet + var scale_proximity_modifier = 6.0 + + # Radius of `self` + var radius = 32.0 + + # Movement vector of `self` + var offset = new Point[Float](0.0, 0.0) - # not very useful at this time - fun do_turn + # Calculates the acceleration of `self` + fun acceleration(x,y: Float) do + var max_offset = 10.0 + var max_value = 9.80 + var offset_x = offset.x - x/max_value + var offset_y = offset.y + y/max_value + if offset_x > max_offset then offset_x = max_offset + if offset_x < -max_offset then offset_x = -max_offset + if offset_y > max_offset then offset_y = max_offset + if offset_y < -max_offset then offset_y = -max_offset + offset = new Point[Float](offset_x, offset_y) end - fun intercepts(event: InputEvent): Bool + # Do the collision detection, then move `self`consequently + fun do_turn(game: Game) do - if event isa ASensorAccelerometer then - do_move(event) - else if event isa ASensorMagneticField then - #deal with Magnetic field sensor - print "ASensorMagneticField : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s - else if event isa ASensorGyroscope then - #deal with Gyroscope sensor - print "ASensorGyroscope : x = " + event.x.to_s + " y = " + event.y.to_s + " z = " + event.z.to_s - else if event isa ASensorLight then - #deal with light sensor - print "ASensorLight : light = " + event.light.to_s - else if event isa ASensorProximity then - #deal with proximity sensor - print "ASensorProximity : distance = " + event.distance.to_s - else if event isa MotionEvent then - activate_walls(event) + offset = new Point[Float](offset.x * 0.98, offset.y * 0.98) + var np = collision(game.quadtree) + if np != null then + offset = np + center = new Point[Float](center.x + offset.x, center.y + offset.y) + else + center = new Point[Float](center.x + offset.x, center.y + offset.y) end - return true end - fun do_move (event: ASensorAccelerometer) + # Collision detection + fun collision(quadtree: SQuadTree[OrientedLine]): nullable Point[Float] do - # acceleration value - var vx = event.x - var vy = event.y - var gw = game.width - var gh = game.height - - # acceleration - var max_value = 9.80 - var acceleration_x = vx/max_value - var acceleration_y = vy/max_value - offset_x -= (acceleration_x/10.0)*(vx.abs) + offset_x/125.0 - offset_y += (acceleration_y/10.0)*(vy.abs) - offset_y/125.0 - var nx = self.x + offset_x - var ny = self.y + offset_y - going_left = offset_x > 0.0 - going_down = offset_y > 0.0 - - # x value - if nx >= 0.0 and nx <= gw then - self.x = nx - else if nx < 0.0 then - if not walls_activated then self.x = gw else do_bounce(1) - else if nx > gw then - if not walls_activated then self.x = 0.0 else do_bounce(1) + var nx = self.center.x + offset.x + var ny = self.center.y + offset.y + var new_center = new Point[Float](nx, ny) + var effective_radius = radius*scale + # Lines intersecting with the ball + var intersecting_lines = new Array[OrientedLine] + + # Line intersecting closest to the ball + var intersecting_line: nullable OrientedLine = null + + # closest point of the intersecting line + var closest_point: nullable Point[Float] = null + + # get the intersecting lines with help of the quadtree + var lines = quadtree.items_overlapping(new_center.padded(effective_radius)) + for l in lines do + if is_intersecting(new_center, l.point_left, l.point_right, effective_radius) then + intersecting_lines.add(l) + end end - # y value - if ny >= 0.0 and ny <= gh then - self.y = ny - else if ny < 0.0 then - if not walls_activated then self.y = gh else do_bounce(2) - else if ny > gh then - if not walls_activated then self.y = 0.0 else do_bounce(2) + # get the line closest to the ball from the intersecting lines, setting the closest point + var min_dist = 100.0 + if intersecting_lines.length >= 2 then + for l in intersecting_lines do + var closest = point_closest_to_line(new_center, l.point_left, l.point_right) + var distance = distance(closest, new_center) + if distance < min_dist then + min_dist = distance + intersecting_line = l + closest_point = closest + end + end + else if intersecting_lines.length == 1 then + intersecting_line = intersecting_lines[0] + closest_point = point_closest_to_line(new_center, intersecting_line.point_left, intersecting_line.point_right) end - end - # bounce in function of the position of the wall relative to the ball: 1=left or right, 2=top or down - fun do_bounce(wall_position: Int) - do - if wall_position == 1 then - offset_x = -offset_x*0.85 - else if wall_position == 2 then - offset_y = -offset_y*0.85 - end - if offset_x.abs > 1.0 and offset_y.abs > 1.0 then - self.x += offset_x - self.y += offset_y + if intersecting_line != null and closest_point != null then + return bounce(center, intersecting_line.point_left, intersecting_line.point_right, offset) end + return null end - fun activate_walls(event: MotionEvent) - do - if event.just_went_down then - walls_activated = not walls_activated - end - end + # Event interception + fun intercepts(event: InputEvent): Bool is abstract end -class Screen - var ball_img: Image - var game: Game - - init(app: App, display: Display) - do - game = new Game(display) - ball_img = app.load_asset("images/ball.png").as(Image) - var scale = game.img_dim.to_f / game.img_ori_dim.to_f - ball_img.scale = scale - ball_img.scale = 3.0 - end +# The core of the game +class Game - fun do_frame(display: Display) - do - display.clear(0.0, 0.0, 0.0) - display.blit_rotated(ball_img, game.ball.x, game.ball.y, 0.0) - end + # The Ball! + var ball: Ball is noinit - fun input(ie: InputEvent): Bool - do - if ie isa ASensorProximity then - if ie.distance == 0.0 then ball_img.scale = 6.0 else ball_img.scale = 3.0 - else - game.ball.intercepts(ie) - end - return true - end -end + # List of walls in the level + var walls: Array[Wall] is noinit -class Game - var ball: Ball + # Width of the display var width: Float + + # Heightof the display var height: Float - var img_ori_dim: Int = 256 - fun img_dim: Int do return 210 + # Quadtree used for collision detection + var quadtree: SQuadTree[OrientedLine] is noinit - init(display: Display) + init do - width = display.width.to_f - height = display.height.to_f - ball = new Ball(self, width/2.0, height/2.0, false) + ball = new Ball(new Point[Float](width/2.0, height/2.0)) + # Walls initialisation + var walla = new Wall(new Point[Float](width/4.0, height/4.0), pi/3.0, 1.0) + var wallb = new Wall(new Point[Float](width*0.75, height/4.0), 0.0, 1.0) + var wallc = new Wall(new Point[Float](width/4.0, height*0.75), 0.0, 1.0) + var walld = new Wall(new Point[Float](width*0.75, height*0.75), pi/3.0, 1.0) + walls = new Array[Wall].with_items(walla, wallb, wallc, walld) + + # adding screen bordures + var i = new Point[Float](0.0,0.0) + var a = new Point[Float](0.0, height/2.0) + var b = new Point[Float](width/2.0, 0.0) + var c = new Point[Float](width, height/2.0) + var d = new Point[Float](width/2.0, height) + + var l1 = new OrientedLine(i, i, pi/2.0, height, a) + var l2 = new OrientedLine(i, i, 0.0, width, b) + var l3 = new OrientedLine(i, i, pi/2.0, height, c) + var l4 = new OrientedLine(i, i, 0.0, width, d) + + quadtree = new SQuadTree[OrientedLine](5, width, height) + for w in walls do for l in w.lines do + quadtree.add(l) + end + quadtree.add(l1) + quadtree.add(l2) + quadtree.add(l3) + quadtree.add(l4) end - fun do_turn - do - ball.do_turn + # Only calls `do_turn` of the ball for the moment + fun do_turn do ball.do_turn(self) + + # Input gestion + fun input(ie: InputEvent): Bool do return false +end + +redef class App + + # Assets used in all the app + var assets = new Assets + + redef fun on_create do + super + assets.load end end diff --git a/examples/mnit_ballz/src/objects.nit b/examples/mnit_ballz/src/objects.nit new file mode 100644 index 0000000..d8e1686 --- /dev/null +++ b/examples/mnit_ballz/src/objects.nit @@ -0,0 +1,100 @@ +# 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. + +# Module containing all objects of the game +module objects + +import geometry +import geometry::polygon +import geometry::boxes +import collision + +# The ball is the main character of the game! +class Ball + # Center of the ball + var center: Point[Float] is writable +end + +# Walls make the ball bounce on them +class Wall + # Coordinates of the center of the wall + var center: Point[Float] + + # Angle in radian + var angle: Float + + # Scale for drawing `self` + var scale: Float + + # Width of `self` + var width: Float is noautoinit + + # Height of `self` + var height: Float is noautoinit + + # Lines composing `self` + var lines: Array[OrientedLine] is noautoinit + + # Initialize `self` with all its lines from `center` and `angle` + init do + self.height = 128.0 + self.width = 32.0 + var i = new Point[Float](0.0, 0.0) + var j = new Point[Float](0.0, 0.0) + + var a = new Point[Float]((center.x - width/2.0), center.y) + var b = new Point[Float]((center.x), (center.y - height/2.0)) + var c = new Point[Float]((center.x + width/2.0), center.y) + var d = new Point[Float]((center.x), (center.y + height/2.0)) + + var l1 = new OrientedLine(i, j, angle - pi/2.0, height * scale.to_f, rotate_point(a, center, angle)) + var l2 = new OrientedLine(i, j, angle, width * scale.to_f, rotate_point(b, center, angle)) + var l3 = new OrientedLine(i, j, angle - pi/2.0, height * scale.to_f, rotate_point(c, center, angle)) + var l4 = new OrientedLine(i, j, angle, width * scale.to_f, rotate_point(d, center, angle)) + lines = new Array[OrientedLine] + lines.add_all([l1, l2, l3, l4]) + end +end + +# A line represented with a center and an angle +class OrientedLine + super Line[Float] + redef type P: Point[Float] + + # Angle in radian + var angle: Float is writable + + # Length + var length: Float + + # Center + var center: Point[Float] + + redef fun point_left + do + var luv = unit_vector(new Point[Float](angle.cos, angle.sin)) + var offset_from_center = new Point[Float](luv.x * (length / 2.0), luv.y * (length / 2.0)) + return new Point[Float](center.x + offset_from_center.x, center.y + offset_from_center.y) + end + + redef fun point_right + do + var luv = unit_vector(new Point[Float](angle.cos, angle.sin)) + var offset_from_center = new Point[Float](luv.x * length / 2.0, luv.y * length / 2.0) + return new Point[Float](center.x - offset_from_center.x, center.y - offset_from_center.y) + end + + redef fun left do return point_left.x.min(point_right.x) + redef fun right do return point_left.x.max(point_right.x) +end diff --git a/lib/android/audio.nit b/lib/android/audio.nit index c70dd40..b729219 100644 --- a/lib/android/audio.nit +++ b/lib/android/audio.nit @@ -483,7 +483,7 @@ class MediaPlayer end redef class PlayableAudio - redef init do app.add_to_sounds(self) + redef init do add_to_sounds(self) end redef class Sound @@ -617,9 +617,6 @@ end redef class App - # Sounds handled by the application, when you load a sound, it's added to this list. - # This array is used in `pause` and `resume` - private var sounds = new Array[PlayableAudio] # Returns the default MediaPlayer of the application. # When you load a music, it goes in this MediaPlayer. @@ -676,12 +673,6 @@ redef class App return add_to_sounds(default_mediaplayer.load_sound(resource_manager.raw_id(music), self.native_activity)).as(Music) end - # Factorizes `sounds.add` to use it in `load_music`, `load_sound`, `load_music_from_res` and `load_sound_from_res` - private fun add_to_sounds(sound: PlayableAudio): PlayableAudio do - sounds.add(sound) - return sound - end - redef fun on_pause do super for s in sounds do s.pause @@ -700,3 +691,16 @@ redef class App for s in sounds do s.resume end end + +redef class Sys + + # Sounds handled by the application, when you load a sound, it's added to this list. + # This array is used in `pause` and `resume` + private var sounds = new Array[PlayableAudio] + + # Factorizes `sounds.add` to use it in `load_music`, `load_sound`, `load_music_from_res` and `load_sound_from_res` + private fun add_to_sounds(sound: PlayableAudio): PlayableAudio do + sounds.add(sound) + return sound + end +end diff --git a/lib/android/sensors.nit b/lib/android/sensors.nit index 3ee9765..b969389 100644 --- a/lib/android/sensors.nit +++ b/lib/android/sensors.nit @@ -20,19 +20,19 @@ # # ~~~~nitish # #FIXME rewrite the example -# var app = new MyApp -# app.sensors_support_enabled = true -# app.accelerometer.enabled = true -# app.accelerometer.eventrate = 10000 -# app.magnetic_field.enabled = true -# app.gyroscope.enabled = true -# app.light.enabled = true -# app.proximity.enabled = true -# app.main_loop +# redef class App +# sensors_support_enabled = true +# accelerometer.enabled = true +# accelerometer.eventrate = 10000 +# magnetic_field.enabled = true +# gyroscope.enabled = true +# light.enabled = true +# proximity.enabled = true +# end # ~~~~ # -# In this example, we enable the sensor support, then enable all types of sensors supported, before running the app. -# The result is you get all type of SensorEvent (ASensorAccelerometer, ASensorMagneticField ...) in the input method of your app +# In this example, we enable the sensor support, then enable all types of sensors supported by the API, directly with `App` attributes +# As a result, you get all type of SensorEvent (ASensorAccelerometer, ASensorMagneticField ...) in the `input` callback of `App` module sensors import android @@ -270,8 +270,8 @@ redef class App private fun enable_accelerometer do accelerometer.asensor = sensormanager.get_default_sensor(new ASensorType.accelerometer) - if accelerometer.asensor.address_is_null then - print "Accelerometer sensor unavailable" + if accelerometer.asensor.address_is_null then + print "Accelerometer sensor unavailable" else if eventqueue.enable_sensor(accelerometer.asensor) < 0 then print "Accelerometer enabling failed" eventqueue.set_event_rate(accelerometer.asensor, accelerometer.event_rate) @@ -314,7 +314,7 @@ redef class App private fun enable_proximity do proximity.asensor = sensormanager.get_default_sensor(new ASensorType.proximity) - if proximity.asensor.address_is_null then + if proximity.asensor.address_is_null then print "Proximity sensor unavailable" else if eventqueue.enable_sensor(proximity.asensor) < 0 then print "Proximity enabling failed" diff --git a/lib/markdown/markdown.nit b/lib/markdown/markdown.nit index 1bb8815..b9e2f6a 100644 --- a/lib/markdown/markdown.nit +++ b/lib/markdown/markdown.nit @@ -758,8 +758,11 @@ class HTMLDecorator end redef fun add_code(v, block) do - if block isa BlockFence and block.meta != null then - v.add "
"
+		var meta = block.meta
+		if meta != null then
+			v.add "
"
 		else
 			v.add "
"
 		end
@@ -1173,6 +1176,26 @@ abstract class Block
 			block = block.next
 		end
 	end
+
+	# The raw content of the block as a multi-line string.
+	fun raw_content: String do
+		var infence = self isa BlockFence
+		var text = new FlatBuffer
+		var line = self.block.first_line
+		while line != null do
+			if not line.is_empty then
+				var str = line.value
+				if not infence and str.has_prefix("    ") then
+					text.append str.substring(4, str.length - line.trailing)
+				else
+					text.append str
+				end
+			end
+			text.append "\n"
+			line = line.next
+		end
+		return text.write_to_string
+	end
 end
 
 # A block without any markdown specificities.
@@ -1213,6 +1236,9 @@ end
 class BlockCode
 	super Block
 
+	# Any string found after fence token.
+	var meta: nullable Text
+
 	# Number of char to skip at the beginning of the line.
 	#
 	# Block code lines start at 4 spaces.
@@ -1239,9 +1265,6 @@ end
 class BlockFence
 	super BlockCode
 
-	# Any string found after fence token.
-	var meta: nullable Text
-
 	# Fence code lines start at 0 spaces.
 	redef var line_start = 0
 end
diff --git a/src/doc/doc_down.nit b/src/doc/doc_down.nit
index 5284dc1..e04abb9 100644
--- a/src/doc/doc_down.nit
+++ b/src/doc/doc_down.nit
@@ -99,10 +99,8 @@ private class NitdocDecorator
 	var toolcontext = new ToolContext
 
 	redef fun add_code(v, block) do
-		var meta = "nit"
-		if block isa BlockFence and block.meta != null then
-			meta = block.meta.to_s
-		end
+		var meta = block.meta or else "nit"
+
 		# Do not try to highlight non-nit code.
 		if meta != "nit" and meta != "nitish" then
 			v.add "
"
@@ -111,7 +109,7 @@ private class NitdocDecorator
 			return
 		end
 		# Try to parse code
-		var code = code_from_block(block)
+		var code = block.raw_content
 		var ast = toolcontext.parse_something(code)
 		if ast isa AError then
 			v.add "
"
@@ -150,25 +148,6 @@ private class NitdocDecorator
 		for i in [from..to[ do out.add buffer[i]
 		return out.write_to_string
 	end
-
-	fun code_from_block(block: BlockCode): String do
-		var infence = block isa BlockFence
-		var text = new FlatBuffer
-		var line = block.block.first_line
-		while line != null do
-			if not line.is_empty then
-				var str = line.value
-				if not infence and str.has_prefix("    ") then
-					text.append str.substring(4, str.length - line.trailing)
-				else
-					text.append str
-				end
-			end
-			text.append "\n"
-			line = line.next
-		end
-		return text.write_to_string
-	end
 end
 
 # Decorator for span elements.
diff --git a/src/nitcatalog.nit b/src/nitcatalog.nit
index c843b51..ba0cb1c 100644
--- a/src/nitcatalog.nit
+++ b/src/nitcatalog.nit
@@ -25,7 +25,7 @@
 # * [X] generate a page per package with the readme and most metadata
 # * [ ] link/include/be included in the documentation
 # * [ ] propose `related packages`
-# * [ ] show directory content (a la nitls)
+# * [X] show directory content (a la nitls)
 # * [X] gather git information from the working directory
 # * [ ] gather git information from the repository
 # * [ ] gather package information from github
@@ -33,7 +33,7 @@
 # * [ ] reify people
 # * [ ] separate information gathering from rendering
 # * [ ] move up information gathering in (existing or new) service modules
-# * [ ] add command line options
+# * [X] add command line options
 # * [ ] harden HTML (escaping, path injection, etc)
 # * [ ] nitcorn server with RESTful API
 #
@@ -238,6 +238,34 @@ class Catalog
 		res.add ""
 	end
 
+	# Recursively generate a level in the file tree of the *content* section
+	private fun gen_content_level(ot: OrderedTree[Object], os: Array[Object], res: Template)
+	do
+		res.add "
    \n" + for o in os do + res.add "
  • " + if o isa MGroup then + var d = "" + var mdoc = o.mdoc + if mdoc != null then d = ": {mdoc.html_synopsis.write_to_string}" + res.add "{o.name}{d} ({o.filepath.to_s})" + else if o isa ModulePath then + var d = "" + var m = o.mmodule + if m != null then + var mdoc = m.mdoc + if mdoc != null then d = ": {mdoc.html_synopsis.write_to_string}" + end + res.add "{o.name}{d} ({o.filepath.to_s})" + else + abort + end + var subs = ot.sub.get_or_null(o) + if subs != null then gen_content_level(ot, subs, res) + res.add "
  • \n" + end + res.add "
\n" + end # Compute information and generate a full HTML page for a package fun package_page(mpackage: MPackage): Writable @@ -257,6 +285,23 @@ class Catalog res.add mdoc.html_documentation score += mdoc.content.length.score end + + res.add "

Content

" + var ot = new OrderedTree[Object] + for g in mpackage.mgroups do + var pa = g.parent + if g.is_interesting then + ot.add(pa, g) + pa = g + end + for mp in g.module_paths do + ot.add(pa, mp) + end + end + ot.sort_with(alpha_comparator) + gen_content_level(ot, ot.roots, res) + + res.add """