<commit_before>'use strict';

var INDICES        = 'indices';

var BUFFER_DATA = 'BUFFER_DATA';
var UNIFORM_INPUT = 'UNIFORM_INPUT';
var MATERIAL_INPUT = 'MATERIAL_INPUT';
var GL_SPEC = 'GL_SPEC';
var WITH = 'WITH';

var GL_UNIFORMS = 'GL_UNIFORMS';
var GL_BUFFER_DATA = 'GL_BUFFER_DATA';
var GL_SET_GEOMETRY = 'GL_SET_GEOMETRY';

var FRAME_END = 'FRAME_END';

var Texture = require('./Texture');
var Program = require('./Program');
var Buffer = require('./Buffer');

var checkerBoard = require('./Checkerboard');
var BufferRegistry = require('./BufferRegistry');

var uniformNames = ['perspective', 'transform', 'opacity', 'origin', 'size', 'baseColor'];
var resolutionName = ['resolution'];
var uniformValues = [];
var resolutionValues = [];

var inputIdx = { baseColor: 0, normal: 1, metalness: 2, glossiness: 3 };
var inputNames = ['baseColor', 'normal', 'metalness', 'glossiness'];
var inputValues = [[.5, .5, .5], [0,0,0], .2, .8];
var identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];

/**
 * WebGLRenderer is a private class that reads commands from a Mesh
 * and converts them into webGL api calls.
 *
 * @class WebGLRenderer
 * @constructor
 *
 * @param {DOMElement} canvas The dom element that GL will paint itself onto.
 *
 */

function WebGLRenderer(container) {
    this.container = container;
    this.canvas = document.createElement('canvas');

    if (this.container.target === document.body) {
        window.addEventListener('resize', this.updateSize.bind(this));
    }

    this.container.target.appendChild(this.canvas);
    this.canvas.className = 'famous-webgl GL';

    var context = this.canvas.getContext('webgl') || this.canvas.getContext('experimental-webgl');
    var containerSize = this.container._getSize();

    var gl = this.gl = context;

    gl.polygonOffset(0.1, 0.1);
    gl.enable(gl.POLYGON_OFFSET_FILL);
    gl.enable(gl.DEPTH_TEST);
    gl.disable(gl.BLEND);
    gl.depthFunc(gl.LEQUAL);

    this.meshRegistry = {};
    this.textureRegistry = {};
    this.texCache = {};
    this.bufferRegistry = new BufferRegistry(gl);
    this.program = new Program(gl);

    this.state = {
        boundArrayBuffer: null,
        boundElementBuffer: null,
        lastDrawn: null
    };

    this.cachedSize = [];
    this.updateSize(containerSize[0], containerSize[1], containerSize[2], this.container);

    this.projectionTransform = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
}

/**
 * Draws a mesh onto the screen
 *
 * @method render
 *
 * @param {Context} object with local transform data and mesh
 *
 * @chainable
 */

WebGLRenderer.prototype.receive = function receive(path, commands) {
    var mesh = this.meshRegistry[path];

    if (!mesh) {
        mesh = this.meshRegistry[path] = {
            uniforms: {
                opacity: 1,
                transform: identity,
                size: [0, 0, 0],
                origin: [0, 0, 0],
                baseColor: [.5, .5, .5]
            },
            buffers: {},
            geometry: null,
            drawType: null
        };
    }
    var bufferName;
    var bufferValue;
    var bufferSpacing;
    var uniformName;
    var uniformValue;
    var geometryId;

    while (commands.length) {
        var command = commands.shift();

        switch (command) {
            case 'MATERIAL_INPUT':
                var name = commands.shift();
                var mat = commands.shift();
                mesh.uniforms.baseColor[0] = - mat._id;
                this.program.registerMaterial(name, mat);
                this.updateSize();
                break;
            case GL_SET_GEOMETRY:

                mesh.geometry = commands.shift();
                mesh.drawType = commands.shift();
                mesh.dynamic = commands.shift();
                break;

            case GL_UNIFORMS:

                uniformName = commands.shift();
                uniformValue = commands.shift();

                mesh.uniforms[uniformName] = uniformValue;
                break;

            case GL_BUFFER_DATA:

                geometryId = commands.shift();
                bufferName = commands.shift();
                bufferValue = commands.shift();
                bufferSpacing = commands.shift();

                this.bufferRegistry.allocate(geometryId, bufferName, bufferValue, bufferSpacing, mesh.dynamic);
                break;

            case WITH: commands.unshift(command); return;
        }
    }
};

WebGLRenderer.prototype.draw = function draw() {
    var mesh;
    var buffers;
    var size;

    for (var key in this.meshRegistry) {
        mesh = this.meshRegistry[key];
        buffers = this.bufferRegistry.registry[mesh.geometry];

        if (!buffers) return;

        uniformValues[0] = this.projectionTransform;
        uniformValues[1] = mesh.uniforms.transform;
        uniformValues[2] = mesh.uniforms.opacity;
        uniformValues[3] = mesh.uniforms.origin;
        uniformValues[4] = mesh.uniforms.size;
        uniformValues[5] = mesh.uniforms.baseColor;

        this.program.setUniforms(uniformNames, uniformValues);

        this.drawBuffers(buffers, mesh.drawType, mesh.geometry);
    }
};

/**
 * Loads the buffers and issues the draw command for a geometry
 *
 * @method drawBuffers
 *
 * @param {Object} Map of vertex buffers keyed by attribute identifier
 * @param {Number} Enumerator defining what primitive to draw
 *
 */

WebGLRenderer.prototype.drawBuffers = function drawBuffers(vertexBuffers, mode, id) {
    var gl = this.gl;
    var length = 0;
    var attribute;
    var location;
    var spacing;
    var offset;
    var buffer;
    var j;

    for (var i = 0; i < vertexBuffers.keys.length; i++) {
        attribute = vertexBuffers.keys[i];

        // Do not set vertexAttribPointer if index buffer.

        if (attribute === INDICES) {
            j = i; continue;
        }

        // Retreive the attribute location and make sure it is enabled.

        location = this.program.attributeLocations[attribute];

        if (location === -1) continue;
        if (location === undefined) {
            location = gl.getAttribLocation(this.program.program, attribute);
            this.program.attributeLocations[attribute] = location;
            if (location !== -1) gl.enableVertexAttribArray(location);
        }

        // Retreive buffer information used to set attribute pointer.

        buffer = vertexBuffers.values[i];
        spacing = vertexBuffers.spacing[i];
        offset = vertexBuffers.offset[i];
        length = vertexBuffers.length[i];

        // Skip bindBuffer if buffer is currently bound.

        if (this.state.boundArrayBuffer !== buffer) {
            gl.bindBuffer(buffer.target, buffer.buffer);
            this.state.boundArrayBuffer = buffer;
        }

        if (this.state.lastDrawn !== id) {
            gl.vertexAttribPointer(location, spacing, gl.FLOAT, gl.FALSE, 0, 4 * offset);
        }
    }

    if (length) {

        // If index buffer, use drawElements.

        if (j !== undefined) {
            buffer = vertexBuffers.values[j];
            offset = vertexBuffers.offset[j];
            spacing = vertexBuffers.spacing[j];
            length = vertexBuffers.length[j];

            // Skip bindBuffer if buffer is currently bound.

            if (this.state.boundElementBuffer !== buffer) {
                gl.bindBuffer(buffer.target, buffer.buffer);
                this.state.boundElementBuffer = buffer;
            }

            gl.drawElements(mode, length, gl.UNSIGNED_SHORT, 2 * offset);
        }
        else {
            gl.drawArrays(mode, 0, length);
        }
    }

    this.state.lastDrawn = id;
};

/**
 * Loads the image data into the material
 *
 * @method registerMaterial
 *
 * @param {Material} the object that contains the image data
 *
 */

WebGLRenderer.prototype.registerMaterial = function registerMaterial(material) {
    var image = material.options.image;
    var tex;

    if (image) {
        tex = this.texCache[image];
        if (!tex) {
            tex = new Texture(this.gl);
            tex.setImage(checkerBoard);
            this.texCache[image] = tex;
            loadImage(image, function (img) {
                tex.bind();
                tex.setImage(img);
            });
        }

        this.textureRegistry[material.entity] = tex;
    }
};

/**
 * Allocates an array buffer where vertex data is sent to via compile.
 *
 * @method renderOffscreen
 *
 * @param {Function} The render function to be called after setup and before cleanup
 * @param {spec} The object containing mesh data
 * @param {context} The object containing global render information
 * @param {Texture} The location where the render data is stored
 *
 */

function renderOffscreen(callback, spec, context, texture) {
    var gl = this.gl;
    var v = context._size;

    var framebuffer  = this.framebuffer ? this.framebuffer : this.framebuffer = gl.createFramebuffer();
    var renderbuffer = this.renderbuffer ? this.renderbuffer : this.renderbuffer = gl.createRenderbuffer();

    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);

    if (v[0] != renderbuffer.width || v[1] != renderbuffer.height) {
        renderbuffer.width = v[0];
        renderbuffer.height = v[1];
        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, v[0], v[1]);
    }

    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture.id, 0);
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);

    if (this.debug) checkFrameBufferStatus(gl);

    callback.call(this, spec);

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
};

/**
 * Uploads an image if it is a string
 *
 * @method loadImage
 *
 * @param {Object, String} image object or string url
 * @param {Function} proc that gets called when the image is loaded
 *
 */
function loadImage (img, callback) {
    var obj = (typeof img === 'string' ? new Image() : img) || {};
    obj.crossOrigin = 'anonymous';
    if (! obj.src) obj.src = img;
    if (! obj.complete) obj.onload = function () { callback(obj); };
    else callback(obj);

    return obj;
}

/**
 * Diagonose the failed intialization of an FBO
 *
 * @method checkFrameBufferStatus
 *
 * @param {Object} the glContext that owns this FBO
 *
 */
function checkFrameBufferStatus(gl) {
    var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);

    switch (status) {
        case gl.FRAMEBUFFER_COMPLETE:
            break;
        case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            throw("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); break;
        case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
            throw("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); break;
        case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
            throw("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); break;
        case gl.FRAMEBUFFER_UNSUPPORTED:
            throw("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED"); break;
        default:
            throw("Incomplete framebuffer: " + status);
    }
};

/**
 * Updates the width and height of parent canvas, sets the viewport size on
 * the WebGL context and updates the resolution uniform for the shader program.
 * If no size is passed in this function will update using the cached size.
 *
 * @method updateSize
 *
 * @param {Number} width Updated width of the drawing context.
 * @param {Number} height Updated height of the drawing context.
 * @param {Number} depth Updated depth of the drawing context.
 *
 */
WebGLRenderer.prototype.updateSize = function updateSize() {
    var newSize = this.container._getSize();

    var width = newSize[0];
    var height = newSize[1];
    var depth = 0;

    if (width != null) {
        this.cachedSize[0] = width;
        this.cachedSize[1] = height;
        this.cachedSize[2] = width;
    }

    this.canvas.width  = width;
    this.canvas.height = height;

    this.gl.viewport(0, 0, this.cachedSize[0], this.cachedSize[1]);

    resolutionValues[0] = this.cachedSize;
    this.program.setUniforms(resolutionName, resolutionValues);
};

module.exports = WebGLRenderer;
<commit_msg>Fix: Corrected interface expectations of container and perfed updateSize<commit_after>'use strict';

var INDICES        = 'indices';

var BUFFER_DATA = 'BUFFER_DATA';
var UNIFORM_INPUT = 'UNIFORM_INPUT';
var MATERIAL_INPUT = 'MATERIAL_INPUT';
var GL_SPEC = 'GL_SPEC';
var WITH = 'WITH';

var GL_UNIFORMS = 'GL_UNIFORMS';
var GL_BUFFER_DATA = 'GL_BUFFER_DATA';
var GL_SET_GEOMETRY = 'GL_SET_GEOMETRY';

var FRAME_END = 'FRAME_END';

var Texture = require('./Texture');
var Program = require('./Program');
var Buffer = require('./Buffer');

var checkerBoard = require('./Checkerboard');
var BufferRegistry = require('./BufferRegistry');

var uniformNames = ['perspective', 'transform', 'opacity', 'origin', 'size', 'baseColor'];
var resolutionName = ['resolution'];
var uniformValues = [];
var resolutionValues = [];

var inputIdx = { baseColor: 0, normal: 1, metalness: 2, glossiness: 3 };
var inputNames = ['baseColor', 'normal', 'metalness', 'glossiness'];
var inputValues = [[.5, .5, .5], [0,0,0], .2, .8];
var identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];

/**
 * WebGLRenderer is a private class that reads commands from a Mesh
 * and converts them into webGL api calls.
 *
 * @class WebGLRenderer
 * @constructor
 *
 * @param {DOMElement} canvas The dom element that GL will paint itself onto.
 *
 */

function WebGLRenderer(container) {
    this.container = container;
    this.canvas = document.createElement('canvas');

    if (this.container.getTarget() === document.body) {
        window.addEventListener('resize', this.updateSize.bind(this));
    }

    this.container.getTarget().appendChild(this.canvas);
    this.canvas.className = 'famous-webgl GL';

    var context = this.canvas.getContext('webgl') || this.canvas.getContext('experimental-webgl');
    var containerSize = this.container._getSize();

    var gl = this.gl = context;

    gl.polygonOffset(0.1, 0.1);
    gl.enable(gl.POLYGON_OFFSET_FILL);
    gl.enable(gl.DEPTH_TEST);
    gl.disable(gl.BLEND);
    gl.depthFunc(gl.LEQUAL);

    this.meshRegistry = {};
    this.textureRegistry = {};
    this.texCache = {};
    this.bufferRegistry = new BufferRegistry(gl);
    this.program = new Program(gl);

    this.state = {
        boundArrayBuffer: null,
        boundElementBuffer: null,
        lastDrawn: null
    };

    this.cachedSize = [];
    this.updateSize(containerSize[0], containerSize[1], containerSize[2], this.container);

    this.projectionTransform = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
}

/**
 * Draws a mesh onto the screen
 *
 * @method render
 *
 * @param {Context} object with local transform data and mesh
 *
 * @chainable
 */

WebGLRenderer.prototype.receive = function receive(path, commands) {
    var mesh = this.meshRegistry[path];

    if (!mesh) {
        mesh = this.meshRegistry[path] = {
            uniforms: {
                opacity: 1,
                transform: identity,
                size: [0, 0, 0],
                origin: [0, 0, 0],
                baseColor: [.5, .5, .5]
            },
            buffers: {},
            geometry: null,
            drawType: null
        };
    }
    var bufferName;
    var bufferValue;
    var bufferSpacing;
    var uniformName;
    var uniformValue;
    var geometryId;

    while (commands.length) {
        var command = commands.shift();

        switch (command) {
            case 'MATERIAL_INPUT':
                var name = commands.shift();
                var mat = commands.shift();
                mesh.uniforms.baseColor[0] = - mat._id;
                this.program.registerMaterial(name, mat);
                this.updateSize();
                break;
            case GL_SET_GEOMETRY:

                mesh.geometry = commands.shift();
                mesh.drawType = commands.shift();
                mesh.dynamic = commands.shift();
                break;

            case GL_UNIFORMS:

                uniformName = commands.shift();
                uniformValue = commands.shift();

                mesh.uniforms[uniformName] = uniformValue;
                break;

            case GL_BUFFER_DATA:

                geometryId = commands.shift();
                bufferName = commands.shift();
                bufferValue = commands.shift();
                bufferSpacing = commands.shift();

                this.bufferRegistry.allocate(geometryId, bufferName, bufferValue, bufferSpacing, mesh.dynamic);
                break;

            case WITH: commands.unshift(command); return;
        }
    }
};

WebGLRenderer.prototype.draw = function draw() {
    var mesh;
    var buffers;
    var size;

    for (var key in this.meshRegistry) {
        mesh = this.meshRegistry[key];
        buffers = this.bufferRegistry.registry[mesh.geometry];

        if (!buffers) return;

        uniformValues[0] = this.projectionTransform;
        uniformValues[1] = mesh.uniforms.transform;
        uniformValues[2] = mesh.uniforms.opacity;
        uniformValues[3] = mesh.uniforms.origin;
        uniformValues[4] = mesh.uniforms.size;
        uniformValues[5] = mesh.uniforms.baseColor;

        this.program.setUniforms(uniformNames, uniformValues);

        this.drawBuffers(buffers, mesh.drawType, mesh.geometry);
    }
};

/**
 * Loads the buffers and issues the draw command for a geometry
 *
 * @method drawBuffers
 *
 * @param {Object} Map of vertex buffers keyed by attribute identifier
 * @param {Number} Enumerator defining what primitive to draw
 *
 */

WebGLRenderer.prototype.drawBuffers = function drawBuffers(vertexBuffers, mode, id) {
    var gl = this.gl;
    var length = 0;
    var attribute;
    var location;
    var spacing;
    var offset;
    var buffer;
    var j;

    for (var i = 0; i < vertexBuffers.keys.length; i++) {
        attribute = vertexBuffers.keys[i];

        // Do not set vertexAttribPointer if index buffer.

        if (attribute === INDICES) {
            j = i; continue;
        }

        // Retreive the attribute location and make sure it is enabled.

        location = this.program.attributeLocations[attribute];

        if (location === -1) continue;
        if (location === undefined) {
            location = gl.getAttribLocation(this.program.program, attribute);
            this.program.attributeLocations[attribute] = location;
            if (location !== -1) gl.enableVertexAttribArray(location);
        }

        // Retreive buffer information used to set attribute pointer.

        buffer = vertexBuffers.values[i];
        spacing = vertexBuffers.spacing[i];
        offset = vertexBuffers.offset[i];
        length = vertexBuffers.length[i];

        // Skip bindBuffer if buffer is currently bound.

        if (this.state.boundArrayBuffer !== buffer) {
            gl.bindBuffer(buffer.target, buffer.buffer);
            this.state.boundArrayBuffer = buffer;
        }

        if (this.state.lastDrawn !== id) {
            gl.vertexAttribPointer(location, spacing, gl.FLOAT, gl.FALSE, 0, 4 * offset);
        }
    }

    if (length) {

        // If index buffer, use drawElements.

        if (j !== undefined) {
            buffer = vertexBuffers.values[j];
            offset = vertexBuffers.offset[j];
            spacing = vertexBuffers.spacing[j];
            length = vertexBuffers.length[j];

            // Skip bindBuffer if buffer is currently bound.

            if (this.state.boundElementBuffer !== buffer) {
                gl.bindBuffer(buffer.target, buffer.buffer);
                this.state.boundElementBuffer = buffer;
            }

            gl.drawElements(mode, length, gl.UNSIGNED_SHORT, 2 * offset);
        }
        else {
            gl.drawArrays(mode, 0, length);
        }
    }

    this.state.lastDrawn = id;
};

/**
 * Loads the image data into the material
 *
 * @method registerMaterial
 *
 * @param {Material} the object that contains the image data
 *
 */

WebGLRenderer.prototype.registerMaterial = function registerMaterial(material) {
    var image = material.options.image;
    var tex;

    if (image) {
        tex = this.texCache[image];
        if (!tex) {
            tex = new Texture(this.gl);
            tex.setImage(checkerBoard);
            this.texCache[image] = tex;
            loadImage(image, function (img) {
                tex.bind();
                tex.setImage(img);
            });
        }

        this.textureRegistry[material.entity] = tex;
    }
};

/**
 * Allocates an array buffer where vertex data is sent to via compile.
 *
 * @method renderOffscreen
 *
 * @param {Function} The render function to be called after setup and before cleanup
 * @param {spec} The object containing mesh data
 * @param {context} The object containing global render information
 * @param {Texture} The location where the render data is stored
 *
 */

function renderOffscreen(callback, spec, context, texture) {
    var gl = this.gl;
    var v = context._size;

    var framebuffer  = this.framebuffer ? this.framebuffer : this.framebuffer = gl.createFramebuffer();
    var renderbuffer = this.renderbuffer ? this.renderbuffer : this.renderbuffer = gl.createRenderbuffer();

    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);

    if (v[0] != renderbuffer.width || v[1] != renderbuffer.height) {
        renderbuffer.width = v[0];
        renderbuffer.height = v[1];
        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, v[0], v[1]);
    }

    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture.id, 0);
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);

    if (this.debug) checkFrameBufferStatus(gl);

    callback.call(this, spec);

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
};

/**
 * Uploads an image if it is a string
 *
 * @method loadImage
 *
 * @param {Object, String} image object or string url
 * @param {Function} proc that gets called when the image is loaded
 *
 */
function loadImage (img, callback) {
    var obj = (typeof img === 'string' ? new Image() : img) || {};
    obj.crossOrigin = 'anonymous';
    if (! obj.src) obj.src = img;
    if (! obj.complete) obj.onload = function () { callback(obj); };
    else callback(obj);

    return obj;
}

/**
 * Diagonose the failed intialization of an FBO
 *
 * @method checkFrameBufferStatus
 *
 * @param {Object} the glContext that owns this FBO
 *
 */
function checkFrameBufferStatus(gl) {
    var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);

    switch (status) {
        case gl.FRAMEBUFFER_COMPLETE:
            break;
        case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            throw("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); break;
        case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
            throw("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); break;
        case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
            throw("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); break;
        case gl.FRAMEBUFFER_UNSUPPORTED:
            throw("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED"); break;
        default:
            throw("Incomplete framebuffer: " + status);
    }
};

/**
 * Updates the width and height of parent canvas, sets the viewport size on
 * the WebGL context and updates the resolution uniform for the shader program.
 * If no size is passed in this function will update using the cached size.
 *
 * @method updateSize
 *
 * @param {Number} width Updated width of the drawing context.
 * @param {Number} height Updated height of the drawing context.
 * @param {Number} depth Updated depth of the drawing context.
 *
 */
WebGLRenderer.prototype.updateSize = function updateSize() {
    var newSize = this.container._getSize();

    var width = newSize[0];
    var height = newSize[1];

    this.cachedSize[0] = width;
    this.cachedSize[1] = height;
    this.cachedSize[2] = (width > height) ? width : height;

    this.canvas.width  = width;
    this.canvas.height = height;

    this.gl.viewport(0, 0, this.cachedSize[0], this.cachedSize[1]);

    resolutionValues[0] = this.cachedSize;
    this.program.setUniforms(resolutionName, resolutionValues);
};

module.exports = WebGLRenderer;
<|endoftext|>


<commit_before>
 /*
  Copyright 2016 - 2017 by Jan Dockx

  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.
 */

(function(factory) {
  "use strict";

  var dependencies = [];

  if (typeof define === 'function' && define.amd) {
    dependencies.push("module");
    define(dependencies, factory);
  }
  else if (typeof exports === 'object') {
    module.exports = factory.apply(undefined, dependencies.map(function(d) {return require(d);}));
  }
}(function(amdModule) {
  "use strict";

  /**
   * eol is always \n in modern browsers. On node, it depends on the platform, and is offered by
   * the os-module.
   */
  var eol = "\n";
  if (typeof exports === "object") {
    eol = require("os").EOL;
  }

  var path;
  if (typeof exports === "object") {
    path = require("path");
  }

  var dirSeparator = "/";
  var thisDirectory = ".";
  var parentDirectory = "..";

  function browserModuleLocation(amdModule) {
    var location = window.location.href;
    location = location.split(dirSeparator);
    if (0 <= location[location.length - 1].indexOf(".")) { // last entry is a file
      location.pop();
    }
    location = location.concat(amdModule.uri.split(dirSeparator));
    var dotLocation = location.indexOf(thisDirectory); // remove "this directory" path elements
    while (0 <= dotLocation) {
      location.splice(dotLocation, 1);
      dotLocation = location.indexOf(thisDirectory);
    }
    dotLocation = location.indexOf(parentDirectory); // remove "parent directory" path elements
    while (0 <= dotLocation) {
      location.splice(dotLocation - 1, 2);
      dotLocation = location.indexOf(parentDirectory);
    }
    return location.join(dirSeparator);
  }

  var fileName = (typeof module === "object") ? module.filename : browserModuleLocation(amdModule);

  function typeOf(obj) {
    if (obj === null) { // workaround for some weird implementations
      return "null";
    }
    var result = Object.prototype.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
    // on some browsers, the main window returns as "global" (WebKit) or "window" (FF), but this is an object too
    if (result === "global" || result === "window") {
      result = "object";
    }
    return result; // return String
  }

  /**
   *
Returns the directory name of a path, similar to the Unix dirname command.
   * For example:

   *

   * path.dirname('/foo/bar/baz/asdf/quux');
   * // Returns: '/foo/bar/baz/asdf'
   *

   *
A TypeError is thrown if path is not a string.

   *
This method is a wrapper around node's path.dirname, which is not available on the browser
   * directly.
   */
  var dirname = path
    ? path.dirname
    : function(path) {
        if (typeOf(path) !== "string") {
          throw new TypeError("path is not a string");
        }
        var result = path.split(dirSeparator);
        result.pop();
        return result.join(dirSeparator);
      };

  //noinspection MagicNumberJS
  var util = {

    /**
     * eol is always \n in modern browsers. On node, it depends on the platform.
     */
    eol: eol,

    /**
     * Pattern that matches stack lines on node and Chrome, and not on Safari or Firefox.
     */
    atStackLocation: /^    at (.*)(:\d+:\d+\)?| \(native\))$/,

    /**
     * Pattern that matches stack lines on Safari or Firefox, and not on node and Chrome.
     */
    "@StackLocation": /^(.*@)?https?:\/\/[^\/]*\/([^:\/]*\/)*[^:\/]*.js:\d+:\d+$/,

    /**
     * Pattern that matches stack lines on the current platform.
     */
    stackLocation: null,

    contractLibPath: dirname(dirname(fileName)), // 2 directories up

    /**
     * A better type then Object.toString() or typeof.
     * - toType(undefined); //"undefined"
     * - toType(new); //"null"
     * - toType({a: 4}); //"object"
     * - toType([1, 2, 3]); //"array"
     * - (function() {console.log(toType(arguments))})(); //arguments
     * - toType(new ReferenceError); //"error"
     * - toType(new Date); //"date"
     * - toType(/a-z/); //"regexp"
     * - toType(Math); //"math"
     * - toType(JSON); //"json"
     * - toType(new Number(4)); //"number"
     * - toType(new String("abc")); //"string"
     * - toType(new Boolean(true)); //"boolean"
     *
     * Based on
     * http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
     */
    typeOf: typeOf,

    /**
     * p is a true primitive, i.e., not null, undefined, an object (which implies, not a Date, Math or JSON, nor any
     * Error, and not an array or arguments, and wrapped primitives), not a function. p is a true string, number or
     * boolean.
     */
    isPrimitive: function(p) {
      return (p !== null) && 0 <= ["number", "string", "boolean"].indexOf(typeof p);
    },

    isInteger: function(value) {
      return Number.isInteger
        ? Number.isInteger(value)
        : typeof value === "number"
          && isFinite(value)
          && Math.floor(value) === value;
    },

    pre: function(/*Object?*/ self, /*Function*/ condition) {
      var shiftedCondition = condition || self;
      var shiftedSelf = condition ? self : undefined;
      if (!shiftedCondition.apply(self)) {
        throw new Error("Precondition violation in Toryt Contracts: " + shiftedCondition);
      }
    },

    setAndFreezeProperty: function(obj, propName, value) {
      this.pre(function() {return !util.isPrimitive(obj);});
      this.pre(function() {return util.typeOf(propName) === "string";});

      Object.defineProperty(
        obj,
        propName,
        {
          configurable: false,
          enumerable: true,
          writable: false,
          value: value
        }
      );
    },

    defineConfigurableDerivedProperty: function(prototype, propertyName, derivation) {
      util.pre(function() {return !!prototype && !util.isPrimitive(prototype);});
      util.pre(function() {return util.typeOf(propertyName) === "string";});
      util.pre(function() {return util.typeOf(derivation) === "function";});

      Object.defineProperty(
        prototype,
        propertyName,
        {
          configurable: true,
          enumerable: true,
          get: derivation,
          set: undefined
        }
      );
    },

    defineFrozenDerivedProperty: function(prototype, propertyName, derivation) {
      util.pre(function() {return !!prototype && !util.isPrimitive(prototype);});
      util.pre(function() {return util.typeOf(propertyName) === "string";});
      util.pre(function() {return util.typeOf(derivation) === "function";});

      Object.defineProperty(
        prototype,
        propertyName,
        {
          configurable: false,
          enumerable: true,
          get: derivation,
          set: undefined
        }
      );
    },

    defineFrozenReadOnlyArrayProperty: function(prototype, propName, privatePropName) {
      this.pre(function() {return !util.isPrimitive(prototype);});
      this.pre(function() {return util.typeOf(propName) === "string";});
      this.pre(function() {return util.typeOf(privatePropName) === "string";});
      this.pre(function() {return propName !== privatePropName;});

      this.defineFrozenDerivedProperty(
        prototype,
        propName,
        function() {return this[privatePropName].slice();}
      );
    },

    isFrozenOwnProperty: function(obj, propName) {
      this.pre(function() {return obj !== null && obj !== undefined;});

      var descriptor = Object.getOwnPropertyDescriptor(obj, propName);
      return descriptor
             && descriptor.enumerable === true
             && descriptor.configurable === false
             && (descriptor.writable === false || (this.typeOf(descriptor.get) === "function" && !descriptor.set));
    },

    nrOfLines: function(str) {
      return ("" + str).split(this.eol).length;
    },

    /**
     * location is a stack line location, that refers to code that is not inside this library,
     * and does not refer to native code. Native code is defined as a location that does not contain a "/".
     * The latter is only relevant on node. This is not an issue in browsers.
     */
    isALocationOutsideLibrary: function(location) {
      if (this.typeOf(location) !== "string") {
        return false;
      }
      var lines = location.split(this.eol);
      return lines.length === 1
             && this.stackLocation.test(lines[0])
             && 0 <= lines[0].indexOf("/")
             && lines[0].indexOf(this.contractLibPath) < 0;
    },

    /**
     * The first line from a stack trace created here that refers to code that is not inside this library,
     * and does not refer to native code. Returns the empty string if no such line is found.
     *
     * When this result is used as a line on its own, it is clickable to navigate to the referred source code
     * in most console.
     */
    firstLocationOutsideLibrary: function() {
      var stackSource = new Error();

      var nrOfMessageLines = 0;
      var stack = stackSource.stack;
      var messageLines = stackSource.toString();
      if (stack.indexOf(messageLines) === 0) {
        nrOfMessageLines = util.nrOfLines(messageLines); // skip these
      }
      stack = stack.split(this.eol);
      for (var i = nrOfMessageLines; i < stack.length; i++) {
        // skip the message lines, and then look for the first line that refers to code not in this library,
        // that is not native code (i.e., the reference does contain a '/')
        if (0 <= stack[i].indexOf("/") && stack[i].indexOf(this.contractLibPath) < 0) {
          return stack[i];
        }
      }
      return ""; // could not find a line outside this library
    },

    /**
     * Input an error, and transform its stack so it only contains lines that refer to
     * code outside this library, and not to native code. The initial name and message is removed,
     * taking into account that the message could be multi-line.
     */
    stackOutsideThisLibrary: function(error) {
      util.pre(function() {return error instanceof Error;});
      util.pre(function() {return !!error.stack;});

      var nrOfMessageLines = 0;
      var stack = error.stack;
      var messageLines = error.toString();
      if (stack.indexOf(messageLines) === 0) {
        nrOfMessageLines = util.nrOfLines(messageLines); // skip these
      }
      var foundALineOutsideTheLibrary = false;
      var result = error.stack
        .split(util.eol)
        .splice(nrOfMessageLines) // everything after the message lines
        .reduce(
          function(acc, line, index) {
            if (!foundALineOutsideTheLibrary &&
                line.indexOf(util.contractLibPath) < 0 &&
                0 <= line.indexOf("/")) {
              // we found the first line of code not in this library and not native code
              foundALineOutsideTheLibrary = true;
            }
            if (line &&
                line.indexOf(util.contractLibPath) < 0 &&
                 (0 <= line.indexOf("/") || foundALineOutsideTheLibrary)) {
              // copy the lines not referring to this library that are not referring to
              // native code, and the lines that are referring to native code once we encountered the first line
              // of non-native code that refers to code outside this library, if the are not empty
              acc.push(line);
            }
            return acc;
          },
          []
        );
      return result.join(util.eol);
    },

    maxLengthOfConciseRepresentation: 80,
    lengthOfEndConciseRepresentation: 15,
    conciseSeparator: " … ",

    /**
     * Returns a concise representation of f to be used in output.
     */
    conciseConditionRepresentation: function(prefix, f) {
      util.pre(function() {return util.typeOf(prefix) === "string";});

      var result = (f && f.displayName) || (prefix + " " + ((f && f.name) || f));
      result = result.replace(/\s\s+/g, " ");
      if (util.maxLengthOfConciseRepresentation < result.length) {
        var startLength = util.maxLengthOfConciseRepresentation
                          - util.lengthOfEndConciseRepresentation
                          - util.conciseSeparator.length;
        var start = result.slice(0, startLength);
        var end = result.slice(-util.lengthOfEndConciseRepresentation);
        result = start + util.conciseSeparator + end;
      }
      return result;
    },

    /**
     *
Returns a moderately normalized extensive, multiline representation of a thrown.
     *
Anything can be thrown, not only Error instances.

     *
The stack of an Error is different in different environments. In node and Chrome, the first line of the
     *   stack is actually the toString of the Error, followed by the true stack, one call per line, that starts
     *   with /^    at/, followed by the path of the file where the call was made.
     *   In Firefox and Safari, the stack only contains the true stack, and the lines
     *   are the name of the called function (or the empty string for anonymous functions), followed by @,
     *   followed by the path of the file where the call was made.

     *
If the thrown does not have a stack property, its standard string representation is returned.

     *
If the thrown does have a stack property, its stack is returned. If the stack starts with
     *   the string representation of the thrown, that's it. Otherwise, the string representation of the
     *   thrown is added in the front on a separate line.
     */
    extensiveThrownRepresentation: function(thrown) {
      var thrownString = "" + thrown;
      var stack = thrown && thrown.stack;
      if (!stack) {
        return thrownString;
      }
      stack = "" + stack; // make sure it is a string
      /* On node and chrome, the stack starts with thrown.toString (name and message).
         On safari and FF, it doesn't: thrown.stack it is the pure stack. We add the toString ourselves */
      return (stack.indexOf(thrownString) === 0) ? stack : (thrownString + this.eol + stack);
    },

    /**
     *
Returns the directory name of a path, similar to the Unix dirname command.
     * For example:

     *

     * path.dirname('/foo/bar/baz/asdf/quux');
     * // Returns: '/foo/bar/baz/asdf'
     *

     *
A TypeError is thrown if path is not a string.

     *
This method is a wrapper around node's path.dirname, which is not available on the browser
     * directly.
     */
    dirname: dirname,

    browserModuleLocation: browserModuleLocation
  };

  // not the first line, because on some platforms, that is the toString
  var stackLine = (new Error("Error for setup")).stack.split(util.eol)[2];
  if (util.atStackLocation.test(stackLine)) {
    util.stackLocation = util.atStackLocation;
  }
  else if (util["@StackLocation"].test(stackLine)) {
    util.stackLocation = util["@StackLocation"];
  }
  else {
    throw new Error("Determined from an Error stack line that the current platform is not supported.");
  }

  return util;
}));
<commit_msg>Note a MUDO and a TODO<commit_after>
 /*
  Copyright 2016 - 2017 by Jan Dockx

  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.
 */

(function(factory) {
  "use strict";

  var dependencies = [];

  if (typeof define === 'function' && define.amd) {
    dependencies.push("module");
    define(dependencies, factory);
  }
  else if (typeof exports === 'object') {
    module.exports = factory.apply(undefined, dependencies.map(function(d) {return require(d);}));
  }
}(function(amdModule) {
  "use strict";

  /**
   * eol is always \n in modern browsers. On node, it depends on the platform, and is offered by
   * the os-module.
   */
  // TODO is there no way to do this without the os-dependency?
  var eol = "\n";
  if (typeof exports === "object") {
    eol = require("os").EOL;
  }

  var path;
  if (typeof exports === "object") {
    path = require("path");
  }

  var dirSeparator = "/";
  var thisDirectory = ".";
  var parentDirectory = "..";

  function browserModuleLocation(amdModule) {
    var location = window.location.href;
    location = location.split(dirSeparator);
    if (0 <= location[location.length - 1].indexOf(".")) { // last entry is a file
      location.pop();
    }
    location = location.concat(amdModule.uri.split(dirSeparator));
    var dotLocation = location.indexOf(thisDirectory); // remove "this directory" path elements
    while (0 <= dotLocation) {
      location.splice(dotLocation, 1);
      dotLocation = location.indexOf(thisDirectory);
    }
    dotLocation = location.indexOf(parentDirectory); // remove "parent directory" path elements
    while (0 <= dotLocation) {
      location.splice(dotLocation - 1, 2);
      dotLocation = location.indexOf(parentDirectory);
    }
    return location.join(dirSeparator);
  }

  var fileName = (typeof module === "object") ? module.filename : browserModuleLocation(amdModule);

  function typeOf(obj) {
    if (obj === null) { // workaround for some weird implementations
      return "null";
    }
    var result = Object.prototype.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
    // on some browsers, the main window returns as "global" (WebKit) or "window" (FF), but this is an object too
    if (result === "global" || result === "window") {
      result = "object";
    }
    return result; // return String
  }

  /* MUDO we still need a unit test for this function; better then to just do away with ugly path dependency
     once and for all */
  /**
   *
Returns the directory name of a path, similar to the Unix dirname command.
   * For example:

   *

   * path.dirname('/foo/bar/baz/asdf/quux');
   * // Returns: '/foo/bar/baz/asdf'
   *

   *
A TypeError is thrown if path is not a string.

   *
This method is a wrapper around node's path.dirname, which is not available on the browser
   * directly.
   */
  var dirname = path
    ? path.dirname
    : function(path) {
        if (typeOf(path) !== "string") {
          throw new TypeError("path is not a string");
        }
        var result = path.split(dirSeparator);
        result.pop();
        return result.join(dirSeparator);
      };

  //noinspection MagicNumberJS
  var util = {

    /**
     * eol is always \n in modern browsers. On node, it depends on the platform.
     */
    eol: eol,

    /**
     * Pattern that matches stack lines on node and Chrome, and not on Safari or Firefox.
     */
    atStackLocation: /^    at (.*)(:\d+:\d+\)?| \(native\))$/,

    /**
     * Pattern that matches stack lines on Safari or Firefox, and not on node and Chrome.
     */
    "@StackLocation": /^(.*@)?https?:\/\/[^\/]*\/([^:\/]*\/)*[^:\/]*.js:\d+:\d+$/,

    /**
     * Pattern that matches stack lines on the current platform.
     */
    stackLocation: null,

    contractLibPath: dirname(dirname(fileName)), // 2 directories up

    /**
     * A better type then Object.toString() or typeof.
     * - toType(undefined); //"undefined"
     * - toType(new); //"null"
     * - toType({a: 4}); //"object"
     * - toType([1, 2, 3]); //"array"
     * - (function() {console.log(toType(arguments))})(); //arguments
     * - toType(new ReferenceError); //"error"
     * - toType(new Date); //"date"
     * - toType(/a-z/); //"regexp"
     * - toType(Math); //"math"
     * - toType(JSON); //"json"
     * - toType(new Number(4)); //"number"
     * - toType(new String("abc")); //"string"
     * - toType(new Boolean(true)); //"boolean"
     *
     * Based on
     * http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
     */
    typeOf: typeOf,

    /**
     * p is a true primitive, i.e., not null, undefined, an object (which implies, not a Date, Math or JSON, nor any
     * Error, and not an array or arguments, and wrapped primitives), not a function. p is a true string, number or
     * boolean.
     */
    isPrimitive: function(p) {
      return (p !== null) && 0 <= ["number", "string", "boolean"].indexOf(typeof p);
    },

    isInteger: function(value) {
      return Number.isInteger
        ? Number.isInteger(value)
        : typeof value === "number"
          && isFinite(value)
          && Math.floor(value) === value;
    },

    pre: function(/*Object?*/ self, /*Function*/ condition) {
      var shiftedCondition = condition || self;
      var shiftedSelf = condition ? self : undefined;
      if (!shiftedCondition.apply(self)) {
        throw new Error("Precondition violation in Toryt Contracts: " + shiftedCondition);
      }
    },

    setAndFreezeProperty: function(obj, propName, value) {
      this.pre(function() {return !util.isPrimitive(obj);});
      this.pre(function() {return util.typeOf(propName) === "string";});

      Object.defineProperty(
        obj,
        propName,
        {
          configurable: false,
          enumerable: true,
          writable: false,
          value: value
        }
      );
    },

    defineConfigurableDerivedProperty: function(prototype, propertyName, derivation) {
      util.pre(function() {return !!prototype && !util.isPrimitive(prototype);});
      util.pre(function() {return util.typeOf(propertyName) === "string";});
      util.pre(function() {return util.typeOf(derivation) === "function";});

      Object.defineProperty(
        prototype,
        propertyName,
        {
          configurable: true,
          enumerable: true,
          get: derivation,
          set: undefined
        }
      );
    },

    defineFrozenDerivedProperty: function(prototype, propertyName, derivation) {
      util.pre(function() {return !!prototype && !util.isPrimitive(prototype);});
      util.pre(function() {return util.typeOf(propertyName) === "string";});
      util.pre(function() {return util.typeOf(derivation) === "function";});

      Object.defineProperty(
        prototype,
        propertyName,
        {
          configurable: false,
          enumerable: true,
          get: derivation,
          set: undefined
        }
      );
    },

    defineFrozenReadOnlyArrayProperty: function(prototype, propName, privatePropName) {
      this.pre(function() {return !util.isPrimitive(prototype);});
      this.pre(function() {return util.typeOf(propName) === "string";});
      this.pre(function() {return util.typeOf(privatePropName) === "string";});
      this.pre(function() {return propName !== privatePropName;});

      this.defineFrozenDerivedProperty(
        prototype,
        propName,
        function() {return this[privatePropName].slice();}
      );
    },

    isFrozenOwnProperty: function(obj, propName) {
      this.pre(function() {return obj !== null && obj !== undefined;});

      var descriptor = Object.getOwnPropertyDescriptor(obj, propName);
      return descriptor
             && descriptor.enumerable === true
             && descriptor.configurable === false
             && (descriptor.writable === false || (this.typeOf(descriptor.get) === "function" && !descriptor.set));
    },

    nrOfLines: function(str) {
      return ("" + str).split(this.eol).length;
    },

    /**
     * location is a stack line location, that refers to code that is not inside this library,
     * and does not refer to native code. Native code is defined as a location that does not contain a "/".
     * The latter is only relevant on node. This is not an issue in browsers.
     */
    isALocationOutsideLibrary: function(location) {
      if (this.typeOf(location) !== "string") {
        return false;
      }
      var lines = location.split(this.eol);
      return lines.length === 1
             && this.stackLocation.test(lines[0])
             && 0 <= lines[0].indexOf("/")
             && lines[0].indexOf(this.contractLibPath) < 0;
    },

    /**
     * The first line from a stack trace created here that refers to code that is not inside this library,
     * and does not refer to native code. Returns the empty string if no such line is found.
     *
     * When this result is used as a line on its own, it is clickable to navigate to the referred source code
     * in most console.
     */
    firstLocationOutsideLibrary: function() {
      var stackSource = new Error();

      var nrOfMessageLines = 0;
      var stack = stackSource.stack;
      var messageLines = stackSource.toString();
      if (stack.indexOf(messageLines) === 0) {
        nrOfMessageLines = util.nrOfLines(messageLines); // skip these
      }
      stack = stack.split(this.eol);
      for (var i = nrOfMessageLines; i < stack.length; i++) {
        // skip the message lines, and then look for the first line that refers to code not in this library,
        // that is not native code (i.e., the reference does contain a '/')
        if (0 <= stack[i].indexOf("/") && stack[i].indexOf(this.contractLibPath) < 0) {
          return stack[i];
        }
      }
      return ""; // could not find a line outside this library
    },

    /**
     * Input an error, and transform its stack so it only contains lines that refer to
     * code outside this library, and not to native code. The initial name and message is removed,
     * taking into account that the message could be multi-line.
     */
    stackOutsideThisLibrary: function(error) {
      util.pre(function() {return error instanceof Error;});
      util.pre(function() {return !!error.stack;});

      var nrOfMessageLines = 0;
      var stack = error.stack;
      var messageLines = error.toString();
      if (stack.indexOf(messageLines) === 0) {
        nrOfMessageLines = util.nrOfLines(messageLines); // skip these
      }
      var foundALineOutsideTheLibrary = false;
      var result = error.stack
        .split(util.eol)
        .splice(nrOfMessageLines) // everything after the message lines
        .reduce(
          function(acc, line, index) {
            if (!foundALineOutsideTheLibrary &&
                line.indexOf(util.contractLibPath) < 0 &&
                0 <= line.indexOf("/")) {
              // we found the first line of code not in this library and not native code
              foundALineOutsideTheLibrary = true;
            }
            if (line &&
                line.indexOf(util.contractLibPath) < 0 &&
                 (0 <= line.indexOf("/") || foundALineOutsideTheLibrary)) {
              // copy the lines not referring to this library that are not referring to
              // native code, and the lines that are referring to native code once we encountered the first line
              // of non-native code that refers to code outside this library, if the are not empty
              acc.push(line);
            }
            return acc;
          },
          []
        );
      return result.join(util.eol);
    },

    maxLengthOfConciseRepresentation: 80,
    lengthOfEndConciseRepresentation: 15,
    conciseSeparator: " … ",

    /**
     * Returns a concise representation of f to be used in output.
     */
    conciseConditionRepresentation: function(prefix, f) {
      util.pre(function() {return util.typeOf(prefix) === "string";});

      var result = (f && f.displayName) || (prefix + " " + ((f && f.name) || f));
      result = result.replace(/\s\s+/g, " ");
      if (util.maxLengthOfConciseRepresentation < result.length) {
        var startLength = util.maxLengthOfConciseRepresentation
                          - util.lengthOfEndConciseRepresentation
                          - util.conciseSeparator.length;
        var start = result.slice(0, startLength);
        var end = result.slice(-util.lengthOfEndConciseRepresentation);
        result = start + util.conciseSeparator + end;
      }
      return result;
    },

    /**
     *
Returns a moderately normalized extensive, multiline representation of a thrown.
     *
Anything can be thrown, not only Error instances.

     *
The stack of an Error is different in different environments. In node and Chrome, the first line of the
     *   stack is actually the toString of the Error, followed by the true stack, one call per line, that starts
     *   with /^    at/, followed by the path of the file where the call was made.
     *   In Firefox and Safari, the stack only contains the true stack, and the lines
     *   are the name of the called function (or the empty string for anonymous functions), followed by @,
     *   followed by the path of the file where the call was made.

     *
If the thrown does not have a stack property, its standard string representation is returned.

     *
If the thrown does have a stack property, its stack is returned. If the stack starts with
     *   the string representation of the thrown, that's it. Otherwise, the string representation of the
     *   thrown is added in the front on a separate line.
     */
    extensiveThrownRepresentation: function(thrown) {
      var thrownString = "" + thrown;
      var stack = thrown && thrown.stack;
      if (!stack) {
        return thrownString;
      }
      stack = "" + stack; // make sure it is a string
      /* On node and chrome, the stack starts with thrown.toString (name and message).
         On safari and FF, it doesn't: thrown.stack it is the pure stack. We add the toString ourselves */
      return (stack.indexOf(thrownString) === 0) ? stack : (thrownString + this.eol + stack);
    },

    /**
     *
Returns the directory name of a path, similar to the Unix dirname command.
     * For example:

     *

     * path.dirname('/foo/bar/baz/asdf/quux');
     * // Returns: '/foo/bar/baz/asdf'
     *

     *
A TypeError is thrown if path is not a string.

     *
This method is a wrapper around node's path.dirname, which is not available on the browser
     * directly.
     */
    dirname: dirname,

    browserModuleLocation: browserModuleLocation
  };

  // not the first line, because on some platforms, that is the toString
  var stackLine = (new Error("Error for setup")).stack.split(util.eol)[2];
  if (util.atStackLocation.test(stackLine)) {
    util.stackLocation = util.atStackLocation;
  }
  else if (util["@StackLocation"].test(stackLine)) {
    util.stackLocation = util["@StackLocation"];
  }
  else {
    throw new Error("Determined from an Error stack line that the current platform is not supported.");
  }

  return util;
}));
<|endoftext|>


<commit_before>"use strict";

var cycl = require('cycl'),
    processor = require('./processor.js'),
    presets = require('./presets.js'),
    rubix = require('./rubix.js'),
    Props = require('./props.js'),
    Values = require('./values.js'),
    Pointer = require('../input/pointer.js'),
    KEY = require('../opts/keys.js'),
    utils = require('../utils/utils.js'),
    Data = require('../bits/data.js'),

    Action = function () {
        var self = this;

        // Create value manager
        this.values = new Values();

        // Create new property manager
        this.props = new Props();

        // Create data store
        this.data = new Data();

        // Register process wth cycl
        this.process = cycl.newProcess(function (framestamp, frameDuration) {
            processor.action(self, framestamp, frameDuration);
        });
    };

Action.prototype = {

    // [number]: Progress represented in a range of 0 - 1
    progress: 0,

    // [number]: Time elapsed in ms
    elapsed: 0,

    /*
        Play the provided actions as animations

        Syntax
            .play(playlist, [override])
                @param [string]: Playlist of presets
                @param [object]: (optional) Override object

            .play(params)
                @param [object]: Action properties

        @return [Action]
    */
    play: function (defs, override) {
        return this.start(KEY.RUBIX.TIME, presets.createBase(defs, override));
    },

    /*
        Track values to mouse, touch or custom Input

        Syntax
            .track(preset, [override], input)
                @param [string]: Name of preset
                @param [object]: (optional) Override object
                @param [event || Input]: Input or event to start tracking

            .track(params, input)
                @param [object]: Action properties
                @param [event || Input]: Input or event to start tracking

        @return [Action]
    */
    track: function (defs) {
        var hasAllArgs = (arguments[2] !== undefined),
            input = hasAllArgs ? arguments[2] : arguments[1],
            override = hasAllArgs ? arguments[1] : {},
            base = presets.createBase(defs, override);

        // If we have an input, check if it's a custom input.
        // Create a new pointer if it isn't
        if (input) {
            base.input = (input.current) ? input : new Pointer(input);
            base.inputOrigin = base.input.get();
        }

        return this.start(KEY.RUBIX.INPUT, base);
    },

    /*
        Run Action indefinitely

        Syntax
            .run(preset, [override])
                @param [string]: Name of preset
                @param [object]: (optional) Override object

            .run(params)
                @param [object]: Action properties

        @return [Action]
    */
    run: function (defs, override) {
        return this.start(KEY.RUBIX.RUN, presets.createBase(defs, override));
    },

    /*
        Start Action

        @param [string]: Name of processing type to sue
        @param [object]: Base Action properties to apply
        @return [Action]
    */
    start: function (processType, base) {
        this.resetProgress();
        this.change(processType, base);
        this.isActive(true);
        this.started = utils.currentTime() + this.props.get('delay');
        this.framestamp = this.started;
        this.firstFrame = true;

        this.process.start();

        return this;
    },

    /*
        Stop current Action process
    */
    stop: function () {
        this.isActive(false);
        this.process.stop();

        return this;
    },

    /*
        Pause current Action
    */
    pause: function () {
        this.stop();

        return this;
    },

    /*
        Resume a paused Action
    */
    resume: function () {
        this.started = utils.currentTime() - this.elapsed;
        this.framestamp = this.started;

        this.process.start();

        return this;
    },

    /*

    */
    reset: function () {
        this.resetProgress();
        this.values.reset();

        return this;
    },

    resetProgress: function () {
        this.progress = 0;
        this.elapsed = 0;
        this.started = utils.currentTime();
    },

    reverse: function () {
        this.progress = calc.difference(this.progress, 1);
        this.elapsed = calc.difference(this.elapsed, this.duration);
        this.values.reverse();

        return this;
    },

    /*
        Check for next steps and perform, stop if not
    */
    next: function () {
        var nexts = [{
                key: 'loop',
                callback: this.reset
            }, {
                key: 'yoyo',
                callback: this.reverse
            }],
            possibles = nexts.length,
            hasNext = false;

        for (var i = 0; i < possibles; ++i) {
            if (this.checkNextStep(nexts[i].key, nexts[i].callback)) {
                hasNext = true;
                break;
            }
        }

        if (!hasNext && !this.checkNextStep()) {
            this.stop();
        }
    },

    /*
        Check next step

        @param [string]: Name of step ('yoyo' or 'loop')
        @param [callback]: Function to run if we take this step
    */
    checkNextStep: function (key, callback) {
        var stepTaken = false,
            step = this.props.get(key),
            count = this.props.get(key + 'Count'),
            forever = (step === true);

        if (forever || utils.isNum(step)) {
            ++count;
            this.props.set(key + 'Count', count);

            if (forever || count <= step) {
                callback.call(this);
                stepTaken = true;
            }
        }
    },

    /*
        Next in playlist
    */
    playNext: function () {
        var stepTaken = false,
            playlist = this.props.get('playlist'),
            platlistLength = playlist.length,
            playhead = this.props.get('playhead'),
            next = {};

        // Check we have a playlist
        if (playlistLength > 1) {
            ++playhead;

            if (playhead < playlistLength) {
                next = presets.getDefined(playlist[playhead]);
                next.playhead = playhead;

                this.change(KEY.RUBIX.TIME, next);
                stepTaken = true;
            }
        }
    },

    setValue: function (key, value) {
        this.values.set(key, value);
    },

    getValue: function (key) {
        return this.values.get(key);
    },

    setProp: function (key, value) {
        this.props.set(key, value);
    },

    getProp: function (key) {
        return this.props.get(key);
    },

    /*
        Is Action active?

        @param [boolean] (optional): If provided, will set action to active/inactive
        @return [boolean]: Active status
    */
    isActive: function (active) {
        if (active !== active) {
            this.active = active;
        }

        return this.active;
    },

    /*
        Change Action properties

        @param [string]: Type of processing rubix to use
        @param [object]: Base properties of new input
    */
    change: function (processType, base) {
        // Assign the processing rubix
        base.rubix = rubix[processType];

        this.props.apply(base);
        this.values.apply(base.values, this.props);

        this.origin = {};
        // Create origins
        for (var key in this.values) {
            if (this.values.hasOwnProperty(key)) {
                this.origin[key] = this.values[key].current;
            }
        }
    }

};

module.exports = Action;<commit_msg>fixed looping<commit_after>"use strict";

var cycl = require('cycl'),
    processor = require('./processor.js'),
    presets = require('./presets.js'),
    rubix = require('./rubix.js'),
    Props = require('./props.js'),
    Values = require('./values.js'),
    Pointer = require('../input/pointer.js'),
    KEY = require('../opts/keys.js'),
    utils = require('../utils/utils.js'),
    Data = require('../bits/data.js'),

    Action = function () {
        var self = this;

        // Create value manager
        this.values = new Values();

        // Create new property manager
        this.props = new Props();

        // Create data store
        this.data = new Data();

        // Register process wth cycl
        this.process = cycl.newProcess(function (framestamp, frameDuration) {
            processor.action(self, framestamp, frameDuration);
        });
    };

Action.prototype = {

    // [number]: Progress represented in a range of 0 - 1
    progress: 0,

    // [number]: Time elapsed in ms
    elapsed: 0,

    /*
        Play the provided actions as animations

        Syntax
            .play(playlist, [override])
                @param [string]: Playlist of presets
                @param [object]: (optional) Override object

            .play(params)
                @param [object]: Action properties

        @return [Action]
    */
    play: function (defs, override) {
        return this.start(KEY.RUBIX.TIME, presets.createBase(defs, override));
    },

    /*
        Track values to mouse, touch or custom Input

        Syntax
            .track(preset, [override], input)
                @param [string]: Name of preset
                @param [object]: (optional) Override object
                @param [event || Input]: Input or event to start tracking

            .track(params, input)
                @param [object]: Action properties
                @param [event || Input]: Input or event to start tracking

        @return [Action]
    */
    track: function (defs) {
        var hasAllArgs = (arguments[2] !== undefined),
            input = hasAllArgs ? arguments[2] : arguments[1],
            override = hasAllArgs ? arguments[1] : {},
            base = presets.createBase(defs, override);

        // If we have an input, check if it's a custom input.
        // Create a new pointer if it isn't
        if (input) {
            base.input = (input.current) ? input : new Pointer(input);
            base.inputOrigin = base.input.get();
        }

        return this.start(KEY.RUBIX.INPUT, base);
    },

    /*
        Run Action indefinitely

        Syntax
            .run(preset, [override])
                @param [string]: Name of preset
                @param [object]: (optional) Override object

            .run(params)
                @param [object]: Action properties

        @return [Action]
    */
    run: function (defs, override) {
        return this.start(KEY.RUBIX.RUN, presets.createBase(defs, override));
    },

    /*
        Start Action

        @param [string]: Name of processing type to sue
        @param [object]: Base Action properties to apply
        @return [Action]
    */
    start: function (processType, base) {
        this.resetProgress();
        this.change(processType, base);
        this.isActive(true);
        this.started = utils.currentTime() + this.props.get('delay');
        this.framestamp = this.started;
        this.firstFrame = true;

        this.process.start();

        return this;
    },

    /*
        Stop current Action process
    */
    stop: function () {
        this.isActive(false);
        this.process.stop();

        return this;
    },

    /*
        Pause current Action
    */
    pause: function () {
        this.stop();

        return this;
    },

    /*
        Resume a paused Action
    */
    resume: function () {
        this.started = utils.currentTime() - this.elapsed;
        this.framestamp = this.started;

        this.process.start();

        return this;
    },

    /*
        Reset Action progress and values
    */
    reset: function () {
        this.resetProgress();
        this.values.reset();

        return this;
    },

    /*
	    Reset Action progress
    */
    resetProgress: function () {
        this.progress = 0;
        this.elapsed = 0;
        this.started = utils.currentTime();
    },

    /*
	    Reverse Action progress and values
    */
    reverse: function () {
        this.progress = calc.difference(this.progress, 1);
        this.elapsed = calc.difference(this.elapsed, this.duration);
        this.values.reverse();

        return this;
    },

    /*
        Check for next steps and perform, stop if not
    */
    next: function () {
        var nexts = [{
                key: 'loop',
                callback: this.reset
            }, {
                key: 'yoyo',
                callback: this.reverse
            }],
            possibles = nexts.length,
            hasNext = false;

        for (var i = 0; i < possibles; ++i) {
            if (this.checkNextStep(nexts[i].key, nexts[i].callback)) {
                hasNext = true;
                break;
            }
        }

        if (!hasNext && !this.checkNextStep()) {
            this.stop();
        }
    },

    /*
        Check next step

        @param [string]: Name of step ('yoyo' or 'loop')
        @param [callback]: Function to run if we take this step
    */
    checkNextStep: function (key, callback) {
        var stepTaken = false,
            step = this.props.get(key),
            count = this.props.get(key + 'Count'),
            forever = (step === true);

        if (forever || utils.isNum(step)) {
            ++count;
            this.props.set(key + 'Count', count);

            if (forever || count <= step) {
                callback.call(this);
                stepTaken = true;
            }
        }

        return stepTaken;
    },

    /*
        Next in playlist
    */
    playNext: function () {
        var stepTaken = false,
            playlist = this.props.get('playlist'),
            platlistLength = playlist.length,
            playhead = this.props.get('playhead'),
            next = {};

        // Check we have a playlist
        if (playlistLength > 1) {
            ++playhead;

            if (playhead < playlistLength) {
                next = presets.getDefined(playlist[playhead]);
                next.playhead = playhead;

                this.change(KEY.RUBIX.TIME, next);
                stepTaken = true;
            }
        }
    },

    setValue: function (key, value) {
        this.values.set(key, value);
    },

    getValue: function (key) {
        return this.values.get(key);
    },

    setProp: function (key, value) {
        this.props.set(key, value);
    },

    getProp: function (key) {
        return this.props.get(key);
    },

    /*
        Is Action active?

        @param [boolean] (optional): If provided, will set action to active/inactive
        @return [boolean]: Active status
    */
    isActive: function (active) {
        if (active !== active) {
            this.active = active;
        }

        return this.active;
    },

    /*
        Change Action properties

        @param [string]: Type of processing rubix to use
        @param [object]: Base properties of new input
    */
    change: function (processType, base) {
        // Assign the processing rubix
        base.rubix = rubix[processType];

        this.props.apply(base);
        this.values.apply(base.values, this.props);

        this.origin = {};
        // Create origins
        for (var key in this.values) {
            if (this.values.hasOwnProperty(key)) {
                this.origin[key] = this.values[key].current;
            }
        }
    }

};

module.exports = Action;<|endoftext|>


<commit_before>/*

entityManager.js

A module which handles arbitrary entity-management for "Asteroids"

We create this module as a single global object, and initialise it
with suitable 'data' and 'methods'.

"Private" properties are denoted by an underscore prefix convention.

*/

"use strict";

// Tell jslint not to complain about my use of underscore prefixes (nomen),
// my flattening of some indentation (white), or my use of incr/decr ops
// (plusplus).
//
/*jslint nomen: true, white: true, plusplus: true*/

var entityManager = {

// "PRIVATE" DATA

_rocks   : [],
_bullets : [],
_ships   : [],

_bShowRocks : true,

// "PRIVATE" METHODS

_generateRocks : function() {
    var i,
        NUM_ROCKS = 4;

    for (i = 0; i < NUM_ROCKS; ++i) {
        this.generateRock();
    }
},

_findNearestShip : function(posX, posY) {
    var closestShip = null,
        closestIndex = -1,
        closestSq = 1000 * 1000;

    for (var i = 0; i < this._ships.length; ++i) {

        var thisShip = this._ships[i];
        var shipPos = thisShip.getPos();
        var distSq = util.wrappedDistSq(
            shipPos.posX, shipPos.posY,
            posX, posY,
            g_canvas.width, g_canvas.height);

        if (distSq < closestSq) {
            closestShip = thisShip;
            closestIndex = i;
            closestSq = distSq;
        }
    }
    return {
        theShip : closestShip,
        theIndex: closestIndex
    };
},

_forEachOf: function(aCategory, fn) {
    for (var i = 0; i < aCategory.length; ++i) {
        fn.call(aCategory[i]);
    }
},

// PUBLIC METHODS

// A special return value, used by other objects,
// to request the blessed release of death!
//
KILL_ME_NOW : -1,

// Some things must be deferred until after initial construction
// i.e. thing which need `this` to be defined.
//
deferredSetup : function () {
    this._categories = [this._rocks, this._bullets, this._ships];
},

init: function() {
    if (g_settings.enableRocks){
	console.log("generating rocks");
	this._generateRocks();
	}
    //this._generateShip();
},

fireBullet: function(cx, cy, velX, velY, rotation) {
    this._bullets.push(new Bullet({
        cx   : cx,
        cy   : cy,
        velX : velX,
        velY : velY,

        rotation : rotation
    }));
},

generateRock : function(descr) {
    this._rocks.push(new Rock(descr));
},

generateShip : function(descr) {
    this._ships.push(new Ship(descr));
},

killNearestShip : function(xPos, yPos) {
    var theShip = this._findNearestShip(xPos, yPos).theShip;
    if (theShip) {
        theShip.kill();
    }
},

yoinkNearestShip : function(xPos, yPos) {
    var theShip = this._findNearestShip(xPos, yPos).theShip;
    if (theShip) {
        theShip.setPos(xPos, yPos);
    }
},

resetShips: function() {
    this._forEachOf(this._ships, Ship.prototype.reset);
},

haltShips: function() {
    this._forEachOf(this._ships, Ship.prototype.halt);
},

toggleRocks: function() {
    this._bShowRocks = !this._bShowRocks;
},

update: function(du) {

    for (var c = 0; c < this._categories.length; ++c) {

        var aCategory = this._categories[c];
        var i = 0;

        while (i < aCategory.length) {

            var status = aCategory[i].update(du);

            if (status === this.KILL_ME_NOW) {
                // remove the dead guy, and shuffle the others down to
                // prevent a confusing gap from appearing in the array
		spatialManager.unregister(aCategory[i]);
                aCategory.splice(i,1);

            }
            else {
                ++i;
            }
        }
    }

    if (g_settings.enableRocks && this._rocks.length === 0) this._generateRocks();

},

getMainShip: function() {
    return this._ships[0];
    },

render: function(ctx) {

    var debugX = 10, debugY = 100;
    ctx.save();
    if(this._ships[0]){
        var s = this._ships[0];
	//virkar ekki, reyndu t.d. ad kveikja a collsiion,
	//sem a ad teikna hring a skipinu, en gerir thad ekki.
	//this.offset = [-s.cx - g_canvas.width/2,-s.cy - g_canvas.height/2]
        ctx.translate(-s.cx + g_canvas.width/2,-s.cy + g_canvas.height/2);
	//console.log((s.cx) + " "  + (s.cy));
    }

    ctx.strokeStyle="white";
    ctx.beginPath();
    //ctx.rect(g_canvas.width,g_canvas.height,g_canvas.width,g_canvas.height);
    ctx.moveTo(s.cx - g_canvas.width/2, g_settings.seaLevel-g_canvas.width);
    ctx.lineTo(s.cy + 5*g_canvas.width/2, g_settings.seaLevel-g_canvas.width);
    ctx.stroke();
    ctx.closePath();

    for (var c = 0; c < this._categories.length; ++c) {

        var aCategory = this._categories[c];

        if (!this._bShowRocks &&
            aCategory == this._rocks)
            continue;

        for (var i = 0; i < aCategory.length; ++i) {

            aCategory[i].render(ctx);
            //debug.text(".", debugX + i * 10, debugY);

        }
        debugY += 10;
    }
    ctx.restore();
}

}

// Some deferred setup which needs the object to have been created first
entityManager.deferredSetup();

<commit_msg>Matti fixed it already, added small fix for better bottom rendering<commit_after>/*

entityManager.js

A module which handles arbitrary entity-management for "Asteroids"

We create this module as a single global object, and initialise it
with suitable 'data' and 'methods'.

"Private" properties are denoted by an underscore prefix convention.

*/

"use strict";

// Tell jslint not to complain about my use of underscore prefixes (nomen),
// my flattening of some indentation (white), or my use of incr/decr ops
// (plusplus).
//
/*jslint nomen: true, white: true, plusplus: true*/

var entityManager = {

// "PRIVATE" DATA

_rocks   : [],
_bullets : [],
_ships   : [],

_bShowRocks : true,

// "PRIVATE" METHODS

_generateRocks : function() {
    var i,
        NUM_ROCKS = 4;

    for (i = 0; i < NUM_ROCKS; ++i) {
        this.generateRock();
    }
},

_findNearestShip : function(posX, posY) {
    var closestShip = null,
        closestIndex = -1,
        closestSq = 1000 * 1000;

    for (var i = 0; i < this._ships.length; ++i) {

        var thisShip = this._ships[i];
        var shipPos = thisShip.getPos();
        var distSq = util.wrappedDistSq(
            shipPos.posX, shipPos.posY,
            posX, posY,
            g_canvas.width, g_canvas.height);

        if (distSq < closestSq) {
            closestShip = thisShip;
            closestIndex = i;
            closestSq = distSq;
        }
    }
    return {
        theShip : closestShip,
        theIndex: closestIndex
    };
},

_forEachOf: function(aCategory, fn) {
    for (var i = 0; i < aCategory.length; ++i) {
        fn.call(aCategory[i]);
    }
},

// PUBLIC METHODS

// A special return value, used by other objects,
// to request the blessed release of death!
//
KILL_ME_NOW : -1,

// Some things must be deferred until after initial construction
// i.e. thing which need `this` to be defined.
//
deferredSetup : function () {
    this._categories = [this._rocks, this._bullets, this._ships];
},

init: function() {
    if (g_settings.enableRocks){
	console.log("generating rocks");
	this._generateRocks();
	}
    //this._generateShip();
},

fireBullet: function(cx, cy, velX, velY, rotation) {
    this._bullets.push(new Bullet({
        cx   : cx,
        cy   : cy,
        velX : velX,
        velY : velY,

        rotation : rotation
    }));
},

generateRock : function(descr) {
    this._rocks.push(new Rock(descr));
},

generateShip : function(descr) {
    this._ships.push(new Ship(descr));
},

killNearestShip : function(xPos, yPos) {
    var theShip = this._findNearestShip(xPos, yPos).theShip;
    if (theShip) {
        theShip.kill();
    }
},

yoinkNearestShip : function(xPos, yPos) {
    var theShip = this._findNearestShip(xPos, yPos).theShip;
    if (theShip) {
        theShip.setPos(xPos, yPos);
    }
},

resetShips: function() {
    this._forEachOf(this._ships, Ship.prototype.reset);
},

haltShips: function() {
    this._forEachOf(this._ships, Ship.prototype.halt);
},

toggleRocks: function() {
    this._bShowRocks = !this._bShowRocks;
},

update: function(du) {

    for (var c = 0; c < this._categories.length; ++c) {

        var aCategory = this._categories[c];
        var i = 0;

        while (i < aCategory.length) {

            var status = aCategory[i].update(du);

            if (status === this.KILL_ME_NOW) {
                // remove the dead guy, and shuffle the others down to
                // prevent a confusing gap from appearing in the array
		spatialManager.unregister(aCategory[i]);
                aCategory.splice(i,1);

            }
            else {
                ++i;
            }
        }
    }

    if (g_settings.enableRocks && this._rocks.length === 0) this._generateRocks();

},

getMainShip: function() {
    return this._ships[0];
    },

render: function(ctx) {

    var debugX = 10, debugY = 100;
    ctx.save();
    if(this._ships[0]){
        var s = this._ships[0];
	//virkar ekki, reyndu t.d. ad kveikja a collsiion,
	//sem a ad teikna hring a skipinu, en gerir thad ekki.
	//this.offset = [-s.cx - g_canvas.width/2,-s.cy - g_canvas.height/2]
        ctx.translate(-s.cx + g_canvas.width/2,-s.cy + g_canvas.height/2);
	//console.log((s.cx) + " "  + (s.cy));
    }

    ctx.strokeStyle="white";
    ctx.beginPath();
    //ctx.rect(g_canvas.width,g_canvas.height,g_canvas.width,g_canvas.height);
    ctx.moveTo(s.cx - 3*g_canvas.width/2, g_settings.seaLevel-g_canvas.width);
    ctx.lineTo(s.cy + 3*g_canvas.width/2, g_settings.seaLevel-g_canvas.width);
    ctx.stroke();
    ctx.closePath();

    for (var c = 0; c < this._categories.length; ++c) {

        var aCategory = this._categories[c];

        if (!this._bShowRocks &&
            aCategory == this._rocks)
            continue;

        for (var i = 0; i < aCategory.length; ++i) {

            aCategory[i].render(ctx);
            //debug.text(".", debugX + i * 10, debugY);

        }
        debugY += 10;
    }
    ctx.restore();
}

}

// Some deferred setup which needs the object to have been created first
entityManager.deferredSetup();

<|endoftext|>


<commit_before>"use strict";

var bossTime = false;
var bossOn = false;

var update = function (game, Enemy, Bullet, audio) {

	[game.world.enemies,
	game.world.players,
	game.world.bullets,
	game.world.boss
	].forEach (
		function(gameElementArray) {
			gameElementArray.forEach(function(gameElement) {
				gameElement.update();
			});
		}
	);

	game.world.players.forEach(
		function(gameElement) {
			if (gameElement.kills > 22) {
				bossTime = true;
			}
		}
	);

	game.world.enemies = game.world.enemies.filter(function(enemy) {
		return enemy.active;
	});

	game.world.bullets = game.world.bullets.filter(function(bullet) {
		return bullet.active;
	});

	game.world.boss = game.world.boss.filter(function(boss) {
		return boss.active;
	});

	if (!bossTime && !bossOn) {
		if (Math.random() < 0.02) {
			if (Math.random() < 0.1) {
			} else {
				if (Math.random() < 0.8) {
					game.world.enemies.push(new Enemy(game.world, "right"));
				} else {
					game.world.enemies.push(new Enemy(game.world, "left"));
				}
			}
		}
	} else if (bossTime && !bossOn) {
		game.world.enemies.push(new Boss(game.world, Bullet, audio));
		bossTime = false;
		bossOn = true;
		audio["casanova"].stop();
		audio["pokemonRuby"].loop();
		audio["pokemonRuby"].volume = 30;
		audio["pokemonRuby"].play();
	} else if (bossTime && bossOn) {
		//document.write("foo");
	}
};
<commit_msg>Update update.js<commit_after>"use strict";

var bossTime = false;
var bossOn = false;

var update = function (game, Enemy, Bullet, audio) {

	[game.world.platforms,
	game.world.enemies,
	game.world.boss,
	game.world.players,
	game.world.bullets
	].forEach (
		function(gameElementArray) {
			gameElementArray.forEach(function(gameElement) {
				gameElement.update();
			});
		}
	);

	game.world.players.forEach(
		function(gameElement) {
			if (gameElement.kills > 22) {
				bossTime = true;
			}
		}
	);

	game.world.enemies = game.world.enemies.filter(function(enemy) {
		return enemy.active;
	});

	game.world.bullets = game.world.bullets.filter(function(bullet) {
		return bullet.active;
	});

	game.world.boss = game.world.boss.filter(function(boss) {
		return boss.active;
	});

	game.world.arms = game.world.arms.filter(function(arm) {
		return arm.active;
	});

	game.world.platforms = game.world.platforms.filter(function(platform) {
		return platform.active;
	});

	if (!bossTime && !bossOn) {
		if (Math.random() < 0.02) {
			if (Math.random() < 0.1) {
			} else {
				if (Math.random() < 0.8) {
					game.world.enemies.push(new Enemy(game.world, "right"));
				} else {
					game.world.enemies.push(new Enemy(game.world, "left"));
				}
			}
		}
	} else if (bossTime && !bossOn) {
		game.world.boss.push(new QuadrapusBoss(game.world, Bullet, audio));
		game.world.platforms.push(new Platform(game.world, {
			x: 125,
			y: 250,
		}));
		game.world.platforms.push(new Platform(game.world, {
			x: 425,
			y: 250,
		}));
		game.world.platforms.push(new Platform(game.world, {
			x: 100,
			y: 191,
		}));
		game.world.platforms.push(new Platform(game.world, {
			x: 450,
			y: 191,
		}));
		bossTime = false;
		bossOn = true;
		audio["casanova"].stop();
		audio["pokemonRuby"].loop();
		audio["pokemonRuby"].volume = 30;
		audio["pokemonRuby"].play();
	} else if (bossTime && bossOn) {
	}
};
<|endoftext|>


<commit_before>document.addEventListener("DOMContentLoaded", function() {
  var STATES = [
    "Alaska",
    "Alabama",
    "Arkansas",
    "Arizona",
    "California",
    "Colorado",
    "Connecticut",
    "District of Columbia",
    "Delaware",
    "Florida",
    "Georgia",
    "Hawaii",
    "Iowa",
    "Idaho",
    "Illinois",
    "Indiana",
    "Kansas",
    "Kentucky",
    "Louisiana",
    "Massachusetts",
    "Maryland",
    "Maine",
    "Michigan",
    "Minnesota",
    "Missouri",
    "Mississippi",
    "Montana",
    "North Carolina",
    "North Dakota",
    "Nebraska",
    "New Hampshire",
    "New Jersey",
    "New Mexico",
    "Nevada",
    "New York",
    "Ohio",
    "Oklahoma",
    "Oregon",
    "Pennsylvania",
    "Rhode Island",
    "South Carolina",
    "South Dakota",
    "Tennessee",
    "Texas",
    "Utah",
    "Virginia",
    "Vermont",
    "Washington",
    "Wisconsin",
    "West Virginia",
    "Wyoming"
  ];

  var app = new Vue({
    el: '#political-scoreboard',

    data: {
      states: STATES,
      selectedState: null,
      politicians: [],
      isLoaded: false
    },

    computed: {
      // ORDER BY yesOnCRA ASC, partyCode ASC, name ASC
      sortedPoliticians: function() {
        return this.politicians.sort(function(a, b){
          if (a.yesOnCRA === b.yesOnCRA) {
            if (a.partyCode === b.partyCode) {
              if (a.name < b.name) {
                return -1;
              }
              else if (a.name > b.name) {
                return 1;
              }
              else {
                return 0;
              }
            }
            else if (a.partyCode < b.partyCode) {
              return -1;
            }
            else {
              return 1;
            }
          }
          else if (a.yesOnCRA) {
            return 1;
          }
          else {
            return -1;
          }
        });
      },

      senators: function() {
        return this.sortedPoliticians.filter(function(p){
          return p.organization === 'Senate';
        });
      },

      representatives: function() {
        return this.sortedPoliticians.filter(function(p){
          return p.organization === 'House';
        });
      },

      senatorsInState: function() {
        var self = this;
        return this.senators.filter(function(p){
          return p.state === self.selectedState;
        });
      },

      congressInState: function() {
        var self = this;
        return this.politicians.filter(function(p){
          return p.state === self.selectedState;
        });
      },

      teamInternet: function() {
        return this.politicians.filter(function(p){
          return p.team === 'team-internet';
        });
      },

      undecided: function() {
        return this.politicians.filter(function(p){
          return p.team === 'undecided';
        });
      },

      teamCable: function() {
        return this.politicians.filter(function(p){
          return p.team === 'team-cable';
        });
      },

      // this function needs to change once we add house members because it counts all.
      senateCRACount: function () {
        return this.politicians.filter(function(p){
          return p.yesOnCRA
        }).length
      }
    },

    created: function() {
      this.geocodeSelectedState();
      this.fetchPoliticians();
    },

    methods: {
      geocodeSelectedState: function() {
        var self = this;
        this.$http.get('https://fftf-geocoder.herokuapp.com').then(function(response){
          if (response.ok) {
            var geo = response.body;

            if (
              geo.country.iso_code === 'US' &&
              geo.subdivisions &&
              geo.subdivisions[0] &&
              geo.subdivisions[0].names &&
              geo.subdivisions[0].names.en
            ) {
              self.selectedState = geo.subdivisions[0].names.en;
            }
          }
        });
      },

      fetchPoliticians: function() {
        var self = this;
        this.$http.get('https://data.battleforthenet.com/politicians.json').then(function(response){
          if (response.ok) {
            self.politicians = response.body;
            self.isLoaded = true;
          }
        });
      }
    }
  });

  Vue.component('politician-card', {
    template: '#politician-card-template',
    props: [ 'politician' ],
    methods: {
      imageURL: function(pol, suffix='_x1') {
        return 'https://www.fightforthefuture.org/congress-images/' +  pol.biocode + suffix + '.jpg';
      },

      isLong: function(name) {
        return name.indexOf(' ') === -1 && name.length > 11;
      },

      tweetURL: function(pol) {
        var tweetText;

        if (pol.yesOnCRA) {
          tweetText = '.@' + pol.twitter + ', I will only be voting for folks (like you) who are voting for the CRA to save #NetNeutrality. Thanks!\n\n(Friends: text "WIN" to 384-387 to make this same pledge to your reps. VoteForNetNeutrality.com will text you how they voted, right before the election.)';
        }
        else {
          tweetText = '.@' + pol.twitter + ' just FYI, I will not be voting for anyone who doesn’t vote for the CRA to save #NetNeutrality.\n\n(Friends: text "WIN" to 384-387 to make this same pledge to your reps! VoteForNetNeutrality.com will text you how they voted, right before the election!)'
        }

        return 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(tweetText);
      },

      openTweetURL: function(pol) {
        var url = this.tweetURL(pol);
        window.open(url, '_blank');
      }
    }
  });
});<commit_msg>updated tweet text in scoreboard page<commit_after>document.addEventListener("DOMContentLoaded", function() {
  var STATES = [
    "Alaska",
    "Alabama",
    "Arkansas",
    "Arizona",
    "California",
    "Colorado",
    "Connecticut",
    "District of Columbia",
    "Delaware",
    "Florida",
    "Georgia",
    "Hawaii",
    "Iowa",
    "Idaho",
    "Illinois",
    "Indiana",
    "Kansas",
    "Kentucky",
    "Louisiana",
    "Massachusetts",
    "Maryland",
    "Maine",
    "Michigan",
    "Minnesota",
    "Missouri",
    "Mississippi",
    "Montana",
    "North Carolina",
    "North Dakota",
    "Nebraska",
    "New Hampshire",
    "New Jersey",
    "New Mexico",
    "Nevada",
    "New York",
    "Ohio",
    "Oklahoma",
    "Oregon",
    "Pennsylvania",
    "Rhode Island",
    "South Carolina",
    "South Dakota",
    "Tennessee",
    "Texas",
    "Utah",
    "Virginia",
    "Vermont",
    "Washington",
    "Wisconsin",
    "West Virginia",
    "Wyoming"
  ];

  var app = new Vue({
    el: '#political-scoreboard',

    data: {
      states: STATES,
      selectedState: null,
      politicians: [],
      isLoaded: false
    },

    computed: {
      // ORDER BY yesOnCRA ASC, partyCode ASC, name ASC
      sortedPoliticians: function() {
        return this.politicians.sort(function(a, b){
          if (a.yesOnCRA === b.yesOnCRA) {
            if (a.partyCode === b.partyCode) {
              if (a.name < b.name) {
                return -1;
              }
              else if (a.name > b.name) {
                return 1;
              }
              else {
                return 0;
              }
            }
            else if (a.partyCode < b.partyCode) {
              return -1;
            }
            else {
              return 1;
            }
          }
          else if (a.yesOnCRA) {
            return 1;
          }
          else {
            return -1;
          }
        });
      },

      senators: function() {
        return this.sortedPoliticians.filter(function(p){
          return p.organization === 'Senate';
        });
      },

      representatives: function() {
        return this.sortedPoliticians.filter(function(p){
          return p.organization === 'House';
        });
      },

      senatorsInState: function() {
        var self = this;
        return this.senators.filter(function(p){
          return p.state === self.selectedState;
        });
      },

      congressInState: function() {
        var self = this;
        return this.politicians.filter(function(p){
          return p.state === self.selectedState;
        });
      },

      teamInternet: function() {
        return this.politicians.filter(function(p){
          return p.team === 'team-internet';
        });
      },

      undecided: function() {
        return this.politicians.filter(function(p){
          return p.team === 'undecided';
        });
      },

      teamCable: function() {
        return this.politicians.filter(function(p){
          return p.team === 'team-cable';
        });
      },

      // this function needs to change once we add house members because it counts all.
      senateCRACount: function () {
        return this.politicians.filter(function(p){
          return p.yesOnCRA
        }).length
      }
    },

    created: function() {
      this.geocodeSelectedState();
      this.fetchPoliticians();
    },

    methods: {
      geocodeSelectedState: function() {
        var self = this;
        this.$http.get('https://fftf-geocoder.herokuapp.com').then(function(response){
          if (response.ok) {
            var geo = response.body;

            if (
              geo.country.iso_code === 'US' &&
              geo.subdivisions &&
              geo.subdivisions[0] &&
              geo.subdivisions[0].names &&
              geo.subdivisions[0].names.en
            ) {
              self.selectedState = geo.subdivisions[0].names.en;
            }
          }
        });
      },

      fetchPoliticians: function() {
        var self = this;
        this.$http.get('https://data.battleforthenet.com/politicians.json').then(function(response){
          if (response.ok) {
            self.politicians = response.body;
            self.isLoaded = true;
          }
        });
      }
    }
  });

  Vue.component('politician-card', {
    template: '#politician-card-template',
    props: [ 'politician' ],
    methods: {
      imageURL: function(pol, suffix='_x1') {
        return 'https://www.fightforthefuture.org/congress-images/' +  pol.biocode + suffix + '.jpg';
      },

      isLong: function(name) {
        return name.indexOf(' ') === -1 && name.length > 11;
      },

      tweetURL: function(pol) {
        var tweetText;

        if (pol.yesOnCRA) {
          tweetText = 'I am delighted that @' + pol.twitter + ' will be voting for the CRA to overrule the FCC and save our #NetNeutrality rules. Find out where your representatives stand and ask them to do the same! https://battleforthenet.com'
        }
        else {
          tweetText = '@' + pol.twitter + ', why haven\'t you promised to vote for the CRA to overrule the FCC and save our #NetNeutrality rules? This issue matters to me! (Friends: find out where your representatives stand and contact them at https://battleforthenet.com)'
        }

        return 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(tweetText);
      },

      openTweetURL: function(pol) {
        var url = this.tweetURL(pol);
        window.open(url, '_blank');
      }
    }
  });
});<|endoftext|>


<commit_before>(function () {
    'use strict';
    var path = require('path'),
        fs = require('fs'),
        Q = require('q'),
        csv = require("fast-csv"),
        util = require('../util/index');

    var exports = module.exports = {};

    exports.localData = {};

    exports.load = function () {
        var deferred = Q.defer();
        setTimeout(function () {
            csv.fromPath(path.join(__dirname, 'data-sm.csv'))
                .on("data", function (data) {
                    exports.localData[data[0]] = data;
                })
                .on("error", function (data) {
                    deferred.reject();
                })
                .on("end", function () {
                    deferred.resolve(exports);
                });
        }, 0);
        return deferred.promise;
    };

    exports.getLatLongForCity = function (city) {
        city = util.strings.nullSafeLowerCase(city);
        if (exports.localData && exports.localData[city]) {
            return exports.localData[city];
        }
        return null;
    };

}());<commit_msg>removed util and replaced it with strings<commit_after>(function () {
    'use strict';
    var path = require('path'),
        fs = require('fs'),
        Q = require('q'),
        csv = require("fast-csv"),
        strings = require('../util/strings');

    var exports = module.exports = {};

    exports.localData = {};

    exports.load = function () {
        var deferred = Q.defer();
        setTimeout(function () {
            csv.fromPath(path.join(__dirname, 'data-sm.csv'))
                .on("data", function (data) {
                    exports.localData[data[0]] = data;
                })
                .on("error", function (data) {
                    deferred.reject();
                })
                .on("end", function () {
                    deferred.resolve(exports);
                });
        }, 0);
        return deferred.promise;
    };

    exports.getLatLongForCity = function (city) {
        city = strings.nullSafeLowerCase(city);
        if (exports.localData && exports.localData[city]) {
            return exports.localData[city];
        }
        return null;
    };

}());<|endoftext|>


<commit_before>import request from 'superagent'

const url = 'http://localhost:3000'
const projV1 = '/v1/projects'
const blogV1 = '/v1/blogs'

export const receiveProjects = (projects) => {
  return {
    type: 'RECEIVE_PROJECTS',
    projects: projects.map(project => project.data)
  }
}

export function getAllProjects (projects) {
  return (dispatch) => {
    request
      .get(`${url}${projV1}`)
      .end((err, res) => {
        if (err) {
          res.send('Whoops! There was a problem!')
        }
        dispatch(receiveProjects(projects))
      })
  }
}

export const receiveBlogs = (blogs) => {
  return {
    type: 'RECEIVE_BLOGS',
    blogs
  }
}

export const getAllBlogs = () => {
  return (dispatch) => {
    request
      .get(`${url}${blogV1}`)
      .end((err, res) => {
        if (err) {
          res.send('Whoops! There was a problem!')
        }
          dispatch(receiveBlogs(res.body.data))
      })
  }
}
<commit_msg>updated actions<commit_after>import request from 'superagent'

const url = 'http://localhost:3000'
const projV1 = '/v1/projects'
const blogV1 = '/v1/blogs'

export const getAllBlogs = () => {
  return (dispatch) => {
    request
      .get(`${url}${blogV1}`)
      .end((err, res) => {
        if (err) {
          res.send('Whoops! There was a problem!')
        }
        dispatch(receiveBlogs(res.body.data))
      })
  }
}

export const receiveBlogs = (blogs) => {
  return {
    type: 'RECEIVE_BLOGS',
    blogs: blogs
  }
}

export const receiveProjects = (projects) => {
  return {
    type: 'RECEIVE_PROJECTS',
    projects: projects.map(project => project.data)
  }
}

export const getAllProjects = (projects) => {
  return (dispatch) => {
    request
      .get(`${url}${projV1}`)
      .end((err, res) => {
        if (err) {
          res.send('Whoops! There was a problem!')
        }
        dispatch(receiveProjects(projects))
      })
  }
}
<|endoftext|>