From 07db5af1dbbf7408cc12eddb39923d1a2e791cbd Mon Sep 17 00:00:00 2001 From: xibyte Date: Tue, 1 Feb 2022 03:24:44 -0800 Subject: [PATCH] schema from UI definition --- modules/gems/linkedMap.js | 2 +- modules/lstream/index.d.ts | 6 +- modules/occ/occ.d.ts | 14 -- modules/occ/occAdapters.ts | 11 -- modules/occ/occUtils.ts | 37 ------ .../features/extrude/extrude.operation.ts | 62 ++++----- test/coreTests/testCases/craftBoolean.js | 2 +- test/coreTests/testCases/craftDatum.js | 2 +- web/app/cad/craft/cadRegistryPlugin.ts | 4 +- web/app/cad/craft/craftPlugin.ts | 5 +- web/app/cad/craft/cutExtrude/cutExtrude.js | 3 +- web/app/cad/craft/e0/occIO.ts | 4 +- web/app/cad/craft/fillet/schema.js | 16 ++- web/app/cad/craft/intializeBySchema.js | 48 ------- web/app/cad/craft/materializeParams.js | 94 ------------- web/app/cad/craft/operationPlugin.ts | 46 +------ .../simplePlane/simplePlaneOpSchema.js | 3 +- .../cad/craft/schema/initializeBySchema.ts | 44 +++++++ web/app/cad/craft/schema/materializeParams.ts | 123 ++++++++++++++++++ web/app/cad/craft/schema/schema.ts | 33 +++++ web/app/cad/craft/schema/types/arrayType.ts | 39 ++++++ web/app/cad/craft/schema/types/entityType.ts | 37 ++++++ web/app/cad/craft/schema/types/enumType.ts | 26 ++++ web/app/cad/craft/schema/types/index.ts | 37 ++++++ web/app/cad/craft/schema/types/numberType.ts | 47 +++++++ web/app/cad/craft/schema/types/objectType.ts | 25 ++++ web/app/cad/craft/schemaUtils.js | 5 - .../wizard/components/form/MultiEntity.jsx | 2 +- web/app/cad/craft/wizard/wizardPlugin.js | 4 +- .../cad/craft/wizard/wizardSelectionPlugin.js | 94 ++++++------- web/app/cad/mdf/mdf.ts | 87 ++++++++----- web/app/cad/mdf/ui/AccordionWidget.tsx | 15 +++ web/app/cad/mdf/ui/ContainerWidget.tsx | 26 ++++ web/app/cad/mdf/ui/DynamicComponentWidget.tsx | 43 ++++++ web/app/cad/mdf/ui/GroupWidget.tsx | 22 ++++ web/app/cad/mdf/ui/NumberWidget.tsx | 31 +++++ web/app/cad/mdf/ui/SelectionWidget.tsx | 50 +++++++ web/app/cad/mdf/ui/componentRegistry.ts | 15 +++ web/app/cad/mdf/ui/field.ts | 20 +++ web/app/cad/mdf/ui/render.tsx | 7 + web/app/cad/mdf/ui/uiDefinition.ts | 24 ++++ web/app/cad/model/entities.ts | 22 ++++ web/app/cad/model/mdatum.ts | 8 +- web/app/cad/model/medge.ts | 3 +- web/app/cad/model/mface.ts | 3 +- web/app/cad/model/mloop.ts | 3 +- web/app/cad/model/mobject.ts | 5 +- web/app/cad/model/mshell.ts | 3 +- web/app/cad/model/msketchObject.ts | 3 +- web/app/cad/model/mvertex.ts | 3 +- .../scene/controls/defaultSelectionState.js | 2 +- .../cad/scene/controls/pickControlPlugin.js | 2 +- web/app/cad/scene/entites.js | 21 --- ...ontextPlugin.js => entityContextPlugin.ts} | 28 +++- .../cad/scene/selectionMarker/markerPlugin.js | 16 +-- web/app/cad/scene/views/datumView.js | 2 +- web/app/cad/scene/views/faceView.js | 2 +- web/app/cad/scene/views/openFaceView.js | 2 +- web/app/cad/scene/views/shellView.js | 2 +- web/app/cad/scene/views/sketchLoopView.js | 2 +- web/app/cad/sketch/inPlaceSketcher.js | 2 +- web/app/sketcher/constr/constractibles.js | 2 +- web/app/sketcher/project.js | 2 +- 63 files changed, 905 insertions(+), 448 deletions(-) delete mode 100644 modules/occ/occ.d.ts delete mode 100644 modules/occ/occAdapters.ts delete mode 100644 modules/occ/occUtils.ts delete mode 100644 web/app/cad/craft/intializeBySchema.js delete mode 100644 web/app/cad/craft/materializeParams.js create mode 100644 web/app/cad/craft/schema/initializeBySchema.ts create mode 100644 web/app/cad/craft/schema/materializeParams.ts create mode 100644 web/app/cad/craft/schema/schema.ts create mode 100644 web/app/cad/craft/schema/types/arrayType.ts create mode 100644 web/app/cad/craft/schema/types/entityType.ts create mode 100644 web/app/cad/craft/schema/types/enumType.ts create mode 100644 web/app/cad/craft/schema/types/index.ts create mode 100644 web/app/cad/craft/schema/types/numberType.ts create mode 100644 web/app/cad/craft/schema/types/objectType.ts delete mode 100644 web/app/cad/craft/schemaUtils.js create mode 100644 web/app/cad/mdf/ui/AccordionWidget.tsx create mode 100644 web/app/cad/mdf/ui/ContainerWidget.tsx create mode 100644 web/app/cad/mdf/ui/DynamicComponentWidget.tsx create mode 100644 web/app/cad/mdf/ui/GroupWidget.tsx create mode 100644 web/app/cad/mdf/ui/NumberWidget.tsx create mode 100644 web/app/cad/mdf/ui/SelectionWidget.tsx create mode 100644 web/app/cad/mdf/ui/componentRegistry.ts create mode 100644 web/app/cad/mdf/ui/field.ts create mode 100644 web/app/cad/mdf/ui/render.tsx create mode 100644 web/app/cad/mdf/ui/uiDefinition.ts create mode 100644 web/app/cad/model/entities.ts delete mode 100644 web/app/cad/scene/entites.js rename web/app/cad/scene/{entityContextPlugin.js => entityContextPlugin.ts} (69%) diff --git a/modules/gems/linkedMap.js b/modules/gems/linkedMap.js index 081783d6..c06b6b6e 100644 --- a/modules/gems/linkedMap.js +++ b/modules/gems/linkedMap.js @@ -21,7 +21,7 @@ export class OrderedMap { } has(key) { - this.map.has(key); + return this.map.has(key); } delete(key) { diff --git a/modules/lstream/index.d.ts b/modules/lstream/index.d.ts index 47aa20e1..d9dedf3f 100644 --- a/modules/lstream/index.d.ts +++ b/modules/lstream/index.d.ts @@ -5,15 +5,15 @@ interface Observable { interface Stream extends Observable { - map(fn: (value: T) => V); + map(fn: (value: T) => V); - filter(stream: Stream, predicate: (T) => boolean): Stream; + filter(predicate: (T) => boolean): Stream; pairwise(first: T): Stream<[T, T]>; scan(initAccumulator: any): Stream; - remember(initialValue: T, usingStream: any): Stream + remember(initialValue: T, usingStream: any): StateStream distinct(): Stream; diff --git a/modules/occ/occ.d.ts b/modules/occ/occ.d.ts deleted file mode 100644 index 47576e5f..00000000 --- a/modules/occ/occ.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {vectorTo_gp_Pnt} from "occ/occAdapters"; - -export interface OCC_Handle { - get(): T; -} - -export type OCC_Geom_TrimmedCurve = any; -export type OCC_Geom_Curve = any; -export type OCC_gp_Pnt = any; -export type OCC_gp_Vector = any; -export type OCC_TopoDS_Shape = any; -export type OCC_TopoDS_Edge = any; -export type OCC_TopoDS_Face = any; -export type OCC_ListOfShapes = any; diff --git a/modules/occ/occAdapters.ts b/modules/occ/occAdapters.ts deleted file mode 100644 index c7cd88da..00000000 --- a/modules/occ/occAdapters.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {OCC_gp_Pnt, OCC_gp_Vector} from "occ/occ"; -import Vector from "math/vector"; -import {OCCContext} from "cad/craft/occPlugin"; - -export function vectorTo_gp_Pnt(oc: OCCContext, v: Vector): OCC_gp_Pnt { - return new oc.gp_Pnt_3(v.x, v.y, v.z); -} - -export function vectorTo_gp_Vector(oc: OCCContext, v: Vector): OCC_gp_Vector { - return new oc.gp_Vec_4(v.x, v.y, v.z); -} diff --git a/modules/occ/occUtils.ts b/modules/occ/occUtils.ts deleted file mode 100644 index ed15c81f..00000000 --- a/modules/occ/occUtils.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - OCC_Geom_Curve, - OCC_Geom_TrimmedCurve, - OCC_Handle, OCC_ListOfShapes, - OCC_TopoDS_Edge, - OCC_TopoDS_Face, - OCC_TopoDS_Shape -} from "occ/occ"; -import {OCCContext} from "cad/craft/occPlugin"; - -export function upcastCurve(oc: OCCContext, curve: OCC_Handle): OCC_Handle { - return new oc.Handle_Geom_Curve_2(curve.get()); -} - -export function occIterateEdges(oc: OCCContext, root: OCC_TopoDS_Shape, callback: (edge: OCC_TopoDS_Edge) => any) { - const explorer = new oc.TopExp_Explorer_2(root, oc.TopAbs_ShapeEnum.TopAbs_EDGE, oc.TopAbs_ShapeEnum.TopAbs_SHAPE); - while(explorer.More()) { - callback(oc.TopoDS.Edge_1(explorer.Current())); - explorer.Next(); - } -} - -export function occIterateFaces(oc: OCCContext, root: OCC_TopoDS_Shape, callback: (edge: OCC_TopoDS_Face) => any) { - const explorer = new oc.TopExp_Explorer_2(root, oc.TopAbs_ShapeEnum.TopAbs_FACE, oc.TopAbs_ShapeEnum.TopAbs_SHAPE); - while(explorer.More()) { - callback(oc.TopoDS.Face_1(explorer.Current())); - explorer.Next(); - } -} - -export function occIterateListOfShape(oc: OCCContext, listOfShapes: OCC_ListOfShapes, callback: (edge: OCC_TopoDS_Shape) => any) { - const it = oc.TopTools_ListIteratorOfListOfShape(listOfShapes); - while (it.More()) { - callback(it.Value()); - it.Next(); - } -} diff --git a/modules/workbenches/modeler/features/extrude/extrude.operation.ts b/modules/workbenches/modeler/features/extrude/extrude.operation.ts index 14ca7367..d9035fea 100644 --- a/modules/workbenches/modeler/features/extrude/extrude.operation.ts +++ b/modules/workbenches/modeler/features/extrude/extrude.operation.ts @@ -1,25 +1,27 @@ import {roundValueForPresentation as r} from 'cad/craft/operationHelper'; import {MFace} from "cad/model/mface"; import {ApplicationContext} from "context"; +import {MDFCommand} from "cad/mdf/mdf"; +import {EntityKind} from "cad/model/entities"; interface ExtrudeParams { length: number; face: MFace; } -export default { +const ExtrudeOperation: MDFCommand = { id: 'EXTRUDE', label: 'Extrude', icon: 'img/cad/extrude', info: 'extrudes 2D sketch', - paramsInfo: ({value}) => `(${r(value)})`, + paramsInfo: ({length}) => `(${r(length)})`, mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'], run: (params: ExtrudeParams, ctx: ApplicationContext) => { let occ = ctx.occService; const oci = occ.commandInterface; - const face = ctx.cadRegistry.findFace(params.face); + const face = params.face; let sketch = ctx.sketchStorageService.readSketch(face.id); if (!sketch) throw 'sketch not found for the face ' + face.id; @@ -36,44 +38,26 @@ export default { }; }, - schema: { - length: { + + form: [ + { type: 'number', + label: 'length', + name: 'length', defaultValue: 50, - label: 'length' }, - - face: { - type: 'face', - initializeBySelection: 0 + { + type: 'selection', + name: 'face', + capture: [EntityKind.FACE], + label: 'face', + multi: false, + defaultValue: { + usePreselection: true, + preselectionIndex: 0 + }, }, - - direction: { - type: 'direction', - optional: true - }, - - datumAxisVector: { - type: 'datumAxis', - optional: true, - label: 'datum axis' - }, - edgeVector: { - type: 'edge', - optional: true, - label: 'edge', - accept: edge => edge.brepEdge.curve.degree === 1 - }, - sketchSegmentVector: { - type: 'sketchObject', - optional: true, - label: 'sketch segment', - accept: obj => obj.isSegment - }, - flip: { - type: 'boolean', - defaultValue: false, - } - - } + ], } + +export default ExtrudeOperation; \ No newline at end of file diff --git a/test/coreTests/testCases/craftBoolean.js b/test/coreTests/testCases/craftBoolean.js index c4e0e217..5933f1b0 100644 --- a/test/coreTests/testCases/craftBoolean.js +++ b/test/coreTests/testCases/craftBoolean.js @@ -1,4 +1,4 @@ -import {DATUM} from '../../../web/app/cad/scene/entites'; +import {DATUM} from 'cad/model/entities'; import {assertEquals, assertTrue} from '../utils/asserts'; export const TEST_MODE = 'modellerUI'; diff --git a/test/coreTests/testCases/craftDatum.js b/test/coreTests/testCases/craftDatum.js index fc8af4bd..64c80737 100644 --- a/test/coreTests/testCases/craftDatum.js +++ b/test/coreTests/testCases/craftDatum.js @@ -1,5 +1,5 @@ import {assertEquals, assertTrue} from '../utils/asserts'; -import {DATUM} from '../../../web/app/cad/scene/entites'; +import {DATUM} from 'cad/model/entities'; export const TEST_MODE = 'modellerUI'; diff --git a/web/app/cad/craft/cadRegistryPlugin.ts b/web/app/cad/craft/cadRegistryPlugin.ts index 2c426b3d..06d9011f 100644 --- a/web/app/cad/craft/cadRegistryPlugin.ts +++ b/web/app/cad/craft/cadRegistryPlugin.ts @@ -1,6 +1,6 @@ import {MShell} from '../model/mshell'; import {MObject} from "../model/mobject"; -import {ApplicationContext} from "context"; +import {ApplicationContext, CoreContext} from "context"; import {Stream} from "lstream"; import {MFace} from "../model/mface"; import {MEdge} from "../model/medge"; @@ -102,7 +102,7 @@ export interface CadRegistry { } declare module 'context' { - interface ApplicationContext { + interface CoreContext { cadRegistry: CadRegistry; } diff --git a/web/app/cad/craft/craftPlugin.ts b/web/app/cad/craft/craftPlugin.ts index 5f258ac2..30078dbc 100644 --- a/web/app/cad/craft/craftPlugin.ts +++ b/web/app/cad/craft/craftPlugin.ts @@ -1,11 +1,12 @@ import {addModification, stepOverriding} from './craftHistoryUtils'; import {Emitter, state, StateStream, stream} from 'lstream'; -import materializeParams from './materializeParams'; +import materializeParams from './schema/materializeParams'; import CadError from '../../utils/errors'; import {MObject, MObjectIdGenerator} from '../model/mobject'; import {intercept} from "lstream/intercept"; import {CoreContext} from "context"; import {MFace} from "../model/mface"; +import {OperationParams} from "cad/craft/schema/schema"; export function activate(ctx: CoreContext) { @@ -229,7 +230,7 @@ function historyTravel(modifications$) { export interface OperationRequest { type: string; - params: any; + params: OperationParams; } export interface OperationResult { diff --git a/web/app/cad/craft/cutExtrude/cutExtrude.js b/web/app/cad/craft/cutExtrude/cutExtrude.js index 0f65abd8..cb8933d9 100644 --- a/web/app/cad/craft/cutExtrude/cutExtrude.js +++ b/web/app/cad/craft/cutExtrude/cutExtrude.js @@ -98,7 +98,8 @@ export function getEncloseDetails(params, contours, target, csys, sketchSurface, } for (let i = 0; i < basePath.length; ++i) { const curve = basePath[i]; - let lidCurve = curve.translate(target); + let lidCurve = cur + ve.translate(target); if (applyPrism) { lidCurve = lidCurve.transform(prismTr); } diff --git a/web/app/cad/craft/e0/occIO.ts b/web/app/cad/craft/e0/occIO.ts index 6d85b00b..82cff5e5 100644 --- a/web/app/cad/craft/e0/occIO.ts +++ b/web/app/cad/craft/e0/occIO.ts @@ -11,8 +11,6 @@ export interface OCCIO { pushModel(model: MObject, name: string); - anchorModel(name: string); - cleanupRegistry(); sketchLoader: OCCSketchLoader @@ -39,7 +37,7 @@ export function createOCCIO(oci: OCCCommandInterface): OCCIO { return { - getShell, pushModel, anchorModel, cleanupRegistry, + getShell, pushModel, cleanupRegistry, sketchLoader: createOCCSketchLoader(oci) } diff --git a/web/app/cad/craft/fillet/schema.js b/web/app/cad/craft/fillet/schema.js index 026517ef..c4eec0e2 100644 --- a/web/app/cad/craft/fillet/schema.js +++ b/web/app/cad/craft/fillet/schema.js @@ -1,11 +1,21 @@ export default { edges: { type: 'array', - itemType: 'edge', - initializeBySelection: true + itemType: ['edge', 'face'], + + max: 1, + initializeBySelection: true, + ui: { + + } }, thickness: { type: 'number', - defaultValue: 20 + defaultValue: 20, + min: 10, + max: 30, + ui: { + widget: 'slider' + } } } diff --git a/web/app/cad/craft/intializeBySchema.js b/web/app/cad/craft/intializeBySchema.js deleted file mode 100644 index f6610d83..00000000 --- a/web/app/cad/craft/intializeBySchema.js +++ /dev/null @@ -1,48 +0,0 @@ -import {isEntityType} from './schemaUtils'; - -export default function initializeBySchema(schema, context) { - let fields = Object.keys(schema); - let obj = {}; - for (let field of fields ) { - let val; - let md = schema[field]; - if (md.type === 'array') { - if (md.itemType === 'object') { - if (md.defaultValue) { - val = md.defaultValue; - } else if (md.initializeBySelection === true) { - let {itemField, entity} = md.defaultValue; - val = context.streams.selection[entity].value.map(s => { - let item = initializeBySchema(md.schema, context); - item[itemField] = s; - return item; - }); - } else { - val = []; - } - } else if (isEntityType(md.itemType)) { - if (md.initializeBySelection === true) { - let entityContext = context.streams.selection[md.itemType]; - if (entityContext) { - val = [...entityContext.value]; - } - } else { - val = [] - } - } else { - throw 'unsupported'; - } - } else if (isEntityType(md.type) && md.initializeBySelection !== undefined) { - const entityContext = context.streams.selection[md.type]; - if (entityContext) { - val = entityContext.value[md.initializeBySelection]; - } - } else if (md.type === 'object') { - val = initializeBySchema(md.schema, context); - } else { - val = md.defaultValue; - } - obj[field] = val; - } - return obj; -} diff --git a/web/app/cad/craft/materializeParams.js b/web/app/cad/craft/materializeParams.js deleted file mode 100644 index 2a64ac36..00000000 --- a/web/app/cad/craft/materializeParams.js +++ /dev/null @@ -1,94 +0,0 @@ -import {isEntityType} from './schemaUtils'; - -export default function materializeParams(ctx, params, schema, result, errors, parentPath) { - - parentPath = parentPath || ROOT_PATH; - - for (let field of Object.keys(schema)) { - let md = schema[field]; - if (!md) { - continue; - } - let value = params[field]; - if (value === undefined || value === null || value === '') { - if (!md.optional) { - errors.push({path: [...parentPath, field], message: 'required'}); - } - } else { - if (md.type === 'number') { - try { - const valueType = typeof value; - if (valueType === 'string') { - value = ctx.expressionService.evaluateExpression(value); - } else if (valueType !== 'number') { - errors.push({path: [...parentPath, field], message: 'invalid value'}); - } - } catch (e) { - errors.push({path: [...parentPath, field], message: 'unable to evaluate expression'}); - } - - if (md.min !== undefined ) { - if (value < md.min) { - errors.push({path: [...parentPath, field], message: 'less than allowed'}); - } - } - if (md.max !== undefined ) { - if (value > md.max) { - errors.push({path: [...parentPath, field], message: 'greater than allowed'}); - } - } - } else if (md.type === 'string') { - if (typeof value !== 'string') { - errors.push({path: [...parentPath, field], message: 'not a string type'}); - } - } else if (md.type === 'boolean') { - value = !!value; - } else if (md.type === 'enum') { - if (md.values.indexOf(value) === -1) { - value = md.defaultValue || md.values[0]; - } - } else if (isEntityType(md.type)) { - if (typeof value !== 'string') { - errors.push({path: [...parentPath, field], message: 'not a valid model reference'}); - } - let ref = value.trim(); - if (!ref && !md.optional) { - errors.push({path: [...parentPath, field], message: 'required'}); - } - let model = ctx.cadRegistry.findEntity(md.type, ref); - if (!model) { - errors.push({path: [...parentPath, field], message: 'referrers to nonexistent ' + md.type}); - } - } else if (md.type === 'array') { - if (!Array.isArray(value)) { - errors.push({path: [...parentPath, field], message: 'not an array type'}); - continue; - } - if (md.min !== undefined && value.length < md.min) { - errors.push({path: [...parentPath, field], message: 'required minimum ' + md.min + ' elements'}); - } - if (md.max !== undefined && value.length > md.max) { - errors.push({path: [...parentPath, field], message: 'required maximum ' + md.max + ' elements'}); - } - if (md.itemType === 'object') { - value = value.map((item , i) => { - let itemResult = {}; - materializeParams(ctx, item, md.schema, itemResult, errors, [...parentPath, i]); - return itemResult; - }); - } else { - if (isEntityType(md.itemType)) { - value.forEach(ref => { - if (!ctx.cadRegistry.findEntity(md.itemType, ref)) { - errors.push({path: [...parentPath, field], message: 'referrers to nonexistent ' + md.itemType}); - } - }) - } - } - } - result[field] = value; - } - } -} - -const ROOT_PATH = []; \ No newline at end of file diff --git a/web/app/cad/craft/operationPlugin.ts b/web/app/cad/craft/operationPlugin.ts index ed7314c5..1242a8a7 100644 --- a/web/app/cad/craft/operationPlugin.ts +++ b/web/app/cad/craft/operationPlugin.ts @@ -1,10 +1,11 @@ import React from 'react'; import {state} from 'lstream'; import {IconType} from "react-icons"; -import {isEntityType} from './schemaUtils'; import {ActionAppearance} from "../actions/actionSystemPlugin"; import {ApplicationContext, CoreContext} from "context"; import {OperationResult} from "./craftPlugin"; +import {OperationSchema} from "cad/craft/schema/schema"; +import {FieldWidgetProps, UIDefinition} from "cad/mdf/ui/uiDefinition"; export function activate(ctx: ApplicationContext) { @@ -14,7 +15,7 @@ export function activate(ctx: ApplicationContext) { registry:registry$ }; - function addOperation(descriptor, actions) { + function addOperation(descriptor: OperationDescriptor, actions) { let {id, label, info, icon, actionParams} = descriptor; let appearance: ActionAppearance = { label, @@ -34,9 +35,7 @@ export function activate(ctx: ApplicationContext) { }; actions.push(opAction); - let schemaIndex = createSchemaIndex(descriptor.schema); - - registry$.mutate(registry => registry[id] = Object.assign({appearance, schemaIndex}, descriptor, { + registry$.mutate(registry => registry[id] = Object.assign({appearance}, descriptor, { run: (request, opContext) => runOperation(request, descriptor, opContext) })); } @@ -87,40 +86,8 @@ export interface Operation extends OperationDescriptor{ icon96: string; icon: string|IconType; }; - schemaIndex: { - entitiesByType: any; - entitiesByParam: any; - entityParams: any[]; - params: any[]; - }, } -function createSchemaIndex(schema) { - const entitiesByType = {}; - const entitiesByParam = {}; - const entityParams = []; - for (let field of Object.keys(schema)) { - let md = schema[field]; - let entityType = md.type === 'array' ? md.itemType : md.type; - - if (isEntityType(entityType)) { - let byType = entitiesByType[entityType]; - if (!byType) { - byType = []; - entitiesByType[entityType] = byType; - } - byType.push(field); - entitiesByParam[field] = entityType; - entityParams.push(field); - } - } - return {entitiesByType, entitiesByParam, - entityParams: Object.keys(entitiesByParam), - params: Object.keys(schema) - }; -} - - export interface OperationDescriptor { id: string; label: string; @@ -131,8 +98,9 @@ export interface OperationDescriptor { paramsInfo: (params: R) => string, previewGeomProvider?: (params: R) => OperationGeometryProvider, form: () => React.ReactNode, - schema: any, - onParamsUpdate?: (params, name, value) => void + schema: OperationSchema, + formFields: FieldWidgetProps[], + onParamsUpdate?: (params, name, value) => void, } export interface OperationService { diff --git a/web/app/cad/craft/primitives/simplePlane/simplePlaneOpSchema.js b/web/app/cad/craft/primitives/simplePlane/simplePlaneOpSchema.js index f5a03d37..a7c1b4f2 100644 --- a/web/app/cad/craft/primitives/simplePlane/simplePlaneOpSchema.js +++ b/web/app/cad/craft/primitives/simplePlane/simplePlaneOpSchema.js @@ -5,7 +5,8 @@ export default { defaultValue: 'XY' }, parallelTo: { - type: 'face', + type: 'entity', + allowedKinds: 'face', optional: true, }, depth: { diff --git a/web/app/cad/craft/schema/initializeBySchema.ts b/web/app/cad/craft/schema/initializeBySchema.ts new file mode 100644 index 00000000..0ddca6f3 --- /dev/null +++ b/web/app/cad/craft/schema/initializeBySchema.ts @@ -0,0 +1,44 @@ +import {TypeRegistry, Types} from "cad/craft/schema/types"; +import {OperationSchema, SchemaField} from "cad/craft/schema/schema"; +import {ApplicationContext} from "context"; + +export default function initializeBySchema(schema: OperationSchema, context: ApplicationContext) { + let fields = Object.keys(schema); + let obj = {}; + for (let field of fields) { + let val = undefined; + let md = schema[field] as SchemaField; + + if (md.type === Types.array) { + if (md.items.type === Types.entity && md.items.defaultValue !== undefined) { + const defaultValue = md.items.defaultValue; + if (defaultValue.usePreselection === true) { + const entitySchema = md.items; + const currentSelection = + context.entityContextService.selectedEntities.value.filter(e => entitySchema.allowedKinds.includes(e.TYPE)); + val = currentSelection.map(e => e.id); + } + } else { + val = md.defaultValue || []; + } + } else if (md.type === Types.entity && md.defaultValue !== undefined) { + const defaultValue = md.defaultValue; + if (defaultValue.usePreselection === true && defaultValue.preselectionIndex !== undefined) { + const allowedKinds = md.allowedKinds; + const currentSelection = + context.entityContextService.selectedEntities.value.filter(e => allowedKinds.includes(e.TYPE)); + + let mObject = currentSelection[defaultValue.preselectionIndex as number]; + if (mObject) { + val = mObject.id; + } + } + } else if (md.type === Types.object) { + val = md.defaultValue || initializeBySchema(md.schema, context); + } else { + val = md.defaultValue; + } + obj[field] = val; + } + return obj; +} diff --git a/web/app/cad/craft/schema/materializeParams.ts b/web/app/cad/craft/schema/materializeParams.ts new file mode 100644 index 00000000..ceb553ce --- /dev/null +++ b/web/app/cad/craft/schema/materializeParams.ts @@ -0,0 +1,123 @@ +import {TypeRegistry} from "cad/craft/schema/types"; +import {CoreContext} from "context"; +import { + OperationParams, + OperationParamsError, + OperationParamsErrorReporter, + OperationSchema +} from "cad/craft/schema/schema"; + +function createErrorReporter(path: string[], errors: OperationParamsError[]): OperationParamsErrorReporter { + + function report(message: string) { + errors.push({path, message}); + } + + report.dot = segment => createErrorReporter([...path, segment], errors); + + return report; +} + +export default function materializeParams(ctx: CoreContext, + params: OperationParams, + schema: OperationSchema, + result: any, + errors: OperationParamsError[]) { + return materializeParamsImpl(ctx, params, schema, result, createErrorReporter([], errors)) + +} + +function materializeParamsImpl(ctx: CoreContext, + params: OperationParams, + schema: OperationSchema, + result: any, + reportError: OperationParamsErrorReporter) { + + for (let field of Object.keys(schema)) { + const md = schema[field]; + let value = params[field]; + + if (value === undefined || value === null || value === '') { + if (!md.optional) { + reportError('required'); + } + } else { + const typeDef = TypeRegistry[md.type]; + value = typeDef.resolve(ctx, value, md as any, reportError.dot(field), materializeParamsImpl); + + // if (md.type === Types.NUMBER) { + // try { + // const valueType = typeof value; + // if (valueType === 'string') { + // value = ctx.expressionService.evaluateExpression(value); + // } else if (valueType !== 'number') { + // errors.push({path, message: 'invalid value'}); + // } + // } catch (e) { + // errors.push({path, message: 'unable to evaluate expression'}); + // } + // + // if (md.min !== undefined ) { + // if (value < md.min) { + // errors.push({path, message: 'less than allowed'}); + // } + // } + // if (md.max !== undefined ) { + // if (value > md.max) { + // errors.push({path, message: 'greater than allowed'}); + // } + // } + // } else if (md.type === Types.STRING) { + // if (typeof value !== 'string') { + // errors.push({path, message: 'not a string type'}); + // } + // } else if (md.type === Types.BOOLEAN) { + // value = !!value; + // } else if (md.type === Types.ENUM) { + // if (md.values.indexOf(value) === -1) { + // value = md.defaultValue || md.values[0]; + // } + // } else if (isEntityType(md.type)) { + // if (typeof value !== 'string') { + // errors.push({path, message: 'not a valid model reference'}); + // } + // let ref = value.trim(); + // if (!ref && !md.optional) { + // errors.push({path, message: 'required'}); + // } + // let model = ctx.cadRegistry.find(ref); + // if (!model) { + // errors.push({path, message: 'referrers to nonexistent ' + md.type}); + // } + // value = model; + // } else if (md.type === Types.ARRAY) { + // if (!Array.isArray(value)) { + // errors.push({path, message: 'not an array type'}); + // continue; + // } + // if (md.min !== undefined && value.length < md.min) { + // errors.push({path, message: 'required minimum ' + md.min + ' elements'}); + // } + // if (md.max !== undefined && value.length > md.max) { + // errors.push({path, message: 'required maximum ' + md.max + ' elements'}); + // } + // if (md.itemType === Types.OBJECT) { + // value = value.map((item , i) => { + // let itemResult = {}; + // materializeParams(ctx, item, md.schema, itemResult, errors, [...parentPath, i]); + // return itemResult; + // }); + // } else { + // if (isEntityType(md.itemType)) { + // value.forEach(ref => { + // if (!ctx.cadRegistry.findEntity(md.itemType, ref)) { + // errors.push({path, message: 'referrers to nonexistent ' + md.itemType}); + // } + // }) + // } + // } + // } + result[field] = value; + } + } +} diff --git a/web/app/cad/craft/schema/schema.ts b/web/app/cad/craft/schema/schema.ts new file mode 100644 index 00000000..5d350371 --- /dev/null +++ b/web/app/cad/craft/schema/schema.ts @@ -0,0 +1,33 @@ +import {Types} from "cad/craft/schema/types"; +import {NumberTypeSchema} from "cad/craft/schema/types/numberType"; +import {EntityTypeSchema} from "cad/craft/schema/types/entityType"; +import {ArrayTypeSchema} from "cad/craft/schema/types/arrayType"; +import {ObjectTypeSchema} from "cad/craft/schema/types/objectType"; +import {EnumTypeSchema} from "cad/craft/schema/types/enumType"; + +export type SchemaField = NumberTypeSchema | EntityTypeSchema | ArrayTypeSchema | ObjectTypeSchema | EnumTypeSchema; + +export type OperationSchema = { + [key: string]: SchemaField; +}; + +export interface BaseSchemaField { + defaultValue: Coercable, + optional: boolean, + label?: string +} + +export type Coercable = any; + +export type OperationParams = { + [key: string]: Coercable +} + +export type OperationParamsError = { + path: string[], + message: string +}; + +export type OperationParamsErrorReporter = ((msg: string) => void) & { + dot: (pathPart: string|number) => OperationParamsErrorReporter +}; \ No newline at end of file diff --git a/web/app/cad/craft/schema/types/arrayType.ts b/web/app/cad/craft/schema/types/arrayType.ts new file mode 100644 index 00000000..a8df2004 --- /dev/null +++ b/web/app/cad/craft/schema/types/arrayType.ts @@ -0,0 +1,39 @@ +import {Materializer, Type, TypeRegistry, Types} from "cad/craft/schema/types/index"; +import {CoreContext} from "context"; +import {BaseSchemaField, OperationParamsErrorReporter, SchemaField} from "cad/craft/schema/schema"; + +export interface ArrayTypeSchema extends BaseSchemaField { + + type: Types.array; + + items: SchemaField; + + min: number; + + max: number; +} + +export const ArrayType: Type = { + + resolve(ctx: CoreContext, + value: any[], + md: ArrayTypeSchema, + reportError: OperationParamsErrorReporter, + materializer: Materializer): any[] { + + if (!value || !Array.isArray(value)) { + reportError('not an array type'); + return []; + } + if (md.min !== undefined && value.length < md.min) { + reportError('required minimum ' + md.min + ' elements'); + } + if (md.max !== undefined && value.length > md.max) { + reportError('required maximum ' + md.max + ' elements'); + } + + const itemType = TypeRegistry[md.items.type]; + + return value.map((v, i) => itemType.resolve(ctx, v, md.items as any, reportError.dot(i), materializer)); + } +} diff --git a/web/app/cad/craft/schema/types/entityType.ts b/web/app/cad/craft/schema/types/entityType.ts new file mode 100644 index 00000000..afed12c5 --- /dev/null +++ b/web/app/cad/craft/schema/types/entityType.ts @@ -0,0 +1,37 @@ +import {Type, TypeRegistry, Types} from "cad/craft/schema/types/index"; +import {CoreContext} from "context"; +import {BaseSchemaField, OperationParamsErrorReporter} from "cad/craft/schema/schema"; +import {EntityKind} from "cad/model/entities"; +import {MObject} from "cad/model/mobject"; + +export interface EntityTypeSchema extends BaseSchemaField { + + type: Types.entity, + + allowedKinds: EntityKind[]; + + initializeBySelection: boolean | number; +} + +export const EntityType: Type = { + + resolve(ctx: CoreContext, + value: string, + md: EntityTypeSchema, + reportError: OperationParamsErrorReporter): MObject { + + if (typeof value !== 'string') { + reportError('not a valid model reference'); + } + let ref = value.trim(); + if (!ref && !md.optional) { + reportError('required'); + } + let model = ctx.cadRegistry.find(ref); + if (!model) { + reportError('refers to a nonexistent object'); + } + return model; + } + +} diff --git a/web/app/cad/craft/schema/types/enumType.ts b/web/app/cad/craft/schema/types/enumType.ts new file mode 100644 index 00000000..b5ce89d2 --- /dev/null +++ b/web/app/cad/craft/schema/types/enumType.ts @@ -0,0 +1,26 @@ +import {Materializer, Type, TypeRegistry, Types} from "cad/craft/schema/types/index"; +import {CoreContext} from "context"; +import {BaseSchemaField, OperationParamsErrorReporter} from "cad/craft/schema/schema"; + +export interface EnumTypeSchema extends BaseSchemaField { + + type: Types.number, + + values: string[] + +} + +export const EnumType: Type = { + + resolve(ctx: CoreContext, + value: any, + md: EnumTypeSchema, + reportError: OperationParamsErrorReporter, + materializer: Materializer): number { + + if (md.values.indexOf(value) === -1) { + value = md.defaultValue || md.values[0]; + } + return value; + } +} diff --git a/web/app/cad/craft/schema/types/index.ts b/web/app/cad/craft/schema/types/index.ts new file mode 100644 index 00000000..30d9fdaf --- /dev/null +++ b/web/app/cad/craft/schema/types/index.ts @@ -0,0 +1,37 @@ +import {CoreContext} from "context"; +import {OperationParams, OperationParamsErrorReporter, OperationSchema, SchemaField} from "cad/craft/schema/schema"; +import {ArrayType} from "cad/craft/schema/types/arrayType"; +import {EntityType} from "cad/craft/schema/types/entityType"; +import {NumberType} from "cad/craft/schema/types/numberType"; +import {ObjectType} from "cad/craft/schema/types/objectType"; +import {EnumType} from "cad/craft/schema/types/enumType"; + +export type Materializer = (ctx: CoreContext, + params: OperationParams, + schema: OperationSchema, + result: any, + reportError: OperationParamsErrorReporter) => void; + +export interface Type { + + resolve(ctx: CoreContext, value: IN, md: METADATA, + reportError: OperationParamsErrorReporter, + materializer: Materializer): OUT; + +} + +export enum Types { + array = 'array', + entity = 'entity', + number = 'number', + object = 'object', + enum = 'enum', +} + +export const TypeRegistry = { + [Types.array]: ArrayType, + [Types.entity]: EntityType, + [Types.number]: NumberType, + [Types.object]: ObjectType, + [Types.enum]: EnumType, +}; diff --git a/web/app/cad/craft/schema/types/numberType.ts b/web/app/cad/craft/schema/types/numberType.ts new file mode 100644 index 00000000..2f6f95d7 --- /dev/null +++ b/web/app/cad/craft/schema/types/numberType.ts @@ -0,0 +1,47 @@ +import {Materializer, Type, TypeRegistry, Types} from "cad/craft/schema/types/index"; +import {CoreContext} from "context"; +import {BaseSchemaField, OperationParamsErrorReporter, SchemaField} from "cad/craft/schema/schema"; +import {EntityType} from "cad/craft/schema/types/entityType"; + +export interface NumberTypeSchema extends BaseSchemaField { + + type: Types.number, + + min: number; + + max: number; + +} + +export const NumberType: Type = { + + resolve(ctx: CoreContext, + value: any, + md: NumberTypeSchema, + reportError: OperationParamsErrorReporter, + materializer: Materializer): number { + + try { + const valueType = typeof value; + if (valueType === 'string') { + value = ctx.expressionService.evaluateExpression(value); + } else if (valueType !== 'number') { + reportError('invalid value'); + } + } catch (e) { + reportError('unable to evaluate expression'); + } + + if (md.min !== undefined) { + if (value < md.min) { + reportError('less than allowed'); + } + } + if (md.max !== undefined) { + if (value > md.max) { + reportError('greater than allowed'); + } + } + return value; + } +} diff --git a/web/app/cad/craft/schema/types/objectType.ts b/web/app/cad/craft/schema/types/objectType.ts new file mode 100644 index 00000000..d0a661af --- /dev/null +++ b/web/app/cad/craft/schema/types/objectType.ts @@ -0,0 +1,25 @@ +import {Materializer, Type, TypeRegistry, Types} from "cad/craft/schema/types/index"; +import {CoreContext} from "context"; +import {BaseSchemaField, OperationParamsErrorReporter, OperationSchema} from "cad/craft/schema/schema"; + +export interface ObjectTypeSchema extends BaseSchemaField { + + type: Types.object; + + schema: OperationSchema; + +} + +export const ObjectType: Type = { + + resolve(ctx: CoreContext, + value: any, + md: ObjectTypeSchema, + reportError: OperationParamsErrorReporter, + materializer: Materializer): any { + + const result = {}; + materializer(ctx, value, md.schema, result, reportError); + return result; + } +} diff --git a/web/app/cad/craft/schemaUtils.js b/web/app/cad/craft/schemaUtils.js deleted file mode 100644 index d51af5ef..00000000 --- a/web/app/cad/craft/schemaUtils.js +++ /dev/null @@ -1,5 +0,0 @@ -import {ENTITIES} from '../scene/entites'; - -export function isEntityType(type) { - return ENTITIES.indexOf(type) !== -1 -} \ No newline at end of file diff --git a/web/app/cad/craft/wizard/components/form/MultiEntity.jsx b/web/app/cad/craft/wizard/components/form/MultiEntity.jsx index 28988c5a..63582d60 100644 --- a/web/app/cad/craft/wizard/components/form/MultiEntity.jsx +++ b/web/app/cad/craft/wizard/components/form/MultiEntity.jsx @@ -4,7 +4,7 @@ import Stack from 'ui/components/Stack'; import {FormContext} from '../form/Form'; import mapContext from 'ui/mapContext'; import PropTypes from 'prop-types'; -import initializeBySchema from '../../../intializeBySchema'; +import initializeBySchema from '../../../schema/initializeBySchema'; @attachToForm @mapContext(({streams}) => ({streams})) diff --git a/web/app/cad/craft/wizard/wizardPlugin.js b/web/app/cad/craft/wizard/wizardPlugin.js index 4269d8f5..52559e55 100644 --- a/web/app/cad/craft/wizard/wizardPlugin.js +++ b/web/app/cad/craft/wizard/wizardPlugin.js @@ -1,7 +1,7 @@ import {state} from 'lstream'; -import initializeBySchema from '../intializeBySchema'; +import initializeBySchema from '../schema/initializeBySchema'; import {clone, EMPTY_OBJECT} from 'gems/objects'; -import materializeParams from '../materializeParams'; +import materializeParams from '../schema/materializeParams'; import {createFunctionList} from 'gems/func'; import {onParamsUpdate} from '../cutExtrude/extrudeOperation'; import {propsChangeTracker} from 'lstream/utils'; diff --git a/web/app/cad/craft/wizard/wizardSelectionPlugin.js b/web/app/cad/craft/wizard/wizardSelectionPlugin.js index 958adca3..0d40e7d9 100644 --- a/web/app/cad/craft/wizard/wizardSelectionPlugin.js +++ b/web/app/cad/craft/wizard/wizardSelectionPlugin.js @@ -1,4 +1,5 @@ -import {DATUM, DATUM_AXIS, EDGE, FACE, LOOP, SHELL, SKETCH_OBJECT} from '../../scene/entites'; +import {FACE, SHELL} from '../../model/entities'; +import {memoize} from "lodash/function"; export function activate(ctx) { ctx.streams.wizard.wizardContext.attach(wizCtx => { @@ -9,16 +10,22 @@ export function activate(ctx) { wizCtx.workingRequest$.attach(({type, params}) => { const marker = ctx.services.marker; marker.startSession(); - let {schema, schemaIndex} = wizCtx.operation; - schemaIndex.entityParams.forEach(param => { - let color = schema[param].markColor; + let {schema} = wizCtx.operation; + Object.keys(schema).forEach(param => { + let md = schema[param]; + + if (md.type !== 'entity') { + return; + } + + //TODO: move to uiDefinition + let color = md.markColor; let val = params[param]; - let entity = schemaIndex.entitiesByParam[param]; if (Array.isArray(val)) { - val.forEach(id => marker.mark(entity, id, color)); + val.forEach(id => marker.mark(id, color)); } else { if (val) { - marker.mark(entity, val, color); + marker.mark(val, color); } } }); @@ -42,7 +49,10 @@ const arrayValue = (id, arr) => { return arr; }; +const getEntityParams = memoize(schema => Object.keys(schema).filter(key => schema[key].type === 'entity')); + function createPickHandlerFromSchema(wizCtx) { + function update(param, value, paramToMakeActive) { wizCtx.updateParam(param, value); wizCtx.updateState(state => { @@ -55,44 +65,44 @@ function createPickHandlerFromSchema(wizCtx) { const params = wizCtx.workingRequest$.value.params; const state = wizCtx.state$.value; - let {schema, schemaIndex} = wizCtx.operation; - const {entitiesByType, entitiesByParam, entityParams} = schemaIndex; + let {schema} = wizCtx.operation; const activeMd = state.activeParam && schema[state.activeParam]; - const activeEntity = state.activeParam && entitiesByParam[state.activeParam]; + const activeCanTakeIt = kind => activeMd.allowedKinds && activeMd.allowedKinds.includes(kind); - function select(param, entity, md, id) { + function select(param, md, id) { const valueGetter = md.type === 'array' ? arrayValue : singleValue; - let paramToMakeActive = getNextActiveParam(param, entity, md); + let paramToMakeActive = getNextActiveParam(param, md); update(param, valueGetter(id, params[param]), paramToMakeActive); } - function getNextActiveParam(currParam, entity, currMd) { + function getNextActiveParam(currParam, currMd) { if (currMd.type !== 'array') { - let entityGroup = entitiesByType[entity]; - if (entityGroup) { - const index = entityGroup.indexOf(currParam); - const nextIndex = (index + 1) % entityGroup.length; - return entityGroup[nextIndex]; - } + const entityParams = getEntityParams(schema); + const index = entityParams.indexOf(currParam); + const nextIndex = (index + 1) % entityParams.length; + return entityParams[nextIndex]; } return currParam; } function selectActive(id) { - select(state.activeParam, activeEntity, activeMd, id); + select(state.activeParam, activeMd, id); } function selectToFirst(entity, id) { - let entities = entitiesByType[entity]; - if (!entities) { - return false; + const entityParams = getEntityParams(schema); + for (let param of entityParams) { + const md = schema[param]; + if (md.allowedKinds.includes(entity)) { + select(param, md, id); + } } - let param = entities[0]; - select(param, entity, schema[param], id); + return true; } function deselectIfNeeded(id) { + const entityParams = getEntityParams(schema); for (let param of entityParams) { let val = params[param]; if (val === id) { @@ -117,44 +127,20 @@ function createPickHandlerFromSchema(wizCtx) { } if (modelType === FACE) { - if (activeEntity === SHELL) { + if (activeCanTakeIt(SHELL)) { selectActive(model.shell.id); - } else if (activeEntity === FACE) { + } else if (activeCanTakeIt(FACE)) { selectActive(model.id); } else { if (!selectToFirst(FACE, model.id)) { selectToFirst(SHELL, model.shell.id) } } - } else if (modelType === SKETCH_OBJECT) { - if (activeEntity === SKETCH_OBJECT) { + } else{ + if (activeCanTakeIt(modelType)) { selectActive(model.id); } else { - selectToFirst(SKETCH_OBJECT, model.id); - } - } else if (modelType === EDGE) { - if (activeEntity === EDGE) { - selectActive(model.id); - } else { - selectToFirst(EDGE, model.id); - } - } else if (modelType === DATUM) { - if (activeEntity === DATUM) { - selectActive(model.id); - } else { - selectToFirst(DATUM, model.id); - } - } else if (modelType === DATUM_AXIS) { - if (activeEntity === DATUM_AXIS) { - selectActive(model.id); - } else { - selectToFirst(DATUM_AXIS, model.id); - } - } else if (modelType === LOOP) { - if (activeEntity === LOOP) { - selectActive(model.id); - } else { - selectToFirst(LOOP, model.id); + selectToFirst(modelType, model.id); } } return false; diff --git a/web/app/cad/mdf/mdf.ts b/web/app/cad/mdf/mdf.ts index e73f4d18..bc98885d 100644 --- a/web/app/cad/mdf/mdf.ts +++ b/web/app/cad/mdf/mdf.ts @@ -1,41 +1,39 @@ -import { IconDeclaration } from "cad/icons/IconDeclaration"; -import { CoreContext } from "context"; -import { IconType } from "react-icons"; -import { OperationResult } from "../craft/craftPlugin"; -import { OperationDescriptor } from "../craft/operationPlugin"; -import { generateForm } from "./generateForm"; -import { resolveMDFIcon } from "./mdfIconResolver"; +import {IconDeclaration} from "cad/icons/IconDeclaration"; +import {CoreContext} from "context"; +import {IconType} from "react-icons"; +import {OperationResult} from "../craft/craftPlugin"; +import {OperationDescriptor} from "../craft/operationPlugin"; +import {resolveMDFIcon} from "./mdfIconResolver"; +import {OperationSchema} from "cad/craft/schema/schema"; +import { + DynamicWidgetProps, + FieldWidgetProps, FormDefinition, + isContainerWidgetProps, + isFieldWidgetProps, + UIDefinition +} from "cad/mdf/ui/uiDefinition"; +import {uiDefinitionToReact} from "cad/mdf/ui/render"; +import {DynamicComponents} from "cad/mdf/ui/componentRegistry"; - -interface MDFCommand { +export interface MDFCommand { id: string; label: string; info: string; icon: IconType | IconDeclaration; run: (request: R, opContext: CoreContext) => OperationResult | Promise; paramsInfo: (params: R) => string, - schema: OperationSchema, - mutualExclusiveFields?: string[] + mutualExclusiveFields?: string[], + form: FormDefinition } -export type Coercable = any; - -export type OperationSchema = { - [key: string]: SchemaField -}; - -export interface SchemaField { - type: 'number' | 'boolean' | 'string' | 'face' | 'datumAxis' | 'edge' | 'sketchObject', - enum?: { - value: string; - label: string; - }[]; - defaultValue: Coercable, - optional: boolean, - label?: string -} export function loadMDFCommand(mdfCommand: MDFCommand): OperationDescriptor { + const uiDefinition: UIDefinition = { + type: 'group', + content: mdfCommand.form + } + const formFields = extractFormFields(uiDefinition); + const derivedSchema = deriveSchema(formFields); return { id: mdfCommand.id, label: mdfCommand.label, @@ -51,11 +49,42 @@ export function loadMDFCommand(mdfCommand: MDFCommand): OperationDescripto // actionParams: { // ...requiresFaceSelection(1) // }, - form: generateForm(mdfCommand.schema), - schema: mdfCommand.schema + form: uiDefinitionToReact(uiDefinition), + formFields, + schema: derivedSchema } } +function extractFormFields(uiDefinition: UIDefinition): FieldWidgetProps[] { + + const fields: FieldWidgetProps[] = []; + + function inorder(comp: DynamicWidgetProps) { + + if (isFieldWidgetProps(comp)) { + fields.push(comp); + } + + if (isContainerWidgetProps(comp)) { + comp.content.forEach(inorder) + } + } + + inorder(uiDefinition); + + return fields; +} + +export function deriveSchema(formFields: FieldWidgetProps[]): OperationSchema { + const schema = {}; + formFields.forEach(f => { + let propsToSchema = DynamicComponents[f.type].propsToSchema; + schema[f.name] = propsToSchema(schema, f as any); + }); + return schema; +} + + export function handleMutualExclusiveFields(mutualExclusiveFields, params, name, value) { if (mutualExclusiveFields.includes(name)) { mutualExclusiveFields.forEach(param => { diff --git a/web/app/cad/mdf/ui/AccordionWidget.tsx b/web/app/cad/mdf/ui/AccordionWidget.tsx new file mode 100644 index 00000000..2b32d705 --- /dev/null +++ b/web/app/cad/mdf/ui/AccordionWidget.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import {ContainerBasicProps, ContainerWidgetProps} from "cad/mdf/ui/ContainerWidget"; + +export interface AccordionWidgetProps extends ContainerBasicProps { + + type: 'accordion'; + +} + +export function AccordionWidget(props: AccordionWidgetProps) { + return "TBD" +} + + + diff --git a/web/app/cad/mdf/ui/ContainerWidget.tsx b/web/app/cad/mdf/ui/ContainerWidget.tsx new file mode 100644 index 00000000..69cecb27 --- /dev/null +++ b/web/app/cad/mdf/ui/ContainerWidget.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import {DynamicWidgetProps} from "cad/mdf/ui/uiDefinition"; +import {DynamicComponentWidget} from "cad/mdf/ui/DynamicComponentWidget"; + +export interface ContainerBasicProps { + + content: DynamicWidgetProps[]; + +} + +export interface ContainerWidgetProps extends ContainerBasicProps { + + type: 'container', + +} + + +export function ContainerWidget({content}: ContainerBasicProps) { + + return {content.map((comp, i) => )}; + +} + + + + diff --git a/web/app/cad/mdf/ui/DynamicComponentWidget.tsx b/web/app/cad/mdf/ui/DynamicComponentWidget.tsx new file mode 100644 index 00000000..80ec0a76 --- /dev/null +++ b/web/app/cad/mdf/ui/DynamicComponentWidget.tsx @@ -0,0 +1,43 @@ +import React from 'react'; + +import {DynamicComponents} from "cad/mdf/ui/componentRegistry"; +import {DynamicWidgetProps} from "cad/mdf/ui/uiDefinition"; + + +export function DynamicComponentWidget(props: DynamicWidgetProps) { + const ToRender = DynamicComponents[props.type]; + if (!ToRender) { + return Unknown component: {props.type} + } + return + // return function DynamicUI() { + // return + // {Object.keys(schema).map(key => { + // + // const fieldDef: SchemaField = schema[key]; + // const label = fieldDef.label || key; + // + // if (fieldDef.type === 'number') { + // return + // } else if (fieldDef.type === 'string') { + // if (fieldDef.enum) { + // return + // {fieldDef.enum.map(opt => + // {opt.label} + // )} + // + // } else { + // return ; + // } + // } else if (['face', 'edge', 'sketchObject', 'datumAxis'].includes(fieldDef.type)) { + // return ; + // } else if (fieldDef.type === 'boolean') { + // return ; + // } else { + // return "I don't know"; + // } + // + // })} + // ; + // }; +} \ No newline at end of file diff --git a/web/app/cad/mdf/ui/GroupWidget.tsx b/web/app/cad/mdf/ui/GroupWidget.tsx new file mode 100644 index 00000000..8bdb7096 --- /dev/null +++ b/web/app/cad/mdf/ui/GroupWidget.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import {ContainerBasicProps, ContainerWidget} from "cad/mdf/ui/ContainerWidget"; +import {Group} from "cad/craft/wizard/components/form/Form"; + +export interface GroupWidgetProps extends ContainerBasicProps { + + type: 'group', + +} + + +export function GroupWidget({content}: GroupWidgetProps) { + + return + + + +} + + + + diff --git a/web/app/cad/mdf/ui/NumberWidget.tsx b/web/app/cad/mdf/ui/NumberWidget.tsx new file mode 100644 index 00000000..06fb6749 --- /dev/null +++ b/web/app/cad/mdf/ui/NumberWidget.tsx @@ -0,0 +1,31 @@ +import {NumberField} from "cad/craft/wizard/components/form/Fields"; +import React from "react"; +import {OperationSchema} from "cad/craft/schema/schema"; +import {FieldBasicProps, fieldToSchemaGeneric} from "cad/mdf/ui/field"; +import {Types} from "cad/craft/schema/types"; + +export interface NumberWidgetProps extends FieldBasicProps { + + type: 'number'; + + style?: 'slider' | 'default'; + + min?: number; + + max?: number; +} + +export function NumberWidget(props: NumberWidgetProps) { + return +} + +NumberWidget.propsToSchema = (consumer: OperationSchema, props: NumberWidgetProps) => { + return { + type: Types.number, + min: props.min, + max: props.max, + ...fieldToSchemaGeneric(props), + } +}; + + diff --git a/web/app/cad/mdf/ui/SelectionWidget.tsx b/web/app/cad/mdf/ui/SelectionWidget.tsx new file mode 100644 index 00000000..26afb03b --- /dev/null +++ b/web/app/cad/mdf/ui/SelectionWidget.tsx @@ -0,0 +1,50 @@ +import React from "react"; + +import Entity from "cad/craft/wizard/components/form/EntityList"; +import {EntityType} from "cad/craft/schema/types/entityType"; +import {OperationSchema, SchemaField} from "cad/craft/schema/schema"; +import {FieldBasicProps, fieldToSchemaGeneric} from "cad/mdf/ui/field"; +import {EntityKind} from "cad/model/entities"; +import {ArrayType, ArrayTypeSchema} from "cad/craft/schema/types/arrayType"; +import {Types} from "cad/craft/schema/types"; + + +export interface SelectionWidgetProps extends FieldBasicProps { + + type: 'selection'; + + multi?: boolean; + + capture: EntityKind[]; + + min?: number; + + max?: number; +} + +export function SelectionWidget(props: SelectionWidgetProps) { + return ; +} + +SelectionWidget.propsToSchema = (consumer: OperationSchema, props: SelectionWidgetProps) => { + + let value = { + type: Types.entity, + allowedKinds: props.capture, + initializeBySelection: true, + ...fieldToSchemaGeneric(props), + } as SchemaField; + + if (props.multi) { + const items = value; + value = { + type: Types.array, + min: props.min, + max: props.max, + items + } as ArrayTypeSchema; + } + return value; +}; + + diff --git a/web/app/cad/mdf/ui/componentRegistry.ts b/web/app/cad/mdf/ui/componentRegistry.ts new file mode 100644 index 00000000..ed15175a --- /dev/null +++ b/web/app/cad/mdf/ui/componentRegistry.ts @@ -0,0 +1,15 @@ +import {NumberWidget} from "cad/mdf/ui/NumberWidget"; +import {SelectionWidget} from "cad/mdf/ui/SelectionWidget"; +import {ContainerWidget} from "cad/mdf/ui/ContainerWidget"; +import {GroupWidget} from "cad/mdf/ui/GroupWidget"; + +export const DynamicComponents = { + + 'number': NumberWidget, + + 'selection': SelectionWidget, + + 'container': ContainerWidget, + + 'group': GroupWidget, +} \ No newline at end of file diff --git a/web/app/cad/mdf/ui/field.ts b/web/app/cad/mdf/ui/field.ts new file mode 100644 index 00000000..24498a8e --- /dev/null +++ b/web/app/cad/mdf/ui/field.ts @@ -0,0 +1,20 @@ +import {Coercable} from "cad/craft/schema/schema"; + +export interface FieldBasicProps { + + name: string; + + label?: string; + + defaultValue?: Coercable; + + optional?: boolean +} + +export function fieldToSchemaGeneric(props: FieldBasicProps) { + return { + label: props.label, + defaultValue: props.defaultValue, + optional: !!props.optional, + } +} \ No newline at end of file diff --git a/web/app/cad/mdf/ui/render.tsx b/web/app/cad/mdf/ui/render.tsx new file mode 100644 index 00000000..8759e9ea --- /dev/null +++ b/web/app/cad/mdf/ui/render.tsx @@ -0,0 +1,7 @@ +import React from 'react'; +import {DynamicComponentWidget} from "cad/mdf/ui/DynamicComponentWidget"; +import {UIDefinition} from "cad/mdf/ui/uiDefinition"; + +export function uiDefinitionToReact(uiDefinition: UIDefinition) { + return () => ; +} diff --git a/web/app/cad/mdf/ui/uiDefinition.ts b/web/app/cad/mdf/ui/uiDefinition.ts new file mode 100644 index 00000000..f5ee11d7 --- /dev/null +++ b/web/app/cad/mdf/ui/uiDefinition.ts @@ -0,0 +1,24 @@ +import {NumberWidgetProps} from "cad/mdf/ui/NumberWidget"; +import {SelectionWidgetProps} from "cad/mdf/ui/SelectionWidget"; +import {AccordionWidgetProps} from "cad/mdf/ui/AccordionWidget"; +import {DynamicComponents} from "cad/mdf/ui/componentRegistry"; +import {ContainerWidgetProps} from "cad/mdf/ui/ContainerWidget"; + +export type FieldWidgetProps = NumberWidgetProps | SelectionWidgetProps; + +export type BasicWidgetProps = ContainerWidgetProps | AccordionWidgetProps; + +export type DynamicWidgetProps = FieldWidgetProps | BasicWidgetProps; + +export type UIDefinition = DynamicWidgetProps; + +export type FormDefinition = DynamicWidgetProps[]; + + +export function isContainerWidgetProps(comp: DynamicWidgetProps): comp is ContainerWidgetProps { + return (comp as ContainerWidgetProps).content !== undefined; +} + +export function isFieldWidgetProps(comp: DynamicWidgetProps): comp is FieldWidgetProps { + return DynamicComponents[comp.type].propsToSchema !== undefined; +} diff --git a/web/app/cad/model/entities.ts b/web/app/cad/model/entities.ts new file mode 100644 index 00000000..7484e0c7 --- /dev/null +++ b/web/app/cad/model/entities.ts @@ -0,0 +1,22 @@ + +export enum EntityKind { + SHELL = 'shell', + FACE = 'face', + EDGE = 'edge', + VERTEX = 'vertex', + SKETCH_OBJECT = 'sketchObject', + DATUM = 'datum', + DATUM_AXIS = 'datumAxis', + LOOP = 'loop' +} + +//Backward comp. +export const SHELL = EntityKind.SHELL; +export const FACE = EntityKind.FACE; +export const EDGE = EntityKind.EDGE; +export const VERTEX = EntityKind.VERTEX; +export const SKETCH_OBJECT = EntityKind.SKETCH_OBJECT; +export const DATUM = EntityKind.DATUM; +export const DATUM_AXIS = EntityKind.DATUM_AXIS; +export const LOOP = EntityKind.LOOP; + diff --git a/web/app/cad/model/mdatum.ts b/web/app/cad/model/mdatum.ts index ed320c31..d36721c2 100644 --- a/web/app/cad/model/mdatum.ts +++ b/web/app/cad/model/mdatum.ts @@ -1,11 +1,11 @@ -import {MObject, MObjectIdGenerator, MRootObject} from './mobject'; +import {MObject, MObjectIdGenerator} from './mobject'; import CSys from "math/csys"; import Vector from "math/vector"; -import {Matrix3x4} from "math/matrix"; +import {EntityKind} from "cad/model/entities"; export class MDatum extends MObject { - static TYPE = 'datum'; + static TYPE = EntityKind.DATUM; csys: CSys; xAxis: MDatumAxis; yAxis: MDatumAxis; @@ -42,7 +42,7 @@ export class MDatum extends MObject { export class MDatumAxis extends MObject { - static TYPE = 'datumAxis'; + static TYPE = EntityKind.DATUM_AXIS; origin: Vector; dir: Vector; holder: MObject; diff --git a/web/app/cad/model/medge.ts b/web/app/cad/model/medge.ts index 38509f3d..7e0b134b 100644 --- a/web/app/cad/model/medge.ts +++ b/web/app/cad/model/medge.ts @@ -1,9 +1,10 @@ import {MObject} from './mobject'; import {MBrepShell} from "./mshell"; +import {EntityKind} from "cad/model/entities"; export class MEdge extends MObject { - static TYPE = 'edge'; + static TYPE = EntityKind.EDGE; shell: MBrepShell; brepEdge: any; diff --git a/web/app/cad/model/mface.ts b/web/app/cad/model/mface.ts index 9a69ab1d..2a882fd8 100644 --- a/web/app/cad/model/mface.ts +++ b/web/app/cad/model/mface.ts @@ -9,10 +9,11 @@ import {MBrepShell, MShell} from "./mshell"; import BBox from "math/bbox"; import {Basis, BasisForPlane} from "math/basis"; import {Face} from "brep/topo/face"; +import {EntityKind} from "cad/model/entities"; export class MFace extends MObject { - static TYPE = 'face'; + static TYPE = EntityKind.FACE; shell: MShell; surface: any; sketchObjects: MSketchObject[]; diff --git a/web/app/cad/model/mloop.ts b/web/app/cad/model/mloop.ts index 3f6ce612..deba964b 100644 --- a/web/app/cad/model/mloop.ts +++ b/web/app/cad/model/mloop.ts @@ -1,10 +1,11 @@ import {MObject} from './mobject'; import {MFace} from "./mface"; import {MSketchObject} from "./msketchObject"; +import {EntityKind} from "cad/model/entities"; export class MLoop extends MObject { - static TYPE = 'loop'; + static TYPE = EntityKind.LOOP; constructor(id) { super(MLoop.TYPE, id); diff --git a/web/app/cad/model/mobject.ts b/web/app/cad/model/mobject.ts index 50df1ea7..eddfb2c5 100644 --- a/web/app/cad/model/mobject.ts +++ b/web/app/cad/model/mobject.ts @@ -1,13 +1,14 @@ import {IDENTITY_MATRIX, Matrix3x4} from "math/matrix"; +import {EntityKind} from "cad/model/entities"; export abstract class MObject { - TYPE: string; + TYPE: EntityKind; id: string; ext: any = {}; - constructor(TYPE, id) { + protected constructor(TYPE, id) { this.TYPE = TYPE; this.id = id; } diff --git a/web/app/cad/model/mshell.ts b/web/app/cad/model/mshell.ts index a01b7f6d..38f2f86c 100644 --- a/web/app/cad/model/mshell.ts +++ b/web/app/cad/model/mshell.ts @@ -7,10 +7,11 @@ import {state, StateStream} from "lstream"; import {Matrix3x4} from "math/matrix"; import {Shell} from "brep/topo/shell"; import {TopoObject} from "brep/topo/topo-object"; +import {EntityKind} from "cad/model/entities"; export class MShell extends MObject { - static TYPE = 'shell'; + static TYPE = EntityKind.SHELL; csys: CSys; diff --git a/web/app/cad/model/msketchObject.ts b/web/app/cad/model/msketchObject.ts index 8578f708..654ebda0 100644 --- a/web/app/cad/model/msketchObject.ts +++ b/web/app/cad/model/msketchObject.ts @@ -1,9 +1,10 @@ import {MObject} from './mobject'; import {MFace} from "./mface"; +import {EntityKind} from "cad/model/entities"; export class MSketchObject extends MObject { - static TYPE = 'sketchObject'; + static TYPE = EntityKind.SKETCH_OBJECT; face: MFace; sketchPrimitive: any; construction: boolean; diff --git a/web/app/cad/model/mvertex.ts b/web/app/cad/model/mvertex.ts index 25a56317..d096ec6a 100644 --- a/web/app/cad/model/mvertex.ts +++ b/web/app/cad/model/mvertex.ts @@ -1,9 +1,10 @@ import {MObject} from './mobject'; import {MShell} from "./mshell"; +import {EntityKind} from "cad/model/entities"; export class MVertex extends MObject { - static TYPE = 'vertex'; + static TYPE = EntityKind.VERTEX; shell: MShell; brepVertex: any; diff --git a/web/app/cad/scene/controls/defaultSelectionState.js b/web/app/cad/scene/controls/defaultSelectionState.js index 6fe91b0b..1f44e80e 100644 --- a/web/app/cad/scene/controls/defaultSelectionState.js +++ b/web/app/cad/scene/controls/defaultSelectionState.js @@ -1,5 +1,5 @@ import {state} from 'lstream'; -import {DATUM, EDGE, FACE, SHELL, SKETCH_OBJECT} from '../entites'; +import {DATUM, EDGE, FACE, SHELL, SKETCH_OBJECT} from '../../model/entities'; const SELECTABLE_ENTITIES = [FACE, EDGE, SKETCH_OBJECT, DATUM, SHELL]; diff --git a/web/app/cad/scene/controls/pickControlPlugin.js b/web/app/cad/scene/controls/pickControlPlugin.js index 6dce7d86..6b0298c4 100644 --- a/web/app/cad/scene/controls/pickControlPlugin.js +++ b/web/app/cad/scene/controls/pickControlPlugin.js @@ -1,6 +1,6 @@ import * as mask from 'gems/mask' import {getAttribute, setAttribute} from 'scene/objectData'; -import {FACE, EDGE, SKETCH_OBJECT, DATUM, SHELL, DATUM_AXIS, LOOP} from '../entites'; +import {FACE, EDGE, SKETCH_OBJECT, DATUM, SHELL, DATUM_AXIS, LOOP} from '../../model/entities'; import {LOG_FLAGS} from '../../logFlags'; import * as vec from 'math/vec'; import {initRayCastDebug, printRaycastDebugInfo, RayCastDebugInfo} from "./rayCastDebug"; diff --git a/web/app/cad/scene/entites.js b/web/app/cad/scene/entites.js deleted file mode 100644 index 54494743..00000000 --- a/web/app/cad/scene/entites.js +++ /dev/null @@ -1,21 +0,0 @@ -import {MShell} from '../model/mshell'; -import {MFace} from '../model/mface'; -import {MEdge} from '../model/medge'; -import {MVertex} from '../model/mvertex'; -import {MSketchObject} from '../model/msketchObject'; -import {MDatum, MDatumAxis} from '../model/mdatum'; -import {MLoop} from '../model/mloop'; - -export const SHELL = MShell.TYPE; -export const FACE = MFace.TYPE; -export const EDGE = MEdge.TYPE; -export const VERTEX = MVertex.TYPE; -export const SKETCH_OBJECT = MSketchObject.TYPE; -export const DATUM = MDatum.TYPE; -export const DATUM_AXIS = MDatumAxis.TYPE; -export const LOOP = MLoop.TYPE; - - -export const ENTITIES = [SHELL, DATUM, FACE, EDGE, VERTEX, SKETCH_OBJECT, DATUM_AXIS, LOOP]; -export const PART_MODELING_ENTITIES = [SHELL, FACE, EDGE, VERTEX, SKETCH_OBJECT]; -export const ASSEMBLY_ENTITIES = [SHELL, FACE, EDGE, VERTEX]; diff --git a/web/app/cad/scene/entityContextPlugin.js b/web/app/cad/scene/entityContextPlugin.ts similarity index 69% rename from web/app/cad/scene/entityContextPlugin.js rename to web/app/cad/scene/entityContextPlugin.ts index b9048e14..22c6b0c7 100644 --- a/web/app/cad/scene/entityContextPlugin.js +++ b/web/app/cad/scene/entityContextPlugin.ts @@ -1,9 +1,10 @@ -import {state} from 'lstream'; +import {state, StateStream} from 'lstream'; import {addToListInMap} from 'gems/iterables'; import {EMPTY_ARRAY} from 'gems/iterables'; -import {DATUM, FACE, SHELL, SKETCH_OBJECT, EDGE, LOOP} from './entites'; +import {DATUM, FACE, SHELL, SKETCH_OBJECT, EDGE, LOOP} from '../model/entities'; import {combine} from "lstream"; +import {MObject} from "cad/model/mobject"; export const SELECTABLE_ENTITIES = [FACE, EDGE, SKETCH_OBJECT, DATUM, SHELL]; @@ -12,7 +13,8 @@ export function defineStreams(ctx) { SELECTABLE_ENTITIES.forEach(entity => { ctx.streams.selection[entity] = state([]); }); - ctx.streams.selection.all = combine(...Object.values(ctx.streams.selection)).map(selection => [].concat(...selection)).throttle(); + ctx.streams.selection.all = combine(...(Object.values(ctx.streams.selection) as StateStream[])) + .map(selection => [].concat(...selection)).throttle(); } export function activate(ctx) { @@ -20,8 +22,9 @@ export function activate(ctx) { SELECTABLE_ENTITIES.forEach(entity => { let entitySelectApi = { objects: [], - single: undefined - }; + single: undefined, + select: null as (ids: string[]) => void + }; ctx.services.selection[entity] = entitySelectApi; let selectionState = ctx.streams.selection[entity]; @@ -53,4 +56,17 @@ export function activate(ctx) { } }); }) -} \ No newline at end of file + + ctx.entityContextService = { + selectedEntities: ctx.streams.selection.all.map(ids => ids.map(ctx.cadRegistry.find)).remember() + } +} + +declare module 'context' { + interface CoreContext { + + entityContextService: { + selectedEntities: StateStream + }; + } +} diff --git a/web/app/cad/scene/selectionMarker/markerPlugin.js b/web/app/cad/scene/selectionMarker/markerPlugin.js index c45b3e72..756c0f53 100644 --- a/web/app/cad/scene/selectionMarker/markerPlugin.js +++ b/web/app/cad/scene/selectionMarker/markerPlugin.js @@ -2,7 +2,7 @@ import {OrderedMap} from 'gems/linkedMap'; import {eventStream} from 'lstream'; export function activate(ctx) { - ctx.services.marker = createMarker(ctx.services.cadRegistry.findEntity, ctx.services.viewer.requestRender); + ctx.services.marker = createMarker(ctx.services.cadRegistry.find, ctx.services.viewer.requestRender); ctx.streams.craft.models.attach(() => { ctx.services.marker.clear(); }); @@ -19,8 +19,8 @@ function createMarker(findEntity, requestRender) { const notify = () => $markedEntities.next(marked); const isMarked = id => marked.has(id); - function doMark(entity, id, color) { - let mObj = findEntity(entity, id); + function doMark(id, color) { + let mObj = findEntity(id); if (!mObj) { console.warn('no entity found to highlight: ' + entity + ' ' + id); return; @@ -57,19 +57,19 @@ function createMarker(findEntity, requestRender) { function markExclusively(entity, id, color) { withdrawAllOfType(entity); - doMark(entity, id, color); + doMark(id, color); onUpdate(); } function markArrayExclusively(entity, ids, color) { withdrawAllOfType(entity); - ids.forEach(id => doMark(entity, id, color)); + ids.forEach(id => doMark(id, color)); onUpdate(); } function markAdding(entity, id, color) { if (!marked.has(id)) { - doMark(entity, id, color); + doMark(id, color); onUpdate(); } } @@ -81,13 +81,13 @@ function createMarker(findEntity, requestRender) { needUpdate = false; } - function mark(entity, id, color) { + function mark(id, color) { if (!sessionInProgress) { throw 'can be called only withing a session'; } markingSession.add(id); if (!marked.has(id)) { - doMark(entity, id, color); + doMark(id, color); needUpdate = true; } } diff --git a/web/app/cad/scene/views/datumView.js b/web/app/cad/scene/views/datumView.js index 6b641328..0744470b 100644 --- a/web/app/cad/scene/views/datumView.js +++ b/web/app/cad/scene/views/datumView.js @@ -1,6 +1,6 @@ import {View} from './view'; import DatumObject3D from '../../craft/datum/datumObject'; -import {DATUM, DATUM_AXIS} from '../entites'; +import {DATUM, DATUM_AXIS} from '../../model/entities'; import {setAttribute} from 'scene/objectData'; import {Mesh, MeshBasicMaterial, PolyhedronGeometry, SphereGeometry} from 'three'; import {CSYS_SIZE_MODEL} from '../../craft/datum/csysObject'; diff --git a/web/app/cad/scene/views/faceView.js b/web/app/cad/scene/views/faceView.js index 33354b66..880ab8dd 100644 --- a/web/app/cad/scene/views/faceView.js +++ b/web/app/cad/scene/views/faceView.js @@ -1,6 +1,6 @@ import {setAttribute} from 'scene/objectData'; import {brepFaceToGeom, tessDataToGeom} from '../wrappers/brepSceneObject'; -import {FACE} from '../entites'; +import {FACE} from '../../model/entities'; import * as SceneGraph from 'scene/sceneGraph'; import {SketchObjectView} from './sketchObjectView'; import {View} from './view'; diff --git a/web/app/cad/scene/views/openFaceView.js b/web/app/cad/scene/views/openFaceView.js index 5111f910..bdc78cd8 100644 --- a/web/app/cad/scene/views/openFaceView.js +++ b/web/app/cad/scene/views/openFaceView.js @@ -1,5 +1,5 @@ import {setAttribute} from 'scene/objectData'; -import {FACE, SHELL} from '../entites'; +import {FACE, SHELL} from '../../model/entities'; import {NULL_COLOR, SELECTION_COLOR, setFacesColor, SketchingView} from './faceView'; import {View} from './view'; import {SketchMesh} from './shellView'; diff --git a/web/app/cad/scene/views/shellView.js b/web/app/cad/scene/views/shellView.js index 410fb1d3..f2b0c257 100644 --- a/web/app/cad/scene/views/shellView.js +++ b/web/app/cad/scene/views/shellView.js @@ -4,7 +4,7 @@ import {getAttribute, setAttribute} from 'scene/objectData'; import {createSolidMaterial} from '../wrappers/sceneObject'; import {FaceView, SELECTION_COLOR} from './faceView'; import {EdgeView} from './edgeView'; -import {FACE, SHELL} from '../entites'; +import {FACE, SHELL} from '../../model/entities'; import {Mesh} from 'three'; import {VertexView} from "./vertexView"; diff --git a/web/app/cad/scene/views/sketchLoopView.js b/web/app/cad/scene/views/sketchLoopView.js index 4e73c2ad..18c1d4ee 100644 --- a/web/app/cad/scene/views/sketchLoopView.js +++ b/web/app/cad/scene/views/sketchLoopView.js @@ -6,7 +6,7 @@ import {DoubleSide, Geometry, Mesh} from 'three'; import {surfaceAndPolygonsToGeom} from '../wrappers/brepSceneObject'; import {TriangulatePolygons} from '../../tess/triangulation'; import Vector from 'math/vector'; -import {LOOP} from '../entites'; +import {LOOP} from '../../model/entities'; import {setAttribute} from 'scene/objectData'; export class SketchLoopView extends MarkTracker(View) { diff --git a/web/app/cad/sketch/inPlaceSketcher.js b/web/app/cad/sketch/inPlaceSketcher.js index 33bd2342..11d779c4 100644 --- a/web/app/cad/sketch/inPlaceSketcher.js +++ b/web/app/cad/sketch/inPlaceSketcher.js @@ -48,7 +48,7 @@ export class InPlaceSketcher { this.ctx.streams.ui.toolbars.headsUpShowTitles.next(false); let sketchData = this.ctx.services.storage.get(this.sketchStorageKey); - this.viewer.historyManager.init(sketchData); + this.viewer.historyManager.init(sketchData, md); this.viewer.io.loadSketch(sketchData); this.ctx.streams.sketcher.sketchingFace.next(face); this.ctx.streams.sketcher.sketcherAppContext.next(this.sketcherAppContext); diff --git a/web/app/sketcher/constr/constractibles.js b/web/app/sketcher/constr/constractibles.js index d47d199d..988dc780 100644 --- a/web/app/sketcher/constr/constractibles.js +++ b/web/app/sketcher/constr/constractibles.js @@ -106,7 +106,7 @@ export class GCCircle extends ContractibleObject { static TYPE = 'GCCircle'; static newInstance(x, y, r) { - return GCCircle().init(new GCPoint(x, y), new GCParam(r)) + return GCCircle().init(new GCPoint(x, y), md) } init(c, r) { diff --git a/web/app/sketcher/project.js b/web/app/sketcher/project.js index d085b445..9509e765 100644 --- a/web/app/sketcher/project.js +++ b/web/app/sketcher/project.js @@ -47,7 +47,7 @@ export class Project { let sketchId = this.getSketchId(); let sketchData = localStorage.getItem(sketchId); if (sketchData != null) { - this.viewer.historyManager.init(sketchData); + this.viewer.historyManager.init(sketchData, md); this.viewer.io.loadSketch(sketchData); } this.viewer.repaint();