diff --git a/package.json b/package.json index c03f26d0..5567d777 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "version": "0.1.0", "description": "JS.Sketcher is a parametric 2D and 3D CAD modeler written in pure javascript", "scripts": { - "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.config.dev.js --content-base web/ --port 3000", + "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.config.js --content-base web/ --port 3000", + "start-test": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.config.dev.js --content-base web/ --port 3000", "pack": "node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --progress --profile --colors", "build": "grunt", "lint": "eslint web/app" @@ -31,6 +32,7 @@ "babel-preset-stage-2": "6.24.1", "babel-polyfill": "6.26.0", "babel-preset-react": "6.24.1", + "babel-plugin-local-styles-transformer": "git://github.com/xibyte/babel-plugin-local-styles-transformer.git#0.0.1", "css-loader": "0.28.7", "less-loader": "4.0.5", @@ -58,6 +60,7 @@ "less": "2.7.3", "libtess": "1.2.2", "numeric": "1.2.6", - "sprintf": "0.1.5" + "sprintf": "0.1.5", + "classnames": "2.2.5" } } diff --git a/web/app/3d/debug.js b/web/app/3d/debug.js index 6f436fdb..3c84092c 100644 --- a/web/app/3d/debug.js +++ b/web/app/3d/debug.js @@ -4,6 +4,11 @@ import {createSolidMaterial} from './scene/scene-object' import DPR from '../utils/dpr' import Vector from "../math/vector"; import {NurbsCurve} from "../brep/geom/impl/nurbs"; +import * as ui from '../ui/ui'; + +import React from 'react'; +import ReactDOM from 'react-dom'; +import BrepDebugger from './../brep/debug/debugger/brepDebugger'; export const DEBUG = true; @@ -207,7 +212,7 @@ const DebugMenuConfig = { label: 'debug', cssIcons: ['bug'], info: 'set of debug actions', - actions: [ 'DebugPrintAllSolids', 'DebugPrintFace', 'DebugFaceId', 'DebugFaceSketch'] + actions: [ 'DebugPrintAllSolids', 'DebugPrintFace', 'DebugFaceId', 'DebugFaceSketch', 'DebugOpenBrepDebugger'] } }; @@ -274,5 +279,27 @@ const DebugActions = { }; console.log(JSON.stringify(squashed)); } + }, + 'DebugOpenBrepDebugger': { + cssIcons: ['cubes'], + label: 'open BREP debugger', + info: 'open the BREP debugger in a window', + invoke: (app) => { + + let debuggerWinDom = document.getElementById('brep-debugger'); + if (!debuggerWinDom) { + //Temporary hack until win infrastructure is done for 3d + debuggerWinDom = document.createElement('div'); + debuggerWinDom.setAttribute('id', 'brep-debugger'); + debuggerWinDom.innerHTML = '
Brep Debugger
'; + document.body.appendChild(debuggerWinDom); + debuggerWinDom.debuggerWin = new ui.Window($(debuggerWinDom), new ui.WinManager()); + ReactDOM.render( + , + debuggerWinDom.getElementsByClassName('content')[0] + ); + } + debuggerWinDom.debuggerWin.show(); + } } }; diff --git a/web/app/3d/ui/keymaps/default.js b/web/app/3d/ui/keymaps/default.js index 27d71b53..2a7ca0fa 100644 --- a/web/app/3d/ui/keymaps/default.js +++ b/web/app/3d/ui/keymaps/default.js @@ -1,5 +1,4 @@ export const keymap = { - 'CUT': 'C', 'EXTRUDE': 'E', 'ZoomIn': '+', @@ -8,5 +7,6 @@ export const keymap = { 'menu.primitives': 'shift+A', 'menu.main': 'space', 'Save': 'ctrl+S', - 'Info': 'F1' + 'Info': 'F1', + 'DebugOpenBrepDebugger': 'ctrl+B' }; diff --git a/web/app/brep/debug/brep-debug.js b/web/app/brep/debug/brep-debug.js new file mode 100644 index 00000000..b27e317d --- /dev/null +++ b/web/app/brep/debug/brep-debug.js @@ -0,0 +1,34 @@ + +class BRepDebug { + + constructor() { + this.booleanSessions = []; + } + + startBooleanSession(a, b, type) { + this.currentBooleanSession = new BooleanSession(a, b, type) + this.booleanSessions.push(this.currentBooleanSession); + } + + +} + +class BooleanSession { + + constructor(a, b, type) { + this.inputOperandA = a; + this.inputOperandB = b; + } + + setWorkingOperands(a, b) { + this.workingOperandA = a; + this.workingOperandB = b; + } + + setResult(result) { + this.result = result; + } + +} + +export default (new BRepDebug()); \ No newline at end of file diff --git a/web/app/brep/debug/debugger/brepDebugger.jsx b/web/app/brep/debug/debugger/brepDebugger.jsx new file mode 100644 index 00000000..911bc33a --- /dev/null +++ b/web/app/brep/debug/debugger/brepDebugger.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import './brepDebugger.less'; +import BREP_DEBUG from '../brep-debug'; +import ShellExplorer from './shellExplorer'; +import Section from './section' + +export default class BrepDebugger extends React.PureComponent { + + render() { + let {booleanSessions} = BREP_DEBUG; + + return
+
+ __DEBUG__.HideSolids()} /> +
+ +
+ {booleanSessions.map(session => +
+
+ +
+
+
+
Operand A
+ +
+
+
Operand B
+ +
+
+
+ +
+ +
+
+
+
Operand A
+ +
+
+
Operand B
+ +
+
+
Result
+ +
+
+
+
)} +
+
; + } + +} + + diff --git a/web/app/brep/debug/debugger/brepDebugger.less b/web/app/brep/debug/debugger/brepDebugger.less new file mode 100644 index 00000000..02b26981 --- /dev/null +++ b/web/app/brep/debug/debugger/brepDebugger.less @@ -0,0 +1,53 @@ +.brep-debugger { + + padding: 0.3em; + line-height: 1.5; + button { + font-size: inherit; + padding: 0 0.3em; + } + + & .operands-veiew { + display: flex; + justify-content: space-between; + & > * { + flex: 1 1; + } + } + + & .section { + & .caption { + &.closable { + cursor: pointer; + &:hover { + color: blue; + } + } + &.accent { + background-color: rgb(255, 244, 244); + font-weight: bold; + } + &.centered { + text-align: center; + } + &.operand-a { + background-color: rgb(239, 244, 255) + } + + &.operand-b { + background-color: rgb(244, 255, 245) + } + &.result { + background-color: rgb(254, 255, 244) + } + } + } + .button { + cursor: pointer; + font-size: 1.3em; + &:hover { + color: blue; + } + } +} + diff --git a/web/app/brep/debug/debugger/edgeIntersectionsExplorer.jsx b/web/app/brep/debug/debugger/edgeIntersectionsExplorer.jsx new file mode 100644 index 00000000..e69de29b diff --git a/web/app/brep/debug/debugger/faceIntersectionsExplorer.jsx b/web/app/brep/debug/debugger/faceIntersectionsExplorer.jsx new file mode 100644 index 00000000..e69de29b diff --git a/web/app/brep/debug/debugger/faceMergeExplorer.js b/web/app/brep/debug/debugger/faceMergeExplorer.js new file mode 100644 index 00000000..e69de29b diff --git a/web/app/brep/debug/debugger/loopDetectionExplorer.jsx b/web/app/brep/debug/debugger/loopDetectionExplorer.jsx new file mode 100644 index 00000000..e69de29b diff --git a/web/app/brep/debug/debugger/section.jsx b/web/app/brep/debug/debugger/section.jsx new file mode 100644 index 00000000..beb5619b --- /dev/null +++ b/web/app/brep/debug/debugger/section.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import cx from 'classnames'; + + +export default class Section extends React.PureComponent { + + constructor() { + super(); + this.state = { + closed: false + } + } + + render() { + let {name, tabs, closable, defaultClosed, accent, children, captionStyles} = this.props; + let closed = closable && (this.state.closed || defaultClosed); + return
+
+ {closable && } {name}
+ {children} +
; + } +} + +function mapIterator(it, fn) { + for (let i of it) { + fn(i); + } +} + + diff --git a/web/app/brep/debug/debugger/shellExplorer.jsx b/web/app/brep/debug/debugger/shellExplorer.jsx new file mode 100644 index 00000000..0e8888d9 --- /dev/null +++ b/web/app/brep/debug/debugger/shellExplorer.jsx @@ -0,0 +1,26 @@ +import React from 'react'; + +export default class ShellExplorer extends React.PureComponent { + + render() { + let {shell} = this.props; + return
+
faces
+ {shell.faces.map(face =>
+
face {face.refId}
+ {mapIterator(face.edges, e =>
+ edge: {e.refId} +
)} +
) + } +
; + } +} + +function mapIterator(it, fn) { + for (let i of it) { + fn(i); + } +} + + diff --git a/web/app/brep/operations/boolean.js b/web/app/brep/operations/boolean.js index 24692af6..0b685082 100644 --- a/web/app/brep/operations/boolean.js +++ b/web/app/brep/operations/boolean.js @@ -11,15 +11,17 @@ import {Ray} from "../utils/ray"; import pickPointInside2dPolygon from "../utils/pickPointInPolygon"; import CadError from "../../utils/errors"; import {createBoundingNurbs} from "../brep-builder"; +import BREP_DEBUG from '../debug/brep-debug'; + const A = 0, B = 1; const DEBUG = { OPERANDS_MODE: false, - LOOP_DETECTION: true, - FACE_FACE_INTERSECTION: true, + LOOP_DETECTION: false, + FACE_FACE_INTERSECTION: false, RAY_CAST: false, - FACE_MERGE: true, + FACE_MERGE: false, NOOP: () => {} }; @@ -78,9 +80,13 @@ function checkShellForErrors(shell, code) { export function BooleanAlgorithm( shellA, shellB, type ) { + BREP_DEBUG.startBooleanSession(shellA, shellB, type); + shellA = prepareWorkingCopy(shellA); shellB = prepareWorkingCopy(shellB); + BREP_DEBUG.currentBooleanSession.setWorkingOperands(shellA, shellB); + let facesData = []; mergeVertices(shellA, shellB); @@ -137,6 +143,7 @@ export function BooleanAlgorithm( shellA, shellB, type ) { // __DEBUG__.ClearVolumes(); // __DEBUG__.Clear(); + BREP_DEBUG.currentBooleanSession.setResult(result); return result; } @@ -585,8 +592,8 @@ function filterFacesByNewEdges(faces) { const validFaces = new Set(faces); const result = new Set(); for (let face of faces) { - __DEBUG__.Clear(); - __DEBUG__.AddFace(face); + // __DEBUG__.Clear(); + // __DEBUG__.AddFace(face); traverseFaces(face, validFaces, (it) => { if (result.has(it) || isFaceContainNewEdge(it)) { result.add(face); @@ -866,7 +873,7 @@ function collectNodesOfIntersectionOfFace(curve, face, nodes, operand) { } function collectNodesOfIntersection(curve, loop, nodes, operand) { - __DEBUG__.AddCurve(curve, 0xffffff); + // __DEBUG__.AddCurve(curve, 0xffffff); let skippedEnclosures = new Set(); for (let edge of loop.halfEdges) { diff --git a/web/app/ui/ui.js b/web/app/ui/ui.js index bb223f99..f7c1fa87 100644 --- a/web/app/ui/ui.js +++ b/web/app/ui/ui.js @@ -19,6 +19,11 @@ function Window(el, winManager) { winManager.registerDrag(this.root, caption); } + +Window.prototype.show = function() { + this.root.show(); +} + Window.prototype.toggle = function() { var aboutToShow = !this.root.is(':visible'); if (aboutToShow) { diff --git a/web/css/app3d.less b/web/css/app3d.less index dff880c8..1457a439 100644 --- a/web/css/app3d.less +++ b/web/css/app3d.less @@ -1,3 +1,5 @@ +@import 'brep-debugger.less'; + @tab-switcher-inner-height: 20px; @tab-switcher-top-border: 1px; @tab-switcher-height: @tab-switcher-inner-height + @tab-switcher-top-border; diff --git a/web/css/brep-debugger.less b/web/css/brep-debugger.less new file mode 100644 index 00000000..a8c9dff2 --- /dev/null +++ b/web/css/brep-debugger.less @@ -0,0 +1,18 @@ +#brep-debugger { + position: absolute; + min-width: 100px; + min-height: 100px; + height: 50%; + width: 300px; + left:100px; + top:300px; + background: #eee; + border: 5px solid rgb(49, 121, 255); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + & .tool-caption { + padding: 0.3em; + background-color: rgb(238, 255, 246); + cursor: default; + user-select: none + } +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 41c8b98d..a48e236a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,8 @@ const path = require('path'); const webpack = require('webpack'); +const WEB_APP = path.join(__dirname, 'web/app'); + module.exports = { devtool: 'source-map', entry: { @@ -25,21 +27,26 @@ module.exports = { module: { rules: [{ test: /\.(js|jsx)$/, - use: ['babel-loader'], - include: [path.join(__dirname, 'web/app'), path.join(__dirname, 'web/test')] + loader: 'babel-loader', + include: [WEB_APP, path.join(__dirname, 'web/test')], + options: { + plugins: [ + ['local-styles-transformer', {include: WEB_APP}] + ] + } }, { test: /\.css$/, use: [ - "style-loader", - "css-loader", + 'style-loader', + 'css-loader', ] }, { test: /\.less$/, use: [ - "style-loader", - "css-loader?-url", - "less-loader" + 'style-loader', + 'css-loader?-url', + 'less-loader' ] }, { @@ -50,5 +57,9 @@ module.exports = { test: /\.json$/, use: 'json-loader' }] + }, + devServer: { + hot: false, + inline: false, } };