view Platforms/WebAssembly/wasm-viewport.js @ 223:d30a10d574ec am

refactoring continued - not working
author am@osimis.io
date Thu, 14 Jun 2018 10:57:02 +0200
parents
children
line wrap: on
line source

// http://stackoverflow.com/a/28900478/881731

function WebAssemblyViewport(module, canvasId) {
    this.module = module;
    
    // Obtain a reference to the canvas element using its id
    this.htmlCanvas = document.getElementById(canvasId);
  
    // Obtain a graphics context on the canvas element for drawing.
    this.context = htmlCanvas.getContext('2d');
  
    // ImageData structure that can be used to update the content of the canvas
    this.imageData = null;
  
    // Temporary buffer in the WebAssembly heap that is used to render the pixels
    this.renderingBuffer = null;
  
    // Get access to the WebAssembly functions
    this.ViewportSetSize = this.module.cwrap('ViewportSetSize', null, [ 'number', 'number' ]);
    this.ViewportRender = this.module.cwrap('ViewportRender', 'number', [ 'number', 'number', 'number' ]);
    this.ViewportMouseDown = this.module.cwrap('ViewportMouseDown', null, [ 'number', 'number', 'number', 'number' ]);
    this.ViewportMouseMove = this.module.cwrap('ViewportMouseMove', null, [ 'number', 'number' ]);
    this.ViewportMouseUp = this.module.cwrap('ViewportMouseUp', null, [ ]);
    this.ViewportMouseEnter = this.module.cwrap('ViewportMouseEnter', null, []);
    this.ViewportMouseLeave = this.module.cwrap('ViewportMouseLeave', null, []);
    this.ViewportMouseWheel = this.module.cwrap('ViewportMouseWheel', null, [ 'number', 'number', 'number', 'number' ]);
    this.ViewportKeyPressed = this.module.cwrap('ViewportKeyPressed', null, [ 'string', 'number', 'number' ]);
  
    this.Redraw = function() {
      if (this.imageData === null ||
          this.renderingBuffer === null ||
          ViewportRender(this.imageData.width,
                         this.imageData.height,
                         this.renderingBuffer) == 0) {
        console.log('The rendering has failed');
      } else {
        // Create an accessor to the rendering buffer (i.e. create a
        // "window" above the heap of the WASM module), then copy it to
        // the ImageData object
        this.imageData.data.set(new Uint8ClampedArray(
          this.module.buffer,
          this.renderingBuffer,
          this.imageData.width * this.imageData.height * 4));
        
        this.context.putImageData(imageData, 0, 0);
      }
    }
  
    this.Resize = function() {
      if (this.imageData != null &&
          (this.imageData.width != this.window.innerWidth ||
           this.imageData.height != this.window.innerHeight)) {
        this.imageData = null;
      }
      
      this.htmlCanvas.width = window.innerWidth;
      this.htmlCanvas.height = window.innerHeight;
  
      if (this.imageData === null) {
        this.imageData = context.getImageData(0, 0, this.htmlCanvas.width, this.htmlCanvas.height);
        ViewportSetSize(this.htmlCanvas.width, this.htmlCanvas.height);
  
        if (this.renderingBuffer != null) {
          this.module._free(this.renderingBuffer);
        }
        
        renderingBuffer = this.module._malloc(this.imageData.width * this.imageData.height * 4);
      }
      
      this.Redraw();
    }
  
    // Force the rendering of the viewport for the first time
    this.Resize();
  
    // Register an event listener to call the Resize() function 
    // each time the window is resized.
    window.addEventListener('resize', this.Resize, false);
  
    var that = this;
  
    this.htmlCanvas.addEventListener('contextmenu', function(event) {
      // Prevent right click on the canvas
      event.preventDefault();
    }, false);
    
    this.htmlCanvas.addEventListener('mouseleave', function(event) {
      that.ViewportMouseLeave();
    });
    
    this.htmlCanvas.addEventListener('mouseenter', function(event) {
      that.ViewportMouseEnter();
    });
  
    this.htmlCanvas.addEventListener('mousedown', function(event) {
      var x = event.pageX - this.offsetLeft;
      var y = event.pageY - this.offsetTop;
      that.ViewportMouseDown(event.button, x, y, 0 /* TODO */);    
    });
  
    this.htmlCanvas.addEventListener('mousemove', function(event) {
      var x = event.pageX - this.offsetLeft;
      var y = event.pageY - this.offsetTop;
      that.ViewportMouseMove(x, y);
    });
  
    this.htmlCanvas.addEventListener('mouseup', function(event) {
      that.ViewportMouseUp();
    });
  
    window.addEventListener('keydown', function(event) {
      that.ViewportKeyPressed(event.key, event.shiftKey, event.ctrlKey, event.altKey);
    });
  
    this.htmlCanvas.addEventListener('wheel', function(event) {
      var x = event.pageX - this.offsetLeft;
      var y = event.pageY - this.offsetTop;
      that.ViewportMouseWheel(event.deltaY, x, y, event.ctrlKey);
      event.preventDefault();
    });
  
  
    // Touch events
    this.touchTranslation = false;
    this.touchZoom = false;
  
    this.ResetTouch = function() {
      if (this.touchTranslation ||
          this.touchZoom) {
        this.ViewportMouseUp();
      }
  
      this.touchTranslation = false;
      this.touchZoom = false;
    }
  
    this.GetTouchTranslation = function(event) {
      var touch = event.targetTouches[0];
      return [
        touch.pageX,
        touch.pageY
      ];
    }
    
    this.GetTouchZoom = function(event) {
      var touch1 = event.targetTouches[0];
      var touch2 = event.targetTouches[1];
      var dx = (touch1.pageX - touch2.pageX);
      var dy = (touch1.pageY - touch2.pageY);
      var d = Math.sqrt(dx * dx + dy * dy);
      return [
        (touch1.pageX + touch2.pageX) / 2.0,
        (touch1.pageY + touch2.pageY) / 2.0,
        d
      ];
    }
    
    this.htmlCanvas.addEventListener('touchstart', function(event) {
      ResetTouch();
    });
  
    this.htmlCanvas.addEventListener('touchend', function(event) {
      ResetTouch();
    });
    
    this.htmlCanvas.addEventListener('touchmove', function(event) {
      if (that.touchTranslation.length == 2) {
        var t = GetTouchTranslation(event);
        that.ViewportMouseMove(t[0], t[1]);
      }
      else if (that.touchZoom.length == 3) {
        var z0 = that.touchZoom;
        var z1 = GetTouchZoom(event);
        that.ViewportMouseMove(z0[0], z0[1] - z0[2] + z1[2]);
      }
      else {
        // Realize the gesture event
        if (event.targetTouches.length == 1) {
          // Exactly one finger inside the canvas => Setup a translation
          that.touchTranslation = GetTouchTranslation(event);
          that.ViewportMouseDown(1 /* middle button */,
                                 that.touchTranslation[0],
                                 that.touchTranslation[1], 0);
        } else if (event.targetTouches.length == 2) {
          // Exactly 2 fingers inside the canvas => Setup a pinch/zoom
          that.touchZoom = GetTouchZoom(event);
          var z0 = that.touchZoom;
          that.ViewportMouseDown(2 /* right button */,
                                 z0[0],
                                 z0[1], 0);
        }        
      }
    });
    
    return this;
  }