diff --git a/.github/workflows/tests.charlie.yml b/.github/workflows/tests.charlie.yml index 7ab9496c1c3..877ebb46f6d 100644 --- a/.github/workflows/tests.charlie.yml +++ b/.github/workflows/tests.charlie.yml @@ -23,7 +23,7 @@ jobs: env: CI: true - name: Install peer & test dependencies - run: "cd packages/charlie && npm install @freesewing/core@^2.12.1 @freesewing/plugin-bundle@^2.12.1 @freesewing/models@2.12.1 @freesewing/pattern-info@2.12.1 mocha chai" + run: "cd packages/charlie && npm install @freesewing/core@^2.14.0 @freesewing/plugin-bundle@^2.14.0 @freesewing/models@2.14.0 @freesewing/pattern-info@2.14.0 mocha chai" env: CI: true - name: Build pattern diff --git a/packages/charlie/CHANGELOG.md b/packages/charlie/CHANGELOG.md index 4c276f600af..b0669d9ac51 100644 --- a/packages/charlie/CHANGELOG.md +++ b/packages/charlie/CHANGELOG.md @@ -1,6 +1,12 @@ # Change log for: @freesewing/charlie +## 2.15.0 (NaN-NaN-NaN) + +### Added + + - Inital release of the Charlie Chinos pattern + This is the **initial release**, and the start of this change log. diff --git a/packages/charlie/README.md b/packages/charlie/README.md index 106618d22ed..3a15cf6b71d 100644 --- a/packages/charlie/README.md +++ b/packages/charlie/README.md @@ -1,4 +1,4 @@ -![FreeSewing](https://freesewing.org/banner.jpg) +![FreeSewing](https://static.freesewing.org/banner.png)

Open issues tagged pkg:charlie + Project board

-## What am I looking at? 🤔 - -This repository is our *monorepo* holding [all our NPM packages](https://www.npmjs.com/search?q=keywords:freesewing). -This folder holds **@freesewing/charlie** +# @freesewing/charlie A FreeSewing pattern for chino trousers +## What am I looking at? 🤔 + +This repository is our *monorepo* +holding [all our NPM packages](https://freesewing.dev/reference/packages/). + +This folder holds: @freesewing/charlie + ## 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 +our sewing patterns adapted to your measurements. + +If you're a developer, our documentation is on [freesewing.dev](https://freesewing.dev/). Our [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox -for parametric design of sewing patterns. It's a modular system (check our list -of [plugins](https://freesewing.dev/reference/plugins/) and getting started is as simple as: +for parametric design of sewing patterns. But we also provide 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 -npm init freesewing-pattern +npx create-freesewing-pattern ``` -The [getting started](https://freesewing.dev/guides/getting-started/) section on [freesewing.dev](https://freesewing.dev/) is a good -entrypoint to our documentation, but you'll find a lot more there, including -our [API reference](https://freesewing.dev/reference/api/), -as well as [our turorial](https://freesewing.dev/tutorials/pattern-design/), -and [howtos](https://freesewing.dev/howtos/). +Or, consult our getting started guides +for [Linux](https://freesewing.dev/tutorials/getting-started-linux/), +[MacOS](https://freesewing.dev/tutorials/getting-started-mac/), +or [Windows](https://freesewing.dev/tutorials/getting-started-windows/). -If you're a maker, checkout [freesewing.org](https://freesewing/) where you can generate -our sewing patterns adapted to your measurements. +We also have a [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) that +walks you through your first parametric design, +and [a friendly community](https://freesewing.org/community/where/) with +people who can help you when you get stuck. ## Support FreeSewing: Become a patron 🥰 FreeSewing is an open source project run by a community, and financially supported by our patrons. -If you feel what we do is worthwhile, you too -should [become a patron](https://freesewing.org/patrons/join). +If you feel what we do 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 👩‍💻 - 💻 Makers website: [freesewing.org](https://freesewing.org) - 💻 Developers website: [freesewing.dev](https://freesewing.dev) - 💬 Chat: On Discord via [chat.freesewing.org](https://chat.freesewing.org/) + - ✅ Todo list/Kanban board: On Github via [todo.freesewing.org](https://todo.freesewing.org/) - 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org) - 📷 Instagram: [@freesewing_org](https://instagram.com/freesewing_org) diff --git a/packages/charlie/config/index.js b/packages/charlie/config/index.js index 453d9029bd8..9f553ceb461 100644 --- a/packages/charlie/config/index.js +++ b/packages/charlie/config/index.js @@ -11,7 +11,7 @@ export default { tags: ['bottom', 'basics'], optionGroups: { fit: ['seatEase', 'kneeEase', 'waistEase'], - style: ['waistHeight', 'lengthBonus', 'crotchDrop'], + style: ['waistHeight', 'waistbandWidth', 'lengthBonus', 'crotchDrop'], pockets: [ { backPockets: [ @@ -43,6 +43,7 @@ export default { 'grainlinePosition', 'legBalance', 'waistBalance', + 'beltLoops', { fly: ['flyCurve', 'flyLength', 'flyWidth'] } @@ -69,17 +70,17 @@ export default { frontPocket: 'front', frontPocketFacing: 'frontPocket', backPocketFacing: 'backPocket', + backPocketInterfacing: 'backPocket', backPocketJet: 'backPocketFacing', flyFacing: 'front', - flyExtention: 'flyFacing' + flyExtension: 'flyFacing' }, - parts: ['beltLoop'], + parts: ['beltLoops'], dependencies: { // The inheritance makes this a bit messy + titanFront: 'titanBack', back: ['titanBack', 'titanFront', 'front'], - waistband: ['titanBack', 'titanFront', 'front', 'back'], - waistbandButtonSide: 'waistband', - waistbandButtonholeSide: 'waistband' + waistband: ['titanBack', 'titanFront', 'front', 'back'] }, options: { // Constants (from Titan) @@ -87,12 +88,11 @@ export default { fitCrossSeam: true, fitCrossSeamFront: true, fitCrossSeamBack: true, - // Lock titan options fitKnee: true, // Charlie constants - waistbandReduction: 0.3, // See src/index.js + waistbandReduction: 0.25, // See src/index.js waistbandFactor: 0.1, // Fit (from Titan) @@ -101,7 +101,8 @@ export default { kneeEase: { pct: 15, min: 10, max: 30 }, // Style (from Titan) - waistHeight: { pct: 15, min: 0, max: 30 }, + waistHeight: { pct: -4, min: -50, max: 30 }, + waistbandWidth: { mm: 40, min: 20, max: 60 }, lengthBonus: { pct: 2, min: -20, max: 10 }, crotchDrop: { pct: 2, min: 0, max: 15 }, @@ -133,9 +134,6 @@ export default { frontPocketWidth: { pct: 55, min: 45, max: 65 }, frontPocketDepth: { pct: 100, min: 85, max: 110 }, - // Belt - waistbandWidth: { mm: 25, min: 5, max: 45 }, - // Fly flyCurve: { pct: 72, min: 50, max: 100 }, flyLength: { pct: 45, min: 30, max: 60 }, @@ -143,6 +141,7 @@ export default { // Waistband splitWaistband: { bool: false }, - waistbandWidth: { pct: 40, min: 25, max: 65 } + waistbandWidth: { mm: 40, min: 20, max: 60 }, + beltLoops: { count: 8, min: 6, max: 12 } } } diff --git a/packages/charlie/example/package.json b/packages/charlie/example/package.json index 56a47b3bc4f..0f82bb75aaf 100644 --- a/packages/charlie/example/package.json +++ b/packages/charlie/example/package.json @@ -15,21 +15,20 @@ "@freesewing/mui-theme": "latest", "@freesewing/pattern-info": "latest", "@freesewing/plugin-bundle": "latest", - "@freesewing/plugin-buttons": "^2.14.0", + "@freesewing/plugin-theme": "latest", "@freesewing/plugin-i18n": "latest", "@freesewing/plugin-svgattr": "latest", - "@freesewing/plugin-theme": "latest", "@freesewing/utils": "latest", "@material-ui/core": "^4.11.2", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^v4.0.0-alpha.57", - "file-saver": "^2.0.5", "pattern": "link:..", "prismjs": "1.22.0", "react": "^17.0.1", "react-dom": "^17.0.1", - "react-markdown": "5.0.3", - "react-scripts": "^3.4.4" + "react-scripts": "^3.4.4", + "file-saver": "^2.0.5", + "react-markdown": "5.0.3" }, "scripts": { "start": "react-scripts start", diff --git a/packages/charlie/example/src/index.js b/packages/charlie/example/src/index.js index 9dd7ba788d4..24aefad45a1 100644 --- a/packages/charlie/example/src/index.js +++ b/packages/charlie/example/src/index.js @@ -2,6 +2,7 @@ import React from 'react' import ReactDOM from 'react-dom' import App from './App' import * as serviceWorker from './serviceWorker' +import './layout.css' ReactDOM.render(, document.getElementById('root')) diff --git a/packages/charlie/example/src/layout.css b/packages/charlie/example/src/layout.css new file mode 100644 index 00000000000..94c9ddf0649 --- /dev/null +++ b/packages/charlie/example/src/layout.css @@ -0,0 +1,303 @@ +div.layout-wrapper { + width: 100%; + margin: 0; + padding: 0; + background-color: red; + background: #f8f9fa; + background: linear-gradient(90deg, #f1f3f5 0%, #f1f3f5 25%, #f8f9fa 26%, #f8f9fa 100%); +} +div.layout-wrapper div.layout { + display: flex; + max-width: 1600px; + margin: auto; + padding: 0; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; + background-color: #f8f9fa; + min-height: calc(100vh - 64px); +} +div.layout-wrapper div.layout > aside { + width: 33%; + background: #f1f3f5; + border-right: 2px solid #dee2e6; +} +div.layout-wrapper div.layout > section { + margin: 0; + padding: 1rem; +} +div.layout-wrapper div.layout > section > div.content { + max-width: 66ch; + min-width: 340px; +} +div.layout-wrapper div.layout > section > div.content.wide { + max-width: 100%; + margin: auto; +} + +.theme-wrapper.dark header { + background-color: #1a1d21; +} + +.theme-wrapper.dark div.layout-wrapper { + background: #f8f9fa; + background: linear-gradient(90deg, #1a1d21 0%, #1a1d21 25%, #212529 26%, #212529 100%); +} +.theme-wrapper.dark div.layout-wrapper div.layout { + background-color: #212529; +} +.theme-wrapper.dark div.layout-wrapper div.layout > aside { + background-color: #1a1d21; + border-right: 2px solid #343a40; +} + +header a svg { + color: #ced4da; +} + +header a:first-of-type svg { + color: #f8f9fa; +} + +header a:hover svg { + color: #b197fc; +} + +header a span, +header button span { + color: #ced4da; +} +header a span svg, +header button span svg { + color: #dee2e6; +} + +header a:hover span, +header button:hover span { + color: #f8f9fa; +} +header a:hover span svg, +header button:hover span svg { + color: #b197fc; +} + +header a, +header button { + padding: 0 1vw !important; +} + +/* monitor */ +@media (min-width: 1200px) { + div.layout > section { + width: 63%; + } +} + +/* slate */ +@media (max-width: 1199px) and (min-width: 960px) { + div.layout > aside { + width: 298px; + } + div.layout > section { + width: calc(100% - 300px - 4rem); + max-width: none; + margin: 0 1rem 0 3rem; + } +} + +/* tablet */ +@media (max-width: 959px) { + div.layout > aside { + width: 218px; + } + div.layout > section { + width: calc(100% - 220px - 4rem); + max-width: none; + margin: 0; + padding: 0 2rem; + } + div.layout > section div.content { + min-width: inherit; + } +} + +/* mobile */ +@media (max-width: 599px) { + div.layout > aside { + display: none; + } + div.layout > section { + width: calc(100%); + margin: 0 auto; + padding: 0 1.5rem; + max-width: none; + } +} + +div.gatsby-highlight { + margin-bottom: 1rem; +} + +@media (max-width: 599px) { + #mobile-menu { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + padding: 0 0 1rem; + max-width: 600px; + z-index: -10; + transition: opacity 0.25s ease 0s; + opacity: 0; + overflow: scroll; + } + #mobile-menu > ul, + #mobile-menu > div { + transform: translate(0px, 10px); + transition: transform 0.25s ease 0s; + } + .theme-wrapper.show-menu #mobile-menu { + opacity: 1; + z-index: 10; + } + .theme-wrapper.show-menu #mobile-menu > div { + transform: translate(0px, 0px); + } +} + +.theme-wrapper.light div.draft-ui-menu, +.theme-wrapper.light div.menu { + background: #f1f3f5; +} + +.theme-wrapper.dark div.draft-ui-menu, +.theme-wrapper.dark div.menu { + background: #343a40; +} + +.theme-wrapper.show-menu div.menu { + opacity: 1; + z-index: 10; +} +.theme-wrapper.show-menu div.menu > div { + transform: translate(0px, 0px); +} + +div.spaced-buttons > button { + margin: 0 0.5rem 0.5rem 0; +} + +div.spaced > * { + margin: 0 0.5rem 0.5rem 0; +} + +ul#pre-main-menu { + margin: 0; + padding: 0; +} + +.boldish { + font-weight: 500; +} + +.freesewing.draft { + padding: 1rem; +} + +li.action { + clear: both; +} + +li.action span.MuiSwitch-root { + float: right; +} + +.theme-wrapper.light ul#draft-config li.action.toggle.off, +.theme-wrapper.dark ul#draft-config li.action.toggle.off { + color: #868e96; +} +.theme-wrapper.light ul#draft-config li.action.toggle.off > span svg, +.theme-wrapper.dark ul#draft-config li.action.toggle.off > span svg { + color: #868e96; +} + +footer { + background-color: #1a1d21; + color: #adb5bd; + padding: 3rem 0 6rem; +} +footer a { + color: #dee2e6 !important; + font-weight: 400; +} +footer a:hover { + color: #d0bfff !important; +} +footer div.cols { + display: flex; + flex-direction: row; + justify-content: space-between; + max-width: 1600px; + margin: auto; + padding: 0 1.5rem; +} +footer div.cols > div { + min-width: 150px; + max-width: calc(20% - 4rem); + padding: 0 2rem 0 0; + width: 100%; +} +footer ul { + text-align: left; + font-size: 1.1rem; + margin: 0; + padding: 0; + width: 100%; +} +footer ul li:first-of-type { + padding: 0.35rem 0.75rem; +} +footer ul li { + display: block; +} +footer ul li a:hover { + text-decoration: none !important; +} +footer ul li.heading { + font-weight: bold; + border-bottom: 3px solid #adb5bd; + margin-bottom: 0.5rem; +} + +/* XL screens */ +@media (min-width: 1200px) { + footer div.cols > div:last-of-type { + min-width: 350px; + } +} + +/* SM screens */ +@media (min-width: 600px) and (max-width: 959px) { + footer div.cols { + flex-wrap: wrap; + } + footer div.cols > div { + width: calc(30% - 4rem); + padding: 0 1rem; + } +} + +/* XS screens */ +@media (max-width: 599px) { + footer div.cols { + display: block; + } + footer div.cols > div { + margin: 2rem auto 0; + max-width: calc(100% - 4rem); + } + footer div.cols > div:first-of-type { + margin-top: 0; + } +} diff --git a/packages/charlie/package.json b/packages/charlie/package.json index 8e90f4be675..8564f7959b7 100644 --- a/packages/charlie/package.json +++ b/packages/charlie/package.json @@ -1,6 +1,6 @@ { "name": "@freesewing/charlie", - "version": "2.12.2", + "version": "2.14.0", "description": "A FreeSewing pattern for chino trousers", "author": "Joost De Cock (https://github.com/joostdecock)", "homepage": "https://freesewing.org/", @@ -34,8 +34,8 @@ "testci": "BABEL_ENV=production ./node_modules/.bin/_mocha tests/*.test.js --require @babel/register" }, "peerDependencies": { - "@freesewing/core": "^2.12.1", - "@freesewing/plugin-bundle": "^2.12.1" + "@freesewing/core": "^2.14.0", + "@freesewing/plugin-bundle": "^2.14.0" }, "dependencies": {}, "devDependencies": { @@ -46,14 +46,14 @@ "eslint": "^7.6.0", "babel-jest": "^26.2.2", "jest": "26.2.2", - "@freesewing/components": "^2.12.1", - "@freesewing/css-theme": "^2.12.1", - "@freesewing/i18n": "^2.12.1", - "@freesewing/mui-theme": "^2.12.1", - "@freesewing/plugin-bust": "^2.12.1", - "@freesewing/plugin-buttons": "^2.12.1", - "@freesewing/plugin-flip": "^2.12.1", - "@freesewing/utils": "^2.12.1", + "@freesewing/components": "^2.14.0", + "@freesewing/css-theme": "^2.14.0", + "@freesewing/i18n": "^2.14.0", + "@freesewing/mui-theme": "^2.14.0", + "@freesewing/plugin-bust": "^2.14.0", + "@freesewing/plugin-buttons": "^2.14.0", + "@freesewing/plugin-flip": "^2.14.0", + "@freesewing/utils": "^2.14.0", "@svgr/rollup": "^2.4.1", "cross-env": "^7.0.2", "react-scripts": "^3.4.1", diff --git a/packages/charlie/src/back-pocket-facing.js b/packages/charlie/src/back-pocket-facing.js index f2fd84b8695..e69266244e8 100644 --- a/packages/charlie/src/back-pocket-facing.js +++ b/packages/charlie/src/back-pocket-facing.js @@ -42,7 +42,7 @@ export default (part) => { points.titleAnchor = points.rightNotch.shiftFractionTowards(points.leftNotch, 0.5) macro('title', { at: points.titleAnchor, - nr: 5, + nr: 6, title: 'backPocketBagFacing' }) points.grainlineTop = points.waistbandLeft.shiftFractionTowards(points.waistbandRight, 0.15) diff --git a/packages/charlie/src/back-pocket-interfacing.js b/packages/charlie/src/back-pocket-interfacing.js new file mode 100644 index 00000000000..d053135104e --- /dev/null +++ b/packages/charlie/src/back-pocket-interfacing.js @@ -0,0 +1,60 @@ +export default (part) => { + // Shorthand + let { + points, + Point, + paths, + Path, + measurements, + options, + complete, + paperless, + store, + macro, + utils, + snippets, + Snippet, + sa + } = part.shorthand() + + // Clean up + for (let id in paths) delete paths[id] + delete snippets.logo + + const height = points.bottomRight.x / 3 + points.bottomLeft = points.curveStartLeft.shift(-90, points.rightNotch.x / 1.75) + points.bottomRight = points.bottomLeft.flipX() + points.midLeft = points.bottomLeft.shift(90, height) + points.midRight = points.bottomRight.shift(90, height) + points.topLeft = points.bottomLeft.shift(90, height * 2) + points.topRight = points.bottomRight.shift(90, height * 2) + points.leftNotch = new Point(points.leftNotch.x, points.midRight.y) + points.rightNotch = points.leftNotch.flipX() + + paths.seam = new Path() + .move(points.topLeft) + .line(points.bottomLeft) + .line(points.bottomRight) + .line(points.topRight) + .line(points.topLeft) + .close() + .attr('class', 'interfacing') + + if (complete) { + paths.fold = new Path() + .move(points.leftNotch) + .line(points.rightNotch) + .attr('class', 'interfacing dashed') + points.titleAnchor = points.rightNotch.shiftFractionTowards(points.leftNotch, 0.5) + macro('title', { + at: points.titleAnchor, + nr: 3, + title: 'backPocketInterfacing' + }) + + if (paperless) { + } + } + + return part +} diff --git a/packages/charlie/src/back-pocket-jet.js b/packages/charlie/src/back-pocket-jet.js index bcff6ddf4e1..a1729b47869 100644 --- a/packages/charlie/src/back-pocket-jet.js +++ b/packages/charlie/src/back-pocket-jet.js @@ -45,7 +45,7 @@ export default (part) => { points.titleAnchor = points.rightNotch.shiftFractionTowards(points.leftNotch, 0.5) macro('title', { at: points.titleAnchor, - nr: 3, + nr: 4, title: 'backPocketJet', scale: 0.5 }) diff --git a/packages/charlie/src/back-pocket.js b/packages/charlie/src/back-pocket.js index 9ddd3e6a9d6..fd7d2b42245 100644 --- a/packages/charlie/src/back-pocket.js +++ b/packages/charlie/src/back-pocket.js @@ -56,7 +56,7 @@ export default (part) => { points.titleAnchor = points.rightNotch.shiftFractionTowards(points.foldLeft, 0.5) macro('title', { at: points.titleAnchor, - nr: 4, + nr: 5, title: 'backPocketBag' }) points.logoAnchor = points.foldLeft.shiftFractionTowards(points.bottomRight, 0.5) diff --git a/packages/charlie/src/back.js b/packages/charlie/src/back.js index fa71facae32..18e6da43eaa 100644 --- a/packages/charlie/src/back.js +++ b/packages/charlie/src/back.js @@ -2,22 +2,15 @@ export default (part) => { // Helper method to draw the outseam path const drawOutseam = () => { let waistOut = points.styleWaistOut || points.waistOut - if (points.waistOut.x > points.seatOut.x) { - let outseam = new Path() - .move(points.styleWaistOut) - .curve(points.seatOut, points.kneeOutCp2, points.floorOut) - return new Path() - .move(points.slantOut) - .line(points.slantCurveStart) - .curve(points.slantCurveCp1, points.slantCurveCp2, points.slantCurveEnd) - .join(outseam.split(points.slantCurveEnd).pop()) - .reverse() - } else { - return new Path() - .move(points.floorOut) - .curve(points.kneeOutCp2, points.seatOutCp1, points.seatOut) - .curve_(points.seatOutCp2, waistOut) - } + let outseam = new Path() + .move(points.styleWaistOut) + .curve(points.seatOut, points.kneeOutCp2, points.floorOut) + return new Path() + .move(points.slantOut) + .line(points.slantCurveStart) + .curve(points.slantCurveCp1, points.slantCurveCp2, points.slantCurveEnd) + .join(outseam.split(points.slantCurveEnd).pop()) + .reverse() } /* * Helper method to draw the outline path @@ -88,10 +81,11 @@ export default (part) => { .move(points.styleWaistOut) .curve(points.seatOut, points.kneeOutCp2, points.floorOut) + // Keep the seat control point vertically between the (lowered) waist and seat line + points.seatOutCp2.y = points.styleWaistOut.y + points.styleWaistOut.dy(points.seatOut) / 2 + // Construct pocket slant - if (points.waistOut.x > points.seatOut.x) { - points.slantBottom = titanOutseam.shiftAlong(store.get('slantLength')) - } + points.slantBottom = titanOutseam.shiftAlong(store.get('slantLength')) points.slantOut = points.styleWaistIn.shiftOutwards(points.styleWaistOut, store.get('slantWidth')) // Shape waist @@ -165,6 +159,19 @@ export default (part) => { on: ['grainlineBottom', 'slantBottomNotch', 'slantTopNotch'] }) + macro('bartack', { + anchor: points.slantTopNotch, + angle: points.slantTopNotch.angle(points.slantBottomNotch) - 90, + length: sa ? sa / 2 : 5, + suffix: 'slantTop' + }) + macro('bartack', { + anchor: points.slantBottomNotch, + length: sa ? sa / 2 : 5, + angle: 180, + suffix: 'slantBottom' + }) + if (sa) { paths.sa = paths.saBase .offset(sa) diff --git a/packages/charlie/src/beltloop.js b/packages/charlie/src/beltloop.js deleted file mode 100644 index 63314aa89b2..00000000000 --- a/packages/charlie/src/beltloop.js +++ /dev/null @@ -1,60 +0,0 @@ -export default (part) => { - // Shorthand - let { - points, - Point, - paths, - Path, - measurements, - options, - complete, - paperless, - store, - macro, - utils, - snippets, - Snippet, - sa - } = part.shorthand() - - let length = measurements.waist * options.waistbandWidth * options.waistbandFactor * 1.2 - let width = length / 5 - - points.topLeft = new Point(0, 0) - points.topRight = new Point(width, 0) - points.bottomLeft = new Point(0, length) - points.bottomRight = new Point(width, length) - - paths.seam = new Path() - .move(points.topLeft) - .line(points.bottomLeft) - .line(points.bottomRight) - .line(points.topRight) - .line(points.topLeft) - .close() - .attr('class', 'fabric') - - if (complete) { - macro('title', { - at: new Point(width / 4, length / 4), - nr: 11, - title: 'beltLoop', - scale: 0.3, - rotation: 90 - }) - if (sa) - paths.sa = new Path() - .move(points.topLeft.shift(180, sa).shift(90, 2 * sa)) - .line(points.bottomLeft.shift(180, sa).shift(-90, 2 * sa)) - .line(points.bottomRight.shift(0, sa).shift(-90, 2 * sa)) - .line(points.topRight.shift(0, sa).shift(90, 2 * sa)) - .line(points.topLeft.shift(180, sa).shift(90, 2 * sa)) - .close() - .attr('class', 'sa fabric') - - if (paperless) { - } - } - - return part -} diff --git a/packages/charlie/src/beltloops.js b/packages/charlie/src/beltloops.js new file mode 100644 index 00000000000..241a353a908 --- /dev/null +++ b/packages/charlie/src/beltloops.js @@ -0,0 +1,78 @@ +export default (part) => { + // Shorthand + let { + points, + Point, + paths, + Path, + measurements, + options, + complete, + paperless, + store, + macro, + utils, + snippets, + Snippet, + sa + } = part.shorthand() + + let count = options.beltLoops + let length = options.waistbandWidth * 2.5 * count + let width = options.waistbandWidth / 4 + + points.topLeft = new Point(0, 0) + points.topRight = new Point(width * 2.8, 0) + points.bottomLeft = new Point(0, length) + points.bottomRight = new Point(width * 2.8, length) + points.topFold1 = new Point(width * 0.8, 0) + points.topFold2 = new Point(width * 1.8, 0) + points.bottomFold1 = new Point(width * 0.8, length) + points.bottomFold2 = new Point(width * 1.8, length) + for (let i = 1; i < count; i++) { + points[`cut${i}a`] = points.topLeft.shiftFractionTowards(points.bottomLeft, i / count) + points[`cut${i}b`] = points.topRight.shiftFractionTowards(points.bottomRight, i / count) + } + + paths.seam = new Path() + .move(points.topLeft) + .line(points.bottomLeft) + .line(points.bottomRight) + .line(points.topRight) + .line(points.topLeft) + .close() + .attr('class', 'fabric') + + if (complete) { + paths.fold = new Path() + .move(points.topFold1) + .line(points.bottomFold1) + .move(points.bottomFold2) + .line(points.topFold2) + .attr('class', 'fabric help') + macro('title', { + at: new Point(width / 2, length / 2), + nr: 12, + title: 'beltLoops', + rotation: 90, + scale: 0.7 + }) + points.grainlineTop = new Point(points.topRight.x / 2, 0) + points.grainlineBottom = new Point(points.topRight.x / 2, length) + macro('grainline', { + from: points.grainlineTop, + to: points.grainlineBottom + }) + for (let i = 1; i < count; i++) { + paths[`cut${i}`] = new Path() + .move(points[`cut${i}a`]) + .line(points[`cut${i}b`]) + .attr('class', 'fabric dashed') + } + + if (paperless) { + } + } + + return part +} diff --git a/packages/charlie/src/fly-extention.js b/packages/charlie/src/fly-extension.js similarity index 99% rename from packages/charlie/src/fly-extention.js rename to packages/charlie/src/fly-extension.js index d26538d823b..430ba4218ed 100644 --- a/packages/charlie/src/fly-extention.js +++ b/packages/charlie/src/fly-extension.js @@ -56,7 +56,7 @@ export default (part) => { points.titleAnchor = points.flyCurveStart macro('title', { at: points.titleAnchor, - nr: 9, + nr: 10, title: 'flyExtention' }) if (sa) diff --git a/packages/charlie/src/fly-facing.js b/packages/charlie/src/fly-facing.js index e5137f62a99..dd744d30614 100644 --- a/packages/charlie/src/fly-facing.js +++ b/packages/charlie/src/fly-facing.js @@ -45,7 +45,7 @@ export default (part) => { points.titleAnchor = points.grainlineTop.shiftFractionTowards(points.grainlineBottom, 0.5) macro('title', { at: points.titleAnchor, - nr: 8, + nr: 9, title: 'flyFacing' }) if (sa) diff --git a/packages/charlie/src/front-pocket-facing.js b/packages/charlie/src/front-pocket-facing.js index 7eb53e3a79f..b70ed9f4037 100644 --- a/packages/charlie/src/front-pocket-facing.js +++ b/packages/charlie/src/front-pocket-facing.js @@ -41,7 +41,7 @@ export default (part) => { points.titleAnchor = points.slantBottomNotch.shift(0, 10) macro('title', { at: points.titleAnchor, - nr: 7, + nr: 8, title: 'frontPocketBagFacing' }) macro('grainline', { diff --git a/packages/charlie/src/front-pocket.js b/packages/charlie/src/front-pocket.js index 2398db5b60a..fa553699f93 100644 --- a/packages/charlie/src/front-pocket.js +++ b/packages/charlie/src/front-pocket.js @@ -28,9 +28,15 @@ export default (part) => { 'slantTop', 'slantBottom', 'slantTop', + 'pocketbagBottomCp1', 'pocketbagBottomCp2', 'pocketbagBottom', - 'pocketbagBottomRight' + 'pocketbagBottomRight', + 'pocketFacingBottom', + 'slantCurveStart', + 'slantCurveCp1', + 'slantCurveCp2', + 'slantCurveEnd' ]) points[id] = points[id].rotate(-1 * (slant - 90), points.pocketbagTopRight) @@ -61,7 +67,7 @@ export default (part) => { ) macro('title', { at: points.titleAnchor, - nr: 6, + nr: 7, title: 'frontPocketBag' }) macro('cutonfold', { diff --git a/packages/charlie/src/front.js b/packages/charlie/src/front.js index 5f48877afa3..df1efc0bca3 100644 --- a/packages/charlie/src/front.js +++ b/packages/charlie/src/front.js @@ -67,11 +67,15 @@ export default (part) => { points.styleWaistIn, 1 - options.flyWidth ) + points.flyCorner = points.flyTop.shift( points.styleWaistIn.angle(points.crotchSeamCurveStart), points.styleWaistIn.dist(points.flyBottom) ) - points.flyCurveStart = points.flyBottom.rotate(90, points.flyCorner) + points.flyCurveStart = points.flyCorner.shiftTowards( + points.flyTop, + points.flyBottom.dist(points.flyCorner) + ) points.flyCurveCp1 = points.flyBottom.shiftFractionTowards(points.flyCorner, options.flyCurve) points.flyCurveCp2 = points.flyCurveStart.shiftFractionTowards(points.flyCorner, options.flyCurve) @@ -185,15 +189,6 @@ export default (part) => { .attr('class', 'dashed') .attr('data-text', 'Left panel only') .attr('data-text-class', 'center') - points.barTack1 = Jseam.reverse().shiftFractionAlong(0.1) - points.barTack2a = Jseam.shiftFractionAlong(0.2) - points.barTack2b = Jseam.shiftFractionAlong(0.35) - paths.barTack1 = paths.Jseam.split(points.barTack1).pop().attr('class', 'bartack') - paths.barTack2 = paths.Jseam.split(points.barTack2a) - .pop() - .split(points.barTack2b) - .shift() - .attr('class', 'bartack') paths.pocketBag = new Path() .move(points.slantTop) .line(points.slantCurveStart) @@ -205,6 +200,25 @@ export default (part) => { .line(points.pocketFacingBottom) .attr('class', 'lining dashed') + // Bartack + macro('bartack', { + anchor: points.slantTopNotch, + angle: points.slantTopNotch.angle(points.slantCurveStart) + 90, + length: sa ? sa / 1.5 : 7.5, + suffix: 'slantTop' + }) + macro('bartack', { + anchor: points.slantBottomNotch, + length: sa ? sa / 2 : 5, + suffix: 'slantBottom' + }) + macro('bartackFractionAlong', { + path: Jseam.reverse(), + start: 0, + end: 0.1, + suffix: 'stom' + }) + if (sa) { paths.sa = drawPath() .offset(sa) diff --git a/packages/charlie/src/index.js b/packages/charlie/src/index.js index aece940da28..02d02235c06 100644 --- a/packages/charlie/src/index.js +++ b/packages/charlie/src/index.js @@ -3,42 +3,24 @@ import Titan from '@freesewing/titan' import plugins from '@freesewing/plugin-bundle' import mirrorPlugin from '@freesewing/plugin-mirror' import buttonsPlugin from '@freesewing/plugin-buttons' +import bartackPlugin from '@freesewing/plugin-bartack' import config from '../config' // Parts import draftBack from './back' import draftFront from './front' import draftWaistband from './waistband' -import draftWaistbandButtonSide from './waistband-button-side' -import draftWaistbandButtonholeSide from './waistband-buttonhole-side' import draftFrontPocket from './front-pocket' import draftFrontPocketFacing from './front-pocket-facing' import draftBackPocket from './back-pocket' import draftBackPocketFacing from './back-pocket-facing' +import draftBackPocketInterfacing from './back-pocket-interfacing' import draftBackPocketJet from './back-pocket-jet' import draftFlyFacing from './fly-facing' -import draftFlyExtention from './fly-extention' -import draftBeltLoop from './beltloop' - -// Hack the waistHeight option to make room for waistband -const waistbandPlugin = { - name: 'charlieWaistbandPlugin', - version: config.version, - hooks: { - preDraft: function ({ settings }) { - // Reduce the waistHeight option by 25% to make room for the waistband - // We could also just use negative numbers, but that might confuse the user - settings.options.waistHeight -= settings.options.waistbandReduction - } - } -} +import draftFlyExtension from './fly-extension' +import draftBeltLoops from './beltloops' // Create design -const Pattern = new freesewing.Design(config, [ - plugins, - mirrorPlugin, - buttonsPlugin, - waistbandPlugin -]) +const Pattern = new freesewing.Design(config, [plugins, mirrorPlugin, buttonsPlugin, bartackPlugin]) // Attach titan draft methods to prototype for (let p of ['Front', 'Back']) { @@ -51,15 +33,14 @@ for (let p of ['Front', 'Back']) { Pattern.prototype.draftBack = (part) => draftBack(part) Pattern.prototype.draftFront = (part) => draftFront(part) Pattern.prototype.draftWaistband = (part) => draftWaistband(part) -Pattern.prototype.draftWaistbandButtonSide = (part) => draftWaistbandButtonSide(part) -Pattern.prototype.draftWaistbandButtonholeSide = (part) => draftWaistbandButtonholeSide(part) Pattern.prototype.draftFrontPocket = (part) => draftFrontPocket(part) Pattern.prototype.draftFrontPocketFacing = (part) => draftFrontPocketFacing(part) Pattern.prototype.draftBackPocket = (part) => draftBackPocket(part) Pattern.prototype.draftBackPocketFacing = (part) => draftBackPocketFacing(part) +Pattern.prototype.draftBackPocketInterfacing = (part) => draftBackPocketInterfacing(part) Pattern.prototype.draftBackPocketJet = (part) => draftBackPocketJet(part) Pattern.prototype.draftFlyFacing = (part) => draftFlyFacing(part) -Pattern.prototype.draftFlyExtention = (part) => draftFlyExtention(part) -Pattern.prototype.draftBeltLoop = (part) => draftBeltLoop(part) +Pattern.prototype.draftFlyExtension = (part) => draftFlyExtension(part) +Pattern.prototype.draftBeltLoops = (part) => draftBeltLoops(part) export default Pattern diff --git a/packages/charlie/src/waistband-button-side.js b/packages/charlie/src/waistband-button-side.js deleted file mode 100644 index 3899c5e1c79..00000000000 --- a/packages/charlie/src/waistband-button-side.js +++ /dev/null @@ -1,87 +0,0 @@ -export default (part) => { - // Shorthand - let { - points, - Point, - paths, - Path, - measurements, - options, - complete, - paperless, - store, - macro, - utils, - snippets, - Snippet, - sa - } = part.shorthand() - - if (!options.splitWaistband) return part - - points.topLeft = new Point(0, 0) - points.top = new Point(measurements.waist * options.waistbandWidth * options.waistbandFactor, 0) - points.topRight = new Point(points.top.x * 2, 0) - points.bottomLeft = new Point( - 0, - store.get('waistbandBack') + store.get('waistbandFront') + store.get('waistbandFly') - ) - points.bottom = new Point(points.top.x, points.bottomLeft.y) - points.bottomRight = new Point(points.topRight.x, points.bottomLeft.y) - - paths.saBase = new Path() - .move(points.topLeft) - .line(points.topRight) - .line(points.bottomRight) - .setRender(false) - paths.seam = paths.saBase - .clone() - .line(points.bottomLeft) - .line(points.topLeft) - .close() - .attr('class', 'fabric') - .setRender(true) - - if (complete) { - points.flyNotchRight = points.topRight.shift(-90, store.get('waistbandFly')) - points.flyNotchLeft = new Point(0, points.flyNotchRight.y) - points.firstSideNotchRight = points.flyNotchRight.shift(-90, store.get('waistbandFront')) - points.firstSideNotchLeft = new Point(0, points.firstSideNotchRight.y) - macro('sprinkle', { - snippet: 'notch', - on: ['flyNotchRight', 'flyNotchLeft', 'firstSideNotchRight', 'firstSideNotchLeft', 'bottom'] - }) - points.titleAnchor = points.top.shiftFractionTowards(points.bottom, 0.25) - points.logoAnchor = points.top.shiftFractionTowards(points.bottom, 0.75) - macro('title', { - at: points.titleAnchor, - nr: '3a', - title: 'waistbandButtonSide', - rotation: 90 - }) - macro('grainline', { - from: points.firstSideNotchLeft, - to: points.firstSideNotchRight - }) - snippets.logo = new Snippet('logo', points.logoAnchor) - paths.fold = new Path().move(points.top).line(points.bottom).attr('class', 'fabric help') - if (sa) { - paths.sa = paths.saBase - .offset(sa * -1) - .join( - new Path() - .move(points.bottomRight) - .line(points.bottomLeft) - .line(points.topLeft) - .offset(sa * -2) - ) - .close() - .attr('class', 'fabric sa') - } - - if (paperless) { - } - } - - return part -} diff --git a/packages/charlie/src/waistband-buttonhole-side.js b/packages/charlie/src/waistband-buttonhole-side.js deleted file mode 100644 index 0c5dcb9d307..00000000000 --- a/packages/charlie/src/waistband-buttonhole-side.js +++ /dev/null @@ -1,81 +0,0 @@ -export default (part) => { - // Shorthand - let { - points, - Point, - paths, - Path, - measurements, - options, - complete, - paperless, - store, - macro, - utils, - snippets, - Snippet, - sa - } = part.shorthand() - - if (!options.splitWaistband) return part - - points.topLeft = new Point(0, 0) - points.top = new Point(measurements.waist * options.waistbandWidth * options.waistbandFactor, 0) - points.topRight = new Point(points.top.x * 2, 0) - points.bottomLeft = new Point(0, store.get('waistbandFront') + store.get('waistbandBack')) - points.bottom = new Point(points.top.x, points.bottomLeft.y) - points.bottomRight = new Point(points.topRight.x, points.bottomLeft.y) - - paths.saBase = new Path() - .move(points.topRight) - .line(points.bottomRight) - .line(points.bottomLeft) - .setRender(false) - paths.seam = paths.saBase - .clone() - .line(points.topLeft) - .close() - .attr('class', 'fabric') - .setRender(true) - - if (complete) { - points.firstSideNotchRight = points.topRight.shift(-90, store.get('waistbandBack')) - points.firstSideNotchLeft = new Point(0, points.firstSideNotchRight.y) - macro('sprinkle', { - snippet: 'notch', - on: ['firstSideNotchRight', 'firstSideNotchLeft', 'top'] - }) - points.titleAnchor = points.top.shiftFractionTowards(points.bottom, 0.25) - points.logoAnchor = points.top.shiftFractionTowards(points.bottom, 0.75) - macro('title', { - at: points.titleAnchor, - nr: '3b', - title: 'waistbandButtonholeSide', - rotation: 90 - }) - macro('grainline', { - from: points.firstSideNotchLeft, - to: points.firstSideNotchRight - }) - snippets.logo = new Snippet('logo', points.logoAnchor) - paths.fold = new Path().move(points.top).line(points.bottom).attr('class', 'fabric help') - if (sa) { - paths.sa = paths.saBase - .offset(sa * -1) - .join( - new Path() - .move(points.bottomLeft) - .line(points.topLeft) - .line(points.topRight) - .offset(sa * -2) - ) - .close() - .attr('class', 'fabric sa') - } - - if (paperless) { - } - } - - return part -} diff --git a/packages/charlie/src/waistband.js b/packages/charlie/src/waistband.js index 8f6aa7c3aaa..e150168256a 100644 --- a/packages/charlie/src/waistband.js +++ b/packages/charlie/src/waistband.js @@ -17,10 +17,8 @@ export default (part) => { sa } = part.shorthand() - if (options.splitWaistband) return part - points.topLeft = new Point(0, 0) - points.top = new Point(measurements.waist * options.waistbandWidth * options.waistbandFactor, 0) + points.top = new Point(options.waistbandWidth, 0) points.topRight = new Point(points.top.x * 2, 0) points.bottomLeft = new Point( 0, @@ -55,7 +53,7 @@ export default (part) => { points.logoAnchor = points.top.shiftFractionTowards(points.bottom, 0.6) macro('title', { at: points.titleAnchor, - nr: 10, + nr: 11, title: 'waistband', rotation: 90 })