diff --git a/web/app/cad/scene/controls/pickControlPlugin.js b/web/app/cad/scene/controls/pickControlPlugin.js index dbf6e21e..849a81c7 100644 --- a/web/app/cad/scene/controls/pickControlPlugin.js +++ b/web/app/cad/scene/controls/pickControlPlugin.js @@ -174,6 +174,9 @@ export function activate(context) { for (let i = 0; i < pickResults.length; i++) { const pickResult = pickResults[i]; for (let picker of pickers) { + if (pickResult.object && pickResult.object.passRayCast && pickResult.object.passRayCast(pickResults)) { + // continue; + } if (picker(pickResult)) { return; } diff --git a/web/app/cad/scene/entityContextPlugin.js b/web/app/cad/scene/entityContextPlugin.js index e1dd639f..7e7b780d 100644 --- a/web/app/cad/scene/entityContextPlugin.js +++ b/web/app/cad/scene/entityContextPlugin.js @@ -2,7 +2,7 @@ import {state} from 'lstream'; import {addToListInMap} from 'gems/iterables'; import {EMPTY_ARRAY} from '../../../../modules/gems/iterables'; -import {DATUM, FACE, SHELL, SKETCH_OBJECT, EDGE} from './entites'; +import {DATUM, FACE, SHELL, SKETCH_OBJECT, EDGE, LOOP} from './entites'; export const SELECTABLE_ENTITIES = [FACE, EDGE, SKETCH_OBJECT, DATUM, SHELL]; @@ -34,7 +34,13 @@ export function activate(ctx) { ctx.services.marker.$markedEntities.attach(marked => { let byType = new Map(); marked.forEach((obj) => { - addToListInMap(byType, obj.TYPE, obj); + if (obj.TYPE === LOOP) { + if (byType[FACE] && !byType[FACE].includes(obj.face)) { + addToListInMap(byType, FACE, obj.face); + } + } else { + addToListInMap(byType, obj.TYPE, obj); + } }); SELECTABLE_ENTITIES.forEach(entityType => { let entities = byType.get(entityType); diff --git a/web/app/cad/scene/views/openFaceView.js b/web/app/cad/scene/views/openFaceView.js index fa14284c..91ea5e32 100644 --- a/web/app/cad/scene/views/openFaceView.js +++ b/web/app/cad/scene/views/openFaceView.js @@ -2,6 +2,7 @@ import {setAttribute} from '../../../../../modules/scene/objectData'; import {FACE, SHELL} from '../entites'; import {NULL_COLOR, SELECTION_COLOR, setFacesColor, SketchingView} from './faceView'; import {View} from './view'; +import {SketchMesh} from './shellView'; export class OpenFaceShellView extends View { @@ -54,7 +55,7 @@ export class OpenFaceView extends SketchingView { geometry.faces.push(new THREE.Face3(0, 2, 3)); geometry.faces.forEach(f => setAttribute(f, FACE, this)); geometry.computeFaceNormals(); - this.mesh = new THREE.Mesh(geometry, this.material); + this.mesh = new SketchMesh(geometry, this.material); this.rootGroup.add(this.mesh); } diff --git a/web/app/cad/scene/views/shellView.js b/web/app/cad/scene/views/shellView.js index 7b9c8e40..f6ddf181 100644 --- a/web/app/cad/scene/views/shellView.js +++ b/web/app/cad/scene/views/shellView.js @@ -1,10 +1,11 @@ import {View} from './view'; import * as SceneGraph from '../../../../../modules/scene/sceneGraph'; -import {setAttribute} from '../../../../../modules/scene/objectData'; +import {getAttribute, setAttribute} from '../../../../../modules/scene/objectData'; import {createSolidMaterial} from '../wrappers/sceneObject'; import {FaceView, SELECTION_COLOR} from './faceView'; import {EdgeView} from './edgeView'; -import {SHELL} from '../entites'; +import {FACE, SHELL} from '../entites'; +import {Mesh} from 'three'; export class ShellView extends View { @@ -27,7 +28,7 @@ export class ShellView extends View { const geometry = new THREE.Geometry(); geometry.dynamic = true; - this.mesh = new THREE.Mesh(geometry, this.material); + this.mesh = new SketchMesh(geometry, this.material); this.rootGroup.add(this.mesh); @@ -68,4 +69,30 @@ export class ShellView extends View { } super.dispose(); } +} + +export class SketchMesh extends Mesh { + + constructor(geometry, material) { + super(geometry, material); + } + + passRayCast(hits) { + for (let hit of hits) { + if (hit.object === this && hit.face) { + let faceView = getAttribute(hit.face, FACE); + if (faceView) { + if (faceView.sketchLoopViews.find(v => hits.find(h => v.mesh.geometry.faces.indexOf(h.face) !== -1))) { + return true; + } + } + + } + } + } + + passMouseEvent(e) { + return this.passRayCast(e.hits); + }; + } \ No newline at end of file diff --git a/web/app/cad/scene/views/sketchLoopView.js b/web/app/cad/scene/views/sketchLoopView.js index f593c7a3..5575e39b 100644 --- a/web/app/cad/scene/views/sketchLoopView.js +++ b/web/app/cad/scene/views/sketchLoopView.js @@ -1,4 +1,4 @@ -import {View} from './view'; +import {MarkTracker, View} from './view'; import * as SceneGraph from 'scene/sceneGraph'; import {tessellateLoopsOnSurface} from '../../tess/brep-tess'; import {createSolidMaterial} from '../wrappers/sceneObject'; @@ -9,7 +9,7 @@ import Vector from '../../../../../modules/math/vector'; import {LOOP} from '../entites'; import {setAttribute} from '../../../../../modules/scene/objectData'; -export class SketchLoopView extends View { +export class SketchLoopView extends MarkTracker(View) { constructor(mLoop) { super(mLoop); this.rootGroup = SceneGraph.createGroup(); @@ -17,11 +17,13 @@ export class SketchLoopView extends View { const geometry = new Geometry(); geometry.dynamic = true; this.mesh = new Mesh(geometry, createSolidMaterial({ - color: 0xDBFFD9, + color: SKETCH_LOOP_DEFAULT_HIGHLIGHT_COLOR, side: DoubleSide, + // transparent: true, + depthTest: true, + depthWrite: false, polygonOffset: true, - polygonOffsetFactor: 1, - polygonOffsetUnits: 0.1, + polygonOffsetFactor: -4, visible: false })); let surface = mLoop.face.surface; @@ -44,21 +46,26 @@ export class SketchLoopView extends View { this.rootGroup.add(this.mesh); this.mesh.onMouseEnter = (e) => { - this.mesh.material.visible = true; + this.mark(SKETCH_LOOP_DEFAULT_HIGHLIGHT_COLOR, 5); e.viewer.requestRender(); }; this.mesh.onMouseLeave = (e) => { - this.mesh.material.visible = false; + this.withdraw(5); e.viewer.requestRender(); }; } - mark(color) { - + mark(color = SKETCH_LOOP_DEFAULT_SELECT_COLOR, priority = 10) { + super.mark(color, priority); + } + + markImpl(color) { + this.mesh.material.visible = true; + this.mesh.material.color.setHex(color) } - withdraw(color) { - + withdrawImpl() { + this.mesh.material.visible = false; } dispose() { @@ -66,4 +73,7 @@ export class SketchLoopView extends View { this.mesh.geometry.dispose(); super.dispose(); } -} \ No newline at end of file +} + +const SKETCH_LOOP_DEFAULT_HIGHLIGHT_COLOR = 0xDBFFD9; +const SKETCH_LOOP_DEFAULT_SELECT_COLOR = 0xCCEFCA; \ No newline at end of file diff --git a/web/app/cad/scene/views/view.js b/web/app/cad/scene/views/view.js index b73b9058..a6518374 100644 --- a/web/app/cad/scene/views/view.js +++ b/web/app/cad/scene/views/view.js @@ -10,11 +10,10 @@ export class View { setVisible(value) { } - mark(color) { - + mark(color, priority) { } - withdraw() { + withdraw(priority) { } dispose() { @@ -23,3 +22,41 @@ export class View { }; } + +export const MarkTracker = ViewClass => class extends ViewClass { + + constructor(model) { + super(model); + this.marks = new Map(); + } + + mark(color, priority) { + this.marks.set(priority, color); + this.doMark(); + } + + withdraw(priority) { + this.marks.delete(priority); + this.doMark(); + } + + doMark() { + let keys = this.marks.keys(); + let maxPriority = - Number.MAX_VALUE; + for (let key of keys) { + if (key > maxPriority) { + maxPriority = key; + } + } + let color = this.marks.get(maxPriority); + if (color !== undefined) { + this.markImpl(color) + } else { + this.withdrawImpl(color) + } + } + + markImpl(color) {} + + withdrawImpl(color) {} +}; \ No newline at end of file