2018-01-18 12:06:14 +01:00
|
|
|
import * as THREE from 'three';
|
2017-11-13 02:47:53 +01:00
|
|
|
import _ from 'lodash';
|
2017-11-11 20:23:45 +01:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'proptypes';
|
2018-01-15 15:17:38 +01:00
|
|
|
import { centerGeometry, placeOnGround, createScene, fetchProgress, slice, TabTemplate } from './utils.js';
|
2017-11-11 20:23:45 +01:00
|
|
|
import injectSheet from 'react-jss';
|
2017-11-12 16:58:59 +01:00
|
|
|
import RaisedButton from 'material-ui/RaisedButton';
|
2017-12-04 19:31:15 +01:00
|
|
|
import FlatButton from 'material-ui/FlatButton';
|
2017-11-12 16:58:59 +01:00
|
|
|
import Slider from 'material-ui/Slider';
|
2017-12-04 15:08:29 +01:00
|
|
|
import LinearProgress from 'material-ui/LinearProgress';
|
2017-12-04 17:51:56 +01:00
|
|
|
import { grey50, grey300, grey800, red500 } from 'material-ui/styles/colors';
|
2017-12-24 17:18:33 +01:00
|
|
|
import Popover from 'material-ui/Popover/Popover';
|
|
|
|
import Menu from 'material-ui/Menu';
|
|
|
|
import MenuItem from 'material-ui/MenuItem';
|
2017-12-04 17:44:08 +01:00
|
|
|
import { Tabs, Tab } from 'material-ui/Tabs';
|
2017-11-13 02:09:39 +01:00
|
|
|
import Settings from './Settings.js';
|
2017-11-13 12:42:35 +01:00
|
|
|
import ReactResizeDetector from 'react-resize-detector';
|
2018-01-15 15:17:38 +01:00
|
|
|
import JSONToSketchData from 'doodle3d-core/shape/JSONToSketchData';
|
|
|
|
import createSceneData from 'doodle3d-core/d3/createSceneData.js';
|
|
|
|
import { generateExportMesh } from 'doodle3d-core/utils/exportUtils.js';
|
2018-01-17 13:26:30 +01:00
|
|
|
import muiThemeable from 'material-ui/styles/muiThemeable';
|
2018-01-17 15:53:03 +01:00
|
|
|
import Dialog from 'material-ui/Dialog';
|
2017-11-13 02:47:53 +01:00
|
|
|
|
2017-12-04 15:08:29 +01:00
|
|
|
const MAX_FULLSCREEN_WIDTH = 720;
|
|
|
|
|
2017-11-11 20:23:45 +01:00
|
|
|
const styles = {
|
|
|
|
container: {
|
2017-11-12 18:41:00 +01:00
|
|
|
position: 'relative',
|
2017-11-13 12:42:35 +01:00
|
|
|
display: 'flex',
|
|
|
|
height: '100%',
|
2017-12-04 17:51:56 +01:00
|
|
|
backgroundColor: grey50,
|
|
|
|
color: grey800,
|
2017-12-04 15:08:29 +01:00
|
|
|
overflow: 'hidden',
|
|
|
|
fontFamily: 'roboto, sans-serif'
|
2017-11-11 20:23:45 +01:00
|
|
|
},
|
|
|
|
controlBar: {
|
|
|
|
position: 'absolute',
|
2017-11-12 16:58:59 +01:00
|
|
|
bottom: '10px',
|
|
|
|
left: '10px'
|
2017-11-11 20:23:45 +01:00
|
|
|
},
|
2017-11-13 12:42:35 +01:00
|
|
|
d3View: {
|
2017-12-04 15:08:29 +01:00
|
|
|
flexGrow: 1,
|
|
|
|
flexBasis: 0
|
2017-11-13 12:42:35 +01:00
|
|
|
},
|
|
|
|
canvas: {
|
|
|
|
position: 'absolute'
|
|
|
|
},
|
2017-12-04 17:44:08 +01:00
|
|
|
settingsBar: {
|
2017-12-04 15:08:29 +01:00
|
|
|
display: 'flex',
|
|
|
|
flexDirection: 'column',
|
2018-01-17 12:21:36 +01:00
|
|
|
maxWidth: '320px',
|
2017-12-04 15:08:29 +01:00
|
|
|
boxSizing: 'border-box',
|
2018-01-17 12:21:36 +01:00
|
|
|
padding: '10px 20px',
|
2017-11-13 12:42:35 +01:00
|
|
|
backgroundColor: 'white',
|
|
|
|
borderLeft: `1px solid ${grey300}`
|
2017-11-12 12:34:50 +01:00
|
|
|
},
|
|
|
|
sliceActions: {
|
2017-12-04 15:08:29 +01:00
|
|
|
flexShrink: 0,
|
|
|
|
},
|
2018-01-17 16:52:14 +01:00
|
|
|
sliceInfo: {
|
|
|
|
margin: '10px 0'
|
|
|
|
},
|
2017-12-04 15:08:29 +01:00
|
|
|
sliceButtons: {
|
|
|
|
justifyContent: 'flex-end',
|
|
|
|
display: 'flex'
|
2017-11-12 18:41:00 +01:00
|
|
|
},
|
|
|
|
button: {
|
2017-12-04 15:08:29 +01:00
|
|
|
margin: '5px 0 5px 5px'
|
2017-11-13 11:01:57 +01:00
|
|
|
},
|
|
|
|
controlButton: {
|
|
|
|
marginRight: '2px'
|
2017-12-04 15:08:29 +01:00
|
|
|
},
|
|
|
|
buttonContainer: {
|
|
|
|
width: '100%',
|
|
|
|
padding: '10px'
|
|
|
|
},
|
|
|
|
error: {
|
|
|
|
color: red500
|
2017-12-04 17:51:56 +01:00
|
|
|
},
|
|
|
|
title: {
|
2018-01-17 12:23:03 +01:00
|
|
|
userSelect: 'none',
|
2018-01-17 09:11:15 +01:00
|
|
|
position: 'absolute',
|
|
|
|
left: '10px'
|
2018-01-17 08:40:48 +01:00
|
|
|
},
|
|
|
|
detail: {
|
2018-01-17 12:23:03 +01:00
|
|
|
userSelect: 'none',
|
2018-01-17 08:40:48 +01:00
|
|
|
marginBottom: '10px'
|
2017-11-11 20:23:45 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class Interface extends React.Component {
|
2017-11-16 14:54:47 +01:00
|
|
|
static propTypes = {
|
2018-01-17 17:18:28 +01:00
|
|
|
fileUrl: PropTypes.string,
|
|
|
|
mesh: PropTypes.shape({ isMesh: PropTypes.oneOf([true]) }),
|
2017-11-16 14:54:47 +01:00
|
|
|
classes: PropTypes.objectOf(PropTypes.string),
|
2017-12-04 19:31:15 +01:00
|
|
|
pixelRatio: PropTypes.number.isRequired,
|
2017-12-05 13:03:00 +01:00
|
|
|
onCancel: PropTypes.func,
|
2018-01-17 13:26:30 +01:00
|
|
|
name: PropTypes.string.isRequired,
|
2018-01-17 17:42:58 +01:00
|
|
|
muiTheme: PropTypes.object.isRequired,
|
|
|
|
allowDragDrop: PropTypes.bool.isRequired
|
2017-11-16 14:54:47 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static defaultProps = {
|
2017-12-05 13:03:00 +01:00
|
|
|
pixelRatio: 1,
|
2018-01-17 17:42:58 +01:00
|
|
|
name: 'Doodle3D',
|
|
|
|
allowDragDrop: true
|
2017-11-16 14:54:47 +01:00
|
|
|
};
|
|
|
|
|
2017-11-12 01:41:05 +01:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-01-15 15:17:38 +01:00
|
|
|
|
2018-01-16 17:57:34 +01:00
|
|
|
const scene = createScene(this.props);
|
2017-11-12 01:41:05 +01:00
|
|
|
this.state = {
|
2018-01-16 17:57:34 +01:00
|
|
|
scene,
|
|
|
|
settings: null,
|
2017-12-04 17:44:08 +01:00
|
|
|
showFullScreen: false,
|
2017-11-12 16:58:59 +01:00
|
|
|
isSlicing: false,
|
2017-12-04 15:08:29 +01:00
|
|
|
error: null,
|
2018-01-17 23:53:40 +01:00
|
|
|
mesh: null,
|
2018-01-17 08:40:48 +01:00
|
|
|
objectDimensions: '0x0x0mm',
|
2018-01-17 17:18:28 +01:00
|
|
|
popover: { open: false, element: null },
|
2018-01-17 15:55:21 +01:00
|
|
|
openUrlDialog: { open: false, url: '' }
|
2017-11-12 01:41:05 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-11-11 20:23:45 +01:00
|
|
|
componentDidMount() {
|
|
|
|
const { canvas } = this.refs;
|
2018-01-16 17:57:34 +01:00
|
|
|
const { scene } = this.state;
|
|
|
|
scene.updateCanvas(canvas);
|
2018-01-15 15:17:38 +01:00
|
|
|
|
2018-01-17 17:18:28 +01:00
|
|
|
const { mesh, fileUrl } = this.props;
|
|
|
|
if (mesh) {
|
|
|
|
this.updateMesh(mesh, scene);
|
|
|
|
} else if (fileUrl) {
|
2018-01-17 17:42:58 +01:00
|
|
|
this.loadFile(fileUrl);
|
2018-01-15 15:17:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-17 17:42:58 +01:00
|
|
|
loadFile = (fileUrl) => {
|
|
|
|
fetch(fileUrl)
|
|
|
|
.then(resonse => resonse.json())
|
|
|
|
.then(json => JSONToSketchData(json))
|
|
|
|
.then(file => createSceneData(file))
|
2018-01-18 12:06:14 +01:00
|
|
|
.then(sketch => generateExportMesh(sketch, { offsetSingleWalls: false, matrix: new THREE.Matrix4() }))
|
2018-01-17 17:42:58 +01:00
|
|
|
.then(mesh => this.updateMesh(mesh));
|
|
|
|
};
|
|
|
|
|
|
|
|
updateMesh(mesh, scene = this.state.scene) {
|
2018-01-15 15:17:38 +01:00
|
|
|
scene.mesh.geometry = mesh.geometry;
|
|
|
|
centerGeometry(scene.mesh);
|
|
|
|
placeOnGround(scene.mesh);
|
2018-01-17 08:40:48 +01:00
|
|
|
this.calculateDimensions();
|
2018-01-15 15:17:38 +01:00
|
|
|
scene.render();
|
2018-01-17 23:53:40 +01:00
|
|
|
|
|
|
|
this.setState({ mesh });
|
2017-11-11 20:23:45 +01:00
|
|
|
}
|
|
|
|
|
2017-12-04 15:08:29 +01:00
|
|
|
componentWillUnmount() {
|
2018-01-15 14:21:42 +01:00
|
|
|
const { scene: { editorControls, mesh: { material } }, renderer } = this.state;
|
2017-12-19 12:38:58 +01:00
|
|
|
editorControls.dispose();
|
|
|
|
material.dispose();
|
|
|
|
renderer.dispose();
|
2017-12-04 15:08:29 +01:00
|
|
|
}
|
|
|
|
|
2017-11-11 20:23:45 +01:00
|
|
|
resetMesh = () => {
|
2018-01-17 17:18:28 +01:00
|
|
|
const { scene: { mesh, render }, isSlicing } = this.state;
|
|
|
|
if (isSlicing) return;
|
2017-11-11 20:23:45 +01:00
|
|
|
if (mesh) {
|
|
|
|
mesh.position.set(0, 0, 0);
|
|
|
|
mesh.scale.set(1, 1, 1);
|
|
|
|
mesh.rotation.set(0, 0, 0);
|
|
|
|
mesh.updateMatrix();
|
|
|
|
placeOnGround(mesh);
|
2018-01-17 08:40:48 +01:00
|
|
|
this.calculateDimensions();
|
2017-11-11 20:23:45 +01:00
|
|
|
render();
|
|
|
|
}
|
2017-11-12 01:04:26 +01:00
|
|
|
};
|
|
|
|
|
2017-12-04 15:08:29 +01:00
|
|
|
scaleUp = () => this.scaleMesh(0.9);
|
|
|
|
scaleDown = () => this.scaleMesh(1.0 / 0.9);
|
|
|
|
scaleMesh = (factor) => {
|
2018-01-17 17:18:28 +01:00
|
|
|
const { scene: { mesh, render }, isSlicing } = this.state;
|
|
|
|
if (isSlicing) return;
|
2017-12-04 15:08:29 +01:00
|
|
|
if (mesh) {
|
|
|
|
mesh.scale.multiplyScalar(factor);
|
|
|
|
mesh.updateMatrix();
|
|
|
|
placeOnGround(mesh);
|
2018-01-17 08:40:48 +01:00
|
|
|
this.calculateDimensions();
|
2017-12-04 15:08:29 +01:00
|
|
|
render();
|
|
|
|
}
|
|
|
|
};
|
2017-11-12 01:04:26 +01:00
|
|
|
|
2018-01-18 12:06:14 +01:00
|
|
|
rotateX = () => this.rotate(new THREE.Vector3(0, 0, 1), Math.PI / 2.0);
|
|
|
|
rotateY = () => this.rotate(new THREE.Vector3(1, 0, 0), Math.PI / 2.0);
|
|
|
|
rotateZ = () => this.rotate(new THREE.Vector3(0, 1, 0), Math.PI / 2.0);
|
2017-12-05 11:10:17 +01:00
|
|
|
rotate = (axis, angle) => {
|
2018-01-17 17:18:28 +01:00
|
|
|
const { scene: { mesh, render }, isSlicing } = this.state;
|
|
|
|
if (isSlicing) return;
|
2017-12-04 15:08:29 +01:00
|
|
|
if (mesh) {
|
2017-12-06 11:54:09 +01:00
|
|
|
mesh.rotateOnWorldAxis(axis, angle);
|
2017-12-04 15:08:29 +01:00
|
|
|
placeOnGround(mesh);
|
2018-01-17 08:40:48 +01:00
|
|
|
this.calculateDimensions();
|
2017-12-04 15:08:29 +01:00
|
|
|
render();
|
|
|
|
}
|
2017-11-12 01:04:26 +01:00
|
|
|
};
|
2017-11-11 20:23:45 +01:00
|
|
|
|
2017-12-24 17:18:33 +01:00
|
|
|
slice = async (target) => {
|
2018-01-17 17:18:28 +01:00
|
|
|
const { isSlicing, settings, mesh, scene: { material, mesh: { matrix } } } = this.state;
|
2018-01-15 15:17:38 +01:00
|
|
|
const { name } = this.props;
|
2017-11-12 00:46:00 +01:00
|
|
|
|
2018-01-17 17:18:28 +01:00
|
|
|
if (isSlicing) return;
|
|
|
|
if (!mesh) {
|
|
|
|
this.setState({ error: 'there is no file to slice' });
|
|
|
|
return;
|
|
|
|
}
|
2017-11-12 00:46:00 +01:00
|
|
|
|
2017-12-24 17:18:33 +01:00
|
|
|
this.closePopover();
|
|
|
|
this.setState({ isSlicing: true, progress: { action: '', percentage: 0, step: 0 }, error: null });
|
2017-11-12 12:34:50 +01:00
|
|
|
|
2018-01-18 12:06:14 +01:00
|
|
|
const exportMesh = new THREE.Mesh(mesh.geometry, mesh.material);
|
2017-12-19 12:38:58 +01:00
|
|
|
exportMesh.applyMatrix(matrix);
|
|
|
|
|
2017-12-04 15:08:29 +01:00
|
|
|
try {
|
2018-01-16 17:57:34 +01:00
|
|
|
const updateProgres = progress => this.setState({ progress: { ...this.state.progress, ...progress } });
|
|
|
|
await slice(target, name, exportMesh, settings, updateProgres);
|
2017-12-04 15:08:29 +01:00
|
|
|
} catch (error) {
|
2018-01-17 15:53:03 +01:00
|
|
|
if (error.code === 3) {
|
|
|
|
this.setState({ openUrlDialog: { open: true, url: error.url } });
|
|
|
|
} else {
|
|
|
|
this.setState({ error: error.message });
|
|
|
|
throw error;
|
|
|
|
}
|
2017-12-18 16:37:03 +01:00
|
|
|
} finally {
|
|
|
|
this.setState({ isSlicing: false });
|
2017-12-04 15:08:29 +01:00
|
|
|
}
|
2017-11-12 00:11:05 +01:00
|
|
|
};
|
|
|
|
|
2017-12-24 17:18:33 +01:00
|
|
|
openPopover = (event) => {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
popover: {
|
|
|
|
element: event.currentTarget,
|
|
|
|
open: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
closePopover = () => {
|
|
|
|
this.setState({
|
|
|
|
popover: {
|
|
|
|
element: null,
|
|
|
|
open: false
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-12-04 17:44:08 +01:00
|
|
|
componentDidUpdate() {
|
2018-01-15 14:21:42 +01:00
|
|
|
const { scene: { updateCanvas } } = this.state;
|
2017-12-04 17:44:08 +01:00
|
|
|
const { canvas } = this.refs;
|
|
|
|
if (updateCanvas && canvas) updateCanvas(canvas);
|
|
|
|
}
|
|
|
|
|
2017-12-04 15:08:29 +01:00
|
|
|
onResize3dView = (width, height) => {
|
2017-11-13 12:42:35 +01:00
|
|
|
window.requestAnimationFrame(() => {
|
2018-01-15 14:21:42 +01:00
|
|
|
const { scene: { setSize } } = this.state;
|
2017-11-13 12:42:35 +01:00
|
|
|
const { pixelRatio } = this.props;
|
2017-12-19 12:38:58 +01:00
|
|
|
if (setSize) setSize(width, height, pixelRatio);
|
2017-11-13 12:42:35 +01:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-12-04 15:08:29 +01:00
|
|
|
onResizeContainer = (width) => {
|
2017-12-04 17:44:08 +01:00
|
|
|
this.setState({ showFullScreen: width > MAX_FULLSCREEN_WIDTH });
|
2017-12-04 15:08:29 +01:00
|
|
|
};
|
|
|
|
|
2018-01-16 17:57:34 +01:00
|
|
|
onChangeSettings = (settings) => {
|
|
|
|
const { scene: { box, render } } = this.state;
|
|
|
|
|
|
|
|
let changed = false;
|
|
|
|
if (!this.state.settings || this.state.settings.dimensions !== settings.dimensions) {
|
|
|
|
box.scale.set(settings.dimensions.y, settings.dimensions.z, settings.dimensions.x);
|
|
|
|
box.updateMatrix();
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
if (changed) render();
|
|
|
|
|
|
|
|
this.setState({ settings, error: null });
|
|
|
|
};
|
|
|
|
|
2018-01-17 08:40:48 +01:00
|
|
|
calculateDimensions = () => {
|
|
|
|
const { scene: { mesh } } = this.state;
|
2018-01-18 12:06:14 +01:00
|
|
|
const { x, y, z } = new THREE.Box3().setFromObject(mesh).getSize();
|
2018-01-17 08:40:48 +01:00
|
|
|
this.setState({ objectDimensions: `${Math.round(x)}x${Math.round(y)}x${Math.round(z)}mm` });
|
|
|
|
};
|
|
|
|
|
2018-01-17 17:42:58 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-11 20:23:45 +01:00
|
|
|
render() {
|
2018-01-16 17:57:34 +01:00
|
|
|
const { classes, onCancel } = this.props;
|
2018-01-17 17:18:28 +01:00
|
|
|
const { isSlicing, progress, showFullScreen, error, objectDimensions, openUrlDialog } = this.state;
|
2017-12-04 15:08:29 +01:00
|
|
|
|
2017-12-19 12:38:58 +01:00
|
|
|
const style = { ...(showFullScreen ? {} : { maxWidth: 'inherit', width: '100%', height: '100%' }) };
|
2017-12-04 15:08:29 +01:00
|
|
|
|
2017-12-04 17:44:08 +01:00
|
|
|
const settingsPanel = (
|
2017-12-19 12:38:58 +01:00
|
|
|
<div className={classes.settingsBar} style={style}>
|
2017-12-04 17:44:08 +01:00
|
|
|
<Settings
|
2018-01-17 17:18:28 +01:00
|
|
|
disabled={isSlicing}
|
2017-12-04 17:44:08 +01:00
|
|
|
onChange={this.onChangeSettings}
|
|
|
|
/>
|
|
|
|
<div className={classes.sliceActions}>
|
2018-01-17 16:52:14 +01:00
|
|
|
<div className={classes.sliceInfo}>
|
|
|
|
{error && <p className={classes.error}>{error}</p>}
|
|
|
|
{isSlicing && <p>{progress.action}</p>}
|
|
|
|
{isSlicing && <LinearProgress mode="determinate" value={progress.percentage * 100.0} />}
|
|
|
|
</div>
|
2017-12-04 17:44:08 +01:00
|
|
|
<div className={classes.sliceButtons}>
|
2017-12-04 19:31:15 +01:00
|
|
|
{onCancel && <RaisedButton
|
|
|
|
label="Cancel"
|
|
|
|
className={`${classes.button}`}
|
|
|
|
onTouchTap={onCancel}
|
|
|
|
/>}
|
2017-12-04 17:44:08 +01:00
|
|
|
<RaisedButton
|
|
|
|
label="Print"
|
2017-12-24 17:18:33 +01:00
|
|
|
ref="button"
|
2017-12-04 17:44:08 +01:00
|
|
|
primary
|
|
|
|
className={`${classes.button}`}
|
2017-12-24 17:18:33 +01:00
|
|
|
onTouchTap={this.openPopover}
|
2018-01-17 17:18:28 +01:00
|
|
|
disabled={isSlicing}
|
2017-12-04 17:44:08 +01:00
|
|
|
/>
|
2017-12-24 17:18:33 +01:00
|
|
|
<Popover
|
|
|
|
open={this.state.popover.open}
|
|
|
|
anchorEl={this.state.popover.element}
|
|
|
|
anchorOrigin={{horizontal: 'left', vertical: 'bottom'}}
|
|
|
|
targetOrigin={{horizontal: 'left', vertical: 'bottom'}}
|
|
|
|
onRequestClose={this.closePopover}
|
|
|
|
>
|
|
|
|
<Menu>
|
|
|
|
<MenuItem primaryText="Send over WiFi" onTouchTap={() => this.slice('WIFI')} />
|
|
|
|
<MenuItem primaryText="Download GCode" onTouchTap={() => this.slice('DOWNLOAD')} />
|
|
|
|
</Menu>
|
|
|
|
</Popover>
|
2017-12-04 15:08:29 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
2017-11-11 20:23:45 +01:00
|
|
|
</div>
|
|
|
|
);
|
2017-12-04 17:44:08 +01:00
|
|
|
|
|
|
|
const d3Panel = (
|
|
|
|
<div className={classes.d3View}>
|
|
|
|
<ReactResizeDetector handleWidth handleHeight onResize={this.onResize3dView} />
|
|
|
|
<canvas className={classes.canvas} ref="canvas" />
|
2017-12-24 14:52:24 +01:00
|
|
|
<div className={classes.controlBar}>
|
2018-01-17 08:40:48 +01:00
|
|
|
<div className={classes.detail}>
|
|
|
|
<p>Dimensions: {objectDimensions}</p>
|
|
|
|
</div>
|
2018-01-17 17:18:28 +01:00
|
|
|
<RaisedButton disabled={isSlicing} className={classes.controlButton} onTouchTap={this.resetMesh} label="reset" />
|
|
|
|
<RaisedButton disabled={isSlicing} className={classes.controlButton} onTouchTap={this.scaleUp} label="scale down" />
|
|
|
|
<RaisedButton disabled={isSlicing} className={classes.controlButton} onTouchTap={this.scaleDown} label="scale up" />
|
|
|
|
<RaisedButton disabled={isSlicing} className={classes.controlButton} onTouchTap={this.rotateX} label="rotate x" />
|
|
|
|
<RaisedButton disabled={isSlicing} className={classes.controlButton} onTouchTap={this.rotateY} label="rotate y" />
|
|
|
|
<RaisedButton disabled={isSlicing} className={classes.controlButton} onTouchTap={this.rotateZ} label="rotate z" />
|
2017-12-24 14:52:24 +01:00
|
|
|
</div>
|
2017-12-04 17:44:08 +01:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
2018-01-17 15:53:03 +01:00
|
|
|
const closeDialog = () => this.setState({ openUrlDialog: { open: false, url: '' } });
|
|
|
|
|
|
|
|
const dialog = (
|
|
|
|
<Dialog
|
|
|
|
open={openUrlDialog.open}
|
|
|
|
title="Open with Doodle3D Connect"
|
|
|
|
contentStyle={{ maxWidth: '400px' }}
|
|
|
|
actions={[
|
|
|
|
<FlatButton
|
|
|
|
label="Cancel"
|
|
|
|
onTouchTap={closeDialog}
|
|
|
|
/>,
|
2018-01-17 16:15:13 +01:00
|
|
|
<RaisedButton
|
2018-01-17 15:53:03 +01:00
|
|
|
label="Open"
|
|
|
|
primary
|
|
|
|
onTouchTap={() => {
|
|
|
|
window.open(openUrlDialog.url, '_blank');
|
|
|
|
closeDialog();
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
<p>Click 'Open' to continue to Doodle3D Connect</p>
|
|
|
|
</Dialog>
|
|
|
|
)
|
|
|
|
|
2017-12-04 17:44:08 +01:00
|
|
|
if (showFullScreen) {
|
|
|
|
return (
|
2018-01-17 17:42:58 +01:00
|
|
|
<div
|
|
|
|
className={classes.container}
|
|
|
|
ref={(container) => {
|
|
|
|
if (container) {
|
|
|
|
container.addEventListener('dragover', event => event.preventDefault());
|
|
|
|
container.addEventListener('drop', this.onDrop);
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
>
|
2017-12-04 17:44:08 +01:00
|
|
|
<ReactResizeDetector handleWidth handleHeight onResize={this.onResizeContainer} />
|
2018-01-17 09:11:15 +01:00
|
|
|
<h1 className={classes.title}>Doodle3D Slicer</h1>
|
2017-12-04 17:44:08 +01:00
|
|
|
{d3Panel}
|
|
|
|
{settingsPanel}
|
2018-01-17 15:53:03 +01:00
|
|
|
{dialog}
|
2017-12-04 17:44:08 +01:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return (
|
2018-01-17 17:42:58 +01:00
|
|
|
<div
|
|
|
|
className={classes.container}
|
|
|
|
ref={(container) => {
|
|
|
|
if (container) {
|
|
|
|
container.addEventListener('dragover', event => event.preventDefault());
|
|
|
|
container.addEventListener('drop', this.onDrop);
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
>
|
2017-12-04 17:44:08 +01:00
|
|
|
<ReactResizeDetector handleWidth handleHeight onResize={this.onResizeContainer} />
|
|
|
|
<Tabs
|
|
|
|
style={{ width: '100%', display: 'flex', flexDirection: 'column' }}
|
|
|
|
tabItemContainerStyle={{ flexShrink: 0 }}
|
|
|
|
contentContainerStyle={{ flexGrow: 1, display: 'flex' }}
|
|
|
|
tabTemplateStyle={{ display: 'flex' }}
|
|
|
|
tabTemplate={TabTemplate}
|
|
|
|
>
|
|
|
|
<Tab label="Settings">
|
|
|
|
{settingsPanel}
|
|
|
|
</Tab>
|
2017-12-04 17:45:28 +01:00
|
|
|
<Tab label="Edit Model">
|
2017-12-04 17:44:08 +01:00
|
|
|
{d3Panel}
|
|
|
|
</Tab>
|
|
|
|
</Tabs>
|
2018-01-17 15:53:03 +01:00
|
|
|
{dialog}
|
2017-12-04 17:44:08 +01:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2017-11-11 20:23:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-17 13:26:30 +01:00
|
|
|
export default muiThemeable()(injectSheet(styles)(Interface));
|