'use strict' module.exports = createGLPlot2D var createPick = require('gl-select-static') var createGrid = require('./lib/grid') var createText = require('./lib/text') var createLine = require('./lib/line') var createBox = require('./lib/box') function GLPlot2D(gl, pickBuffer) { this.gl = gl this.pickBuffer = pickBuffer this.screenBox = [0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight] this.viewBox = [0, 0, 0, 0] this.dataBox = [-10, -10, 10, 10] this.gridLineEnable = [true,true] this.gridLineWidth = [1,1] this.gridLineColor = [[0,0,0,1], [0,0,0,1]] this.pixelRatio = 1 this.tickMarkLength = [0,0,0,0] this.tickMarkWidth = [0,0,0,0] this.tickMarkColor = [[0,0,0,1], [0,0,0,1], [0,0,0,1], [0,0,0,1]] this.tickPad = [15,15,15,15] this.tickAngle = [0,0,0,0] this.tickEnable = [true,true,true,true] this.tickColor = [[0,0,0,1], [0,0,0,1], [0,0,0,1], [0,0,0,1]] this.labelPad = [15,15,15,15] this.labelAngle = [0,Math.PI/2,0,3.0*Math.PI/2] this.labelEnable = [true,true,true,true] this.labelColor = [[0,0,0,1], [0,0,0,1], [0,0,0,1], [0,0,0,1]] this.titleCenter = [0,0] this.titleEnable = true this.titleAngle = 0 this.titleColor = [0,0,0,1] this.borderColor = [0,0,0,0] this.backgroundColor = [0,0,0,0] this.zeroLineEnable = [true, true] this.zeroLineWidth = [4, 4] this.zeroLineColor = [[0, 0, 0, 1],[0, 0, 0, 1]] this.borderLineEnable = [true,true,true,true] this.borderLineWidth = [2,2,2,2] this.borderLineColor = [[0,0,0,1], [0,0,0,1], [0,0,0,1], [0,0,0,1]] //Drawing parameters this.grid = null this.text = null this.line = null this.box = null this.objects = [] this.overlays = [] this._tickBounds = [Infinity, Infinity, -Infinity, -Infinity] this.static = false this.dirty = false this.pickDirty = false this.pickDelay = 120 this.pickRadius = 10 this._pickTimeout = null this._drawPick = this.drawPick.bind(this) this._depthCounter = 0 } var proto = GLPlot2D.prototype proto.setDirty = function() { this.dirty = this.pickDirty = true } proto.setOverlayDirty = function() { this.dirty = true } proto.nextDepthValue = function() { return (this._depthCounter++) / 65536.0 } function lerp(a, b, t) { var s = 0.5 * (t + 1.0) return Math.floor((1.0-s)*a + s*b)|0 } proto.draw = (function() { var TICK_MARK_BOX = [0,0,0,0] return function() { var gl = this.gl var screenBox = this.screenBox var viewPixels = this.viewBox var dataBox = this.dataBox var pixelRatio = this.pixelRatio var grid = this.grid var line = this.line var text = this.text var objects = this.objects this._depthCounter = 0 if(this.pickDirty) { if(this._pickTimeout) { clearTimeout(this._pickTimeout) } this.pickDirty = false this._pickTimeout = setTimeout(this._drawPick, this.pickDelay) } if(!this.dirty) { return } this.dirty = false gl.bindFramebuffer(gl.FRAMEBUFFER, null) //Turn on scissor gl.enable(gl.SCISSOR_TEST) //Turn off depth buffer gl.disable(gl.DEPTH_TEST) gl.depthFunc(gl.LESS) gl.depthMask(false) //Configure premultiplied alpha blending gl.enable(gl.BLEND) gl.blendEquation(gl.FUNC_ADD, gl.FUNC_ADD); gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); //Draw border if (this.borderColor) { gl.scissor( screenBox[0], screenBox[1], screenBox[2]-screenBox[0], screenBox[3]-screenBox[1]) var borderColor = this.borderColor gl.clearColor( borderColor[0]*borderColor[3], borderColor[1]*borderColor[3], borderColor[2]*borderColor[3], borderColor[3]) gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) } //Draw center pane gl.scissor( viewPixels[0], viewPixels[1], viewPixels[2]-viewPixels[0], viewPixels[3]-viewPixels[1]) gl.viewport( viewPixels[0], viewPixels[1], viewPixels[2]-viewPixels[0], viewPixels[3]-viewPixels[1]) var backgroundColor = this.backgroundColor gl.clearColor( backgroundColor[0]*backgroundColor[3], backgroundColor[1]*backgroundColor[3], backgroundColor[2]*backgroundColor[3], backgroundColor[3]) gl.clear(gl.COLOR_BUFFER_BIT) //Draw grid grid.draw() //Draw zero lines separately var zeroLineEnable = this.zeroLineEnable var zeroLineColor = this.zeroLineColor var zeroLineWidth = this.zeroLineWidth if(zeroLineEnable[0] || zeroLineEnable[1]) { line.bind() for(var i=0; i<2; ++i) { if(!zeroLineEnable[i] || !(dataBox[i] <= 0 && dataBox[i+2] >= 0)) { continue } var zeroIntercept = screenBox[i] - dataBox[i] * (screenBox[i+2] - screenBox[i]) / (dataBox[i+2] - dataBox[i]) if(i === 0) { line.drawLine( zeroIntercept, screenBox[1], zeroIntercept, screenBox[3], zeroLineWidth[i], zeroLineColor[i]) } else { line.drawLine( screenBox[0], zeroIntercept, screenBox[2], zeroIntercept, zeroLineWidth[i], zeroLineColor[i]) } } } //Draw traces for(var i=0; i=0; --i) { this.objects[i].dispose() } this.objects.length = 0 for(var i=this.overlays.length-1; i>=0; --i) { this.overlays[i].dispose() } this.overlays.length = 0 this.gl = null } proto.addObject = function(object) { if(this.objects.indexOf(object) < 0) { this.objects.push(object) this.setDirty() } } proto.removeObject = function(object) { var objects = this.objects for(var i=0; i