remove redux logger for production
parent
662ced6edd
commit
4a3c0bd1e4
Binary file not shown.
|
@ -0,0 +1,209 @@
|
||||||
|
import {
|
||||||
|
Vector3
|
||||||
|
} from '../../../build/three.module.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage:
|
||||||
|
* var exporter = new STLExporter();
|
||||||
|
*
|
||||||
|
* // second argument is a list of options
|
||||||
|
* var data = exporter.parse( mesh, { binary: true } );
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var STLExporter = function () {};
|
||||||
|
|
||||||
|
STLExporter.prototype = {
|
||||||
|
|
||||||
|
constructor: STLExporter,
|
||||||
|
|
||||||
|
parse: function ( scene, options ) {
|
||||||
|
|
||||||
|
if ( options === undefined ) options = {};
|
||||||
|
|
||||||
|
var binary = options.binary !== undefined ? options.binary : false;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
var objects = [];
|
||||||
|
var triangles = 0;
|
||||||
|
|
||||||
|
scene.traverse( function ( object ) {
|
||||||
|
|
||||||
|
if ( object.isMesh ) {
|
||||||
|
|
||||||
|
var geometry = object.geometry;
|
||||||
|
|
||||||
|
if ( geometry.isBufferGeometry !== true ) {
|
||||||
|
|
||||||
|
throw new Error( 'THREE.STLExporter: Geometry is not of type THREE.BufferGeometry.' );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = geometry.index;
|
||||||
|
var positionAttribute = geometry.getAttribute( 'position' );
|
||||||
|
|
||||||
|
triangles += ( index !== null ) ? ( index.count / 3 ) : ( positionAttribute.count / 3 );
|
||||||
|
|
||||||
|
objects.push( {
|
||||||
|
object3d: object,
|
||||||
|
geometry: geometry
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
var output;
|
||||||
|
var offset = 80; // skip header
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
|
||||||
|
var arrayBuffer = new ArrayBuffer( bufferLength );
|
||||||
|
output = new DataView( arrayBuffer );
|
||||||
|
output.setUint32( offset, triangles, true ); offset += 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output = '';
|
||||||
|
output += 'solid exported\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var vA = new Vector3();
|
||||||
|
var vB = new Vector3();
|
||||||
|
var vC = new Vector3();
|
||||||
|
var cb = new Vector3();
|
||||||
|
var ab = new Vector3();
|
||||||
|
var normal = new Vector3();
|
||||||
|
|
||||||
|
for ( var i = 0, il = objects.length; i < il; i ++ ) {
|
||||||
|
|
||||||
|
var object = objects[ i ].object3d;
|
||||||
|
var geometry = objects[ i ].geometry;
|
||||||
|
|
||||||
|
var index = geometry.index;
|
||||||
|
var positionAttribute = geometry.getAttribute( 'position' );
|
||||||
|
|
||||||
|
if ( index !== null ) {
|
||||||
|
|
||||||
|
// indexed geometry
|
||||||
|
|
||||||
|
for ( var j = 0; j < index.count; j += 3 ) {
|
||||||
|
|
||||||
|
var a = index.getX( j + 0 );
|
||||||
|
var b = index.getX( j + 1 );
|
||||||
|
var c = index.getX( j + 2 );
|
||||||
|
|
||||||
|
writeFace( a, b, c, positionAttribute, object );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// non-indexed geometry
|
||||||
|
|
||||||
|
for ( var j = 0; j < positionAttribute.count; j += 3 ) {
|
||||||
|
|
||||||
|
var a = j + 0;
|
||||||
|
var b = j + 1;
|
||||||
|
var c = j + 2;
|
||||||
|
|
||||||
|
writeFace( a, b, c, positionAttribute, object );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( binary === false ) {
|
||||||
|
|
||||||
|
output += 'endsolid exported\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
function writeFace( a, b, c, positionAttribute, object ) {
|
||||||
|
|
||||||
|
vA.fromBufferAttribute( positionAttribute, a );
|
||||||
|
vB.fromBufferAttribute( positionAttribute, b );
|
||||||
|
vC.fromBufferAttribute( positionAttribute, c );
|
||||||
|
|
||||||
|
if ( object.isSkinnedMesh === true ) {
|
||||||
|
|
||||||
|
object.boneTransform( a, vA );
|
||||||
|
object.boneTransform( b, vB );
|
||||||
|
object.boneTransform( c, vC );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vA.applyMatrix4( object.matrixWorld );
|
||||||
|
vB.applyMatrix4( object.matrixWorld );
|
||||||
|
vC.applyMatrix4( object.matrixWorld );
|
||||||
|
|
||||||
|
writeNormal( vA, vB, vC );
|
||||||
|
|
||||||
|
writeVertex( vA );
|
||||||
|
writeVertex( vB );
|
||||||
|
writeVertex( vC );
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
output.setUint16( offset, 0, true ); offset += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output += '\t\tendloop\n';
|
||||||
|
output += '\tendfacet\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeNormal( vA, vB, vC ) {
|
||||||
|
|
||||||
|
cb.subVectors( vC, vB );
|
||||||
|
ab.subVectors( vA, vB );
|
||||||
|
cb.cross( ab ).normalize();
|
||||||
|
|
||||||
|
normal.copy( cb ).normalize();
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
output.setFloat32( offset, normal.x, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, normal.y, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, normal.z, true ); offset += 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
|
||||||
|
output += '\t\touter loop\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeVertex( vertex ) {
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
output.setFloat32( offset, vertex.x, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, vertex.y, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, vertex.z, true ); offset += 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export { STLExporter };
|
|
@ -0,0 +1,209 @@
|
||||||
|
import {
|
||||||
|
Vector3
|
||||||
|
} from '../node_modules/three/src/Three';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage:
|
||||||
|
* var exporter = new STLExporter();
|
||||||
|
*
|
||||||
|
* // second argument is a list of options
|
||||||
|
* var data = exporter.parse( mesh, { binary: true } );
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var STLExporter = function () {};
|
||||||
|
|
||||||
|
STLExporter.prototype = {
|
||||||
|
|
||||||
|
constructor: STLExporter,
|
||||||
|
|
||||||
|
parse: function ( scene, options ) {
|
||||||
|
|
||||||
|
if ( options === undefined ) options = {};
|
||||||
|
|
||||||
|
var binary = options.binary !== undefined ? options.binary : false;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
var objects = [];
|
||||||
|
var triangles = 0;
|
||||||
|
|
||||||
|
scene.traverse( function ( object ) {
|
||||||
|
|
||||||
|
if ( object.isMesh ) {
|
||||||
|
|
||||||
|
var geometry = object.geometry;
|
||||||
|
|
||||||
|
if ( geometry.isBufferGeometry !== true ) {
|
||||||
|
|
||||||
|
throw new Error( 'THREE.STLExporter: Geometry is not of type THREE.BufferGeometry.' );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = geometry.index;
|
||||||
|
var positionAttribute = geometry.getAttribute( 'position' );
|
||||||
|
|
||||||
|
triangles += ( index !== null ) ? ( index.count / 3 ) : ( positionAttribute.count / 3 );
|
||||||
|
|
||||||
|
objects.push( {
|
||||||
|
object3d: object,
|
||||||
|
geometry: geometry
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
var output;
|
||||||
|
var offset = 80; // skip header
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
|
||||||
|
var arrayBuffer = new ArrayBuffer( bufferLength );
|
||||||
|
output = new DataView( arrayBuffer );
|
||||||
|
output.setUint32( offset, triangles, true ); offset += 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output = '';
|
||||||
|
output += 'solid exported\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var vA = new Vector3();
|
||||||
|
var vB = new Vector3();
|
||||||
|
var vC = new Vector3();
|
||||||
|
var cb = new Vector3();
|
||||||
|
var ab = new Vector3();
|
||||||
|
var normal = new Vector3();
|
||||||
|
|
||||||
|
for ( var i = 0, il = objects.length; i < il; i ++ ) {
|
||||||
|
|
||||||
|
var object = objects[ i ].object3d;
|
||||||
|
var geometry = objects[ i ].geometry;
|
||||||
|
|
||||||
|
var index = geometry.index;
|
||||||
|
var positionAttribute = geometry.getAttribute( 'position' );
|
||||||
|
|
||||||
|
if ( index !== null ) {
|
||||||
|
|
||||||
|
// indexed geometry
|
||||||
|
|
||||||
|
for ( var j = 0; j < index.count; j += 3 ) {
|
||||||
|
|
||||||
|
var a = index.getX( j + 0 );
|
||||||
|
var b = index.getX( j + 1 );
|
||||||
|
var c = index.getX( j + 2 );
|
||||||
|
|
||||||
|
writeFace( a, b, c, positionAttribute, object );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// non-indexed geometry
|
||||||
|
|
||||||
|
for ( var j = 0; j < positionAttribute.count; j += 3 ) {
|
||||||
|
|
||||||
|
var a = j + 0;
|
||||||
|
var b = j + 1;
|
||||||
|
var c = j + 2;
|
||||||
|
|
||||||
|
writeFace( a, b, c, positionAttribute, object );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( binary === false ) {
|
||||||
|
|
||||||
|
output += 'endsolid exported\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
function writeFace( a, b, c, positionAttribute, object ) {
|
||||||
|
|
||||||
|
vA.fromBufferAttribute( positionAttribute, a );
|
||||||
|
vB.fromBufferAttribute( positionAttribute, b );
|
||||||
|
vC.fromBufferAttribute( positionAttribute, c );
|
||||||
|
|
||||||
|
if ( object.isSkinnedMesh === true ) {
|
||||||
|
|
||||||
|
object.boneTransform( a, vA );
|
||||||
|
object.boneTransform( b, vB );
|
||||||
|
object.boneTransform( c, vC );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vA.applyMatrix4( object.matrixWorld );
|
||||||
|
vB.applyMatrix4( object.matrixWorld );
|
||||||
|
vC.applyMatrix4( object.matrixWorld );
|
||||||
|
|
||||||
|
writeNormal( vA, vB, vC );
|
||||||
|
|
||||||
|
writeVertex( vA );
|
||||||
|
writeVertex( vB );
|
||||||
|
writeVertex( vC );
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
output.setUint16( offset, 0, true ); offset += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output += '\t\tendloop\n';
|
||||||
|
output += '\tendfacet\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeNormal( vA, vB, vC ) {
|
||||||
|
|
||||||
|
cb.subVectors( vC, vB );
|
||||||
|
ab.subVectors( vA, vB );
|
||||||
|
cb.cross( ab ).normalize();
|
||||||
|
|
||||||
|
normal.copy( cb ).normalize();
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
output.setFloat32( offset, normal.x, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, normal.y, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, normal.z, true ); offset += 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
|
||||||
|
output += '\t\touter loop\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeVertex( vertex ) {
|
||||||
|
|
||||||
|
if ( binary === true ) {
|
||||||
|
|
||||||
|
output.setFloat32( offset, vertex.x, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, vertex.y, true ); offset += 4;
|
||||||
|
output.setFloat32( offset, vertex.z, true ); offset += 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export { STLExporter };
|
43
src/Scene.js
43
src/Scene.js
|
@ -1,22 +1,16 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import * as THREE from '../node_modules/three/src/Three';
|
import * as THREE from '../node_modules/three/src/Three';
|
||||||
import { TrackballControls } from '../lib/trackball'
|
|
||||||
import { Sketch } from './Sketch'
|
|
||||||
import Stats from '../lib/stats.module.js';
|
|
||||||
|
|
||||||
|
import { Sketch } from './Sketch'
|
||||||
import { extrude, flipBufferGeometryNormals } from './extrude'
|
import { extrude, flipBufferGeometryNormals } from './extrude'
|
||||||
import { onHover, onPick, clearSelection } from './mouseEvents';
|
import { onHover, onPick, clearSelection } from './mouseEvents';
|
||||||
import { _vec2, _vec3, color, awaitSelection, ptObj, setHover } from './shared'
|
import { _vec2, _vec3, color, awaitSelection, ptObj, setHover } from './shared'
|
||||||
|
|
||||||
import { AxesHelper } from './axes'
|
import { AxesHelper } from './axes'
|
||||||
|
|
||||||
|
|
||||||
|
import { TrackballControls } from '../lib/trackball'
|
||||||
import CSG from "../lib/three-csg"
|
import CSG from "../lib/three-csg"
|
||||||
|
import { STLExporter } from '../lib/stl'
|
||||||
import { STLExporter } from '../node_modules/three/examples/jsm/exporters/STLExporter'
|
import Stats from '../lib/stats.module.js';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -376,37 +370,34 @@ function render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function addSketch() {
|
function addSketch() {
|
||||||
|
|
||||||
let sketch;
|
let sketch;
|
||||||
|
|
||||||
const references = await this.awaitSelection({ selpoint: 3 }, { plane: 1 });
|
if (this.selected.length == 3 && this.selected.every(e=>e.userData.type == 'selpoint')) {
|
||||||
|
|
||||||
if (!references) return;
|
|
||||||
|
|
||||||
if (references[0].userData.type == 'plane') {
|
|
||||||
sketch = new Sketch(this)
|
|
||||||
sketch.obj3d.matrix = references[0].matrix
|
|
||||||
sketch.plane.applyMatrix4(sketch.obj3d.matrix)
|
|
||||||
sketch.obj3d.inverse = sketch.obj3d.matrix.clone().invert()
|
|
||||||
this.obj3d.add(sketch.obj3d)
|
|
||||||
} else {
|
|
||||||
sketch = new Sketch(this)
|
sketch = new Sketch(this)
|
||||||
this.obj3d.add(sketch.obj3d)
|
this.obj3d.add(sketch.obj3d)
|
||||||
sketch.align(
|
sketch.align(
|
||||||
...references.map(
|
...this.selected.map(
|
||||||
el => new THREE.Vector3(...el.geometry.attributes.position.array).applyMatrix4(el.matrixWorld)
|
el => new THREE.Vector3(...el.geometry.attributes.position.array).applyMatrix4(el.matrixWorld)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
} else if (this.selected.length && this.selected[0].userData.type == 'plane') {
|
||||||
|
sketch = new Sketch(this)
|
||||||
|
sketch.obj3d.matrix = this.selected[0].matrix
|
||||||
|
sketch.plane.applyMatrix4(sketch.obj3d.matrix)
|
||||||
|
sketch.obj3d.inverse = sketch.obj3d.matrix.clone().invert()
|
||||||
|
this.obj3d.add(sketch.obj3d)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.newSketch = true
|
||||||
|
|
||||||
this.clearSelection()
|
this.clearSelection()
|
||||||
|
|
||||||
sketch.obj3d.addEventListener('change', this.render);
|
sketch.obj3d.addEventListener('change', this.render);
|
||||||
|
|
||||||
return sketch
|
return sketch
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.sc = new Scene(store)
|
window.sc = new Scene(store)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as THREE from '../node_modules/three/src/Three';
|
||||||
import { _vec2, _vec3, raycaster, awaitSelection, ptObj, setHover } from './shared'
|
import { _vec2, _vec3, raycaster, awaitSelection, ptObj, setHover } from './shared'
|
||||||
|
|
||||||
import { drawOnClick1, drawOnClick2, drawPreClick2, drawOnClick3, drawPreClick3, drawClear, drawPoint } from './drawEvents'
|
import { drawOnClick1, drawOnClick2, drawPreClick2, drawOnClick3, drawPreClick3, drawClear, drawPoint } from './drawEvents'
|
||||||
import { onHover, onDrag, onPick, onRelease, clearSelection} from './mouseEvents'
|
import { onHover, onDrag, onPick, onRelease, clearSelection } from './mouseEvents'
|
||||||
import { setCoincident, setOrdinate, setTangent } from './constraintEvents'
|
import { setCoincident, setOrdinate, setTangent } from './constraintEvents'
|
||||||
import { get3PtArc } from './drawArc'
|
import { get3PtArc } from './drawArc'
|
||||||
import { replacer, reviver } from './utils'
|
import { replacer, reviver } from './utils'
|
||||||
|
@ -197,6 +197,9 @@ class Sketch {
|
||||||
this.obj3d.traverse(e => e.layers.disable(2))
|
this.obj3d.traverse(e => e.layers.disable(2))
|
||||||
this.scene.axes.visible = false
|
this.scene.axes.visible = false
|
||||||
this.scene.activeSketch = null
|
this.scene.activeSketch = null
|
||||||
|
if (this.scene.newSketch) {
|
||||||
|
this.scene.newSketch = false
|
||||||
|
}
|
||||||
|
|
||||||
this.clearSelection()
|
this.clearSelection()
|
||||||
|
|
||||||
|
@ -255,8 +258,11 @@ class Sketch {
|
||||||
this.canvas.addEventListener('pointerdown', this.drawOnClick1, { once: true })
|
this.canvas.addEventListener('pointerdown', this.drawOnClick1, { once: true })
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
|
if (this.mode != 'dimension') {
|
||||||
drawClear.call(this)
|
drawClear.call(this)
|
||||||
|
this.mode = "dimension"
|
||||||
this.drawDimension()
|
this.drawDimension()
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
drawClear.call(this)
|
drawClear.call(this)
|
||||||
|
@ -284,6 +290,7 @@ class Sketch {
|
||||||
console.log('undo would be nice')
|
console.log('undo would be nice')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// console.log('this mode:', this.mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteSelected() {
|
deleteSelected() {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
import { Vector2 } from 'three';
|
import {
|
||||||
|
Vector2
|
||||||
|
} from '../node_modules/three/src/Three';
|
||||||
import { ptObj, lineObj } from './shared'
|
import { ptObj, lineObj } from './shared'
|
||||||
|
|
||||||
const n = 30
|
const n = 30
|
||||||
|
|
|
@ -138,7 +138,7 @@ export async function drawDimension() {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
this.dimGroup.children.splice(this.dimGroup.length - 2, 2).forEach(
|
this.dimGroup.children.splice(this.dimGroup.children.length - 2, 2).forEach(
|
||||||
e => {
|
e => {
|
||||||
e.geometry.dispose()
|
e.geometry.dispose()
|
||||||
e.material.dispose()
|
e.material.dispose()
|
||||||
|
@ -147,6 +147,10 @@ export async function drawDimension() {
|
||||||
this.labelContainer.removeChild(this.labelContainer.lastChild);
|
this.labelContainer.removeChild(this.labelContainer.lastChild);
|
||||||
sc.render()
|
sc.render()
|
||||||
}
|
}
|
||||||
|
if (this.mode=="dimension") {
|
||||||
|
this.drawDimension()
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { onDimMoveEnd } from './drawDimension'
|
||||||
let ptLoc
|
let ptLoc
|
||||||
|
|
||||||
export function onHover(e) {
|
export function onHover(e) {
|
||||||
if (this.mode || e.buttons) return
|
if (( this.mode && this.mode!='dimension') || e.buttons) return
|
||||||
|
|
||||||
raycaster.setFromCamera(
|
raycaster.setFromCamera(
|
||||||
new THREE.Vector2(
|
new THREE.Vector2(
|
||||||
|
@ -114,7 +114,7 @@ export function onHover(e) {
|
||||||
|
|
||||||
let draggedLabel;
|
let draggedLabel;
|
||||||
export function onPick(e) {
|
export function onPick(e) {
|
||||||
if (this.mode || e.buttons != 1) return
|
if (( this.mode && this.mode!='dimension') || e.buttons != 1) return
|
||||||
// if (this.mode || e.buttons != 1 || e.ctrlKey || e.metaKey) return
|
// if (this.mode || e.buttons != 1 || e.ctrlKey || e.metaKey) return
|
||||||
|
|
||||||
if (this.hovered.length) {
|
if (this.hovered.length) {
|
||||||
|
|
|
@ -57,6 +57,13 @@ body {
|
||||||
hover:bg-gray-500 hover:text-gray-200;
|
hover:bg-gray-500 hover:text-gray-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.active-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
@apply fill-current
|
||||||
|
bg-green-400 text-gray-200
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.btn-green {
|
.btn-green {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
|
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import React, { } from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { createStore, applyMiddleware } from 'redux'
|
import { createStore, applyMiddleware } from 'redux'
|
||||||
import { Provider, useSelector } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { reducer } from './reducer'
|
import { reducer } from './reducer'
|
||||||
import logger from 'redux-logger'
|
import logger from 'redux-logger'
|
||||||
|
|
||||||
|
@ -11,27 +10,19 @@ import { Tree } from './tree'
|
||||||
import { NavBar } from './navBar'
|
import { NavBar } from './navBar'
|
||||||
import { ToolTip } from './toolTip'
|
import { ToolTip } from './toolTip'
|
||||||
|
|
||||||
|
|
||||||
import './app.css'
|
import './app.css'
|
||||||
|
|
||||||
const preloadedState = {
|
|
||||||
treeEntries: {
|
|
||||||
byId: {},
|
|
||||||
allIds: [],
|
let store
|
||||||
tree: {},
|
if (process.env.NODE_ENV === 'production') {
|
||||||
order: {},
|
store = createStore(reducer)
|
||||||
visible: {},
|
} else {
|
||||||
activeSketchId: ""
|
const { logger } = require(`redux-logger`);
|
||||||
},
|
store = createStore(reducer, {}, applyMiddleware(logger))
|
||||||
}
|
}
|
||||||
|
|
||||||
// const store = createStore(reducer, preloadedState, applyMiddleware(logger))
|
|
||||||
|
|
||||||
|
|
||||||
const store = createStore(reducer, {}, applyMiddleware(logger))
|
|
||||||
// const store = createStore(reducer, sc.loadState(), applyMiddleware(logger))
|
|
||||||
|
|
||||||
|
|
||||||
const App = ({ store }) => {
|
const App = ({ store }) => {
|
||||||
return <Provider store={store}>
|
return <Provider store={store}>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
|
|
|
@ -111,8 +111,12 @@ export const Dialog = () => {
|
||||||
|| sc.activeSketch.idOnActivate != id
|
|| sc.activeSketch.idOnActivate != id
|
||||||
|| sc.activeSketch.c_idOnActivate != sc.activeSketch.c_id
|
|| sc.activeSketch.c_idOnActivate != sc.activeSketch.c_id
|
||||||
) {
|
) {
|
||||||
|
if (sc.newSketch) {
|
||||||
|
dispatch({ type: 'delete-node', id: sc.activeSketch.obj3d.name })
|
||||||
|
sc.sid -= 1
|
||||||
|
} else {
|
||||||
dispatch({ type: "restore-sketch" })
|
dispatch({ type: "restore-sketch" })
|
||||||
// dispatch({ type: 'set-modified', status: false })
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ type: 'finish-sketch' })
|
dispatch({ type: 'finish-sketch' })
|
||||||
|
|
|
@ -15,16 +15,12 @@ var tzoffset = (new Date()).getTimezoneOffset() * 60000;
|
||||||
|
|
||||||
|
|
||||||
export function STLExport(filename) {
|
export function STLExport(filename) {
|
||||||
if (sc.selected[0] && sc.selected[0].userData.type == 'mesh') {
|
|
||||||
|
|
||||||
const result = STLexp.parse(sc.selected[0], { binary: true });
|
const result = STLexp.parse(sc.selected[0], { binary: true });
|
||||||
|
|
||||||
const time = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5).replace(/:/g, '-');
|
const time = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5).replace(/:/g, '-');
|
||||||
|
|
||||||
saveLegacy(new Blob([result], { type: 'model/stl' }), `${filename}_${time}.stl`);
|
saveLegacy(new Blob([result], { type: 'model/stl' }), `${filename}_${time}.stl`);
|
||||||
} else {
|
|
||||||
alert('please select one body to export')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +37,6 @@ export async function saveFile(fileHandle, file, dispatch) {
|
||||||
console.error(msg, ex);
|
console.error(msg, ex);
|
||||||
alert(msg);
|
alert(msg);
|
||||||
}
|
}
|
||||||
// app.setFocus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function saveFileAs(file, dispatch) {
|
export async function saveFileAs(file, dispatch) {
|
||||||
|
@ -83,16 +78,11 @@ export async function saveFileAs(file, dispatch) {
|
||||||
alert(msg);
|
alert(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// app.setFocus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export async function openFile(dispatch) {
|
export async function openFile(dispatch) {
|
||||||
// if (!app.confirmDiscard()) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
let fileHandle
|
let fileHandle
|
||||||
|
|
||||||
// If a fileHandle is provided, verify we have permission to read/write it,
|
// If a fileHandle is provided, verify we have permission to read/write it,
|
||||||
|
@ -143,7 +133,7 @@ export function confirmDiscard(modified) {
|
||||||
|
|
||||||
export async function verifyPermission(fileHandle) {
|
export async function verifyPermission(fileHandle) {
|
||||||
const opts = {
|
const opts = {
|
||||||
mode:'readwrite'
|
mode: 'readwrite'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if we already have permission, if so, return true.
|
// Check if we already have permission, if so, return true.
|
||||||
|
|
|
@ -4,16 +4,13 @@ import React, { useEffect, useReducer } from 'react';
|
||||||
|
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
|
|
||||||
import { FaEdit } from 'react-icons/fa'
|
import { FaEdit, FaLinkedin, FaGithub } from 'react-icons/fa'
|
||||||
import { MdSave, MdFolder, MdInsertDriveFile } from 'react-icons/md'
|
import { MdSave, MdFolder, MdInsertDriveFile } from 'react-icons/md'
|
||||||
|
|
||||||
import * as Icon from "./icons";
|
import * as Icon from "./icons";
|
||||||
import { Dialog } from './dialog'
|
import { Dialog } from './dialog'
|
||||||
import { STLExport, saveFile, openFile, verifyPermission } from './fileHelpers'
|
import { STLExport, saveFile, openFile, verifyPermission } from './fileHelpers'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const NavBar = () => {
|
export const NavBar = () => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const sketchActive = useSelector(state => state.ui.sketchActive)
|
const sketchActive = useSelector(state => state.ui.sketchActive)
|
||||||
|
@ -22,7 +19,10 @@ export const NavBar = () => {
|
||||||
const modified = useSelector(state => state.ui.modified)
|
const modified = useSelector(state => state.ui.modified)
|
||||||
|
|
||||||
const boolOp = (code) => {
|
const boolOp = (code) => {
|
||||||
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
|
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) {
|
||||||
|
alert('please first select two bodies for boolean operation')
|
||||||
|
return
|
||||||
|
}
|
||||||
const [m1, m2] = sc.selected
|
const [m1, m2] = sc.selected
|
||||||
|
|
||||||
const mesh = sc.boolOp(m1, m2, code)
|
const mesh = sc.boolOp(m1, m2, code)
|
||||||
|
@ -46,8 +46,12 @@ export const NavBar = () => {
|
||||||
forceUpdate()
|
forceUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
const addSketch = async () => {
|
const addSketch = () => {
|
||||||
const sketch = await sc.addSketch()
|
const sketch = sc.addSketch()
|
||||||
|
if (!sketch) {
|
||||||
|
alert('please select a plane or 3 points to define sketch plane')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({ type: 'rx-sketch', obj: sketch })
|
dispatch({ type: 'rx-sketch', obj: sketch })
|
||||||
|
|
||||||
|
@ -100,16 +104,16 @@ export const NavBar = () => {
|
||||||
dispatch({ type: 'set-dialog', action: 'extrude', target: sc.activeSketch })
|
dispatch({ type: 'set-dialog', action: 'extrude', target: sc.activeSketch })
|
||||||
|
|
||||||
}, 'Extrude [e]'],
|
}, 'Extrude [e]'],
|
||||||
[Icon.Dimension, () => sc.activeSketch.command('d'), 'Dimension [d]'],
|
[Icon.Dimension, () => sc.activeSketch.command('d'), 'Dimension [D]'],
|
||||||
[Icon.Line, () => sc.activeSketch.command('l'), 'Line [l]'],
|
[Icon.Line, () => sc.activeSketch.command('l'), 'Line [L]'],
|
||||||
[Icon.Arc, () => sc.activeSketch.command('a'), 'Arc [a]'],
|
[Icon.Arc, () => sc.activeSketch.command('a'), 'Arc [A]'],
|
||||||
[Icon.Coincident, () => sc.activeSketch.command('c'), 'Coincident [c]'],
|
[Icon.Coincident, () => sc.activeSketch.command('c'), 'Coincident [C]'],
|
||||||
[Icon.Vertical, () => sc.activeSketch.command('v'), 'Vertical [v]'],
|
[Icon.Vertical, () => sc.activeSketch.command('v'), 'Vertical [V]'],
|
||||||
[Icon.Horizontal, () => sc.activeSketch.command('h'), 'Horizontal [h]'],
|
[Icon.Horizontal, () => sc.activeSketch.command('h'), 'Horizontal [H]'],
|
||||||
[Icon.Tangent, () => sc.activeSketch.command('t'), 'Tangent [t]'],
|
[Icon.Tangent, () => sc.activeSketch.command('t'), 'Tangent [T]'],
|
||||||
[MdSave,
|
[MdSave,
|
||||||
async () => {
|
async () => {
|
||||||
if(await verifyPermission(fileHandle) === false) return
|
if (await verifyPermission(fileHandle) === false) return
|
||||||
sc.refreshNode(sc.activeSketch.obj3d.name, treeEntries)
|
sc.refreshNode(sc.activeSketch.obj3d.name, treeEntries)
|
||||||
sc.activeSketch.clearSelection()
|
sc.activeSketch.clearSelection()
|
||||||
saveFile(fileHandle, JSON.stringify([id, sc.sid, sc.mid, treeEntries]), dispatch)
|
saveFile(fileHandle, JSON.stringify([id, sc.sid, sc.mid, treeEntries]), dispatch)
|
||||||
|
@ -121,9 +125,14 @@ export const NavBar = () => {
|
||||||
|
|
||||||
|
|
||||||
const partModeButtons = [
|
const partModeButtons = [
|
||||||
[FaEdit, addSketch, 'Sketch [s]'],
|
[FaEdit, addSketch, 'Sketch'],
|
||||||
[Icon.Extrude, () => {
|
[Icon.Extrude, () => {
|
||||||
|
if (sc.selected[0] && treeEntries.byId[sc.selected[0].name].userData.type == 'sketch') {
|
||||||
dispatch({ type: 'set-dialog', action: 'extrude', target: treeEntries.byId[sc.selected[0].name] })
|
dispatch({ type: 'set-dialog', action: 'extrude', target: treeEntries.byId[sc.selected[0].name] })
|
||||||
|
} else {
|
||||||
|
alert('please select a sketch from the left pane extrude')
|
||||||
|
}
|
||||||
|
|
||||||
}, 'Extrude'],
|
}, 'Extrude'],
|
||||||
|
|
||||||
[Icon.Union, () => boolOp('u'), 'Union'],
|
[Icon.Union, () => boolOp('u'), 'Union'],
|
||||||
|
@ -147,9 +156,12 @@ export const NavBar = () => {
|
||||||
)
|
)
|
||||||
}, 'Open'],
|
}, 'Open'],
|
||||||
[Icon.Stl, () => {
|
[Icon.Stl, () => {
|
||||||
STLExport('box')
|
if (sc.selected[0] && sc.selected[0].userData.type == 'mesh') {
|
||||||
},
|
STLExport(fileHandle ? fileHandle.name.replace(/\.[^/.]+$/, "") : 'untitled')
|
||||||
, 'Export STL'],
|
} else {
|
||||||
|
alert('please first select one body to export')
|
||||||
|
}
|
||||||
|
}, 'Export to STL'],
|
||||||
]
|
]
|
||||||
|
|
||||||
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
||||||
|
@ -175,30 +187,16 @@ export const NavBar = () => {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className='w-auto h-full flex-1 items-center'>
|
<div className='w-auto h-full flex-1 items-center flex justify-end'>
|
||||||
|
<a href='https://github.com/twpride/threeCAD' className='h-full w=auto'>
|
||||||
|
<FaGithub className="btn-green w-auto h-full p-3.5"></FaGithub>
|
||||||
|
</a>
|
||||||
|
<a href='https://www.linkedin.com/in/howard-hwang-b3000335' className='h-full w=auto'>
|
||||||
|
<FaLinkedin className="btn-green w-auto h-full p-3.5"></FaLinkedin>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// app.saveFile = async () => {
|
|
||||||
// try {
|
|
||||||
// if (!app.file.handle) {
|
|
||||||
// return await app.saveFileAs();
|
|
||||||
// }
|
|
||||||
// gaEvent('FileAction', 'Save');
|
|
||||||
// await writeFile(app.file.handle, app.getText());
|
|
||||||
// app.setModified(false);
|
|
||||||
// } catch (ex) {
|
|
||||||
// gaEvent('Error', 'FileSave', ex.name);
|
|
||||||
// const msg = 'Unable to save file';
|
|
||||||
// console.error(msg, ex);
|
|
||||||
// alert(msg);
|
|
||||||
// }
|
|
||||||
// app.setFocus();
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ export const Tree = () => {
|
||||||
const fileHandle = useSelector(state => state.ui.fileHandle)
|
const fileHandle = useSelector(state => state.ui.fileHandle)
|
||||||
|
|
||||||
return <div className='sideNav flex flex-col bg-gray-800'>
|
return <div className='sideNav flex flex-col bg-gray-800'>
|
||||||
<div className='w-16 text-gray-50 h-7 mx-1 border-0 focus:outline-none bg-transparent'>
|
<div className='w-16 text-gray-50 h-9 text-lg mx-1 border-0 flex items-center focus:outline-none bg-transparent'>
|
||||||
{fileHandle ? fileHandle.name.replace(/\.[^/.]+$/, "") : 'untitled'}
|
{fileHandle ? fileHandle.name.replace(/\.[^/.]+$/, "") : 'untitled'}
|
||||||
</div>
|
</div>
|
||||||
{treeEntries.allIds.map((entId, idx) => (
|
{treeEntries.allIds.map((entId, idx) => (
|
||||||
|
|
|
@ -128,6 +128,7 @@ async function awaitSelection(...criteria) {
|
||||||
|
|
||||||
references.push(pt)
|
references.push(pt)
|
||||||
const type = pt.userData.type
|
const type = pt.userData.type
|
||||||
|
|
||||||
if (counter[type]) {
|
if (counter[type]) {
|
||||||
counter[type] += 1;
|
counter[type] += 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -144,7 +145,7 @@ async function awaitSelection(...criteria) {
|
||||||
window.removeEventListener('keydown', onKey)
|
window.removeEventListener('keydown', onKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('fail')
|
// console.log('fail')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
todo.txt
27
todo.txt
|
@ -35,48 +35,49 @@ dim tag delete //resolved
|
||||||
auto update extrude // done
|
auto update extrude // done
|
||||||
extrude edit dialog // done
|
extrude edit dialog // done
|
||||||
file save, stl export// done
|
file save, stl export// done
|
||||||
|
seperate scene from init logic only init cam and rendere // not an issue , ended up just splicing (1)
|
||||||
|
add download button, different from save button // done
|
||||||
|
|
||||||
-unable cancel out of new sketches //fixed seemingly
|
-unable cancel out of new sketches //fixed seemingly
|
||||||
|
-unable to delete arc // fixed seemingly
|
||||||
|
|
||||||
-sometimes unable to hit return and change dimensionk
|
-sometimes unable to hit return and change dimensionk
|
||||||
-unable to delete arc
|
|
||||||
hover not clearing sometimes in sketch
|
hover not clearing sometimes in sketch
|
||||||
0.000 artifact
|
0.000 artifact
|
||||||
lighting messed up
|
lighting messed up
|
||||||
|
|
||||||
seperate scene from init logic only init cam and rendere
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reattach sketch
|
reattach sketch
|
||||||
auto snap
|
auto snap
|
||||||
|
vertical and horzontal baseline to dimension to / or just smart ordinate dir dimenensing
|
||||||
highlight button to indicate active mode
|
highlight button to indicate active mode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add cancle soft button for line arc
|
add cancle soft button for line arc
|
||||||
|
|
||||||
|
|
||||||
constraint labels,equal
|
constraint labels,equal
|
||||||
|
|
||||||
add download button, different from save button
|
|
||||||
parallel // need to add antoher button to feature ,or empty placeholder
|
parallel // need to add antoher button to feature ,or empty placeholder
|
||||||
|
|
||||||
|
|
||||||
tree relation tool tip
|
tree relation tool tip
|
||||||
tree ent renaming
|
tree ent renaming
|
||||||
vertical and horzontal baseline to dimension to
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
set pieces
|
set pieces
|
||||||
|
|
||||||
|
wasm data structure
|
||||||
|
|
||||||
hover state for sketch
|
hover state for sketch
|
||||||
await selection
|
await selection
|
||||||
3 point arc implementation
|
3 point arc implementation
|
||||||
|
local file save and mark dirty
|
||||||
saerch tree for loop finding // need dev effor
|
saerch tree for loop finding // need dev effor
|
||||||
|
|
||||||
dep tree for biuidling design treee
|
dep tree for biuidling design treee
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -174,8 +174,7 @@ int main(int argc, char *argv[])
|
||||||
sys.failed = CheckMalloc(500 * sizeof(sys.failed[0]));
|
sys.failed = CheckMalloc(500 * sizeof(sys.failed[0]));
|
||||||
sys.faileds = 500;
|
sys.faileds = 500;
|
||||||
|
|
||||||
// Example2d(150.0);
|
|
||||||
|
|
||||||
printf("hello\n");
|
// printf("hello\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
const { merge } = require('webpack-merge');
|
const { merge } = require('webpack-merge');
|
||||||
|
|
||||||
const common = require('./webpack.common.js');
|
const common = require('./webpack.common.js');
|
||||||
|
const webpack = require('webpack')
|
||||||
|
|
||||||
module.exports = merge(common, {
|
module.exports = merge(common, {
|
||||||
|
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
// 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
|
||||||
|
'process.env.NODE_ENV': 'production'
|
||||||
|
}),
|
||||||
|
new webpack.IgnorePlugin(/redux-logger/)
|
||||||
|
]
|
||||||
});
|
});
|
Loading…
Reference in New Issue