diff --git a/.vscode/settings.json b/.vscode/settings.json index aaa161b..78eaf8e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,10 @@ { "cSpell.words": [ "Cadhub", + "cadquery", + "curv", "Customizer", "Hutten", - "cadquery", "jscad", "openscad", "sendmail" diff --git a/app/api/src/docker/aws-emulator.js b/app/api/src/docker/aws-emulator.js index 239d8a0..6b99ce7 100644 --- a/app/api/src/docker/aws-emulator.js +++ b/app/api/src/docker/aws-emulator.js @@ -34,8 +34,12 @@ const makeRequest = (route, port) => [ app.post(...makeRequest('/openscad/preview', 5052)) app.post(...makeRequest('/openscad/stl', 5053)) + app.post(...makeRequest('/cadquery/stl', 5060)) +app.post(...makeRequest('/curv/preview', 5070)) +app.post(...makeRequest('/curv/stl', 5071)) + app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }) diff --git a/app/api/src/docker/curv/Dockerfile b/app/api/src/docker/curv/Dockerfile index ffda554..1dae1b0 100644 --- a/app/api/src/docker/curv/Dockerfile +++ b/app/api/src/docker/curv/Dockerfile @@ -2,17 +2,27 @@ FROM public.ecr.aws/lts/ubuntu:20.04_stable ARG DEBIAN_FRONTEND=noninteractive + RUN apt-get update --fix-missing -qq -RUN apt-get -y -qq install git software-properties-common dirmngr apt-transport-https lsb-release ca-certificates xvfb unzip maim clang cmake git-core libboost-all-dev libopenexr-dev libtbb-dev libglm-dev libpng-dev libeigen3-dev dbus-x11 libxcursor-dev libxinerama-dev libxrandr-dev libglu1-mesa-dev libgles2-mesa-dev libgl1-mesa-dev libxi-dev -RUN git clone https://github.com/curv3d/curv.git -RUN cd curv -RUN git submodule init && git submodule update -RUN mkdir build -RUN cd build -RUN sed -i 's/set(LEAN_BUILD 0)/set(LEAN_BUILD 1)/' ../CMakeLists.txt -RUN cmake .. -RUN make -RUN make install +RUN apt-get update --fix-missing && apt-get -y -qq install software-properties-common dirmngr apt-transport-https lsb-release ca-certificates xvfb + +RUN apt-get update -qq + +RUN apt-get -y -qq install git +RUN apt-get update --fix-missing && apt-get -y --fix-broken install python-pycurl python-apt +RUN apt-get -y -qq --fix-broken install software-properties-common + +RUN apt-get -y -qq install xvfb unzip maim clang cmake +RUN apt-get -y -qq install git-core libboost-all-dev +RUN apt-get -y -qq install libopenexr-dev libtbb-dev +RUN apt-get -y -qq install libglm-dev libpng-dev +RUN apt-get -y -qq install libeigen3-dev dbus-x11 +RUN apt-get -y -qq install libxcursor-dev libxinerama-dev +RUN apt-get -y -qq install libxrandr-dev libglu1-mesa-dev +RUN apt-get -y -qq install libgles2-mesa-dev libgl1-mesa-dev +RUN apt-get -y -qq install libxi-dev + +RUN git clone --recursive https://github.com/curv3d/curv; cd curv; make; make install # install node14, see comment at the top of node14source_setup.sh ADD src/docker/common/node14source_setup.sh /nodesource_setup.sh @@ -46,7 +56,7 @@ RUN echo "cadhub-concat-split" > /var/task/cadhub-concat-split # using built javascript from dist # run `yarn rw build` before bulding this image -COPY dist/docker/openscad/* /var/task/js/ +COPY dist/docker/curv/* /var/task/js/ COPY dist/docker/common/* /var/task/common/ COPY src/docker/common/entrypoint.sh /entrypoint.sh RUN ["chmod", "+x", "/entrypoint.sh"] diff --git a/app/api/src/docker/curv/runCurv.ts b/app/api/src/docker/curv/runCurv.ts index 70c7b08..767d529 100644 --- a/app/api/src/docker/curv/runCurv.ts +++ b/app/api/src/docker/curv/runCurv.ts @@ -1,21 +1,5 @@ import { writeFiles, runCommand } from '../common/utils' import { nanoid } from 'nanoid' -const { readFile } = require('fs/promises') -const fs = require('fs'); -const { spawn } = require('child_process'); - -function* getXDisplayNumber() { - const startValue = 99; - let i = startValue; - while(true) { - i -= 1; - - // Never hit zero since 0 is usually used by desktop users. - if (i <= 0) i = startValue; - yield ':' + i; - } -} - export const runCurv = async ({ file, @@ -54,61 +38,23 @@ export const runCurv = async ({ const fullPath = `/tmp/${tempFile}/output.gz` const imPath = `/tmp/${tempFile}/output.png` const customizerPath = `/tmp/${tempFile}/customizer.param` - const summaryPath = `/tmp/${tempFile}/summary.json` // contains camera info - - const code = file; - const DISPLAY = getXDisplayNumber().next().value; - - const xvfbProcess = spawn( - 'Xvfb', - [DISPLAY, '-ac', '-nocursor', '-screen', '0', '480x500x24'], - ); - - const curvProcess = spawn( - 'curv', - ['-' ], - { env: Object.assign({}, process.env, { DISPLAY, PATH: '/usr/local/bin' }) } - ); - - curvProcess.stdin.write(code); - curvProcess.stdin.end(); - - let statusSet = false; - let contentTypeSet = false; - - curvProcess.stderr.on('data', (buf) => { - const data = buf.toString('utf8'); - if (data.indexOf('shape') >= 0) { - setTimeout(() => { - const screenshotProcess = spawn('maim', ['--hidecursor', imPath], { env: { DISPLAY } }); - screenshotProcess.on('close', () => { - curvProcess.kill(); - xvfbProcess.kill(); - }); - }, 1000); - } - - if (data.indexOf('ERROR') < 0) { return; } - curvProcess.kill(); - xvfbProcess.kill(); - }); + const command = [ + 'xvfb-run --auto-servernum --server-args "-screen 0 1024x768x24" curv', + `-o ${imPath}`, + `-O xsize=${x}`, + `-O ysize=${y}`, + `-O bg=webRGB[26,26,29]`, // #1A1A1D + `/tmp/${tempFile}/main.curv`, + ].join(' ') + console.log('command', command) try { - const files: string[] = await Promise.all( - [customizerPath, summaryPath].map((path) => - readFile(path, { encoding: 'ascii' }) - ) - ) - const [params, cameraInfo] = files.map((fileStr: string) => - JSON.parse(fileStr) - ) + const consoleMessage = await runCommand(command, 15000) await writeFiles( [ { file: JSON.stringify({ - cameraInfo: viewAll ? cameraInfo.camera : undefined, - customizerParams: params.parameters, consoleMessage, type: 'png', }), @@ -143,7 +89,6 @@ export const stlExport = async ({ file, settings: { parameters } } = {}) => { ) const fullPath = `/tmp/${tempFile}/output.gz` const stlPath = `/tmp/${tempFile}/output.stl` - const customizerPath = `/tmp/${tempFile}/customizer.param` const command = [ 'curv', '-o', stlPath, @@ -155,14 +100,10 @@ export const stlExport = async ({ file, settings: { parameters } } = {}) => { try { // lambda will time out before this, we might need to look at background jobs if we do git integration stl generation const consoleMessage = await runCommand(command, 60000) - const params = JSON.parse( - await readFile(customizerPath, { encoding: 'ascii' }) - ).parameters await writeFiles( [ { file: JSON.stringify({ - customizerParams: params, consoleMessage, type: 'stl', }), @@ -175,7 +116,7 @@ export const stlExport = async ({ file, settings: { parameters } } = {}) => { `cat ${stlPath} /var/task/cadhub-concat-split /tmp/${tempFile}/metadata.json | gzip > ${fullPath}`, 15000 ) - return { consoleMessage, fullPath, customizerPath } + return { consoleMessage, fullPath } } catch (error) { return { error, fullPath } } diff --git a/app/api/src/docker/docker-compose.yml b/app/api/src/docker/docker-compose.yml index 892d57a..b6be985 100644 --- a/app/api/src/docker/docker-compose.yml +++ b/app/api/src/docker/docker-compose.yml @@ -53,11 +53,20 @@ services: command: js/curv.preview # Adding volumes so that the containers can be restarted for js only changes in local dev volumes: - - ../../dist/docker/openscad:/var/task/js/ + - ../../dist/docker/curv:/var/task/js/ - ../../dist/docker/common:/var/task/common/ ports: - - "5052:8080" - environment: - AWS_SECRET_ACCESS_KEY: "${DEV_AWS_SECRET_ACCESS_KEY}" - AWS_ACCESS_KEY_ID: "${DEV_AWS_ACCESS_KEY_ID}" - BUCKET: "${DEV_BUCKET}" + - "5070:8080" + curv-stl: + build: + context: ../../ + dockerfile: ./src/docker/curv/Dockerfile + image: curv + command: js/curv.stl + # Adding volumes so that the containers can be restarted for js only changes in local dev + volumes: + - ../../dist/docker/curv:/var/task/js/ + - ../../dist/docker/common:/var/task/common/ + ports: + - "5071:8080" + diff --git a/app/web/config/webpack.config.js b/app/web/config/webpack.config.js index 103151b..f9b7db7 100644 --- a/app/web/config/webpack.config.js +++ b/app/web/config/webpack.config.js @@ -6,7 +6,7 @@ module.exports = (config, { env }) => { } }) config.module.rules.push({ - test: /\.(md|jscad\.js|py|scad)$/i, + test: /\.(md|jscad\.js|py|scad|curv)$/i, use: 'raw-loader', }); return config diff --git a/app/web/src/components/IdeEditor/IdeEditor.tsx b/app/web/src/components/IdeEditor/IdeEditor.tsx index 20a2bee..b0dd204 100644 --- a/app/web/src/components/IdeEditor/IdeEditor.tsx +++ b/app/web/src/components/IdeEditor/IdeEditor.tsx @@ -18,7 +18,7 @@ const IdeEditor = ({ Loading }) => { cadquery: 'python', openscad: 'cpp', jscad: 'javascript', - curv: 'javascript', + curv: 'python', INIT: '', } const monaco = useMonaco() diff --git a/app/web/src/helpers/cadPackages/curv/curvController.ts b/app/web/src/helpers/cadPackages/curv/curvController.ts index 8323a8b..e972b68 100644 --- a/app/web/src/helpers/cadPackages/curv/curvController.ts +++ b/app/web/src/helpers/cadPackages/curv/curvController.ts @@ -7,8 +7,6 @@ import { RenderArgs, splitGziped, } from '../common' -import { CurvToCadhubParams } from './openScadParams' -import type { XYZ, Camera } from 'src/helpers/hooks/useIdeState' export const render = async ({ code, settings }: RenderArgs) => { const pixelRatio = window.devicePixelRatio || 1 @@ -61,21 +59,8 @@ export const render = async ({ code, settings }: RenderArgs) => { } const blob = await response.blob() const text = await new Response(blob).text() - const { consoleMessage, customizerParams, type, cameraInfo } = + const { consoleMessage, type } = splitGziped(text) - const vecArray2Obj = (arr: number[]): XYZ => ({ - x: arr[0], - y: arr[1], - z: arr[2], - }) - const camera: Camera = cameraInfo - ? { - dist: cameraInfo?.distance, - position: vecArray2Obj(cameraInfo?.translation), - rotation: vecArray2Obj(cameraInfo?.rotation), - isScadUpdate: true, - } - : undefined return createHealthyResponse({ type: type !== 'stl' ? 'png' : 'geometry', data: @@ -83,9 +68,7 @@ export const render = async ({ code, settings }: RenderArgs) => { ? blob : await stlToGeometry(window.URL.createObjectURL(blob)), consoleMessage, - camera, date: new Date(), - customizerParams: curvToCadhubParams(customizerParams || []), }) } catch (e) { return createUnhealthyResponse(new Date()) @@ -115,7 +98,7 @@ export const stl = async ({ code /*settings*/ }: RenderArgs) => { } const blob = await response.blob() const text = await new Response(blob).text() - const { consoleMessage, customizerParams, type } = splitGziped(text) + const { consoleMessage, type } = splitGziped(text) return createHealthyResponse({ type: type !== 'stl' ? 'png' : 'geometry', data: @@ -124,7 +107,6 @@ export const stl = async ({ code /*settings*/ }: RenderArgs) => { : await stlToGeometry(window.URL.createObjectURL(blob)), consoleMessage, date: new Date(), - customizerParams: openScadToCadhubParams(customizerParams || []), }) } catch (e) { return createUnhealthyResponse(new Date())