diff --git a/config/exceptions.yaml b/config/exceptions.yaml index fd9f119bdb5..d66147cd1bf 100644 --- a/config/exceptions.yaml +++ b/config/exceptions.yaml @@ -81,6 +81,8 @@ packageJson: author: Thrunic (https://github.com/Thrunic) onyx: author: Thrunic (https://github.com/Thrunic) + opal: + author: Thrunic (https://github.com/Thrunic) tiberius: *starf waralee: author: woutervdub (https://github.com/woutervdub) diff --git a/config/software/designs.json b/config/software/designs.json index 6dfae93edd2..66fc0ec701d 100644 --- a/config/software/designs.json +++ b/config/software/designs.json @@ -664,6 +664,25 @@ "ribbing" ] }, + "opal": { + "code": "Thrunic", + "description": "A FreeSewing pattern for overalls", + "design": "Thrunic", + "difficulty": 3, + "lab": true, + "org": true, + "tags": [ + "overalls", + "onePiece" + ], + "techniques": [ + "flatFelledSeam", + "hem", + "curvedSeam", + "button", + "pocket" + ] + }, "otis": { "code": "Wouter Van Wageningen", "description": "A FreeSewing pattern for a baby romper", diff --git a/designs/opal/CHANGELOG.md b/designs/opal/CHANGELOG.md new file mode 100644 index 00000000000..6cf18c7fa91 --- /dev/null +++ b/designs/opal/CHANGELOG.md @@ -0,0 +1,17 @@ +# Change log for: @freesewing/opal + + +## 3.0.0 (2022-09-30) + +### Changed + + - All FreeSewing pacakges are now ESM only. + - All FreeSewing pacakges now use named exports. + - Dropped support for NodeJS 14. NodeJS 18 (LTS/hydrogen) or more recent is now required. + + +This is the **initial release**, and the start of this change log. + +> Prior to version 2, FreeSewing was not a JavaScript project. +> As such, that history is out of scope for this change log. + diff --git a/designs/opal/README.md b/designs/opal/README.md new file mode 100644 index 00000000000..a975b283258 --- /dev/null +++ b/designs/opal/README.md @@ -0,0 +1,143 @@ +![FreeSewing](https://static.freesewing.org/banner.png) +

@freesewing/opal on NPM + License: MIT + Code quality on DeepScan + Open issues tagged pkg:opal + All Contributors +

Follow @freesewing_org on Twitter + Chat with us on Discord + Become a FreeSewing Patron + Follow @freesewing_org on Twitter +

+ +# @freesewing/opal + +A FreeSewing pattern that needs a description + + + + +## What am I looking at? 🤔 + +This repository is the FreeSewing *monorepo* holding all FreeSewing's websites, documentation, designs, plugins, and other NPM packages. + +This folder holds: @freesewing/opal + +If you're not entirely sure what to do or how to start, type this command: + +``` +npm run tips +``` + +> If you don't want to set up a dev environment, you can run it in your browser: +> +> [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/freesewing/freesewing) +> +> We recommend that you fork our repository and then +> put `gitpod.io/# to start up a browser-based dev environment of your own. + +## About FreeSewing 💀 + +Where the world of makers and developers collide, that's where you'll find FreeSewing. + +If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate +sewing patterns adapted to your measurements. + +If you're a developer, the FreeSewing documentation lives at [freesewing.dev](https://freesewing.dev/). +The FreeSewing [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox +for parametric design of sewing patterns. But FreeSewing also provides a range +of [plugins](https://freesewing.dev/reference/plugins/) that further extend the +functionality of the platform. + +If you have NodeJS installed, you can try it right now by running: + +```bash +npx create-freesewing-pattern +``` + +Getting started guides are available for: +- [Linux](https://freesewing.dev/tutorials/getting-started-linux/) +- [MacOS](https://freesewing.dev/tutorials/getting-started-mac/) +- [Windows](https://freesewing.dev/tutorials/getting-started-windows/) + +The [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) will +show you how to create your first parametric design. + +## Support FreeSewing: Become a patron 🥰 + +FreeSewing is an open source project maintained by Joost De Cock and financially supported by the FreeSewing patrons. + +If you feel FreeSewing is worthwhile, and you can spend a few coind without +hardship, then you should [join us and become a patron](https://freesewing.org/community/join). + +## Links 👩‍💻 + +**Official channels** + + - 💻 Makers website: [FreeSewing.org](https://freesewing.org) + - 💻 Developers website: [FreeSewing.dev](https://freesewing.dev) + - ✅ [Support](https://github.com/freesewing/freesewing/issues/new/choose), + [Issues](https://github.com/freesewing/freesewing/issues) & + [Discussions](https://github.com/freesewing/freesewing/discussions) on + [GitHub](https://github.com/freesewing/freesewing) + +**Social media** + + - 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org) + - 📷 Instagram: [@freesewing_org](https://instagram.com/freesewing_org) + +**Places the FreeSewing community hangs out** + + - 💬 [Discord](https://discord.freesewing.org/) + - 💬 [Facebook](https://www.facebook.com/groups/627769821272714/) + - 💬 [Reddit](https://www.reddit.com/r/freesewing/) + +## License: MIT 🤓 + +© [Joost De Cock](https://github.com/joostdecock). +See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details. + +## Where to get help 🤯 + +For [Support](https://github.com/freesewing/freesewing/issues/new/choose), +please use the [Issues](https://github.com/freesewing/freesewing/issues) & +[Discussions](https://github.com/freesewing/freesewing/discussions) on +[GitHub](https://github.com/freesewing/freesewing). + diff --git a/designs/opal/build.mjs b/designs/opal/build.mjs new file mode 100644 index 00000000000..99ace216bc8 --- /dev/null +++ b/designs/opal/build.mjs @@ -0,0 +1,35 @@ +/* This script will build the package with esbuild */ +import esbuild from 'esbuild' +import pkg from './package.json' assert { type: 'json' } + +// Create banner based on package info +const banner = `/** + * ${pkg.name} | v${pkg.version} + * ${pkg.description} + * (c) ${new Date().getFullYear()} ${pkg.author} + * @license ${pkg.license} + */` + +// Shared esbuild options +const options = { + banner: { js: banner }, + bundle: true, + entryPoints: ['src/index.mjs'], + format: 'esm', + outfile: 'dist/index.mjs', + external: ['@freesewing'], + metafile: process.env.VERBOSE ? true : false, + minify: process.env.NO_MINIFY ? false : true, + sourcemap: true, +} + +// Let esbuild generate the build +const build = async () => { + const result = await esbuild.build(options).catch(() => process.exit(1)) + + if (process.env.VERBOSE) { + const info = await esbuild.analyzeMetafile(result.metafile) + console.log(info) + } +} +build() diff --git a/designs/opal/data.mjs b/designs/opal/data.mjs new file mode 100644 index 00000000000..33ca4c4ebda --- /dev/null +++ b/designs/opal/data.mjs @@ -0,0 +1,4 @@ +// This file is auto-generated | All changes you make will be overwritten. +export const name = '@freesewing/opal' +export const version = '3.0.0' +export const data = { name, version } diff --git a/designs/opal/i18n/de.json b/designs/opal/i18n/de.json new file mode 100644 index 00000000000..15ff85543e0 --- /dev/null +++ b/designs/opal/i18n/de.json @@ -0,0 +1,7 @@ +{ + "t": "Opal", + "d": "A FreeSewing pattern that needs a description", + "p": { }, + "s": { }, + "o": { } +} diff --git a/designs/opal/i18n/en.json b/designs/opal/i18n/en.json new file mode 100644 index 00000000000..bd29e6a3b1c --- /dev/null +++ b/designs/opal/i18n/en.json @@ -0,0 +1,338 @@ +{ + "t": "Opal Overalls", + "d": "A FreeSewing design for overalls", + "p": { + "back": "Back", + "front": "Front", + "bib": "Bib", + "pocketSlash": "Slash pocket", + "pocketBack": "Back pocket", + "pocketBib": "Bib pocket", + "pocketShield": "Pocket shield", + "pocketCarpenter": "Carpenter pocket", + "pocketCarpenterExtra": "2nd Carpenter pocket", + "hammerLoop": "Hammer loop", + "waistband": "Waistband", + "bibPlacket": "Bib placket" + }, + "s": { + "crossSeamFrontTooSmall.t": "The **front** cannot be drafted.", + "crossSeamFrontTooSmall.d": "The **cross seam front**, of length {{{length}}}, is too short to be drafted onto a body with a seat located {{{depth}}} below the waist and a crotch fork extending {{{girth}}} horizontally beyond the waist. Please check your measurements and options, especially *cross seam front*, *waist to seat*, and *crotch ease*.", + "fold": "Fold", + "grainlineEitherWay": "Grainline goes either way" + }, + "o": { + "hemAllowance": { + "t": "Hem allowance", + "d": "Sets how wide the hems around the front and back bibs and the straps are, as a percent of the seam allowance." + }, + "legHemAllowance": { + "t": "Leg hem allowance", + "d": "Sets how wide the hems around the legs are, as a percent of the seam allowance." + }, + "waistEase": { + "t": "Waist ease", + "d": "Controls how wide the garment will be around the waist." + }, + "waistBalance": { + "t": "Waist balance", + "d": "Controls how much of the waist is part of the front piece and how much is part of the back piece." + }, + "seatEase": { + "t": "Seat ease", + "d": "Controls how wide the garment will be around the seat." + }, + "seatBalance": { + "t": "Seat balance", + "d": "Controls how much of the seat is part of the front piece and how much is part of the back piece." + }, + "thighShape": { + "t": "Thigh shape", + "d": "Controls how elongated the thighs of the garment are. Higher values are used for deeper but narrower thighs." + }, + "legHemEase": { + "t": "Leg hem ease", + "d": "Controls how much ease there is at the bottom of the legs." + }, + "legLength": { + "t": "Leg length", + "d": "Controls how long the legs of the garment will be." + }, + "crossSeamCurveStart": { + "t": "Cross seam curve start", + "d": "Controls where the cross seam starts curving on the back." + }, + "crossSeamCurveBend": { + "t": "Cross seam curve bend", + "d": "Controls how deeply scooped the cross seam is." + }, + "crossSeamCurveAngle": { + "t": "Cross seam curve angle", + "d": "Controls at what angle the cross seam reaches the crotch fork." + }, + "crotchSeamCurveStart": { + "t": "Crotch seam curve start", + "d": "Controls where the crotch seam starts curving on the front." + }, + "crotchSeamCurveBend": { + "t": "Crotch seam curve bend", + "d": "Controls how deeply scooped the crotch seam is." + }, + "crotchSeamCurveAngle": { + "t": "Crotch seam curve angle", + "d": "Controls at what angle the crotch seam reaches the crotch fork." + }, + "crotchForkBalance": { + "t": "Crotch fork balance", + "d": "Controls how far back/forward the crotch fork is placed." + }, + "crotchEase": { + "t": "Crotch ease", + "d": "Controls horizontal ease at the crotch fork." + }, + "crotchDrop": { + "t": "Crotch drop", + "d": "Controls vertical ease at the crotch fork." + }, + "legBalance": { + "t": "Leg balance", + "d": "Positive values move more of the fabric to the back piece, negative values to the front piece." + }, + "waistPosition": { + "t": "Waist position", + "d": "Controls where the waistband is on the front of the overalls. 0 is at the natural waist and -100 is at the seat." + }, + "outseamHeight": { + "t": "Outseam height", + "d": "Controls how far up past the waist the outseam extends, and thus how far up the front and back bibs separate." + }, + "waistbandWidth": { + "t": "Waistband width", + "d": "Controls how wide the front waistband is." + }, + "waistbandLayers": { + "t": "Waistband layers", + "d": "Sets how many layers the front waistband is folded into." + }, + "pocketSlash": { + "t": "Slash pocket", + "d": "Toggles whether or not to include slash (front) pockets in the pattern." + }, + "pocketSlashOpeningWidth": { + "t": "Slash pocket opening width", + "d": "Controls how wide the openings of the slash pockets are." + }, + "pocketSlashOpeningHeight": { + "t": "Slash pocket opening height", + "d": "Controls how high the openings of the slash pockets are." + }, + "pocketSlashOpeningCurve": { + "t": "Slash pocket curve", + "d": "Controls the shape of the openings the slash pockets. 0 is a straight opening, while larger values are more deeply curved." + }, + "pocketSlashWidth": { + "t": "Slash pocket width", + "d": "Controls how wide the slash pocket bags are." + }, + "pocketSlashHeight": { + "t": "Slash pocket height", + "d": "Controls how deep the slash pocket bags are." + }, + "pocketSlashShieldOverlap": { + "t": "Slash pocket shield overlap", + "d": "Controls how far the pocket shield extends past the opening of the slash pockets." + }, + "bibWaistDrop": { + "t": "Waist drop", + "d": "Places extra fabric in the center of the waist, to help the garment better wrap around the belly." + }, + "bibHeight": { + "t": "Bib height", + "d": "Controls how tall the front bib is." + }, + "bibWidth": { + "t": "Bib width", + "d": "Controls how wide the top of the front bib is." + }, + "bibPocketOnFold": { + "t": "Bib pocket on fold", + "d": "Toggles whether to draft the bib pocket pattern on-the-fold, or as a full pattern piece." + }, + "bibPlacketWidth": { + "t": "Bib placket width", + "d": "Controls how wide to make the placket at the top of the front bib." + }, + "bibPlacketLayers": { + "t": "Bib placket layers", + "d": "Sets how many layers of fabric are used for the placket at the top of the front bib." + }, + "pocketBib": { + "t": "Bib pocket", + "d": "Toggles whether to include a bib pocket in the pattern." + }, + "pocketBibVerticalPosition": { + "t": "Bib pocket vertical position", + "d": "Controls where the bib pocket is located on the bib vertically." + }, + "pocketBibStyle": { + "t": "Bib pocket style", + "d": "Choose among the available types/styles of bib pockets." + }, + "pocketBibWidth": { + "t": "Bib pocket width", + "d": "Controls how wide the top of the bib pocket is." + }, + "pocketBibHeight": { + "t": "Bib pocket height", + "d": "Controls how tall the bib pocket is." + }, + "pocketBibFeatureWidth": { + "t": "Bib pocket feature width", + "d": "The exact effect of this option varies based on the selected bib pocket style." + }, + "pocketBibFeatureHeight": { + "t": "Bib pocket feature height", + "d": "The exact effect of this option varies based on the selected bib pocket style." + }, + "pocketBibFeatureCurve": { + "t": "Bib pocket feature curve", + "d": "The exact effect of this option varies based on the selected bib pocket style." + }, + "backBibBaseAngle": { + "t": "Back bib base angle", + "d": "Controls the angle at which the back bib rises from side seam." + }, + "backBibBaseCurve": { + "t": "Back bib base curve", + "d": "Controls how strongly curved the back bib is as it rises from the side seam." + }, + "backBibHexagonVerticalPosition": { + "t": "Back bib hexagon vertical position", + "d": "Controls how far up the hexagon formed by the straps crossing is." + }, + "backBibHexagonHeight": { + "t": "Back bib hexagon height", + "d": "Controls how tall the hexagon formed by the straps crossing is." + }, + "backBibHexagonWidth": { + "t": "Back bib hexagon width", + "d": "Controls how wide the hexagon formed by the straps crossing is." + }, + "backBibHexagonSideHeight": { + "t": "Back bib hexagon side height", + "d": "Controls how tall the left and right sides of the hexagon formed by the straps crossing are." + }, + "strapLength": { + "t": "Strap length", + "d": "Controls how long the straps are." + }, + "strapWidth": { + "t": "Strap width", + "d": "Controls how wide the straps are." + }, + "strapPosition": { + "t": "Strap position", + "d": "Controls where the straps are positioned with respect to the hexagon." + }, + "strapTaperCurve": { + "t": "Strap taper curve", + "d": "Controls how strongly curved the taper of the straps is." + }, + "strapTaperPosition": { + "t": "Strap taper position", + "d": "Controls how long the tapered portion of the straps is." + }, + "pocketBack": { + "t": "Back pocket", + "d": "Toggles whether to include back pockets in the pattern." + }, + "pocketBackPositionX": { + "t": "Back pocket horizontal position", + "d": "Controls where the back pockets are horizontally." + }, + "pocketBackPositionY": { + "t": "Back pocket vertical position", + "d": "Controls where the back pockets are vertically." + }, + "pocketBackWidth": { + "t": "Back pocket width", + "d": "Controls how wide the back pockets are." + }, + "pocketBackHeight": { + "t": "Back pocket height", + "d": "Controls how tall the back pockets are." + }, + "pocketBackCornerWidth": { + "t": "Back pocket corner width", + "d": "Controls how wide the bottom-left and bottom-right corners of the back pocket are." + }, + "pocketBackCornerHeight": { + "t": "Back pocket corner height", + "d": "Controls how tall the bottom-left and bottom-right corners of the back pocket are." + }, + "pocketCarpenter": { + "t": "Carpenter pocket", + "d": "Toggles whether to include a carpenter pocket under the right back pocket." + }, + "pocketCarpenterHeight": { + "t": "Carpenter pocket height", + "d": "Controls how tall the carpenter pocket is." + }, + "pocketCarpenterAnchorX": { + "t": "Carpenter pocket anchor horizontal position", + "d": "Controls where the carpenter pocket is anchored under the back pocket horizontally." + }, + "pocketCarpenterAnchorY": { + "t": "Carpenter pocket anchor vertical position", + "d": "Controls where the carpenter pocket is anchored under the back pocket vertically." + }, + "pocketCarpenterAnchorWidth": { + "t": "Carpenter pocket anchor width", + "d": "Controls how wide the section of the carpenter pocket anchored under the back pocket is." + }, + "pocketCarpenterOpeningHeight": { + "t": "Carpenter pocket opening height", + "d": "Controls how tall the opening to the carpenter pocket is." + }, + "pocketCarpenterExtra": { + "t": "Carpenter pocket extra", + "d": "Toggles whether to include a second pocket over the bottom portion of the carpenter pocket." + }, + "pocketCarpenterExtraHeight": { + "t": "Carpenter pocket extra height", + "d": "Controls how tall to make the second carpenter pocket." + }, + "hammerLoop": { + "t": "Hammer loop", + "d": "Toggles whether to include a hammer loop under the left back pocket." + }, + "hammerLoopWidth": { + "t": "Hammer loop width", + "d": "How wide to make the hammer loop." + }, + "hammerLoopCornerX": { + "t": "Hammer loop corner horizontal position", + "d": "Controls where the hammer loop curves towards. Used for calculating its length." + }, + "hammerLoopCornerY": { + "t": "Hammer loop corner vertical position", + "d": "Controls where the hammer loop curves towards. Used for calculating its length." + }, + "hammerLoopCurve": { + "t": "Hammer loop curve", + "d": "Controls how deeply the hammer loop is curved. Used for calculating its length." + }, + "hammerLoopOutseam": { + "t": "Hammer loop outseam", + "d": "Controls how far down the outseam the hammer loop is inserted. Used for calculating its length." + }, + "hammerLoopFirstFold": { + "t": "Hammer loop first fold", + "d": "Controls how wide the first fold of the hammer loop is." + }, + "hammerLoopSecondFold": { + "t": "Hammer loop second fold", + "d": "Controls how wide the second fold of the hammer loop is." + } +} +} diff --git a/designs/opal/i18n/es.json b/designs/opal/i18n/es.json new file mode 100644 index 00000000000..15ff85543e0 --- /dev/null +++ b/designs/opal/i18n/es.json @@ -0,0 +1,7 @@ +{ + "t": "Opal", + "d": "A FreeSewing pattern that needs a description", + "p": { }, + "s": { }, + "o": { } +} diff --git a/designs/opal/i18n/fr.json b/designs/opal/i18n/fr.json new file mode 100644 index 00000000000..15ff85543e0 --- /dev/null +++ b/designs/opal/i18n/fr.json @@ -0,0 +1,7 @@ +{ + "t": "Opal", + "d": "A FreeSewing pattern that needs a description", + "p": { }, + "s": { }, + "o": { } +} diff --git a/designs/opal/i18n/index.mjs b/designs/opal/i18n/index.mjs new file mode 100644 index 00000000000..36aac928b67 --- /dev/null +++ b/designs/opal/i18n/index.mjs @@ -0,0 +1,8 @@ +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } + +export const i18n = { en, de, es, fr, nl, uk } diff --git a/designs/opal/i18n/nl.json b/designs/opal/i18n/nl.json new file mode 100644 index 00000000000..15ff85543e0 --- /dev/null +++ b/designs/opal/i18n/nl.json @@ -0,0 +1,7 @@ +{ + "t": "Opal", + "d": "A FreeSewing pattern that needs a description", + "p": { }, + "s": { }, + "o": { } +} diff --git a/designs/opal/i18n/uk.json b/designs/opal/i18n/uk.json new file mode 100644 index 00000000000..15ff85543e0 --- /dev/null +++ b/designs/opal/i18n/uk.json @@ -0,0 +1,7 @@ +{ + "t": "Opal", + "d": "A FreeSewing pattern that needs a description", + "p": { }, + "s": { }, + "o": { } +} diff --git a/designs/opal/package.json b/designs/opal/package.json new file mode 100644 index 00000000000..c3a02a99ac1 --- /dev/null +++ b/designs/opal/package.json @@ -0,0 +1,73 @@ +{ + "name": "@freesewing/opal", + "version": "3.0.0", + "description": "A FreeSewing pattern that needs a description", + "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" + }, + "funding": { + "type": "individual", + "url": "https://freesewing.org/patrons/join" + }, + "keywords": [ + "freesewing", + "design", + "diy", + "fashion", + "made to measure", + "parametric design", + "pattern", + "sewing", + "sewing pattern" + ], + "type": "module", + "module": "dist/index.mjs", + "exports": { + ".": { + "internal": "./src/index.mjs", + "default": "./dist/index.mjs" + } + }, + "scripts": { + "build": "node build.mjs", + "build:all": "yarn build", + "clean": "rimraf dist", + "mbuild": "NO_MINIFY=1 node build.mjs", + "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", + "test": "npx mocha tests/*.test.mjs", + "vbuild": "VERBOSE=1 node build.mjs", + "lab": "cd ../../sites/lab && yarn start", + "tips": "node ../../scripts/help.mjs", + "lint": "npx eslint 'src/**' 'tests/*.mjs'", + "prettier": "npx prettier --write 'src/*.mjs' 'tests/*.mjs'", + "testci": "NODE_OPTIONS=\"--conditions=internal\" npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js", + "wbuild": "node build.mjs", + "wbuild:all": "yarn wbuild" + }, + "peerDependencies": { + "@freesewing/core": "3.0.0" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "10.2.0", + "chai": "4.3.10", + "@freesewing/models": "3.0.0", + "@freesewing/plugin-timing": "3.0.0" + }, + "files": [ + "dist/*", + "README.md" + ], + "publishConfig": { + "access": "public", + "tag": "latest" + }, + "engines": { + "node": ">= 18.17.0 <22", + "npm": "9" + } +} diff --git a/designs/opal/src/back.mjs b/designs/opal/src/back.mjs new file mode 100644 index 00000000000..46809b3e0f2 --- /dev/null +++ b/designs/opal/src/back.mjs @@ -0,0 +1,764 @@ +import { bib } from './bib.mjs' + +function draftBack({ + measurements, + options, + absoluteOptions, + Point, + Path, + points, + paths, + Snippet, + snippets, + sa, + complete, + macro, + part, + store, + utils, + scale, +}) { + // The distance from the front waist, over the HPS, and back down to the back waist. This plus the cross seam gives the vertical trunk. + const waistToWaist = measurements.hpsToWaistFront + measurements.hpsToWaistBack + + // First let's draft the bottoms. + points.cfWaist = new Point( + -measurements.waistBackArc * (1 + options.waistEase) * (1 + options.waistBalance), + 0 + ) + points.cfSeat = new Point( + -measurements.seatBackArc * (1 + options.seatEase) * (1 + options.seatBalance), + measurements.waistToSeat + ) + points.crossSeamCurveStart = points.cfWaist.shiftFractionTowards( + points.cfSeat, + options.crossSeamCurveStart + ) + points.fork = new Point( + (-measurements.upperLeg / 2) * + options.thighShape * + (1 + options.crotchEase + options.crotchForkBalance), + measurements.waistToUpperLeg * (1 + options.crotchDrop) + ) + + points.crossSeamCurveMax = utils.beamsIntersect( + points.cfWaist, + points.cfSeat, + points.fork, + points.fork.shift(0, 1337) + ) + points.crossSeamCurveCp1 = points.crossSeamCurveStart.shiftFractionTowards( + points.crossSeamCurveMax, + options.crossSeamCurveBend + ) + points.crossSeamCurveCp2 = points.fork + .shiftFractionTowards(points.crossSeamCurveMax, options.crossSeamCurveBend) + .rotate(options.crossSeamCurveAngle, points.fork) + + const legLength = (measurements.waistToFloor - points.fork.y) * options.legLength + const thighAnkleRatio = Math.min(1, options.legLength / options.anklePosition) + const legWidth = + measurements.upperLeg * (1 - thighAnkleRatio) + measurements.ankle * thighAnkleRatio + points.inseamHem = new Point( + ((-(1 + options.legHemEase) * legWidth) / 2) * (1 + options.legBalance), + points.fork.y + legLength + ) + points.outseamHem = new Point(0, points.fork.y + legLength) + points.waist = new Point(0, 0) + + // Now let's draft the back bib. + points.cfWaist.y = store.get('waistYCoordinate') + points.waist.y = points.cfWaist.y - waistToWaist * options.outseamHeight + const seatWaistInverseSlope = 1 / points.crossSeamCurveStart.slope(points.cfWaist) + points.bibHexagonBottom = new Point( + 0, + -measurements.hpsToWaistBack * + (options.backBibHexagonVerticalPosition - (1 / 2) * options.backBibHexagonHeight) + ) + points.bibHexagonBottom.x = + points.cfWaist.x + (1 / 2) * points.bibHexagonBottom.y * seatWaistInverseSlope + points.bibHexagonCenter = points.bibHexagonBottom.translate( + 0, + +measurements.hpsToWaistBack * ((-1 / 2) * options.backBibHexagonHeight) + ) + points.bibHexagonLowerInside = points.bibHexagonCenter.translate( + (measurements.waist / 4) * options.backBibHexagonWidth, + measurements.hpsToWaistBack * ((1 / 2) * options.backBibHexagonSideHeight) + ) + points.bibHexagonUpperInside = points.bibHexagonCenter.translate( + (measurements.waist / 4) * options.backBibHexagonWidth, + measurements.hpsToWaistBack * ((-1 / 2) * options.backBibHexagonSideHeight) + ) + points.bibHexagonTop = points.bibHexagonCenter.translate( + 0, + +measurements.hpsToWaistBack * ((-1 / 2) * options.backBibHexagonHeight) + ) + points.bibHexagonLowerOutside = points.bibHexagonCenter.translate( + (-measurements.waist / 4) * options.backBibHexagonWidth, + measurements.hpsToWaistBack * ((1 / 2) * options.backBibHexagonSideHeight) + ) + points.bibHexagonUpperOutside = points.bibHexagonCenter.translate( + (-measurements.waist / 4) * options.backBibHexagonWidth, + measurements.hpsToWaistBack * ((-1 / 2) * options.backBibHexagonSideHeight) + ) + + // Next come the straps. + const strapLength = + (waistToWaist - store.get('bibFrontHeight') + points.bibHexagonTop.y) * options.strapLength + const strapWidth = options.strapWidth * waistToWaist + points.strapTaperOutside = new Point( + points.bibHexagonUpperOutside.x + measurements.waistBack * options.strapPosition, + points.bibHexagonTop.y - options.strapTaperPosition * strapLength + ) + points.strapTaperInside = points.strapTaperOutside.translate(strapWidth, 0) + points.strapEndOutside = points.strapTaperOutside.translate( + 0, + -strapLength * (1 - options.strapTaperPosition) + ) + points.strapEndInside = points.strapEndOutside.translate(strapWidth, 0) + + // Finally, let's draft the control points for the curves. + points.forkCp2 = points.crossSeamCurveCp2.rotate(-90, points.fork) + points.inseamHemCp1 = points.inseamHem.shiftFractionTowards(points.forkCp2, 2 / 3) + + points.bibCurveMax = utils.beamsIntersect( + points.waist, + points.waist.shift(180 - options.backBibBaseAngle, 9001), + points.bibHexagonLowerInside, + points.bibHexagonUpperInside + ) + // Avoids an ugly case if backBibBaseCurve would overshoot the hexagon and recurve. + if (points.bibCurveMax.y < points.bibHexagonLowerInside.y) + points.bibCurveMax.y = points.bibHexagonLowerInside.y + points.waistCp2 = points.waist.shiftFractionTowards(points.bibCurveMax, options.backBibBaseCurve) + points.bibHexagonLowerInsideCp1 = points.bibHexagonLowerInside.shiftFractionTowards( + points.bibCurveMax, + options.backBibBaseCurve + ) + + points.strapTaperCurveMax = utils.beamsIntersect( + points.bibHexagonUpperInside, + points.bibHexagonTop, + points.strapTaperInside, + points.strapEndInside + ) + // Avoids an ugly case if the taper point is set too low. + if (points.strapTaperInside.y > points.strapTaperCurveMax.y) { + points.strapTaperInside.y = points.strapTaperCurveMax.y + points.strapTaperOutside.y = points.strapTaperCurveMax.y + } + points.bibHexagonTopCp2 = points.bibHexagonTop.shiftFractionTowards( + points.strapTaperCurveMax, + options.strapTaperCurve + ) + points.strapTaperInsideCp1 = points.strapTaperInside.shiftFractionTowards( + points.strapTaperCurveMax, + options.strapTaperCurve + ) + points.strapTaperOutsideCp2 = points.strapTaperOutside.translate( + 0, + (points.strapTaperOutside.dy(points.bibHexagonUpperOutside) * 1) / 2 + ) + points.bibHexagonUpperOutsideCp1 = points.bibHexagonUpperOutside.translate( + 0, + (points.bibHexagonUpperOutside.dy(points.strapTaperOutside) * 1) / 6 + ) + + points.cfBackMax = utils.beamsIntersect( + points.bibHexagonBottom, + points.bibHexagonTop, + points.cfWaist, + points.crossSeamCurveStart + ) + points.bibHexagonBottomCp2 = points.bibHexagonBottom.shiftFractionTowards(points.cfBackMax, 2 / 3) + points.cfWaistCp1 = points.cfWaist.shiftFractionTowards(points.cfBackMax, 2 / 3) + + // Draft points for the back pocket. + const pocketMetric = -points.cfWaist.x + points.backPocket = new Point( + -pocketMetric * options.pocketBackPositionX, + pocketMetric * options.pocketBackPositionY + ).addText('opal:pocketBack', 'center') + points.backPocketFrontTop = points.backPocket.translate( + (pocketMetric * options.pocketBackWidth) / 2, + (-pocketMetric * options.pocketBackHeight) / 2 + ) + points.backPocketBackTop = points.backPocketFrontTop.translate( + -pocketMetric * options.pocketBackWidth, + 0 + ) + points.backPocketFrontBottom = points.backPocketFrontTop.translate( + 0, + pocketMetric * options.pocketBackHeight + ) + points.backPocketBackBottom = new Point( + points.backPocketBackTop.x, + points.backPocketFrontBottom.y + ) + points.backPocketBackBottomP1 = points.backPocketBackBottom.shiftFractionTowards( + points.backPocketBackTop, + options.pocketBackCornerHeight + ) + points.backPocketBackBottomP2 = points.backPocketBackBottom.shiftFractionTowards( + points.backPocketFrontBottom, + options.pocketBackCornerWidth / 2 + ) + points.backPocketFrontBottomP1 = points.backPocketFrontBottom.shiftFractionTowards( + points.backPocketBackBottom, + options.pocketBackCornerWidth / 2 + ) + points.backPocketFrontBottomP2 = points.backPocketFrontBottom.shiftFractionTowards( + points.backPocketFrontTop, + options.pocketBackCornerHeight + ) + + // Draft points for the carpenter pockets. + points.carpenterPocketTopBack = points.backPocketFrontBottom.translate( + pocketMetric * -options.pocketCarpenterAnchorX, + pocketMetric * -options.pocketCarpenterAnchorY + ) + points.carpenterPocketTopFront = points.carpenterPocketTopBack.translate( + pocketMetric * options.pocketCarpenterAnchorWidth, + 0 + ) + points.carpenterPocketOutseamTop = new Point( + 0, + points.carpenterPocketTopBack.y + pocketMetric * options.pocketCarpenterOpeningHeight + ) + points.carpenterPocketOutseamBottom = new Point( + 0, + points.carpenterPocketTopBack.y + pocketMetric * options.pocketCarpenterHeight + ) + points.carpenterPocketBottomBack = new Point( + points.carpenterPocketTopBack.x, + points.carpenterPocketOutseamBottom.y + ) + points.carpenterPocketExtraOutseamTop = points.carpenterPocketOutseamBottom.translate( + 0, + pocketMetric * -options.pocketCarpenterExtraHeight + ) + points.carpenterPocketExtraBackTop = new Point( + points.carpenterPocketBottomBack.x, + points.carpenterPocketExtraOutseamTop.y + ) + points.carpenterPocketLabel = points.carpenterPocketTopBack + .shiftFractionTowards(points.carpenterPocketOutseamBottom, 0.4) + .addText('opal:pocketCarpenter', 'center') + points.carpenterPocketExtraLabel = points.carpenterPocketBottomBack + .shiftFractionTowards(points.carpenterPocketExtraOutseamTop, 1 / 2) + .addText('opal:pocketCarpenterExtra', 'center') + store.set('carpenterPocketLabel', points.carpenterPocketLabel) + store.set('carpenterPocketExtraLabel', points.carpenterPocketExtraLabel) + + // Draft points for the hammer loop. + points.hammerLoopTop = points.backPocketFrontBottomP1.shiftFractionTowards( + points.backPocketFrontBottomP2, + 0.5 + ) + points.hammerLoopMax = points.hammerLoopTop.translate( + pocketMetric * options.hammerLoopCornerX, + pocketMetric * options.hammerLoopCornerY + ) + points.hammerLoopOutseam = new Point( + 0, + points.hammerLoopTop.y + pocketMetric * options.hammerLoopOutseam + ) + points.hammerLoopCp1 = points.hammerLoopTop.shiftFractionTowards( + points.hammerLoopMax, + options.hammerLoopCurve + ) + points.hammerLoopCp2 = points.hammerLoopOutseam.shiftFractionTowards( + points.hammerLoopMax, + options.hammerLoopCurve + ) + const hammerLoopWidth = pocketMetric * options.hammerLoopWidth + + paths.centerSeam = new Path() + .move(points.bibHexagonBottom) + .curve(points.bibHexagonBottomCp2, points.cfWaistCp1, points.cfWaist) + .line(points.crossSeamCurveStart) + .curve(points.crossSeamCurveCp1, points.crossSeamCurveCp2, points.fork) + .curve(points.forkCp2, points.inseamHemCp1, points.inseamHem) + .addClass('fabric') + paths.outseam = new Path().move(points.outseamHem).line(points.waist).addClass('fabric') + paths.legHem = new Path().move(points.inseamHem).line(points.outseamHem).addClass('fabric') + paths.hem = new Path() + .move(points.waist) + .curve(points.waistCp2, points.bibHexagonLowerInsideCp1, points.bibHexagonLowerInside) + .line(points.bibHexagonUpperInside) + .line(points.bibHexagonTop) + .curve(points.bibHexagonTopCp2, points.strapTaperInsideCp1, points.strapTaperInside) + .line(points.strapEndInside) + .line(points.strapEndOutside) + .line(points.strapTaperOutside) + .curve( + points.strapTaperOutsideCp2, + points.bibHexagonUpperOutsideCp1, + points.bibHexagonUpperOutside + ) + .line(points.bibHexagonLowerOutside) + .line(points.bibHexagonBottom) + .addClass('fabric') + + if (options.pocketBack) { + paths.pocketBackHem = new Path() + .move(points.backPocketFrontTop) + .line(points.backPocketBackTop) + .addClass('fabric dashed') + paths.pocketBackSeam = new Path() + .move(points.backPocketBackTop) + .line(points.backPocketBackBottomP1) + .line(points.backPocketBackBottomP2) + .line(points.backPocketFrontBottomP1) + .line(points.backPocketFrontBottomP2) + .line(points.backPocketFrontTop) + .addClass('fabric dashed') + } + + if (options.pocketCarpenter) { + paths.pocketCarpenterHem = new Path() + .move(points.carpenterPocketOutseamTop) + .line(points.carpenterPocketTopFront) + .addClass('fabric dashed') + + paths.pocketCarpenterSeam = new Path() + .move(points.carpenterPocketTopFront) + .line(points.carpenterPocketTopBack) + .line(points.carpenterPocketBottomBack) + .line(points.carpenterPocketOutseamBottom) + .line(points.carpenterPocketOutseamTop) + .addClass('fabric dashed') + } + + if (options.pocketCarpenterExtra) { + paths.pocketCarpenterExtraHem = new Path() + .move(points.carpenterPocketExtraOutseamTop) + .line(points.carpenterPocketExtraBackTop) + .addClass('fabric dashed') + paths.pocketCarpenterExtraSeam = new Path() + .move(points.carpenterPocketExtraBackTop) + .line(points.carpenterPocketBottomBack) + .line(points.carpenterPocketOutseamBottom) + .line(points.carpenterPocketExtraOutseamTop) + .addClass('fabric dashed') + } + + if (options.hammerLoop) { + paths.hammerLoopCenter = new Path() + .move(points.hammerLoopTop) + .curve(points.hammerLoopCp1, points.hammerLoopCp2, points.hammerLoopOutseam) + .addClass('various dotted') + .addText('opal:hammerLoop', 'center') + paths.hammerLoopLeft = paths.hammerLoopCenter + .offset(hammerLoopWidth / 2) + .addClass('fabric dashed') + paths.hammerLoopRight = paths.hammerLoopCenter + .offset(-hammerLoopWidth / 2) + .addClass('fabric dashed') + store.set('hammerLoopLength', paths.hammerLoopCenter.length()) + store.set('hammerLoopWidth', hammerLoopWidth) + } + + if (sa) { + points.inseamHemAllowance = points.inseamHem.translate(-sa, absoluteOptions.legHemAllowance) + points.outseamHemAllowance = points.outseamHem.translate(sa, absoluteOptions.legHemAllowance) + paths.sa = paths.outseam + .offset(sa) + .join(paths.hem.offset(absoluteOptions.hemAllowance).join(paths.centerSeam.offset(sa))) + .line(points.inseamHemAllowance) + .line(points.outseamHemAllowance) + .close() + .addClass('fabric sa') + } + + if (complete) + paths.hint = new Path() + .move(points.crossSeamCurveStart) + .line(points.crossSeamCurveMax) + .line(points.fork) + .addClass('note help') + + paths.bibLowerHexagonHint = new Path() + .move(points.bibHexagonBottom) + .line(points.bibHexagonLowerInside) + .addClass('note help') + + paths.bibUpperHexagonHint = new Path() + .move(points.bibHexagonTop) + .line(points.bibHexagonUpperOutside) + .addClass('note help') + + macro('hd', { + id: 'wWaist', + from: points.cfWaist, + to: points.waist, + y: points.cfWaist.y, + }) + macro('hd', { + id: 'wWaistToCrossSeamCurveStart', + from: points.crossSeamCurveStart, + to: points.cfWaist, + y: points.cfWaist.y - (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + id: 'wCrossSeamCurveStartToCrossCurveSeamMax', + from: points.crossSeamCurveMax, + to: points.crossSeamCurveStart, + y: points.cfWaist.y - (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + id: 'wCrossSeamCurveMaxToFork', + from: points.fork, + to: points.crossSeamCurveMax, + y: points.cfWaist.y - (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + id: 'wCrossSeamCurveStartToFork', + from: points.fork, + to: points.crossSeamCurveStart, + y: points.cfWaist.y - (sa + 30), + }) + macro('hd', { + id: 'wWidthAtFork', + from: points.fork, + to: points.waist, + y: points.outseamHem.y + (sa + 30), + }) + macro('hd', { + id: 'wHem', + from: points.inseamHem, + to: points.outseamHem, + y: points.outseamHem.y + (sa + 15), + }) + macro('hd', { + id: 'wForkToHem', + from: points.fork, + to: points.inseamHem, + y: points.inseamHem.y + (sa + 15), + }) + macro('hd', { + id: 'wStrapWidth', + from: points.strapEndOutside, + to: points.strapEndInside, + y: points.strapEndOutside.y - (absoluteOptions.hemAllowance + 15), + }) + macro('hd', { + id: 'wStrapInsideToHexagonTop', + from: points.strapEndInside, + to: points.bibHexagonTop, + y: points.strapEndOutside.y - (absoluteOptions.hemAllowance + 15), + }) + macro('hd', { + id: 'wStrapOutsideToHexagonTop', + from: points.strapEndOutside, + to: points.bibHexagonTop, + y: points.strapEndOutside.y - (absoluteOptions.hemAllowance + 30), + }) + macro('hd', { + id: 'wHexagonWidth', + from: points.bibHexagonLowerOutside, + to: points.bibHexagonLowerInside, + y: points.bibHexagonLowerOutside.y, + }) + macro('hd', { + id: 'wWidthHexagonBottomToOutseam', + from: points.bibHexagonBottom, + to: points.waist, + y: points.bibHexagonBottom.y, + }) + macro('hd', { + id: 'wBackBibCurve', + from: points.bibHexagonLowerInside, + to: points.waist, + y: points.bibHexagonLowerInside.y, + }) + macro('vd', { + id: 'vOutseam', + from: points.waist, + to: points.outseamHem, + x: points.waist.x + (sa + 15), + }) + macro('vd', { + id: 'vHexagonLowerSideToOutseamTop', + from: points.bibHexagonLowerInside, + to: points.waist, + x: points.waist.x + 0, + }) + macro('vd', { + id: 'vHexagonUpperSideToLowerSide', + from: points.bibHexagonUpperInside, + to: points.bibHexagonLowerInside, + x: points.waist.x + 0, + }) + macro('vd', { + id: 'vHexagonTopToUpperSide', + from: points.bibHexagonTop, + to: points.bibHexagonUpperInside, + x: points.waist.x + 0, + }) + macro('vd', { + id: 'vHexagonTopToOutseam', + from: points.bibHexagonTop, + to: points.waist, + x: points.waist.x + 15, + }) + macro('vd', { + id: 'vStrapInsideTaperedHeight', + from: points.strapTaperInside, + to: points.bibHexagonTop, + x: points.waist.x + 0, + }) + macro('vd', { + id: 'vStrapInsideStraightHeight', + from: points.strapEndInside, + to: points.strapTaperInside, + x: points.waist.x + 0, + }) + macro('vd', { + id: 'vStrapInsideHeight', + from: points.strapEndInside, + to: points.bibHexagonTop, + x: points.waist.x + 15, + }) + macro('vd', { + id: 'vLegHemAllowance', + from: points.outseamHem, + to: points.outseamHemAllowance, + x: points.waist.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'vWaistToCrossSeamCurveStart', + from: points.cfWaist, + to: points.crossSeamCurveStart, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vCrossSeamCurveStartToFork', + from: points.crossSeamCurveStart, + to: points.fork, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vHexagonBottomToFork', + from: points.bibHexagonBottom, + to: points.fork, + x: points.fork.x - (sa + 30), + }) + macro('vd', { + id: 'vForkToHem', + from: points.fork, + to: points.inseamHem, + x: points.fork.x - (sa + 30), + }) + macro('vd', { + id: 'vHexagonBottomToWaist', + from: points.bibHexagonBottom, + to: points.cfWaist, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vHexagonLowerSideToHexagonBottom', + from: points.bibHexagonLowerOutside, + to: points.bibHexagonBottom, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vHexagonUpperSideToHexagonLowerSide', + from: points.bibHexagonUpperOutside, + to: points.bibHexagonLowerOutside, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vHexagonTopToHexagonUpperSide', + from: points.bibHexagonTop, + to: points.bibHexagonUpperOutside, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vHexagonHeight', + from: points.bibHexagonTop, + to: points.bibHexagonBottom, + x: points.fork.x - (sa + 30), + }) + macro('vd', { + id: 'vStrapStraightHeight', + from: points.strapEndOutside, + to: points.strapTaperOutside, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vStrapTaperHeight', + from: points.strapTaperOutside, + to: points.bibHexagonTop, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vStrapHeight', + from: points.strapEndOutside, + to: points.bibHexagonTop, + x: points.fork.x - (sa + 30), + }) + macro('vd', { + id: 'vTotal', + from: points.strapEndOutside, + to: points.inseamHem, + x: points.fork.x - (sa + 45), + }) + + points.grainlineTop = points.waist.shiftFractionTowards(points.cfWaist, 0.05) + points.grainlineBottom = new Point(points.grainlineTop.x, points.outseamHem.y) + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + store.cutlist.addCut({ cut: 2, from: 'fabric' }) + + points.title = points.cfWaist + .shiftFractionTowards(points.outseamHem, 0.5) + .shiftFractionTowards(points.inseamHem, 0.5) + macro('title', { at: points.title, nr: 2, title: 'opal:back' }) + points.logo = points.title.translate(scale * -20, scale * 35) + snippets.logo = new Snippet('logo', points.logo) + points.scalebox = points.title.translate(scale * -10, scale * -80) + macro('scalebox', { at: points.scalebox }) + + return part +} + +export const back = { + name: 'back', + after: bib, + draft: draftBack, + options: { + // What angle the back bib leaves the outseam at. 0 is horizontal, 90 is vertical. + backBibBaseAngle: { deg: 25, min: 0, max: 90, menu: 'style' }, + // How deep to make the curve connecting the top of the outseam with the hexagon of the back bib. + backBibBaseCurve: { pct: 40, min: 0, max: 100, menu: 'style' }, + // How high up the hexagon of the back bib is located. 0% refers to the waist, while 100% refers to the HPS. + backBibHexagonVerticalPosition: { pct: 50, min: 10, max: 90, menu: 'style' }, + // How tall the hexagon where the two sides of the back bib cross over is, as a percent of hpsToWaistBack. + backBibHexagonHeight: { pct: 40, min: 10, max: 60, menu: 'style' }, + // How wide the hexagon of the back bib is, as a percent of the waist measurement. + backBibHexagonWidth: { pct: 50, min: 20, max: 80, menu: 'style' }, + // How long to make the two vertical sides of the back bib hexagon. + backBibHexagonSideHeight: { pct: 12, min: 5, max: 40, menu: 'style' }, + // How long to make the straps, as a percent of the distance from the front waist, over the HPS, and down to the back waist. Recommended 100-110% for fixed straps, 130-140% for adjustable straps. + strapLength: { pct: 160, min: 100, max: 200, menu: 'style' }, + strapWidth: { + pct: 4, + min: 2, + max: 10, + toAbs: (pct, settings, mergedOptions) => + mergedOptions.strapWidth * + (settings.measurements.hpsToWaistFront + settings.measurements.hpsToWaistBack), + menu: 'style', + }, + // How the straps are positioned with respect to the hexagon. 0 places the outer edge of each strap lined up with the outer edge of the hexagon. Negative values place the outer edge farther out. 0 is generally the most fabric efficient, while negative values may fit better. + strapPosition: { pct: 0, min: -10, max: 0, menu: 'style' }, + // How long the tapered portions of the straps are. Larger values give a longer, more gradual taper from the back bib's width down to the strap's width. + strapTaperPosition: { pct: 50, min: 0, max: 100, menu: 'style' }, + // Controls the shape of the curve as the back bib tapers into the straps. + strapTaperCurve: { pct: 80, min: 0, max: 100, menu: 'style' }, + // Back pocket percentages are as a percentage of the back waist arc, including any ease. + pocketBack: { bool: true, menu: 'style' }, + pocketBackPositionX: { + pct: 60, + min: 20, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketBack ? 'style' : false), + }, + + pocketBackPositionY: { + pct: 100, + min: 0, + max: 160, + menu: (settings, mergedOptions) => (mergedOptions.pocketBack ? 'style' : false), + }, + pocketBackWidth: { + pct: 60, + min: 10, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketBack ? 'style' : false), + }, + + pocketBackHeight: { + pct: 80, + min: 10, + max: 120, + menu: (settings, mergedOptions) => (mergedOptions.pocketBack ? 'style' : false), + }, + pocketBackCornerWidth: { + pct: 50, + min: 0, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketBack ? 'style' : false), + }, + pocketBackCornerHeight: { + pct: 10, + min: 0, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketBack ? 'style' : false), + }, + // Carpenter pocket percentages are as a percentage of the back waist arc, including any ease. + pocketCarpenter: { bool: true, menu: 'style' }, + pocketCarpenterHeight: { + pct: 100, + min: 30, + max: 150, + menu: (settings, mergedOptions) => (mergedOptions.pocketCarpenter ? 'style' : false), + }, + // How far into the back pocket the carpenter pocket goes. Affects style. Larger values will be more secure, but will add bulk. + pocketCarpenterAnchorX: { + pct: 20, + min: 0, + max: 80, + menu: (settings, mergedOptions) => (mergedOptions.pocketCarpenter ? 'style' : false), + }, + pocketCarpenterAnchorY: { + pct: 10, + min: 0, + max: 50, + menu: (settings, mergedOptions) => (mergedOptions.pocketCarpenter ? 'style' : false), + }, + pocketCarpenterAnchorWidth: { + pct: 15, + min: 0, + max: 80, + menu: (settings, mergedOptions) => (mergedOptions.pocketCarpenter ? 'style' : false), + }, + pocketCarpenterOpeningHeight: { + pct: 60, + min: 40, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketCarpenter ? 'style' : false), + }, + pocketCarpenterExtra: { + bool: true, + menu: (settings, mergedOptions) => (mergedOptions.pocketCarpenter ? 'style' : false), + }, + pocketCarpenterExtraHeight: { + pct: 50, + min: 10, + max: 80, + menu: (settings, mergedOptions) => + mergedOptions.pocketCarpenter && mergedOptions.pocketCarpenterExtra ? 'style' : false, + }, + hammerLoop: { bool: true, menu: 'style' }, + hammerLoopWidth: { pct: 10, min: 0, max: 20, menu: 'style' }, + hammerLoopCornerX: { pct: 0, min: -50, max: 50, menu: 'style' }, + hammerLoopCornerY: { pct: 20, min: 0, max: 100, menu: 'style' }, + hammerLoopCurve: { pct: 100, min: 0, max: 100, menu: 'style' }, + hammerLoopOutseam: { pct: 20, min: 0, max: 80, menu: 'style' }, + hammerLoopFirstFold: { pct: 90, min: 0, max: 100, menu: 'style' }, + hammerLoopSecondFold: { pct: 60, min: 0, max: 200, menu: 'style' }, + }, +} diff --git a/designs/opal/src/bib.mjs b/designs/opal/src/bib.mjs new file mode 100644 index 00000000000..6340f65999e --- /dev/null +++ b/designs/opal/src/bib.mjs @@ -0,0 +1,400 @@ +import { front } from './front.mjs' + +function draftBib({ + measurements, + options, + absoluteOptions, + Point, + Path, + points, + paths, + Snippet, + snippets, + sa, + macro, + part, + store, + scale, + utils, +}) { + const waistToWaist = measurements.hpsToWaistFront + measurements.hpsToWaistBack + + points.cfWaist = store + .get('cfWaist') + .copy() + .translate(0, measurements.waistFront * options.bibWaistDrop) + points.outseamWaist = store.get('waist') + + points.cfWaistCp2 = points.cfWaist.translate( + (points.cfWaist.dist(points.outseamWaist) * 1) / 3, + 0 + ) + points.outseamTopCp1 = points.cfWaist + .translate((points.cfWaist.dist(points.outseamWaist) * 1) / 2, 0) + .shiftFractionTowards(points.outseamWaist, 1 / 3) + + // Adjust the waist seam so that it matches the length of the waist seam on the front piece. + paths.waistCurve = new Path() + .move(points.cfWaist) + .curve(points.cfWaistCp2, points.outseamTopCp1, points.outseamWaist) + .hide() + points.outseamWaist = points.outseamWaist.translate( + points.cfWaist.dx(points.outseamWaist) - paths.waistCurve.length(), + 0 + ) + + // Recalculate needed points and paths. + points.cfWaistCp2 = points.cfWaist.translate( + (points.cfWaist.dist(points.outseamWaist) * 1) / 3, + 0 + ) + points.outseamTopCp1 = points.cfWaist + .translate((points.cfWaist.dist(points.outseamWaist) * 1) / 2, 0) + .shiftFractionTowards(points.outseamWaist, 1 / 3) + paths.waistCurve = new Path() + .move(points.outseamWaist.flipX(points.cfWaist)) + .curve( + points.outseamTopCp1.flipX(points.cfWaist), + points.cfWaistCp2.flipX(points.cfWaist), + points.cfWaist + ) + .curve(points.cfWaistCp2, points.outseamTopCp1, points.outseamWaist) + .hide() + + points.outseamTop = points.outseamWaist.translate(0, -waistToWaist * options.outseamHeight) + points.topSide = new Point( + points.cfWaist.x * (1 - options.bibWidth), + -measurements.hpsToWaistFront * options.bibHeight + ) + points.cfTop = new Point(points.cfWaist.x, -measurements.hpsToWaistFront * options.bibHeight) + store.set('bibFrontHeight', -points.cfTop.y) + points.cfMax = points.cfWaist.translate(0, (-points.cfWaist.dist(points.cfTop) * 1) / 2) + points.cfTopCp2 = points.cfTop.shiftFractionTowards(points.cfMax, 2 / 3) + points.cfWaistCp1 = points.cfWaist.shiftFractionTowards(points.cfMax, 2 / 3) + + points.placketCenterBottom = points.cfTop.translate(0, absoluteOptions.bibPlacketWidth) + points.placketSideBottom = utils.beamIntersectsY( + points.topSide, + points.outseamTop, + points.placketCenterBottom.y + ) + if (options.bibPlacketLayers > 0) { + paths.placket = new Path() + .move(points.placketSideBottom.flipX(points.placketCenterBottom)) + .line(points.placketSideBottom) + paths.placket.setClass('fabric dashed') + paths.placket.addText('opal:bibPlacket', 'center') + + store.set('bibPlacketLengthTop', points.cfTop.dist(points.topSide) * 2) + store.set( + 'bibPlacketLengthBottom', + points.placketCenterBottom.dist(points.placketSideBottom) * 2 + ) + } + + points.pocketCenterTop = points.cfWaist.shiftFractionTowards( + points.cfTop, + options.pocketBibVerticalPosition + options.pocketBibHeight / 2 + ) + points.pocketCenterBottom = points.pocketCenterTop.translate( + 0, + points.cfWaist.dist(points.cfTop) * options.pocketBibHeight + ) + points.pocketSideTop = points.pocketCenterTop.translate( + points.cfWaist.dx(points.outseamWaist) * options.pocketBibWidth, + 0 + ) + points.pocketSideBottom = points.pocketCenterBottom.translate( + points.cfWaist.dx(points.outseamWaist) * options.pocketBibWidth, + 0 + ) + points.pocketFeatureSide = points.pocketCenterBottom.translate( + points.cfWaist.dx(points.outseamWaist) * options.pocketBibFeatureWidth, + points.cfWaist.dy(points.cfTop) * options.pocketBibFeatureHeight + ) + if (options.pocketBibStyle === 'hexagon' || options.pocketBibStyle === 'curvedBottom') { + points.pocketMax = points.pocketSideBottom.copy() + points.pocketFeatureSide = points.pocketCenterBottom.translate( + points.cfWaist.dx(points.outseamWaist) * options.pocketBibWidth, + points.cfWaist.dy(points.cfTop) * options.pocketBibFeatureHeight + ) + points.pocketSideBottom = points.pocketCenterBottom.translate( + points.cfWaist.dx(points.pocketSideTop) * options.pocketBibFeatureWidth, + 0 + ) + + points.pocketSideBottomCp2 = points.pocketSideBottom.shiftFractionTowards( + points.pocketMax, + options.pocketBibFeatureCurve + ) + points.pocketFeatureSideCp1 = points.pocketFeatureSide.shiftFractionTowards( + points.pocketMax, + options.pocketBibFeatureCurve + ) + } + + paths.seam = new Path() + .move(points.outseamTop.flipX(points.cfWaist)) + .line(points.outseamWaist.flipX(points.cfWaist)) + .curve( + points.outseamTopCp1.flipX(points.cfWaist), + points.cfWaistCp2.flipX(points.cfWaist), + points.cfWaist + ) + .curve(points.cfWaistCp2, points.outseamTopCp1, points.outseamWaist) + .line(points.outseamTop) + paths.hem = new Path() + .move(points.outseamTop) + .line(points.topSide) + .line(points.topSide.flipX(points.cfTop)) + .line(points.outseamTop.flipX(points.cfWaist)) + .addClass('fabric') + + // Draft the pocket. + if (options.pocketBib) { + paths.bibPocketHem = new Path() + .move(points.pocketSideTop) + .line( + options.bibPocketOnFold + ? points.pocketCenterTop + : points.pocketSideTop.flipX(points.pocketCenterTop) + ) + .addClass('fabric dashed') + + if (options.pocketBibStyle === 'pentagon' && options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketCenterTop) + .line(points.pocketCenterBottom) + .line(points.pocketFeatureSide) + .line(points.pocketSideTop) + .addClass('fabric dashed') + if (options.pocketBibStyle === 'pentagon' && !options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketSideTop.flipX(points.pocketCenterTop)) + .line(points.pocketFeatureSide.flipX(points.pocketCenterTop)) + .line(points.pocketCenterBottom) + .line(points.pocketFeatureSide) + .line(points.pocketSideTop) + .addClass('fabric dashed') + if (options.pocketBibStyle === 'hexagon' && options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketCenterTop) + .line(points.pocketCenterBottom) + .line(points.pocketSideBottom) + .line(points.pocketFeatureSide) + .line(points.pocketSideTop) + .addClass('fabric dashed') + if (options.pocketBibStyle === 'hexagon' && !options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketSideTop.flipX(points.pocketCenterTop)) + .line(points.pocketFeatureSide.flipX(points.pocketCenterTop)) + .line(points.pocketSideBottom.flipX(points.pocketCenterTop)) + .line(points.pocketSideBottom) + .line(points.pocketFeatureSide) + .line(points.pocketSideTop) + .addClass('fabric dashed') + if (options.pocketBibStyle === 'curvedBottom' && options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketCenterTop) + .line(points.pocketCenterBottom) + .line(points.pocketSideBottom) + .curve(points.pocketSideBottomCp2, points.pocketFeatureSideCp1, points.pocketFeatureSide) + .line(points.pocketSideTop) + .addClass('fabric dashed') + if (options.pocketBibStyle === 'curvedBottom' && !options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketSideTop.flipX(points.pocketCenterTop)) + .line(points.pocketFeatureSide.flipX(points.pocketCenterTop)) + .curve( + points.pocketFeatureSideCp1.flipX(points.pocketCenterTop), + points.pocketSideBottomCp2.flipX(points.pocketCenterTop), + points.pocketSideBottom.flipX(points.pocketCenterTop) + ) + .line(points.pocketSideBottom) + .curve(points.pocketSideBottomCp2, points.pocketFeatureSideCp1, points.pocketFeatureSide) + .line(points.pocketSideTop) + .addClass('fabric dashed') + if (options.pocketBibStyle === 'rectangle' && options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketCenterTop) + .line(points.pocketCenterBottom) + .line(points.pocketSideBottom) + .line(points.pocketSideTop) + .addClass('fabric dashed') + if (options.pocketBibStyle === 'rectangle' && !options.bibPocketOnFold) + paths.bibPocketSeam = new Path() + .move(points.pocketSideTop.flipX(points.pocketCenterTop)) + .line(points.pocketSideBottom.flipX(points.pocketCenterTop)) + .line(points.pocketSideBottom) + .line(points.pocketSideTop) + .addClass('fabric dashed') + store.set( + 'bibPocketCenter', + points.pocketCenterTop.shiftFractionTowards(points.pocketCenterBottom, 1 / 2) + ) + } + + points.bibPocketText = points.pocketCenterTop + .shiftFractionTowards(points.pocketCenterBottom, 1 / 16) + .addText('opal:pocketBib', 'center') + + if (sa) { + paths.sa = paths.seam + .offset(sa) + .join(paths.hem.offset(absoluteOptions.hemAllowance)) + .close() + .addClass('fabric sa') + } + + macro('pd', { + id: 'pWaistCurve', + path: paths.waistCurve, + }) + macro('hd', { + id: 'wBibTrapezoidalPart', + from: points.topSide, + to: points.outseamTop, + y: points.cfTop.y - (absoluteOptions.hemAllowance + 15), + }) + macro('vd', { + id: 'hOutseam', + from: points.outseamTop, + to: points.outseamWaist, + x: points.outseamWaist.x + (sa + 15), + }) + macro('vd', { + id: 'hBibTrapezoidalPart', + from: points.topSide, + to: points.outseamTop, + x: points.outseamWaist.x + (sa + 15), + }) + macro('vd', { + id: 'hOutside', + from: points.topSide, + to: points.outseamWaist, + x: points.outseamWaist.x + (sa + 30), + }) + macro('vd', { + id: 'hCurve', + from: points.outseamWaist, + to: points.cfWaist, + x: points.outseamWaist.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'hTotal', + from: points.topSide, + to: points.cfWaist, + x: points.outseamWaist.x + (sa + 45), + }) + macro('hd', { + id: 'wTop', + from: points.topSide.flipX(points.cfTop), + to: points.topSide, + y: points.topSide.y - (absoluteOptions.hemAllowance + 15), + }) + macro('hd', { + id: 'wTotal', + from: points.outseamTop.flipX(points.cfTop), + to: points.outseamTop, + y: points.cfTop.y - (absoluteOptions.hemAllowance + 30), + }) + + points.grainlineTop = points.cfTop + points.grainlineBottom = points.cfWaist + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + store.cutlist.addCut({ cut: 1, from: 'fabric' }) + + points.title = points.cfTop + .shiftFractionTowards(points.cfWaist, 1 / 2) + .translate(scale * 20, scale * 15) + macro('title', { at: points.title, nr: 3, title: 'opal:bib' }) + points.logo = points.title.translate(-scale * 35, scale * 35) + snippets.logo = new Snippet('logo', points.logo) + + return part +} + +export const bib = { + name: 'bib', + draft: draftBib, + options: { + // How much extra fabric to put in the waist, horizontally, to help the overalls fit around the belly. Larger values work better on larger bellies. + bibWaistDrop: { pct: 5, min: 0, max: 15, menu: 'fit' }, + // Height of the front bib, as a percentage of the way from the waist to the HPS. Measured from the natural waist. + bibHeight: { pct: 70, min: 20, max: 90, menu: 'style' }, + // Width of the top of the bib, as a percentage of the waistFront measurement. + bibWidth: { pct: 50, min: 20, max: 100, menu: 'style' }, + // Set to true to the bib on the fold, or false to draft the full piece. + bibPocketOnFold: { + bool: false, + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'construction' : false), + }, + + // How wide to make the reinforced placket at the top of the bib. + bibPlacketWidth: { + pct: 15, + min: 0, + max: 30, + toAbs: (pct, settings, mergedOptions) => + (settings.measurements.waist / 4) * mergedOptions.bibPlacketWidth, + menu: 'construction', + }, + bibPlacketLayers: { count: 3, min: 0, max: 8, menu: 'construction' }, + pocketBib: { bool: true, menu: 'style' }, + pocketBibVerticalPosition: { + pct: 50, + min: 20, + max: 80, + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'style' : false), + }, + pocketBibStyle: { + dflt: 'pentagon', + list: ['pentagon', 'hexagon', 'curvedBottom', 'rectangle'], + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'style' : false), + }, + pocketBibWidth: { + pct: 40, + min: 20, + max: 80, + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'style' : false), + }, + + pocketBibHeight: { + pct: 60, + min: 20, + max: 80, + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'style' : false), + }, + + // How wide the bottom feature is. For pentagons, this is the width at the widest part as a percent of the bib width, for hexagons and curved bottoms, this is the width of the straight section at the bottom as a percent of the pocket width, and this is ignored for rectangles. + pocketBibFeatureWidth: { + pct: 50, + min: 0, + max: 80, + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'style' : false), + }, + + // How far up the bottom feature extends. This is ignored for rectangles. + pocketBibFeatureHeight: { + pct: 5, + min: 0, + max: 20, + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'style' : false), + }, + + // Used for curvedBottom style only. + pocketBibFeatureCurve: { + pct: 50, + min: 0, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketBib ? 'style' : false), + }, + }, + after: front, +} diff --git a/designs/opal/src/bibplacket.mjs b/designs/opal/src/bibplacket.mjs new file mode 100644 index 00000000000..9d60562f40a --- /dev/null +++ b/designs/opal/src/bibplacket.mjs @@ -0,0 +1,119 @@ +import { bib } from './bib.mjs' + +function draftBibPlacket({ + options, + absoluteOptions, + Point, + Path, + points, + paths, + macro, + part, + store, + scale, +}) { + if (options.bibPlacketLayers <= 0) return part.hide() + + const bibPlacketLengthTop = store.get('bibPlacketLengthTop') / 2 + const bibPlacketLengthBottom = store.get('bibPlacketLengthBottom') / 2 + + points.topRight = new Point( + bibPlacketLengthTop, + (-absoluteOptions.bibPlacketWidth * options.bibPlacketLayers) / 2 + ) + points.topLeft = points.topRight.flipX() + points.bottomRight = points.topRight.flipY() + if (options.bibPlacketLayers % 2) points.bottomRight.x = bibPlacketLengthBottom + points.bottomLeft = points.bottomRight.flipX() + + for (let i = 1; i < options.bibPlacketLayers; i++) { + points[`fold${i}Left`] = points.topLeft.shiftFractionTowards( + points.bottomLeft, + i / options.bibPlacketLayers + ) + i % 2 + ? (points[`fold${i}Left`].x = -bibPlacketLengthBottom) + : (points[`fold${i}Left`].x = -bibPlacketLengthTop) + points[`fold${i}Right`] = points.topRight.shiftFractionTowards( + points.bottomRight, + i / options.bibPlacketLayers + ) + i % 2 + ? (points[`fold${i}Right`].x = bibPlacketLengthBottom) + : (points[`fold${i}Right`].x = bibPlacketLengthTop) + paths[`fold${i}`] = new Path() + .move(points[`fold${i}Left`]) + .line(points[`fold${i}Right`]) + .setClass('fabric dashed') + .addText('opal:fold', 'center') + } + + paths.seam = new Path().move(points.topRight).line(points.topLeft) + for (let i = 1; i < options.bibPlacketLayers; i++) { + paths.seam.line(points[`fold${i}Left`]) + } + paths.seam.line(points.bottomLeft).line(points.bottomRight) + for (let i = options.bibPlacketLayers - 1; i > 0; i--) { + paths.seam.line(points[`fold${i}Right`]) + } + paths.seam.line(points.topRight).close().setClass('fabric') + + if (options.bibPlacketLayers == 1) { + points.fold1Left = points.bottomLeft + points.fold1Right = points.bottomRight + } + + macro('hd', { + id: 'wTop', + from: points.topLeft, + to: points.topRight, + y: points.topLeft.y - 15, + }) + macro('hd', { + id: 'wDifference', + from: points.fold1Left, + to: points.topLeft, + y: points.topLeft.y - 15, + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + id: 'wBottom', + from: points.fold1Left, + to: points.fold1Right, + y: points.topLeft.y - 30, + }) + macro('vd', { + id: 'hSingleFold', + from: points.topLeft, + to: points.fold1Left, + x: points.fold1Left.x - 15, + }) + macro('vd', { + id: 'hAllFolds', + from: points.topLeft, + to: points.bottomLeft, + x: points.fold1Left.x - 30, + }) + + points.grainlineTop = points.bottomLeft.shiftFractionTowards(points.topRight, 1 / 16) + points.grainlineBottom = points.grainlineTop.flipX() + + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + store.cutlist.addCut({ cut: 1, from: 'fabric' }) + + points.title = new Point(scale * 30, scale * 15) + macro('title', { at: points.title, nr: 12, title: 'opal:bibPlacket', scale: 0.75 }) + + return part +} + +export const bibPlacket = { + name: 'bibPlacket', + draft: draftBibPlacket, + after: bib, +} diff --git a/designs/opal/src/front.mjs b/designs/opal/src/front.mjs new file mode 100644 index 00000000000..22cf5a88492 --- /dev/null +++ b/designs/opal/src/front.mjs @@ -0,0 +1,425 @@ +function draftFront({ + measurements, + options, + absoluteOptions, + Point, + Path, + points, + paths, + Snippet, + snippets, + sa, + complete, + macro, + part, + store, + utils, + scale, +}) { + points.cfWaist = new Point( + -measurements.waistFrontArc * (1 + options.waistEase) * (1 - options.waistBalance), + 0 + ) + points.cfSeat = new Point( + -measurements.seatFrontArc * (1 + options.seatEase) * (1 - options.seatBalance), + measurements.waistToSeat + ) + points.crossSeamCurveStart = points.cfWaist.shiftFractionTowards( + points.cfSeat, + options.crotchSeamCurveStart + ) + points.fork = new Point( + (-measurements.upperLeg / 2) * + options.thighShape * + (1 + options.crotchEase - options.crotchForkBalance), + measurements.waistToUpperLeg * (1 + options.crotchDrop) + ) + + points.crossSeamCurveMax = utils.beamsIntersect( + points.cfWaist, + points.cfSeat, + points.fork, + points.fork.shift(0, 1337) + ) + points.crossSeamCurveCp1 = points.crossSeamCurveStart.shiftFractionTowards( + points.crossSeamCurveMax, + options.crotchSeamCurveBend + ) + points.crossSeamCurveCp2 = points.fork + .shiftFractionTowards(points.crossSeamCurveMax, options.crotchSeamCurveBend) + .rotate(options.crotchSeamCurveAngle, points.fork) + + store.set('forkYCoordinate', points.fork.y) + + const legLength = (measurements.waistToFloor - points.fork.y) * options.legLength + const thighAnkleRatio = Math.min(1, options.legLength / options.anklePosition) + const legWidth = + measurements.upperLeg * (1 - thighAnkleRatio) + measurements.ankle * thighAnkleRatio + points.inseamHem = new Point( + ((-(1 + options.legHemEase) * legWidth) / 2) * (1 - options.legBalance), + points.fork.y + legLength + ) + points.outseamHem = new Point(0, points.fork.y + legLength) + points.waist = new Point(0, 0) + + // Move the waist points from the natural waist to where they should be for the garment. + points.cfWaist = points.cfWaist.shiftFractionTowards(points.cfSeat, -options.waistPosition) + points.waist.y = points.cfWaist.y + + // Draft the points for the slash pocket. + const waistDist = points.waist.dist(points.cfWaist) + points.slashTop = points.waist.shiftTowards( + points.cfWaist, + waistDist * options.pocketSlashOpeningWidth + ) + points.slashSide = points.waist.shiftTowards( + points.outseamHem, + waistDist * options.pocketSlashOpeningHeight + ) + // and draft the points for the pocket outline. + points.slashOutlineTopOutside = points.waist + points.slashOutlineTopInside = points.waist.shiftTowards( + points.cfWaist, + waistDist * options.pocketSlashWidth + ) + points.slashOutlineBottomOutside = points.waist.shiftTowards( + points.outseamHem, + waistDist * options.pocketSlashHeight + ) + points.slashOutlineBottomInside = new Point( + points.slashOutlineTopInside.x, + points.slashOutlineBottomOutside.y + ) + + // Draft control points for curves. + points.forkCp2 = points.crossSeamCurveCp2.rotate(-90, points.fork) + points.inseamHemCp1 = points.inseamHem.shiftFractionTowards(points.forkCp2, 2 / 3) + points.slashMax = new Point(points.slashTop.x, points.slashSide.y) + points.slashSideCp2 = points.slashSide.shiftFractionTowards( + points.slashMax, + options.pocketSlashOpeningCurve + ) + points.slashTopCp1 = points.slashTop.shiftFractionTowards( + points.slashMax, + options.pocketSlashOpeningCurve + ) + + store.set('waistYCoordinate', points.cfWaist.y) // Needed for the back. + store.set('cfWaist', points.cfWaist) // Needed for the bib. + store.set('waist', points.waist) // Needed for the bib. + store.set('waistDist', waistDist) // Needed for the slash pockets and the waistband. + + if (options.pocketSlash) + paths.slashPocketOutline = new Path() + .move(points.slashOutlineTopOutside) + .line(points.slashOutlineTopInside) + .line(points.slashOutlineBottomInside) + .line(points.slashOutlineBottomOutside) + .line(points.slashOutlineTopOutside) + .close() + .addClass('lining dashed') + + options.pocketSlash + ? (paths.seam = new Path() + .move(points.outseamHem) + .line(points.slashSide) + .curve(points.slashSideCp2, points.slashTopCp1, points.slashTop) + .line(points.cfWaist) + .line(points.crossSeamCurveStart) + .curve(points.crossSeamCurveCp1, points.crossSeamCurveCp2, points.fork) + .curve(points.forkCp2, points.inseamHemCp1, points.inseamHem) + .addClass('fabric')) + : (paths.seam = new Path() + .move(points.outseamHem) + .line(points.waist) + .line(points.cfWaist) + .line(points.crossSeamCurveStart) + .curve(points.crossSeamCurveCp1, points.crossSeamCurveCp2, points.fork) + .curve(points.forkCp2, points.inseamHemCp1, points.inseamHem) + .addClass('fabric')) + + paths.hem = new Path().move(points.inseamHem).line(points.outseamHem).addClass('fabric') + + if (sa) { + points.inseamHemAllowance = points.inseamHem.translate(-sa, absoluteOptions.legHemAllowance) + points.outseamHemAllowance = points.outseamHem.translate(sa, absoluteOptions.legHemAllowance) + paths.sa = paths.seam + .offset(sa) + .line(points.inseamHemAllowance) + .line(points.outseamHemAllowance) + .close() + .addClass('fabric sa') + } + + if (complete) + paths.hint = new Path() + .move(points.crossSeamCurveStart) + .line(points.crossSeamCurveMax) + .line(points.fork) + .addClass('note help') + + if (options.pocketSlash) + macro('hd', { + id: 'wWaistSlash', + from: points.cfWaist, + to: points.slashTop, + y: points.waist.y - (sa + 15), + }) + if (options.pocketSlash) + macro('hd', { + id: 'wWaistExSlash', + from: points.slashTop, + to: points.waist, + y: points.waist.y - (sa + 15), + }) + macro('hd', { + id: 'wWaistTotal', + from: points.cfWaist, + to: points.waist, + y: points.waist.y - (sa + 30), + }) + macro('hd', { + id: 'wWaistToCrossSeamCurveStart', + from: points.crossSeamCurveStart, + to: points.cfWaist, + y: points.waist.y - (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + id: 'wCrossSeamCurveStartToCrossCurveSeamMax', + from: points.crossSeamCurveMax, + to: points.crossSeamCurveStart, + y: points.waist.y - (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + id: 'wCrossSeamCurveMaxToFork', + from: points.fork, + to: points.crossSeamCurveMax, + y: points.waist.y - (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + id: 'wCrossSeamCurveStartToFork', + from: points.fork, + to: points.crossSeamCurveStart, + y: points.waist.y - (sa + 30), + }) + macro('hd', { + id: 'wWidthAtFork', + from: points.fork, + to: points.waist, + y: points.waist.y - (sa + 45), + }) + macro('hd', { + id: 'wHem', + from: points.inseamHem, + to: points.outseamHem, + y: points.outseamHem.y + (sa + 15), + }) + macro('hd', { + id: 'wForkToHem', + from: points.fork, + to: points.inseamHem, + y: points.inseamHem.y + (sa + 15), + }) + if (options.pocketSlash) + macro('vd', { + id: 'vSlashOpening', + from: points.waist, + to: points.slashSide, + x: points.waist.x + (sa + 15), + }) + if (options.pocketSlash) + macro('vd', { + id: 'vOutseam', + from: points.slashSide, + to: points.outseamHem, + x: points.waist.x + (sa + 15), + }) + macro('vd', { + id: 'vTotal', + from: points.waist, + to: points.outseamHem, + x: points.waist.x + (sa + 30), + }) + macro('vd', { + id: 'vLegHemAllowance', + from: points.outseamHem, + to: points.outseamHemAllowance, + x: points.waist.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'vWaistToCrossSeamCurveStart', + from: points.cfWaist, + to: points.crossSeamCurveStart, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vCrossSeamCurveStartToFork', + from: points.crossSeamCurveStart, + to: points.fork, + x: points.fork.x - (sa + 15), + }) + macro('vd', { + id: 'vWaistToFork', + from: points.cfWaist, + to: points.fork, + x: points.fork.x - (sa + 30), + }) + macro('vd', { + id: 'vForkToHem', + from: points.fork, + to: points.inseamHem, + x: points.fork.x - (sa + 30), + }) + + points.grainlineTop = points.slashSide.translate(-waistDist * 0.05, 0) + points.grainlineBottom = new Point(points.grainlineTop.x, points.outseamHem.y) + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + store.cutlist.addCut({ cut: 2, from: 'fabric' }) + + points.title = points.cfWaist.shiftFractionTowards(points.outseamHem, 0.5) + macro('title', { at: points.title, nr: 1, title: 'opal:front' }) + points.logo = points.title.translate(-scale * 20, scale * 35) + snippets.logo = new Snippet('logo', points.logo) + points.scalebox = points.title.translate(0, -scale * 100) + macro('scalebox', { at: points.scalebox }) + + return part +} + +export const front = { + name: 'front', + measurements: [ + 'waist', + 'waistBack', + 'seat', + 'seatBack', + 'waistToSeat', + 'upperLeg', + 'hpsToWaistFront', + 'hpsToWaistBack', + 'waistToUpperLeg', + 'waistToArmpit', + 'waistToFloor', + 'inseam', + 'ankle', + ], + options: { + // How wide to make the hem allowance for everywhere except the legs. The default (150%) is set to make a double-fold hem equal in width to the seam allowance, where the first fold is half the width of the second fold. + hemAllowance: { + pct: 150, + min: 0, + max: 400, + toAbs: (pct, settings, mergedOptions) => settings.sa * mergedOptions.hemAllowance, + menu: 'construction', + }, + // Sets the hem allowance for the legs. Very large values are used for cuffs. If making a regular hem, setting this equal to hemAllowance can work well. + legHemAllowance: { + pct: 150, + min: 0, + max: 1600, + toAbs: (pct, settings, mergedOptions) => settings.sa * mergedOptions.legHemAllowance, + menu: 'construction', + }, + waistEase: { pct: 15, min: -30, max: 100, menu: 'fit' }, + // Moves fabric towards the back piece for positive values, and towards the front piece for negative values. + waistBalance: { pct: 0, min: -15, max: 15, menu: 'fit' }, + seatEase: { pct: 10, min: -30, max: 100, menu: 'fit' }, + seatBalance: { pct: 0, min: -15, max: 15, menu: 'fit' }, + // Ratio between the circumference around both legs individually (2 * upperLeg) vs. around both legs together (like 'seat', but measured at the fork). Larger for deeper and narrower thighs. + thighShape: { pct: 122, min: 116, max: 135, menu: 'advanced' }, + // How much ease to have where the leg ends, wherever that may be. + legHemEase: { pct: 20, min: -30, max: 200, menu: 'fit' }, + // How long the legs on the garment are, measured from the waist to the floor: 40-70% for shorts, ~93% for ankle-length legs, 100% for legs that touch the floor. + legLength: { pct: 30, min: 10, max: 120, menu: 'style' }, + crossSeamCurveStart: { pct: 85, min: 60, max: 100, menu: 'advanced' }, + crossSeamCurveBend: { pct: 65, min: 45, max: 85, menu: 'advanced' }, + crossSeamCurveAngle: { deg: 12, min: 0, max: 45, menu: 'advanced' }, + crotchSeamCurveStart: { pct: 80, min: 60, max: 95, menu: 'advanced' }, + crotchSeamCurveBend: { pct: 80, min: 45, max: 100, menu: 'advanced' }, + crotchSeamCurveAngle: { deg: 25, min: 0, max: 45, menu: 'advanced' }, + // Positive values move more of the fabric to the back piece, negative values to the front piece. + crotchForkBalance: { pct: 10, min: -20, max: 40, menu: 'fit' }, + // Horizontal ease at the crotch fork. + crotchEase: { pct: 10, min: -30, max: 100, menu: 'fit' }, + // Vertical ease at the crotch fork. + crotchDrop: { pct: 5, min: -10, max: 80, menu: 'fit' }, + // Positive values move more of the fabric to the back piece, negative values to the front piece. + legBalance: { pct: 0, min: -30, max: 30, menu: 'fit' }, + // Where to put the waistband on the front of the overalls. 0 is at the natural waist and -100 is at the seat. + waistPosition: { pct: 0, min: -50, max: 50, menu: 'style' }, + anklePosition: 0.91, + // How far up past the waist the outseam extends, and thus how far up the back bib starts and the front bib starts to taper. + outseamHeight: { pct: 5, min: 0, max: 20, menu: 'style' }, + // How wide to make the waistband between the bib and the front piece. + waistbandWidth: { + pct: 10, + min: 0, + max: 20, + toAbs: (pct, settings, mergedOptions) => + (settings.measurements.waist / 4) * mergedOptions.waistbandWidth, + menu: 'construction', + }, + waistbandLayers: { count: 3, min: 0, max: 8, menu: 'construction' }, + + // All slash pocket percentages are with respect to the length of the top of the front piece. + pocketSlash: { bool: true, menu: 'style' }, + // Dimensions of the pocket opening, as a percentage of the distance from. + pocketSlashOpeningWidth: { + pct: 30, + min: 4, + max: 60, + menu: (settings, mergedOptions) => (mergedOptions.pocketSlash ? 'style' : false), + }, + + pocketSlashOpeningHeight: { + pct: 60, + min: 4, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketSlash ? 'style' : false), + }, + + // Shape of the pocket opening. 0 (default) is a straight diagonal line, while positive values make a curve. + pocketSlashOpeningCurve: { + pct: 0, + min: 0, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketSlash ? 'style' : false), + }, + + // Dimensions of the pocket itself, as a percentage of the waistFront. + pocketSlashWidth: { + pct: 70, + min: 20, + max: 100, + menu: (settings, mergedOptions) => (mergedOptions.pocketSlash ? 'style' : false), + }, + + pocketSlashHeight: { + pct: 90, + min: 20, + max: 200, + menu: (settings, mergedOptions) => (mergedOptions.pocketSlash ? 'style' : false), + }, + + // How much past the pocket entrance to extend the pocket shield. + pocketSlashShieldOverlap: { + pct: 30, + min: 0, + max: 60, + menu: (settings, mergedOptions) => (mergedOptions.pocketSlash ? 'style' : false), + }, + }, + draft: draftFront, +} diff --git a/designs/opal/src/hammerloop.mjs b/designs/opal/src/hammerloop.mjs new file mode 100644 index 00000000000..7f9bc00feb1 --- /dev/null +++ b/designs/opal/src/hammerloop.mjs @@ -0,0 +1,142 @@ +import { back } from './back.mjs' + +function draftHammerLoop({ options, Point, Path, points, paths, sa, macro, part, store, scale }) { + if (!options.hammerLoop) return part.hide() + + const hammerLoopLength = store.get('hammerLoopLength') * options.hammerLoopLengthFactor + const hammerLoopWidth = store.get('hammerLoopWidth') + + points.topLeftInside = new Point(-hammerLoopLength / 2, -hammerLoopWidth / 2) + points.bottomLeftInside = new Point(-hammerLoopLength / 2, hammerLoopWidth / 2) + points.bottomRightInside = new Point(hammerLoopLength / 2, hammerLoopWidth / 2) + points.topRightInside = new Point(hammerLoopLength / 2, -hammerLoopWidth / 2) + + points.bottomLeftFold1 = points.bottomLeftInside.translate( + 0, + hammerLoopWidth * options.hammerLoopFirstFold + ) + points.bottomRightFold1 = points.bottomRightInside.translate( + 0, + hammerLoopWidth * options.hammerLoopFirstFold + ) + points.topLeftFold1 = points.topLeftInside.translate( + 0, + -hammerLoopWidth * options.hammerLoopFirstFold + ) + points.topRightFold1 = points.topRightInside.translate( + 0, + -hammerLoopWidth * options.hammerLoopFirstFold + ) + points.topLeftFold2 = points.topLeftFold1.translate( + 0, + -hammerLoopWidth * options.hammerLoopSecondFold + ) + points.topRightFold2 = points.topRightFold1.translate( + 0, + -hammerLoopWidth * options.hammerLoopSecondFold + ) + + points.saTopLeft = points.topLeftFold2.translate(-sa, 0) + points.saBottomLeft = points.bottomLeftFold1.translate(-sa, 0) + points.saTopRight = points.topRightFold2.translate(sa, 0) + points.saBottomRight = points.bottomRightFold1.translate(sa, 0) + + paths.hammerLoop = new Path() + .move(points.topLeftFold2) + .line(points.bottomLeftFold1) + .line(points.bottomRightFold1) + .line(points.topRightFold2) + .line(points.topLeftFold2) + .close() + .addClass('fabric') + + paths.bottomInside = new Path() + .move(points.bottomLeftInside) + .line(points.bottomRightInside) + .addClass('fabric dashed') + .addText('opal:fold', 'center') + paths.topInside = new Path() + .move(points.topLeftInside) + .line(points.topRightInside) + .addClass('fabric dashed') + .addText('opal:fold', 'center') + paths.topFold1 = new Path() + .move(points.topLeftFold1) + .line(points.topRightFold1) + .addClass('fabric dashed') + .addText('opal:fold', 'center') + + if (sa) { + paths.saLeft = new Path() + .move(points.topLeftFold2) + .line(points.saTopLeft) + .line(points.saBottomLeft) + .line(points.bottomLeftFold1) + .addClass('fabric sa') + paths.saRight = new Path() + .move(points.topRightFold2) + .line(points.saTopRight) + .line(points.saBottomRight) + .line(points.bottomRightFold1) + .addClass('fabric sa') + } + + macro('hd', { + id: 'wWidth', + from: points.topLeftFold2, + to: points.topRightFold2, + y: points.topLeftFold2.y - 15, + }) + macro('vd', { + id: 'hBase', + from: points.topRightInside, + to: points.bottomRightInside, + x: points.topRightFold2.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'hFoldBottom', + from: points.bottomRightInside, + to: points.bottomRightFold1, + x: points.topRightFold2.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'hFoldTop1', + from: points.topRightFold1, + to: points.topRightInside, + x: points.topRightFold2.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'hFoldTop2', + from: points.topRightFold2, + to: points.topRightFold1, + x: points.topRightFold2.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'hTotal', + from: points.topRightFold2, + to: points.bottomRightFold1, + x: points.topRightFold2.x + (sa + 30), + }) + + points.title = points.topLeftFold2 + .shiftFractionTowards(points.bottomLeftFold1, 0.5) + .translate(scale * 5, 0) + macro('title', { at: points.title, nr: 10, title: 'opal:hammerLoop', scale: 0.4 }) + + return part +} + +export const hammerLoop = { + name: 'HammerLoop', + draft: draftHammerLoop, + after: back, + options: { hammerLoopLengthFactor: 1 }, +} diff --git a/designs/opal/src/index.mjs b/designs/opal/src/index.mjs new file mode 100644 index 00000000000..010bef67feb --- /dev/null +++ b/designs/opal/src/index.mjs @@ -0,0 +1,53 @@ +import { Design } from '@freesewing/core' +import { i18n } from '../i18n/index.mjs' +import { data } from '../data.mjs' +// Parts +import { front } from './front.mjs' +import { back } from './back.mjs' +import { bib } from './bib.mjs' +import { waistband } from './waistband.mjs' +import { bibPlacket } from './bibplacket.mjs' +import { pocketSlash } from './pocketslash.mjs' +import { pocketSlashShield } from './pocketslashshield.mjs' +import { pocketBib } from './pocketbib.mjs' +import { pocketBack } from './pocketback.mjs' +import { pocketCarpenter } from './pocketcarpenter.mjs' +import { pocketCarpenterExtra } from './pocketcarpenterextra.mjs' +import { hammerLoop } from './hammerloop.mjs' + +// Create new design +const Opal = new Design({ + data, + parts: [ + front, + back, + bib, + waistband, + bibPlacket, + pocketSlash, + pocketSlashShield, + pocketBib, + pocketBack, + pocketCarpenter, + pocketCarpenterExtra, + hammerLoop, + ], +}) + +// Named exports +export { + front, + back, + bib, + waistband, + bibPlacket, + pocketSlash, + pocketSlashShield, + pocketBib, + pocketBack, + pocketCarpenter, + pocketCarpenterExtra, + hammerLoop, + i18n, + Opal, +} diff --git a/designs/opal/src/pocketback.mjs b/designs/opal/src/pocketback.mjs new file mode 100644 index 00000000000..105daf1c59f --- /dev/null +++ b/designs/opal/src/pocketback.mjs @@ -0,0 +1,99 @@ +import { back } from './back.mjs' + +function draftPocketBack({ + options, + absoluteOptions, + points, + paths, + Snippet, + snippets, + sa, + macro, + part, + scale, +}) { + if (!options.pocketBack) return part.hide() + + macro('rmad') + macro('rmScalebox') + + points.title = points.backPocket.copy().translate(scale * 10, scale * 10) + + const keepPaths = ['pocketBackSeam', 'pocketBackHem'] + for (const name in paths) { + if (keepPaths.indexOf(name) === -1) delete paths[name] + } + + paths.pocketBackSeam.setClass('fabric') + paths.pocketBackHem.setClass('fabric') + if (sa) + paths.sa = paths.pocketBackSeam + .offset(sa) + .join(paths.pocketBackHem.offset(absoluteOptions.hemAllowance)) + .close() + .setClass('fabric sa') + + macro('hd', { + id: 'wTop', + from: points.backPocketBackTop, + to: points.backPocketFrontTop, + y: points.backPocketBackTop.y - (absoluteOptions.hemAllowance + 15), + }) + macro('hd', { + id: 'wBottomCenter', + from: points.backPocketBackBottomP2, + to: points.backPocketFrontBottomP1, + y: points.backPocketBackBottom.y + (sa + 15), + }) + macro('hd', { + id: 'wBottomSide', + from: points.backPocketFrontBottomP1, + to: points.backPocketFrontBottomP2, + y: points.backPocketBackBottom.y + (sa + 15), + }) + macro('vd', { + id: 'hSideMain', + from: points.backPocketFrontTop, + to: points.backPocketFrontBottomP2, + x: points.backPocketFrontTop.x + (sa + 15), + }) + macro('vd', { + id: 'hSideDiagonal', + from: points.backPocketFrontBottomP2, + to: points.backPocketFrontBottomP1, + x: points.backPocketFrontTop.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + id: 'hSideTotal', + from: points.backPocketFrontTop, + to: points.backPocketFrontBottomP1, + x: points.backPocketFrontTop.x + (sa + 30), + }) + + points.grainlineTop = points.backPocketBackTop.shiftFractionTowards( + points.backPocketFrontTop, + 0.5 + ) + points.grainlineBottom = points.backPocketBackBottom.shiftFractionTowards( + points.backPocketFrontBottom, + 0.5 + ) + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + macro('title', { at: points.title, nr: 7, title: 'opal:pocketBack' }) + points.logo = points.title.translate(-scale * 20, scale * 35) + snippets.logo = new Snippet('logo', points.logo) + + return part +} + +export const pocketBack = { + name: 'pocketBack', + draft: draftPocketBack, + from: back, +} diff --git a/designs/opal/src/pocketbib.mjs b/designs/opal/src/pocketbib.mjs new file mode 100644 index 00000000000..998e0ac3dea --- /dev/null +++ b/designs/opal/src/pocketbib.mjs @@ -0,0 +1,125 @@ +import { bib } from './bib.mjs' + +function draftPocketBib({ + options, + absoluteOptions, + points, + paths, + Snippet, + snippets, + sa, + macro, + part, + scale, +}) { + if (!options.pocketBib) return part.hide() + + macro('rmad') + + const keepPaths = ['bibPocketSeam', 'bibPocketHem', 'cf'] + for (const name in paths) { + if (keepPaths.indexOf(name) === -1) delete paths[name] + } + + if (options.bibPocketOnFold) delete paths.cf + paths.bibPocketSeam.unhide().setClass('fabric') + paths.bibPocketHem.unhide().setClass('fabric') + + delete points.bibPocketText + + if (sa) + paths.sa = paths.bibPocketHem + .offset(absoluteOptions.hemAllowance) + .join(paths.bibPocketSeam.offset(sa)) + .close() + .setClass('fabric sa') + + macro('hd', { + id: 'wTop', + from: options.bibPocketOnFold + ? points.pocketCenterTop + : points.pocketSideTop.flipX(points.pocketCenterTop), + to: points.pocketSideTop, + y: points.pocketCenterTop.y - (absoluteOptions.hemAllowance + 15), + }) + if (options.pocketBibStyle !== 'rectangle') { + if (options.pocketBibStyle !== 'pentagon') + macro('hd', { + id: 'wBottomCenter', + from: options.bibPocketOnFold + ? points.pocketCenterBottom + : points.pocketSideBottom.flipX(points.pocketCenterTop), + to: points.pocketSideBottom, + y: points.pocketCenterBottom.y + (sa + 15), + }) + if (options.pocketBibStyle !== 'pentagon') + macro('hd', { + id: 'wBottomSide', + from: points.pocketSideBottom, + to: points.pocketFeatureSide, + y: points.pocketCenterBottom.y + (sa + 15), + }) + macro('hd', { + id: 'wBottom', + from: options.bibPocketOnFold + ? points.pocketCenterBottom + : points.pocketFeatureSide.flipX(points.pocketCenterTop), + to: points.pocketFeatureSide, + y: points.pocketCenterBottom.y + (sa + 30), + }) + macro('vd', { + id: 'hUpperSide', + from: points.pocketSideTop, + to: points.pocketFeatureSide, + x: points.pocketFeatureSide.x + (sa + 15), + }) + macro('vd', { + id: 'hLowerSide', + from: points.pocketFeatureSide, + to: points.pocketCenterBottom, + x: points.pocketFeatureSide.x + (sa + 15), + noStartMarker: true, + noEndMarker: true, + }) + } + macro('vd', { + id: 'hTotalSide', + from: points.pocketSideTop, + to: points.pocketCenterBottom, + x: + options.pocketBibStyle === 'rectangle' + ? points.pocketSideBottom.x + (sa + 15) + : points.pocketFeatureSide.x + (sa + 30), + }) + + points.grainlineTop = points.pocketCenterTop + points.grainlineBottom = points.pocketCenterBottom + options.bibPocketOnFold + ? macro('cutOnFold', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + : macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + points.title = points.pocketCenterTop + .shiftFractionTowards(points.pocketCenterBottom, 1 / 2) + .translate(scale * 10, scale * 10) + macro('title', { at: points.title, nr: 4, title: 'opal:pocketBib' }) + options.bibPocketOnFold + ? delete snippets.logo + : (snippets.logo = new Snippet( + 'logo', + (points.logo = points.title.translate(-scale * 20, scale * 35)) + )) + + return part +} + +export const pocketBib = { + name: 'pocketBib', + draft: draftPocketBib, + from: bib, +} diff --git a/designs/opal/src/pocketcarpenter.mjs b/designs/opal/src/pocketcarpenter.mjs new file mode 100644 index 00000000000..94f3be9a9eb --- /dev/null +++ b/designs/opal/src/pocketcarpenter.mjs @@ -0,0 +1,99 @@ +import { back } from './back.mjs' + +function draftPocketCarpenter({ + options, + absoluteOptions, + points, + paths, + Snippet, + snippets, + sa, + macro, + part, + store, + scale, +}) { + if (!options.pocketCarpenter) return part.hide() + + macro('rmad') + macro('rmScalebox') + + const keepPaths = ['pocketCarpenterSeam', 'pocketCarpenterHem'] + for (const name in paths) { + if (keepPaths.indexOf(name) === -1) delete paths[name] + } + + delete snippets.logo + + paths.pocketCarpenterHem.setClass('fabric') + paths.pocketCarpenterSeam.setClass('fabric') + if (sa) + paths.sa = paths.pocketCarpenterSeam + .offset(sa) + .join(paths.pocketCarpenterHem.offset(absoluteOptions.hemAllowance)) + .close() + .setClass('fabric sa') + + macro('hd', { + id: 'wTop', + from: points.carpenterPocketTopBack, + to: points.carpenterPocketTopFront, + y: points.carpenterPocketTopFront.y - (sa + 15), + }) + macro('hd', { + id: 'wOpening', + from: points.carpenterPocketTopFront, + to: points.carpenterPocketOutseamTop, + y: points.carpenterPocketTopFront.y - (sa + 15), + }) + macro('hd', { + id: 'wTotal', + from: points.carpenterPocketTopBack, + to: points.carpenterPocketOutseamTop, + y: points.carpenterPocketTopFront.y - (sa + 30), + }) + macro('vd', { + id: 'hOpening', + from: points.carpenterPocketTopFront, + to: points.carpenterPocketOutseamTop, + x: points.carpenterPocketOutseamTop.x + (sa + 15), + }) + macro('vd', { + id: 'hSide', + from: points.carpenterPocketOutseamTop, + to: points.carpenterPocketOutseamBottom, + x: points.carpenterPocketOutseamTop.x + (sa + 15), + }) + macro('vd', { + id: 'hTotal', + from: points.carpenterPocketTopFront, + to: points.carpenterPocketOutseamBottom, + x: points.carpenterPocketOutseamTop.x + (sa + 30), + }) + + points.grainlineTop = points.carpenterPocketTopBack.translate(scale * 10, 0) + points.grainlineBottom = points.carpenterPocketBottomBack.translate(scale * 10, 0) + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + store.cutlist.removeCut('fabric') + store.cutlist.addCut({ cut: 1, from: 'fabric' }) + + points.title = points.carpenterPocketTopBack.shiftFractionTowards( + points.carpenterPocketOutseamBottom, + 0.5 + ) + macro('title', { at: points.title, nr: 8, title: 'opal:pocketCarpenter', align: 'center' }) + points.logo = points.title.translate(scale * 20, scale * 120) + snippets.logo = new Snippet('logo', points.logo) + + return part +} + +export const pocketCarpenter = { + name: 'pocketCarpenter', + draft: draftPocketCarpenter, + from: back, +} diff --git a/designs/opal/src/pocketcarpenterextra.mjs b/designs/opal/src/pocketcarpenterextra.mjs new file mode 100644 index 00000000000..44169993c46 --- /dev/null +++ b/designs/opal/src/pocketcarpenterextra.mjs @@ -0,0 +1,73 @@ +import { back } from './back.mjs' + +function draftPocketCarpenterExtra({ + options, + absoluteOptions, + points, + paths, + snippets, + sa, + macro, + part, + store, + scale, +}) { + if (!options.pocketCarpenterExtra) return part.hide() + + macro('rmad') + macro('rmScalebox') + + const keepPaths = ['pocketCarpenterExtraSeam', 'pocketCarpenterExtraHem'] + for (const name in paths) { + if (keepPaths.indexOf(name) === -1) delete paths[name] + } + + delete snippets.logo + + paths.pocketCarpenterExtraHem.setClass('fabric') + paths.pocketCarpenterExtraSeam.setClass('fabric') + if (sa) + paths.sa = paths.pocketCarpenterExtraSeam + .offset(sa) + .join(paths.pocketCarpenterExtraHem.offset(absoluteOptions.hemAllowance)) + .close() + .setClass('fabric sa') + + macro('hd', { + id: 'wWidth', + from: points.carpenterPocketExtraBackTop, + to: points.carpenterPocketExtraOutseamTop, + y: points.carpenterPocketExtraBackTop.y - (absoluteOptions.hemAllowance + 15), + }) + macro('vd', { + id: 'hHeight', + from: points.carpenterPocketExtraOutseamTop, + to: points.carpenterPocketOutseamBottom, + x: points.carpenterPocketExtraOutseamTop.x + (sa + 15), + }) + + points.grainlineTop = points.carpenterPocketExtraBackTop.translate(scale * 10, 0) + points.grainlineBottom = points.carpenterPocketBottomBack.translate(scale * 10, 0) + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + }) + + store.cutlist.removeCut('fabric') + store.cutlist.addCut({ cut: 1, from: 'fabric' }) + + points.title = points.carpenterPocketExtraBackTop.shiftFractionTowards( + points.carpenterPocketOutseamBottom, + 0.5 + ) + macro('title', { at: points.title, nr: 9, title: 'opal:pocketCarpenterExtra', align: 'center' }) + points.logo = points.title.translate(scale * -10, scale * 35) + + return part +} + +export const pocketCarpenterExtra = { + name: 'pocketCarpenterExtra', + draft: draftPocketCarpenterExtra, + from: back, +} diff --git a/designs/opal/src/pocketslash.mjs b/designs/opal/src/pocketslash.mjs new file mode 100644 index 00000000000..c948e78758a --- /dev/null +++ b/designs/opal/src/pocketslash.mjs @@ -0,0 +1,207 @@ +import { front } from './front.mjs' + +function draftPocketSlash({ + options, + Point, + Path, + points, + paths, + Snippet, + snippets, + sa, + macro, + part, + store, + scale, + utils, +}) { + if (!options.pocketSlash) return part.hide() + + const waistDist = store.get('waistDist') + + // Draft the points for the pocket outline. + points.centerTop = new Point(0, 0) + points.centerBottom = new Point(0, waistDist * options.pocketSlashHeight) + points.topRight = new Point(waistDist * options.pocketSlashWidth, 0) + points.topLeft = new Point(-waistDist * options.pocketSlashWidth, 0) + points.bottomLeft = new Point( + -waistDist * options.pocketSlashWidth, + waistDist * options.pocketSlashHeight + ) + points.bottomRight = new Point( + waistDist * options.pocketSlashWidth, + waistDist * options.pocketSlashHeight + ) + points.slashTop = points.topRight.translate(-waistDist * options.pocketSlashOpeningWidth, 0) + points.slashSide = points.topRight.translate(0, waistDist * options.pocketSlashOpeningHeight) + + const shieldHorizontal = options.pocketSlashOpeningWidth + const shieldVertical = options.pocketSlashOpeningHeight + const shieldHypotenuse = Math.hypot(shieldHorizontal, shieldVertical) + points.shieldTop = points.topLeft.translate( + waistDist * + (options.pocketSlashOpeningWidth + + (shieldHorizontal / shieldHypotenuse) * options.pocketSlashShieldOverlap), + 0 + ) + points.shieldSide = points.topLeft.translate( + 0, + waistDist * + (options.pocketSlashOpeningHeight + + (shieldVertical / shieldHypotenuse) * options.pocketSlashShieldOverlap) + ) + + // Clip the shield if it extends past the ends of the pocket. + if (points.shieldSide.y > points.bottomLeft.y) { + points.shieldSideTrim = utils.beamIntersectsY( + points.shieldSide, + points.shieldTop, + points.bottomLeft.y + ) + points.shieldSide = points.bottomLeft + } else { + points.shieldSideTrim = points.shieldSide + } + if (points.shieldTop.x > points.centerTop.x) { + points.shieldTopTrim = utils.beamIntersectsX( + points.shieldSide, + points.shieldTop, + points.centerTop.x + ) + points.shieldTop = points.centerTop + } else { + points.shieldTopTrim = points.shieldTop + } + + points.slashMax = new Point(points.slashTop.x, points.slashSide.y) + points.slashSideCp2 = points.slashSide.shiftFractionTowards( + points.slashMax, + options.pocketSlashOpeningCurve + ) + points.slashTopCp1 = points.slashTop.shiftFractionTowards( + points.slashMax, + options.pocketSlashOpeningCurve + ) + + points.shieldMax = new Point(points.shieldTop.x, points.shieldSideTrim.y) + points.shieldSideCp2 = points.shieldSideTrim.shiftFractionTowards( + points.shieldMax, + options.pocketSlashOpeningCurve + ) + points.shieldTopCp1 = points.shieldTopTrim.shiftFractionTowards( + points.shieldMax, + options.pocketSlashOpeningCurve + ) + + paths.seam = new Path() + .move(points.topLeft) + .line(points.bottomLeft) + .line(points.bottomRight) + .line(points.slashSide) + .curve(points.slashSideCp2, points.slashTopCp1, points.slashTop) + .line(points.topLeft) + .close() + .addClass('lining') + + paths.fold = new Path() + .move(points.centerTop) + .line(points.centerBottom) + .addText('opal:fold') + .addClass('various dashed') + + paths.shield = new Path() + .move(points.shieldTop) + .line(points.topLeft) + .line(points.shieldSide) + .line(points.shieldSideTrim) + .curve(points.shieldSideCp2, points.shieldTopCp1, points.shieldTopTrim) + .line(points.shieldTop) + .close() + .addClass('fabric dashed') + + points.shieldText = points.shieldTop + .shiftFractionTowards(points.shieldSide, 1 / 2) + .shiftFractionTowards(points.topLeft, 3 / 4) + .addText('opal:pocketShield') + points.shieldCenter = points.shieldTop + .shiftFractionTowards(points.shieldSide, 1 / 2) + .shiftFractionTowards(points.topLeft, 1 / 2) + + if (sa) { + paths.sa = paths.seam.offset(sa).addClass('sa lining') + + points.saShieldTopRight = points.shieldTop.translate(0, -sa) + points.saShieldTopLeft = points.topLeft.translate(-sa, -sa) + points.saShieldBottomLeft = points.shieldSide.translate( + -sa, + points.bottomLeft.y === points.shieldSide.y ? sa : 0 + ) + points.saShieldBottomRight = points.shieldSideTrim.translate( + 0, + points.bottomLeft.y === points.shieldSide.y ? sa : 0 + ) + paths.saShield = new Path() + .move(points.shieldTop) + .line(points.saShieldTopRight) + .line(points.saShieldTopLeft) + .line(points.saShieldBottomLeft) + .line(points.saShieldBottomRight) + .line(points.shieldSideTrim) + .addClass('sa fabric') + .hide() + } + + macro('hd', { + id: 'wTopLeft', + from: points.topLeft, + to: points.centerTop, + y: points.topLeft.y - (sa + 15), + }) + macro('hd', { + id: 'wTop', + from: points.topLeft, + to: points.slashTop, + y: points.topLeft.y - (sa + 30), + }) + macro('hd', { + id: 'wSlash', + from: points.slashTop, + to: points.slashSide, + y: points.topLeft.y - (sa + 15), + }) + macro('hd', { + id: 'wBottom', + from: points.bottomLeft, + to: points.bottomRight, + y: points.bottomLeft.y + (sa + 15), + }) + macro('vd', { + id: 'hSlash', + from: points.slashTop, + to: points.slashSide, + x: points.bottomRight.x + (sa + 15), + }) + macro('vd', { + id: 'hSide', + from: points.slashTop, + to: points.bottomRight, + x: points.bottomRight.x + (sa + 30), + }) + + store.cutlist.addCut({ cut: 2, from: 'lining' }) + + points.title = points.centerTop + .shiftFractionTowards(points.centerBottom, 1 / 2) + .translate(scale * 10, scale * 25) + macro('title', { at: points.title, nr: 5, title: 'opal:pocketSlash' }) + points.logo = points.title.translate(-scale * 20, scale * 35) + snippets.logo = new Snippet('logo', points.logo) + + return part +} + +export const pocketSlash = { + name: 'pocketSlash', + draft: draftPocketSlash, + after: front, +} diff --git a/designs/opal/src/pocketslashshield.mjs b/designs/opal/src/pocketslashshield.mjs new file mode 100644 index 00000000000..7a956e82bc9 --- /dev/null +++ b/designs/opal/src/pocketslashshield.mjs @@ -0,0 +1,85 @@ +import { pocketSlash } from './pocketslash.mjs' + +function draftPocketSlashShield({ + options, + points, + paths, + snippets, + sa, + macro, + part, + store, + scale, +}) { + if (!options.pocketSlash) return part.hide() + + macro('rmad') + + const keepPaths = ['shield', 'saShield'] + for (const name in paths) { + if (keepPaths.indexOf(name) === -1) delete paths[name] + } + + if (sa) paths.saShield.unhide() + paths.shield.setClass('fabric') + points.shieldText.setText(null) + delete snippets.logo + + macro('hd', { + id: 'wTop', + from: points.topLeft, + to: points.shieldTop, + y: points.topLeft.y - (sa + 15), + }) + macro('vd', { + id: 'hTop', + from: points.topLeft, + to: points.shieldSide, + x: points.shieldSide.x - (sa + 15), + }) + if (points.shieldSide.x != points.shieldSideTrim.x) { + macro('hd', { + id: 'wBottomTrim', + from: points.shieldSide, + to: points.shieldSideTrim, + y: points.shieldSide.y + (sa + 15), + noStartMarker: points.shieldSideTrim.x - points.shieldSide.x < 25 * scale ? true : false, + noEndMarker: points.shieldSideTrim.x - points.shieldSide.x < 25 * scale ? true : false, + }) + macro('hd', { + id: 'wDiagonal', + from: points.shieldSideTrim, + to: points.shieldTopTrim, + y: points.shieldSide.y + (sa + 15), + }) + } + if (points.shieldTop.y != points.shieldTopTrim.y) { + macro('vd', { + id: 'hSideTrim', + from: points.shieldTop, + to: points.shieldTopTrim, + x: points.shieldTop.x + (sa + 15), + noStartMarker: points.shieldTopTrim.y - points.shieldTop.y < 25 * scale ? true : false, + noEndMarker: points.shieldTopTrim.y - points.shieldTop.y < 25 * scale ? true : false, + }) + macro('vd', { + id: 'hDiagonal', + from: points.shieldTopTrim, + to: points.shieldSideTrim, + x: points.shieldTop.x + (sa + 15), + }) + } + + points.title = points.shieldCenter.translate(scale * -10, scale * 10) + macro('title', { at: points.title, nr: 6, title: 'opal:pocketShield', scale: 0.6 }) + store.cutlist.removeCut('lining') + store.cutlist.addCut({ cut: 2, from: 'fabric' }) + + return part +} + +export const pocketSlashShield = { + name: 'pocketSlashShield', + draft: draftPocketSlashShield, + from: pocketSlash, +} diff --git a/designs/opal/src/waistband.mjs b/designs/opal/src/waistband.mjs new file mode 100644 index 00000000000..7fe473d1562 --- /dev/null +++ b/designs/opal/src/waistband.mjs @@ -0,0 +1,116 @@ +import { front } from './front.mjs' + +function draftWaistband({ + options, + absoluteOptions, + Point, + Path, + points, + paths, + sa, + macro, + part, + store, + scale, +}) { + const waistDist = store.get('waistDist') + points.topRight = new Point( + waistDist, + (-absoluteOptions.waistbandWidth * options.waistbandLayers) / 2 + ) + points.topLeft = points.topRight.flipX() + points.bottomRight = points.topRight.flipY() + points.bottomLeft = points.bottomRight.flipX() + + for (let i = 1; i < options.waistbandLayers; i++) { + points[`fold${i}Left`] = points.topLeft.shiftFractionTowards( + points.bottomLeft, + i / options.waistbandLayers + ) + points[`fold${i}Right`] = points.topRight.shiftFractionTowards( + points.bottomRight, + i / options.waistbandLayers + ) + paths[`fold${i}`] = new Path() + .move(points[`fold${i}Left`]) + .line(points[`fold${i}Right`]) + .setClass('fabric dashed') + .addText('opal:fold', 'center') + } + + paths.seam = new Path() + .move(points.topRight) + .line(points.topLeft) + .line(points.bottomLeft) + .line(points.bottomRight) + .line(points.topRight) + .close() + .setClass('fabric') + + points.saTopRight = points.topRight.translate(sa, 0) + points.saTopLeft = points.topLeft.translate(-sa, 0) + points.saBottomRight = points.bottomRight.translate(sa, 0) + points.saBottomLeft = points.bottomLeft.translate(-sa, 0) + + if (sa) { + paths.saRight = new Path() + .move(points.bottomRight) + .line(points.saBottomRight) + .line(points.saTopRight) + .line(points.topRight) + .addClass('sa fabric') + paths.saLeft = new Path() + .move(points.bottomLeft) + .line(points.saBottomLeft) + .line(points.saTopLeft) + .line(points.topLeft) + .addClass('sa fabric') + } + + macro('hd', { + id: 'wWaistband', + from: points.topLeft, + to: points.topRight, + y: points.topLeft.y - 15, + }) + macro('vd', { + id: 'hWaistband', + from: points.topLeft, + to: points.bottomLeft, + x: points.topLeft.x - (sa + 15), + }) + + points.grainlineTop = points.topLeft.shiftFractionTowards(points.bottomRight, 3 / 32) + points.grainlineBottom = points.grainlineTop.flipY() + points.grainlineTop2 = new Point((points.topLeft.x * 15) / 16, 0) + points.grainlineBottom2 = new Point((points.topLeft.x * 11) / 16, 0) + points.grainText = new Point((points.topLeft.x * 13) / 16, (points.topLeft.y * 1) / 16).addText( + 'opal:grainlineEitherWay', + 'note center' + ) + + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom, + text: null, + }) + macro('grainline', { + id: 'grainline2', + from: points.grainlineTop2, + to: points.grainlineBottom2, + text: null, + }) + + store.cutlist.addCut({ cut: 1, from: 'fabric' }) + + points.title = new Point(scale * 30, scale * 5) + macro('title', { at: points.title, nr: 11, title: 'opal:waistband', scale: 0.75 }) + + return part +} + +export const waistband = { + name: 'waistband', + draft: draftWaistband, + after: front, +} diff --git a/designs/opal/tests/shared.test.mjs b/designs/opal/tests/shared.test.mjs new file mode 100644 index 00000000000..9267c200845 --- /dev/null +++ b/designs/opal/tests/shared.test.mjs @@ -0,0 +1,20 @@ +// This file is auto-generated | Any changes you make will be overwritten. +import { Opal, i18n } from '../src/index.mjs' + +// Shared tests +import { testPatternConfig } from '../../../tests/designs/config.mjs' +import { testPatternI18n } from '../../../tests/designs/i18n.mjs' +import { testPatternDrafting } from '../../../tests/designs/drafting.mjs' +import { testPatternSampling } from '../../../tests/designs/sampling.mjs' + +// Test config +testPatternConfig(Opal) + +// Test translation +testPatternI18n(Opal, i18n) + +// Test drafting - Change the second parameter to `true` to log errors +testPatternDrafting(Opal, false) + +// Test sampling - Change the second parameter to `true` to log errors +testPatternSampling(Opal, false) diff --git a/markdown/org/docs/designs/opal/cutting/en.md b/markdown/org/docs/designs/opal/cutting/en.md new file mode 100644 index 00000000000..92071871276 --- /dev/null +++ b/markdown/org/docs/designs/opal/cutting/en.md @@ -0,0 +1,25 @@ +--- +title: "Opal Overalls: Cutting Instructions" +--- + +- Cut **2 front** parts +- Cut **2 back** parts +- Cut **1 bib** part +- Cut **1 waistband** part +- Cut **1 bib placket** part +- Cut **1 bib pocket** part (optional) +- Cut **2 slash pocket** parts (optional) +- Cut **2 pocket shield** parts (optional) +- Cut **2 back pocket** parts (optional) +- Cut **1 carpenter pocket** part (optional) +- Cut **1 2nd carpenter pocket** part (optional) +- Cut **1 hammer loop** part (optional) + + + +When cutting out two, you can cut them [good sides together](/docs/sewing/good-sides-together). +However, when working with fabric with a pattern, I prefer to cut them individually to finely control the pattern matching. + +When you cut them individually, remember that they need to be mirror images of each other. So flip either your pattern or your fabric over when cutting the second one. + + diff --git a/markdown/org/docs/designs/opal/en.md b/markdown/org/docs/designs/opal/en.md new file mode 100644 index 00000000000..ce3306cdb2e --- /dev/null +++ b/markdown/org/docs/designs/opal/en.md @@ -0,0 +1,5 @@ +--- +title: "Opal Overalls" +--- + + diff --git a/markdown/org/docs/designs/opal/fabric/en.md b/markdown/org/docs/designs/opal/fabric/en.md new file mode 100644 index 00000000000..03565664215 --- /dev/null +++ b/markdown/org/docs/designs/opal/fabric/en.md @@ -0,0 +1,5 @@ +--- +title: "Opal Overalls: Fabric Options" +--- + +This pattern is designed to work with denim, but should work with most woven fabrics. diff --git a/markdown/org/docs/designs/opal/instructions/en.md b/markdown/org/docs/designs/opal/instructions/en.md new file mode 100644 index 00000000000..6b48d9d7cea --- /dev/null +++ b/markdown/org/docs/designs/opal/instructions/en.md @@ -0,0 +1,112 @@ +--- +title: "Opal Overalls: Sewing Instructions" +--- + +## Note +- A _double row of stitching_ means a row of *edgestitching* no more than 3mm in from the edge, followed by a row of *topstitching* about 6-10mm in from the first row. This should produce stitching that looks like the stitching found on jeans, or a flat felled seam. + +### Step 0: Customizing and fitting your pattern + +Select an appropriate leg length: +- 20-60% for shorts +- 90% for ankle-length legs +- 100% for legs that touch the floor. + +Decide on what hardware you want to use, if any. These instruction assume you're using traditional overalls hardware (tack buttons + buckles + sliders), but there are many ways of securing the straps to the front bib. + +Decide on what pockets to include, if any. The designs supports up to seven pockets in a classical carpenter style (a bib pocket, two front slash pockets, two back pockets, and two carpenter pockets on the right leg), along with a hammer loop. If not including front slash pockets, the front piece will have to have the triangular gap filled in where the pocket would go. + +Figure out what kind of fit you want and set your eases accordingly. + - Overalls are generally much roomier than pants. As such, they usually have quite a bit of ease. + - Keep in mind that the waist must slide over your hips. Either make sure the waist has enough ease to slide over the hips, or use a fabric with some two-way stretch (like the fabric used in skinny jeans). + - The straps must be long enough to add any extra length needed for the hardware. Traditional overalls hardware (tack buttons + buckles + sliders) generally need 20-30cm of extra length to accomodate the straps being adjustable. + +If you wish to do any embroidery, it's easiest to do it now, before starting to assemble the garment. + +### Step 1: Slash Pockets + +- Overcast or serge the slanted edge of the pocket shield to prevent it from fraying. +- With the slash pocket laying flat with *good sides up* place the pocket shield onto the slash pocket *wrong side* to *good side* in the upper corner, matching the slanted edge of the pocket shield to the line indicated on the slash pocket part. +- *Edgestitch* the slanted edge of the pocket shield to the slash pocket. +- Turn the pocket *right-side-out*. +- Secure the seam with a double row of stitching. +- *Baste* the remaining two sides; these will be secured when the pocket is sewn into the legs. +- Repeat for the other slash pocket making sure it is mirrored to one you've already made. + +### Step 2: Bib Pocket + +- Press a double fold hem into the top edge of the bib pocket, and secure with a double row of stitching. +- Press a single fold hem into the remaining sides of the bib pocket, and secure with clips or pins. Place the bib pocket carefully into place onto the front bib, *wrong side to good side*, and pin into place, removing the previous clips/pins as you do so. +- Secure with a double row of stitching. + +### Step 3a: Back Pockets (first part) + +- Press a double fold hem into the top edge of the back pocket, and secure with a double row of stitching. +- Press a single fold hem into the remaining sides of the back pocket, and secure with clips or pins. Place the back pocket carefully into place onto the rear piece, *wrong side to good side*, and pin into place, removing the previous clips/pins as you do so. + +### Step 3b: Carpenter Pockets +- Press a double fold hem into the slanted edge of the carpenter pocket, and secure with a double row of stitching. +- Press a single fold hem into the remaining sides of the carpenter pocket, and secure with clips or pins. +- Carefully remove pins as needed from the right back pocket to make room for the carpenter pocket to be slid under the back pocket. + Place the carpenter pocket carefully into place *on top of* the right(opposite of left) rear piece and *under* the back pocket, *wrong side to good side*, and pin into place, removing the previous clips/pins as you do so. +- Secure with a double row of stitching on the top, left, and bottom sides of the carpenter pocket, being careful to lift the back pocket out of the way as you sew to avoid sewing into it. +- Baste the rightmost edges of the carpenter pocket and rear pieces together. + +- Press a double fold hem into the slanted edge of the 2nd carpenter pocket, and secure with a double row of stitching. +- Press a single fold hem into the remaining sides of the 2nd carpenter pocket, and secure with clips or pins. +- Baste the rightmost edges of the 2nd carpenter pocket and rear pieces together. + +### Step 3c: Hammer Loop + +- Fold the hammer loop piece to the desired width and clip/pin. +- Carefully remove pins from the left back pockets to make room for the hammer loop to be slid under the back pocket. +- Slide the hammer loop *under* the left back pocket, and replace the pins, securing the hammer loop into place. +- Place the hammer loop along the left edge of the left rear piece, and baste into place. + +### Step 3d: Back Pockets (second part) +- Secure with a double row of stitching. +- Repeat for the second back pocket. + +### Step 4: Assembling the front +- Fold the waistband piece as indicated and clip/pin it. +- With *right sides together* join the front pieces together along the center seam with a flat felled or mock flat felled seam. +- Place the front piece and front bib together with *right sides together* and secure them together with a straight stitch to form the front assembly. Press the seam so that it lays towards to top the garment. +- Unfold the front assembly and lay it on the table *wrong side up*. +- Place the waistband over the waist seam, with the smooth side face up, and the side with the raw edge placed against the front assembly. Place the bottom edge of the waistband 3-5mm below the seam, and make sure that the waistband fully covers the seam. +- Trim any excess waistband length. +- Pin into place, removing existing clips/pins from the waistband in the process. +- Flip the front assembly *right side up*. +- Topstitch 3 or 4 horizontal rows of straight stitching to secure the waistband to the front assembly and reinforce the waist seam, making sure to enclose the waist seam fully within the topstitching. + +### Step 5: Assembling the back + +Note: The center seam runs from the bottom of the 'hexagon' to the crotch fork. Be careful not to stitch any part of the hexagon in this step. +- With *right sides together* , join the front and back assemblies along the center seam with a flat felled or mock flat felled seam. + +### Step 6: Joining the front and back assemblies +- With *right sides together*, join the front and back assemblies along each outseam with a flat felled or mock flat felled seam. +- With *right sides still together*, close the inseam with a flat felled or mock flat felled seam. + +### Step 7: Forming the hexagon and hemming the bibs +- Lay the back bib flat with *right sides up*, so that the two back bibs overlap to form the hexagon. The left back/right strap crosses over the right back/left strap. +- Fold the hem allowances of the hexagon inwards into a single-fold topstitched hem/seam, and pin into place (clips won't work here). +- Fold the remaining hem allowances of the straps and bibs into a double-fold hem, and clip or pin. +- Secure the hexagon and the hems with a double row of stitching. You should be able to be do this in two parts, starting and finishing on the sides of the hexagon for each one. + +### Step 8: Reinforcing the front bib and installing hardware + +- Fold the bib placket piece as indicated, and clip or pin. +- Trim any excess length away. +- (optional) Serge or overlock the sides of the bib placket to prevent fraying. +- Clip or pin the bib placket into place. It should be slightly inset from the edges of the front bib, and the side with the raw edge should be placed against the *wrong side* of the bib. +- Topstitch 3 or 4 horizontal rows of straight stitching from the *right side* of the garment to secure the placket into place. + +### Step 9: Hemming the legs + +- Fold the hem allowances of the legs into double-fold hems, and clip or pin. +- Secure the hems with a single row of stitching. + +### Step 10: Finishing +- Put on a comfortable shirt or one-piece garment for underneath, or just go shirtless. +- Put on your finished overalls. +- You're all done. Enjoy. diff --git a/markdown/org/docs/designs/opal/measurements/en.md b/markdown/org/docs/designs/opal/measurements/en.md new file mode 100644 index 00000000000..fe40a0414f3 --- /dev/null +++ b/markdown/org/docs/designs/opal/measurements/en.md @@ -0,0 +1,5 @@ +--- +title: "Opal Overalls: Required Measurements" +--- + + diff --git a/markdown/org/docs/designs/opal/needs/en.md b/markdown/org/docs/designs/opal/needs/en.md new file mode 100644 index 00000000000..eb02163da29 --- /dev/null +++ b/markdown/org/docs/designs/opal/needs/en.md @@ -0,0 +1,16 @@ +--- +title: "Opal Overalls: What You Need" +--- + +To make Opal, you will need the following: + +- Basic sewing supplies +- Between 1 - 3 meters (1.1 - 3.3 yards) of a suitable fabric, depending on size and style ([see Fabric options](/docs/patterns/opal/fabric)). +- (optional) Fasteners to attach the straps to the front bib. I make my overalls using tack buttons on the bib, and a buckle and slider on each strap. + + + + - Long legs and a looser fit will increase fabric requirements. Pockets usually can be fit on the otherwise wasted portion of the fabric, and don't change the fabric length requirement. + - A pair of shortalls for a typical adult will need about 2 meters of fabric. + + diff --git a/markdown/org/docs/designs/opal/options/en.md b/markdown/org/docs/designs/opal/options/en.md new file mode 100644 index 00000000000..6903b2dd2b7 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/en.md @@ -0,0 +1,5 @@ +--- +title: "Opal Overalls: Design Options" +--- + + diff --git a/markdown/org/docs/designs/opal/options/es.md b/markdown/org/docs/designs/opal/options/es.md new file mode 100644 index 00000000000..73d4e7ec917 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/es.md @@ -0,0 +1,5 @@ +--- +title: "Onyx de una pieza: Opciones de diseño" +--- + + diff --git a/markdown/org/docs/designs/opal/options/fr.md b/markdown/org/docs/designs/opal/options/fr.md new file mode 100644 index 00000000000..7f7063728c8 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/fr.md @@ -0,0 +1,5 @@ +--- +title: "Onyx en une seule pièce : Options de conception" +--- + + diff --git a/markdown/org/docs/designs/opal/options/hammerloop/en.md b/markdown/org/docs/designs/opal/options/hammerloop/en.md new file mode 100644 index 00000000000..45cb895152f --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloop/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop" +--- + +Toggles whether to include a hammer loop under the left back pocket. diff --git a/markdown/org/docs/designs/opal/options/hammerloopcornerx/en.md b/markdown/org/docs/designs/opal/options/hammerloopcornerx/en.md new file mode 100644 index 00000000000..d17f6f4c09f --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloopcornerx/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop corner horizontal position" +--- + +Controls how the hammer loop curves. Used for calculating its length. diff --git a/markdown/org/docs/designs/opal/options/hammerloopcornery/en.md b/markdown/org/docs/designs/opal/options/hammerloopcornery/en.md new file mode 100644 index 00000000000..1f160cd8488 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloopcornery/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop corner vertical position" +--- + +Controls how the hammer loop curves. Used for calculating its length. diff --git a/markdown/org/docs/designs/opal/options/hammerloopcurve/en.md b/markdown/org/docs/designs/opal/options/hammerloopcurve/en.md new file mode 100644 index 00000000000..52f666b9098 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloopcurve/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop curve" +--- + +Controls how the hammer loop curves. Used for calculating its length. diff --git a/markdown/org/docs/designs/opal/options/hammerloopfirstfold/en.md b/markdown/org/docs/designs/opal/options/hammerloopfirstfold/en.md new file mode 100644 index 00000000000..ddc9983d598 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloopfirstfold/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop first fold" +--- + +Controls how wide the first fold of the hammer loop is. This is used for calculating how wide the fabric needs to be cut for the hammer loop. diff --git a/markdown/org/docs/designs/opal/options/hammerloopoutseam/en.md b/markdown/org/docs/designs/opal/options/hammerloopoutseam/en.md new file mode 100644 index 00000000000..203e534d0dd --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloopoutseam/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop outseam" +--- + +Controls how far down the outseam the hammer loop is inserted. Used for calculating its length. diff --git a/markdown/org/docs/designs/opal/options/hammerloopsecondfold/en.md b/markdown/org/docs/designs/opal/options/hammerloopsecondfold/en.md new file mode 100644 index 00000000000..6b69d00c997 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloopsecondfold/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop second fold" +--- + +Controls how wide the second fold of the hammer loop is. This is used for calculating how wide the fabric needs to be cut for the hammer loop. diff --git a/markdown/org/docs/designs/opal/options/hammerloopwidth/en.md b/markdown/org/docs/designs/opal/options/hammerloopwidth/en.md new file mode 100644 index 00000000000..196b7c2612a --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hammerloopwidth/en.md @@ -0,0 +1,5 @@ +--- +title: "Hammer loop width" +--- + +How wide to make the hammer loop. diff --git a/markdown/org/docs/designs/opal/options/hemallowance/en.md b/markdown/org/docs/designs/opal/options/hemallowance/en.md new file mode 100644 index 00000000000..5311296560a --- /dev/null +++ b/markdown/org/docs/designs/opal/options/hemallowance/en.md @@ -0,0 +1,7 @@ +--- +title: "Hem allowance" +--- + +Sets how wide the hems are around the front bib, back bib, and straps are. A larger hem will make the bibs and straps a little stiffer and stronger, but large values can make the curves harder to sew. + +Note: This option does not change the hem around the legs. Use the Leg hem allowance options for that. diff --git a/markdown/org/docs/designs/opal/options/legbalance/en.md b/markdown/org/docs/designs/opal/options/legbalance/en.md new file mode 100644 index 00000000000..31e14c8e99e --- /dev/null +++ b/markdown/org/docs/designs/opal/options/legbalance/en.md @@ -0,0 +1,5 @@ +--- +title: "Leg balance" +--- + +Positive values move more of the fabric to the back piece, negative values to the front piece. diff --git a/markdown/org/docs/designs/opal/options/leghemallowance/en.md b/markdown/org/docs/designs/opal/options/leghemallowance/en.md new file mode 100644 index 00000000000..d7d6e1ecf00 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/leghemallowance/en.md @@ -0,0 +1,5 @@ +--- +title: "Leg hem allowance" +--- + +Sets how wide the hems are around the legs. If you want to cuff the legs as well as hem them, add additional allowance here for the cuffs. diff --git a/markdown/org/docs/designs/opal/options/leghemease/en.md b/markdown/org/docs/designs/opal/options/leghemease/en.md new file mode 100644 index 00000000000..005ba2ed6dc --- /dev/null +++ b/markdown/org/docs/designs/opal/options/leghemease/en.md @@ -0,0 +1,7 @@ +--- +title: "Leg hem ease" +--- + +Controls how much ease there is at the bottom of the legs. + +Note: This option does _not_ affect the width of any hem. It only affects the length around the circumference of the leg, with the greatest effect felt at the hem, and tapering off towards the thighs. diff --git a/markdown/org/docs/designs/opal/options/leglength/en.md b/markdown/org/docs/designs/opal/options/leglength/en.md new file mode 100644 index 00000000000..17a88a315f9 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/leglength/en.md @@ -0,0 +1,9 @@ +--- +title: "Leg length" +--- + +Controls how long the legs of the garment will be. A value of 100% should produce legs that reach the floor. Much smaller values (20%-60%) are used to draft a pattern for shortalls. + +Note: The exact length needed will probably need tweaking, based on how the garment is intended to be worn. I recommend that you take a measuring tape, place one end where you want the top of the outseam to rest, measure from there to where you want the bottom of the legs to reach, and adjust this option so that the outseam of the drafted pattern is the right length. + +Note: Too long is better than too short. Excess leg length can be hemmed, cuffed, or cut away, but it's hard to add more length to overalls that are too short. \ No newline at end of file diff --git a/markdown/org/docs/designs/opal/options/nl.md b/markdown/org/docs/designs/opal/options/nl.md new file mode 100644 index 00000000000..d48d3ff4a1b --- /dev/null +++ b/markdown/org/docs/designs/opal/options/nl.md @@ -0,0 +1,5 @@ +--- +title: "Onyx eendelig: Ontwerpopties" +--- + + diff --git a/markdown/org/docs/designs/opal/options/outseamheight/en.md b/markdown/org/docs/designs/opal/options/outseamheight/en.md new file mode 100644 index 00000000000..cdbd97da304 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/outseamheight/en.md @@ -0,0 +1,7 @@ +--- +title: "Outseam height" +--- + +Controls how far up past the waist the outseam extends, and thus how far up the front and back bibs separate. + +Note: This option has a major effect on the overall style of your design. Larger values will give overalls with more side coverage and are more common in mens' or kids' overalls, while smaller values will expose more of the sides and are more common in feminine overalls. Larger values should produce a stronger (more tear-resistant) garment. diff --git a/markdown/org/docs/designs/opal/options/pocketback/en.md b/markdown/org/docs/designs/opal/options/pocketback/en.md new file mode 100644 index 00000000000..152870109d9 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketback/en.md @@ -0,0 +1,13 @@ +--- +title: "Back pocket" +--- + +Toggles whether to include back pockets in the pattern. + +Note: Setting this option to 'true' will enable the following options: +- Back pocket horizontal position +- Back pocket vertical position +- Back pocket width +- Back pocket height +- Back pocket corner width +- Back pocket corner height diff --git a/markdown/org/docs/designs/opal/options/pocketbackcornerheight/en.md b/markdown/org/docs/designs/opal/options/pocketbackcornerheight/en.md new file mode 100644 index 00000000000..4d6f54e4f8d --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbackcornerheight/en.md @@ -0,0 +1,5 @@ +--- +title: "Back pocket corner height" +--- + +Controls how tall the bottom-left and bottom-right corners of the back pocket are. diff --git a/markdown/org/docs/designs/opal/options/pocketbackcornerwidth/en.md b/markdown/org/docs/designs/opal/options/pocketbackcornerwidth/en.md new file mode 100644 index 00000000000..c12f2365469 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbackcornerwidth/en.md @@ -0,0 +1,5 @@ +--- +title: "Back pocket corner width" +--- + +Controls how wide the bottom-left and bottom-right corners of the back pocket are. diff --git a/markdown/org/docs/designs/opal/options/pocketbackheight/en.md b/markdown/org/docs/designs/opal/options/pocketbackheight/en.md new file mode 100644 index 00000000000..948019c1be5 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbackheight/en.md @@ -0,0 +1,5 @@ +--- +title: "Back pocket height" +--- + +Controls how tall the back pockets are. diff --git a/markdown/org/docs/designs/opal/options/pocketbackpositionx/en.md b/markdown/org/docs/designs/opal/options/pocketbackpositionx/en.md new file mode 100644 index 00000000000..1ba2890f3ae --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbackpositionx/en.md @@ -0,0 +1,5 @@ +--- +title: "Back pocket horizontal position" +--- + +Controls where the back pockets are horizontally. diff --git a/markdown/org/docs/designs/opal/options/pocketbackpositiony/en.md b/markdown/org/docs/designs/opal/options/pocketbackpositiony/en.md new file mode 100644 index 00000000000..fef70246df3 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbackpositiony/en.md @@ -0,0 +1,5 @@ +--- +title: "Back pocket vertical position" +--- + +Controls where the back pockets are vertically. diff --git a/markdown/org/docs/designs/opal/options/pocketbackwidth/en.md b/markdown/org/docs/designs/opal/options/pocketbackwidth/en.md new file mode 100644 index 00000000000..1c09f3940cd --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbackwidth/en.md @@ -0,0 +1,5 @@ +--- +title: "Back pocket width" +--- + +Controls how wide the back pockets are. diff --git a/markdown/org/docs/designs/opal/options/pocketbib/en.md b/markdown/org/docs/designs/opal/options/pocketbib/en.md new file mode 100644 index 00000000000..7b1bdf4fa30 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbib/en.md @@ -0,0 +1,15 @@ +--- +title: "Bib pocket" +--- + +Toggles whether to include a bib pocket in the pattern. + +Note: Setting this option to 'true' will enable the following options: +- Bib pocket on fold +- Bib pocket vertical position +- Bib pocket style +- Bib pocket width +- Bib pocket height +- Bib pocket feature width +- Bib pocket feature height +- Bib pocket curve diff --git a/markdown/org/docs/designs/opal/options/pocketbibfeaturecurve/en.md b/markdown/org/docs/designs/opal/options/pocketbibfeaturecurve/en.md new file mode 100644 index 00000000000..4e0786c0c12 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibfeaturecurve/en.md @@ -0,0 +1,9 @@ +--- +title: "Bib pocket feature curve" +--- + +The exact effect of this option varies based on the selected bib pocket style: +- Pentagon: This option has no effect. +- Hexagon: This option has no effect. +- Curved bottom: This option controls how strongly curved the curved sections on the bottom of the pocket extends. +- Rectangle: This option has no effect. diff --git a/markdown/org/docs/designs/opal/options/pocketbibfeatureheight/en.md b/markdown/org/docs/designs/opal/options/pocketbibfeatureheight/en.md new file mode 100644 index 00000000000..517585e82ef --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibfeatureheight/en.md @@ -0,0 +1,9 @@ +--- +title: "Bib pocket feature height" +--- + +The exact effect of this option varies based on the selected bib pocket style: +- Pentagon: This option controls how far up the bottom-right and bottom-left corners are. +- Hexagon: This option controls how high the diagonal (bottom-right and bottom-left) edges of the pocket are. +- Curved bottom: This option controls how high the curved sections on the bottom of the pocket extend. +- Rectangle: This option has no effect. diff --git a/markdown/org/docs/designs/opal/options/pocketbibfeaturewidth/en.md b/markdown/org/docs/designs/opal/options/pocketbibfeaturewidth/en.md new file mode 100644 index 00000000000..c5742cc1ea1 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibfeaturewidth/en.md @@ -0,0 +1,9 @@ +--- +title: "Bib pocket feature width" +--- + +The exact effect of this option varies based on the selected bib pocket style: +- Pentagon: This option controls how wide the bib pocket is at the bottom-right and bottom-left corners. +- Hexagon: This option controls how wide bottom edge of the pocket is. +- Curved bottom: This option controls how wide the flat section on the bottom edge of the pocket is. +- Rectangle: This option has no effect. diff --git a/markdown/org/docs/designs/opal/options/pocketbibheight/en.md b/markdown/org/docs/designs/opal/options/pocketbibheight/en.md new file mode 100644 index 00000000000..c74e2a248df --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibheight/en.md @@ -0,0 +1,5 @@ +--- +title: "Bib pocket height" +--- + +Controls how tall the bib pocket is. diff --git a/markdown/org/docs/designs/opal/options/pocketbibonfold/en.md b/markdown/org/docs/designs/opal/options/pocketbibonfold/en.md new file mode 100644 index 00000000000..a9ffbf32ce1 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibonfold/en.md @@ -0,0 +1,7 @@ +--- +title: "Bib pocket on fold" +--- + +Toggles whether to draft the bib pocket pattern on-the-fold, or as a full pattern piece. + +Note: Printing on-the-fold can save a small amount of paper, but I recommend to print the full pattern piece to avoid confusion, since the other pieces are all full pieces. diff --git a/markdown/org/docs/designs/opal/options/pocketbibstyle/en.md b/markdown/org/docs/designs/opal/options/pocketbibstyle/en.md new file mode 100644 index 00000000000..819de492882 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibstyle/en.md @@ -0,0 +1,9 @@ +--- +title: "Bib pocket style" +--- + +Choose among the available types/styles for the bib pocket: +- Pentagon: The bib pocket is in the shape of a pentagon. The feature options control the bottom-right and bottom-left points of the pentagon. This is the designer's preferred style, as it follows the trapezoidal shape of the front bib. +- Hexagon: The bib pocket is in the shape of a hexagon, similar to the style of the back pockets. +- Curved bottom: This is like 'hexagon,' but the two diagonal edges are curves instead of straight lines. +- Rectangle: The bib pocket is in the shape of a rectangle. diff --git a/markdown/org/docs/designs/opal/options/pocketbibverticalposition/en.md b/markdown/org/docs/designs/opal/options/pocketbibverticalposition/en.md new file mode 100644 index 00000000000..ef59ee03ac7 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibverticalposition/en.md @@ -0,0 +1,5 @@ +--- +title: "Bib pocket vertical position" +--- + +Controls where the bib pocket is located on the bib vertically. diff --git a/markdown/org/docs/designs/opal/options/pocketbibwidth/en.md b/markdown/org/docs/designs/opal/options/pocketbibwidth/en.md new file mode 100644 index 00000000000..a6e714866de --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketbibwidth/en.md @@ -0,0 +1,5 @@ +--- +title: "Bib pocket width" +--- + +Controls how wide the top of the bib pocket is. For the rectangular bib pocket style, this also controls how wide the bottom of the bib pocket is. diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenter/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenter/en.md new file mode 100644 index 00000000000..661912bddeb --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenter/en.md @@ -0,0 +1,14 @@ +--- +title: "Carpenter pocket" +--- + +Toggles whether to include a carpenter pocket under the right back pocket. + +Note: Setting this option to 'true' will enable the following options: +- Carpenter pocket height +- Carpenter pocket anchor horizontal position +- Carpenter pocket anchor vertical position +- Carpenter pocket anchor width +- Carpenter pocket opening height +- Carpenter pocket extra +- Carpenter pocket extra height (If carpenter pocket extra is also true) diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenteranchorwidth/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenteranchorwidth/en.md new file mode 100644 index 00000000000..e1fce497baf --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenteranchorwidth/en.md @@ -0,0 +1,7 @@ +--- +title: "Carpenter pocket anchor width" +--- + +Controls how wide the section of the carpenter pocket anchored under the back pocket is. + +Note: This option also controls how slanted the opening of the carpenter pocket is. diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenteranchorx/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenteranchorx/en.md new file mode 100644 index 00000000000..fe04fb9aadd --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenteranchorx/en.md @@ -0,0 +1,5 @@ +--- +title: "Carpenter pocket height" +--- + +Controls how tall the carpenter pocket is. diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenteranchory/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenteranchory/en.md new file mode 100644 index 00000000000..7a768f77787 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenteranchory/en.md @@ -0,0 +1,5 @@ +--- +title: "Carpenter pocket anchor vertical position" +--- + +Controls where the carpenter pocket is anchored under the back pocket vertically. diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenterextra/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenterextra/en.md new file mode 100644 index 00000000000..6ef8b904bdb --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenterextra/en.md @@ -0,0 +1,8 @@ +--- +title: "Carpenter pocket extra" +--- + +Toggles whether to include a second pocket over the bottom portion of the carpenter pocket. + +Note: Setting this option to 'true' will enable the following option: +- Carpenter pocket extra height diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenterextraheight/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenterextraheight/en.md new file mode 100644 index 00000000000..d4bda3fdda2 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenterextraheight/en.md @@ -0,0 +1,5 @@ +--- +title: "Carpenter pocket extra height" +--- + +Controls how tall to make the second carpenter pocket. diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenterheight/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenterheight/en.md new file mode 100644 index 00000000000..fe04fb9aadd --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenterheight/en.md @@ -0,0 +1,5 @@ +--- +title: "Carpenter pocket height" +--- + +Controls how tall the carpenter pocket is. diff --git a/markdown/org/docs/designs/opal/options/pocketcarpenteropeningheight/en.md b/markdown/org/docs/designs/opal/options/pocketcarpenteropeningheight/en.md new file mode 100644 index 00000000000..17c6da25e12 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketcarpenteropeningheight/en.md @@ -0,0 +1,7 @@ +--- +title: "Carpenter pocket opening height" +--- + +Controls how tall the opening to the carpenter pocket is. + +Note: The width of the opening to the carpenter pocket is adjusted using the carpenter pocket anchor width option. diff --git a/markdown/org/docs/designs/opal/options/pocketslash/en.md b/markdown/org/docs/designs/opal/options/pocketslash/en.md new file mode 100644 index 00000000000..e17603d11d3 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketslash/en.md @@ -0,0 +1,13 @@ +--- +title: "Slash pocket" +--- + +Toggles whether or not to include slash (front) pockets in the pattern. + +Note: Setting this option to 'true' will enable the following options: +- Slash pocket opening width +- Slash pocket opening height +- Slash pocket curve +- Slash pocket width +- Slash pocket height +- Slash pocket shield overlap diff --git a/markdown/org/docs/designs/opal/options/pocketslashheight/en.md b/markdown/org/docs/designs/opal/options/pocketslashheight/en.md new file mode 100644 index 00000000000..c2f1dad3b45 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketslashheight/en.md @@ -0,0 +1,5 @@ +--- +title: "Slash pocket height" +--- + +Controls how deep the slash pocket bags are. diff --git a/markdown/org/docs/designs/opal/options/pocketslashopeningcurve/en.md b/markdown/org/docs/designs/opal/options/pocketslashopeningcurve/en.md new file mode 100644 index 00000000000..265fddb4ec9 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketslashopeningcurve/en.md @@ -0,0 +1,5 @@ +--- +title: "Slash pocket opening curve" +--- + +Controls the shape of the openings the slash pockets. 0 is a straight opening, while larger values are more deeply curved. diff --git a/markdown/org/docs/designs/opal/options/pocketslashopeningheight/en.md b/markdown/org/docs/designs/opal/options/pocketslashopeningheight/en.md new file mode 100644 index 00000000000..39b424c599c --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketslashopeningheight/en.md @@ -0,0 +1,5 @@ +--- +title: "Slash pocket opening height" +--- + +Controls how tall the openings of the slash pockets are. diff --git a/markdown/org/docs/designs/opal/options/pocketslashopeningwidth/en.md b/markdown/org/docs/designs/opal/options/pocketslashopeningwidth/en.md new file mode 100644 index 00000000000..e90cdfa3751 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketslashopeningwidth/en.md @@ -0,0 +1,5 @@ +--- +title: "Slash pocket opening width" +--- + +Controls how wide the openings of the slash pockets are. diff --git a/markdown/org/docs/designs/opal/options/pocketslashshieldoverlap/en.md b/markdown/org/docs/designs/opal/options/pocketslashshieldoverlap/en.md new file mode 100644 index 00000000000..5c424d8dd64 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketslashshieldoverlap/en.md @@ -0,0 +1,5 @@ +--- +title: "Slash pocket shield overlap" +--- + +Controls how far the pocket shield extends past the opening of the slash pockets. Larger values will make it less likely for the pocket lining to be visible from the outside, but will add more bulk to the pockets. diff --git a/markdown/org/docs/designs/opal/options/pocketslashwidth/en.md b/markdown/org/docs/designs/opal/options/pocketslashwidth/en.md new file mode 100644 index 00000000000..192703459cd --- /dev/null +++ b/markdown/org/docs/designs/opal/options/pocketslashwidth/en.md @@ -0,0 +1,5 @@ +--- +title: "Slash pocket width" +--- + +Controls how wide the slash pocket bags are. diff --git a/markdown/org/docs/designs/opal/options/seatbalance/en.md b/markdown/org/docs/designs/opal/options/seatbalance/en.md new file mode 100644 index 00000000000..1666eb2d69e --- /dev/null +++ b/markdown/org/docs/designs/opal/options/seatbalance/en.md @@ -0,0 +1,9 @@ +--- +title: "Seat balance" +--- + +Controls the position of the side seam at the seat. Positive values will cause the front piece to be wider, while negative values will cause the back piece to be wider. + +Note: The side seam in this design is always straight. Instead, all adjustments are made by moving the center seam. + +Note: For most people, this option will be set less positive/more negative than the waist balance. diff --git a/markdown/org/docs/designs/opal/options/seatease/en.md b/markdown/org/docs/designs/opal/options/seatease/en.md new file mode 100644 index 00000000000..a460704866c --- /dev/null +++ b/markdown/org/docs/designs/opal/options/seatease/en.md @@ -0,0 +1,7 @@ +--- +title: "Seat ease" +--- + +Controls how wide the garment will be at seat height. + +Note: This option controls the circumference/overall ease of the garment at this height. If you want to move fabric to<->from the seat or the crotch, you should adjust the seat balance option instead. diff --git a/markdown/org/docs/designs/opal/options/straplength/en.md b/markdown/org/docs/designs/opal/options/straplength/en.md new file mode 100644 index 00000000000..307cbc4ca3c --- /dev/null +++ b/markdown/org/docs/designs/opal/options/straplength/en.md @@ -0,0 +1,7 @@ +--- +title: "Strap length" +--- + +Controls how long the straps are. This option should generally be substantially larger than 100%, to allow the strap to be passed through the hardware. 160% is generally a good value to allow for a wide range of adjustments using the hardware. + +Note: If not using hardware and permanently sewing the straps to the front bib, or if using non-adjustable buttons, a value of slightly over 100% should be used. diff --git a/markdown/org/docs/designs/opal/options/strapposition/en.md b/markdown/org/docs/designs/opal/options/strapposition/en.md new file mode 100644 index 00000000000..1fc7c044b58 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/strapposition/en.md @@ -0,0 +1,7 @@ +--- +title: "Strap position" +--- + +Controls where the straps are positioned with respect to the hexagon. This option can only go negative, and smaller (more negative) values set the straps a little farther away from the centerline, which can affect how they fit around the shoulders. + +Note: If you don't have a good reason to change this, it is recommended to leave it at the default (0%). diff --git a/markdown/org/docs/designs/opal/options/straptapercurve/en.md b/markdown/org/docs/designs/opal/options/straptapercurve/en.md new file mode 100644 index 00000000000..8beb5a2771e --- /dev/null +++ b/markdown/org/docs/designs/opal/options/straptapercurve/en.md @@ -0,0 +1,5 @@ +--- +title: "Strap taper curve" +--- + +Controls how strongly curved the taper of the straps is. diff --git a/markdown/org/docs/designs/opal/options/straptaperposition/en.md b/markdown/org/docs/designs/opal/options/straptaperposition/en.md new file mode 100644 index 00000000000..c6ddef457bd --- /dev/null +++ b/markdown/org/docs/designs/opal/options/straptaperposition/en.md @@ -0,0 +1,5 @@ +--- +title: "Strap taper position" +--- + +Controls how long the tapered portion of the straps is. Setting this value too low can make for unnatural-looking straps, but the larger this value is set, the smaller the range over which the straps can be adjusted, since the slider can't fit over the tapered portion of the straps. It is recommended to set this to as small a value as will still produce nice-looking straps. diff --git a/markdown/org/docs/designs/opal/options/strapwidth/en.md b/markdown/org/docs/designs/opal/options/strapwidth/en.md new file mode 100644 index 00000000000..349230d785c --- /dev/null +++ b/markdown/org/docs/designs/opal/options/strapwidth/en.md @@ -0,0 +1,7 @@ +--- +title: "Strap length" +--- + +Controls how wide the straps are. + +Note: It is recommended to select your hardware first, and make sure that the strap width that you choose is compatible with your sliders and buckles. diff --git a/markdown/org/docs/designs/opal/options/thighshape/en.md b/markdown/org/docs/designs/opal/options/thighshape/en.md new file mode 100644 index 00000000000..8d7bd2f507c --- /dev/null +++ b/markdown/org/docs/designs/opal/options/thighshape/en.md @@ -0,0 +1,7 @@ +--- +title: "Thigh shape" +--- + +Controls how elongated the thighs of the garment are. Higher values are used for deeper but narrower thighs. + +This controls the transition between the trunk (one big tube) and the legs (two smaller tubes). The two legs will always require more fabric than the trunk, but the shape of the thighs affects how much more fabric is needed. This option is used to account for this. diff --git a/markdown/org/docs/designs/opal/options/uk.md b/markdown/org/docs/designs/opal/options/uk.md new file mode 100644 index 00000000000..5ce986a4cb3 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/uk.md @@ -0,0 +1,5 @@ +--- +title: "Онікс Цілісний: Варіанти дизайну" +--- + + diff --git a/markdown/org/docs/designs/opal/options/waistbalance/en.md b/markdown/org/docs/designs/opal/options/waistbalance/en.md new file mode 100644 index 00000000000..d1554bd84a9 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/waistbalance/en.md @@ -0,0 +1,9 @@ +--- +title: "Waist balance" +--- + +Controls the position of the side seam at the waist. Positive values will cause the front piece to be wider, while negative values will cause the back piece to be wider. + +Note: The side seam in this design is always straight. Instead, all adjustments are made by moving the center seam. + +Note: For most people, this option will be set more positive/less negative than the seat balance. diff --git a/markdown/org/docs/designs/opal/options/waistbandlayers/en.md b/markdown/org/docs/designs/opal/options/waistbandlayers/en.md new file mode 100644 index 00000000000..add6a480be8 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/waistbandlayers/en.md @@ -0,0 +1,5 @@ +--- +title: "Waistband layers" +--- + +Sets how many layers the front waistband is folded into. diff --git a/markdown/org/docs/designs/opal/options/waistbandwidth/en.md b/markdown/org/docs/designs/opal/options/waistbandwidth/en.md new file mode 100644 index 00000000000..832b52f81df --- /dev/null +++ b/markdown/org/docs/designs/opal/options/waistbandwidth/en.md @@ -0,0 +1,5 @@ +--- +title: "Waistband width" +--- + +Controls how wide the front (and only) waistband is. Make sure that the waistband is at least a little larger than the seam allowance. Seam allowance + 6mm should be the minimum. diff --git a/markdown/org/docs/designs/opal/options/waistease/en.md b/markdown/org/docs/designs/opal/options/waistease/en.md new file mode 100644 index 00000000000..f603b21f540 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/waistease/en.md @@ -0,0 +1,7 @@ +--- +title: "Waist ease" +--- + +Controls how wide the garment will be around the waist. + +Note: This overalls design does not feature any side closure. As such, there must be enough ease in the waist for the garment to slide over the widest part of the hips. As such, waist ease should usually be set to fairly large positive value. If the waist ease is too narrow, you may make a garment that cannot be put on or taken off. diff --git a/markdown/org/docs/designs/opal/options/waistposition/en.md b/markdown/org/docs/designs/opal/options/waistposition/en.md new file mode 100644 index 00000000000..73309bd4127 --- /dev/null +++ b/markdown/org/docs/designs/opal/options/waistposition/en.md @@ -0,0 +1,5 @@ +--- +title: "Waist position" +--- + +Controls where the waistband is on the front of the overalls. 0 is at the natural waist and -100 is at the seat. Positive values will place the waistband above the natural waist. Values near 0 are recommended for traditional overalls.