diff --git a/app/web/config/worker-loader.d.ts b/app/web/config/worker-loader.d.ts new file mode 100644 index 0000000..cf7fd6b --- /dev/null +++ b/app/web/config/worker-loader.d.ts @@ -0,0 +1,10 @@ +declare module "worker-loader!*" { + // You need to change `Worker`, if you specified a different value for the `workerType` option + class WebpackWorker extends Worker { + constructor(); + } + + // Uncomment this if you set the `esModule` option to `false` + // export = WebpackWorker; + export default WebpackWorker; +} diff --git a/app/web/package.json b/app/web/package.json index 76b4728..77285a4 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -45,7 +45,8 @@ "react-tabs": "^3.2.2", "rich-markdown-editor": "^11.0.2", "styled-components": "^5.2.0", - "three": "^0.130.1" + "three": "^0.130.1", + "worker-loader": "^3.0.8" }, "devDependencies": { "@types/lodash": "^4.14.170", @@ -56,4 +57,4 @@ "postcss-loader": "^6.1.1", "tailwindcss": "^2.2.7" } -} \ No newline at end of file +} diff --git a/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx b/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx index 4f8c2f2..5562de7 100644 --- a/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx +++ b/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx @@ -16,6 +16,7 @@ import { Mesh, } from 'three' import { jsCadToCadhubParams } from './jscadParams' +import TheWorker from 'worker-loader!./jscadWorker' const materials = { mesh: { @@ -134,19 +135,7 @@ export const render: DefaultKernelExport['render'] = async ({ }: RenderArgs) => { if (!scriptWorker) { const baseURI = document.baseURI.toString() - const scriptUrl = '/demo-worker.js' - const script = `let baseURI = '${baseURI}' - importScripts(new URL('${scriptUrl}',baseURI)) - let worker = jscadWorker({ - baseURI: baseURI, - scope:'worker', - convertToSolids: 'buffers', - callback:(params)=>self.postMessage(params), - }) - self.addEventListener('message', (e)=>worker.postMessage(e.data)) - ` - const blob = new Blob([script], { type: 'text/javascript' }) - scriptWorker = new Worker(window.URL.createObjectURL(blob)) + scriptWorker = new TheWorker() let parameterDefinitions = [] scriptWorker.addEventListener('message', ({ data }) => { if (data.action == 'parameterDefinitions') { diff --git a/app/web/public/demo-worker.js b/app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts similarity index 78% rename from app/web/public/demo-worker.js rename to app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts index f49e365..283f28a 100644 --- a/app/web/public/demo-worker.js +++ b/app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts @@ -1,25 +1,3 @@ -(function(f) { - if (typeof exports === "object" && typeof module !== "undefined") { - module.exports = f() - } else if (typeof define === "function" && define.amd) { - define([], f) - } else { - var g; - if (typeof window !== "undefined") { - g = window - } else if (typeof global !== "undefined") { - g = global - } else if (typeof self !== "undefined") { - g = self - } else { - g = this - } - g.jscadWorker = f() - } -})(function() { -// multi purpose module - - const setPoints = (points, p, i)=>{ points[i++] = p[0] @@ -176,56 +154,6 @@ require.cache = {} require.alias = {} -const initCanvas = (canvas, callback)=>{ - - // convert HTML events (mouse movement) to viewer changes - let lastX = 0 - let lastY = 0 - - let pointerDown = false - - const moveHandler = (ev) => { - if(!pointerDown) return - const cmd = { - worker: 'render', - dx: lastX - ev.pageX, - dy: ev.pageY - lastY - } - - const shiftKey = (ev.shiftKey === true) || (ev.touches && ev.touches.length > 2) - cmd.action = shiftKey ? 'pan':'rotate' - callback(cmd) - - lastX = ev.pageX - lastY = ev.pageY - - ev.preventDefault() - } - const downHandler = (ev) => { - pointerDown = true - lastX = ev.pageX - lastY = ev.pageY - canvas.setPointerCapture(ev.pointerId) - ev.preventDefault() - } - - const upHandler = (ev) => { - pointerDown = false - canvas.releasePointerCapture(ev.pointerId) - ev.preventDefault() - } - - const wheelHandler = (ev) => { - callback({action:'zoom', dy:ev.deltaY, worker: 'render'}) - ev.preventDefault() - } - - canvas.onpointermove = moveHandler - canvas.onpointerdown = downHandler - canvas.onpointerup = upHandler - canvas.onwheel = wheelHandler -} - const cmdHandler = (handlers)=>(cmd)=>{ const fn = handlers[cmd.action] if (!fn) throw new Error('no handler for type: ' + cmd.action) @@ -239,7 +167,7 @@ function parseParams(script){ let lines = script.split('\n').map(l=>l.trim()) lines = lines.map((l,i)=>{ - return {code:l, line:i+1, group: l[0] == '/' && !lines[i+1]} + return {code:l, line:i+1, group: l[0] == '/' && !lines[i+1]} }).filter(l=>l.code) let i = 0, line, next, lineNum @@ -322,13 +250,13 @@ function parseComment(comment, line){ const ret = {} const idx = comment.indexOf('{') if(idx !== -1){ - try{ - ret.options = eval('('+comment.substring(idx)+')') - }catch(e){ - console.log('Error in line '+line); - console.log(comment); - throw e - } + try{ + ret.options = eval('('+comment.substring(idx)+')') + }catch(e){ + console.log('Error in line '+line); + console.log(comment); + throw e + } comment = comment.substring(0,idx).trim() } @@ -365,8 +293,8 @@ function parseDef(code, line){ try { ret.initial = eval(initial) } catch (e) { - console.log('Error in line '+line); - console.log(code); + console.log('Error in line '+line); + console.log(code); console.log('problem evaluating inital value:', initial) e = new EvalError(e.message, 'code', line); e.lineNumber = line @@ -380,9 +308,8 @@ function parseDef(code, line){ - const makeScriptWorker = ({callback, convertToSolids})=>{ - let workerBaseURI, onInit + let onInit, main, scriptStats, entities function runMain(params={}){ @@ -695,92 +622,41 @@ let perspectiveCamera } - - - - - - - - -return (params)=>{ - let { canvas, baseURI=(typeof document === 'undefined') ? '':document.location.toString(), scope='main', renderInWorker, render, callback=()=>{}, scriptUrl='demo-worker.js', alias, convertToSolids=false } = params +function start(params) { + let { + callback=()=>{}, + convertToSolids=false + } = params // by default 'render' messages go outside of this instance (result of modeling) - let sendToRender = callback - let scriptWorker, renderWorker - workerBaseURI = baseURI + let scriptWorker const sendCmd = (params, transfer)=>{ - if(params.worker === 'render') - sendToRender(params, transfer) - else if(params.worker === 'script') - scriptWorker.postMessage(params, transfer) + if(params.worker === 'script') scriptWorker.postMessage(params, transfer) else{ - // parameter definitions will arrive from scriptWorker callback(params, transfer) } } - const updateSize = function({width,height}){ - sendCmd({ action:'resize', worker:'render', width: canvas.offsetWidth, height: canvas.offsetHeight}) - } - renderInWorker = !!(canvas && renderInWorker && canvas.transferControlToOffscreen) - const makeRenderWorkerHere = (scope === 'main' && canvas && !renderInWorker) || (scope === 'worker' && render) - // worker is in current thread - if(makeRenderWorkerHere){ - renderWorker = makeRenderWorker({callback:sendCmd}) - sendToRender = (params, transfer)=>renderWorker.postMessage(params, transfer) - } - - if(scope === 'main'){ -// let extraScript = renderInWorker ? `,'https://unpkg.com/@jscad/regl-renderer'`:'' - let script =`let baseURI = '${baseURI}' -importScripts(new URL('${scriptUrl}',baseURI)) -let worker = jscadWorker({ - baseURI: baseURI, - convertToSolids: ${convertToSolids}, - scope:'worker', - callback:(params)=>self.postMessage(params), - render:${renderInWorker} -}) -self.addEventListener('message', (e)=>worker.postMessage(e.data)) -` - let blob = new Blob([script],{type: 'text/javascript'}) - scriptWorker = new Worker(window.URL.createObjectURL(blob)) - scriptWorker.addEventListener('message',(e)=>sendCmd(e.data)) - scriptWorker.postMessage({action:'init', baseURI, alias}) - if(renderInWorker) renderWorker = scriptWorker - - if(canvas){ - initCanvas(canvas, sendCmd) - window.addEventListener('resize',updateSize) - } - }else{ - scriptWorker = makeScriptWorker({callback:sendCmd, convertToSolids}) - callback({action:'workerInit',worker:'main'}) - } - - if(canvas){ - // redirect 'render' messages to renderWorker - sendToRender = (params, transfer)=>renderWorker.postMessage(params, transfer) - let width = canvas.width = canvas.clientWidth - let height = canvas.height = canvas.clientHeight - if(scope == 'main'){ - const offscreen = renderInWorker ? canvas.transferControlToOffscreen() : canvas - renderWorker.postMessage({action:'init', worker:'render', canvas:offscreen, width, height}, [offscreen]) - } - } + scriptWorker = makeScriptWorker({callback:sendCmd, convertToSolids}) + callback({action:'workerInit',worker:'main'}) return { - updateSize, updateParams:({params={}})=>sendCmd({ action:'updateParams', worker:'script', params}), runScript: ({script,url=''})=>sendCmd({ action:'runScript', worker:'script', script, url}), postMessage: sendCmd, } } +const init = start({ + convertToSolids: 'buffers', + callback:(params)=>self.postMessage(params), +}) -// multi purpose module -}); +self.onmessage = ({data}) => { + if (data.action === 'init') { + workerBaseURI = data.baseURI + } + init.postMessage(data, null) +}; diff --git a/app/yarn.lock b/app/yarn.lock index 3adfcb0..f75c025 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -19057,6 +19057,14 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" +worker-loader@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-3.0.8.tgz#5fc5cda4a3d3163d9c274a4e3a811ce8b60dbb37" + integrity sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + worker-rpc@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/worker-rpc/-/worker-rpc-0.1.1.tgz#cb565bd6d7071a8f16660686051e969ad32f54d5"