text: /** 
   * Class creates listeners for a range of user events on the canvas.
   * This class is responsible for setting up and implimenting listeners for different sets of actions performed
   * on the canvas area. Including zooming, rotating and moving around the scene.
   * @name CanvasController
   * @class CanvasController
   * @constructor
   */
  define(function() {
  
      var windowHalfX = window.innerWidth / 2;
      var windowHalfY = window.innerHeight / 2;
      var renderer;
      var camera;
      var targetRotationY = 0;
      var targetRotationOnMouseDownY = 0;
      var targetRotationX = 0;
      var targetRotationOnMouseDownX = 0;
      var mouseX = 0;
      var mouseXOnMouseDown = 0;
      var mouseY = 0;
      var mouseYOnMouseDown = 0;
      var scale = 1;
      var getLatestMoveX = 0;
      var getLatestMoveZ = 0;
  
      /**
       * Event that calculates the rotation and movement performed by the user starting from the mouse down to 
       * mouse up events. Sets global variables holding these values for use in the get methods used by the 
       * {@link Main} class.
       * @name CanvasController#onDocumentMouseDown
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onDocumentMouseDown(event) {
          event.preventDefault();
          renderer.domElement.addEventListener('mousemove', onDocumentMouseMove, false);
          renderer.domElement.addEventListener('mousemove', onDocumentMouseMove, false);
          renderer.domElement.addEventListener('mouseup', onDocumentMouseUp, false);
          renderer.domElement.addEventListener('mouseout', onDocumentMouseOut, false);
          mouseXOnMouseDown = event.clientX - windowHalfX;
          mouseYOnMouseDown = event.clientY - windowHalfY;
          targetRotationOnMouseDownX = targetRotationX;
          targetRotationOnMouseDownY = targetRotationY;
      }
  
      /**
       * Multiplies the rotating by 0.02 each time the mouse is moved whilst held down on the canvas.
       * @name CanvasController#onDocumentMouseMove
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onDocumentMouseMove(event) {
          mouseX = event.clientX - windowHalfX;
          mouseY = event.clientY - windowHalfY;
          targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDown) * 0.02;
          targetRotationY = targetRotationOnMouseDownY + (mouseY - mouseYOnMouseDown) * 0.02;
      }
  
      /**
       * Removes the listeners for mouse events once a user releases the mouse click button on the canvas.
       * @name CanvasController#onDocumentMouseUp
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onDocumentMouseUp(event) {
          renderer.domElement.removeEventListener('mousemove', onDocumentMouseMove, false);
          renderer.domElement.removeEventListener('mouseup', onDocumentMouseUp, false);
          renderer.domElement.removeEventListener('mouseout', onDocumentMouseOut, false);
      }
  
      /**
       * Removes the listeners for mouse events once a user moves the mouse out of the canvas.
       * @name CanvasController#onDocumentMouseOut
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onDocumentMouseOut(event) {
          renderer.domElement.removeEventListener('mousemove', onDocumentMouseMove, false);
          renderer.domElement.removeEventListener('mouseup', onDocumentMouseUp, false);
          renderer.domElement.removeEventListener('mouseout', onDocumentMouseOut, false);
      }
  
      /**
       * Adds the listener for different mouse actions once a user clicks onto the canvas, holding the mouse down/
       * @name CanvasController#onDocumentTouchStart
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onDocumentTouchStart(event) {
  
          if (event.touches.length == 1) {
              event.preventDefault();
              mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
              targetRotationOnMouseDownX = targetRotationX;
              mouseYOnMouseDown = event.touches[0].pageY - windowHalfY;
              targetRotationOnMouseDownY = targetRotationY;
          }
      }
  
      /**
       * Alternative event for calculating rotation, for touch devices. Will work on phones and rotate scene 
       * when user drags across the screen.
       * @name CanvasController#onDocumentTouchMove
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onDocumentTouchMove(event) {
  
          if (event.touches.length == 1) {
              event.preventDefault();
              mouseX = event.touches[0].pageX - windowHalfX;
              targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDown) * 0.05;
              mouseY = event.touches[0].pageX - windowHalfX;
              targetRotationY = targetRotationOnMouseDownY + (mouseY - mouseYOnMouseDown) * 0.05;
          }
      }
  
      /**
       * Resizes the canvas in relation to the window size. Resizes all the objects too, and changes the 
       * camera perspective to view from the correct range.
       * @name CanvasController#onWindowResize
       * @function
       *
       */
      function onWindowResize() {
          windowHalfX = window.innerWidth;
          windowHalfY = window.innerHeight;
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();
          renderer.setSize(window.innerWidth, window.innerHeight);
      }
  
      /**
       * Updates the camera zoom parameter based on the amount scrolled. Has a maximum and minimum value of scroll.
       * @name CanvasController#onMouseScroll
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onMouseScroll(event) {
          var event = window.event || e; // old IE support
          var d = ((typeof event.wheelDelta != "undefined") ? (-event.wheelDelta) : event.detail);
          d = 100 * ((d > 0) ? 1 : -1);
          var cPos = camera.position;
          if (isNaN(cPos.x) || isNaN(cPos.y) || isNaN(cPos.y)) 
              return;
          if (cPos.x > 1 || cPos.x < 0) {
              return;
          }
          mb = d > 0 ? 1.1 : 0.9;
          cPos.x = cPos.x * mb;
          cPos.y = cPos.y * mb;
          cPos.z = cPos.z * mb;
          camera.updateProjectionMatrix();
      }
  
      /**
       * A listener to run each time the up, down, left and right arrows are pressed. Sets the global variables
       * which are acesses in get methods to navigate the camera about the canvas.
       * @name CanvasController#onKeyDown
       * @function
       *
       * @param {Event} event  Event triggured
       */
      function onKeyDown(event) {
          var step = 5;
          switch (event.keyCode.toString()) {
              case "38":
                  // up
                  getLatestMoveZ += step;
                  break;
              case "40":
                  // down
                  getLatestMoveZ -= step;
                  break;
              case "37":
                  // left
                  getLatestMoveX += step;
                  break;
              case "39":
                  // right
                  getLatestMoveX -= step;
                  break;
          }
      }
  
      return {
  
          /**
           * Initial function which is called on startup for creating event listeners in the canvas area. 
           * Including scroll, mouse drag, touch drag and keyboard events. 
           * @name CanvasController#init
           * @function
           *
           * @param {Renderer} r  Renderer object to have listeners added to
           * @param {Camera} c  Camera object to have zoom and aspect ratio modified by events
           */
          init: function(r, c) {
              renderer = r;
              camera = c;
              renderer.domElement.addEventListener('mousedown', onDocumentMouseDown, false);
              renderer.domElement.addEventListener('touchstart', onDocumentTouchStart, false);
              renderer.domElement.addEventListener('touchmove', onDocumentTouchMove, false);
              window.addEventListener('resize', onWindowResize, false);
              renderer.domElement.addEventListener("mousewheel", onMouseScroll, false);
              renderer.domElement.addEventListener("DOMMouseScroll", onMouseScroll, false);
              window.addEventListener("keydown", onKeyDown, false);
          },
  
          /**
           * Returns the last accumulated rotatoion on X axis
           * @name CanvasController#getLatestTargetRotationX
           * @function
           *
           * @returns {Integer} targetRotationX  Amount of rotation along x axis in degrees.
           */
          getLatestTargetRotationX: function() {
              return targetRotationX;
          },
  
          /**
           * Returns the last accumulated rotation on Y axis
           * @name CanvasController#getLatestTargetRotationY
           * @function
           *
           * @returns {Integer} targetRotationY  Amount of rotation along y axis in degrees.
           */
          getLatestTargetRotationY: function() {
              return targetRotationY;
          },
  
          /**
           * Returns the last accumulated movement along X axis
           * @name CanvasController#getLatestMoveX
           * @function
           *
           * @returns {Integer} getLatestMoveX  Amount of movement along x axis in pixels.
           */
          getLatestMoveX: function() {
              return getLatestMoveX;
          },
  
          /**
           * Returns the last accumulated movement along Z axis
           * @name CanvasController#getLatestMoveZ
           * @function
           *
           * @returns {Integer} getLatestMoveZ  Amount of movement along z axis in pixels.
           */
          getLatestMoveZ: function() {
              return getLatestMoveZ;
          }
      }
  });
  