diff --git a/web/app/cad/context/index.ts b/web/app/cad/context/index.ts index 6d22b4df..f4c84f71 100644 --- a/web/app/cad/context/index.ts +++ b/web/app/cad/context/index.ts @@ -22,6 +22,7 @@ import {SketchStorageBundleContext} from "cad/sketch/sketchStorageBundle"; import {StorageBundleContext} from "cad/storage/storageBundle"; import {WorkbenchBundleContext} from "cad/workbench/workbenchBundle"; import {LegacyStructureBundleContext} from "cad/context/LegacyStructureBundle"; +import {PickControlBundleContext} from "cad/scene/controls/pickControlBundle"; export interface ApplicationContext extends LegacyStructureBundleContext, @@ -47,7 +48,8 @@ export interface ApplicationContext extends SketcherBundleContext, SketchStorageBundleContext, StorageBundleContext, - WorkbenchBundleContext + WorkbenchBundleContext, + PickControlBundleContext {} export default {} as ApplicationContext; diff --git a/web/app/cad/craft/wizard/wizardSelectionBundle.ts b/web/app/cad/craft/wizard/wizardSelectionBundle.ts index cff344fe..207f5275 100644 --- a/web/app/cad/craft/wizard/wizardSelectionBundle.ts +++ b/web/app/cad/craft/wizard/wizardSelectionBundle.ts @@ -1,7 +1,7 @@ import {FACE} from 'cad/model/entities'; import {OperationRequest} from "cad/craft/craftBundle"; -import {ParamsPath, WizardService} from "cad/craft/wizard/wizardTypes"; -import {OperationParamPrimitive} from "cad/craft/schema/schema"; +import {ParamsPath, WizardService, WizardState, WorkingRequest} from "cad/craft/wizard/wizardTypes"; +import {OperationParamPrimitive, OperationParams, OperationParamValue} from "cad/craft/schema/schema"; import {EntityReference} from "cad/craft/operationBundle"; import {Bundle} from "bundler/bundleSystem"; import {MarkerBundleContext} from "cad/scene/selectionMarker/markerBundle"; @@ -9,6 +9,7 @@ import {WizardBundleContext} from "cad/craft/wizard/wizardBundle"; import {PickControlBundleContext} from "cad/scene/controls/pickControlBundle"; import _ from "lodash"; import {MObject} from "cad/model/mobject"; +import {combine} from "lstream"; type WizardSelectionBundleActivationContext = MarkerBundleContext & WizardBundleContext & PickControlBundleContext; @@ -63,6 +64,27 @@ export const WizardSelectionBundle: Bundle syncMarkers(); } }); + + combine(wizardService.state$, wizardService.workingRequest$).attach(([state, req]: [WizardState, WorkingRequest]) => { + if (req && state?.activeParam && ctx.wizardService.operation) { + + const entity = ctx.wizardService.operation.schemaIndex.entitiesByFlattenedPaths[state.activeParam]; + + if (entity) { + ctx.pickControlService.setSelectionFilter(entity.metadata.entityCapture); + } else { + ctx.pickControlService.setSelectionFilter(() => false); + } + } else { + ctx.pickControlService.setSelectionFilter(null); + } + }); + + wizardService.state$.attach(state => { + if (state?.activeParam) { + + } + }) }, BundleName: "@WizardSelection", diff --git a/web/app/cad/scene/controls/PickListDialog.tsx b/web/app/cad/scene/controls/PickListDialog.tsx index 18559cb5..2ab6f9b9 100644 --- a/web/app/cad/scene/controls/PickListDialog.tsx +++ b/web/app/cad/scene/controls/PickListDialog.tsx @@ -1,11 +1,11 @@ -import React from "react"; +import React, {useContext} from "react"; import {state} from "lstream"; import {useStreamWithUpdater} from "ui/effects"; import Window from "ui/components/Window"; import {MObject} from "cad/model/mobject"; import Stack from "ui/components/Stack"; -import {ModelSection} from "cad/craft/ui/SceneInlineObjectExplorer"; import {ModelButton} from "cad/craft/ui/ModelButton"; +import {ReactApplicationContext} from "cad/dom/ReactApplicationContext"; export interface PickListDialogRequest { @@ -21,6 +21,8 @@ export function PickListDialog() { const [req, setReq] = useStreamWithUpdater(() => PickListDialogRequest$); + const ctx = useContext(ReactApplicationContext); + const close = () => setReq(null); if (!req) { @@ -35,12 +37,14 @@ export function PickListDialog() { className='small-typography' onClose={close}> - {req.capture.map(model => { - return - })} + {req.capture + .filter(model => ctx.pickControlService.isSelectionEnabledFor(model)) + .map(model => { + return + })} diff --git a/web/app/cad/scene/controls/pickControlBundle.ts b/web/app/cad/scene/controls/pickControlBundle.ts index 705a0d20..af984072 100644 --- a/web/app/cad/scene/controls/pickControlBundle.ts +++ b/web/app/cad/scene/controls/pickControlBundle.ts @@ -1,6 +1,6 @@ import * as mask from 'gems/mask' import {getAttribute} from 'scene/objectData'; -import {DATUM, DATUM_AXIS, EDGE, FACE, LOOP, SHELL, SKETCH_OBJECT} from 'cad/model/entities'; +import {DATUM, DATUM_AXIS, EDGE, EntityKind, FACE, LOOP, SHELL, SKETCH_OBJECT} from 'cad/model/entities'; import {LOG_FLAGS} from 'cad/logFlags'; import {initRayCastDebug, printRaycastDebugInfo, RayCastDebugInfo} from "./rayCastDebug"; import {PickListDialog, PickListDialogRequest$} from "cad/scene/controls/PickListDialog"; @@ -20,6 +20,10 @@ export interface PickControlService { releasePickControl(controlToken: PickControlToken); + setSelectionFilter(selectionFilter: (entity: MObject) => boolean); + + isSelectionEnabledFor(entity: MObject): boolean; + deselectAll() pick() @@ -61,6 +65,9 @@ interface PickContext { export const ALL_EXCLUDING_SOLID_KINDS = PICK_KIND.FACE | PICK_KIND.SKETCH | PICK_KIND.EDGE | PICK_KIND.DATUM_AXIS | PICK_KIND.LOOP; export const ALL_POSSIBLE_KIND = Number.MAX_SAFE_INTEGER; + +const ALLOW_ALL = (kind) => true; + export function activate(context) { const {services} = context; @@ -112,7 +119,9 @@ export function activate(context) { let pickContext: PickContext = defaultPickContext; let contextStack = []; - + + let selectionFilter: (kind: EntityKind) => boolean = ALLOW_ALL; + const domElement = services.viewer.sceneSetup.domElement(); domElement.addEventListener('mousedown', mousedown, false); @@ -187,6 +196,12 @@ export function activate(context) { pickContext.syncMarkers(); } + function setSelectionFilter(_selectionFilter: (kind: EntityKind) => boolean) { + selectionFilter = _selectionFilter || ALLOW_ALL; + } + + const isSelectionEnabledFor = (kind: EntityKind) => selectionFilter(kind); + const deselectAll = () => { if (pickContext !== defaultPickContext) { console.info("deselect all cannot be used in current context"); @@ -259,7 +274,8 @@ export function activate(context) { } services.pickControl = { - takePickControl, releasePickControl, deselectAll, pick, pickFromRay, simulatePickFromRay + takePickControl, releasePickControl, setSelectionFilter, isSelectionEnabledFor, + deselectAll, pick, pickFromRay, simulatePickFromRay }; context.pickControlService = services.pickControl; diff --git a/web/app/cad/scene/viewSyncBundle.js b/web/app/cad/scene/viewSyncBundle.js index 07ebf8d5..80ba166d 100644 --- a/web/app/cad/scene/viewSyncBundle.js +++ b/web/app/cad/scene/viewSyncBundle.js @@ -9,6 +9,7 @@ import DatumView from './views/datumView'; import {View} from './views/view'; import {HighlightBundle} from "cad/scene/highlightBundle"; import {AttributesBundle} from "cad/attributes/attributesBundle"; +import {EntityKind} from "cad/model/entities"; export const ViewSyncBundle = { @@ -16,18 +17,32 @@ export const ViewSyncBundle = { activationDependencies: [ HighlightBundle.BundleName, - AttributesBundle.BundleName + AttributesBundle.BundleName, + "@PickControl" ], activate(ctx) { const {streams} = ctx; ctx.highlightService.highlightEvents.attach(id => { const model = ctx.cadRegistry.find(id); - model?.ext?.view?.mark('highlight'); + if (model) { + if (ctx.pickControlService.isSelectionEnabledFor(model)) { + model.ext?.view?.mark('highlight'); + } else if (model.TYPE === EntityKind.FACE && model.parent) { + if (ctx.pickControlService.isSelectionEnabledFor(model.parent)) { + model.parent?.ext?.view?.mark('highlight'); + } + } + } }); ctx.highlightService.unHighlightEvents.attach(id => { const model = ctx.cadRegistry.find(id); - model?.ext?.view?.withdraw('highlight'); + if (model) { + model.ext?.view?.withdraw('highlight'); + if (model.TYPE === EntityKind.FACE && model.parent) { + model.parent.ext?.view?.withdraw('highlight'); + } + } }); streams.cadRegistry.update.attach(sceneSynchronizer(ctx));