mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 08:25:19 +01:00
revert md
This commit is contained in:
parent
07db5af1db
commit
0cbd38d36c
41 changed files with 678 additions and 107 deletions
|
|
@ -35,7 +35,7 @@ export default class CSys {
|
|||
return new Matrix3x4().setBasisAxises(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
get outTransformation() {
|
||||
get outTransformation(): Matrix3x4 {
|
||||
const mx = new Matrix3x4().setBasisAxises(this.x, this.y, this.z);
|
||||
mx.tx = this.origin.x;
|
||||
mx.ty = this.origin.y;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,10 @@ export default class Folder extends React.Component{
|
|||
}
|
||||
|
||||
export function Title({children, isClosed, onClick}) {
|
||||
return <div className={ls.title} onClick={onClick}>
|
||||
const titleCss = onClick ? {
|
||||
cursor: 'pointer'
|
||||
} : {};
|
||||
return <div className={ls.title} onClick={onClick} style={titleCss}>
|
||||
<span className={ls.handle}><Fa fw icon={isClosed ? 'chevron-right' : 'chevron-down'}/></span>
|
||||
{' '}{children}
|
||||
</div>;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import {Title} from '../Folder';
|
|||
export class StackSection extends React.Component {
|
||||
|
||||
render() {
|
||||
const {title, children} = this.props;
|
||||
const {title, children, isClosed, onTitleClick} = this.props;
|
||||
return <React.Fragment>
|
||||
<Title>{title}</Title>
|
||||
{children}
|
||||
<Title isClosed={isClosed} onClick={onTitleClick}>{title}</Title>
|
||||
{!isClosed && children}
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,14 @@ 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";
|
||||
|
||||
interface ExtrudeParams {
|
||||
length: number;
|
||||
face: MFace;
|
||||
direction?: Vector,
|
||||
boolean: BooleanDefinition
|
||||
}
|
||||
|
||||
const ExtrudeOperation: MDFCommand<ExtrudeParams> = {
|
||||
|
|
@ -28,17 +32,49 @@ const ExtrudeOperation: MDFCommand<ExtrudeParams> = {
|
|||
|
||||
const occFaces = occ.utils.sketchToFaces(sketch, face.csys);
|
||||
|
||||
const shapeNames = occ.utils.prism(occFaces, [0, 0, params.length]);
|
||||
const dir = (params.direction && params.direction) || face.normal();
|
||||
|
||||
const created = shapeNames.map(shapeName => occ.io.getShell(shapeName));
|
||||
const extrusionVector = dir.normalize()._multiply(params.length).data();
|
||||
|
||||
const tools = occFaces.map((faceName, i) => {
|
||||
const shapeName = "Tool" + i;
|
||||
oci.prism(shapeName, faceName, ...extrusionVector)
|
||||
|
||||
// occIterateFaces(oc, shape, face => {
|
||||
// let role;
|
||||
// if (face.IsSame(prismAPI.FirstShape())) {
|
||||
// role = "bottom";
|
||||
// } else if (face.IsSame(prismAPI.LastShape())) {
|
||||
// role = "top";
|
||||
// } else {
|
||||
// role = "sweep";
|
||||
// }
|
||||
// getProductionInfo(face).role = role;
|
||||
// });
|
||||
//
|
||||
// occIterateEdges(oc, wire, edge => {
|
||||
// const generatedList = prismAPI.Generated(edge);
|
||||
// occIterateListOfShape(oc, generatedList, face => {
|
||||
// console.log(face);
|
||||
// })
|
||||
// })
|
||||
|
||||
return shapeName;
|
||||
});
|
||||
|
||||
return {
|
||||
consumed: [face.parent],
|
||||
created
|
||||
};
|
||||
created: tools.map(shapeName => occ.io.getShell(shapeName)),
|
||||
consumed: []
|
||||
}
|
||||
// return occ.utils.applyBooleanModifier(tools, params.boolean);
|
||||
|
||||
},
|
||||
|
||||
// useBoolean: {
|
||||
// booleanField: 'boolean',
|
||||
// impliedTargetField: 'face'
|
||||
// },
|
||||
|
||||
form: [
|
||||
{
|
||||
type: 'number',
|
||||
|
|
@ -57,6 +93,33 @@ const ExtrudeOperation: MDFCommand<ExtrudeParams> = {
|
|||
preselectionIndex: 0
|
||||
},
|
||||
},
|
||||
// {
|
||||
// type: 'vector',
|
||||
// name: 'direction',
|
||||
// label: 'direction'
|
||||
// },
|
||||
// {
|
||||
// type: 'boolean',
|
||||
// name: 'boolean',
|
||||
// label: 'boolean',
|
||||
// defaultValue: {
|
||||
// implyItFromField: 'face'
|
||||
// }
|
||||
// },
|
||||
{
|
||||
type: 'vector',
|
||||
name: 'direction',
|
||||
label: 'direction',
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
type: 'boolean',
|
||||
name: 'boolean',
|
||||
label: 'boolean',
|
||||
optional: true,
|
||||
defaultValue: 'NONE'
|
||||
}
|
||||
|
||||
],
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ import {SketchGeom} from "cad/sketch/sketchReader";
|
|||
import {OCCService} from "cad/craft/e0/occService";
|
||||
import {CoreContext} from "context";
|
||||
import CSys from "math/csys";
|
||||
import {OperationResult} from "cad/craft/craftPlugin";
|
||||
import {MShell} from "cad/model/mshell";
|
||||
import {BooleanDefinition, BooleanKind} from "cad/craft/schema/common/BooleanDefinition";
|
||||
import {bool} from "prop-types";
|
||||
|
||||
export interface OCCUtils {
|
||||
|
||||
|
|
@ -11,8 +15,9 @@ export interface OCCUtils {
|
|||
|
||||
sketchToFaces(sketch: SketchGeom, csys: CSys): string[];
|
||||
|
||||
prism(faces: string[], dir: Vec3): string[];
|
||||
// applyBoolean(tools: string[], kind: BooleanKind): string[];
|
||||
|
||||
applyBooleanModifier(tools: string[], booleanDef?: BooleanDefinition): OperationResult;
|
||||
}
|
||||
|
||||
export function createOCCUtils(ctx: CoreContext): OCCUtils {
|
||||
|
|
@ -32,39 +37,67 @@ export function createOCCUtils(ctx: CoreContext): OCCUtils {
|
|||
});
|
||||
}
|
||||
|
||||
function prism(faces: string[], dir: Vec3): string[] {
|
||||
const oci = ctx.occService.commandInterface;
|
||||
return faces.map((faceName, i) => {
|
||||
|
||||
const shapeName = "Shape:" + i;
|
||||
function applyBoolean(tools: string[], target: string[], kind: BooleanKind): string[] {
|
||||
|
||||
oci.prism(shapeName, faceName, ...dir)
|
||||
|
||||
// occIterateFaces(oc, shape, face => {
|
||||
// let role;
|
||||
// if (face.IsSame(prismAPI.FirstShape())) {
|
||||
// role = "bottom";
|
||||
// } else if (face.IsSame(prismAPI.LastShape())) {
|
||||
// role = "top";
|
||||
// } else {
|
||||
// role = "sweep";
|
||||
// }
|
||||
// getProductionInfo(face).role = role;
|
||||
// });
|
||||
//
|
||||
// occIterateEdges(oc, wire, edge => {
|
||||
// const generatedList = prismAPI.Generated(edge);
|
||||
// occIterateListOfShape(oc, generatedList, face => {
|
||||
// console.log(face);
|
||||
// })
|
||||
// })
|
||||
|
||||
return shapeName;
|
||||
});
|
||||
}
|
||||
|
||||
function applyBooleanModifier(tools: string[], booleanDef?: BooleanDefinition): OperationResult {
|
||||
const occ = ctx.occService;
|
||||
const oci = ctx.occService.commandInterface;
|
||||
|
||||
if (!booleanDef || booleanDef.kind === 'NONE') {
|
||||
|
||||
return {
|
||||
wiresToFaces, sketchToFaces, prism
|
||||
created: tools.map(shapeName => occ.io.getShell(shapeName)),
|
||||
consumed: []
|
||||
}
|
||||
|
||||
} else {
|
||||
const kind = booleanDef.kind;
|
||||
|
||||
let targets = booleanDef.targets;
|
||||
if (targets.length === 0) {
|
||||
targets = ctx.cadRegistry.shells;
|
||||
}
|
||||
|
||||
let targetNames = targets.map((target, i) => {
|
||||
const targetName = 'Target:' + i;
|
||||
ctx.occService.io.pushModel(target, targetName)
|
||||
return targetName;
|
||||
});
|
||||
|
||||
oci.bfuzzyvalue(0.0001);
|
||||
oci.bclearobjects();
|
||||
oci.bcleartools();
|
||||
|
||||
targetNames.forEach(targetName => oci.baddobjects(targetName));
|
||||
tools.forEach(toolName => oci.baddtools(toolName));
|
||||
|
||||
oci.bfillds();
|
||||
oci.bcbuild("BooleanResult");
|
||||
|
||||
// oci.bopcommon("result");
|
||||
//oci.bopfuse("result");
|
||||
//oci.bopcut("result");
|
||||
|
||||
return {
|
||||
consumed: targets,
|
||||
created: tools.map(shapeName => occ.io.getShell(shapeName), targets)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
wiresToFaces, sketchToFaces, applyBooleanModifier
|
||||
}
|
||||
|
||||
}
|
||||
5
web/app/cad/craft/e0/OCI.d.ts
vendored
5
web/app/cad/craft/e0/OCI.d.ts
vendored
|
|
@ -54,6 +54,11 @@ interface OCCCommands {
|
|||
*/
|
||||
BRepIntCS(...args: any[]);
|
||||
|
||||
/*
|
||||
Generic webcad engine command
|
||||
*/
|
||||
EngineCommand(...args: any[]);
|
||||
|
||||
/*
|
||||
XProgress [+|-t] [+|-c] [+|-g]
|
||||
The options are:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export const OCI: OCCCommandInterface = new Proxy({}, {
|
|||
get: function (target, prop: string, receiver) {
|
||||
return prop in target ? target[prop] : function() {
|
||||
prop = prop.replace(/^_/, '');
|
||||
const args = Array.from(arguments).map(a => a + "");
|
||||
const args = Array.from(arguments).map(a => JSON.stringify(a));
|
||||
console.log("ARGUMENTS:", args);
|
||||
const returnCode = CallCommand(prop, [prop, ...args]);
|
||||
// if (returnCode !== 0) {
|
||||
|
|
|
|||
18
web/app/cad/craft/e0/occEngineInterface.ts
Normal file
18
web/app/cad/craft/e0/occEngineInterface.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import {OCCCommandInterface} from "cad/craft/e0/occCommandInterface";
|
||||
import {MShell} from "cad/model/mshell";
|
||||
import {MObject} from "cad/model/mobject";
|
||||
import {Interrogate} from "cad/craft/e0/interact";
|
||||
import {readShellEntityFromJson} from "cad/scene/wrappers/entityIO";
|
||||
import {createOCCSketchLoader, OCCSketchLoader} from "cad/craft/e0/occSketchLoader";
|
||||
|
||||
export function createOCCEngineInterface(oci: OCCCommandInterface) {
|
||||
|
||||
return {
|
||||
io: {
|
||||
pushModel: (params: {
|
||||
name: string, operand: number,
|
||||
}) => oci.EngineCommand(params)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import {OCCCommandInterface} from "cad/craft/e0/occCommandInterface";
|
||||
import {OCI} from "cad/craft/e0/occCommandInterface";
|
||||
import {MShell} from "cad/model/mshell";
|
||||
import {MObject} from "cad/model/mobject";
|
||||
import {Interrogate} from "cad/craft/e0/interact";
|
||||
import {readShellEntityFromJson} from "cad/scene/wrappers/entityIO";
|
||||
import {createOCCSketchLoader, OCCSketchLoader} from "cad/craft/e0/occSketchLoader";
|
||||
import {CoreContext} from "context";
|
||||
|
||||
export interface OCCIO {
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ export interface OCCIO {
|
|||
sketchLoader: OCCSketchLoader
|
||||
}
|
||||
|
||||
export function createOCCIO(oci: OCCCommandInterface): OCCIO {
|
||||
export function createOCCIO(ctx: CoreContext): OCCIO {
|
||||
|
||||
function getShell(shapeName: string, consumed: MShell[]): MShell {
|
||||
const shapeJson = Interrogate(shapeName);
|
||||
|
|
@ -24,11 +25,10 @@ export function createOCCIO(oci: OCCCommandInterface): OCCIO {
|
|||
}
|
||||
|
||||
function pushModel(model: MObject, name: string) {
|
||||
|
||||
}
|
||||
|
||||
function anchorModel() {
|
||||
|
||||
ctx.occService.engineInterface.pushModel({
|
||||
name,
|
||||
operand: model.brepShell.data.externals.ptr
|
||||
});
|
||||
}
|
||||
|
||||
function cleanupRegistry() {
|
||||
|
|
@ -38,7 +38,7 @@ export function createOCCIO(oci: OCCCommandInterface): OCCIO {
|
|||
|
||||
return {
|
||||
getShell, pushModel, cleanupRegistry,
|
||||
sketchLoader: createOCCSketchLoader(oci)
|
||||
sketchLoader: createOCCSketchLoader(OCI)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import {CoreContext} from "context";
|
|||
import {OCCCommandInterface, OCI} from "cad/craft/e0/occCommandInterface";
|
||||
import {createOCCIO, OCCIO} from "cad/craft/e0/occIO";
|
||||
import {createOCCUtils, OCCUtils} from "cad/craft/e0/OCCUtils";
|
||||
import {createOCCEngineInterface} from "cad/craft/e0/occEngineInterface";
|
||||
|
||||
export interface OCCService {
|
||||
|
||||
|
|
@ -9,7 +10,9 @@ export interface OCCService {
|
|||
|
||||
commandInterface: OCCCommandInterface;
|
||||
|
||||
utils: OCCUtils
|
||||
utils: OCCUtils,
|
||||
|
||||
engineInterface: any
|
||||
}
|
||||
|
||||
export function createOCCService(ctx: CoreContext): OCCService {
|
||||
|
|
@ -18,10 +21,12 @@ export function createOCCService(ctx: CoreContext): OCCService {
|
|||
|
||||
return {
|
||||
|
||||
io: createOCCIO(oci),
|
||||
io: createOCCIO(ctx),
|
||||
|
||||
commandInterface: oci,
|
||||
|
||||
engineInterface: createOCCEngineInterface(oci),
|
||||
|
||||
utils: createOCCUtils(ctx)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {IconType} from "react-icons";
|
|||
import {ActionAppearance} from "../actions/actionSystemPlugin";
|
||||
import {ApplicationContext, CoreContext} from "context";
|
||||
import {OperationResult} from "./craftPlugin";
|
||||
import {OperationSchema} from "cad/craft/schema/schema";
|
||||
import {OperationFlattenSchema, OperationSchema, schemaIterator} from "cad/craft/schema/schema";
|
||||
import {FieldWidgetProps, UIDefinition} from "cad/mdf/ui/uiDefinition";
|
||||
|
||||
export function activate(ctx: ApplicationContext) {
|
||||
|
|
@ -35,7 +35,9 @@ export function activate(ctx: ApplicationContext) {
|
|||
};
|
||||
actions.push(opAction);
|
||||
|
||||
registry$.mutate(registry => registry[id] = Object.assign({appearance}, descriptor, {
|
||||
const workingSchema = flattenSchema(descriptor.schema);
|
||||
|
||||
registry$.mutate(registry => registry[id] = Object.assign({appearance, workingSchema}, descriptor, {
|
||||
run: (request, opContext) => runOperation(request, descriptor, opContext)
|
||||
}));
|
||||
}
|
||||
|
|
@ -86,6 +88,7 @@ export interface Operation<R> extends OperationDescriptor<R>{
|
|||
icon96: string;
|
||||
icon: string|IconType;
|
||||
};
|
||||
workingSchema: OperationFlattenSchema;
|
||||
}
|
||||
|
||||
export interface OperationDescriptor<R> {
|
||||
|
|
@ -117,6 +120,14 @@ export interface OperationGeometryProvider {
|
|||
|
||||
}
|
||||
|
||||
function flattenSchema(schema: OperationSchema): OperationFlattenSchema {
|
||||
const flatSchema = {} as OperationFlattenSchema;
|
||||
schemaIterator(schema, (path, flattenedPath, schemaField) => {
|
||||
flatSchema[flattenedPath] = schemaField;
|
||||
});
|
||||
return flatSchema;
|
||||
}
|
||||
|
||||
declare module 'context' {
|
||||
interface CoreContext {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export default {
|
||||
orientation: {
|
||||
type: 'enum',
|
||||
values: ['XY', 'XZ', 'ZY'],
|
||||
type: 'string',
|
||||
enum: ['XY', 'XZ', 'ZY'],
|
||||
defaultValue: 'XY'
|
||||
},
|
||||
parallelTo: {
|
||||
|
|
|
|||
12
web/app/cad/craft/schema/common/BooleanDefinition.ts
Normal file
12
web/app/cad/craft/schema/common/BooleanDefinition.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import {MObject} from "cad/model/mobject";
|
||||
|
||||
export type BooleanKind = 'NONE' | 'UNION' | 'SUBTRACT' | 'INTERSECT';
|
||||
|
||||
export interface BooleanDefinition {
|
||||
|
||||
kind: BooleanKind;
|
||||
|
||||
targets: MObject[];
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -45,6 +45,12 @@ function materializeParamsImpl(ctx: CoreContext,
|
|||
const typeDef = TypeRegistry[md.type];
|
||||
value = typeDef.resolve(ctx, value, md as any, reportError.dot(field), materializeParamsImpl);
|
||||
|
||||
if (md.resolve !== undefined) {
|
||||
value = md.resolve(
|
||||
ctx, value, md as any, reportError.dot(field), materializeParamsImpl
|
||||
)
|
||||
}
|
||||
|
||||
// if (md.type === Types.NUMBER) {
|
||||
// try {
|
||||
// const valueType = typeof value;
|
||||
|
|
|
|||
31
web/app/cad/craft/schema/resolvers/vectorResolver.ts
Normal file
31
web/app/cad/craft/schema/resolvers/vectorResolver.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import {Materializer} from "cad/craft/schema/types/index";
|
||||
import {CoreContext} from "context";
|
||||
import {OperationParamsErrorReporter} from "cad/craft/schema/schema";
|
||||
import Vector from "math/vector";
|
||||
import {MObject} from "cad/model/mobject";
|
||||
import {ObjectTypeSchema} from "cad/craft/schema/types/objectType";
|
||||
|
||||
type VectorInput = {
|
||||
vectorEntity: MObject,
|
||||
flip: boolean
|
||||
}
|
||||
|
||||
export function VectorResolver(ctx: CoreContext,
|
||||
value: VectorInput,
|
||||
md: ObjectTypeSchema,
|
||||
reportError: OperationParamsErrorReporter,
|
||||
materializer: Materializer): Vector {
|
||||
|
||||
if (!value.vectorEntity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let vector = value.vectorEntity.toDirection();
|
||||
if (!vector) {
|
||||
throw 'unsupported entity type: ' + value.vectorEntity.TYPE;
|
||||
}
|
||||
if (value.flip) {
|
||||
vector = vector.negate();
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
|
@ -1,16 +1,27 @@
|
|||
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";
|
||||
import {StringTypeSchema} from "cad/craft/schema/types/stringType";
|
||||
import {BooleanTypeSchema} from "cad/craft/schema/types/booleanType";
|
||||
|
||||
export type SchemaField = NumberTypeSchema | EntityTypeSchema | ArrayTypeSchema | ObjectTypeSchema | EnumTypeSchema;
|
||||
export type FlatSchemaField =
|
||||
| ArrayTypeSchema
|
||||
| EntityTypeSchema
|
||||
| NumberTypeSchema
|
||||
| StringTypeSchema
|
||||
| BooleanTypeSchema;
|
||||
|
||||
export type SchemaField = FlatSchemaField | ObjectTypeSchema;
|
||||
|
||||
export type OperationSchema = {
|
||||
[key: string]: SchemaField;
|
||||
};
|
||||
|
||||
export type OperationFlattenSchema = {
|
||||
[key: string]: FlatSchemaField;
|
||||
};
|
||||
|
||||
export interface BaseSchemaField {
|
||||
defaultValue: Coercable,
|
||||
optional: boolean,
|
||||
|
|
@ -31,3 +42,25 @@ export type OperationParamsError = {
|
|||
export type OperationParamsErrorReporter = ((msg: string) => void) & {
|
||||
dot: (pathPart: string|number) => OperationParamsErrorReporter
|
||||
};
|
||||
|
||||
export function schemaIterator(schema: OperationSchema,
|
||||
callback: (path: string[], flattenedPath: string, field: FlatSchemaField) => void) {
|
||||
|
||||
function inorder(schema: OperationSchema, parentPath: string[]) {
|
||||
|
||||
Object.keys(schema).forEach(key => {
|
||||
const path = [...parentPath, key]
|
||||
const flattenedPath = path.join('/');
|
||||
const schemaField = schema[key];
|
||||
|
||||
|
||||
if (schemaField.type === 'object') {
|
||||
inorder(schemaField.schema, path);
|
||||
} else {
|
||||
callback(path, flattenedPath, schemaField as FlatSchemaField);
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
inorder(schema, []);
|
||||
}
|
||||
20
web/app/cad/craft/schema/types/booleanType.ts
Normal file
20
web/app/cad/craft/schema/types/booleanType.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import {Materializer, Type, Types} from "cad/craft/schema/types/index";
|
||||
import {CoreContext} from "context";
|
||||
import {BaseSchemaField, OperationParamsErrorReporter} from "cad/craft/schema/schema";
|
||||
|
||||
export interface BooleanTypeSchema extends BaseSchemaField {
|
||||
|
||||
type: Types.boolean,
|
||||
|
||||
}
|
||||
|
||||
export const BooleanType: Type<any, boolean, BooleanTypeSchema> = {
|
||||
|
||||
resolve(ctx: CoreContext,
|
||||
value: any,
|
||||
md: BooleanTypeSchema,
|
||||
reportError: OperationParamsErrorReporter,
|
||||
materializer: Materializer): boolean {
|
||||
return !!value;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,8 @@ 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";
|
||||
import {StringType} from "cad/craft/schema/types/stringType";
|
||||
import {BooleanType} from "cad/craft/schema/types/booleanType";
|
||||
|
||||
export type Materializer = (ctx: CoreContext,
|
||||
params: OperationParams,
|
||||
|
|
@ -22,16 +23,18 @@ export interface Type<IN, OUT, METADATA extends SchemaField> {
|
|||
|
||||
export enum Types {
|
||||
array = 'array',
|
||||
object = 'object',
|
||||
entity = 'entity',
|
||||
number = 'number',
|
||||
object = 'object',
|
||||
enum = 'enum',
|
||||
boolean = 'boolean',
|
||||
string = 'string'
|
||||
}
|
||||
|
||||
export const TypeRegistry = {
|
||||
[Types.array]: ArrayType,
|
||||
[Types.object]: ObjectType,
|
||||
[Types.entity]: EntityType,
|
||||
[Types.number]: NumberType,
|
||||
[Types.object]: ObjectType,
|
||||
[Types.enum]: EnumType,
|
||||
[Types.boolean]: BooleanType,
|
||||
[Types.string]: StringType,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ export interface ObjectTypeSchema extends BaseSchemaField {
|
|||
|
||||
schema: OperationSchema;
|
||||
|
||||
resolver: (input: any) => any;
|
||||
|
||||
}
|
||||
|
||||
export const ObjectType: Type<any, any, ObjectTypeSchema> = {
|
||||
|
|
|
|||
|
|
@ -2,25 +2,28 @@ import {Materializer, Type, TypeRegistry, Types} from "cad/craft/schema/types/in
|
|||
import {CoreContext} from "context";
|
||||
import {BaseSchemaField, OperationParamsErrorReporter} from "cad/craft/schema/schema";
|
||||
|
||||
export interface EnumTypeSchema extends BaseSchemaField {
|
||||
export interface StringTypeSchema extends BaseSchemaField {
|
||||
|
||||
type: Types.number,
|
||||
|
||||
values: string[]
|
||||
enum?: string[]
|
||||
|
||||
}
|
||||
|
||||
export const EnumType: Type<any, number, EnumTypeSchema> = {
|
||||
export const StringType: Type<any, string, StringTypeSchema> = {
|
||||
|
||||
resolve(ctx: CoreContext,
|
||||
value: any,
|
||||
md: EnumTypeSchema,
|
||||
md: StringTypeSchema,
|
||||
reportError: OperationParamsErrorReporter,
|
||||
materializer: Materializer): number {
|
||||
materializer: Materializer): string {
|
||||
|
||||
if (md.values.indexOf(value) === -1) {
|
||||
value = md.defaultValue || md.values[0];
|
||||
value = value + '';
|
||||
|
||||
if (md.enum && md.enum.indexOf(value) === -1) {
|
||||
value = md.defaultValue || md.enum[0];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import materializeParams from '../schema/materializeParams';
|
|||
import {createFunctionList} from 'gems/func';
|
||||
import {onParamsUpdate} from '../cutExtrude/extrudeOperation';
|
||||
import {propsChangeTracker} from 'lstream/utils';
|
||||
import {OperationSchema, schemaIterator} from "cad/craft/schema/schema";
|
||||
|
||||
export function activate(ctx) {
|
||||
|
||||
|
|
@ -59,9 +60,9 @@ export function activate(ctx) {
|
|||
let params;
|
||||
let {changingHistory, noWizardFocus} = opRequest;
|
||||
if (changingHistory) {
|
||||
params = clone(opRequest.params)
|
||||
params = flattenParams(opRequest.params, operation.schema);
|
||||
} else {
|
||||
params = initializeBySchema(operation.schema, ctx);
|
||||
params = initializeBySchema(operation.workingSchema, ctx);
|
||||
if (opRequest.initialOverrides) {
|
||||
applyOverrides(params, opRequest.initialOverrides);
|
||||
}
|
||||
|
|
@ -75,7 +76,8 @@ export function activate(ctx) {
|
|||
let materializedWorkingRequest$ = workingRequest$.map(req => {
|
||||
let params = {};
|
||||
let errors = [];
|
||||
materializeParams(ctx, req.params, operation.schema, params, errors, []);
|
||||
let unflatten = unflattenParams(req.params, operation.schema);
|
||||
materializeParams(ctx, unflatten, operation.schema, params, errors);
|
||||
if (errors.length !== 0) {
|
||||
return INVALID_REQUEST;
|
||||
}
|
||||
|
|
@ -83,7 +85,7 @@ export function activate(ctx) {
|
|||
type: req.type,
|
||||
params
|
||||
};
|
||||
}).remember(INVALID_REQUEST).filter(r => r !== INVALID_REQUEST);
|
||||
}).remember(INVALID_REQUEST).filter(r => r !== INVALID_REQUEST).throttle(500);
|
||||
const state$ = state({});
|
||||
const updateParams = mutator => workingRequest$.mutate(data => mutator(data.params));
|
||||
const updateState = mutator => state$.mutate(state => mutator(state));
|
||||
|
|
@ -129,8 +131,12 @@ export function activate(ctx) {
|
|||
},
|
||||
|
||||
applyWorkingRequest: () => {
|
||||
let {type, params} = streams.wizard.wizardContext.value.workingRequest$.value;
|
||||
let request = clone({type, params});
|
||||
let wizCtx = streams.wizard.wizardContext.value;
|
||||
let {type, params} = wizCtx.workingRequest$.value;
|
||||
let request = {
|
||||
type,
|
||||
params: unflattenParams(params, wizCtx.operation.schema)
|
||||
};
|
||||
const setError = error => streams.wizard.wizardContext.mutate(ctx => ctx.state$.mutate(state => state.error = error));
|
||||
if (streams.wizard.insertOperation.value.type) {
|
||||
ctx.services.craft.modify(request, () => streams.wizard.insertOperation.value = EMPTY_OBJECT, setError );
|
||||
|
|
@ -143,6 +149,23 @@ export function activate(ctx) {
|
|||
};
|
||||
}
|
||||
|
||||
function flattenParams(params, originalSchema) {
|
||||
const flatParams = {};
|
||||
schemaIterator(originalSchema, (path, flattenedPath, schemaField) => {
|
||||
flatParams[flattenedPath] = _.get(params, path);
|
||||
});
|
||||
return flatParams;
|
||||
}
|
||||
|
||||
function unflattenParams(params, originalSchema) {
|
||||
const unflatParams = {};
|
||||
schemaIterator(originalSchema, (path, flattenedPath, schemaField) => {
|
||||
_.set(unflatParams, path, params[flattenedPath]);
|
||||
});
|
||||
return unflatParams;
|
||||
}
|
||||
|
||||
|
||||
function applyOverrides(params, initialOverrides) {
|
||||
Object.assign(params, initialOverrides);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export function activate(ctx) {
|
|||
wizCtx.workingRequest$.attach(({type, params}) => {
|
||||
const marker = ctx.services.marker;
|
||||
marker.startSession();
|
||||
let {schema} = wizCtx.operation;
|
||||
let {workingSchema: schema} = wizCtx.operation;
|
||||
Object.keys(schema).forEach(param => {
|
||||
let md = schema[param];
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ function createPickHandlerFromSchema(wizCtx) {
|
|||
const params = wizCtx.workingRequest$.value.params;
|
||||
const state = wizCtx.state$.value;
|
||||
|
||||
let {schema} = wizCtx.operation;
|
||||
let {workingSchema: schema} = wizCtx.operation;
|
||||
|
||||
const activeMd = state.activeParam && schema[state.activeParam];
|
||||
const activeCanTakeIt = kind => activeMd.allowedKinds && activeMd.allowedKinds.includes(kind);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import { ComboBoxOption } from 'ui/components/controls/ComboBoxControl';
|
|||
import Entity from '../craft/wizard/components/form/Entity';
|
||||
import { CheckboxField, NumberField, ComboBoxField, TextField } from '../craft/wizard/components/form/Fields';
|
||||
import { Group } from '../craft/wizard/components/form/Form';
|
||||
import { OperationSchema, SchemaField } from './mdf';
|
||||
import {OperationSchema, SchemaField} from "cad/craft/schema/schema";
|
||||
|
||||
|
||||
export function generateForm(schema: OperationSchema) {
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ export function loadMDFCommand<R>(mdfCommand: MDFCommand<R>): OperationDescripto
|
|||
type: 'group',
|
||||
content: mdfCommand.form
|
||||
}
|
||||
const formFields = extractFormFields(uiDefinition);
|
||||
const derivedSchema = deriveSchema(formFields);
|
||||
const {schema: derivedSchema, formFields} = deriveSchema(uiDefinition);
|
||||
return {
|
||||
id: mdfCommand.id,
|
||||
label: mdfCommand.label,
|
||||
|
|
@ -75,13 +74,20 @@ function extractFormFields(uiDefinition: UIDefinition): FieldWidgetProps[] {
|
|||
return fields;
|
||||
}
|
||||
|
||||
export function deriveSchema(formFields: FieldWidgetProps[]): OperationSchema {
|
||||
export function deriveSchema(uiDefinition: UIDefinition): {
|
||||
schema: OperationSchema,
|
||||
formFields: FieldWidgetProps[]
|
||||
} {
|
||||
const formFields: FieldWidgetProps[] = extractFormFields(uiDefinition)
|
||||
const schema = {};
|
||||
formFields.forEach(f => {
|
||||
let propsToSchema = DynamicComponents[f.type].propsToSchema;
|
||||
schema[f.name] = propsToSchema(schema, f as any);
|
||||
});
|
||||
return schema;
|
||||
return {
|
||||
schema,
|
||||
formFields
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
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"
|
||||
}
|
||||
|
||||
|
||||
|
||||
84
web/app/cad/mdf/ui/BooleanWidget.tsx
Normal file
84
web/app/cad/mdf/ui/BooleanWidget.tsx
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
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";
|
||||
import {EntityKind} from "cad/model/entities";
|
||||
import {SectionWidgetProps} from "cad/mdf/ui/SectionWidget";
|
||||
import {DynamicComponentWidget} from "cad/mdf/ui/DynamicComponentWidget";
|
||||
import {VectorResolver} from "cad/craft/schema/resolvers/vectorResolver";
|
||||
|
||||
export interface BooleanWidgetProps extends FieldBasicProps {
|
||||
|
||||
type: 'boolean';
|
||||
|
||||
}
|
||||
|
||||
const ENTITY_CAPTURE = [EntityKind.SHELL];
|
||||
|
||||
const BOOLEAN_OPTIONS = ['NONE', 'UNION', 'SUBTRACT', 'INTERSECT'];
|
||||
|
||||
const BooleanUIDefinition = (fieldName: string, label: string) => ({
|
||||
|
||||
type: 'section',
|
||||
|
||||
title: label,
|
||||
|
||||
collapsible: true,
|
||||
|
||||
initialCollapse: false,
|
||||
|
||||
content: [
|
||||
{
|
||||
name: fieldName+"/kind",
|
||||
label: 'kind',
|
||||
type: "choice",
|
||||
optional: true,
|
||||
values: BOOLEAN_OPTIONS
|
||||
},
|
||||
{
|
||||
name: fieldName+"/targets",
|
||||
label: 'target',
|
||||
type: "selection",
|
||||
capture: ENTITY_CAPTURE,
|
||||
multi: true,
|
||||
optional: true,
|
||||
}
|
||||
]
|
||||
} as SectionWidgetProps);
|
||||
|
||||
|
||||
export function BooleanWidget(props: BooleanWidgetProps) {
|
||||
|
||||
let vectorUIDefinition = BooleanUIDefinition(props.name, props.label);
|
||||
|
||||
return <DynamicComponentWidget {...vectorUIDefinition} />
|
||||
}
|
||||
|
||||
BooleanWidget.propsToSchema = (consumer: OperationSchema, props: BooleanWidgetProps) => {
|
||||
return {
|
||||
type: Types.object,
|
||||
schema: {
|
||||
kind: {
|
||||
label: 'kind',
|
||||
type: Types.string,
|
||||
enum: BOOLEAN_OPTIONS,
|
||||
defaultValue: props.defaultValue || 'NONE',
|
||||
optional: false
|
||||
},
|
||||
|
||||
targets: {
|
||||
label: 'targets',
|
||||
type: Types.array,
|
||||
item: {
|
||||
type: Types.boolean,
|
||||
allowedKinds: ENTITY_CAPTURE,
|
||||
},
|
||||
optional: true,
|
||||
applicable: 'kind !== "NONE"'
|
||||
}
|
||||
},
|
||||
...fieldToSchemaGeneric(props),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
27
web/app/cad/mdf/ui/CheckboxWidget.tsx
Normal file
27
web/app/cad/mdf/ui/CheckboxWidget.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
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";
|
||||
import {CheckboxField} from "cad/craft/wizard/components/form/Fields";
|
||||
|
||||
export interface CheckboxWidgetProps extends FieldBasicProps {
|
||||
|
||||
type: 'checkbox';
|
||||
|
||||
min?: number;
|
||||
|
||||
max?: number;
|
||||
}
|
||||
|
||||
export function CheckboxWidget(props: CheckboxWidgetProps) {
|
||||
return <CheckboxField name={props.name} defaultValue={props.defaultValue} label={props.label} />
|
||||
}
|
||||
|
||||
CheckboxWidget.propsToSchema = (consumer: OperationSchema, props: CheckboxWidgetProps) => {
|
||||
return {
|
||||
type: Types.boolean,
|
||||
...fieldToSchemaGeneric(props),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
36
web/app/cad/mdf/ui/ChoiceWidget.tsx
Normal file
36
web/app/cad/mdf/ui/ChoiceWidget.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import {ComboBoxField, 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";
|
||||
import {ComboBoxOption} from "ui/components/controls/ComboBoxControl";
|
||||
|
||||
export interface ChoiceWidgetProps extends FieldBasicProps {
|
||||
|
||||
type: 'choice';
|
||||
|
||||
style?: 'dropdown' | 'radio';
|
||||
|
||||
values: string[];
|
||||
|
||||
}
|
||||
|
||||
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}>{value}</ComboBoxOption>)}
|
||||
</ComboBoxField>
|
||||
} else {
|
||||
throw 'implement me';
|
||||
}
|
||||
}
|
||||
|
||||
ChoiceWidget.propsToSchema = (consumer: OperationSchema, props: ChoiceWidgetProps) => {
|
||||
return {
|
||||
type: Types.string,
|
||||
enum: props.values,
|
||||
...fieldToSchemaGeneric(props),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
31
web/app/cad/mdf/ui/SectionWidget.tsx
Normal file
31
web/app/cad/mdf/ui/SectionWidget.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import React, {useState} from "react";
|
||||
import {ContainerBasicProps, ContainerWidget, ContainerWidgetProps} from "cad/mdf/ui/ContainerWidget";
|
||||
import {Group} from "cad/craft/wizard/components/form/Form";
|
||||
import {StackSection} from "ui/components/controls/FormSection";
|
||||
import Entity from "cad/craft/wizard/components/form/EntityList";
|
||||
import {CheckboxField} from "cad/craft/wizard/components/form/Fields";
|
||||
|
||||
export interface SectionWidgetProps extends ContainerBasicProps {
|
||||
|
||||
type: 'section';
|
||||
|
||||
title: string;
|
||||
|
||||
collapsible: boolean;
|
||||
|
||||
initialCollapse: boolean;
|
||||
|
||||
}
|
||||
|
||||
export function SectionWidget(props: SectionWidgetProps) {
|
||||
const [visible, setVisible] = useState(!props.initialCollapse);
|
||||
|
||||
const onTitleClick = props.collapsible ? () => setVisible(visible => !visible) : undefined;
|
||||
|
||||
return <StackSection title={props.title} onTitleClick={onTitleClick} isClosed={!visible}>
|
||||
{visible && <ContainerWidget content={props.content} />}
|
||||
</StackSection>
|
||||
}
|
||||
|
||||
|
||||
|
||||
75
web/app/cad/mdf/ui/VectorWidget.tsx
Normal file
75
web/app/cad/mdf/ui/VectorWidget.tsx
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
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";
|
||||
import {EntityKind} from "cad/model/entities";
|
||||
import {SectionWidgetProps} from "cad/mdf/ui/SectionWidget";
|
||||
import {DynamicComponentWidget} from "cad/mdf/ui/DynamicComponentWidget";
|
||||
import {VectorResolver} from "cad/craft/schema/resolvers/vectorResolver";
|
||||
|
||||
export interface VectorWidgetProps extends FieldBasicProps {
|
||||
|
||||
type: 'vector';
|
||||
|
||||
}
|
||||
|
||||
const ENTITY_CAPTURE = [EntityKind.EDGE, EntityKind.SKETCH_OBJECT, EntityKind.DATUM_AXIS, EntityKind.FACE];
|
||||
|
||||
const VectorUIDefinition = (fieldName: string, label: string) => ({
|
||||
|
||||
type: 'section',
|
||||
|
||||
title: label,
|
||||
|
||||
collapsible: true,
|
||||
|
||||
initialCollapse: false,
|
||||
|
||||
content: [
|
||||
{
|
||||
name: fieldName+"/vectorEntity",
|
||||
label: 'vector',
|
||||
type: "selection",
|
||||
capture: ENTITY_CAPTURE,
|
||||
multi: false,
|
||||
},
|
||||
{
|
||||
name: fieldName+"/flip",
|
||||
label: 'flip',
|
||||
type: "checkbox",
|
||||
defaultValue: false
|
||||
}
|
||||
]
|
||||
} as SectionWidgetProps);
|
||||
|
||||
|
||||
export function VectorWidget(props: VectorWidgetProps) {
|
||||
|
||||
let vectorUIDefinition = VectorUIDefinition(props.name, props.label);
|
||||
|
||||
return <DynamicComponentWidget {...vectorUIDefinition} />
|
||||
}
|
||||
|
||||
VectorWidget.propsToSchema = (consumer: OperationSchema, props: VectorWidgetProps) => {
|
||||
return {
|
||||
type: Types.object,
|
||||
schema: {
|
||||
vectorEntity: {
|
||||
label: 'vector',
|
||||
type: Types.entity,
|
||||
allowedKinds: ENTITY_CAPTURE,
|
||||
optional: true
|
||||
},
|
||||
flip: {
|
||||
label: 'flip',
|
||||
type: Types.boolean,
|
||||
defaultValue: false,
|
||||
optional: false
|
||||
}
|
||||
},
|
||||
resolve: VectorResolver,
|
||||
...fieldToSchemaGeneric(props),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -2,6 +2,11 @@ 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";
|
||||
import {SectionWidget} from "cad/mdf/ui/SectionWidget";
|
||||
import {VectorWidget} from "cad/mdf/ui/VectorWidget";
|
||||
import {CheckboxWidget} from "cad/mdf/ui/CheckboxWidget";
|
||||
import {BooleanWidget} from "cad/mdf/ui/BooleanWidget";
|
||||
import {ChoiceWidget} from "cad/mdf/ui/ChoiceWidget";
|
||||
|
||||
export const DynamicComponents = {
|
||||
|
||||
|
|
@ -12,4 +17,15 @@ export const DynamicComponents = {
|
|||
'container': ContainerWidget,
|
||||
|
||||
'group': GroupWidget,
|
||||
|
||||
'section': SectionWidget,
|
||||
|
||||
'vector': VectorWidget,
|
||||
|
||||
'checkbox': CheckboxWidget,
|
||||
|
||||
'boolean': BooleanWidget,
|
||||
|
||||
'choice': ChoiceWidget,
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +1,17 @@
|
|||
import {NumberWidgetProps} from "cad/mdf/ui/NumberWidget";
|
||||
import {SelectionWidgetProps} from "cad/mdf/ui/SelectionWidget";
|
||||
import {AccordionWidgetProps} from "cad/mdf/ui/AccordionWidget";
|
||||
import {SectionWidgetProps} from "cad/mdf/ui/SectionWidget";
|
||||
import {DynamicComponents} from "cad/mdf/ui/componentRegistry";
|
||||
import {ContainerWidgetProps} from "cad/mdf/ui/ContainerWidget";
|
||||
import {GroupWidgetProps} from "cad/mdf/ui/GroupWidget";
|
||||
import {CheckboxWidgetProps} from "cad/mdf/ui/CheckboxWidget";
|
||||
import {VectorWidgetProps} from "cad/mdf/ui/VectorWidget";
|
||||
import {BooleanWidgetProps} from "cad/mdf/ui/BooleanWidget";
|
||||
import {ChoiceWidgetProps} from "cad/mdf/ui/ChoiceWidget";
|
||||
|
||||
export type FieldWidgetProps = NumberWidgetProps | SelectionWidgetProps;
|
||||
export type FieldWidgetProps = NumberWidgetProps | CheckboxWidgetProps | ChoiceWidgetProps | SelectionWidgetProps | VectorWidgetProps | BooleanWidgetProps;
|
||||
|
||||
export type BasicWidgetProps = ContainerWidgetProps | AccordionWidgetProps;
|
||||
export type BasicWidgetProps = ContainerWidgetProps | SectionWidgetProps | GroupWidgetProps;
|
||||
|
||||
export type DynamicWidgetProps = FieldWidgetProps | BasicWidgetProps;
|
||||
|
||||
|
|
|
|||
|
|
@ -57,4 +57,8 @@ export class MDatumAxis extends MObject {
|
|||
get parent() {
|
||||
return this.holder;
|
||||
}
|
||||
|
||||
toDirection(): Vector {
|
||||
return this.dir;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
import {MObject} from './mobject';
|
||||
import {MBrepShell} from "./mshell";
|
||||
import {EntityKind} from "cad/model/entities";
|
||||
import {Edge} from "brep/topo/edge";
|
||||
import Vector from "math/vector";
|
||||
|
||||
export class MEdge extends MObject {
|
||||
|
||||
static TYPE = EntityKind.EDGE;
|
||||
shell: MBrepShell;
|
||||
brepEdge: any;
|
||||
brepEdge: Edge;
|
||||
|
||||
constructor(id, shell, brepEdge) {
|
||||
super(MEdge.TYPE, id);
|
||||
|
|
@ -34,4 +36,9 @@ export class MEdge extends MObject {
|
|||
get parent() {
|
||||
return this.shell;
|
||||
}
|
||||
|
||||
toDirection(): Vector {
|
||||
return this.brepEdge.halfEdge1.tangentAtStart();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import BBox from "math/bbox";
|
|||
import {Basis, BasisForPlane} from "math/basis";
|
||||
import {Face} from "brep/topo/face";
|
||||
import {EntityKind} from "cad/model/entities";
|
||||
import {Matrix3x4} from "math/matrix";
|
||||
|
||||
export class MFace extends MObject {
|
||||
|
||||
|
|
@ -141,14 +142,14 @@ export class MFace extends MObject {
|
|||
return EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
get sketchToWorldTransformation() {
|
||||
get sketchToWorldTransformation(): Matrix3x4 {
|
||||
if (!this._sketchToWorldTransformation) {
|
||||
this._sketchToWorldTransformation = this.csys.outTransformation;
|
||||
}
|
||||
return this._sketchToWorldTransformation;
|
||||
}
|
||||
|
||||
get worldToSketchTransformation() {
|
||||
get worldToSketchTransformation(): Matrix3x4 {
|
||||
if (!this._worldToSketchTransformation) {
|
||||
this._worldToSketchTransformation = this.csys.inTransformation;
|
||||
}
|
||||
|
|
@ -223,4 +224,9 @@ export class MBrepFace extends MFace {
|
|||
}
|
||||
return this.#favorablePoint;
|
||||
}
|
||||
|
||||
toDirection(): Vector {
|
||||
return this.normal();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import {IDENTITY_MATRIX, Matrix3x4} from "math/matrix";
|
||||
import {EntityKind} from "cad/model/entities";
|
||||
import Vector from "math/vector";
|
||||
|
||||
export abstract class MObject {
|
||||
|
||||
|
|
@ -19,6 +20,10 @@ export abstract class MObject {
|
|||
|
||||
abstract get parent();
|
||||
|
||||
toDirection() {
|
||||
return null;
|
||||
};
|
||||
|
||||
get root(): MObject {
|
||||
let obj = this;
|
||||
while (obj.parent) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import {MObject} from './mobject';
|
||||
import {MFace} from "./mface";
|
||||
import {EntityKind} from "cad/model/entities";
|
||||
import Vector from "math/vector";
|
||||
import {Segment} from "cad/sketch/sketchModel";
|
||||
|
||||
export class MSketchObject extends MObject {
|
||||
|
||||
|
|
@ -20,4 +22,9 @@ export class MSketchObject extends MObject {
|
|||
return this.face;
|
||||
}
|
||||
|
||||
toDirection(): Vector {
|
||||
const tangent = (this.sketchPrimitive as Segment).tangentAtStart();
|
||||
return this.face.sketchToWorldTransformation.apply(tangent);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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, md);
|
||||
this.viewer.historyManager.init(sketchData);
|
||||
this.viewer.io.loadSketch(sketchData);
|
||||
this.ctx.streams.sketcher.sketchingFace.next(face);
|
||||
this.ctx.streams.sketcher.sketcherAppContext.next(this.sketcherAppContext);
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class SketchPrimitive {
|
|||
}
|
||||
}
|
||||
|
||||
export class Segment<Segment> extends SketchPrimitive {
|
||||
export class Segment extends SketchPrimitive {
|
||||
|
||||
a: Vector;
|
||||
b: Vector;
|
||||
|
|
@ -105,7 +105,12 @@ export class Segment<Segment> extends SketchPrimitive {
|
|||
const [A, B] = genForm;
|
||||
oci.point(underName + "_A", A.x, A.y, A.z);
|
||||
oci.point(underName + "_B", B.x, B.y, B.z);
|
||||
oci.gcarc(underName, "seg", underName + "_A", underName + "_B")}
|
||||
oci.gcarc(underName, "seg", underName + "_A", underName + "_B")
|
||||
}
|
||||
|
||||
tangentAtStart(): Vector {
|
||||
return this.b.minus(this.a);
|
||||
}
|
||||
}
|
||||
|
||||
export class Arc extends SketchPrimitive {
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ export class GCCircle extends ContractibleObject {
|
|||
static TYPE = 'GCCircle';
|
||||
|
||||
static newInstance(x, y, r) {
|
||||
return GCCircle().init(new GCPoint(x, y), md)
|
||||
return GCCircle().init(new GCPoint(x, y), new GCParam(r))
|
||||
}
|
||||
|
||||
init(c, r) {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ export class Project {
|
|||
let sketchId = this.getSketchId();
|
||||
let sketchData = localStorage.getItem(sketchId);
|
||||
if (sketchData != null) {
|
||||
this.viewer.historyManager.init(sketchData, md);
|
||||
this.viewer.historyManager.init(sketchData);
|
||||
this.viewer.io.loadSketch(sketchData);
|
||||
}
|
||||
this.viewer.repaint();
|
||||
|
|
|
|||
Loading…
Reference in a new issue