diff --git a/packages/ursula/config/index.js b/packages/ursula/config/index.js new file mode 100644 index 00000000000..142f460b629 --- /dev/null +++ b/packages/ursula/config/index.js @@ -0,0 +1,51 @@ +import { version } from '../package.json' + +// ?? 🤔 ?? --> https://en.freesewing.dev/packages/core/config + +export default { + name: 'ursula', + version, + design: 'natalia', + code: 'natalia', + department: 'womenswear', + type: 'pattern', + difficulty: 1, + tags: [ + 'freesewing', + 'design', + 'diy', + 'fashion', + 'made to measure', + 'parametric design', + 'pattern', + 'sewing', + 'sewing pattern', + ], + optionGroups: { + fit: ['fabricStretch','gussetWidth','gussetLength','elasticStretch'], + style: ['rise','legOpening','frontDip','backDip','taperToGusset','backExposure'], + }, + measurements: ['waist','seat','waistToSeat','waistToUpperLeg'], // Potentially useful: 'hips', 'waistToHips' + dependencies: {}, + inject: {}, + hide: [], + parts: ['front','back','gusset','elastic'], + //Constants + options: { + backToFrontLength: 1.15, // Maybe include this in advanced options? + backToFrontWidth: 1.1, // Maybe include this in advanced options? + gussetRatio: 0.7, // Relationship between front and back gusset widths + + // Percentages + gussetWidth: { pct : 7.7, min: 4, max: 12 }, // Gusset width in relation to seat + gussetLength: { pct: 12.7, min: 10, max: 16 }, // Gusset length in relation to seat + fabricStretch: { pct: 15, min: 5, max: 25 }, + rise: { pct: 60, min: 30, max: 100 }, + legOpening: { pct: 58, min: 5, max: 85 }, + frontDip: { pct: 5.0, min: -5, max: 15 }, + backDip: { pct: 2.5, min: -5, max: 15 }, + taperToGusset: { pct: 70, min: 5, max: 100}, + backExposure: { pct: 20, min: -30, max: 90}, + elasticStretch: { pct: 8, min: 5, max: 15 } + }, +} diff --git a/packages/ursula/package.json b/packages/ursula/package.json new file mode 100644 index 00000000000..824db4e81ad --- /dev/null +++ b/packages/ursula/package.json @@ -0,0 +1,93 @@ +{ + "name": "@freesewing/ursula", + "version": "2.16.2", + "description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern", + "author": "Joost De Cock (https://github.com/joostdecock)", + "homepage": "https://freesewing.org/", + "repository": "github:freesewing/freesewing", + "license": "MIT", + "bugs": { + "url": "https://github.com/freesewing/freesewing/issues" + }, + "keywords": [ + "freesewing", + "design", + "diy", + "fashion", + "made to measure", + "parametric design", + "pattern", + "sewing", + "sewing pattern" + ], + "main": "dist/index.js", + "module": "dist/index.mjs", + "scripts": { + "clean": "rimraf dist", + "build": "rollup -c", + "test": "BABEL_ENV=production ../../node_modules/.bin/_mocha tests/*.test.js --require @babel/register", + "pubtest": "npm publish --registry http://localhost:6662", + "pubforce": "npm publish", + "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", + "start": "rollup -c -w", + "netlify": "echo \"Not configured yet\"", + "testci": "BABEL_ENV=production ./node_modules/.bin/_mocha tests/*.test.js --require @babel/register" + }, + "peerDependencies": { + "@freesewing/core": "^2.16.2", + "@freesewing/plugin-bundle": "^2.16.2" + }, + "dependencies": {}, + "devDependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "babel-eslint": "^10.1.0", + "eslint": "^7.27.0", + "eslint-config-standard": "^16.0.3", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^1.1.0", + "@freesewing/components": "^2.16.2", + "@freesewing/css-theme": "^2.16.2", + "@freesewing/i18n": "^2.16.2", + "@freesewing/mui-theme": "^2.16.2", + "@freesewing/plugin-bust": "^2.16.2", + "@freesewing/plugin-buttons": "^2.16.2", + "@freesewing/plugin-flip": "^2.16.2", + "@freesewing/utils": "^2.16.2", + "react-scripts": "^4.0.3", + "webpack": "^5.37.0", + "rollup": "^2.50.6", + "@rollup/plugin-babel": "^5.3.0", + "@rollup/plugin-commonjs": "^19.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.0.0", + "rollup-plugin-peer-deps-external": "^2.2.4", + "@material-ui/core": "^4.11.4", + "@material-ui/icons": "^4.11.2", + "@material-ui/lab": "^v4.0.0-alpha.57", + "axios": "0.21.1", + "react-intl": "^5.17.6", + "prop-types": "^15.7.2", + "mocha": "^8.1.0", + "chai": "^4.2.0", + "chai-string": "^1.5.0", + "@babel/register": "^7.10.5" + }, + "files": [ + "dist/*", + "README.md", + "package.json" + ], + "publishConfig": { + "access": "public", + "tag": "latest" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6" + }, + "rollup": { + "exports": "default" + } +} diff --git a/packages/ursula/src/back.js b/packages/ursula/src/back.js new file mode 100644 index 00000000000..fb4a9352349 --- /dev/null +++ b/packages/ursula/src/back.js @@ -0,0 +1,240 @@ +export default function (part) { + let { + options, + Point, + Path, + points, + paths, + measurements, +// Snippet, +// snippets, + store, + utils, + complete, + sa, + paperless, + macro, + } = part.shorthand() + + // Design pattern here + + // Create points + + points.backWaistMid = new Point(measurements.seat / 4, 0) + points.backWaistBandLeft = new Point(store.get('sideSeamWaist').x / options.backToFrontWidth, store.get('sideSeamWaist').y) + points.backLegOpeningLeft = new Point(store.get('sideSeamHip').x / options.backToFrontWidth, store.get('sideSeamHip').y) + points.backGussetLeft = new Point( + (measurements.seat / 4) - (measurements.waist * options.gussetWidth) * store.get('xScale') / options.gussetRatio * options.backToFrontWidth, + measurements.waistToUpperLeg * options.backToFrontLength + ) + points.backGussetMid = new Point(measurements.seat / 4, measurements.waistToUpperLeg * options.backToFrontLength) + + points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid) + points.backLegOpeningRight = points.backLegOpeningLeft.flipX(points.backWaistMid) + points.backWaistBandRight = points.backWaistBandLeft.flipX(points.backWaistMid) + + points.backWaistBandMid = points.backWaistBandLeft.shiftFractionTowards(points.backWaistBandRight, 0.5) + .shift(270,measurements.waistToUpperLeg * options.backDip) + + /* Middle point for label */ + points.backMidMid = points.backLegOpeningLeft.shiftFractionTowards(points.backLegOpeningRight, 0.5) + + + // Create control points + + /* Control point for waistband dip */ + points.backWaistBandLeftCp1 = new Point(points.backWaistBandRight.x / 3, points.backWaistBandMid.y) + + /* Flip points to right side */ + points.backWaistBandRightCp1 = points.backWaistBandLeftCp1.flipX(points.backWaistMid) + + // Shape back coverage + + /* Only have to do this on one side */ + points.backLegOpeningCorner = utils.beamsIntersect( + points.backLegOpeningLeft, + points.backLegOpeningLeft.shift(180, points.backGussetLeft.dy(points.backLegOpeningLeft)), + points.backGussetLeft, + points.backGussetLeft.shift(270, points.backGussetLeft.dy(points.backLegOpeningLeft)) + ) + + if (options.backExposure >= 0) { + /* If back exposure is high, like a thong style */ + /* This controls the hip bit */ + points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shiftFractionTowards( + points.backLegOpeningCorner, + options.backExposure + ) + /* This controls the center bit */ + points.backGussetLeftCp1 = points.backGussetLeft.shiftFractionTowards( + points.backWaistBandMid, + options.backExposure + ) + points.backGussetLeft = points.backGussetLeft.shiftFractionTowards(points.backGussetMid, options.backExposure) // This narrows the back of the gusset + points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid) + } else { + /* If back exposure is low and flares out to cover more */ + /* This controls the hip bit */ + points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shift( + -45, + points.backWaistBandMid.x / 8 + ) + /* This controls the taper to gusset */ + points.backGussetLeftCp1 = points.backGussetLeft.shift( + 115, + points.backWaistBandMid.x / 8 + ) + /* This adds a new point in the middle of the back coverage */ + points.backFlare = points.backGussetLeft.shiftFractionTowards( + points.backLegOpeningLeft, + 0.5 + ) + points.backFlareLeft = points.backFlare.shift( + 215, + -points.backWaistBandMid.x / 2 * options.backExposure + ) + points.backFlareRight = points.backFlareLeft.flipX(points.backWaistBandMid) + /* This controls the flare */ + points.backFlareLeftCp1 = points.backFlareLeft.shift( + 115, + points.backWaistBandMid.x / 5//-150*options.backExposure + ) + points.backFlareLeftCp2 = points.backFlareLeft.shift( + 295, + points.backWaistBandMid.x / 5//-150*options.backExposure + ) + points.backFlareRightCp1 = points.backFlareLeftCp1.flipX(points.backWaistMid) + points.backFlareRightCp2 = points.backFlareLeftCp2.flipX(points.backWaistMid) + } + + /* Flip points to the right */ + + points.backLegOpeningRightCp1 = points.backLegOpeningLeftCp1.flipX(points.backWaistMid) + points.backGussetRightCp1 = points.backGussetLeftCp1.flipX(points.backWaistMid) + + // Draw paths + + if (options.backExposure >= 0) { + paths.seam = new Path() + .move(points.backWaistBandMid) + .curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip + .line(points.backLegOpeningLeft) + .curve(points.backLegOpeningLeftCp1, points.backGussetLeftCp1, points.backGussetLeft) + .line(points.backGussetMid) + .line(points.backGussetRight) + .curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight) + .line(points.backWaistBandRight) + .curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip + .close() + .attr('class', 'fabric') + } else { + paths.seam = new Path() + .move(points.backWaistBandMid) + .curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip + .line(points.backLegOpeningLeft) + .curve(points.backLegOpeningLeftCp1, points.backFlareLeftCp1, points.backFlareLeft) + .curve(points.backFlareLeftCp2, points.backGussetLeftCp1, points.backGussetLeft) + .line(points.backGussetMid) + .line(points.backGussetRight) + .curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight) + .curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight) + .line(points.backWaistBandRight) + .curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip + .close() + .attr('class', 'fabric') + } + + // Store points for use in other parts + + /* Store gusset points for use in gusset */ + + store.set('backGussetLeft', points.backGussetLeft) + store.set('backGussetRight', points.backGussetRight) + + /* Store lengths for use in elastic */ + + if (options.backExposure >= 0 ) { + store.set( + 'backLegOpeningLength', + new Path() + .move(points.backGussetRight) + .curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight) + .length() + ) + } else { + store.set( + 'backLegOpeningLength', + new Path() + .move(points.backGussetRight) + .curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight) + .curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight), + ) + } + + store.set( + 'backWaistBandLength', + new Path() + .move(points.backWaistBandRight) + .curve(points.backWaistBandRightCp1, points.backWaistBandLeftCp1, points.backWaistBandLeft) + .length() + ) + + // Complete? + if (complete) { + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + } + + macro('title', { + at: points.backMidMid, + nr: 2, + title: 'back', + }) + + points.scaleboxAnchor = points.scalebox = points.backMidMid.shift(90, -50) + macro('miniscale', { at: points.scalebox }) + + // Paperless? + if (paperless) { + macro('hd', { + from: points.backWaistBandRight, + to: points.backWaistBandLeft, + y: points.backWaistBandRight.y + sa - 15, + }) + macro('hd', { + from: points.backLegOpeningRight, + to: points.backLegOpeningLeft, + y: points.backLegOpeningRight.y + sa - 15, + }) + macro('hd', { + from: points.backGussetLeft, + to: points.backGussetRight, + y: points.backGussetLeft.y + sa + 15, + }) + macro('vd', { + from: points.backWaistBandMid, + to: points.backGussetMid, + x: points.backWaistBandMid.x + sa + 15, + }) + if (options.backExposure >= 0 ) { + macro('pd', { + path: new Path() + .move(points.backGussetRight) + .curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight), + d: 15 + }) + } else { + macro('pd', { + path: new Path() + .move(points.backGussetRight) + .curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight) + .curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight), + d: 15 + }) + } + } + + return part +} diff --git a/packages/ursula/src/elastic.js b/packages/ursula/src/elastic.js new file mode 100644 index 00000000000..9a1a5bf1505 --- /dev/null +++ b/packages/ursula/src/elastic.js @@ -0,0 +1,56 @@ +export default function (part) { + let { + options, + Point, + Path, + points, + paths, + measurements, +// Snippet, +// snippets, + store, + utils, + units, + complete, + sa, + paperless, + macro, + } = part.shorthand() + + // Stretch utility method + + store.set('elasticScale', utils.stretchToScale(options.elasticStretch)) + + // Design pattern here + + let legOpeningLength = store.get('frontLegOpeningLength') + store.get('backLegOpeningLength') + store.get('gussetSideLength') + let waistBandLength = store.get('frontWaistBandLength') + store.get('backWaistBandLength') + + points.elasticInfo = new Point(0,0) + .attr('data-text', 'cutTwoPiecesOfElasticToFinishTheLegOpenings') + .attr('data-text', ':') + .attr('data-text', units(legOpeningLength * store.get('elasticScale') + 2 * sa)) + .attr('data-text', '\n') + .attr('data-text', 'cutOnePieceOfElasticToFinishTheWaistBand') + .attr('data-text', ':') + .attr('data-text', units(waistBandLength * store.get('elasticScale') + 2 * sa)) + + // Complete? + if (complete) { + + // if (sa) { + // paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + // } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.elasticInfo, + to: points.elasticInfo, + y: points.elasticInfo.y + sa + 15, + }) + } + + return part +} diff --git a/packages/ursula/src/front.js b/packages/ursula/src/front.js new file mode 100644 index 00000000000..7dc0d7e83ba --- /dev/null +++ b/packages/ursula/src/front.js @@ -0,0 +1,174 @@ +export default function (part) { + let { + options, + Point, + Path, + points, + paths, + measurements, +// Snippet, +// snippets, + store, + utils, + complete, + sa, + paperless, + macro, + } = part.shorthand() + + // Stretch utility method + + store.set('xScale', utils.stretchToScale(options.fabricStretch)) + + // Design pattern here + + // Create points + + points.frontWaistMid = new Point(measurements.seat / 4, 0) + points.frontWaistLeft = new Point(measurements.seat / 4 - measurements.waist / 4 * store.get('xScale'), 0) + points.frontHipLeft = new Point(measurements.seat / 4 - measurements.seat / 4 * store.get('xScale'), measurements.waistToSeat) // Consider renaming from "hip" to "seat" + points.frontGussetLeft = new Point((measurements.seat / 4) - (measurements.waist * options.gussetWidth) * store.get('xScale') / 1.2, measurements.waistToUpperLeg) + points.frontGussetMid = new Point(measurements.seat / 4, measurements.waistToUpperLeg) + + /* Flip points to right side */ + points.frontGussetRight = points.frontGussetLeft.flipX(points.frontWaistMid) + points.frontHipRight = points.frontHipLeft.flipX(points.frontWaistMid) + points.frontWaistRight = points.frontWaistLeft.flipX(points.frontWaistMid) + + /* Waist band is based on waist at top, hip at bottom */ + points.frontWaistBandLeft = points.frontHipLeft.shiftFractionTowards(points.frontWaistLeft, options.rise) + points.frontWaistBandRight = points.frontWaistBandLeft.flipX(points.frontWaistMid) + points.frontWaistBandMid = points.frontWaistBandLeft.shiftFractionTowards(points.frontWaistBandRight, 0.5) + .shift(270,measurements.waistToUpperLeg * options.frontDip) /* Waist band dip */ + + /* Leg opening is based on waist band and hip */ +// points.frontLegOpeningLeft = points.frontHipLeft.shiftFractionTowards(points.frontWaistBandLeft, options.legOpening) // Waist band side point +// points.frontLegOpeningRight = points.frontLegOpeningLeft.flipX(points.frontWaistMid) // Waist band side point + +///////////// Replace the point it's shifting towards with a beamsIntersect() of the +///////////// side (frontWaistLeft and frontHipLeft) and the lowest point of the waistband (backWaistBandMid +///////////// and backWaistBandLeftCp1 should work) +///////////// or maybe beamIntersectsY() of backWaistBandMid.y ?? + + points.frontLegOpeningLeft = points.frontHipLeft.shiftFractionTowards(points.frontWaistBandLeft, options.legOpening) // Waist band low point + points.frontLegOpeningRight = points.frontLegOpeningLeft.flipX(points.frontWaistMid) // Waist band low point + + /* Middle point for label */ + points.frontMidMid = points.frontLegOpeningLeft.shiftFractionTowards(points.frontLegOpeningRight, 0.5) + + // Create control points + + /* Control points for leg opening curves */ + points.frontLegOpeningLeftCp1 = points.frontLegOpeningLeft + .shift(180, points.frontGussetLeft.dy(points.frontLegOpeningLeft)/3); + points.frontGussetLeftCp1 = points.frontGussetLeft +// .shift(270, points.frontGussetLeft.dy(points.frontHipLeft) * 4 * options.taperToGusset); // Consider changing this so it's relative + .shift(270, points.frontGussetLeft.dy(points.frontWaistBandMid) * options.taperToGusset); + + /* Control point for waistband dip */ + points.frontWaistBandLeftCp1 = new Point(points.frontWaistBandRight.x / 3, points.frontWaistBandMid.y) + + /* Flip control points to right side */ + points.frontGussetRightCp1 = points.frontGussetLeftCp1.flipX(points.frontWaistMid) + points.frontLegOpeningRightCp1 = points.frontLegOpeningLeftCp1.flipX(points.frontWaistMid) + points.frontWaistBandRightCp1 = points.frontWaistBandLeftCp1.flipX(points.frontWaistMid) + + // Draw paths + + paths.seam = new Path() + .move(points.frontWaistBandMid) + .curve(points.frontWaistBandLeftCp1, points.frontWaistBandLeft, points.frontWaistBandLeft) // Waist band dip + .line(points.frontLegOpeningLeft) + .curve(points.frontLegOpeningLeftCp1, points.frontGussetLeftCp1, points.frontGussetLeft) + .line(points.frontGussetMid) + .line(points.frontGussetRight) + .curve(points.frontGussetRightCp1, points.frontLegOpeningRightCp1, points.frontLegOpeningRight) + .line(points.frontWaistBandRight) + .curve(points.frontWaistBandRight, points.frontWaistBandRightCp1, points.frontWaistBandMid) // Waist band dip + .close() + .attr('class', 'fabric') + + // Store points for use in other parts + + /* Store side seam points for use in back */ + + store.set('sideSeamWaist', points.frontWaistBandLeft) + store.set('sideSeamHip', points.frontLegOpeningLeft) + + /* Store gusset points for use in gusset */ + + store.set('frontGussetLeft', points.frontGussetLeft) + store.set('frontGussetRight', points.frontGussetRight) + store.set('frontGussetMid', points.frontGussetMid) + + /* Store lengths for use in elastic */ + + store.set( + 'frontLegOpeningLength', + new Path() + .move(points.frontGussetRight) + .curve(points.frontGussetRightCp1, points.frontLegOpeningRightCp1, points.frontLegOpeningRight) + .length() + ) + store.set( + 'frontWaistBandLength', + new Path() + .move(points.frontWaistBandRight) + .curve(points.frontWaistBandRightCp1, points.frontWaistBandLeftCp1, points.frontWaistBandLeft) + .length() + ) + + // Complete? + if (complete) { + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + } + macro('title', { + at: points.frontMidMid, + nr: 1, + title: 'front', + }) + // Paperless? + if (paperless) { + macro('hd', { + from: points.frontWaistBandRight, + to: points.frontWaistBandLeft, + y: points.frontWaistBandRight.y + sa - 15, + }) + macro('hd', { + from: points.frontLegOpeningRight, + to: points.frontLegOpeningLeft, + y: points.frontLegOpeningRight.y + sa - 15, + }) + macro('hd', { + from: points.frontGussetLeft, + to: points.frontGussetRight, + y: points.frontGussetLeft.y + sa + 15, + }) + macro('vd', { + from: points.frontWaistBandMid, + to: points.frontGussetMid, + x: points.frontWaistBandMid.x + sa + 15, + }) + macro('ld', { + from: points.frontWaistBandLeft, + to: points.frontLegOpeningLeft, + d: points.frontWaistBandLeft.y + sa - 15 + }) + macro('pd', { + path: new Path() + .move(points.frontGussetRight) + .curve(points.frontGussetRightCp1, points.frontLegOpeningRightCp1, points.frontLegOpeningRight), + d: 15 + }) +/* macro('vd', { + from: points.frontWaistBandLeft, + to: points.frontWaistBandMid, + x: points.frontWaistBandMid.x + sa + 15, + }) */ + } + + return part +} diff --git a/packages/ursula/src/gusset.js b/packages/ursula/src/gusset.js new file mode 100644 index 00000000000..849c318e57b --- /dev/null +++ b/packages/ursula/src/gusset.js @@ -0,0 +1,95 @@ +export default function (part) { + let { + options, + Point, + Path, + points, + paths, + measurements, +// Snippet, +// snippets, + store, + utils, + complete, + sa, + paperless, + macro, + } = part.shorthand() + + // Design pattern here + + // Create points + + points.frontGussetLeft = new Point(store.get('frontGussetLeft').x, 0) + points.backGussetLeft = new Point(store.get('backGussetLeft').x, measurements.seat * options.gussetLength) + points.frontGussetRight = new Point(store.get('frontGussetRight').x, 0) + points.backGussetRight = new Point(store.get('backGussetRight').x, measurements.seat * options.gussetLength) + + // Create control points + + points.gussetCp1 = points.frontGussetLeft.shiftFractionTowards(points.backGussetLeft, 0.5) + .shift(180,points.frontGussetRight.x / -15) + + // Flip points to right side + + points.gussetCp2 = points.gussetCp1.flipX(store.get('frontGussetMid')) + + // Create point for title + + points.frontMidMid = points.gussetCp1.shiftFractionTowards(points.gussetCp2, 0.5) + + /* Store lengths for use in elastic */ + + store.set( + 'gussetSideLength', + new Path() + .move(points.backGussetRight) + .curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight) + .length() + ) + + // Draw paths + + paths.seam = new Path() + .move(points.frontGussetLeft) + .curve(points.gussetCp1, points.backGussetLeft, points.backGussetLeft) + .line(points.backGussetRight) + .curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight) + .line(points.frontGussetLeft) // Without this, doesn't generate seam allowance + .close() + .attr('class', 'fabric') + + // Complete? + if (complete) { + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + } + macro('title', { + at: points.frontMidMid, + nr: 3, + title: 'gusset', + }) + + // Paperless? + if (paperless) { + macro('hd', { + from: points.frontGussetLeft, + to: points.frontGussetRight, + y: points.frontGussetLeft.y + sa + 15, + }) + macro('hd', { + from: points.backGussetLeft, + to: points.backGussetRight, + y: points.backGussetLeft.y + sa + 15, + }) + macro('vd', { + from: points.frontGussetRight, + to: points.backGussetRight, + x: points.frontGussetRight.x + sa + 15, + }) + } + + return part +} diff --git a/packages/ursula/src/index.js b/packages/ursula/src/index.js new file mode 100644 index 00000000000..975d6168b7c --- /dev/null +++ b/packages/ursula/src/index.js @@ -0,0 +1,18 @@ +import freesewing from '@freesewing/core' +import plugins from '@freesewing/plugin-bundle' +import config from '../config' +import draftFront from './front' +import draftBack from './back' +import draftGusset from './gusset' +import draftElastic from './elastic' + +// Create new design +const Pattern = new freesewing.Design(config, plugins) + +// Attach the draft methods to the prototype +Pattern.prototype.draftFront = draftFront +Pattern.prototype.draftBack = draftBack +Pattern.prototype.draftGusset = draftGusset +Pattern.prototype.draftElastic = draftElastic + +export default Pattern