mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 08:25:19 +01:00
work on MDF
This commit is contained in:
parent
e07fd2c5e6
commit
31032051fc
23 changed files with 312 additions and 408 deletions
|
|
@ -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} />
|
||||
};
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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: [],
|
||||
|
|
|
|||
|
|
@ -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> = {
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export type OperationFlattenSchema = {
|
|||
};
|
||||
|
||||
export interface BaseSchemaField {
|
||||
defaultValue: OperationParamValue,
|
||||
defaultValue?: OperationParamValue,
|
||||
optional: boolean,
|
||||
label?: string,
|
||||
resolve?: ValueResolver<any, any>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ export interface ArrayTypeSchema extends BaseSchemaField {
|
|||
min: number;
|
||||
|
||||
max: number;
|
||||
|
||||
defaultValue: {
|
||||
usePreselection: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export const ArrayType: Type<any[], any[], ArrayTypeSchema> = {
|
||||
|
|
|
|||
|
|
@ -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> = {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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} />
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export enum IconSize {
|
|||
small = 'small',
|
||||
medium = 'medium',
|
||||
large = 'large'
|
||||
};
|
||||
}
|
||||
|
||||
export interface IconSetDef {
|
||||
iconType: IconType;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ SelectionWidget.propsToSchema = (props: SelectionWidgetProps) => {
|
|||
let value = {
|
||||
type: Types.entity,
|
||||
allowedKinds: props.capture,
|
||||
initializeBySelection: true,
|
||||
} as SchemaField;
|
||||
|
||||
if (props.multi) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue