mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-24 14:37:58 +01:00
reify code formatting fix
This commit is contained in:
parent
06efd35119
commit
8e01a5c2e2
BIN
data/bunny.stl
Normal file
BIN
data/bunny.stl
Normal file
Binary file not shown.
26
index.js
26
index.js
@ -1,6 +1,6 @@
|
|||||||
import 'babel-polyfill';
|
import 'babel-polyfill';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Interface } from 'doodle3d-slicer';
|
import { Interface } from './src/index.js';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
|
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
|
||||||
import jss from 'jss';
|
import jss from 'jss';
|
||||||
@ -9,6 +9,10 @@ import normalize from 'normalize-jss';
|
|||||||
import queryString from 'query-string';
|
import queryString from 'query-string';
|
||||||
import getMuiTheme from 'material-ui/styles/getMuiTheme';
|
import getMuiTheme from 'material-ui/styles/getMuiTheme';
|
||||||
import { grey400, blue500, blue700 } from 'material-ui/styles/colors';
|
import { grey400, blue500, blue700 } from 'material-ui/styles/colors';
|
||||||
|
import bunny_url from './data/bunny.stl';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import 'three/examples/js/loaders/STLLoader.js';
|
||||||
|
import fileSaver from 'file-saver';
|
||||||
|
|
||||||
const muiTheme = getMuiTheme({
|
const muiTheme = getMuiTheme({
|
||||||
palette: {
|
palette: {
|
||||||
@ -29,11 +33,15 @@ jss.createStyleSheet({
|
|||||||
}
|
}
|
||||||
}).attach();
|
}).attach();
|
||||||
|
|
||||||
let { file, selectedPrinter, actions, name } = queryString.parse(location.search);
|
new THREE.STLLoader().load(bunny_url, geometry => {
|
||||||
if (actions) actions = JSON.parse(actions);
|
const material = new THREE.MeshPhongMaterial({ color: 0xff5533, specular: 0x111111, shininess: 200 });
|
||||||
|
const mesh = new THREE.Mesh(geometry, material);
|
||||||
render((
|
render((
|
||||||
<MuiThemeProvider muiTheme={muiTheme}>
|
<MuiThemeProvider muiTheme={muiTheme}>
|
||||||
<Interface actions={actions} fileUrl={file} selectedPrinter={selectedPrinter} name={name}/>
|
<Interface
|
||||||
</MuiThemeProvider>
|
mesh={mesh}
|
||||||
), document.getElementById('app'));
|
onSliceSucces={({ gcode }) => fileSaver.saveAs(gcode, 'bunny.gcode')}
|
||||||
|
/>
|
||||||
|
</MuiThemeProvider>
|
||||||
|
), document.getElementById('app'));
|
||||||
|
});
|
||||||
|
12267
package-lock.json
generated
12267
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -20,16 +20,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@doodle3d/clipper-js": "^1.0.10",
|
"@doodle3d/clipper-js": "^1.0.10",
|
||||||
"@doodle3d/doodle3d-api": "^1.0.5",
|
|
||||||
"@doodle3d/doodle3d-core": "github:doodle3d/doodle3d-core",
|
|
||||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
|
||||||
"file-saver": "^1.3.3",
|
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"material-ui": "^0.19.4",
|
"material-ui": "^0.19.4",
|
||||||
"material-ui-icons": "^1.0.0-beta.17",
|
"material-ui-icons": "^1.0.0-beta.17",
|
||||||
"material-ui-textfield-icon": "^0.2.2-1",
|
"material-ui-textfield-icon": "^0.2.2-1",
|
||||||
"proptypes": "^1.1.0",
|
"proptypes": "^1.1.0",
|
||||||
"query-string": "^5.0.1",
|
|
||||||
"react": "^16.0.0",
|
"react": "^16.0.0",
|
||||||
"react-addons-update": "^15.6.2",
|
"react-addons-update": "^15.6.2",
|
||||||
"react-dom": "^16.0.0",
|
"react-dom": "^16.0.0",
|
||||||
@ -37,13 +32,14 @@
|
|||||||
"react-resize-detector": "^1.1.0",
|
"react-resize-detector": "^1.1.0",
|
||||||
"shortid": "^2.2.8",
|
"shortid": "^2.2.8",
|
||||||
"three": "^0.88.0",
|
"three": "^0.88.0",
|
||||||
"validate-ip": "^1.0.1",
|
"validate-ip": "^1.0.1"
|
||||||
"webpack-bundle-analyzer": "^2.9.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"file-saver": "^1.3.3",
|
||||||
"babel-cli": "6.24.1",
|
"babel-cli": "6.24.1",
|
||||||
"babel-eslint": "^5.0.4",
|
"babel-eslint": "^5.0.4",
|
||||||
"babel-loader": "7.0.0",
|
"babel-loader": "7.0.0",
|
||||||
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||||
"babel-plugin-transform-es2015-classes": "^6.24.1",
|
"babel-plugin-transform-es2015-classes": "^6.24.1",
|
||||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
@ -59,12 +55,14 @@
|
|||||||
"file-loader": "^1.1.11",
|
"file-loader": "^1.1.11",
|
||||||
"html-webpack-plugin": "^2.29.0",
|
"html-webpack-plugin": "^2.29.0",
|
||||||
"html-webpack-template": "^6.0.2",
|
"html-webpack-template": "^6.0.2",
|
||||||
|
"query-string": "^5.0.1",
|
||||||
"image-webpack-loader": "^4.2.0",
|
"image-webpack-loader": "^4.2.0",
|
||||||
"imports-loader": "^0.7.1",
|
"imports-loader": "^0.7.1",
|
||||||
"material-ui": "^0.19.4",
|
"material-ui": "^0.19.4",
|
||||||
"normalize-jss": "^4.0.0",
|
"normalize-jss": "^4.0.0",
|
||||||
"raw-loader": "^0.5.1",
|
"raw-loader": "^0.5.1",
|
||||||
"webpack": "^3.3.0",
|
"webpack": "^3.8.1",
|
||||||
|
"webpack-bundle-analyzer": "^2.9.2",
|
||||||
"webpack-dev-server": "^2.5.1",
|
"webpack-dev-server": "^2.5.1",
|
||||||
"worker-loader": "^0.8.1",
|
"worker-loader": "^0.8.1",
|
||||||
"yml-loader": "^2.1.0"
|
"yml-loader": "^2.1.0"
|
||||||
|
@ -21,14 +21,8 @@ import update from 'react-addons-update';
|
|||||||
import SettingsIcon from 'material-ui-icons/Settings';
|
import SettingsIcon from 'material-ui-icons/Settings';
|
||||||
import ExitToAppIcon from 'material-ui-icons/ExitToApp';
|
import ExitToAppIcon from 'material-ui-icons/ExitToApp';
|
||||||
import validateIp from 'validate-ip';
|
import validateIp from 'validate-ip';
|
||||||
import { Doodle3DManager } from 'doodle3d-api';
|
|
||||||
import Accordion from './Accordion.js';
|
import Accordion from './Accordion.js';
|
||||||
|
|
||||||
const DOODLE_3D_MANAGER = new Doodle3DManager();
|
|
||||||
DOODLE_3D_MANAGER.checkNonServerBoxes = false;
|
|
||||||
|
|
||||||
const CONNECT_URL = 'http://connect.doodle3d.com/';
|
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
textFieldRow: {
|
textFieldRow: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -91,7 +85,6 @@ class Settings extends React.Component {
|
|||||||
|
|
||||||
state = {
|
state = {
|
||||||
localStorage: getLocalStorage(),
|
localStorage: getLocalStorage(),
|
||||||
wifiBoxes: [],
|
|
||||||
addPrinter: {
|
addPrinter: {
|
||||||
open: false,
|
open: false,
|
||||||
name: '',
|
name: '',
|
||||||
@ -125,15 +118,6 @@ class Settings extends React.Component {
|
|||||||
} else if (!selectedPrinter && !localStorage.active) {
|
} else if (!selectedPrinter && !localStorage.active) {
|
||||||
this.openAddPrinterDialog();
|
this.openAddPrinterDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventListener = ({ boxes }) => this.setState({ wifiBoxes: boxes });
|
|
||||||
DOODLE_3D_MANAGER.addEventListener('boxeschanged', eventListener);
|
|
||||||
this.setState({ eventListener });
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
const { eventListener } = this.state;
|
|
||||||
DOODLE_3D_MANAGER.removeEventListener('boxeschanged', eventListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changeSettings = (fieldName, value) => {
|
changeSettings = (fieldName, value) => {
|
||||||
@ -362,11 +346,6 @@ class Settings extends React.Component {
|
|||||||
closeAddPrinterDialog = (override) => this.setAddPrinterDialog(false, override);
|
closeAddPrinterDialog = (override) => this.setAddPrinterDialog(false, override);
|
||||||
openAddPrinterDialog = (override) => this.setAddPrinterDialog(true, override);
|
openAddPrinterDialog = (override) => this.setAddPrinterDialog(true, override);
|
||||||
setAddPrinterDialog = (open, override = {}) => {
|
setAddPrinterDialog = (open, override = {}) => {
|
||||||
if (open) {
|
|
||||||
DOODLE_3D_MANAGER.setAutoUpdate(true, 10000);
|
|
||||||
} else {
|
|
||||||
DOODLE_3D_MANAGER.setAutoUpdate(false);
|
|
||||||
}
|
|
||||||
this.setState({
|
this.setState({
|
||||||
addPrinter: {
|
addPrinter: {
|
||||||
ip: '',
|
ip: '',
|
||||||
@ -383,16 +362,7 @@ class Settings extends React.Component {
|
|||||||
openManagePrinterDialog = () => this.setManagePrinterDialog(true);
|
openManagePrinterDialog = () => this.setManagePrinterDialog(true);
|
||||||
setManagePrinterDialog = (open) => {
|
setManagePrinterDialog = (open) => {
|
||||||
const { localStorage: { active, printers } } = this.state;
|
const { localStorage: { active, printers } } = this.state;
|
||||||
if (!active) {
|
|
||||||
DOODLE_3D_MANAGER.setAutoUpdate(false);
|
|
||||||
return this.setState({ managePrinter: { open: false } });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open) {
|
|
||||||
DOODLE_3D_MANAGER.setAutoUpdate(true, 10000);
|
|
||||||
} else {
|
|
||||||
DOODLE_3D_MANAGER.setAutoUpdate(false);
|
|
||||||
}
|
|
||||||
this.setState({
|
this.setState({
|
||||||
managePrinter: {
|
managePrinter: {
|
||||||
open,
|
open,
|
||||||
@ -558,7 +528,6 @@ class Settings extends React.Component {
|
|||||||
|
|
||||||
function printDialog(props, state, title, form, submitText, data, closeDialog, removeActivePrinter, save) {
|
function printDialog(props, state, title, form, submitText, data, closeDialog, removeActivePrinter, save) {
|
||||||
const { classes } = props;
|
const { classes } = props;
|
||||||
const { wifiBoxes } = state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
@ -588,19 +557,6 @@ function printDialog(props, state, title, form, submitText, data, closeDialog, r
|
|||||||
<MenuItem key={value} value={value} primaryText={title} />
|
<MenuItem key={value} value={value} primaryText={title} />
|
||||||
))}
|
))}
|
||||||
</SelectField>
|
</SelectField>
|
||||||
<TextField name={`${form}.name`} floatingLabelText="Name" fullWidth />
|
|
||||||
{(data.printer === 'doodle3d_printer') ?
|
|
||||||
<TextField name={`${form}.ip`} floatingLabelText="IP Adress" fullWidth /> :
|
|
||||||
<div className={classes.textFieldRow}>
|
|
||||||
<SelectField name={`${form}.ip`} floatingLabelText="Doodle3D WiFi-Box" fullWidth>
|
|
||||||
{wifiBoxes.map(({ localip, id, wifiboxid }) => (<MenuItem key={id} value={localip} primaryText={wifiboxid} />))}
|
|
||||||
</SelectField>
|
|
||||||
{data.ip && <ExitToAppIcon
|
|
||||||
onClick={() => window.open(`${CONNECT_URL}/?uuid=0#control?localip=${data.ip}`, '_blank')}
|
|
||||||
style={{ fill: grey800, marginLeft: '10px', cursor: 'pointer' }}
|
|
||||||
/>}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{data.error && <p className={classes.error}>{data.error}</p>}
|
{data.error && <p className={classes.error}>{data.error}</p>}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
@ -12,9 +12,6 @@ import MenuItem from 'material-ui/MenuItem';
|
|||||||
import { Tabs, Tab } from 'material-ui/Tabs';
|
import { Tabs, Tab } from 'material-ui/Tabs';
|
||||||
import Settings from './Settings.js';
|
import Settings from './Settings.js';
|
||||||
import ReactResizeDetector from 'react-resize-detector';
|
import ReactResizeDetector from 'react-resize-detector';
|
||||||
import JSONToSketchData from 'doodle3d-core/shape/JSONToSketchData';
|
|
||||||
import createSceneData from 'doodle3d-core/d3/createSceneData.js';
|
|
||||||
import { generateExportMesh } from 'doodle3d-core/utils/exportUtils.js';
|
|
||||||
import muiThemeable from 'material-ui/styles/muiThemeable';
|
import muiThemeable from 'material-ui/styles/muiThemeable';
|
||||||
import logo from '../../img/logo.png';
|
import logo from '../../img/logo.png';
|
||||||
|
|
||||||
@ -99,29 +96,17 @@ const styles = {
|
|||||||
|
|
||||||
class Interface extends React.Component {
|
class Interface extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
fileUrl: PropTypes.string,
|
|
||||||
selectedPrinter: PropTypes.string,
|
selectedPrinter: PropTypes.string,
|
||||||
mesh: PropTypes.shape({ isMesh: PropTypes.oneOf([true]) }),
|
mesh: PropTypes.shape({ isMesh: PropTypes.oneOf([true]) }),
|
||||||
classes: PropTypes.objectOf(PropTypes.string),
|
classes: PropTypes.objectOf(PropTypes.string),
|
||||||
pixelRatio: PropTypes.number.isRequired,
|
pixelRatio: PropTypes.number.isRequired,
|
||||||
onCancel: PropTypes.func,
|
onCancel: PropTypes.func,
|
||||||
name: PropTypes.string.isRequired,
|
onSliceSucces: PropTypes.func.isRequired,
|
||||||
muiTheme: PropTypes.object.isRequired,
|
muiTheme: PropTypes.object.isRequired
|
||||||
allowDragDrop: PropTypes.bool.isRequired,
|
|
||||||
actions: PropTypes.arrayOf(PropTypes.shape({ target: PropTypes.string }))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
actions: [{
|
pixelRatio: 1
|
||||||
target: 'WIFI_PRINT',
|
|
||||||
title: 'Print over WiFi'
|
|
||||||
}, {
|
|
||||||
target: 'DOWNLOAD',
|
|
||||||
title: 'Download GCode'
|
|
||||||
}],
|
|
||||||
pixelRatio: 1,
|
|
||||||
name: 'Doodle3D',
|
|
||||||
allowDragDrop: true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -145,27 +130,12 @@ class Interface extends React.Component {
|
|||||||
const { scene } = this.state;
|
const { scene } = this.state;
|
||||||
scene.updateCanvas(canvas);
|
scene.updateCanvas(canvas);
|
||||||
|
|
||||||
const { mesh, fileUrl } = this.props;
|
const { mesh } = this.props;
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
this.updateMesh(mesh, scene);
|
this.updateMesh(mesh, scene);
|
||||||
} else if (fileUrl) {
|
|
||||||
this.loadFile(fileUrl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFile = (fileUrl) => {
|
|
||||||
const { origin, pathname, password, username, port } = new URL(fileUrl);
|
|
||||||
const headers = {};
|
|
||||||
if (password && username) headers.Authorization = `Basic ${btoa(`${username}:${password}`)}`;
|
|
||||||
|
|
||||||
fetch(`${origin}${port}${pathname}`, { headers })
|
|
||||||
.then(resonse => resonse.json())
|
|
||||||
.then(JSONToSketchData)
|
|
||||||
.then(createSceneData)
|
|
||||||
.then(sketch => generateExportMesh(sketch, { offsetSingleWalls: false, matrix: new THREE.Matrix4() }))
|
|
||||||
.then(mesh => this.updateMesh(mesh));
|
|
||||||
};
|
|
||||||
|
|
||||||
updateMesh(mesh, scene = this.state.scene) {
|
updateMesh(mesh, scene = this.state.scene) {
|
||||||
scene.mesh.geometry = mesh.geometry;
|
scene.mesh.geometry = mesh.geometry;
|
||||||
centerGeometry(scene.mesh);
|
centerGeometry(scene.mesh);
|
||||||
@ -225,19 +195,15 @@ class Interface extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
slice = async (action) => {
|
slice = async () => {
|
||||||
const { isSlicing, settings, mesh, scene: { mesh: { matrix } } } = this.state;
|
const { isSlicing, settings, mesh, scene: { mesh: { matrix } } } = this.state;
|
||||||
const { name } = this.props;
|
const { onSliceSucces } = this.props;
|
||||||
|
|
||||||
if (isSlicing) return;
|
if (isSlicing) return;
|
||||||
if (!settings) {
|
if (!settings) {
|
||||||
this.setState({ error: 'please select a printer first' });
|
this.setState({ error: 'please select a printer first' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (action.target === 'WIFI_PRINT' && !settings.ip) {
|
|
||||||
this.setState({ error: 'no Doodle3D WiFi-Box selected' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
this.setState({ error: 'there is no file to slice' });
|
this.setState({ error: 'there is no file to slice' });
|
||||||
return;
|
return;
|
||||||
@ -251,7 +217,8 @@ class Interface extends React.Component {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const updateProgres = progress => this.setState({ progress: { ...this.state.progress, ...progress } });
|
const updateProgres = progress => this.setState({ progress: { ...this.state.progress, ...progress } });
|
||||||
await slice(action, name, exportMesh, settings, updateProgres);
|
const sliceResults = await slice(exportMesh, settings, updateProgres);
|
||||||
|
onSliceSucces(sliceResults);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.setState({ error: error.message });
|
this.setState({ error: error.message });
|
||||||
throw error;
|
throw error;
|
||||||
@ -317,25 +284,8 @@ class Interface extends React.Component {
|
|||||||
this.setState({ objectDimensions: `${Math.round(y)}x${Math.round(z)}x${Math.round(x)}mm` });
|
this.setState({ objectDimensions: `${Math.round(y)}x${Math.round(z)}x${Math.round(x)}mm` });
|
||||||
};
|
};
|
||||||
|
|
||||||
onDrop = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
if (!this.props.allowDragDrop) return;
|
|
||||||
|
|
||||||
for (const file of event.dataTransfer.files) {
|
|
||||||
const extentions = file.name.split('.').pop();
|
|
||||||
|
|
||||||
switch (extentions.toUpperCase()) {
|
|
||||||
case 'D3SKETCH':
|
|
||||||
this.loadFile(URL.createObjectURL(file));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes, onCancel, selectedPrinter, actions } = this.props;
|
const { classes, onCancel, selectedPrinter } = this.props;
|
||||||
const { isSlicing, settings, progress, showFullScreen, error, objectDimensions } = this.state;
|
const { isSlicing, settings, progress, showFullScreen, error, objectDimensions } = this.state;
|
||||||
|
|
||||||
const style = { ...(showFullScreen ? {} : { maxWidth: 'inherit', width: '100%', height: '100%' }) };
|
const style = { ...(showFullScreen ? {} : { maxWidth: 'inherit', width: '100%', height: '100%' }) };
|
||||||
@ -359,37 +309,14 @@ class Interface extends React.Component {
|
|||||||
className={`${classes.button}`}
|
className={`${classes.button}`}
|
||||||
onClick={onCancel}
|
onClick={onCancel}
|
||||||
/>}
|
/>}
|
||||||
{actions.length === 1 ? (
|
<RaisedButton
|
||||||
<RaisedButton
|
label="Download GCODE"
|
||||||
primary
|
ref="button"
|
||||||
label={actions[0].title}
|
primary
|
||||||
onClick={() => this.slice(actions[0])}
|
className={`${classes.button}`}
|
||||||
className={`${classes.button}`}
|
disabled={isSlicing}
|
||||||
disabled={isSlicing}
|
onClick={() => this.slice()}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<RaisedButton
|
|
||||||
label="Download GCODE"
|
|
||||||
ref="button"
|
|
||||||
primary
|
|
||||||
className={`${classes.button}`}
|
|
||||||
disabled={isSlicing}
|
|
||||||
onClick={() => this.slice({target: 'DOWNLOAD'})}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<RaisedButton
|
|
||||||
label="Print"
|
|
||||||
ref="button"
|
|
||||||
primary
|
|
||||||
className={`${classes.button}`}
|
|
||||||
disabled={settings && settings.ip==""}
|
|
||||||
onClick={() => this.slice({target:'WIFI_PRINT'})}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -415,15 +342,7 @@ class Interface extends React.Component {
|
|||||||
|
|
||||||
if (showFullScreen) {
|
if (showFullScreen) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={classes.container}>
|
||||||
className={classes.container}
|
|
||||||
ref={(container) => {
|
|
||||||
if (container) {
|
|
||||||
container.addEventListener('dragover', event => event.preventDefault());
|
|
||||||
container.addEventListener('drop', this.onDrop);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ReactResizeDetector handleWidth handleHeight onResize={this.onResizeContainer} />
|
<ReactResizeDetector handleWidth handleHeight onResize={this.onResizeContainer} />
|
||||||
<img src={logo} className={classes.logo} />
|
<img src={logo} className={classes.logo} />
|
||||||
{d3Panel}
|
{d3Panel}
|
||||||
@ -432,15 +351,7 @@ class Interface extends React.Component {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={classes.container}>
|
||||||
className={classes.container}
|
|
||||||
ref={(container) => {
|
|
||||||
if (container) {
|
|
||||||
container.addEventListener('dragover', event => event.preventDefault());
|
|
||||||
container.addEventListener('drop', this.onDrop);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ReactResizeDetector handleWidth handleHeight onResize={this.onResizeContainer} />
|
<ReactResizeDetector handleWidth handleHeight onResize={this.onResizeContainer} />
|
||||||
<Tabs
|
<Tabs
|
||||||
style={{ width: '100%', display: 'flex', flexDirection: 'column' }}
|
style={{ width: '100%', display: 'flex', flexDirection: 'column' }}
|
||||||
|
@ -6,8 +6,6 @@ import qualitySettings from '../settings/quality.yml';
|
|||||||
import { sliceGeometry } from '../slicer.js';
|
import { sliceGeometry } from '../slicer.js';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import fileSaver from 'file-saver';
|
|
||||||
import { Doodle3DBox } from 'doodle3d-api';
|
|
||||||
|
|
||||||
export function placeOnGround(mesh) {
|
export function placeOnGround(mesh) {
|
||||||
const boundingBox = new THREE.Box3().setFromObject(mesh);
|
const boundingBox = new THREE.Box3().setFromObject(mesh);
|
||||||
@ -84,91 +82,13 @@ export function createScene({ muiTheme }) {
|
|||||||
return { editorControls, scene, mesh, camera, renderer, render, box, setSize, updateCanvas, focus };
|
return { editorControls, scene, mesh, camera, renderer, render, box, setSize, updateCanvas, focus };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchProgress(url, data = {}, onProgress) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const request = new Request(url, data);
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
|
|
||||||
xhr.onload = () => {
|
|
||||||
resolve(new Response(xhr.response));
|
|
||||||
// const headers = new Headers(xhr.getAllResponseHeaders() || '');
|
|
||||||
// const { status, statusText, response, responseText, responseURL: url = headers.get('X-Request-URL') } = xhr;
|
|
||||||
// resolve(new Response(response || responseText, { headers, status, statusText, url }));
|
|
||||||
};
|
|
||||||
xhr.onerror = () => reject(new TypeError('Network request failed'));
|
|
||||||
xhr.ontimeout = () => reject(new TypeError('Network request failed'));
|
|
||||||
|
|
||||||
xhr.open(request.method, url, true);
|
|
||||||
|
|
||||||
if (request.credentials === 'include') {
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
} else if (request.credentials === 'omit') {
|
|
||||||
xhr.withCredentials = false;
|
|
||||||
}
|
|
||||||
if (xhr.upload && onProgress) xhr.upload.onprogress = onProgress;
|
|
||||||
if (xhr.responseType) xhr.responseType = 'blob';
|
|
||||||
|
|
||||||
// request.headers.forEach((value, name) => xhr.setRequestHeader(name, value));
|
|
||||||
|
|
||||||
xhr.send(data.body);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMalyanStatus(ip) {
|
|
||||||
return fetch(`http://${ip}/inquiry`, { method: 'GET' })
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(statusText => {
|
|
||||||
const [nozzleTemperature, nozzleTargetTemperature, bedTemperature, bedTargetTemperature, progress] = statusText.match(/\d+/g);
|
|
||||||
const status = { nozzleTemperature, nozzleTargetTemperature, bedTemperature, bedTargetTemperature, progress };
|
|
||||||
|
|
||||||
switch (statusText.charAt(statusText.length - 1)) {
|
|
||||||
case 'I':
|
|
||||||
status.state = 'idle';
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
status.state = 'printing';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
status.state = 'unknown';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function sleep(time) {
|
export function sleep(time) {
|
||||||
return new Promise(resolve => setTimeout(resolve, time));
|
return new Promise(resolve => setTimeout(resolve, time));
|
||||||
}
|
}
|
||||||
|
|
||||||
const GCODE_SERVER_URL = 'https://gcodeserver.doodle3d.com';
|
export async function slice(mesh, settings, updateProgress) {
|
||||||
|
let steps = 1;
|
||||||
export async function slice(action, name, mesh, settings, updateProgress) {
|
|
||||||
let steps;
|
|
||||||
let currentStep = 0;
|
let currentStep = 0;
|
||||||
let wifiBox;
|
|
||||||
switch (action.target) {
|
|
||||||
case 'DOWNLOAD':
|
|
||||||
steps = 1;
|
|
||||||
break;
|
|
||||||
case 'WIFI_PRINT':
|
|
||||||
if (settings.printer === 'doodle3d_printer') {
|
|
||||||
// const { state } = await getMalyanStatus(settings.ip);
|
|
||||||
// if (state !== 'idle') throw { message: 'printer is busy', code: 0 };
|
|
||||||
} else {
|
|
||||||
wifiBox = new Doodle3DBox(settings.ip);
|
|
||||||
if (! await wifiBox.checkAlive()) throw { message: `can't connect to printer`, code: 4 };
|
|
||||||
|
|
||||||
const { state } = await wifiBox.info.status();
|
|
||||||
if (state !== 'idle') throw { message: 'printer is busy', code: 0 };
|
|
||||||
}
|
|
||||||
steps = 2;
|
|
||||||
break;
|
|
||||||
case 'CUSTOM_UPLOAD':
|
|
||||||
steps = 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw { message: 'unknown target', code: 1 };
|
|
||||||
}
|
|
||||||
|
|
||||||
const { dimensions } = settings;
|
const { dimensions } = settings;
|
||||||
const centerX = dimensions.x / 2;
|
const centerX = dimensions.x / 2;
|
||||||
@ -178,9 +98,8 @@ export async function slice(action, name, mesh, settings, updateProgress) {
|
|||||||
.multiply(new THREE.Matrix4().makeRotationY(-Math.PI / 2.0))
|
.multiply(new THREE.Matrix4().makeRotationY(-Math.PI / 2.0))
|
||||||
.multiply(mesh.matrix);
|
.multiply(mesh.matrix);
|
||||||
|
|
||||||
const { gcode } = await sliceGeometry({
|
const sliceResult = await sliceGeometry({
|
||||||
...settings,
|
...settings,
|
||||||
name: `${name}.gcode`,
|
|
||||||
printer: { type: settings.printers, title: printerSettings[settings.printer].title },
|
printer: { type: settings.printers, title: printerSettings[settings.printer].title },
|
||||||
material: { type: settings.material, title: materialSettings[settings.material].title },
|
material: { type: settings.material, title: materialSettings[settings.material].title },
|
||||||
quality: { type: settings.quality, title: qualitySettings[settings.quality].title }
|
quality: { type: settings.quality, title: qualitySettings[settings.quality].title }
|
||||||
@ -194,80 +113,7 @@ export async function slice(action, name, mesh, settings, updateProgress) {
|
|||||||
});
|
});
|
||||||
currentStep ++;
|
currentStep ++;
|
||||||
|
|
||||||
switch (action.target) {
|
return sliceResult;
|
||||||
case 'DOWNLOAD': {
|
|
||||||
fileSaver.saveAs(gcode, `${name}.gcode`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'WIFI_PRINT': {
|
|
||||||
if (settings.printer === 'doodle3d_printer') {
|
|
||||||
const body = new FormData();
|
|
||||||
body.append('file', gcode, 'doodle.gcode');
|
|
||||||
|
|
||||||
// because fetch has no way of retrieving progress we fake progress
|
|
||||||
let loaded = 0;
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
loaded += 15 * 1024;
|
|
||||||
updateProgress({
|
|
||||||
action: 'Uploading to printer',
|
|
||||||
percentage: (currentStep + loaded / gcode.size) / steps
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// await fetchProgress(`http://${settings.ip}/set?code=M563 S4`, { method: 'GET' });
|
|
||||||
await fetch(`http://${settings.ip}/upload`, { method: 'POST', body, mode: 'no-cors' }, (progress) => {
|
|
||||||
updateProgress({
|
|
||||||
action: 'Uploading to printer',
|
|
||||||
percentage: (currentStep + progress.loaded / progress.total) / steps
|
|
||||||
});
|
|
||||||
});
|
|
||||||
clearInterval(interval);
|
|
||||||
await fetch(`http://${settings.ip}/set?code=M566 ${name}.gcode`, { method: 'GET', mode: 'no-cors' });
|
|
||||||
await fetch(`http://${settings.ip}/set?code=M565`, { method: 'GET', mode: 'no-cors' });
|
|
||||||
|
|
||||||
currentStep ++;
|
|
||||||
} else {
|
|
||||||
// upload G-code file to AWS S3
|
|
||||||
const { data: { reservation: { fields, url }, id } } = await fetch(`${GCODE_SERVER_URL}/upload`, { method: 'POST' })
|
|
||||||
.then(response => response.json());
|
|
||||||
|
|
||||||
const body = new FormData();
|
|
||||||
for (const key in fields) {
|
|
||||||
body.append(key, fields[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.append('file', gcode, 'doodle.gcode');
|
|
||||||
|
|
||||||
await fetchProgress(url, { method: 'POST', body }, progress => {
|
|
||||||
updateProgress({
|
|
||||||
action: 'Uploading',
|
|
||||||
percentage: (currentStep + progress.loaded / progress.total) / steps
|
|
||||||
});
|
|
||||||
});
|
|
||||||
currentStep ++;
|
|
||||||
|
|
||||||
await wifiBox.printer.fetch(id);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'CUSTOM_UPLOAD': {
|
|
||||||
const body = new FormData();
|
|
||||||
body.append('file', gcode, 'doodle.gcode');
|
|
||||||
|
|
||||||
await fetchProgress(action.url, { method: 'POST', body }, progress => {
|
|
||||||
updateProgress({
|
|
||||||
action: 'Uploading',
|
|
||||||
percentage: (currentStep + progress.loaded / progress.total) / steps
|
|
||||||
});
|
|
||||||
});
|
|
||||||
currentStep ++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw { message: 'unknown target', code: 1 };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TabTemplate = ({ children, selected, style }) => {
|
export const TabTemplate = ({ children, selected, style }) => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Shape from 'clipper-js';
|
import Shape from '@doodle3d/clipper-js';
|
||||||
import { PRECISION } from '../constants.js';
|
import { PRECISION } from '../constants.js';
|
||||||
|
|
||||||
const OFFSET_OPTIONS = {
|
const OFFSET_OPTIONS = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Shape from 'clipper-js';
|
import Shape from '@doodle3d/clipper-js';
|
||||||
|
|
||||||
export default function calculateOutlines(slices) {
|
export default function calculateOutlines(slices) {
|
||||||
for (let layer = 0; layer < slices.length; layer ++) {
|
for (let layer = 0; layer < slices.length; layer ++) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import getFillTemplate from './getFillTemplate.js';
|
import getFillTemplate from './getFillTemplate.js';
|
||||||
import Shape from 'clipper-js';
|
import Shape from '@doodle3d/clipper-js';
|
||||||
import { PRECISION } from '../constants.js';
|
import { PRECISION } from '../constants.js';
|
||||||
|
|
||||||
const PRECISION_SQUARED = Math.pow(PRECISION, 2);
|
const PRECISION_SQUARED = Math.pow(PRECISION, 2);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Shape from 'clipper-js';
|
import Shape from '@doodle3d/clipper-js';
|
||||||
|
|
||||||
export default function getFillTemplate(bounds, gridSize, even, uneven) {
|
export default function getFillTemplate(bounds, gridSize, even, uneven) {
|
||||||
const paths = [];
|
const paths = [];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Shape from 'clipper-js';
|
import Shape from '@doodle3d/clipper-js';
|
||||||
|
|
||||||
export default class Slice {
|
export default class Slice {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { distanceTo } from './helpers/vector2.js';
|
import { distanceTo } from './helpers/vector2.js';
|
||||||
import Shape from 'clipper-js';
|
import Shape from '@doodle3d/clipper-js';
|
||||||
|
|
||||||
export default function optimizePaths(slices) {
|
export default function optimizePaths(slices) {
|
||||||
let start = { x: 0, y: 0 };
|
let start = { x: 0, y: 0 };
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Shape from 'clipper-js';
|
import Shape from '@doodle3d/clipper-js';
|
||||||
import Slice from './helpers/Slice.js';
|
import Slice from './helpers/Slice.js';
|
||||||
|
|
||||||
import { PRECISION, MIN_AREA } from '../constants.js';
|
import { PRECISION, MIN_AREA } from '../constants.js';
|
||||||
@ -14,7 +14,7 @@ export default function shapesToSlices(shapes) {
|
|||||||
.simplify('pftNonZero')
|
.simplify('pftNonZero')
|
||||||
.clean(1)
|
.clean(1)
|
||||||
.thresholdArea(MIN_AREA / Math.pow(PRECISION, 2))
|
.thresholdArea(MIN_AREA / Math.pow(PRECISION, 2))
|
||||||
.seperateShapes();
|
.separateShapes();
|
||||||
|
|
||||||
lineShapesClosed = new Shape(lineShapesClosed, true, true, true, true)
|
lineShapesClosed = new Shape(lineShapesClosed, true, true, true, true)
|
||||||
.clean(1);
|
.clean(1);
|
||||||
|
@ -29,16 +29,6 @@ module.exports = {
|
|||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
path: path.resolve(__dirname, 'dist')
|
path: path.resolve(__dirname, 'dist')
|
||||||
},
|
},
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'doodle3d-slicer': path.resolve(__dirname, 'src/'),
|
|
||||||
'clipper-lib': '@doodle3d/clipper-lib',
|
|
||||||
'clipper-js': '@doodle3d/clipper-js',
|
|
||||||
'doodle3d-core': `@doodle3d/doodle3d-core/${devMode ? 'module' : 'lib'}`,
|
|
||||||
'doodle3d-api': `@doodle3d/doodle3d-api/${devMode ? 'module' : 'lib'}`,
|
|
||||||
'cal': '@doodle3d/cal'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
@ -75,7 +65,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}] : [])]
|
}] : [])]
|
||||||
}, {
|
}, {
|
||||||
test: /\.(woff)$/,
|
test: /\.stl$/,
|
||||||
use: {
|
use: {
|
||||||
loader: 'file-loader'
|
loader: 'file-loader'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user