mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-22 13:37:58 +01:00
make settings editable
This commit is contained in:
parent
c1117a8ce5
commit
6cd899f32b
3
package-lock.json
generated
3
package-lock.json
generated
@ -2985,8 +2985,7 @@
|
||||
"lodash": {
|
||||
"version": "4.17.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
||||
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
|
||||
"dev": true
|
||||
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
|
||||
},
|
||||
"lodash.merge": {
|
||||
"version": "4.6.0",
|
||||
|
@ -15,6 +15,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@doodle3d/clipper-js": "^1.0.7",
|
||||
"lodash": "^4.17.4",
|
||||
"material-ui": "^0.19.4",
|
||||
"proptypes": "^1.1.0",
|
||||
"react": "^16.1.0",
|
||||
|
60
src/interface/FormComponents.js
Normal file
60
src/interface/FormComponents.js
Normal file
@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'proptypes';
|
||||
import _ from 'lodash';
|
||||
import injectSheet from 'react-jss';
|
||||
import MaterialUISelectField from 'material-ui/SelectField'
|
||||
import MaterialUICheckbox from 'material-ui/Checkbox';
|
||||
import MaterialUITextField from 'material-ui/TextField';
|
||||
import { grey100, grey300, grey500 } from 'material-ui/styles/colors';
|
||||
|
||||
const styles = {
|
||||
fieldSet: {
|
||||
border: 'none',
|
||||
backgroundColor: grey100,
|
||||
marginTop: '20px',
|
||||
'& legend': {
|
||||
border: `1px solid ${grey300}`,
|
||||
backgroundColor: 'white',
|
||||
padding: '3px 13px',
|
||||
color: grey500
|
||||
}
|
||||
}
|
||||
};
|
||||
export const SettingsGroup = injectSheet(styles)(({ name, classes, children }) => (
|
||||
<fieldset className={classes.fieldSet}>
|
||||
<legend>{name}</legend>
|
||||
{children}
|
||||
</fieldset>
|
||||
));
|
||||
SettingsGroup.propTypes = {
|
||||
classes: PropTypes.objectOf(PropTypes.string),
|
||||
name: PropTypes.string.isRequired,
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
export const SelectField = (props, context) => (
|
||||
<MaterialUISelectField
|
||||
{ ...props }
|
||||
value={context.state[props.name]}
|
||||
onChange={(event, index, value) => props.onChange(props.name, value)}
|
||||
/>
|
||||
);
|
||||
SelectField.contextTypes = { state: PropTypes.object };
|
||||
|
||||
export const TextField = (props, context) => (
|
||||
<MaterialUITextField
|
||||
{ ...props }
|
||||
value={_.get(context.state, props.name)}
|
||||
onChange={(event, value) => props.onChange(props.name, value)}
|
||||
/>
|
||||
);
|
||||
TextField.contextTypes = { state: PropTypes.object };
|
||||
|
||||
export const Checkbox = (props, context) => (
|
||||
<MaterialUICheckbox
|
||||
{ ...props }
|
||||
checked={_.get(context.state, props.name)}
|
||||
onCheck={(event, value) => props.onChange(props.name, value)}
|
||||
/>
|
||||
);
|
||||
Checkbox.contextTypes = { state: PropTypes.object };
|
175
src/interface/Settings.js
Normal file
175
src/interface/Settings.js
Normal file
@ -0,0 +1,175 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'proptypes';
|
||||
import _ from 'lodash';
|
||||
import baseSettings from '../settings/default.yml';
|
||||
import printerSettings from '../settings/printer.yml';
|
||||
import materialSettings from '../settings/material.yml';
|
||||
import qualitySettings from '../settings/quality.yml';
|
||||
import { Tabs, Tab } from 'material-ui/Tabs';
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
import injectSheet from 'react-jss';
|
||||
import { SettingsGroup, SelectField, TextField, Checkbox } from './FormComponents.js';
|
||||
import { grey500 } from 'material-ui/styles/colors';
|
||||
|
||||
const styles = {
|
||||
textFieldRow: {
|
||||
display: 'flex'
|
||||
},
|
||||
content: {
|
||||
maxHeight: '300px',
|
||||
overflowY: 'scroll'
|
||||
}
|
||||
};
|
||||
|
||||
const DEFAULT_PRINTER = 'ultimaker2';
|
||||
const DEFAULT_MATERIAL = 'pla';
|
||||
const DEFAULT_QUALITY = 'medium';
|
||||
|
||||
const DEFAULT_SETTINGS = {
|
||||
'printer': printerSettings,
|
||||
'quality': qualitySettings,
|
||||
'material': materialSettings
|
||||
};
|
||||
|
||||
class Settings extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
settings: {
|
||||
...baseSettings,
|
||||
...printerSettings[DEFAULT_PRINTER],
|
||||
...qualitySettings[DEFAULT_MATERIAL],
|
||||
...materialSettings[DEFAULT_MATERIAL],
|
||||
title: null
|
||||
},
|
||||
printer: DEFAULT_PRINTER,
|
||||
quality: DEFAULT_QUALITY,
|
||||
material: DEFAULT_MATERIAL
|
||||
};
|
||||
}
|
||||
|
||||
changeSettings = (fieldName, value) => {
|
||||
switch (fieldName) {
|
||||
case 'printer':
|
||||
case 'quality':
|
||||
case 'material':
|
||||
this.setState({
|
||||
[fieldName]: value,
|
||||
settings: {
|
||||
...this.state.settings,
|
||||
...DEFAULT_SETTINGS[fieldName][value],
|
||||
title: null
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
this.setState(_.set(this.state, fieldName, value));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
getChildContext() {
|
||||
return { state: this.state };
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
return (
|
||||
<Tabs>
|
||||
<Tab label="basic settings">
|
||||
<div className={classes.content}>
|
||||
<SelectField name="printer" floatingLabelText="Printer" fullWidth onChange={this.changeSettings}>
|
||||
{Object.entries(printerSettings).map(([value, { title }]) => (
|
||||
<MenuItem key={value} value={value} primaryText={title} />
|
||||
))}
|
||||
</SelectField>
|
||||
<SelectField name="quality" floatingLabelText="Quality" fullWidth onChange={this.changeSettings}>
|
||||
{Object.entries(qualitySettings).map(([value, { title }]) => (
|
||||
<MenuItem key={value} value={value} primaryText={title} />
|
||||
))}
|
||||
</SelectField>
|
||||
<SelectField name="material" floatingLabelText="Material" fullWidth onChange={this.changeSettings}>
|
||||
{Object.entries(materialSettings).map(([value, { title }]) => (
|
||||
<MenuItem key={value} value={value} primaryText={title} />
|
||||
))}
|
||||
</SelectField>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab label="advanced settings">
|
||||
<div className={classes.content}>
|
||||
<SettingsGroup name="Printer dimensions">
|
||||
<div className={classes.textFieldRow}>
|
||||
<TextField name="settings.dimensions.x" fullWidth floatingLabelText="X" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.dimensions.y" fullWidth floatingLabelText="Y" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.dimensions.z" fullWidth floatingLabelText="Z" type="number" onChange={this.changeSettings} />
|
||||
</div>
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Nozzle">
|
||||
<TextField name="settings.nozzleDiameter" fullWidth floatingLabelText="Diameter" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Bed">
|
||||
<TextField name="settings.bedTemperature" fullWidth floatingLabelText="Temperature" type="number" onChange={this.changeSettings} />
|
||||
<Checkbox name="settings.heatedBed" label="Heated" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Material">
|
||||
<TextField name="settings.filamentThickness" fullWidth floatingLabelText="Thickness" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.temperature" fullWidth floatingLabelText="Temperature" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Thickness">
|
||||
<TextField name="settings.thickness.top" fullWidth floatingLabelText="top" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.thickness.bottom" fullWidth floatingLabelText="bottom" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.thickness.shell" fullWidth floatingLabelText="shell" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Retraction">
|
||||
<Checkbox name="settings.retraction.enabled" label="Enabled" onChange={this.changeSettings} />
|
||||
<TextField name="settings.retraction.amount" fullWidth floatingLabelText="Amount" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.retraction.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.retraction.minDistance" fullWidth floatingLabelText="Min distance" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Travel">
|
||||
<TextField name="settings.travel.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<Checkbox name="settings.combing" label="Combing" />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Inner shell">
|
||||
<TextField name="settings.innerShell.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.innerShell.flowRate" fullWidth floatingLabelText="Flow rate" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Outer shell">
|
||||
<TextField name="settings.outerShell.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.outerShell.flowRate" fullWidth floatingLabelText="Flow rate" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Inner infill">
|
||||
<TextField name="settings.innerInfill.gridSize" fullWidth floatingLabelText="Grid size" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.innerInfill.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.innerInfill.flowRate" fullWidth floatingLabelText="Flow rate" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Outer infill">
|
||||
<TextField name="settings.outerInfill.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.outerInfill.flowRate" fullWidth floatingLabelText="Flow rate" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="Brim">
|
||||
<TextField name="settings.brim.offset" fullWidth floatingLabelText="Offset" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.brim.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.brim.flowRate" fullWidth floatingLabelText="Flow rate" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
<SettingsGroup name="First layer">
|
||||
<TextField name="settings.firstLayer.speed" fullWidth floatingLabelText="Speed" type="number" onChange={this.changeSettings} />
|
||||
<TextField name="settings.firstLayer.flowRate" fullWidth floatingLabelText="Flow rate" type="number" onChange={this.changeSettings} />
|
||||
</SettingsGroup>
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
}
|
||||
Settings.childContextTypes = {
|
||||
state: PropTypes.object
|
||||
};
|
||||
Settings.propTypes = {
|
||||
classes: PropTypes.objectOf(PropTypes.string),
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
export default injectSheet(styles)(Settings);
|
@ -1,20 +1,15 @@
|
||||
import React from 'react';
|
||||
import * as THREE from 'three';
|
||||
import { placeOnGround, createScene, createGcodeGeometry } from './utils.js';
|
||||
import baseSettings from '../settings/default.yml';
|
||||
import printerSettings from '../settings/printer.yml';
|
||||
import materialSettings from '../settings/material.yml';
|
||||
import qualitySettings from '../settings/quality.yml';
|
||||
import PropTypes from 'proptypes';
|
||||
import { placeOnGround, createScene, createGcodeGeometry } from './utils.js';
|
||||
import injectSheet from 'react-jss';
|
||||
import { sliceGeometry } from '../slicer.js';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import Paper from 'material-ui/Paper';
|
||||
import Slider from 'material-ui/Slider';
|
||||
import { Tabs, Tab } from 'material-ui/Tabs';
|
||||
import SelectField from 'material-ui/SelectField'
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
import { grey50 } from 'material-ui/styles/colors';
|
||||
import Settings from './Settings.js';
|
||||
import baseSettings from '../settings/default.yml';
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
@ -59,12 +54,10 @@ class Interface extends React.Component {
|
||||
this.state = {
|
||||
controlMode: 'translate',
|
||||
isSlicing: false,
|
||||
sliced: false,
|
||||
printer: props.defaultPrinter
|
||||
sliced: false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
const { canvas } = this.refs;
|
||||
const scene = createScene(canvas, this.props, this.state);
|
||||
@ -97,14 +90,9 @@ class Interface extends React.Component {
|
||||
};
|
||||
|
||||
slice = async () => {
|
||||
const { mesh, render, scene, control, printer } = this.state;
|
||||
const settings = {
|
||||
...baseSettings,
|
||||
...materialSettings.pla,
|
||||
...printerSettings[printer]
|
||||
};
|
||||
const { mesh, render, scene, control } = this.state;
|
||||
|
||||
const { dimensions } = settings;
|
||||
const { dimensions } = baseSettings;
|
||||
const centerX = dimensions.x / 2;
|
||||
const centerY = dimensions.y / 2;
|
||||
|
||||
@ -114,7 +102,7 @@ class Interface extends React.Component {
|
||||
this.setState({ isSlicing: true, progress: { actions: [], percentage: 0 } });
|
||||
|
||||
const matrix = new THREE.Matrix4().makeTranslation(centerY, 0, centerX).multiply(mesh.matrix);
|
||||
const gcode = await sliceGeometry(settings, geometry, matrix, false, true, ({ progress }) => {
|
||||
const gcode = await sliceGeometry(baseSettings, geometry, matrix, false, true, ({ progress }) => {
|
||||
this.setState({ progress: {
|
||||
actions: [...this.state.progress.actions, progress.action],
|
||||
percentage: progress.done / progress.total
|
||||
@ -155,7 +143,7 @@ class Interface extends React.Component {
|
||||
|
||||
render() {
|
||||
const { width, height, classes, onCompleteActions, printers, materials, quality } = this.props;
|
||||
const { sliced, isSlicing, progress, gcode, controlMode, printer } = this.state;
|
||||
const { sliced, isSlicing, progress, gcode, controlMode } = this.state;
|
||||
|
||||
return (
|
||||
<div style={{ width, height }} className={classes.container}>
|
||||
@ -178,31 +166,7 @@ class Interface extends React.Component {
|
||||
/>
|
||||
</div>}
|
||||
{!sliced && <Paper className={classes.sliceBar}>
|
||||
<Tabs>
|
||||
<Tab label="basic settings">
|
||||
<div>
|
||||
<SelectField name="printer" value={printer} floatingLabelText="Printer" fullWidth>
|
||||
{Object.entries(printers).map(([value, { title }]) => (
|
||||
<MenuItem key={value} value={value} primaryText={title} />
|
||||
))}
|
||||
</SelectField>
|
||||
<SelectField value="medium" floatingLabelText="Quality" fullWidth>
|
||||
{Object.entries(quality).map(([value, { title }]) => (
|
||||
<MenuItem key={value} value={value} primaryText={title} />
|
||||
))}
|
||||
</SelectField>
|
||||
<SelectField value="pla" floatingLabelText="Material" fullWidth>
|
||||
{Object.entries(materials).map(([value, { title }]) => (
|
||||
<MenuItem key={value} value={value} primaryText={title} />
|
||||
))}
|
||||
</SelectField>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab label="advanced settings">
|
||||
<div>
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<Settings printers={printers} />
|
||||
<RaisedButton className={classes.button} fullWidth disabled={isSlicing} onTouchTap={this.slice} primary label="slice" />
|
||||
</Paper>}
|
||||
{sliced && <Paper className={classes.sliceBar}>
|
||||
@ -223,13 +187,7 @@ class Interface extends React.Component {
|
||||
}
|
||||
Interface.defaultProps = {
|
||||
width: 720,
|
||||
height: 480,
|
||||
printers: printerSettings,
|
||||
defaultPrinter: 'ultimaker2',
|
||||
quality: qualitySettings,
|
||||
defaultQuality: 'medium',
|
||||
materials: materialSettings,
|
||||
defaultMaterial: 'pla',
|
||||
height: 480
|
||||
};
|
||||
Interface.propTypes = {
|
||||
geometry(props, propName) {
|
||||
@ -240,12 +198,6 @@ Interface.propTypes = {
|
||||
width: PropTypes.number.isRequired,
|
||||
height: PropTypes.number.isRequired,
|
||||
classes: PropTypes.objectOf(PropTypes.string),
|
||||
printers: PropTypes.object.isRequired,
|
||||
defaultPrinter: PropTypes.string.isRequired,
|
||||
quality: PropTypes.object.isRequired,
|
||||
defaultQuality: PropTypes.string.isRequired,
|
||||
materials: PropTypes.object.isRequired,
|
||||
defaultMaterial: PropTypes.string.isRequired,
|
||||
onCompleteActions: PropTypes.arrayOf(PropTypes.shape({ title: PropTypes.string, callback: PropTypes.func })).isRequired,
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as THREE from 'three';
|
||||
import 'three/examples/js/controls/EditorControls';
|
||||
import 'three/examples/js/controls/TransformControls';
|
||||
import printerSettings from '../settings/printer.yml';
|
||||
|
||||
export function placeOnGround(mesh) {
|
||||
const boundingBox = new THREE.Box3().setFromObject(mesh);
|
||||
@ -10,8 +11,8 @@ export function placeOnGround(mesh) {
|
||||
}
|
||||
|
||||
export function createScene(canvas, props, state) {
|
||||
const { width, height, printers, geometry } = props;
|
||||
const { controlMode, printer } = state;
|
||||
const { width, height, geometry } = props;
|
||||
const { controlMode } = state;
|
||||
|
||||
// center geometry
|
||||
geometry.computeBoundingBox();
|
||||
@ -68,7 +69,7 @@ export function createScene(canvas, props, state) {
|
||||
box.material.color.setHex(0x72bcd4);
|
||||
scene.add(box);
|
||||
|
||||
const { dimensions } = printers[printer];
|
||||
const { dimensions } = printerSettings['ultimaker2'];
|
||||
box.scale.set(dimensions.y, dimensions.z, dimensions.x);
|
||||
|
||||
render();
|
||||
|
Loading…
Reference in New Issue
Block a user