"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const puppeteer_1 = __importDefault(require("puppeteer")); const argparse_1 = require("argparse"); const path_1 = require("path"); const promises_1 = require("fs/promises"); const URL = 'https://mattmcw.github.io/plotter-vision/'; const DOWNLOADS = './downloads'; const WIDTH_DEFAULT = 1920; const HEIGHT_DEFAULT = 1080; let PROCESSING = false; let PROCESSING_MONITOR = false; let WAITING = false; async function delay(ms) { return new Promise((resolve, reject) => { return setTimeout(resolve, ms); }); } function compare(before, after) { let downloaded = null; for (let file of after) { if (before.indexOf(file) === -1) { console.log(`Downloaded ${(0, path_1.join)(DOWNLOADS, file)}`); downloaded = (0, path_1.resolve)((0, path_1.join)(DOWNLOADS, file)); break; } } return downloaded; } async function dir(path) { const files = await (0, promises_1.readdir)(path); return files.filter((el) => { return (0, path_1.extname)(el) === '.svg'; }); } async function clearDownloads() { const files = await dir(DOWNLOADS); for (let file of files) { await (0, promises_1.unlink)((0, path_1.resolve)((0, path_1.join)(DOWNLOADS, file))); } } function cli() { const parser = new argparse_1.ArgumentParser({ description: 'STL to SVG', usage: '%(prog)s [input] [output]' }); parser.add_argument('input', { type: 'str', help: 'Input STL to render' }); parser.add_argument('output', { type: 'str', help: 'Output SVG to write' }); parser.add_argument('--width', '-W', { type: 'int', default: WIDTH_DEFAULT, help: `Width of window to render STL (default: ${WIDTH_DEFAULT})` }); parser.add_argument('--height', '-H', { type: 'int', default: HEIGHT_DEFAULT, help: `Height of window to render STL (default: ${HEIGHT_DEFAULT})` }); parser.add_argument('--load-delay', '-l', { type: 'int', default: 0, help: 'Number of milliseconds to wait after loading (default: 0)' }); parser.add_argument('--save-delay', '-s', { type: 'int', default: 0, help: 'Number of milliseconds to wait before saving (default: 0)' }); parser.add_argument('--theta', '-t', { type: 'float', default: null, help: 'Theta of the camera' }); parser.add_argument('--psi', '-p', { type: 'float', default: null, help: 'Psi of the camera' }); parser.add_argument('--radius', '-r', { type: 'float', default: null, help: 'Radius of the camera' }); parser.add_argument('--center', '-c', { type: 'str', default: null, help: 'LookAt center' }); parser.add_argument('--no-display', '-n', { action: 'store_true', default: true, help: 'No display' }); return parser.parse_args(); } async function download(page, dest, save) { let before; let after; let downloaded = null; before = await dir(DOWNLOADS); //console.dir(before) await page.click('#fileDownload'); console.log(`Clicked download`); await delay(100); if (save > 0) { console.log(`Delaying for: ${save}ms`); await delay(save); } while (downloaded === null) { await delay(1); after = await dir(DOWNLOADS); downloaded = compare(before, after); } if (downloaded === null) { console.warn(`Cannot move download file to destination: ${dest}`); return; } await (0, promises_1.copyFile)(downloaded, dest); await (0, promises_1.unlink)(downloaded); console.dir(`${downloaded} => ${dest}`); } function startProcessing() { PROCESSING = true; PROCESSING_MONITOR = true; } async function waitForProcessing() { while (PROCESSING) { await delay(401); } return true; } async function main() { startProcessing(); const args = cli(); console.dir(args); const config = { headless: !args.no_display, args: [`--window-size=${args.width},${args.height}`] }; await clearDownloads(); const browser = await puppeteer_1.default.launch(config); const page = await browser.newPage(); let lookat = [0, 0, 0]; page.on('console', (message) => { const text = message.text(); const type = message.type().substr(0, 3).toUpperCase(); if (type === 'LOG' && text.trim() === 'hidden processing') { PROCESSING = true; PROCESSING_MONITOR = true; } else if (type === 'LOG' && text.indexOf('hidden processing ') !== -1 && text.indexOf(' segments ') !== -1) { PROCESSING_MONITOR = false; setTimeout(() => { if (!PROCESSING_MONITOR && PROCESSING) { PROCESSING = false; console.log('PROCESSING COMPLETE'); } }, 100); } if (!text.startsWith('filtered ')) { console.log(`${type} ${text}`); } }); const client = await page.target().createCDPSession(); await client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: DOWNLOADS, }); await page.setViewport({ width: args.width, height: args.height }); await page.goto(URL, { waitUntil: 'networkidle2' }); await delay(100); console.log(`Loading: ${args.input}`); startProcessing(); const [fileChooser] = await Promise.all([ page.waitForFileChooser(), page.click('#loadFileXml') ]); await fileChooser.accept([args.input]); startProcessing(); await waitForProcessing(); if (args.psi !== null || args.theta !== null) { console.log(`Adjusting the camera rotation`); startProcessing(); await page.evaluate(`cameraView(${args.theta === null ? 0 : args.theta}, ${args.psi === null ? 0 : args.psi});`); } if (args.radius !== null) { console.log(`Adjusting the camera distance`); startProcessing(); await page.evaluate(`camera_radius = ${args.radius}; reproject = true; vz = 0.00001;`); //vz = 0.00001; } if (args.center !== null) { lookat = args.center.split(',').map((el) => { return parseFloat(el); }); await page.evaluate(`camera.lookat.x = ${lookat[0]}; camera.lookat.y = ${lookat[1]}; camera.lookat.z = ${lookat[2]}; vz = 0.00001;`); } if (args.load_delay > 0) { console.log(`Delaying for: ${args.load_delay}ms`); await delay(args.load_delay); } await waitForProcessing(); await download(page, args.output, args.save_delay); await browser.close(); } main(); //# sourceMappingURL=index.js.map