'use strict'; var Lib = require('../../lib'); // make sure scene exists on subplot, return it module.exports = function sceneUpdate(gd, subplot) { var scene = subplot._scene; var resetOpts = { // number of traces in subplot, since scene:subplot -> 1:1 count: 0, // whether scene requires init hook in plot call (dirty plot call) dirty: true, // last used options lineOptions: [], fillOptions: [], markerOptions: [], markerSelectedOptions: [], markerUnselectedOptions: [], errorXOptions: [], errorYOptions: [], textOptions: [], textSelectedOptions: [], textUnselectedOptions: [], // selection batches selectBatch: [], unselectBatch: [] }; // regl- component stubs, initialized in dirty plot call var initOpts = { fill2d: false, scatter2d: false, error2d: false, line2d: false, glText: false, select2d: false }; if(!subplot._scene) { scene = subplot._scene = {}; scene.init = function init() { Lib.extendFlat(scene, initOpts, resetOpts); }; scene.init(); // apply new option to all regl components (used on drag) scene.update = function update(opt) { var opts = Lib.repeat(opt, scene.count); if(scene.fill2d) scene.fill2d.update(opts); if(scene.scatter2d) scene.scatter2d.update(opts); if(scene.line2d) scene.line2d.update(opts); if(scene.error2d) scene.error2d.update(opts.concat(opts)); if(scene.select2d) scene.select2d.update(opts); if(scene.glText) { for(var i = 0; i < scene.count; i++) { scene.glText[i].update(opt); } } }; // draw traces in proper order scene.draw = function draw() { var count = scene.count; var fill2d = scene.fill2d; var error2d = scene.error2d; var line2d = scene.line2d; var scatter2d = scene.scatter2d; var glText = scene.glText; var select2d = scene.select2d; var selectBatch = scene.selectBatch; var unselectBatch = scene.unselectBatch; for(var i = 0; i < count; i++) { if(fill2d && scene.fillOrder[i]) { fill2d.draw(scene.fillOrder[i]); } if(line2d && scene.lineOptions[i]) { line2d.draw(i); } if(error2d) { if(scene.errorXOptions[i]) error2d.draw(i); if(scene.errorYOptions[i]) error2d.draw(i + count); } if(scatter2d && scene.markerOptions[i]) { if(unselectBatch[i].length) { var arg = Lib.repeat([], scene.count); arg[i] = unselectBatch[i]; scatter2d.draw(arg); } else if(!selectBatch[i].length) { scatter2d.draw(i); } } if(glText[i] && scene.textOptions[i]) { glText[i].render(); } } if(select2d) { select2d.draw(selectBatch); } scene.dirty = false; }; // remove scene resources scene.destroy = function destroy() { if(scene.fill2d && scene.fill2d.destroy) scene.fill2d.destroy(); if(scene.scatter2d && scene.scatter2d.destroy) scene.scatter2d.destroy(); if(scene.error2d && scene.error2d.destroy) scene.error2d.destroy(); if(scene.line2d && scene.line2d.destroy) scene.line2d.destroy(); if(scene.select2d && scene.select2d.destroy) scene.select2d.destroy(); if(scene.glText) { scene.glText.forEach(function(text) { if(text.destroy) text.destroy(); }); } scene.lineOptions = null; scene.fillOptions = null; scene.markerOptions = null; scene.markerSelectedOptions = null; scene.markerUnselectedOptions = null; scene.errorXOptions = null; scene.errorYOptions = null; scene.textOptions = null; scene.textSelectedOptions = null; scene.textUnselectedOptions = null; scene.selectBatch = null; scene.unselectBatch = null; // we can't just delete _scene, because `destroy` is called in the // middle of supplyDefaults, before relinkPrivateKeys which will put it back. subplot._scene = null; }; } // in case if we have scene from the last calc - reset data if(!scene.dirty) { Lib.extendFlat(scene, resetOpts); } return scene; };