[Sheet] Minor typos

[Sheet] Minor typos

Jelli Game Engine

#  Sheet  #

The `Sheet` constructor generates sprite-sheets and manages their rendering on a `CanvasRenderingContext2D`.
It is packaged with `Sprite`, which describes a single sprite on the sheet.

##  General functions  ##

The function `drawSprite()` is called by `Sprite`s and `Sheet`s in order to draw their images.
It is not exposed to the window.

    drawSprite = (sheet, start_index, context, x, y, frame = 1) ->

…That's a lot of arguments. Let's go through them:

- `sheet` is the `Sheet` from which to draw the sprite
- `start_index` gives us the index of the sprite within the sheet
- `context` is the `CanvasRenderingContext2D` on which to draw the sprite
- `x` is the x-coordinate of the top-left corner of the sprite
- `y` is the y-coordinate of the top-left corner of the sprite
- `frame` is merely there as a convenience: It increments `start_index` by its value

The first thing we do is make sure everything is typed correctly.
The `sheet` and `context`, clearly, need to be of a certain type in order for this to work.
If any of the other provided arguments aren't numbers, however, we can go ahead and reset them to zero.

        unless sheet instanceof Sheet and start_index < sheet.size and context instanceof CanvasRenderingContext2D then return
        if isNaN(start_index = Number(start_index)) then start_index = 0
        if isNaN(x = Number(x)) then x = 0
        if isNaN(y = Number(y)) then y = 0
        if isNaN(frame = Number(frame)) then frame = 0

Now we can increment `start_index` by `frame`'s value:

        `start_index` += frame

Next, we need to find the horizontal (`i`) and vertical (`j`) position of the sprite on the sheet.
We can get this information from `start_index` with a little math:

        i = start_index % sheet.width
        j = Math.floor start_index / sheet.width

These two lines just make the image a little easier to access:

        source = sheet.source
        image = sheet.image

Now we have all we need to draw the sprite!
There is a HUGE `if`-statement that precedes the draw function, because we want to make sure that what we're drawing is actually there.
If it isn't, then obviously we can't draw anything.

        if (source instanceof HTMLImageElement and source.complete or source instanceof SVGImageElement or source instanceof HTMLCanvasElement or createImageBitmap? and (image instanceof ImageBitmap or source instanceof ImageBitmap)) and not isNaN(i) and not isNaN(j) and Number(width = sheet.sprite_width) and Number(height = sheet.sprite_height) then context.drawImage (if createImageBitmap? and image instanceof ImageBitmap then image else source), i * width, j * height, width, height, x, y, width, height

Let's go through what those did.
First, we make sure that the `Sheet` actually has an image associated with it:

-   `source instanceof HTMLImageElement and source.complete`—
    If the image source is an `<img>` element, then it needs to have finished loading.

-   `source instanceof SVGImageElement or source instanceof HTMLCanvasElement`—
    The source doesn't have to be an `<img>` element though! It can also be an `<svg>` or a `<canvas>`.

-   `createImageBitmap? and (image instanceof ImageBitmap or source instanceof ImageBitmap)`—
    Finally, the source can be an `ImageBitmap`.
    This isn't supported in all browsers, so we check to make sure `createImageBitmap` exists first.
    However, if `createImageBitmap` *is* supported, then `Sheet`s have a special property, `Sheet.image`, which might contain one, and this should be given preference.

We also need to make sure that the sprite exists on the sheet:

-   `not isNaN(i) and not isNaN(j)`—
    This makes sure that our indices are actually, y'know, numbers.

-   `Number(width = sheet.sprite_width) and Number(height = sheet.sprite_height)`—
    This makes sure that the sprites in the sheet have a non-zero width and height.
    It also sets the variables `width` and `height` to those values, for convenient access later.

Finally, we can draw the sprite.
Again, we preference `image` if it is defined.

##  Sprite  ##

The `Sprite` constructor creates a reference to a sprite on a sheet.
For efficiency's sake, it does *not* actually contain any of the image data associated with that sprite.
The constructor takes three arguments: `sheet`, which gives the sheet; `index`, which is the index of the sprite on the sheet; and `length`, which for animated sprites gives the length of the animation.

    Sprite = (sheet, index, length = 1) ->

If `index` or `length` aren't numbers, then we go ahead and set them to `0` and `1`, respectively.

        if isNaN(index = Number(index)) then index = 0
        if isNaN(length = Number(length)) then length = 1

Now we can set the properties.
Note that `draw` simply binds `drawSprite` to the given `Sheet` and `index`.

        @draw = drawSprite.bind(null, sheet, index)
        @height = if sheet instanceof Sheet then sheet.sprite_height else 0
        @index = index
        @frames = length
        @sheet = if sheet instanceof Sheet then sheet else null
        @width = if sheet instanceof Sheet then sheet.sprite_width else 0

Since `Sprite`s are just static references, they should be immutable:

        Object.freeze this

And we're done!

`Sprite`s are very simple, and because the `draw` function is bound above, they don't have a prototype.
For purposes of inheritance, however, I've thrown this minimal one together:

    Sprite.prototype = {draw: ->}
    Object.freeze Sprite.prototype

##  Sheet  ##

`Sheet`s associate images with data and methods to make them easily referencable as sprite-sheets.

###  The constructor  ###

The `Sheet` constructor only takes three arguments: `source`, which gives the source image for the sheet, `sprite_width`, which gives the width of the sprites, and `sprite_height`, which gives their height.
In doing so, it makes the assumption that sprites and sprite-sheets do not have any borders or padding.
(Because borders and padding result in larger download times for users, this restriction is considered acceptable, but it may be lifted at some time in the future.)

    Sheet = (source, sprite_width, sprite_height) ->

First, we need to handle the arguments.
If `source` isn't an image type that we recognize, we go ahead and set it to `null`.
And if the `sprite_width` or `sprite_height` aren't recognizable as numbers, we set them to 0.
(Note from the above that a `Sheet` with zero `sprite_width` or `sprite_height` cannot be drawn.)

        unless source instanceof HTMLImageElement or source instanceof SVGImageElement or source instanceof HTMLCanvasElement or createImageBitmap? and source instanceof ImageBitmap then source = null
        if isNaN(sprite_width = Number(sprite_width)) then sprite_width = 0
        if isNaN(sprite_height = Number(sprite_height)) then sprite_height = 0

Recall that we need to check for `createImageBitmap` before checking to see if the source is an `ImageBitmap`.

We can get the width and height of the image from one of two sources, depending on the source type.
All of the accepted types have `width` and `height` properties, which specify their dimensions.
However, `HTMLImageElement`s also have `naturalWidth` and `naturalHeight` properties, and these should be preferred for pixel-perfect rendering.

If for some reason we can't get *either* of these properties, then the `source_width` and `source_height` are set to zero.

        unless source? and not isNaN(source_width = Number(if source.naturalWidth? then source.naturalWidth else source.width)) then source_width = 0
        unless source? and not isNaN(source_height = Number(if source.naturalHeight? then source.naturalHeight else source.height)) then source_height = 0

We now have everything we need to define the properties.
Note that `width` and `height` are provided in sprite-units, not pixels.
If `sprite_width` or `sprite_height` are `0`, then the corresponding `width` and `height` are obviously `NaN`.

        @height = Math.floor source_height / sprite_height
        @source = source
        @sprite_height = sprite_height
        @sprite_width = sprite_width
        @width = Math.floor source_width / sprite_width

The `size` property is just `width` times `height`.

        @size = @width * @height

`ImageBitmap`s are optimized for drawing to the canvas.
If they are supported, we can pre-render the sprite-sheet and store this in the `image` property.

        if createImageBitmap? then (createImageBitmap source).then (image) => @image = image

Because `Sheet`s contain static images, it doesn't make sense for them to change after creation.
We freeze them:

        Object.freeze this

For convenience's sake, two static methods have been defined for `Sheet` to let you draw arbitrary sprites.
These are largely intended for use with callbacks.

The first is called `draw`, and takes five arguments:

- `context`: A `CanvasRenderingContext2D`
- `sprite`: A `Sprite`
- `x`: The x-coordinate at which to draw the sprite
- `y`: The y-coordinate at which to draw the sprite
- `frame`: The frame of the animation which to draw

It maps onto `sprite.draw`:

    Sheet.draw = (context, sprite, x, y, frame = 0) -> if sprite instanceof Sprite then sprite.draw context, x, y, frame

The second is called `drawSheetAtIndex`, and also takes five arguments:

- `context`: A `CanvasRenderingContext2D`
- `sheet`: A `Sheet`
- `index`: The index of the sprite
- `x`: The x-coordinate at which to draw the sprite
- `y`: The y-coordinate at which to draw the sprite

It maps onto `sheet.drawIndex`:

    Sheet.drawSheetAtIndex = (context, sheet, index, x, y) -> if sheet instanceof Sheet then sheet.drawIndex context, index, x, y

Finally, the `Sprite` constructor is added to `Sheet` for later access:

    Sheet.Sprite = Sprite

And now we can make `Sheet` available to the window:

    window.Sheet = Sheet

##  The prototype  ##

The `Sheet` prototype is fairly minimal, consisting of only two functions.

    Sheet.prototype = {

The first, `drawIndex`, draws the sprite located at the given `index`.
It is little more than a repackaging of `drawSprite`.

        drawIndex: (context, index, x, y) -> drawSprite this, index, context, x, y

The second, `getSprite`, creates a new `Sprite` pointing to the given `index`.
It is the most convenient way of creating `Sprite` objects.
It takes two arguments, the `index` of the sprite, and the `length` of the animation.

        getSprite: (index, length = 1) -> new Sprite this, index, length

We can now freeze the prototype:

    }

    Object.freeze Sheet.prototype

…And that's the end!

Jelli Game Engine

#  Sheet  #

`Sheet()` generates sprite-sheets and manages their rendering on a `CanvasRenderingContext2D`.
It is packaged with `Sprite()`, which describes a single sprite on the sheet.

##  General functions  ##

The function `drawSprite()` is called by `Sprite`s and `Sheet`s in order to draw their images.
It is not exposed to the window.

    drawSprite = (sheet, start_index, context, x, y, frame = 1) ->

…That's a lot of arguments. Let's go through them:

- `sheet` is the `Sheet` from which to draw the sprite
- `start_index` gives us the index of the sprite within the sheet
- `context` is the `CanvasRenderingContext2D` on which to draw the sprite
- `x` is the x-coordinate of the top-left corner of the sprite
- `y` is the y-coordinate of the top-left corner of the sprite
- `frame` is merely there as a convenience: It increments `start_index` by its value

The first thing we do is make sure everything is typed correctly.
The `sheet` and `context`, clearly, need to be of a certain type in order for this to work.
If any of the other provided arguments aren't numbers, however, we can go ahead and reset them to zero.

        unless sheet instanceof Sheet and start_index < sheet.size and context instanceof CanvasRenderingContext2D then return
        if isNaN(start_index = Number(start_index)) then start_index = 0
        if isNaN(x = Number(x)) then x = 0
        if isNaN(y = Number(y)) then y = 0
        if isNaN(frame = Number(frame)) then frame = 0

Now we can increment `start_index` by `frame`'s value:

        `start_index` += frame

Next, we need to find the horizontal (`i`) and vertical (`j`) position of the sprite on the sheet.
We can get this information from `start_index` with a little math:

        i = start_index % sheet.width
        j = Math.floor start_index / sheet.width

These two lines just make the image a little easier to access:

        source = sheet.source
        image = sheet.image

Now we have all we need to draw the sprite!
There is a HUGE `if`-statement that precedes the draw function, because we want to make sure that what we're drawing is actually there.
If it isn't, then obviously we can't draw anything.

        if (source instanceof HTMLImageElement and source.complete or source instanceof SVGImageElement or source instanceof HTMLCanvasElement or createImageBitmap? and (image instanceof ImageBitmap or source instanceof ImageBitmap)) and not isNaN(i) and not isNaN(j) and Number(width = sheet.sprite_width) and Number(height = sheet.sprite_height) then context.drawImage (if createImageBitmap? and image instanceof ImageBitmap then image else source), i * width, j * height, width, height, x, y, width, height

Let's go through what those did.
First, we make sure that the `Sheet` actually has an image associated with it:

-   `source instanceof HTMLImageElement and source.complete`—
    If the image source is an `<img>` element, then it needs to have finished loading.

-   `source instanceof SVGImageElement or source instanceof HTMLCanvasElement`—
    The source doesn't have to be an `<img>` element though! It can also be an `<svg>` or a `<canvas>`.

-   `createImageBitmap? and (image instanceof ImageBitmap or source instanceof ImageBitmap)`—
    Finally, the source can be an `ImageBitmap`.
    This isn't supported in all browsers, so we check to make sure `createImageBitmap` exists first.
    However, if `createImageBitmap` *is* supported, then `Sheet`s have a special property, `Sheet.image`, which might contain one, and this should be given preference.

We also need to make sure that the sprite exists on the sheet:

-   `not isNaN(i) and not isNaN(j)`—
    This makes sure that our indices are actually, y'know, numbers.

-   `Number(width = sheet.sprite_width) and Number(height = sheet.sprite_height)`—
    This makes sure that the `Sheet` has a non-zero width and height.
    It also sets the variables `width` and `height` to those values, for convenient access later.

Finally, we can draw the sprite.
Again, we preference `image` if it is defined.

##  Sprite  ##

The `Sprite` constructor creates a reference to a sprite on a sheet.
For efficiency's sake, it does *not* actually contain any of the image data associated with that sprite.
The constructor takes three arguments: `sheet`, which gives the sheet; `index`, which is the index of the sprite on the sheet; and `length`, which for animated sprites gives the length of the animation.

    Sprite = (sheet, index, length = 1) ->

If `index` or `length` aren't numbers, then we go ahead and set them to `0` and `1`, respectively.

        if isNaN(index = Number(index)) then index = 0
        if isNaN(length = Number(length)) then length = 0

Now we can set the properties.
Note that `draw` simply binds `drawSprite` to the given `Sheet` and `index`.

        @draw = drawSprite.bind(null, sheet, index)
        @height = if sheet instanceof Sheet then sheet.sprite_height else 0
        @index = index
        @frames = length
        @sheet = if sheet instanceof Sheet then sheet else null
        @width = if sheet instanceof Sheet then sheet.sprite_width else 0

Since `Sprite`s are just static references, they should be immutable:

        Object.freeze this

And we're done!

`Sprite`s are very simple, and because the `draw` function is bound above, they don't have a prototype.
For purposes of inheritance, however, I've thrown this minimal one together:

    Sprite.prototype = {draw: ->}
    Object.freeze Sprite.prototype

##  Sheet  ##

`Sheet`s associate images with data and methods to make them easily referencable as sprite-sheets.

###  The constructor  ###

The `Sheet` constructor only takes three arguments: `source`, which gives the source image for the sheet, `sprite_width`, which gives the width of the sprites, and `sprite_height`, which gives their height.
In doing so, it makes the assumption that sprites and sprite-sheets do not have any borders or padding.
(Because borders and padding result in larger download times for users, this restriction is considered acceptable, but it may be lifted at some time in the future.)

    Sheet = (source, sprite_width, sprite_height) ->

First, we need to handle the arguments.
If `source` isn't an image type that we recognize, we go ahead and set it to `null`.
And if the `sprite_width` or `sprite_height` aren't recognizable as numbers, we set them to 0.
(Note from the above that a `Sheet` with zero `sprite_width` or `sprite_height` cannot be drawn.)

        unless source instanceof HTMLImageElement or source instanceof SVGImageElement or source instanceof HTMLCanvasElement or createImageBitmap? and source instanceof ImageBitmap then source = null
        if isNaN(sprite_width = Number(sprite_width)) then sprite_width = 0
        if isNaN(sprite_height = Number(sprite_height)) then sprite_height = 0

Recall that we need to check for `createImageBitmap` before checking to see if the source is an `ImageBitmap`.

We can get the width and height of the image from one of two sources, depending on the source type.
All of the accepted types have `width` and `height` properties, which specify their dimensions.
However, `HTMLImageElement`s also have `naturalWidth` and `naturalHeight` properties, and these should be preferred for pixel-perfect rendering.

If for some reason we can't get *either* of these properties, then the `source_width` and `source_height` are set to zero.

        unless source? and not isNaN(source_width = Number(if source.naturalWidth? then source.naturalWidth else source.width)) then source_width = 0
        unless source? and not isNaN(source_height = Number(if source.naturalHeight? then source.naturalHeight else source.height)) then source_height = 0

We now have everything we need to define the properties.
Note that `width` and `height` are provided in sprite-units, not pixels.
If `sprite_width` or `sprite_height` are `0`, then the corresponding `width` and `height` are obviously `NaN`.

        @height = Math.floor source_height / sprite_height
        @source = source
        @sprite_height = sprite_height
        @sprite_width = sprite_width
        @width = Math.floor source_width / sprite_width

The `size` property is just `width` times `height`.

        @size = @width * @height

`ImageBitmap`s are optimized for drawing to the canvas.
If they are supported, we can pre-render the sprite-sheet and store this in the `image` property.

        if createImageBitmap? then (createImageBitmap source).then (image) => @image = image

Because `Sheet`s contain static images, it doesn't make sense for them to change after creation.
We freeze them:

        Object.freeze this

For convenience's sake, two static method has been defined for `Sheet` to let you draw arbitrary sprites.
These are largely intended for use with callbacks.

The first is called `draw`, and takes five arguments:

- `context`: A `CanvasRenderingContext2D`
- `sprite`: A `Sprite`
- `x`: The x-coordinate at which to draw the sprite
- `y`: The y-coordinate at which to draw the sprite
- `frame`: The frame of the animation which to draw

It maps onto `sprite.draw`:

    Sheet.draw = (context, sprite, x, y, frame = 0) -> if sprite instanceof Sprite then sprite.draw context, x, y, frame

The second is called `drawSheetAtIndex`, and also takes five arguments:

- `context`: A `CanvasRenderingContext2D`
- `sheet`: A `Sheet`
- `index`: The index of the sprite
- `x`: The x-coordinate at which to draw the sprite
- `y`: The y-coordinate at which to draw the sprite

It maps onto `sheet.drawIndex`:

    Sheet.drawSheetAtIndex = (context, sheet, index, x, y) -> if sheet instanceof Sheet then sheet.drawIndex context, index, x, y

Finally, the `Sprite` constructor is added to `Sheet` for later access:

    Sheet.Sprite = Sprite

And now we can make `Sheet` available to the window:

    window.Sheet = Sheet

##  The prototype  ##

The `Sheet` prototype is fairly minimal, consisting of only two functions.

    Sheet.prototype = {

The first, `drawIndex`, draws the sprite located at the given `index`.
It is little more than a repackaging of `drawSprite`.

        drawIndex: (context, index, x, y) -> drawSprite this, index, context, x, y

The second, `getSprite`, creates a new `Sprite` pointing to the given `index`.
It is the most convenient way of creating `Sprite` objects.
It takes two arguments, the `index` of the sprite, and the `length` of the animation.

        getSprite: (index, length = 1) -> new Sprite this, index, length

We can now freeze the prototype:

    }

    Object.freeze Sheet.prototype

…And that's the end!


switched to jade.renderFile

switched to jade.renderFile

# Builder

load modules

    {readFileSync, writeFileSync} = require 'fs'
    {renderFile} = require 'jade'
    {safeLoad} = require 'js-yaml'
    marked = require 'marked'

render html

    options = safeLoad readFileSync process.argv[3], 'utf8'
    options.markdown = marked
    html = renderFile process.argv[2], options

write the output

    if process.argv[4]?
        writeFileSync process.argv[4], html
    else
        console.log html

# Builder

load modules

    {readFileSync, writeFileSync} = require 'fs'
    {render} = require 'jade'
    {safeLoad} = require 'js-yaml'
    marked = require 'marked'

render html

    content = readFileSync process.argv[2], 'utf8'
    options = safeLoad readFileSync process.argv[3], 'utf8'
    options.filename = process.argv[3]
    options.markdown = marked
    html = render content, options

write the output

    if process.argv[4]?
        writeFileSync process.argv[4], html
    else
        console.log html


Moved camera logic into the tick event rather than the draw event to improve framerate stability.

# game

This module contains your game logic.  Its methods are called by the "index"
module to update the game state.

    gamepad = require "./input/gamepad.litcoffee"
    keyboard = require "./input/keyboard.litcoffee"

    context = require "./rendering/context.litcoffee"
    cloud = require "./rendering/cloud.litcoffee"
    matrix = require "./matrix.litcoffee"
    plane = require "./plane.litcoffee"
    misc = require "./misc.litcoffee"
    navmesh = require "./navmesh.litcoffee"
    vector = require "./vector.litcoffee"
    pose = require "./pose.litcoffee"
    ik = require "./ik.litcoffee"

    triangle = undefined

    character = testMap = testNavmesh = undefined
    characterData = require "./characters/test/cloud.coffee"

# load
Called before the first "tick"/"draw" to load any resources needed by the game.
Execute the argument when you have finished successfully.

    load = (callback) ->
        keyboard()
        context.load()
        cloud.load characterData, (character_) ->
            character = character_
            cloud.load (require "./tracks/test/geometry.msc"), (testMap_) ->
                testMap = testMap_
                navmesh.load (require "./tracks/test/navmesh.msn"), (testNavmesh_) ->
                    testNavmesh = testNavmesh_
                    triangle = testNavmesh[0]
                    callback()
                    return
                return
            return
        return

# tick
Called at 20Hz to update game state.  Guaranteed to be called once between
"load" and "draw".  May be called more or than once per call to "draw" or not at
all.

    firstTick = true
    firstDraw = true

    entityTransform = []
    matrix.identity entityTransform

    playerPoseOld = pose.create characterData
    playerPoseNew = pose.create characterData

    torsoTransform = []
    torsoTransformToDraw = []
    torsoTransformPreviousTick = []
    torsoTransformPreviousDraw = []

    surfaceCorrectedEntityTransform = []
    matrix.identity surfaceCorrectedEntityTransform

    cameraTransform = []
    cameraTransformToDraw = []
    cameraTransformPreviousDraw = []
    cameraTransformPreviousTick = []
    cameraLocation = []
    cameraLocationPreviousTick = []
    cameraTarget = []
    cameraTargetPreviousTick = []

    torsoAltitude = 0

    velocity = [0, 0, 0]
    xAxis = []
    yAxis = []
    zAxis = []
    torsoXAxis = []
    torsoZAxis = []
    translation = []
    targetForwardVelocity = []
    targetSidewardVelocity = []
    targetVelocity = []
    torsoTranslation = []

    start = []
    leftFoot = []
    rightFoot = []
    leftHand = []
    leftHandPreviousTick = []
    leftHandToDraw = []
    rightHand = []
    rightHandPreviousTick = []
    rightHandToDraw = []
    walked = 0
    shuffleTicks = 0
    foot = "left"
    ticksSinceLeft = 0
    ticksSinceRight = 0
    offset = []

    yaw = 0
    pitch = 0
    headYawPreviousTick = headYaw = 0

    stick = [0, 0, 0]
    stickAngle = 0

    edgeCallback = (edge) -> vector.flatten velocity, edge.plane.normal, velocity

    tick = ->
        if not firstTick
            matrix.copy cameraTransform, cameraTransformPreviousTick
            vector.copy cameraLocation, cameraLocationPreviousTick
            vector.copy cameraTarget, cameraTargetPreviousTick
            matrix.copy torsoTransform, torsoTransformPreviousTick
            vector.copy leftHand, leftHandPreviousTick
            vector.copy rightHand, rightHandPreviousTick

        matrix.translate velocity, entityTransform
        speed = vector.magnitude velocity
        walked += speed
        moving = speed > 2

        stick[0] = gamepad.right - gamepad.left
        stick[1] = gamepad.forward - gamepad.backward
        stickLength = vector.magnitude stick

        inDeadzone = stickLength < 0.1

        if inDeadzone
            stick[0] = stick[1] = 0
        else
            stickAngle = Math.atan2 -stick[0], stick[1]
            if stickLength > 1
                vector.divide.byScalar stick, stickLength, stick
                stickLength = 1

        # Left/right rotation.
        matrix.rotateY (stick[0] * -0.1), entityTransform, true

        # Apply navmesh triangle collision.
        matrix.getTranslation entityTransform, translation
        triangle = navmesh.constrain translation, triangle, edgeCallback

        # Gravity.
        velocity[1] -= 0.2

        # Forwards/backwards movement.
        matrix.getZ entityTransform, zAxis

        # Determine if we're underground.
        altitude = plane.distance triangle.plane, translation

        if altitude < 0
            velocity = velocity
            plane.project triangle.plane, translation, translation

            # A "bump" when you land.
            matrix.getY entityTransform, yAxis
            impact = Math.abs (vector.dot triangle.plane.normal, velocity) * (vector.dot triangle.plane.normal, yAxis)
            impact -= 1
            if impact < 0 then impact = 0
            impact *= 2
            torsoAltitude -= impact

            # Reflecting the velocity against the hit surface but then
            # flattening it has the effect that hitting a ramp bounces you up it
            # but you don't bounce when falling onto the floor.
            vector.reflect velocity, triangle.plane.normal, velocity
            vector.flatten velocity, triangle.plane.normal, velocity

            if not inDeadzone
                matrix.getX entityTransform, xAxis
                vector.multiply.byScalar zAxis, (stick[1] * 10), targetForwardVelocity
                vector.multiply.byScalar xAxis, (stick[0] * 10), targetSidewardVelocity
                vector.add.vector targetForwardVelocity, targetSidewardVelocity, targetVelocity
            else
                targetVelocity[0] = targetVelocity[1] = targetVelocity[2] = 0
            vector.interpolate velocity, targetVelocity, 0.05, velocity

        # Apply air resistance.
        vector.multiply.byScalar velocity, 0.98, velocity

        # This section attempts to align the entity with the triangle surface.

        # We take the triangle's normal as the Y/up axis.

        # First, flatten the Z/forward axis onto the surface.
        vector.flatten zAxis, triangle.plane.normal, zAxis
        vector.normalize zAxis, zAxis

        # Then, find the X/right axis which is perpendicular to the Z/forward
        # and Y/up axes.
        vector.cross triangle.plane.normal, zAxis, xAxis
        matrix.setX xAxis, surfaceCorrectedEntityTransform
        matrix.setY triangle.plane.normal, surfaceCorrectedEntityTransform
        matrix.setZ zAxis, surfaceCorrectedEntityTransform

        # Blend between our current transform and the aligned one.
        matrix.interpolate entityTransform, surfaceCorrectedEntityTransform, 0.1, entityTransform

        matrix.setTranslation translation, entityTransform

        matrix.copy entityTransform, torsoTransform

        torsoAltitude = misc.interpolate torsoAltitude, (12 - Math.min 2, (speed + if inDeadzone then 0 else 1.5)), 0.4

        matrix.getY entityTransform, yAxis
        vector.multiply.byScalar yAxis, torsoAltitude, torsoTranslation
        vector.add.vector torsoTranslation, translation, torsoTranslation

        yaw = misc.interpolateAngle yaw, stickAngle, 0.1, yaw
        matrix.rotateY yaw, torsoTransform, true

        # Calculating the head angle relative to the torso is complicated by the
        # stick angle being wrapped to 0...2PI, so we have to shift it out of
        # that range to clamp it.
        headYawPreviousTick = headYaw
        headYaw = Math.max Math.PI - 1, Math.min Math.PI + 1, misc.wrapAngle Math.PI + stickAngle - yaw
        headYaw -= Math.PI
        headYaw = misc.interpolateAngle headYawPreviousTick, headYaw, 0.4, headYaw

        matrix.getZ torsoTransform, torsoZAxis # TODO: If the entity transform is ever non-identity at startup we'll need to initialize torsoTransform for this to be right in the first ticks.
        matrix.getX torsoTransform, torsoXAxis # TODO: If the entity transform is ever non-identity at startup we'll need to initialize torsoTransform for this to be right in the first ticks.
        pitch = misc.interpolate pitch, (0.5 * stickLength - 0.1 * vector.dot torsoZAxis, velocity), 0.4
        matrix.rotateX pitch, torsoTransform, true
        matrix.rotateZ (0.1 * vector.dot torsoXAxis, velocity), torsoTransform, true

        matrix.setTranslation torsoTranslation, torsoTransform

        shuffleTicks--
        ticksSinceLeft++
        ticksSinceRight++
        while walked > 5 or shuffleTicks < 0
            shuffleTicks = 5
            walked -= 5
            if (not inDeadzone) or moving
                vector.normalize velocity, offset
                vector.multiply.byScalar offset, 5, offset
            else
                offset[0] = offset[1] = offset[2] = 0
            foot = switch foot
                when "left"
                    matrix.applyToVector playerPoseNew.torso, [-2, -10, 0], leftFoot
                    vector.add.vector offset, leftFoot, leftFoot
                    plane.project triangle.plane, leftFoot, leftFoot
                    ticksSinceLeft = 0
                    "right"
                when "right"
                    matrix.applyToVector playerPoseNew.torso, [2, -10, 0], rightFoot
                    vector.add.vector offset, rightFoot, rightFoot
                    plane.project triangle.plane, rightFoot, rightFoot
                    ticksSinceRight = 0
                    "left"

        if inDeadzone
            leftHand[0] = -6
            rightHand[0] = 6
            leftHand[1] = rightHand[1] = -4
            leftHand[2] = rightHand[2] = 0
        else
            yScale = 7 / (1 + speed)
            rightHand[0] = 2 + (Math.min 4, speed)
            leftHand[0] = -rightHand[0]

            leftHand[1] = rightHand[1] = 3
            motion = Math.pow (Math.cos ticksSinceLeft * 0.25) * 0.5 + 0.5, 4
            leftHand[1] += yScale * motion
            leftHand[2] = 1.5 + 6 * stickLength * motion
            motion = Math.pow (Math.cos ticksSinceRight * 0.25) * 0.5 + 0.5, 4
            rightHand[1] += yScale * motion
            rightHand[2] = 1.5 + 6 * stickLength * motion

        matrix.applyToVector torsoTransform, leftHand, leftHand
        matrix.applyToVector torsoTransform, rightHand, rightHand

        leftHand[1] -= 2
        rightHand[1] -= 2

        matrix.getX entityTransform, xAxis
        matrix.getY entityTransform, yAxis
        matrix.getZ entityTransform, zAxis
        matrix.getTranslation entityTransform, cameraTarget
        vector.multiply.byScalar yAxis, 18, offset
        vector.add.vector cameraTarget, offset, cameraTarget
        vector.multiply.byScalar zAxis, -20, offset
        vector.add.vector cameraTarget, offset, cameraLocation

        vector.interpolate cameraTargetPreviousTick, cameraTarget, 0.6, cameraTarget
        vector.interpolate cameraLocationPreviousTick, cameraLocation, 0.6, cameraLocation

        cameraTriangle = triangle
        cameraTriangle = navmesh.constrain cameraLocation, cameraTriangle
        cameraAltitude = (plane.distance cameraTriangle.plane, cameraLocation) - 4
        if cameraAltitude < 0
            vector.multiply.byScalar cameraTriangle.plane.normal, -cameraAltitude, offset
            vector.add.vector offset, cameraLocation, cameraLocation

        ik.lookAt cameraLocation, cameraTarget, xAxis, cameraTransform
        matrix.invert cameraTransform, cameraTransform

        if firstTick
            matrix.copy cameraTransform, cameraTransformPreviousTick
            vector.copy cameraLocation, cameraLocationPreviousTick
            vector.copy cameraTarget, cameraTargetPreviousTick
            matrix.copy torsoTransform, torsoTransformPreviousTick
            vector.copy leftHand, leftHandPreviousTick
            vector.copy rightHand, rightHandPreviousTick
            firstTick = false

        lag = 0.15 + 0.4 / (1 + speed / 3)
        if inDeadzone then lag = 0.2
        vector.interpolate leftHandPreviousTick, leftHand, lag, leftHand
        vector.interpolate rightHandPreviousTick, rightHand, lag, rightHand

        return

# draw
Called with the progress through the current frame (a number between 0 and 1) to
redraw the scene.

    draw = (progress) ->

        if not firstDraw
            matrix.copy cameraTransformToDraw, cameraTransformPreviousDraw
            matrix.copy torsoTransformToDraw, torsoTransformPreviousDraw
            pose.copy playerPoseNew, playerPoseOld

        matrix.interpolate cameraTransformPreviousTick, cameraTransform, progress, cameraTransformToDraw
        matrix.interpolate torsoTransformPreviousTick, torsoTransform, progress, playerPoseNew.torso

        matrix.applyToVector playerPoseNew.torso, [-1.5, -2.5, 0], start
        matrix.getX playerPoseNew.torso, xAxis
        ik.computeLimb start, leftFoot, 10, xAxis, playerPoseNew.legLeftUpper, playerPoseNew.legLeftLower

        matrix.applyToVector playerPoseNew.torso, [1.5, -2.5, 0], start
        ik.computeLimb start, rightFoot, 10, xAxis, playerPoseNew.legRightUpper, playerPoseNew.legRightLower

        matrix.getY playerPoseNew.torso, yAxis
        vector.negate xAxis, xAxis
        vector.interpolate xAxis, yAxis, 0.05, offset

        matrix.applyToVector playerPoseNew.torso, [-1.5, 4, 0], start
        vector.interpolate leftHandPreviousTick, leftHand, progress, leftHandToDraw
        ik.computeLimb start, leftHandToDraw, 10, offset, playerPoseNew.armLeftUpper, playerPoseNew.armLeftLower

        vector.negate yAxis, yAxis
        vector.interpolate xAxis, yAxis, 0.05, offset

        matrix.applyToVector playerPoseNew.torso, [1.5, 4, 0], start
        vector.interpolate rightHandPreviousTick, rightHand, progress, rightHandToDraw
        ik.computeLimb start, rightHandToDraw, 10, offset, playerPoseNew.armRightUpper, playerPoseNew.armRightLower

        matrix.copy playerPoseNew.torso, playerPoseNew.head
        matrix.translate [0, 6, 0], playerPoseNew.head, true
        matrix.rotateY (misc.interpolate headYawPreviousTick, headYaw, progress), playerPoseNew.head, true

        if firstDraw
            matrix.copy cameraTransformToDraw, cameraTransformPreviousDraw
            pose.copy playerPoseNew, playerPoseOld
            firstDraw = false

        context.begin 0, 0, context.width, context.height, 1, cameraTransformPreviousDraw, cameraTransformToDraw, 0.1, 0.5, 0.9
        cloud.draw testMap
        cloud.draw character, playerPoseOld, playerPoseNew

        return

    module.exports = { load, tick, draw }

# game

This module contains your game logic.  Its methods are called by the "index"
module to update the game state.

    gamepad = require "./input/gamepad.litcoffee"
    keyboard = require "./input/keyboard.litcoffee"

    context = require "./rendering/context.litcoffee"
    cloud = require "./rendering/cloud.litcoffee"
    matrix = require "./matrix.litcoffee"
    plane = require "./plane.litcoffee"
    misc = require "./misc.litcoffee"
    navmesh = require "./navmesh.litcoffee"
    vector = require "./vector.litcoffee"
    pose = require "./pose.litcoffee"
    ik = require "./ik.litcoffee"

    triangle = undefined

    character = testMap = testNavmesh = undefined
    characterData = require "./characters/test/cloud.coffee"

# load
Called before the first "tick"/"draw" to load any resources needed by the game.
Execute the argument when you have finished successfully.

    load = (callback) ->
        keyboard()
        context.load()
        cloud.load characterData, (character_) ->
            character = character_
            cloud.load (require "./tracks/test/geometry.msc"), (testMap_) ->
                testMap = testMap_
                navmesh.load (require "./tracks/test/navmesh.msn"), (testNavmesh_) ->
                    testNavmesh = testNavmesh_
                    triangle = testNavmesh[0]
                    callback()
                    return
                return
            return
        return

# tick
Called at 20Hz to update game state.  Guaranteed to be called once between
"load" and "draw".  May be called more or than once per call to "draw" or not at
all.

    firstTick = true
    firstDraw = true

    entityTransform = []
    entityTransformToDraw = []
    entityTransformPreviousTick = []
    entityTransformPreviousDraw = []
    matrix.identity entityTransform

    playerPoseOld = pose.create characterData
    playerPoseNew = pose.create characterData

    torsoTransform = []
    torsoTransformToDraw = []
    torsoTransformPreviousTick = []
    torsoTransformPreviousDraw = []

    surfaceCorrectedEntityTransform = []
    matrix.identity surfaceCorrectedEntityTransform

    cameraTransform = []
    cameraTransformPreviousDraw = []
    cameraLocation = []
    cameraLocationPreviousDraw = []
    cameraTarget = []
    cameraTargetPreviousDraw = []
    cameraSide = []
    cameraSidePreviousDraw = [0, 0, 1]
    matrix.identity cameraTransform

    torsoAltitude = 0

    velocity = [0, 0, 0]
    xAxis = []
    yAxis = []
    zAxis = []
    torsoXAxis = []
    torsoZAxis = []
    translation = []
    targetForwardVelocity = []
    targetSidewardVelocity = []
    targetVelocity = []
    torsoTranslation = []

    start = []
    leftFoot = []
    rightFoot = []
    leftHand = []
    leftHandPreviousTick = []
    leftHandToDraw = []
    rightHand = []
    rightHandPreviousTick = []
    rightHandToDraw = []
    walked = 0
    shuffleTicks = 0
    foot = "left"
    ticksSinceLeft = 0
    ticksSinceRight = 0
    offset = []

    yaw = 0
    pitch = 0
    headYawPreviousTick = headYaw = 0

    stick = [0, 0, 0]
    stickAngle = 0

    edgeCallback = (edge) -> vector.flatten velocity, edge.plane.normal, velocity

    tick = ->
        if not firstTick
            matrix.copy entityTransform, entityTransformPreviousTick
            matrix.copy torsoTransform, torsoTransformPreviousTick
            vector.copy leftHand, leftHandPreviousTick
            vector.copy rightHand, rightHandPreviousTick

        matrix.translate velocity, entityTransform
        speed = vector.magnitude velocity
        walked += speed
        moving = speed > 2

        stick[0] = gamepad.right - gamepad.left
        stick[1] = gamepad.forward - gamepad.backward
        stickLength = vector.magnitude stick

        inDeadzone = stickLength < 0.1

        if inDeadzone
            stick[0] = stick[1] = 0
        else
            stickAngle = Math.atan2 -stick[0], stick[1]
            if stickLength > 1
                vector.divide.byScalar stick, stickLength, stick
                stickLength = 1

        # Left/right rotation.
        matrix.rotateY (stick[0] * -0.1), entityTransform, true

        # Apply navmesh triangle collision.
        matrix.getTranslation entityTransform, translation
        triangle = navmesh.constrain translation, triangle, edgeCallback

        # Gravity.
        velocity[1] -= 0.2

        # Forwards/backwards movement.
        matrix.getZ entityTransform, zAxis

        # Determine if we're underground.
        altitude = plane.distance triangle.plane, translation

        if altitude < 0
            velocity = velocity
            plane.project triangle.plane, translation, translation

            # A "bump" when you land.
            matrix.getY entityTransform, yAxis
            impact = Math.abs (vector.dot triangle.plane.normal, velocity) * (vector.dot triangle.plane.normal, yAxis)
            impact -= 1
            if impact < 0 then impact = 0
            impact *= 2
            torsoAltitude -= impact

            # Reflecting the velocity against the hit surface but then
            # flattening it has the effect that hitting a ramp bounces you up it
            # but you don't bounce when falling onto the floor.
            vector.reflect velocity, triangle.plane.normal, velocity
            vector.flatten velocity, triangle.plane.normal, velocity

            if not inDeadzone
                matrix.getX entityTransform, xAxis
                vector.multiply.byScalar zAxis, (stick[1] * 10), targetForwardVelocity
                vector.multiply.byScalar xAxis, (stick[0] * 10), targetSidewardVelocity
                vector.add.vector targetForwardVelocity, targetSidewardVelocity, targetVelocity
            else
                targetVelocity[0] = targetVelocity[1] = targetVelocity[2] = 0
            vector.interpolate velocity, targetVelocity, 0.05, velocity

        # Apply air resistance.
        vector.multiply.byScalar velocity, 0.98, velocity

        # This section attempts to align the entity with the triangle surface.

        # We take the triangle's normal as the Y/up axis.

        # First, flatten the Z/forward axis onto the surface.
        vector.flatten zAxis, triangle.plane.normal, zAxis
        vector.normalize zAxis, zAxis

        # Then, find the X/right axis which is perpendicular to the Z/forward
        # and Y/up axes.
        vector.cross triangle.plane.normal, zAxis, xAxis
        matrix.setX xAxis, surfaceCorrectedEntityTransform
        matrix.setY triangle.plane.normal, surfaceCorrectedEntityTransform
        matrix.setZ zAxis, surfaceCorrectedEntityTransform

        # Blend between our current transform and the aligned one.
        matrix.interpolate entityTransform, surfaceCorrectedEntityTransform, 0.1, entityTransform

        matrix.setTranslation translation, entityTransform

        matrix.copy entityTransform, torsoTransform

        torsoAltitude = misc.interpolate torsoAltitude, (12 - Math.min 2, (speed + if inDeadzone then 0 else 1.5)), 0.4

        matrix.getY entityTransform, yAxis
        vector.multiply.byScalar yAxis, torsoAltitude, torsoTranslation
        vector.add.vector torsoTranslation, translation, torsoTranslation

        yaw = misc.interpolateAngle yaw, stickAngle, 0.1, yaw
        matrix.rotateY yaw, torsoTransform, true

        # Calculating the head angle relative to the torso is complicated by the
        # stick angle being wrapped to 0...2PI, so we have to shift it out of
        # that range to clamp it.
        headYawPreviousTick = headYaw
        headYaw = Math.max Math.PI - 1, Math.min Math.PI + 1, misc.wrapAngle Math.PI + stickAngle - yaw
        headYaw -= Math.PI
        headYaw = misc.interpolateAngle headYawPreviousTick, headYaw, 0.4, headYaw

        matrix.getZ torsoTransform, torsoZAxis # TODO: If the entity transform is ever non-identity at startup we'll need to initialize torsoTransform for this to be right in the first ticks.
        matrix.getX torsoTransform, torsoXAxis # TODO: If the entity transform is ever non-identity at startup we'll need to initialize torsoTransform for this to be right in the first ticks.
        pitch = misc.interpolate pitch, (0.5 * stickLength - 0.1 * vector.dot torsoZAxis, velocity), 0.4
        matrix.rotateX pitch, torsoTransform, true
        matrix.rotateZ (0.1 * vector.dot torsoXAxis, velocity), torsoTransform, true

        matrix.setTranslation torsoTranslation, torsoTransform

        shuffleTicks--
        ticksSinceLeft++
        ticksSinceRight++
        while walked > 5 or shuffleTicks < 0
            shuffleTicks = 5
            walked -= 5
            if (not inDeadzone) or moving
                vector.normalize velocity, offset
                vector.multiply.byScalar offset, 5, offset
            else
                offset[0] = offset[1] = offset[2] = 0
            foot = switch foot
                when "left"
                    matrix.applyToVector playerPoseNew.torso, [-2, -10, 0], leftFoot
                    vector.add.vector offset, leftFoot, leftFoot
                    plane.project triangle.plane, leftFoot, leftFoot
                    ticksSinceLeft = 0
                    "right"
                when "right"
                    matrix.applyToVector playerPoseNew.torso, [2, -10, 0], rightFoot
                    vector.add.vector offset, rightFoot, rightFoot
                    plane.project triangle.plane, rightFoot, rightFoot
                    ticksSinceRight = 0
                    "left"

        if inDeadzone
            leftHand[0] = -6
            rightHand[0] = 6
            leftHand[1] = rightHand[1] = -4
            leftHand[2] = rightHand[2] = 0
        else
            yScale = 7 / (1 + speed)
            rightHand[0] = 2 + (Math.min 4, speed)
            leftHand[0] = -rightHand[0]

            leftHand[1] = rightHand[1] = 3
            motion = Math.pow (Math.cos ticksSinceLeft * 0.25) * 0.5 + 0.5, 4
            leftHand[1] += yScale * motion
            leftHand[2] = 1.5 + 6 * stickLength * motion
            motion = Math.pow (Math.cos ticksSinceRight * 0.25) * 0.5 + 0.5, 4
            rightHand[1] += yScale * motion
            rightHand[2] = 1.5 + 6 * stickLength * motion

        matrix.applyToVector torsoTransform, leftHand, leftHand
        matrix.applyToVector torsoTransform, rightHand, rightHand

        leftHand[1] -= 2
        rightHand[1] -= 2

        if firstTick
            matrix.copy entityTransform, entityTransformPreviousTick
            matrix.copy torsoTransform, torsoTransformPreviousTick
            vector.copy leftHand, leftHandPreviousTick
            vector.copy rightHand, rightHandPreviousTick
            firstTick = false

        lag = 0.15 + 0.4 / (1 + speed / 3)
        if inDeadzone then lag = 0.2
        vector.interpolate leftHandPreviousTick, leftHand, lag, leftHand
        vector.interpolate rightHandPreviousTick, rightHand, lag, rightHand

        return

# draw
Called with the progress through the current frame (a number between 0 and 1) to
redraw the scene.

    draw = (progress) ->

        if not firstDraw
            matrix.copy entityTransformToDraw, entityTransformPreviousDraw
            matrix.copy cameraTransform, cameraTransformPreviousDraw
            matrix.copy torsoTransformToDraw, torsoTransformPreviousDraw
            pose.copy playerPoseNew, playerPoseOld
            vector.copy cameraTarget, cameraTargetPreviousDraw
            vector.copy cameraLocation, cameraLocationPreviousDraw

        matrix.interpolate entityTransformPreviousTick, entityTransform, progress, entityTransformToDraw
        matrix.interpolate torsoTransformPreviousTick, torsoTransform, progress, playerPoseNew.torso

        matrix.getY entityTransformToDraw, yAxis
        matrix.getZ entityTransformToDraw, zAxis
        matrix.getTranslation entityTransformToDraw, cameraTarget
        vector.multiply.byScalar yAxis, 18, offset
        vector.add.vector cameraTarget, offset, cameraTarget
        vector.multiply.byScalar zAxis, -20, offset
        vector.add.vector cameraTarget, offset, cameraLocation

        vector.interpolate cameraTargetPreviousDraw, cameraTarget, 0.1, cameraTarget
        vector.interpolate cameraLocationPreviousDraw, cameraLocation, 0.1, cameraLocation

        matrix.getX entityTransformToDraw, cameraSide
        vector.interpolate cameraSidePreviousDraw, cameraSide, 0.1, cameraSide
        vector.copy cameraSide, cameraSidePreviousDraw

        cameraTriangle = triangle
        cameraTriangle = navmesh.constrain cameraLocation, cameraTriangle
        cameraAltitude = (plane.distance cameraTriangle.plane, cameraLocation) - 4
        if cameraAltitude < 0
            vector.multiply.byScalar cameraTriangle.plane.normal, -cameraAltitude, offset
            vector.add.vector offset, cameraLocation, cameraLocation

        ik.lookAt cameraLocation, cameraTarget, cameraSide, cameraTransform
        matrix.invert cameraTransform, cameraTransform

        matrix.applyToVector playerPoseNew.torso, [-1.5, -2.5, 0], start
        matrix.getX playerPoseNew.torso, xAxis
        ik.computeLimb start, leftFoot, 10, xAxis, playerPoseNew.legLeftUpper, playerPoseNew.legLeftLower

        matrix.applyToVector playerPoseNew.torso, [1.5, -2.5, 0], start
        ik.computeLimb start, rightFoot, 10, xAxis, playerPoseNew.legRightUpper, playerPoseNew.legRightLower

        matrix.getY playerPoseNew.torso, yAxis
        vector.negate xAxis, xAxis
        vector.interpolate xAxis, yAxis, 0.05, offset

        matrix.applyToVector playerPoseNew.torso, [-1.5, 4, 0], start
        vector.interpolate leftHandPreviousTick, leftHand, progress, leftHandToDraw
        ik.computeLimb start, leftHandToDraw, 10, offset, playerPoseNew.armLeftUpper, playerPoseNew.armLeftLower

        vector.negate yAxis, yAxis
        vector.interpolate xAxis, yAxis, 0.05, offset

        matrix.applyToVector playerPoseNew.torso, [1.5, 4, 0], start
        vector.interpolate rightHandPreviousTick, rightHand, progress, rightHandToDraw
        ik.computeLimb start, rightHandToDraw, 10, offset, playerPoseNew.armRightUpper, playerPoseNew.armRightLower

        matrix.copy playerPoseNew.torso, playerPoseNew.head
        matrix.translate [0, 6, 0], playerPoseNew.head, true
        matrix.rotateY (misc.interpolate headYawPreviousTick, headYaw, progress), playerPoseNew.head, true

        if firstDraw
            matrix.copy entityTransformToDraw, entityTransformPreviousDraw
            matrix.copy cameraTransform, cameraTransformPreviousDraw
            pose.copy playerPoseNew, playerPoseOld
            vector.copy cameraTarget, cameraTargetPreviousDraw
            vector.copy cameraLocation, cameraLocationPreviousDraw
            firstDraw = false

        context.begin 0, 0, context.width, context.height, 1, cameraTransformPreviousDraw, cameraTransform, 0.1, 0.5, 0.9
        cloud.draw testMap
        cloud.draw character, playerPoseOld, playerPoseNew

        return

    module.exports = { load, tick, draw }


Removed convertToHTML middleware

Removed convertToHTML middleware

#Includes

	{EventEmitter} = require 'events'
	async = require 'async'
	util = require 'util'
	_ = require 'lodash'

	ElementFactory = require './element-factory'
	Phrase = require './phrase'
	InputOption = require './input-option'

#Lacona

	class Parser extends EventEmitter
		constructor: (@options) ->
			@phrases = []

			@middleware = []

			@understand require('./plugins/literal')
			@understand require('./plugins/freetext')
			@understand require('./plugins/integer')
			@understand require('./plugins/date')
			@understand require('./plugins/validator')
			@understand require('./plugins/suggester')
			@understand require('./plugins/list')

		_phraseAccessor: (name) =>
			_.filter @phrases, (phrase) ->
				phrase.name is name or name in phrase.extends

###`understand`

`understand` takes a schema and scope, and defines a set of words for Lacona to understand

		understand: (options) ->
			scope = options.scope
			schema = options.schema ? options
			if not util.isArray(schema)
				schema = [schema]
			for phrase in schema
				elementFactory = new ElementFactory(scope, @)
				@phrases.push new Phrase(phrase, scope, elementFactory)
			return @

###`use`

`use` defines middleware. It must be passed a function that accepts 2 arguments, an inputOption,
and a callback that should be passed an error (or null) and a modulated inputOption. This will be passed
to the `data` event (or the next middleware) rather than the inputOption itself.

		use: (next) ->
			@middleware.push next
			return @

		parse: (inputText, lang) ->
			lang = lang ? window?.navigator?.language?.replace?('-', '_') ? process?.env?.LANG?.split?('.')?[0] ? 'default' #ALL THE QUESTION MARKS

			async.each _.filter(@phrases, (item) -> item.run?), (phrase, done) =>
				input = new InputOption(phrase, inputText)
				phrase.parse input, lang, null, (option) =>
					if option.text is ''
						async.eachSeries @middleware, (call, done) =>
							call option, done
						, (err) =>
							return done(err) if err?
							@emit 'data', option
				, done

			, (err) =>
				if err?
					@emit 'error', err
				else
					@emit 'end'
			return @

		run: (inputOption, done) ->
			inputOption.sentence.scope[inputOption.sentence.run](inputOption.result, done)

	module.exports =
		Parser: Parser

#Includes

	{EventEmitter} = require 'events'
	async = require 'async'
	util = require 'util'
	_ = require 'lodash'

	ElementFactory = require './element-factory'
	Phrase = require './phrase'
	InputOption = require './input-option'

#Lacona

	class Parser extends EventEmitter
		constructor: (@options) ->
			@phrases = []

			@middleware = []

			@understand require('./plugins/literal')
			@understand require('./plugins/freetext')
			@understand require('./plugins/integer')
			@understand require('./plugins/date')
			@understand require('./plugins/validator')
			@understand require('./plugins/suggester')
			@understand require('./plugins/list')

		_phraseAccessor: (name) =>
			_.filter @phrases, (phrase) ->
				phrase.name is name or name in phrase.extends

###`understand`

`understand` takes a schema and scope, and defines a set of words for Lacona to understand

		understand: (options) ->
			scope = options.scope
			schema = options.schema ? options
			if not util.isArray(schema)
				schema = [schema]
			for phrase in schema
				elementFactory = new ElementFactory(scope, @)
				@phrases.push new Phrase(phrase, scope, elementFactory)
			return @

###`use`

`use` defines middleware. It must be passed a function that accepts 2 arguments, an inputOption,
and a callback that should be passed an error (or null) and a modulated inputOption. This will be passed
to the `data` event (or the next middleware) rather than the inputOption itself.

		use: (next) ->
			@middleware.push next
			return @

		parse: (inputText, lang) ->
			lang = lang ? window?.navigator?.language?.replace?('-', '_') ? process?.env?.LANG?.split?('.')?[0] ? 'default' #ALL THE QUESTION MARKS

			async.each _.filter(@phrases, (item) -> item.run?), (phrase, done) =>
				input = new InputOption(phrase, inputText)
				phrase.parse input, lang, null, (option) =>
					if option.text is ''
						async.eachSeries @middleware, (call, done) =>
							call option, done
						, (err) =>
							return done(err) if err?
							@emit 'data', option
				, done

			, (err) =>
				if err?
					@emit 'error', err
				else
					@emit 'end'
			return @

		run: (inputOption, done) ->
			inputOption.sentence.scope[inputOption.sentence.run](inputOption.result, done)

	convertToHTML = (inputOption, done) ->
		html = '
'
		html += ''
		for match in inputOption.match
			html += "#{match.string}"
		html += ''
		for suggestion in inputOption.suggestion.words
			html += "#{suggestion.string}"
		html += ''
		for completion in inputOption.completion
			html += "#{completion.string}"
		html += '
'

		inputOption.html = html
		done()

	module.exports =
		Parser: Parser
		convertToHTML: convertToHTML


little tweaking

little tweaking

# Literate Coffee Content Handler for Punch

## What is Literate Programming?

> "Write what disturbs you, what you fear, what you have not been willing to speak about. Be willing to be split open." - **Natalie Goldberg**

Literate Programming is a way to construct your programs similar to the way you write any other prose, following your train of thoughts. Instead of jumping directly to the mechanical process of coding, you structure your program as a human readable document. The implementations of the ideas are done alongside the description.

Concept of Literate programming was first introduced by Donald Knuth in 1970s as an alternative to structured programming. Recently, this technique was resurfaced with the introduction of "Literate CoffeeScript" mode introduced in CoffeeScript 1.5.

## How I do Literate Programming?

As you could see this program is done using the Literate Programming. Here's how my flow looked like.

* Start with a blank canvas.
* [Distraction-free mode in Vim](http://www.laktek.com/2012/09/05/distraction-free-writing-with-vim/) can be helpful.
* Type whatever comes to your mind, be it prose or code.
* Use markdown formatting to structure the document. Code blocks needs to indent with 4-spaces.
* Write as you would explain it to a friend sitting next to you (imaginery pair-programming)
* CoffeeScript's syntax compliments to this type of programming. No commas, no brackets, short functions, variable scoping.

## What's this project?

		LitCoffeeHandler = module.exports = {}

This is a custom content handler for Punch, to handle Literate CoffeeScript. It will produce human readable HTML pages from the markdown and machine executable JS from the coffeeScript code blocks.

This could be useful for:
* Generating documentation for your library
* To write code tutorials (automatically provide the source)

This works on top of Punch's default content handler. The content requests, that cannot be handled by this will be delegated to default content handler.

		DefaultContentHandler = require('punch').ContentHandler

## Setup

By convention, we expect the source files (`litcoffee` files) of a project to be found in the `src` path.

		LitCoffeeHandler.srcPath = 'src'

Punch calls the `setup` function of each configured plugin at the start, along with [project's configuration](https://github.com/laktek/punch/wiki/Configuration-Options). We can allow users to override the default path by providing a custom path in project's config.

		moduleUtils = require('punch').Utils.Module

		LitCoffeeHandler.setup = (config) ->
			if user_defined_path = config.litcoffee?.path
				LitCoffeeHandler.srcPath = user_defined_path

We need to delegate certain functions to `DefaultContentHandler`, so let's setup it as well.

			DefaultContentHandler.setup config

Let's setup the markdown parser, based on what has been configured.

			LitCoffeeHandler.markdownParser = moduleUtils.requireAndSetup config.plugins.parsers['.markdown'], config

## Negotiating Content

Punch's page renderer will call `negotiateContent` function when user requests content. We shall check if we can serve the content.

		fs = require 'fs'
		path = require 'path'

		LitCoffeeHandler.negotiateContent = (request_path, file_extension, options, callback) ->
			file_path = path.join(LitCoffeeHandler.srcPath, "#{request_path}.litcoffee")
			fs.stat file_path, (err, stats) ->

If no file found, we'll delegate the handling to the `DefaultContentHandler`.

				if err
					return DefaultContentHandler.negotiateContent(request_path, file_extension, options, callback)

Get the file's modified date from the stats.

				modified_date = stats.mtime

If there's a matching `litcoffee` file available in path, then we have to decide what to do with it based on user's request.
* If the user requests for a HTML page, we'll parse the markdown.
* If she requests for JS, we'll compile it using CoffeeScript compiler.
* If the requested type is not something we can handle, again we'll delegate it to `DefaultContentHandler`.

				if file_extension == '.html'
					parseMarkdown file_path, modified_date, callback
				else if file_extension == '.js'
					compileToJs file_path, modified_date, callback
				else
					DefaultContentHandler.negotiateContent(request_path, file_extension, options, callback)

## Parse Markdown

To parse the markdown file, we should use the configured markdown parser. Result should be presented as a JSON object. The parsed content will be assigned to a key named `content`. This is what should be used in the templates to render the parsed content.

		LitCoffeeHandler.markdownParser = null

		parseMarkdown = (file_path, modified_date, callback) ->
			fs.readFile file_path, (err, litcoffee) ->
				if err
					return callback(err)

				LitCoffeeHandler.markdownParser.parse litcoffee.toString(), (err, parsed_output) ->
					if err
						return callback err, {}, {}, modified_date

					callback null, { 'content': parsed_output }, {}, modified_date

## Compile to JS

To compile LiterateCoffee files, we should get the configured CoffeeScript compiler. Similar to parsed markdown content, this will also be presented in a JSON object (with output assigned to a key named `content`). To serve this as a JS file, user should create a mustache template with the tag `{{{content}}}` (named `_layout.js.mustache`).

		CoffeeScript = require('coffee-script')

		compileToJs = (file_path, modified_date, callback) ->
			fs.readFile file_path, (err, litcoffee) ->
				if err
					return callback(err)

				try
					parsed_output = CoffeeScript.compile litcoffee.toString(), { filename: file_path, literate: true }, (err, parsed_output) ->
					callback null, { 'content': parsed_output }, {}, modified_date
				catch err
					return callback err, {}, {}, modified_date

## Get Content Paths

Punch uses `getContentPaths` functions to identify all available pages for it to generate. We traverse the source directory and create an array containing the paths of the `litcoffee` files. We ignore any hidden files or directories.

		_ = require('underscore')

		LitCoffeeHandler.getContentPaths = (basepath, callback) ->
			collected_paths = []

			fs.readdir path.join(process.cwd(), LitCoffeeHandler.srcPath), (err, files) ->
				_.each files, (file) ->
					if file.indexOf '.litcoffee' > 0
						basename = file.split('.').shift()
						collected_paths.push "#{basename}.html"
						collected_paths.push "#{basename}.js"

				callback null, collected_paths

## Is Section?

Punch calls `isSection` to check if there's an implicit index page to be rendered for the given path. We're leaving the section handling to the default content handler.

		LitCoffeeHandler.isSection = (basepath) ->
			DefaultContentHandler.isSection(basepath)

## Get Sections

Punch calls `getSections` to get all available sections under content. Since we don't handle sections let's delegate that also to default content handler.

		LitCoffeeHandler.getSections = (callback) ->
			DefaultContentHandler.getSections(callback)

## Inspiration

* [Journo & Literate CoffeeScript](http://ashkenas.com/literate-coffeescript/)
* [Codd - building immutable SQL queries from relational primitives](https://gist.github.com/grncdr/5039898)
* [TOML parser for JavaScript](https://github.com/JonAbrams/tomljs/blob/master/toml.litcoffee)

## Further Reading

* [Literate Programming on Wikipedia](http://en.wikipedia.org/wiki/Literate_programming)

# Literate Coffee Content Handler for Punch

## What is Literate Programming?

> "Write what disturbs you, what you fear, what you have not been willing to speak about. Be willing to be split open." - **Natalie Goldberg**

Literate Programming is a way to construct your programs similar to the way you write any other prose, following your train of thoughts. Instead of jumping directly to the mechanical process of coding, you structure your program as a human readable document. The implementations of the ideas are done alongside the description.

Concept of Literate programming was first introduced by Donald Knuth in 1970s as an alternative to structured programming. Recently, this technique was resurfaced with the introduction of "Literate CoffeeScript" mode introduced in CoffeeScript 1.5.

## How I do Literate Programming?

As you could see this program is done using the Literate Programming. Here's how my flow looked like.

* Start with a blank paper.
* Use [Distraction-free mode in Vim](http://www.laktek.com/2012/09/05/distraction-free-writing-with-vim/).
* Type whatever comes to your mind, be it prose or code.
* Use markdown formatting to structure the document. Code blocks needs to indent with 4-spaces.
* Write as you would explain it to a friend sitting next to you (imaginery pair-programming)
* CoffeeScript's syntax compliments to this type of programming. No commas, no brackets, short functions, variable scoping.

## What's this project?

		LitCoffeeHandler = module.exports = {}

This is a custom content handler for Punch, to handle Literate CoffeeScript. It will produce human readable HTML pages from the markdown and machine executable JS from the coffeeScript code blocks.

This could be useful for:
* Generating documentation for your library
* To write code tutorials (automatically provide the source)

This works on top of Punch's default content handler. The content requests, that cannot be handled by this will be delegated to default content handler.

		DefaultContentHandler = require('punch').ContentHandler

## Setup

By convention, we expect the source files (`litcoffee` files) of a project to be found in the `src` path.

		LitCoffeeHandler.srcPath = 'src'

Punch calls the `setup` function of each configured plugin at the start, along with [project's configuration](https://github.com/laktek/punch/wiki/Configuration-Options). We can allow users to override the default path by providing a custom path in project's config.

		moduleUtils = require('punch').Utils.Module

		LitCoffeeHandler.setup = (config) ->
			if user_defined_path = config.litcoffee?.path
				LitCoffeeHandler.srcPath = user_defined_path

We need to delegate certain functions to `DefaultContentHandler`, so let's setup it as well.

			DefaultContentHandler.setup config

Let's setup the markdown parser, based on what has been configured.

			LitCoffeeHandler.markdownParser = moduleUtils.requireAndSetup config.plugins.parsers['.markdown'], config

## Negotiating Content

Punch's page renderer will call `negotiateContent` function when user requests content. We shall check if we can serve the content.

		fs = require 'fs'
		path = require 'path'

		LitCoffeeHandler.negotiateContent = (request_path, file_extension, options, callback) ->
			file_path = path.join(LitCoffeeHandler.srcPath, "#{request_path}.litcoffee")
			fs.stat file_path, (err, stats) ->

If no file found, we'll delegate the handling to the `DefaultContentHandler`.

				if err
					return DefaultContentHandler.negotiateContent(request_path, file_extension, options, callback)

Get the file's modified date from the stats.

				modified_date = stats.mtime

If there's a matching `litcoffee` file available in path, then we have to decide what to do with it based on user's request.
* If the user requests for a HTML page, we'll parse the markdown.
* If she requests for JS, we'll compile it using CoffeeScript compiler.
* If the requested type is not something we can handle, again we'll delegate it to `DefaultContentHandler`.

				if file_extension == '.html'
					parseMarkdown file_path, modified_date, callback
				else if file_extension == '.js'
					compileToJs file_path, modified_date, callback
				else
					DefaultContentHandler.negotiateContent(request_path, file_extension, options, callback)

## Parse Markdown

To parse the markdown file, we should use the configured markdown parser. Result should be presented as a JSON object. The parsed content will be assigned to a key named `content`. This is what should be used in the templates to render the parsed content.

		LitCoffeeHandler.markdownParser = null

		parseMarkdown = (file_path, modified_date, callback) ->
			fs.readFile file_path, (err, litcoffee) ->
				if err
					return callback(err)

				LitCoffeeHandler.markdownParser.parse litcoffee.toString(), (err, parsed_output) ->
					if err
						return callback err, {}, {}, modified_date

					callback null, { 'content': parsed_output }, {}, modified_date

## Compile to JS

To compile LiterateCoffee files, we should get the configured CoffeeScript compiler. Similar to parsed markdown content, this will also be presented in a JSON object (with output assigned to a key named `content`). To serve this as a JS file, user should create a mustache template with the tag `{{{content}}}` (named `_layout.js.mustache`).

		CoffeeScript = require('coffee-script')

		compileToJs = (file_path, modified_date, callback) ->
			fs.readFile file_path, (err, litcoffee) ->
				if err
					return callback(err)

				try
					parsed_output = CoffeeScript.compile litcoffee.toString(), { filename: file_path, literate: true }, (err, parsed_output) ->
					callback null, { 'content': parsed_output }, {}, modified_date
				catch err
					return callback err, {}, {}, modified_date

## Get Content Paths

Punch uses `getContentPaths` functions to identify all available pages for it to generate. We traverse the source directory and create an array containing the paths of the `litcoffee` files. We ignore any hidden files or directories.

		_ = require('underscore')

		LitCoffeeHandler.getContentPaths = (basepath, callback) ->
			collected_paths = []

			fs.readdir path.join(process.cwd(), LitCoffeeHandler.srcPath), (err, files) ->
				_.each files, (file) ->
					if file.indexOf '.litcoffee' > 0
						basename = file.split('.').shift()
						collected_paths.push "#{basename}.html"
						collected_paths.push "#{basename}.js"

				callback null, collected_paths

## Is Section?

Punch calls `isSection` to check if there's an implicit index page to be rendered for the given path. We're leaving the section handling to the default content handler.

		LitCoffeeHandler.isSection = (basepath) ->
			DefaultContentHandler.isSection(basepath)

## Get Sections

Punch calls `getSections` to get all available sections under content. Since we don't handle sections let's delegate that also to default content handler.

		LitCoffeeHandler.getSections = (callback) ->
			DefaultContentHandler.getSections(callback)

## Inspiration

* [Journo & Literate CoffeeScript](http://ashkenas.com/literate-coffeescript/)
* [Codd - building immutable SQL queries from relational primitives](https://gist.github.com/grncdr/5039898)
* [TOML parser for JavaScript](https://github.com/JonAbrams/tomljs/blob/master/toml.litcoffee)

## Further Reading

* [Literate Programming on Wikipedia](http://en.wikipedia.org/wiki/Literate_programming)


fix set observer typo

fix set observer typo

# /api/Data Structures/Batman.Set/Batman.SetObserver

`Batman.SetObserver` is a utility for observing `Batman.Set`s and their contents (especially if their contents are `Batman.Object`s). It extends `Batman.Object`. In the wild, `Batman.SetProxy` uses a `Batman.SetObserver` to track its base set and `Batman.SetSort` uses item tracking to maintain its order.

A few other points about `Batman.SetObserver`:

- It fires `itemsWereAdded` and `itemsWereRemoved` when its base `Batman.Set` fires those events.
- When items are added and removed to the base Set, they're automatically observed with `startObservingItems`/`stopObservingItems` -- you don't have to set that up yourself.
- Override `observedItemKeys` and `observerForItemAndKey` to track properties of `Batman.Object` members of the set.

## ::constructor(base : Set) : SetObserver

Returns a new `Batman.SetObserver` tracking `base`.

## ::.base : Set

The set being tracked by the observer.

## ::.observedItemKeys[=[]]: Array

If you set `observedItemKeys` to an array of strings, those keys will be observed on the members of `base`. When those keys change, the provided observer (see `observerForItemAndKey`) will be called.

## ::observerForItemAndKey(item : Batman.Object, key : String) : Function

When you instantiate a `SetObserver`, you should override this function. When the observer starts observing an item, this function will be called for each `key` in `observedItemKeys`. It should return an observer function for `key`. The observer function will be passed `newValue, oldValue`.

## ::startObserving()

Starts observing the `base` and all its members.

## ::stopObserving()

Stops observing the `base` and all its members.

## ::startObservingItems(items : Array)

Adds observers for `observedItemKeys` on each item in `items`, calling `observerForItemAndKey` for each key in `observedItemKeys`

## ::stopObservingItems(items : Array)

Forgets observers on `items`.

# /api/Data Structures/Batman.Set/Batman.SetObserver

`Batman.SetObserver` is a utility for observing `Batman.Set`s and their contents (especially if their contents are `Batman.Object`s). It extends `Batman.Object`. In the wild, `Batman.SetProxy` uses a `Batman.SetObserver` to track its base set and `Batman.SetSort` uses item tracking to maintain its order.

A few other points about `Batman.SetObserver`:

- It fires `itemsWereAdded` and `itemsWereRemoved` when its base `Batman.Set` fires those events.
- When items are added and removed to the base Set, they're automatically observed with `startObservingItems`/`stopObservingItems` -- you don't have to set that up yourself.
- Override `observedItemKeys` and `observerForItemAndKey` to track properties of `Batman.Object` members of the set.

## ::constructor(base : Set) : SetObserver

Returns a new `Batman.SetObserver` tracking `base`.

## ::.base : Set

The set being tracked by the observer.

## ::.observedItemKeys[=[]]: Array

If you set `observedItemKeys` to an array of strings, those keys will be observed on the members of `base`. When those keys change, the provided observer (see `observerForItemAndKey`) will be called.

## ::.observerForItemAndKey(item : Batman.Object, key : String) : Function

When you instantiate a `SetObserver`, you should override this function. When the observer starts observing an item, this function will be called for each `key` in `observedItemKeys`. It should return an observer function for `key`. The observer function will be passed `newValue, oldValue`.

## ::startObserving()

Starts observing the `base` and all its members.

## ::stopObserving()

Stops observing the `base` and all its members.

## ::startObservingItems(items : Array)

Adds observers for `observedItemKeys` on each item in `items`, calling `observerForItemAndKey` for each key in `observedItemKeys`

## ::stopObservingItems(items : Array)

Forgets observers on `items`.


Initial commit:100:

Initial commit:100:

Our thoughts inspired - by Albert Einstein.

gQL®: An efficient Genome Query Language.
-----------------------------------------
[![Apache License](https://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/BioQL/BioQL/blob/master/LICENSE)

Great spirits have always encountered violent opposition from mediocre minds - Albert Einstein.


signal.setImmediate() added

signal.setImmediate() added

# Signal

Signal is a function with listeners which can be emitted.

Access it with:
```javascript
const { signal } = Neft;
```

    'use strict'

    utils = require 'src/utils'
    assert = require 'src/assert'

    pendingSignals = 0

## *Integer* signal.STOP_PROPAGATION

Special constant used to stop calling further listeners.

Must be returned by the listener function.

```javascript
var obj = {};
signal.create(obj, 'onPress');

obj.onPress(function(){
  console.log('listener 1');
  return signal.STOP_PROPAGATION;
});

// this listener won't be called, because first listener will capture this signal
obj.onPress(function(){
  console.log('listener 2');
});

obj.onPress.emit();
// listener 1
```

    STOP_PROPAGATION = exports.STOP_PROPAGATION = 1 << 30

## *Signal* signal.create([*NotPrimitive* object, *String* name])

Creates a new signal in the given object under the given name property.

Returns created signal.

```javascript
var obj = {};

signal.create(obj, 'onRename');

obj.onRename.connect(function(){
  console.log(arguments);
});

obj.onRename.emit('Max', 'George');
// {0: "Max", 1: "George"}
```

    exports.create = (obj, name) ->
        signal = createSignalFunction obj
        if name is undefined
            return signal

        assert.isNotPrimitive obj, 'signal object cannot be primitive'
        assert.isString name, 'signal name must be a string'
        assert.notLengthOf name, 0, 'signal name cannot be an empty string'

        assert not obj.hasOwnProperty(name)
        , "signal object has already defined the '#{name}' property"

        obj[name] = signal

## *Boolean* signal.isEmpty(*Signal* signal)

Returns `true` if the given signal has no listeners.

    exports.isEmpty = (signal) ->
        for func in signal.listeners by 2
            if func isnt null
                return false
        return true

## signal.setImmediate(*Function* callback)

Register a function which will be called when all pending signal emits will be finished.

If there is no pending emits, the given function is calling immediately.

    immediate = []
    exports.setImmediate = (callback) ->
        assert.isFunction callback
        if pendingSignals is 0
            callback()
        else
            immediate.push callback

    callSignal = (obj, listeners, arg1, arg2) ->
        pendingSignals += 1

        i = 0
        n = listeners.length
        result = 0
        containsGaps = false
        while i < n
            func = listeners[i]
            if func is null
                containsGaps = true
            else
                ctx = listeners[i + 1]
                if result <= 0 and func.call(ctx or obj, arg1, arg2) is STOP_PROPAGATION
                    result = STOP_PROPAGATION
                    if containsGaps
                        break
            i += 2

        if containsGaps
            shift = 0
            while i < n
                func = listeners[i]
                if func is null
                    shift -= 2
                else if shift > 0
                    assert.isNotDefined listeners[i + shift]
                    assert.isNotDefined listeners[i + shift + 1]
                    listeners[i + shift] = func
                    listeners[i + shift + 1] = listeners[i + 1]
                    listeners[i] = null
                    listeners[i + 1] = null
                i += 2

        pendingSignals -= 1

        if pendingSignals is 0
            while callback = immediate.shift()
                callback()

        result

    createSignalFunction = (obj) ->
        handler = (listener, ctx) ->
            handler.connect listener, ctx

        handler.obj = obj
        handler.listeners = []
        utils.setPrototypeOf handler, SignalPrototype

        handler

    SignalPrototype =

## Signal::emit([*Any* argument1, *Any* argument2])

Call all of the signal listeners with the given arguments (2 maximally).

        emit: (arg1, arg2) ->
            assert.isFunction @, 'emit must be called on a signal function'
            assert.isArray @listeners, 'emit must be called on a signal function'
            assert.operator arguments.length, '<', 3, 'signal accepts maximally two parameters; use object instead'

            callSignal @obj, @listeners, arg1, arg2

## Signal::connect(*Function* listener, [*Any* context])

Adds the given listener function into the signal listeners.

By default, the signal function works like this method.

```javascript
var obj = {};
signal.create(obj, 'onPress');

obj.onPress(function(){
  console.log('listener 1');
});

obj.onPress.connect(function(){
  console.log('listener 2');
});

obj.onPress.emit()
// listener 1
// listener 2
```

The given context will be used as a context in listener calling.
By default, the listener is called with the object on which the signal is created.

```javascript
var obj = {standard: true};
signal.create(obj, 'onPress');

var fakeContext = {fake: true};
obj.onPress(function(){
  console.log(this);
}, fakeContext);

obj.onPress(function(){
  console.log(this);
});

obj.onPress.emit();
// {fake: true}
// {standard: true}
```

        connect: (listener, ctx = null) ->
            assert.isFunction @, 'connect must be called on a signal function'
            assert.isFunction listener, 'listener is not a function'

            {listeners} = @

            i = n = listeners.length
            while (i -= 2) >= 0
                if listeners[i] isnt null
                    break

            if i + 2 is n
                listeners.push listener, ctx
            else
                assert.isNotDefined listeners[i + 2]
                assert.isNotDefined listeners[i + 3]
                listeners[i + 2] = listener
                listeners[i + 3] = ctx

            return

## Signal::disconnect(*Function* listener, [*Any* context])

Returns the given listener function from the signal listeners.

```javascript
var obj = {};

signal.create(obj, 'onPress');

var listener = function(){
  console.log('listener called!');
};

obj.onPress.connect(listener);
obj.onPress.disconnect(listener);

obj.onPress.emit()
// no loggs...
```

        disconnect: (listener, ctx = null) ->
            assert.isFunction @, 'disconnect must be called on a signal function'
            assert.isFunction listener, 'listener is not a function'

            {listeners} = @
            index = 0

            loop
                index = listeners.indexOf listener, index
                if index is -1 or listeners[index + 1] is ctx
                    break
                index += 2
            assert.isNot index, -1, "listener doesn't exist in this signal"
            assert.is listeners[index], listener
            assert.is listeners[index + 1], ctx

            listeners[index] = null
            listeners[index + 1] = null

            return

## Signal::disconnectAll()

Removes all the signal listeners.

        disconnectAll: ->
            assert.isFunction @, 'disconnectAll must be called on a signal function'

            {listeners} = @
            for _, i in listeners
                listeners[i] = null

            return

    exports.Emitter = require('./emitter')
        create: exports.create
        createSignalFunction: createSignalFunction
        callSignal: callSignal

# Signal

Signal is a function with listeners which can be emitted.

Access it with:
```javascript
const { signal } = Neft;
```

    'use strict'

    utils = require 'src/utils'
    assert = require 'src/assert'

## *Integer* signal.STOP_PROPAGATION

Special constant used to stop calling further listeners.

Must be returned by the listener function.

```javascript
var obj = {};
signal.create(obj, 'onPress');

obj.onPress(function(){
  console.log('listener 1');
  return signal.STOP_PROPAGATION;
});

// this listener won't be called, because first listener will capture this signal
obj.onPress(function(){
  console.log('listener 2');
});

obj.onPress.emit();
// listener 1
```

    STOP_PROPAGATION = exports.STOP_PROPAGATION = 1 << 30

## *Signal* signal.create([*NotPrimitive* object, *String* name])

Creates a new signal in the given object under the given name property.

Returns created signal.

```javascript
var obj = {};

signal.create(obj, 'onRename');

obj.onRename.connect(function(){
  console.log(arguments);
});

obj.onRename.emit('Max', 'George');
// {0: "Max", 1: "George"}
```

    exports.create = (obj, name) ->
        signal = createSignalFunction obj
        if name is undefined
            return signal

        assert.isNotPrimitive obj, 'signal object cannot be primitive'
        assert.isString name, 'signal name must be a string'
        assert.notLengthOf name, 0, 'signal name cannot be an empty string'

        assert not obj.hasOwnProperty(name)
        , "signal object has already defined the '#{name}' property"

        obj[name] = signal

## *Boolean* signal.isEmpty(*Signal* signal)

Returns `true` if the given signal has no listeners.

    exports.isEmpty = (signal) ->
        for func in signal.listeners by 2
            if func isnt null
                return false
        return true

    callSignal = (obj, listeners, arg1, arg2) ->
        i = 0
        n = listeners.length
        result = 0
        containsGaps = false
        while i < n
            func = listeners[i]
            if func is null
                containsGaps = true
            else
                ctx = listeners[i + 1]
                if result <= 0 and func.call(ctx or obj, arg1, arg2) is STOP_PROPAGATION
                    result = STOP_PROPAGATION
                    if containsGaps
                        break
            i += 2

        if containsGaps
            shift = 0
            while i < n
                func = listeners[i]
                if func is null
                    shift -= 2
                else if shift > 0
                    assert.isNotDefined listeners[i + shift]
                    assert.isNotDefined listeners[i + shift + 1]
                    listeners[i + shift] = func
                    listeners[i + shift + 1] = listeners[i + 1]
                    listeners[i] = null
                    listeners[i + 1] = null
                i += 2

        return result

    createSignalFunction = (obj) ->
        handler = (listener, ctx) ->
            handler.connect listener, ctx

        handler.obj = obj
        handler.listeners = []
        utils.setPrototypeOf handler, SignalPrototype

        handler

    SignalPrototype =

## Signal::emit([*Any* argument1, *Any* argument2])

Call all of the signal listeners with the given arguments (2 maximally).

        emit: (arg1, arg2) ->
            assert.isFunction @, 'emit must be called on a signal function'
            assert.isArray @listeners, 'emit must be called on a signal function'
            assert.operator arguments.length, '<', 3, 'signal accepts maximally two parameters; use object instead'

            callSignal @obj, @listeners, arg1, arg2

## Signal::connect(*Function* listener, [*Any* context])

Adds the given listener function into the signal listeners.

By default, the signal function works like this method.

```javascript
var obj = {};
signal.create(obj, 'onPress');

obj.onPress(function(){
  console.log('listener 1');
});

obj.onPress.connect(function(){
  console.log('listener 2');
});

obj.onPress.emit()
// listener 1
// listener 2
```

The given context will be used as a context in listener calling.
By default, the listener is called with the object on which the signal is created.

```javascript
var obj = {standard: true};
signal.create(obj, 'onPress');

var fakeContext = {fake: true};
obj.onPress(function(){
  console.log(this);
}, fakeContext);

obj.onPress(function(){
  console.log(this);
});

obj.onPress.emit();
// {fake: true}
// {standard: true}
```

        connect: (listener, ctx = null) ->
            assert.isFunction @, 'connect must be called on a signal function'
            assert.isFunction listener, 'listener is not a function'

            {listeners} = @

            i = n = listeners.length
            while (i -= 2) >= 0
                if listeners[i] isnt null
                    break

            if i + 2 is n
                listeners.push listener, ctx
            else
                assert.isNotDefined listeners[i + 2]
                assert.isNotDefined listeners[i + 3]
                listeners[i + 2] = listener
                listeners[i + 3] = ctx

            return

## Signal::disconnect(*Function* listener, [*Any* context])

Returns the given listener function from the signal listeners.

```javascript
var obj = {};

signal.create(obj, 'onPress');

var listener = function(){
  console.log('listener called!');
};

obj.onPress.connect(listener);
obj.onPress.disconnect(listener);

obj.onPress.emit()
// no loggs...
```

        disconnect: (listener, ctx = null) ->
            assert.isFunction @, 'disconnect must be called on a signal function'
            assert.isFunction listener, 'listener is not a function'

            {listeners} = @
            index = 0

            loop
                index = listeners.indexOf listener, index
                if index is -1 or listeners[index + 1] is ctx
                    break
                index += 2
            assert.isNot index, -1, "listener doesn't exist in this signal"
            assert.is listeners[index], listener
            assert.is listeners[index + 1], ctx

            listeners[index] = null
            listeners[index + 1] = null

            return

## Signal::disconnectAll()

Removes all the signal listeners.

        disconnectAll: ->
            assert.isFunction @, 'disconnectAll must be called on a signal function'

            {listeners} = @
            for _, i in listeners
                listeners[i] = null

            return

    exports.Emitter = require('./emitter')
        create: exports.create
        createSignalFunction: createSignalFunction
        callSignal: callSignal


example change

example change

Create a sample div

    class Student
     constructor: (name, age) ->
      @name = name
      @age = age

     template: ->
      @div "#name.col-md-6", ->
       @span "Name"
       @span @$.name
      @div "#age.col-md-6", style: {background: "red"}, ->
       @span "Age"
       @span "#{@$.age}"
       @input "#ageInput", type: "text", null

     render: ->
      console.log Weya.markup context: @, @template
      Weya elem: document.body, context: @, @template

    student = new Student "Varuna", 26
    student.render()

Create a sample div

    class Student
     constructor: (name, age) ->
      @name = name
      @age = age

     template: ->
      @div "#name.col-md-6", ->
       @span "Name"
       @span @$.name
      @div "#age.col-md-6", ->
       @span "Age"
       @span "#{@$.age}"
       @input "#ageInput", type: "text", null

     render: ->
      console.log Weya.markup context: @, @template
      Weya elem: document.body, context: @, @template

    student = new Student "Varuna", 26
    student.render()