Initial work to support curv #578
3
.vscode/settings.json
vendored
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"Cadhub",
|
||||
"cadquery",
|
||||
"curv",
|
||||
"Customizer",
|
||||
"Hutten",
|
||||
"cadquery",
|
||||
"jscad",
|
||||
"openscad",
|
||||
"sendmail"
|
||||
|
||||
@@ -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}`)
|
||||
})
|
||||
|
||||
@@ -2,17 +2,27 @@ FROM public.ecr.aws/lts/ubuntu:20.04_stable
|
||||
|
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
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
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN git clone https://github.com/curv3d/curv.git
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN cd curv
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN git submodule init && git submodule update
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN mkdir build
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN cd build
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN sed -i 's/set(LEAN_BUILD 0)/set(LEAN_BUILD 1)/' ../CMakeLists.txt
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN cmake ..
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN make
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN make install
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get update --fix-missing && apt-get -y -qq install software-properties-common dirmngr apt-transport-https lsb-release ca-certificates xvfb
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get update -qq
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install git
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get update --fix-missing && apt-get -y --fix-broken install python-pycurl python-apt
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq --fix-broken install software-properties-common
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install xvfb unzip maim clang cmake
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install git-core libboost-all-dev
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install libopenexr-dev libtbb-dev
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install libglm-dev libpng-dev
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install libeigen3-dev dbus-x11
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install libxcursor-dev libxinerama-dev
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install libxrandr-dev libglu1-mesa-dev
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install libgles2-mesa-dev libgl1-mesa-dev
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN apt-get -y -qq install libxi-dev
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
RUN git clone --recursive https://github.com/curv3d/curv; cd curv; make; make install
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
|
||||
# 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
|
||||
|
built from source? better way to do this? built from source? better way to do this?
built from source? better way to do this? built from source? better way to do this?
|
||||
|
||||
# using built javascript from dist
|
||||
# run `yarn rw build` before bulding this image
|
||||
COPY dist/docker/openscad/* /var/task/js/
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
COPY dist/docker/curv/* /var/task/js/
|
||||
|
built from source? better way to do this? built from source? better way to do this?
|
||||
COPY dist/docker/common/* /var/task/common/
|
||||
COPY src/docker/common/entrypoint.sh /entrypoint.sh
|
||||
RUN ["chmod", "+x", "/entrypoint.sh"]
|
||||
|
||||
|
built from source? better way to do this? built from source? better way to do this?
built from source? better way to do this? built from source? better way to do this?
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18,7 +18,7 @@ const IdeEditor = ({ Loading }) => {
|
||||
cadquery: 'python',
|
||||
openscad: 'cpp',
|
||||
jscad: 'javascript',
|
||||
curv: 'javascript',
|
||||
curv: 'python',
|
||||
INIT: '',
|
||||
}
|
||||
const monaco = useMonaco()
|
||||
|
||||
@@ -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())
|
||||
|
||||
built from source? better way to do this?
built from source? better way to do this?