work on MDF

This commit is contained in:
xibyte 2022-02-19 23:44:42 -08:00 committed by Val Erastov
parent e07fd2c5e6
commit 31032051fc
23 changed files with 312 additions and 408 deletions

View file

@ -1,6 +1,11 @@
import React from 'react';
export default function ImgIcon({url, size, style, ...props}) {
type ImgIconParams = { url: string; size: string|number; style?: any; };
export default function ImgIcon(inprops: ImgIconParams) {
const {url, size, style, ...props} = inprops;
return <span className='img-icon' style={{
display: 'inline-block',
backgroundImage: 'url('+url+')',
@ -10,4 +15,4 @@ export default function ImgIcon({url, size, style, ...props}) {
height: size + 'px',
...style
}} {...props} />
};
}

View file

@ -1,23 +1,20 @@
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";
import Vector from "math/vector";
import { BooleanDefinition } from "cad/craft/schema/common/BooleanDefinition";
import { MShell } from 'cad/model/mshell';
import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
import {ApplicationContext} from "context";
import {EntityKind} from "cad/model/entities";
import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
import {OperationDescriptor} from "cad/craft/operationPlugin";
interface BooleanParams {
tools: [];
boolean: BooleanDefinition
}
const BooleanOperation: MDFCommand<BooleanParams> = {
const BooleanOperation: OperationDescriptor<BooleanParams> = {
id: 'boolean_tool',
label: 'Boolean',
icon: 'img/cad/Boolean',
info: 'Booleans 2D sketch',
paramsInfo: ({ tools, boolean }) => `(${r(tools)} ${r(boolean)})`,
paramsInfo: ({tools, boolean}) => `(${r(tools)} ${r(boolean)})`,
run: (params: BooleanParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;

View file

@ -1,10 +1,10 @@
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";
import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
import {UnitVector} from "math/vector";
import {OperationDescriptor} from "cad/craft/operationPlugin";
interface ExtrudeParams {
@ -14,13 +14,12 @@ interface ExtrudeParams {
boolean: BooleanDefinition
}
const ExtrudeOperation: MDFCommand<ExtrudeParams> = {
const ExtrudeOperation: OperationDescriptor<ExtrudeParams> = {
id: 'EXTRUDE',
label: 'Extrude',
icon: 'img/cad/extrude',
info: 'extrudes 2D sketch',
paramsInfo: ({length}) => `(${r(length)})`,
mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'],
run: (params: ExtrudeParams, ctx: ApplicationContext) => {
let occ = ctx.occService;

View file

@ -1,137 +1,140 @@
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";
import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
import {ApplicationContext} from "context";
import {EntityKind} from "cad/model/entities";
import {OperationDescriptor} from "cad/craft/operationPlugin";
interface HoleParams {
diameter: number;
depth: number;
counterBoreDiameter: number;
counterBoreDepth: number;
countersinkDiameter: number;
countersinkAngle: number;
holeType: string;
diameter: number;
depth: number;
counterBoreDiameter: number;
counterBoreDepth: number;
countersinkDiameter: number;
countersinkAngle: number;
holeType: string;
}
const HoleOperation: MDFCommand<HoleParams> = {
id: 'hole_tool',
label: 'hole',
icon: 'img/cad/Shell',
info: 'creates hole features',
paramsInfo: ({ diameter, depth, counterBoreDiameter, counterBoreDepth, countersinkDiameter, countersinkAngle, holeType, }) => `(${r(depth)} ${r(counterBoreDiameter)}) ${r(counterBoreDepth)})`,
const HoleOperation: OperationDescriptor<HoleParams> = {
id: 'hole_tool',
label: 'hole',
icon: 'img/cad/Shell',
info: 'creates hole features',
paramsInfo: ({
diameter,
depth,
counterBoreDiameter,
counterBoreDepth,
countersinkDiameter,
countersinkAngle,
holeType,
}) => `(${r(depth)} ${r(counterBoreDiameter)}) ${r(counterBoreDepth)})`,
run: (params: HoleParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;
const oci = occ.commandInterface;
run: (params: HoleParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;
const oci = occ.commandInterface;
var returnObject = {
consumed: [],
created: []
};
var returnObject = {
consumed: [],
created: []
};
oci.pcylinder("basehole", params.diameter / 2, params.depth);
oci.pcylinder("basehole", params.diameter / 2, params.depth);
if (params.holeType == "normal") {
returnObject.created.push(occ.io.getShell("basehole"));
}
if (params.holeType == "normal") {
returnObject.created.push(occ.io.getShell("basehole"));
}
if (params.holeType == "counterbore") {
oci.pcylinder("counterbore", params.counterBoreDiameter / 2, params.counterBoreDepth);
if (params.holeType == "counterbore") {
oci.pcylinder("counterbore", params.counterBoreDiameter / 2, params.counterBoreDepth);
oci.bop("basehole", "counterbore");
oci.bopfuse("result");
oci.bop("basehole", "counterbore");
oci.bopfuse("result");
returnObject.created.push(occ.io.getShell("result"));
}
returnObject.created.push(occ.io.getShell("result"));
}
if (params.holeType == "countersink") {
if (params.holeType == "countersink") {
let heightFromDiameterAndAngle = (params.countersinkDiameter - params.diameter) / (Math.tan((params.countersinkAngle / 180 * Math.PI) / 2));
let heightFromDiameterAndAngle = (params.countersinkDiameter - params.diameter) / (Math.tan((params.countersinkAngle / 180 * Math.PI) / 2));
oci.pcone("countersink", params.countersinkDiameter / 2, 0, heightFromDiameterAndAngle);
oci.bop("basehole", "countersink");
oci.bopfuse("result");
returnObject.created.push(occ.io.getShell("result"));
}
oci.pcone("countersink", params.countersinkDiameter / 2, 0, heightFromDiameterAndAngle);
oci.bop("basehole", "countersink");
oci.bopfuse("result");
returnObject.created.push(occ.io.getShell("result"));
}
console.log(returnObject);
return returnObject;
console.log(returnObject);
return returnObject;
},
form: [
{
type: 'selection',
name: 'sketch',
capture: [EntityKind.FACE],
label: 'faces',
multi: true,
defaultValue: {
usePreselection: true,
preselectionIndex: 0
},
},
form: [
{
type: 'selection',
name: 'sketch',
capture: [EntityKind.FACE],
label: 'faces',
multi: true,
defaultValue: {
usePreselection: true,
preselectionIndex: 0
},
},
{
type: 'choice',
label: 'HoleType',
name: "holeType",
style: "dropdown",
defaultValue: "counterbore",
values: ['counterbore', 'countersink', 'normal',],
},
{
type: 'choice',
label: 'HoleType',
name: "holeType",
style: "dropdown",
defaultValue: "counterbore",
values: ['counterbore', 'countersink', 'normal',],
},
{
type: 'number',
name: "diameter",
defaultValue: 10,
label: 'Hole ⌀'
},
{
type: 'number',
name: "depth",
defaultValue: 100,
label: 'Hole ↧'
},
{
type: 'number',
name: "diameter",
defaultValue: 10,
label: 'Hole ⌀'
},
{
type: 'number',
name: "depth",
defaultValue: 100,
label: 'Hole ↧'
},
{
type: 'number',
name: "counterBoreDiameter",
defaultValue: 20,
label: '⌴ ⌀'
},
{
type: 'number',
name: "counterBoreDepth",
defaultValue: 10,
label: '⌴ ↧'
},
{
type: 'number',
name: "counterBoreDiameter",
defaultValue: 20,
label: '⌴ ⌀'
},
{
type: 'number',
name: "counterBoreDepth",
defaultValue: 10,
label: '⌴ ↧'
},
{
type: 'number',
name: "countersinkDiameter",
defaultValue: 20,
label: '⌵ ⌀'
},
{
type: 'number',
name: "countersinkAngle",
defaultValue: 90,
label: '⌵ Angle'
},
],
{
type: 'number',
name: "countersinkDiameter",
defaultValue: 20,
label: '⌵ ⌀'
},
{
type: 'number',
name: "countersinkAngle",
defaultValue: 90,
label: '⌵ Angle'
},
],
}
export default HoleOperation;

View file

@ -1,83 +1,77 @@
import { ApplicationContext } from 'context';
import { roundValueForPresentation as r } from 'cad/craft/operationHelper';
import { MDFCommand } from "cad/mdf/mdf";
import { EntityKind } from "cad/model/entities";
import { BooleanDefinition } from "cad/craft/schema/common/BooleanDefinition";
import {ApplicationContext} from 'context';
import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
import {EntityKind} from "cad/model/entities";
import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
import {OperationDescriptor} from "cad/craft/operationPlugin";
interface PrimitiveBoxParams {
x: Number,
y: Number,
z: Number,
locations: {},
boolean: BooleanDefinition,
x: Number,
y: Number,
z: Number,
locations: {},
boolean: BooleanDefinition,
}
const PrimitiveBoxOperation: MDFCommand<PrimitiveBoxParams> = {
id: 'primitive_box',
label: 'Primitive Box',
icon: 'img/cad/extrude',
info: 'Primitive Box',
paramsInfo: ({ x, y, z }) => `(${r(x)} , ${r(y)} , ${r(z)})`,
form: [
{
type: 'number',
label: 'X',
name: 'x',
defaultValue: 50,
},
{
type: 'number',
label: 'Y',
name: 'y',
defaultValue: 50,
},
{
type: 'number',
label: 'Z',
name: 'z',
defaultValue: 50,
},
{
type: 'selection',
name: 'locations',
capture: [EntityKind.DATUM],
label: 'locations',
multi: false,
optional: true,
defaultValue: {
usePreselection: true,
preselectionIndex: 0
},
},
{
type: 'boolean',
name: 'boolean',
label: 'boolean',
optional: true,
}
],
run: (params: PrimitiveBoxParams, ctx: ApplicationContext) => {
let occ = ctx.occService;
const oci = occ.commandInterface;
oci.box("b", params.x,params.y,params.z);
return occ.utils.applyBooleanModifier(["b"], params.boolean);
const PrimitiveBoxOperation: OperationDescriptor<PrimitiveBoxParams> = {
id: 'primitive_box',
label: 'Primitive Box',
icon: 'img/cad/extrude',
info: 'Primitive Box',
paramsInfo: ({x, y, z}) => `(${r(x)} , ${r(y)} , ${r(z)})`,
form: [
{
type: 'number',
label: 'X',
name: 'x',
defaultValue: 50,
},
{
type: 'number',
label: 'Y',
name: 'y',
defaultValue: 50,
},
{
type: 'number',
label: 'Z',
name: 'z',
defaultValue: 50,
},
{
type: 'selection',
name: 'locations',
capture: [EntityKind.DATUM],
label: 'locations',
multi: false,
optional: true,
defaultValue: {
usePreselection: true,
preselectionIndex: 0
},
},
{
type: 'boolean',
name: 'boolean',
label: 'boolean',
optional: true,
}
],
run: (params: PrimitiveBoxParams, ctx: ApplicationContext) => {
let occ = ctx.occService;
const oci = occ.commandInterface;
oci.box("b", params.x, params.y, params.z);
return occ.utils.applyBooleanModifier(["b"], params.boolean);
},
}
export default PrimitiveBoxOperation;

View file

@ -1,12 +1,10 @@
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";
import Vector from "math/vector";
import { BooleanDefinition } from "cad/craft/schema/common/BooleanDefinition";
import * as vec from "math/vec";
import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
import {MFace} from "cad/model/mface";
import {ApplicationContext} from "context";
import {EntityKind} from "cad/model/entities";
import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
import Axis from "math/axis";
import {OperationDescriptor} from "cad/craft/operationPlugin";
interface RevolveParams {
angle: number;
@ -14,14 +12,13 @@ interface RevolveParams {
axis: Axis,
boolean: BooleanDefinition
}
const RevolveOperation: MDFCommand<RevolveParams> = {
const RevolveOperation: OperationDescriptor<RevolveParams> = {
id: 'Revolve',
label: 'Revolve',
icon: 'img/cad/Revolve',
info: 'Revolves 2D sketch',
paramsInfo: ({ angle }) => `(${r(angle)})`,
mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'],
paramsInfo: ({angle}) => `(${r(angle)})`,
run: (params: RevolveParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;
@ -43,12 +40,6 @@ const RevolveOperation: MDFCommand<RevolveParams> = {
});
return occ.utils.applyBooleanModifier(tools, params.boolean);
},

View file

@ -1,8 +1,8 @@
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";
import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
import {MFace} from "cad/model/mface";
import {ApplicationContext} from "context";
import {EntityKind} from "cad/model/entities";
import {OperationDescriptor} from "cad/craft/operationPlugin";
interface ShellParams {
@ -10,21 +10,18 @@ interface ShellParams {
faces: [MFace];
}
const ShellOperation: MDFCommand<ShellParams> = {
const ShellOperation: OperationDescriptor<ShellParams> = {
id: 'shell_tool',
label: 'Shell',
icon: 'img/cad/Shell',
info: 'Shells 2D sketch',
paramsInfo: ({ thickness }) => `(${r(thickness)})`,
paramsInfo: ({thickness}) => `(${r(thickness)})`,
run: (params: ShellParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;
const oci = occ.commandInterface;
var bodiesToShell = [];
var returnObject = {
consumed: [],

View file

@ -5,10 +5,13 @@ import {ActionAppearance} from "../actions/actionSystemPlugin";
import {ApplicationContext, CoreContext} from "context";
import {OperationResult} from "./craftPlugin";
import {OperationSchema, SchemaField, schemaIterator, unwrapMetadata} from "cad/craft/schema/schema";
import {FieldWidgetProps} from "cad/mdf/ui/uiDefinition";
import {FormDefinition} from "cad/mdf/ui/uiDefinition";
import {Types} from "cad/craft/schema/types";
import {EntityTypeSchema} from "cad/craft/schema/types/entityType";
import {FlattenPath, ParamsPath} from "cad/craft/wizard/wizardTypes";
import {IconDeclaration} from "cad/icons/IconDeclaration";
import {resolveIcon} from "cad/craft/ui/iconResolver";
import {loadDeclarativeForm} from "cad/mdf/declarativeFormLoader";
export function activate(ctx: ApplicationContext) {
@ -19,7 +22,14 @@ export function activate(ctx: ApplicationContext) {
};
function addOperation(descriptor: OperationDescriptor<any>, actions) {
let {id, label, info, icon, actionParams} = descriptor;
let {id, label, info, icon, actionParams, form, schema} = descriptor;
if (!schema) {
let {schema: derivedSchema, form: loadedForm} = loadDeclarativeForm(form as FormDefinition);
schema = derivedSchema;
form = loadedForm;
}
let appearance: ActionAppearance = {
label,
info
@ -28,7 +38,7 @@ export function activate(ctx: ApplicationContext) {
appearance.icon32 = icon + '32.png';
appearance.icon96 = icon + '96.png';
} else {
appearance.icon = icon;
appearance.icon = resolveIcon(icon);
}
let opAction = {
id: id,
@ -38,10 +48,16 @@ export function activate(ctx: ApplicationContext) {
};
actions.push(opAction);
let schemaIndex = createSchemaIndex(descriptor.schema);
registry$.mutate(registry => registry[id] = Object.assign({appearance, schemaIndex}, descriptor, {
run: (request, opContext) => runOperation(request, descriptor, opContext)
}));
let schemaIndex = createSchemaIndex(schema);
let operation = {
appearance,
schemaIndex,
...descriptor,
schema, form
};
registry$.mutate(registry => registry[id] = operation);
}
function registerOperations(operations) {
@ -60,22 +76,9 @@ export function activate(ctx: ApplicationContext) {
return op;
}
let handlers = [];
function runOperation(request, descriptor, opContext) {
for (let handler of handlers) {
let result = handler(descriptor.id, request, opContext);
if (result) {
return result;
}
}
return descriptor.run(request, opContext);
}
ctx.operationService = {
registerOperations,
get,
handlers
get
};
ctx.services.operation = ctx.operationService;
@ -90,31 +93,28 @@ export interface Operation<R> extends OperationDescriptor<R>{
icon96: string;
icon: string|IconType;
};
schemaIndex: SchemaIndex
schemaIndex: SchemaIndex;
form: () => React.ReactNode;
schema: OperationSchema;
}
export interface OperationDescriptor<R> {
id: string;
label: string;
info: string;
icon: IconType | string | ((props: any) => JSX.Element);
icon: IconDeclaration | IconType | string | ((props: any) => JSX.Element);
actionParams?: any;
run: (request: R, opContext: CoreContext) => OperationResult | Promise<OperationResult>;
paramsInfo: (params: R) => string,
previewGeomProvider?: (params: R) => OperationGeometryProvider,
form: () => React.ReactNode,
schema: OperationSchema,
form: FormDefinition | (() => React.ReactNode),
schema?: OperationSchema,
onParamsUpdate?: (params, name, value) => void,
}
export interface OperationService {
registerOperations(descriptior: OperationDescriptor<any>[]);
get<T>(operationId: string): Operation<T>;
handlers: ((
id: string,
request: any,
opContext: CoreContext
) => void)[]
}
export type Index<T> = {

View file

@ -10,8 +10,8 @@ export default function initializeBySchema(schema: OperationSchema, context: App
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 (md.items.type === Types.entity && md.defaultValue !== undefined) {
const defaultValue = md.defaultValue;
if (defaultValue.usePreselection === true) {
const entitySchema = md.items;
const currentSelection =

View file

@ -33,12 +33,14 @@ function materializeParamsImpl(ctx: CoreContext,
result: any,
parentReportError: OperationParamsErrorReporter) {
const notProvided = value => value === undefined || value === null || value === '';
for (let field of Object.keys(schema)) {
const reportError = parentReportError.dot(field);
const md = schema[field];
let value = params[field];
if (value === undefined || value === null || value === '') {
if (notProvided(value)) {
if (!md.optional) {
reportError('required');
}
@ -50,6 +52,9 @@ function materializeParamsImpl(ctx: CoreContext,
value = md.resolve(
ctx, value, md as any, reportError
)
if (notProvided(value) && !md.optional) {
reportError('required');
}
}
// if (md.type === Types.NUMBER) {

View file

@ -28,7 +28,7 @@ export type OperationFlattenSchema = {
};
export interface BaseSchemaField {
defaultValue: OperationParamValue,
defaultValue?: OperationParamValue,
optional: boolean,
label?: string,
resolve?: ValueResolver<any, any>

View file

@ -11,6 +11,10 @@ export interface ArrayTypeSchema extends BaseSchemaField {
min: number;
max: number;
defaultValue: {
usePreselection: boolean;
}
}
export const ArrayType: Type<any[], any[], ArrayTypeSchema> = {

View file

@ -10,7 +10,10 @@ export interface EntityTypeSchema extends BaseSchemaField {
allowedKinds: EntityKind[];
initializeBySelection: boolean | number;
defaultValue?: {
usePreselection: boolean;
preselectionIndex: number;
}
}
export const EntityType: Type<string, MObject, EntityTypeSchema> = {

View file

@ -4,7 +4,7 @@ import React from 'react';
import { AiOutlineQuestion } from 'react-icons/ai';
import { IconType } from 'react-icons/lib';
export function resolveMDFIcon(iconDef: IconDeclaration | IconType) {
export function resolveIcon(iconDef: IconDeclaration | IconType) {
if (iconDef.iconType || iconDef.iconSet) {
return (props) => <DeclaredIcon {...iconDef} {...props}/>
} else {

View file

@ -111,14 +111,15 @@ function createPickHandlerFromSchema(wizCtx: WizardContext) {
function deselectIfNeeded(id) {
for (let entityRef of schemaIndex.entities) {
const val = wizCtx.readParam(entityRef.field.path);
let val = wizCtx.readParam(entityRef.field.path);
if (val === id) {
update(entityRef.field.path, undefined, entityRef.field.flattenedPath);
return true;
} else if (Array.isArray(val)) {
let index = val.indexOf(id);
if (index !== -1) {
update(entityRef.field.path, val.splice(index, 1), entityRef.field.flattenedPath);
val = val.slice(index, 1);
update(entityRef.field.path, val, entityRef.field.flattenedPath);
return true;
}
}

View file

@ -8,12 +8,12 @@ interface IconRenderProps {
size: IconSize
}
export function DeclaredIcon(props: IconRenderProps & IconDeclaration & React.HTMLAttributes<HTMLDivElement>) {
export function DeclaredIcon({iconSet, iconType, ...props}: IconRenderProps & IconDeclaration & React.HTMLAttributes<HTMLDivElement>) {
if (props.iconSet) {
return <IconSet {...props} />
if (iconSet) {
return <IconSet iconSet={iconSet} {...props} />
} else {
return <Icon {...props} />
return <Icon iconType={iconType} {...props} />
}
}

View file

@ -4,7 +4,7 @@ export enum IconSize {
small = 'small',
medium = 'medium',
large = 'large'
};
}
export interface IconSetDef {
iconType: IconType;

View file

@ -1,54 +1,24 @@
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, isSubFormWidgetProps,
isFieldWidgetProps,
isSubFormWidgetProps,
UIDefinition
} from "cad/mdf/ui/uiDefinition";
import {uiDefinitionToReact} from "cad/mdf/ui/render";
import {ComponentLibrary, DynamicComponents} from "cad/mdf/ui/componentRegistry";
export interface MDFCommand<R> {
id: string;
label: string;
info: string;
icon: IconType | IconDeclaration;
run: (request: R, opContext: CoreContext) => OperationResult | Promise<OperationResult>;
paramsInfo: (params: R) => string,
mutualExclusiveFields?: string[],
form: FormDefinition
}
export function loadMDFCommand<R>(mdfCommand: MDFCommand<R>): OperationDescriptor<R> {
export function loadDeclarativeForm(form: FormDefinition) {
const uiDefinition: UIDefinition = {
type: 'group',
content: mdfCommand.form
content: form
}
const derivedSchema = deriveSchema(uiDefinition);
return {
id: mdfCommand.id,
label: mdfCommand.label,
icon: resolveMDFIcon(mdfCommand.icon),
info: mdfCommand.info,
paramsInfo: mdfCommand.paramsInfo,
onParamsUpdate: (params, name, value) => {
if (mdfCommand.mutualExclusiveFields) {
handleMutualExclusiveFields(mdfCommand.mutualExclusiveFields, params, name, value);
}
},
run: mdfCommand.run,
// actionParams: {
// ...requiresFaceSelection(1)
// },
form: uiDefinitionToReact(uiDefinition),
schema: derivedSchema
}
@ -95,14 +65,3 @@ export function deriveSchema(uiDefinition: UIDefinition): OperationSchema {
return schema;
}
export function handleMutualExclusiveFields(mutualExclusiveFields, params, name, value) {
if (mutualExclusiveFields.includes(name)) {
mutualExclusiveFields.forEach(param => {
if (param !== name) {
delete params[param];
}
})
}
}

View file

@ -1,65 +0,0 @@
import { roundValueForPresentation as r } from '../craft/operationHelper';
export const MDF_EXTRUDE_EXAMPLE = {
id: 'EXTRUDE',
label: 'Extrude',
icon: 'img/cad/extrude',
info: 'extrudes 2D sketch',
paramsInfo: ({ value }) => `(${r(value)})`,
mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'],
run: (params, ctx) => {
return ctx.craftEngine.cutExtrude(false, params);
},
schema: {
value: {
type: 'number',
defaultValue: 50,
label: 'height'
},
wierdField: {
type: 'number',
defaultValue: 50,
label: 'weird field'
},
prism: {
type: 'number',
min: 0,
defaultValue: 1
},
angle: {
type: 'number',
defaultValue: 0
},
rotation: {
type: 'number',
defaultValue: 0
},
face: {
type: 'face',
initializeBySelection: 0
},
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,
}
}
}

View file

@ -40,7 +40,6 @@ export interface AxisWidgetProps extends FieldBasicProps {
type: 'axis';
resolve: ValueResolver<AxisInput, any>;
}
const ENTITY_CAPTURE = [EntityKind.EDGE, EntityKind.SKETCH_OBJECT, EntityKind.DATUM_AXIS, EntityKind.FACE];
@ -65,6 +64,7 @@ export const AxisBasedWidgetDefinition = (props: AxisBasedWidgetProps) => ({
type: 'sub-form',
name: props.name,
resolve: props.resolve,
optional: props.optional,
content: [
{
name: "vectorEntity",

View file

@ -1,9 +1,10 @@
import {ComboBoxField, NumberField} from "cad/craft/wizard/components/form/Fields";
import React from "react";
import {OperationSchema} from "cad/craft/schema/schema";
import {flattenPath, OperationSchema} from "cad/craft/schema/schema";
import {FieldBasicProps, fieldToSchemaGeneric} from "cad/mdf/ui/field";
import {Types} from "cad/craft/schema/types";
import {ComboBoxOption} from "ui/components/controls/ComboBoxControl";
import {FormContext, FormContextData} from "cad/craft/wizard/components/form/Form";
export interface ChoiceWidgetProps extends FieldBasicProps {
@ -17,9 +18,22 @@ export interface ChoiceWidgetProps extends FieldBasicProps {
export function ChoiceWidget(props: ChoiceWidgetProps) {
if (!props.style || props.style === 'dropdown') {
return <ComboBoxField name={props.name} defaultValue={props.defaultValue} label={props.label} >
{props.values.map(value => <ComboBoxOption value={value} key={value}>{value}</ComboBoxOption>)}
</ComboBoxField>
return <FormContext.Consumer>
{
(ctx: FormContextData) => {
const value = ctx.readParam(props.name);
let nonExistent = null;
if (!props.values.includes(value as any)) {
nonExistent = <ComboBoxOption value={value}>{value ? value+'' : '<empty>'}</ComboBoxOption>
}
return <ComboBoxField name={props.name} defaultValue={props.defaultValue} label={props.label} >
{nonExistent}
{props.values.map(value => <ComboBoxOption value={value} key={value}>{value}</ComboBoxOption>)}
</ComboBoxField>;
}
}
</FormContext.Consumer>
} else {
throw 'implement me';
}

View file

@ -30,7 +30,6 @@ SelectionWidget.propsToSchema = (props: SelectionWidgetProps) => {
let value = {
type: Types.entity,
allowedKinds: props.capture,
initializeBySelection: true,
} as SchemaField;
if (props.multi) {

View file

@ -1,4 +1,3 @@
import extrudeOperation from '../craft/cutExtrude/extrudeOperation';
import cutOperation from '../craft/cutExtrude/cutOperation';
import planeOperation from '../craft/primitives/simplePlane/simplePlaneOperation';
import filletOperation from '../craft/fillet/filletOperation';
@ -15,32 +14,31 @@ import coneOperation from '../craft/primitives/cone/coneOperation';
import spatialCurveOperation from '../craft/spatialCurve/spatialCurveOperation';
import loftOperation from '../craft/loft/loftOperation';
import {intersectionOperation, subtractOperation, unionOperation} from '../craft/boolean/booleanOperation';
import { loadMDFCommand } from '../mdf/mdf';
import WorkbenchRegistry from 'workbenches/registry';
export function activate({services}) {
services.operation.registerOperations([
planeOperation,
boxOperation,
// extrudeOperation,
cutOperation,
revolveOperation,
filletOperation,
createDatumOperation,
moveDatumOperation,
rotateDatumOperation,
datumOperation,
sphereOperation,
cylinderOperation,
torusOperation,
coneOperation,
spatialCurveOperation,
loftOperation,
intersectionOperation,
subtractOperation,
unionOperation,
]);
WorkbenchRegistry.forEach(w => {
services.operation.registerOperations(w.features.map(loadMDFCommand));
});
services.operation.registerOperations([
planeOperation,
boxOperation,
// extrudeOperation,
cutOperation,
revolveOperation,
filletOperation,
createDatumOperation,
moveDatumOperation,
rotateDatumOperation,
datumOperation,
sphereOperation,
cylinderOperation,
torusOperation,
coneOperation,
spatialCurveOperation,
loftOperation,
intersectionOperation,
subtractOperation,
unionOperation,
]);
WorkbenchRegistry.forEach(w => {
services.operation.registerOperations(w.features);
});
}