diff --git a/config/software/designs.json b/config/software/designs.json index e46320e9ea6..4d7f6e70230 100644 --- a/config/software/designs.json +++ b/config/software/designs.json @@ -330,7 +330,7 @@ "design": "Wouter Van Wageningen", "difficulty": 3, "tags": ["blocks", "tops"], - "techniques": ["curvedSeam", "precision", "princessSeam"] + "techniques": ["block", "curvedSeam", "precision", "princessSeam"] }, "octoplushy": { "lab": true, @@ -414,6 +414,14 @@ "tags": ["tops"], "techniques": ["hem", "button", "interfacing", "curvedSeam", "flatFelledSeam", "flatSleeve"] }, + "skully": { + "description": "A FreeSewing pattern for skully, our logo, a plushy toy", + "code": "Wouter Van Wageningen", + "design": "Wouter Van Wageningen", + "difficulty": 4, + "tags": ["accessories", "toys"], + "techniques": ["curvedSeam", "precision"] + }, "sven": { "lab": true, "org": true, diff --git a/designs/skully/CHANGELOG.md b/designs/skully/CHANGELOG.md new file mode 100644 index 00000000000..4dfcc7b22f6 --- /dev/null +++ b/designs/skully/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change log for: @freesewing/skully + + + +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/skully/README.md b/designs/skully/README.md new file mode 100644 index 00000000000..dfb5b197513 --- /dev/null +++ b/designs/skully/README.md @@ -0,0 +1,297 @@ +![FreeSewing](https://static.freesewing.org/banner.png) +

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

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

+ +# @freesewing/skully + +A FreeSewing pattern for skully, our logo, a plushy toy + + + + +> #### Note: Version 3 is a work in progress +> +> We are working on a new major version (v3) but it is not ready for prime-time. +> For production use, please refer to our v2 packages (the `latest` on NPM) +> or [the `v2` branch in our monorepo](https://github.com/freesewing/freesewing/tree/v2). +> +> We the `main` branch and `next` packages on NPM holds v3 code. But it's alpha for now. + +## What am I looking at? πŸ€” + +This repository is our *monorepo* holding all our NPM designs, plugins, other NPM packages, and (web)sites. + +This folder holds: @freesewing/skully + +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 +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. 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 +npx create-freesewing-pattern +``` + +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/). + +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, 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 [discord.freesewing.org](https://discord.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) + +## 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 🀯 + +Our [chatrooms on Discord](https://chat.freesewing.org/) are the best place to ask questions, +share your feedback, or just hang out. + +If you want to report a problem, please [create an issue](https://github.com/freesewing/freesewing/issues/new). + + + +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Adam Tomkins
Adam Tomkins

πŸ“–
Alexandre Ignjatovic
Alexandre Ignjatovic

πŸ’»
AlfaLyr
AlfaLyr

πŸ’» πŸ”Œ 🎨
Andrew James
Andrew James

πŸ“–
Anneke
Anneke

πŸ“– 🌍
Annie Kao
Annie Kao

πŸ“–
Anternative
Anternative

πŸ“–
Anthony
Anthony

πŸ’¬
Ari Grayzel-student
Ari Grayzel-student

πŸ’»
Bart
Bart

πŸ“–
BenJamesBen
BenJamesBen

πŸ’» πŸ“– πŸ›
Cameron Dubas
Cameron Dubas

πŸ“–
Carsten Biebricher
Carsten Biebricher

πŸ“–
Cathy Zoller
Cathy Zoller

πŸ“–
Chantal Lapointe
Chantal Lapointe

🌍
Damien PIQUET
Damien PIQUET

πŸ’»
Darigov Research
Darigov Research

πŸ“– πŸ€”
David Clegg
David Clegg

🎨 πŸ’»
Elena FdR
Elena FdR

πŸ“– πŸ“
Emmanuel Nyachoke
Emmanuel Nyachoke

πŸ’» πŸ“–
Enoch Riese
Enoch Riese

πŸ’»
EvEkSwed
EvEkSwed

🌍
Fantastik-Maman
Fantastik-Maman

🌍
Forrest O.
Forrest O.

πŸ“–
FrΓ©dΓ©ric
FrΓ©dΓ©ric

🌍
Glenn Matthews
Glenn Matthews

πŸ“–
Greg Sadetsky
Greg Sadetsky

πŸ“–
Igor Couto
Igor Couto

πŸ›
Ikko Ashimine
Ikko Ashimine

πŸ“–
Irapeke
Irapeke

🌍
Jacek Sawoszczuk
Jacek Sawoszczuk

πŸ“–
Jason Williams
Jason Williams

πŸ“–
Jeremy Jackson
Jeremy Jackson

πŸ’»
Jeroen Hoek
Jeroen Hoek

πŸ“–
Joe Schofield
Joe Schofield

πŸ“–
Joebidido
Joebidido

🌍
Joost De Cock
Joost De Cock

🚧
Josh Essman
Josh Essman

πŸ“–
Kake
Kake

πŸ“–
Kapunahele Wong
Kapunahele Wong

πŸ“–
Karen
Karen

πŸ“– πŸ“‹
Katie McGinley
Katie McGinley

πŸ“–
Kieran Klaassen
Kieran Klaassen

πŸ’»
Kittycatou
Kittycatou

🌍
Kris
Kris

πŸ“–
Kristin Ruben
Kristin Ruben

πŸ’»
Loudepeuter
Loudepeuter

🌍
Lucian
Lucian

πŸ“‹
MA-TATAS
MA-TATAS

πŸ“–
Marcus
Marcus

🌍
Martin Tribo
Martin Tribo

πŸ“–
Nadege Michel
Nadege Michel

⚠️ πŸ“–
Natalia
Natalia

πŸ’» 🎨 πŸ“
Nathan Yergler
Nathan Yergler

πŸ“–
Nick Dower
Nick Dower

πŸ“– πŸ’» πŸ›
Nikhil Chelliah
Nikhil Chelliah

πŸ“–
OysteinHoiby
OysteinHoiby

πŸ’»
Patrick Forringer
Patrick Forringer

πŸ”Œ
Paul
Paul

πŸ“– πŸ“ 🌍
Phillip Thelen
Phillip Thelen

πŸ’»
Pixieish
Pixieish

πŸ“–
Prof. dr. Sorcha NΓ­ Dhubhghaill
Prof. dr. Sorcha NΓ­ Dhubhghaill

πŸ“–
Quentin FELIX
Quentin FELIX

πŸ’» 🎨
Rik Hekker
Rik Hekker

πŸ›
Sam Livingston-Gray
Sam Livingston-Gray

πŸ“–
Sanne
Sanne

πŸ’» πŸ“–
Sara Latorre
Sara Latorre

🌍
SeaZeeZee
SeaZeeZee

πŸ“– πŸ’»
SimonbJohnson
SimonbJohnson

πŸ›
SirCharlotte
SirCharlotte

🌍
Slylele
Slylele

πŸ“– 🌍
Soazillon
Soazillon

🌍
SoneaTheBest
SoneaTheBest

🌍
Stefan Sydow
Stefan Sydow

🌍 πŸ“– πŸ’»
TrΓ­ona
TrΓ­ona

πŸ“–
Unmutual
Unmutual

πŸ“–
Wouter van Wageningen
Wouter van Wageningen

πŸ’» 🎨 πŸ”§
amysews
amysews

πŸ“–
anna-puk
anna-puk

πŸ’»
beautifulsummermoon
beautifulsummermoon

🌍
berce
berce

πŸ“–
biou
biou

πŸ’»
bobgeorgethe3rd
bobgeorgethe3rd

πŸ’» πŸ“– 🎨
brmlyklr
brmlyklr

πŸ“–
chri5b
chri5b

πŸ’» ⚠️
dingcycle
dingcycle

🌍
drowned-in-books
drowned-in-books

πŸ’¬
econo202
econo202

πŸ“–
ericamattos
ericamattos

🌍
fightingrabbit
fightingrabbit

πŸ’»
gaylyndie
gaylyndie

πŸ“–
grimlokason
grimlokason

πŸ’»
hellgy
hellgy

🎨
jackseye
jackseye

πŸ“–
marckiesel
marckiesel

🌍
mergerg
mergerg

πŸ“–
mesil
mesil

πŸ›
starfetch
starfetch

πŸ’» πŸ“– 🌍 🎨
timorl
timorl

πŸ’»
ttimearl
ttimearl

πŸ–‹
tuesgloomsday
tuesgloomsday

πŸ“–
valadaptive
valadaptive

πŸ’»
viocky
viocky

🌍
woolishboy
woolishboy

πŸ’»
yc
yc

🌍
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! + diff --git a/designs/skully/build.mjs b/designs/skully/build.mjs new file mode 100644 index 00000000000..99ace216bc8 --- /dev/null +++ b/designs/skully/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/skully/data.mjs b/designs/skully/data.mjs new file mode 100644 index 00000000000..97c1c76603a --- /dev/null +++ b/designs/skully/data.mjs @@ -0,0 +1,4 @@ +// This file is auto-generated | All changes you make will be overwritten. +export const name = '@freesewing/skully' +export const version = '3.0.0-alpha.8' +export const data = { name, version } diff --git a/designs/skully/i18n/de.json b/designs/skully/i18n/de.json new file mode 100644 index 00000000000..cf2665157a0 --- /dev/null +++ b/designs/skully/i18n/de.json @@ -0,0 +1,38 @@ +{ + "t": "Skully logo plush toy", + "d": "A FreeSewing pattern for skully, our logo, a plushy toy.", + "p": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "s": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "o": { + "size": { + "t": "Size", + "d": "Controls the overall size (value shown is the size of the head)" + } + } +} diff --git a/designs/skully/i18n/en.json b/designs/skully/i18n/en.json new file mode 100644 index 00000000000..4fdd6b0ccc3 --- /dev/null +++ b/designs/skully/i18n/en.json @@ -0,0 +1,25 @@ +{ + "t": "Skully logo plush toy", + "d": "A FreeSewing pattern for skully, our logo, a plushy toy.", + "p": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head part 1", + "head2": "Head part 2", + "head3": "Head part 3", + "jawfloor": "Jaw floor", + "lowerjaw": "Lower Jaw", + "lowermouth": "Lower Mouth", + "nose": "Nose", + "uppermouth": "Upper Mouth" + }, + "s": {}, + "o": { + "size": { + "t": "Size", + "d": "Controls the overall size (value shown is the resulting height of Skully)" + } + } +} diff --git a/designs/skully/i18n/es.json b/designs/skully/i18n/es.json new file mode 100644 index 00000000000..cf2665157a0 --- /dev/null +++ b/designs/skully/i18n/es.json @@ -0,0 +1,38 @@ +{ + "t": "Skully logo plush toy", + "d": "A FreeSewing pattern for skully, our logo, a plushy toy.", + "p": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "s": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "o": { + "size": { + "t": "Size", + "d": "Controls the overall size (value shown is the size of the head)" + } + } +} diff --git a/designs/skully/i18n/fr.json b/designs/skully/i18n/fr.json new file mode 100644 index 00000000000..cf2665157a0 --- /dev/null +++ b/designs/skully/i18n/fr.json @@ -0,0 +1,38 @@ +{ + "t": "Skully logo plush toy", + "d": "A FreeSewing pattern for skully, our logo, a plushy toy.", + "p": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "s": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "o": { + "size": { + "t": "Size", + "d": "Controls the overall size (value shown is the size of the head)" + } + } +} diff --git a/designs/skully/i18n/index.mjs b/designs/skully/i18n/index.mjs new file mode 100644 index 00000000000..36aac928b67 --- /dev/null +++ b/designs/skully/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/skully/i18n/nl.json b/designs/skully/i18n/nl.json new file mode 100644 index 00000000000..cf2665157a0 --- /dev/null +++ b/designs/skully/i18n/nl.json @@ -0,0 +1,38 @@ +{ + "t": "Skully logo plush toy", + "d": "A FreeSewing pattern for skully, our logo, a plushy toy.", + "p": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "s": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head1", + "head2": "Head2", + "head3": "Head3", + "jawfloor": "Jawfloor", + "lowerjaw": "Lowerjaw", + "lowermouth": "Lowermouth", + "nose": "Nose", + "uppermouth": "Uppermouth" + }, + "o": { + "size": { + "t": "Size", + "d": "Controls the overall size (value shown is the size of the head)" + } + } +} diff --git a/designs/skully/i18n/uk.json b/designs/skully/i18n/uk.json new file mode 100644 index 00000000000..4fdd6b0ccc3 --- /dev/null +++ b/designs/skully/i18n/uk.json @@ -0,0 +1,25 @@ +{ + "t": "Skully logo plush toy", + "d": "A FreeSewing pattern for skully, our logo, a plushy toy.", + "p": { + "cheek": "Cheek", + "cheekbone": "Cheekbone", + "eye": "Eye", + "forehead": "Forehead", + "head1": "Head part 1", + "head2": "Head part 2", + "head3": "Head part 3", + "jawfloor": "Jaw floor", + "lowerjaw": "Lower Jaw", + "lowermouth": "Lower Mouth", + "nose": "Nose", + "uppermouth": "Upper Mouth" + }, + "s": {}, + "o": { + "size": { + "t": "Size", + "d": "Controls the overall size (value shown is the resulting height of Skully)" + } + } +} diff --git a/designs/skully/package.json b/designs/skully/package.json new file mode 100644 index 00000000000..ff01ff6489e --- /dev/null +++ b/designs/skully/package.json @@ -0,0 +1,69 @@ +{ + "name": "@freesewing/skully", + "version": "3.0.0-alpha.8", + "description": "A FreeSewing pattern for skully, our logo, a plushy toy", + "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": { + ".": "./dist/index.mjs" + }, + "scripts": { + "build": "node build.mjs", + "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": "npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js", + "cibuild_step5": "node build.mjs", + "wbuild": "node build.mjs", + "wcibuild_step5": "node build.mjs" + }, + "peerDependencies": { + "@freesewing/core": "3.0.0-alpha.8", + "@freesewing/plugin-bundle": "3.0.0-alpha.8" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "10.0.0", + "chai": "4.2.0" + }, + "files": [ + "dist/*", + "README.md" + ], + "publishConfig": { + "access": "public", + "tag": "next" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8" + } +} diff --git a/designs/skully/src/cheek.mjs b/designs/skully/src/cheek.mjs new file mode 100644 index 00000000000..46f2aed4285 --- /dev/null +++ b/designs/skully/src/cheek.mjs @@ -0,0 +1,301 @@ +export const cheek = { + name: 'skully.cheek', + options: { + size: { + pct: 75, + min: 10, + max: 300, + // eslint-disable-next-line no-unused-vars + toAbs: (value, { measurements }, mergedOptions) => + value * ((measurements?.head ? measurements.head : 596) / 929.5) * 2 * 175, + menu: 'fit', + }, + }, + optionalMeasurements: ['head'], + draft: ({ + options, + Point, + Path, + points, + paths, + Snippet, + snippets, + measurements, + sa, + complete, + store, + macro, + part, + }) => { + const textAttribute = 'text-xs center' + const sizeFactor = + (('head' in measurements ? measurements.head : 596) / 929.5) * options.size * 2 + store.set('sizeFactor', sizeFactor) + + points.point0 = new Point(0, 0) + points.point1 = points.point0.shift(254.78244159705943, 22.5254232590644 * sizeFactor) + points.point1Cp1 = points.point1.shift(321.2022157426192, 7.140882368447221 * sizeFactor) + points.point2 = points.point0.shift(260.1018837009255, 44.64105174612264 * sizeFactor) + points.point2Cp1 = points.point2.shift(243.25309471936828, 16.615062563830442 * sizeFactor) + points.point2Cp2 = points.point2.shift(322.6411575424251, 21.283352555459906 * sizeFactor) + points.point3 = points.point0.shift(261.38174456728586, 76.35866165668438 * sizeFactor) + points.point3Cp1 = points.point3.shift(333.3176703576494, 12.168666812761435 * sizeFactor) + points.point3Cp2 = points.point3.shift(85.91520774712568, 11.731692674119953 * sizeFactor) + points.point4 = points.point0.shift(299.45265842618784, 86.78060596475459 * sizeFactor) + points.point4Cp1 = points.point4.shift(84.35380802294482, 49.11521286943584 * sizeFactor) + points.point4Cp2 = points.point4.shift(184.39630340760462, 19.40463369919666 * sizeFactor) + points.point5 = points.point0.shift(342.8506386745285, 121.04758752176764 * sizeFactor) + points.point5Cp1 = points.point5.shift(137.52316754335672, 29.889370057597382 * sizeFactor) + points.point5Cp2 = points.point5.shift(196.75764739545923, 56.96390931984925 * sizeFactor) + points.point6 = points.point0.shift(1.1205493505415198, 54.26948752485138 * sizeFactor) + points.point6Cp2 = points.point6.shift(316.18924774003017, 44.726876316259826 * sizeFactor) + points.point7 = points.point0.shift(357.37806779049225, 43.287782602138435 * sizeFactor) + points.point7Cp1 = points.point7.shift(299.1399624138707, 19.59910745416729 * sizeFactor) + points.point8 = points.point0.shift(317.5381963475652, 36.1375990486363 * sizeFactor) + points.point8Cp1 = points.point8.shift(173.12090742697325, 12.479807891149623 * sizeFactor) + points.point8Cp2 = points.point8.shift(353.1201304168364, 15.075322060904695 * sizeFactor) + points.point9 = points.point0.shift(336.14503661026947, 8.388980629373263 * sizeFactor) + points.point9Cp2 = points.point9.shift(255.27121271777986, 18.645853640957277 * sizeFactor) + + points.point5a = new Path() + .move(points.point6) + .curve(points.point6Cp2, points.point5Cp1, points.point5) + .shiftAlong(65 * sizeFactor) + + const sp = new Path() + .move(points.point5) + .curve(points.point5Cp1, points.point6Cp2, points.point6) + .split(points.point5a) + + points.point5aCp1 = sp[1].ops[1].cp1.clone() + points.point6Cp2 = sp[1].ops[1].cp2.clone() + + points.point5 = points.point5.rotate(357, points.point0) + points.point5Cp2 = points.point5.shift(196.75764739545923, 56.96390931984925 * sizeFactor) + + paths.eyeBottom = new Path() + .move(points.point7) + .curve(points.point7Cp1, points.point8Cp2, points.point8) + .curve(points.point8Cp1, points.point9Cp2, points.point9) + .setText(complete ? 'eyeBottom' + ' (4)' : '', textAttribute) + .addClass('hidden') + + paths.mouthTop = new Path() + .move(points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .setText(complete ? 'mouthTop' + ' (16)' : '', textAttribute) + .addClass('hidden') + + paths.upperJaw = new Path() + .move(points.point4) + .curve(points.point4Cp1, points.point5Cp2, points.point5) + .setText(complete ? 'upperJaw' + ' (16)' : '', textAttribute) + .addClass('hidden') + + paths.nose = new Path() + .move(points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .setText(complete ? 'nose (10)' : '', textAttribute) + .addClass('hidden') + + store.set('templeToJaw', points.point5.dist(points.point5a)) + store.set('upperJaw', paths.upperJaw.length()) + + paths.seam1 = new Path() + .move(points.point9) + .line(points.point0) + .setText(complete ? '1' : '', textAttribute) + .addClass('hidden') + paths.seam2 = new Path() + .move(points.point6) + .line(points.point7) + .setText(complete ? '2' : '', textAttribute) + .addClass('hidden') + paths.seam5 = new Path() + .move(points.point5a) + .curve(points.point5aCp1, points.point6Cp2, points.point6) + .setText(complete ? '5' : '', textAttribute) + .addClass('hidden') + paths.seam7 = new Path() + .move(points.point0) + .line(points.point1) + .setText(complete ? '7' : '', textAttribute) + .addClass('hidden') + paths.seam8 = new Path() + .move(points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .setText(complete ? '8' : '', textAttribute) + .addClass('hidden') + + paths.seam = new Path() + .move(points.point0) + .join(paths.seam7) + .join(paths.nose) + .join(paths.seam8) + .join(paths.mouthTop) + .join(paths.upperJaw) + .line(points.point5a) + .join(paths.seam5) + .join(paths.seam2) + .join(paths.eyeBottom) + .join(paths.seam1) + .close() + + store.set('templeWidth', points.point6.dist(points.point7)) + store.set('noseBridgeWidth', points.point0.dist(points.point9)) + store.set('templeWidth', points.point6.dist(points.point7)) + store.set('mouthTop', paths.mouthTop.length()) + store.set('eyeBottom', paths.eyeBottom.length()) + store.set('noseSide', paths.nose.length()) + store.set('noseHeight', points.point1.dist(points.point2)) + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + points.title = points.point4Cp2.shiftFractionTowards(points.point0, 0.3) + macro('title', { + nr: 1, + at: points.title, + scale: 0.5, + title: 'cheek', + }) + + snippets.n1 = new Snippet('notch', points.point9) + snippets.n2 = new Snippet('notch', points.point5) + snippets.n3 = new Snippet('notch', points.point5a) + snippets.n4 = new Snippet('notch', points.point1) + snippets.n5 = new Snippet('bnotch', points.point7) + snippets.n6 = new Snippet('bnotch', points.point2) + + points.gridAnchor = points.point4.clone() + points.logo = points.point7 + .shiftFractionTowards(points.point5, 0.5) + .shiftFractionTowards(points.point4, 0.25) + snippets.logo = new Snippet('logo', points.logo).attr('data-scale', 0.3) + + if (sa) { + paths.sa = paths.seam.offset(sa).trim().attr('class', 'fabric sa') + } + + points.noseX = paths.nose.edge('right') + points.eyeBottomY = paths.eyeBottom.edge('bottom') + points.upperJaw = paths.upperJaw.shiftFractionAlong(0.42) + + macro('hd', { + from: points.noseX, + to: points.point4, + y: points.noseX.y + 5, + id: 'noseToBackOfJaw', + }) + macro('hd', { + from: points.point6, + to: points.point5, + y: points.point6.y - sa - 15, + id: 'cheekBoneToBackOfJaw', + }) + macro('hd', { + from: points.point6, + to: points.point5a, + y: points.point6.y - sa - 5, + id: 'cheekBoneWidth', + }) + macro('hd', { + from: points.point7, + to: points.point5, + y: points.point6.y - sa - 25, + id: 'rightEyeToBackOfJaw', + }) + macro('hd', { + from: points.point3, + to: points.point7, + y: points.point6.y - sa - 35, + id: 'leftToRightEye', + }) + macro('hd', { + from: points.point2, + to: points.point7, + y: points.point6.y - sa - 25, + id: 'bottomNoseToRigthEye', + }) + macro('hd', { + from: points.point1, + to: points.point7, + y: points.point6.y - sa - 15, + id: 'topNoseToRigthEye', + }) + macro('hd', { + from: points.point0, + to: points.point7, + y: points.point6.y - sa - 5, + id: 'foreheadToRightEye', + }) + macro('hd', { + from: points.point9, + to: points.point7, + y: points.point6.y - sa + 5, + id: 'eyeWidth', + }) + macro('hd', { + from: points.point3, + to: points.point4, + y: points.point4.y + sa + 15, + id: 'jawWidth', + }) + macro('hd', { + from: points.point4, + to: points.point5, + y: points.point4.y + sa + 15, + id: 'jawToRight', + }) + + macro('vd', { + from: points.eyeBottomY, + to: points.point4, + x: points.point4.x, + id: 'eyeToJaw', + }) + macro('vd', { + from: points.point6, + to: points.point5a, + x: points.point5.x + sa + 10, + id: 'cheekBoneHeight', + }) + macro('vd', { + from: points.point6, + to: points.point5, + x: points.point5.x + sa + 20, + id: 'cheekBoneToJawCorner', + }) + macro('vd', { + from: points.point5, + to: points.point4, + x: points.point5.x + sa + 20, + id: 'bottomToJaw', + }) + macro('vd', { + from: points.point3, + to: points.point2, + x: points.point2.x - sa - 10, + id: 'jawToBottomNose', + }) + macro('vd', { + from: points.point3, + to: points.point1, + x: points.point2.x - sa - 20, + id: 'jawToTopNose', + }) + macro('vd', { + from: points.point1, + to: points.point0, + x: points.point2.x - sa - 20, + id: 'topNoseToForehead', + }) + macro('vd', { + from: points.point6, + to: points.upperJaw, + x: points.point6.x, + id: 'cheekBoneToJaw', + }) + + return part + }, +} diff --git a/designs/skully/src/cheekbone.mjs b/designs/skully/src/cheekbone.mjs new file mode 100644 index 00000000000..357b1c37d77 --- /dev/null +++ b/designs/skully/src/cheekbone.mjs @@ -0,0 +1,94 @@ +import { cheek } from './cheek.mjs' + +export const cheekbone = { + name: 'skully.cheekbone', + after: cheek, + draft: ({ Point, Path, points, paths, sa, complete, store, macro, part }) => { + const textAttribute = 'text-xs center text-decoration="line-through"' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point0Cp1 = points.point0.shift(26.9653561519379, 19.25431213546719 * sizeFactor) + points.point1 = points.point0.shift(23.857094414377794, 57.23972922717229 * sizeFactor) + points.point1Cp1 = points.point1.shift(135.7075072577942, 32.47486987518195 * sizeFactor) + points.point1Cp2 = points.point1.shift(180.82587279494425, 29.902106313769938 * sizeFactor) + + paths.seam5 = new Path() + .move(points.point1) + .curve_(points.point1Cp1, points.point0) + .setText(complete ? '5' : '', textAttribute) + .addClass('hidden') + paths.seam6 = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .setText(complete ? '6' : '', textAttribute) + .attr('data-text-text-decoration', 'underline') + .addClass('hidden') + + paths.seam = new Path().move(points.point0).join(paths.seam6).join(paths.seam5).close() + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + points.gridAnchor = points.point0.clone() + points.title = points.point0 + .shiftFractionTowards(points.point1, 0.65) + .shiftFractionTowards(points.point1Cp2, 0.4) + macro('title', { + nr: 6, + at: points.title, + scale: 0.15, + rotation: 325, + title: 'cheekbone', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + points.pointY = paths.seam.edge('top') + + macro('hd', { + from: points.point0, + to: points.point1, + y: points.point0.y + sa + 15, + id: 'width', + }) + macro('hd', { + from: points.point0, + to: points.pointY, + y: points.pointY.y - sa - 15, + id: 'leftToTop', + }) + macro('hd', { + from: points.pointY, + to: points.point1, + y: points.pointY.y - sa - 15, + id: 'topToRight', + noStartMarker: true, + noEndMarker: true, + }) + + macro('vd', { + from: points.point1, + to: points.point0, + x: points.point1.x + sa + 15, + id: 'cornerToCornerHeight', + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + from: points.pointY, + to: points.point0, + x: points.point0.x - sa - 15, + id: 'height', + noStartMarker: true, + noEndMarker: true, + }) + + return part + }, +} diff --git a/designs/skully/src/eye.mjs b/designs/skully/src/eye.mjs new file mode 100644 index 00000000000..f3716fd300e --- /dev/null +++ b/designs/skully/src/eye.mjs @@ -0,0 +1,132 @@ +import { cheek } from './cheek.mjs' +import { forehead } from './forehead.mjs' + +export const eye = { + name: 'skully.eye', + after: [cheek, forehead], + draft: ({ Point, Path, points, paths, Snippet, snippets, sa, complete, store, macro, part }) => { + const textAttribute = 'text-xs center' + + const eyeCircumference = store.get('eyeBottom') + store.get('eyeTop') + const eyeDiameter = (eyeCircumference / Math.PI) * 2 + + const c = 0.55191502449351 + points.point0 = new Point(0, 0) + points.point2 = points.point0.shift(0, eyeDiameter / 2).shift(90, eyeDiameter / 2) + points.point0Cp1 = points.point0.shift(0, (eyeDiameter / 2) * c) + points.point2Cp2 = points.point2.shift(270, (eyeDiameter / 2) * c) + + const p = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point2Cp2, points.point2) + + points.point1 = p.shiftAlong(p.length() / 2) + + const sp = p.split(points.point1) + + points.p0 = sp[0].ops[0].to.clone() + points.p0Cp1 = sp[0].ops[1].cp1.clone() + points.p1Cp2 = sp[0].ops[1].cp2.clone() + points.p1 = sp[1].ops[0].to.clone() + points.p1Cp1 = sp[1].ops[1].cp1.clone() + points.p2Cp2 = sp[1].ops[1].cp2.clone() + points.p2 = sp[1].ops[1].to.clone() + + points.p0Cp1 = points.p0.shift(0, (eyeDiameter / 2) * c * 0.4) + points.p2Cp2 = points.p2.shift(270, (eyeDiameter / 2) * c * 0.4) + points.p1Cp1 = points.p1.shift(45, (eyeDiameter / 2) * c * 0.7) + points.p1Cp2 = points.p1.shift(225, (eyeDiameter / 2) * c * 0.7) + + points.p0Cp2 = points.p0Cp1.flipX() + points.p4 = points.p2.flipX() + points.p4Cp1 = points.p2Cp2.flipX() + points.p3 = points.p1.flipX() + points.p3Cp2 = points.p1Cp1.flipX() + points.p3Cp1 = points.p1Cp2.flipX() + + paths.eye = new Path() + .move(points.p4) + .curve(points.p4Cp1, points.p3Cp2, points.p3) + .curve(points.p3Cp1, points.p0Cp2, points.p0) + .curve(points.p0Cp1, points.p1Cp2, points.p1) + .curve(points.p1Cp1, points.p2Cp2, points.p2) + + points.pointNotch = paths.eye.shiftAlong(store.get('eyeTop')) + + const ps = paths.eye.split(points.pointNotch) + paths.eyeTop = ps[0].clone().setText(complete ? 'eyeTop' + ' (4)' : '', textAttribute) + paths.eyeBottom = ps[1].clone().setText(complete ? 'eyeBottom' + ' (4)' : '', textAttribute) + + paths.seam = new Path() + .move(points.p4) + .join(paths.eyeTop) + .join(paths.eyeBottom) + .line(points.p4) + .close() + + points.title = points.p4 + .shiftFractionTowards(points.p1, 0.45) + .shiftFractionTowards(points.p0, 0.5) + + macro('title', { + nr: 9, + at: points.title, + scale: 0.3, + title: 'eye', + }) + + points.ps3a = points.p2.shiftFractionTowards(points.p4, 0.25) + points.ps3aCp1 = points.ps3a.shift(270, points.p4.dist(points.p2) / 6) + points.ps3 = points.p2.shiftFractionTowards(points.p4, 0.5) + points.ps3cross1 = points.ps3.shiftFractionTowards(points.p0, 0.1) + points.ps3cross2 = points.ps3.shiftFractionTowards(points.p0, -0.1) + points.ps3b = points.p2.shiftFractionTowards(points.p4, 0.75) + points.ps3bCp1 = points.ps3b.shift(270, points.p4.dist(points.p2) / 6) + + points.gridAnchor = points.ps3.clone() + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + macro('sewtogether', { + from: points.ps3a, + to: points.ps3b, + hinge: true, + }) + + snippets.n1 = new Snippet('notch', points.p2) + snippets.n2 = new Snippet('notch', points.p4) + snippets.n3 = new Snippet('bnotch', points.pointNotch) + + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + macro('hd', { + from: points.p4, + to: points.pointNotch, + y: points.p0.y + sa + 15, + id: 'leftToNotch', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.p4, + to: points.p2, + y: points.p2.y - sa - 15, + id: 'width', + }) + macro('vd', { + from: points.p2, + to: points.p0, + x: points.p2.x + sa + 15, + id: 'height', + }) + + return part + }, +} diff --git a/designs/skully/src/forehead.mjs b/designs/skully/src/forehead.mjs new file mode 100644 index 00000000000..fb29d67da00 --- /dev/null +++ b/designs/skully/src/forehead.mjs @@ -0,0 +1,246 @@ +import { cheek } from './cheek.mjs' + +export const forehead = { + name: 'skully.forehead', + after: cheek, + draft: ({ Point, Path, points, paths, Snippet, snippets, sa, complete, store, macro, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point0Cp1 = points.point0.shift(241.92955090220636, 37.666339998598225 * sizeFactor) + points.point0Cp2 = points.point0.shift(333.9339465987448, 38.41308527689494 * sizeFactor) + points.point1 = points.point0.shift(255.81688050452775, 105.61426225557886 * sizeFactor) + points.point1Cp2 = points.point1.shift(122.25481630103288, 16.221492810466046 * sizeFactor) + points.point2 = points.point0.shift(260.36453213741225, 104.78002255825727 * sizeFactor) + points.point2Cp1 = points.point2.shift(104.52547665837686, 6.962227517109787 * sizeFactor) + points.point3 = points.point0.shift(266.83135324063875, 91.72676538115797 * sizeFactor) + points.point3Cp1 = points.point3.shift(10.824271939403667, 7.255955140434657 * sizeFactor) + points.point3Cp2 = points.point3.shift(190.82219510192064, 8.8744083082141 * sizeFactor) + points.point4 = points.point0.shift(279.23029819067256, 99.89481626481647 * sizeFactor) + points.point4Cp2 = points.point4.shift(109.3914373863736, 10.114793621226355 * sizeFactor) + points.point5 = points.point0.shift(285.6356187763194, 96.73748550220853 * sizeFactor) + points.point5Cp1 = points.point5.shift(322.25160644653687, 21.112881376069897 * sizeFactor) + points.point6 = points.point0.shift(299.0865415436474, 123.293691591622 * sizeFactor) + points.point6Cp1 = points.point6.shift(102.44153405115529, 30.07799330075059 * sizeFactor) + points.point6Cp2 = points.point6.shift(171.33241486296131, 9.49614011059247 * sizeFactor) + points.point7 = points.point0.shift(301.8945694309706, 53.41879968784397 * sizeFactor) + points.point7Cp1 = points.point7.shift(330.8064552671208, 26.14383661592154 * sizeFactor) + points.point7Cp2 = points.point7.shift(306.82890730505164, 20.883100248765764 * sizeFactor) + points.point8 = points.point0.shift(315.99934749521526, 121.10503287183268 * sizeFactor) + points.point8Cp2 = points.point8.shift(138.225501502238, 23.326308173390803 * sizeFactor) + points.point9 = points.point0.shift(325.07215199461336, 129.7747702101221 * sizeFactor) + points.point9Cp1 = points.point9.shift(126.07355572621562, 42.01723333347864 * sizeFactor) + + paths.firstSeam = new Path() + .move(points.point9) + .curve(points.point9Cp1, points.point0Cp2, points.point0) + .setText(complete ? '20' : '', textAttribute) + .addClass('hidden') + + store.set('firstSeam', paths.firstSeam.length()) + store.set( + 'templeTop', + new Path().move(points.point8).line(points.point9).length() + + new Path() + .move(points.point5) + .curve(points.point5Cp1, points.point6Cp2, points.point6) + .length() + ) + + paths.eyeTop = new Path() + .move(points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .setText(complete ? 'eyeTop' + ' (4)' : '', textAttribute) + .addClass('hidden') + + paths.seam1 = new Path() + .move(points.point1) + .line(points.point2) + .setText(complete ? '1' : '', textAttribute) + .addClass('hidden') + + paths.seam2 = new Path() + .move(points.point4) + .line(points.point5) + .setText(complete ? '2' : '', textAttribute) + .addClass('hidden') + + paths.seam6a = new Path() + .move(points.point5) + .curve(points.point5Cp1, points.point6Cp2, points.point6) + .setText(complete ? '6' : '', textAttribute) + .attr('data-text-text-decoration', 'underline') + .addClass('hidden') + + paths.seam6b = new Path() + .move(points.point8) + .line(points.point9) + .setText(complete ? '6' : '', textAttribute) + .attr('data-text-text-decoration', 'underline') + .addClass('hidden') + + paths.seam7 = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .setText(complete ? '7' : '', textAttribute) + .addClass('hidden') + + paths.seam = new Path() + .move(points.point0) + .join(paths.seam7) + .join(paths.seam1) + .join(paths.eyeTop) + .join(paths.seam2) + .join(paths.seam6a) + .line(points.point8) + .join(paths.seam6b) + .curve(points.point9Cp1, points.point0Cp2, points.point0) + .close() + + paths.dart = new Path() + .move(points.point6) + .curve(points.point6Cp1, points.point7Cp2, points.point7) + .curve(points.point7Cp1, points.point8Cp2, points.point8) + + store.set('eyeTop', paths.eyeTop.length()) + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + points.gridAnchor = points.point0.clone() + points.title = points.point3Cp1.shiftFractionTowards(points.point0, 0.3) + macro('title', { + nr: 2, + at: points.title, + scale: 0.5, + title: 'forehead', + }) + + snippets.n1 = new Snippet('notch', points.point2) + snippets.n2 = new Snippet('bnotch', points.point4) + + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + paths.sa = paths.seam.offset(sa).trim().attr('class', 'fabric sa') + } + + points.pointX = paths.seam.edge('left') + + macro('hd', { + from: points.point0, + to: points.point9, + y: points.point0.y - sa - 15, + id: 'topToRight', + }) + macro('hd', { + from: points.pointX, + to: points.point0, + y: points.point0.y - sa - 15, + id: 'leftToTop', + }) + macro('hd', { + from: points.point6, + to: points.point8, + y: points.point6.y + sa + 5, + id: 'dartWidth', + }) + macro('hd', { + from: points.point6, + to: points.point9, + y: points.point6.y + sa + 15, + id: 'dartToRight', + }) + macro('hd', { + from: points.point5, + to: points.point6, + y: points.point6.y + sa + 5, + id: 'cheekBoneToDart', + }) + macro('hd', { + from: points.point4, + to: points.point6, + y: points.point6.y + sa + 15, + id: 'rightEyeToDart', + }) + macro('hd', { + from: points.point2, + to: points.point6, + y: points.point6.y + sa + 25, + id: 'leftEyeToDart', + }) + macro('hd', { + from: points.point1, + to: points.point6, + y: points.point6.y + sa + 35, + id: 'leftCornerToDart', + }) + macro('hd', { + from: points.pointX, + to: points.point6, + y: points.point6.y + sa + 45, + id: 'leftToDart', + }) + macro('hd', { + from: points.point0, + to: points.point7, + y: points.point7.y, + id: 'topToDartPoint', + }) + + macro('vd', { + from: points.point5, + to: points.point0, + x: points.pointX.x - sa - 10, + id: 'cheekBoneToTop', + }) + macro('vd', { + from: points.point4, + to: points.point0, + x: points.pointX.x - sa - 20, + id: 'rightEyeToTop', + }) + macro('vd', { + from: points.point1, + to: points.point0, + x: points.pointX.x - sa - 30, + id: 'leftCornerToTop', + }) + macro('vd', { + from: points.point2, + to: points.point0, + x: points.pointX.x - sa - 40, + id: 'leftEyeToTop', + }) + macro('vd', { + from: points.point0, + to: points.point9, + x: points.point9.x + sa + 10, + id: 'rightToTop', + }) + macro('vd', { + from: points.point0, + to: points.point8, + x: points.point9.x + sa + 20, + id: 'rightDartToTop', + }) + macro('vd', { + from: points.point0, + to: points.point6, + x: points.point9.x + sa + 30, + id: 'leftDartToTop', + }) + macro('vd', { + from: points.point0, + to: points.point7, + x: points.point0.x, + id: 'dartPointToTop', + }) + + return part + }, +} diff --git a/designs/skully/src/head1.mjs b/designs/skully/src/head1.mjs new file mode 100644 index 00000000000..180a6d86ea3 --- /dev/null +++ b/designs/skully/src/head1.mjs @@ -0,0 +1,132 @@ +import { cheek } from './cheek.mjs' +import { forehead } from './forehead.mjs' + +export const head1 = { + name: 'skully.head1', + after: [cheek, forehead], + draft: ({ Point, Path, points, paths, Snippet, snippets, sa, complete, store, macro, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point0Cp2 = points.point0.shift(270.9766531413822, 42.41716221059584 * sizeFactor) + points.point2 = points.point0.shift(254.08224234639044, 161.93553876093907 * sizeFactor) + points.point2Cp2 = points.point2.shift(105.78717948197567, 54.27380801428633 * sizeFactor) + points.point2Cp1 = points.point2.shift(75.48077210575057, 107.97156739510459 * sizeFactor) + points.point1 = points.point0.shift(180, 72.005 * sizeFactor) + points.point1Cp1 = points.point1.shift(268.60871199245156, 55.97160080799901 * sizeFactor) + + points.point0 = points.point0.shift(270, 5) + points.point0Cp2 = points.point0.shift(270.9766531413822, 42.41716221059584 * sizeFactor) + + paths.firstSeam = new Path() + .move(points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .setText(complete ? '20' : '', textAttribute) + .addClass('hidden') + + points.fs1 = paths.firstSeam.shiftAlong(store.get('firstSeam')) + points.fs2 = paths.firstSeam.shiftAlong(store.get('firstSeam') + store.get('templeToJaw')) + + points.gridAnchor = points.point0.clone() + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + store.set( + 'upperJawToLowerJaw', + paths.firstSeam.length() - store.get('firstSeam') - store.get('templeToJaw') + ) + + paths.secondSeam = new Path() + .move(points.point2) + .curve(points.point2Cp1, points.point0Cp2, points.point0) + .setText(complete ? '17' : '', textAttribute) + .addClass('hidden') + + paths.top = new Path() + .move(points.point0) + .line(points.point1) + .setText(complete ? '19' : '', textAttribute) + .addClass('hidden') + + store.set('secondSeam', paths.secondSeam.length()) + + paths.seam = new Path() + .move(points.point0) + .join(paths.top) + .join(paths.firstSeam) + .join(paths.secondSeam) + .close() + + points.title = points.point2.shiftFractionTowards(points.point1, 0.65).shift(0, 10 * sizeFactor) + macro('title', { + nr: 3, + at: points.title, + scale: 0.5, + title: 'head' + '1', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + snippets.n1 = new Snippet('notch', points.fs1) + snippets.n2 = new Snippet('notch', points.fs2) + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + macro('hd', { + from: points.point1, + to: points.point2, + y: points.point2.y + sa + 10, + id: 'leftToBottom', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.point2, + to: points.point0, + y: points.point2.y + sa + 10, + id: 'bottomToRight', + }) + + macro('vd', { + from: points.point0, + to: points.point2, + x: points.point0.x + sa + 15, + id: 'bottomToRight', + }) + macro('vd', { + from: points.point2, + to: points.point1, + x: points.point1.x - sa - 15, + id: 'bottomToLeft', + }) + + macro('ld', { + from: points.point1, + to: points.point0, + d: 5, + id: 'topWidth', + }) + macro('ld', { + from: points.point2, + to: points.fs2, + d: 5, + noStartMarker: true, + noEndMarker: true, + }) + macro('ld', { + from: points.point2, + to: points.fs1, + d: 15, + id: 'bottomToSecondNotch', + noStartMarker: true, + noEndMarker: true, + }) + + return part + }, +} diff --git a/designs/skully/src/head2.mjs b/designs/skully/src/head2.mjs new file mode 100644 index 00000000000..675919e4fb0 --- /dev/null +++ b/designs/skully/src/head2.mjs @@ -0,0 +1,229 @@ +import { cheek } from './cheek.mjs' +import { head1 } from './head1.mjs' + +export const head2 = { + name: 'skully.head2', + after: [cheek, head1], + draft: ({ Point, Path, points, paths, sa, complete, log, store, macro, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point0Cp2 = points.point0.shift(0, 15 * sizeFactor) + points.point1 = points.point0.shift(257.7901473243395, 66.12988849226953 * sizeFactor) + points.point1Cp1 = points.point1.shift(270, 30.242724116719366 * sizeFactor) + points.point1Cp2 = points.point1.shift(90, 18.83053830882166 * sizeFactor) + points.point2 = points.point0.shift(272.3327760921532, 153.20596573567235 * sizeFactor) + points.point3 = points.point0.shift(282.5001868336755, 164.15422647315543 * sizeFactor) + points.point3Cp1 = points.point3.shift(81.44269285511335, 54.758598457228615 * sizeFactor) + points.point4 = points.point0.shift(340.927384878832, 52.16879559660159 * sizeFactor) + points.point4Cp2 = points.point4.shift(274.04106104609286, 50.57373626695976 * sizeFactor) + + const secondSeam = store.get('secondSeam') + + let iterations = 0 + var p + do { + iterations++ + + p = new Path() + .move(points.point0) + ._curve(points.point1Cp2, points.point1) + .curve_(points.point1Cp1, points.point2) + + if (secondSeam - p.length() > 0.1 || secondSeam - p.length() < -0.1) { + points.point0 = points.point0.shift(90, secondSeam - p.length()) + points.point1 = points.point1.shift(90, secondSeam - p.length()) + points.point1Cp1 = points.point1.shift(270, 30.242724116719366 * sizeFactor) + points.point1Cp2 = points.point1.shift(90, 18.83053830882166 * sizeFactor) + points.point0Cp2 = points.point0.shift(0, 15 * sizeFactor) + } + } while (iterations < 100 && (secondSeam - p.length() > 1 || secondSeam - p.length() < -1)) + if (iterations >= 100) { + log.error('Generating head2 could not be made to fit in 100 iterations!') + } + + points.dartPoint0 = new Path() + .move(points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .shiftAlong(99.23273836900117 * sizeFactor) + points.dartPoint1 = points.point0.shift(285.96197961706986, 65.4910471438654 * sizeFactor) + points.dartPoint1Cp1 = points.dartPoint1.shift( + 354.74216521134053, + 13.662486193954589 * sizeFactor + ) + points.dartPoint1Cp2 = points.dartPoint1.shift( + 356.55115250146685, + 13.680777207454268 * sizeFactor + ) + points.dartPoint2 = new Path() + .move(points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .shiftAlong(92.81578231343269 * sizeFactor) + + paths.secondSeam = new Path() + .move(points.point0) + ._curve(points.point1Cp2, points.point1) + .curve_(points.point1Cp1, points.point2) + .setText(complete ? '17' : '', textAttribute) + .addClass('hidden') + + paths.thirdSeam = new Path() + .move(points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .setText(complete ? '18' : '', textAttribute) + .addClass('hidden') + + paths.top = new Path() + .move(points.point4) + .curve(points.point4, points.point0Cp2, points.point0) + .setText(complete ? '19' : '', textAttribute) + .addClass('hidden') + + paths.bottom = new Path() + .move(points.point2) + .line(points.point3) + .setText(complete ? '21' : '', textAttribute) + .addClass('hidden') + + store.set('thirdSeam', paths.thirdSeam.length() - points.dartPoint0.dist(points.dartPoint2)) + store.set('head2width', points.point2.dist(points.point3)) + paths.dart = new Path() + .move(points.dartPoint0) + ._curve(points.dartPoint1Cp2, points.dartPoint1) + .curve_(points.dartPoint1Cp1, points.dartPoint2) + + paths.seam = new Path() + .move(points.point0) + .join(paths.secondSeam) + .join(paths.bottom) + .join(paths.thirdSeam) + .join(paths.top) + .close() + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + points.gridAnchor = points.dartPoint1.clone() + points.title = points.dartPoint1.shiftFractionTowards(points.point2, 0.35) + macro('title', { + nr: 4, + at: points.title, + scale: 0.5, + title: 'head' + '2', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + points.pointX = paths.seam.edge('right') + + macro('hd', { + from: points.point0, + to: points.point4, + y: points.point0.y - sa - 15, + id: 'topWidth', + }) + macro('hd', { + from: points.point0, + to: points.pointX, + y: points.point0.y - sa - 25, + id: 'topToRight', + }) + macro('hd', { + from: points.point1, + to: points.pointX, + y: points.point0.y - sa - 35, + id: 'totalWidth', + }) + macro('hd', { + from: points.point3, + to: points.pointX, + y: points.point3.y + sa + 15, + id: 'bottomRightToRight', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.point2, + to: points.point3, + y: points.point3.y + sa + 15, + id: 'bottomWidth', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.point1, + to: points.point2, + y: points.point3.y + sa + 15, + id: 'leftToBottomLeft', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.point0, + to: points.dartPoint1, + y: points.dartPoint1.y, + id: 'leftTopToDartPoint', + noStartMarker: true, + noEndMarker: true, + }) + + macro('vd', { + from: points.point1, + to: points.point0, + x: points.point1.x - sa - 15, + id: 'leftToTop', + }) + macro('vd', { + from: points.point2, + to: points.point1, + x: points.point1.x - sa - 15, + id: 'leftToBottomLeft', + }) + macro('vd', { + from: points.point3, + to: points.point1, + x: points.point1.x - sa - 25, + id: 'leftToBottomRight', + }) + macro('vd', { + from: points.point0, + to: points.point4, + x: points.point4.x + sa + 15, + id: 'topRightToTopLeft', + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + from: points.point4, + to: points.dartPoint0, + x: points.point4.x + sa + 15, + id: 'topDartToTopRight', + }) + macro('vd', { + from: points.point4, + to: points.dartPoint2, + x: points.point4.x + sa + 25, + id: 'bottomDartToTopRight', + }) + macro('vd', { + from: points.dartPoint2, + to: points.point3, + x: points.point4.x + sa + 25, + id: 'bottomRightToBottomDart', + }) + macro('vd', { + from: points.point0, + to: points.dartPoint1, + x: points.dartPoint1.x, + id: 'dartPointToTopLeft', + }) + + return part + }, +} diff --git a/designs/skully/src/head3.mjs b/designs/skully/src/head3.mjs new file mode 100644 index 00000000000..7d98fe58c53 --- /dev/null +++ b/designs/skully/src/head3.mjs @@ -0,0 +1,210 @@ +import { cheek } from './cheek.mjs' +import { head2 } from './head2.mjs' +import { jawfloor } from './jawfloor.mjs' + +export const head3 = { + name: 'skully.head3', + after: [cheek, head2, jawfloor], + draft: ({ Point, Path, points, paths, sa, complete, log, store, macro, utils, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + + points.point0Cp2 = points.point0.shift(176.85941213458383, 24.45873430903567 * sizeFactor) + points.point0Cp1 = points.point0.shift(80.97143471134606, 19.435805231582247 * sizeFactor) + points.point5 = points.point0.shift(174.83014371859687, 57.4195861357429 * sizeFactor) + points.point5Cp1 = points.point5.shift(359.48476820979687, 24.91000716579583 * sizeFactor) + points.point4 = points.point0.shift(128.37, 82.29999999999998 * sizeFactor) + points.point4Cp1 = points.point4.shift(280, 20 * sizeFactor) + points.point3 = points.point0.shift(122.10525602099625, 99.24923435875874 * sizeFactor) + points.point3Cp2 = points.point3.shift(75, 20 * sizeFactor) + points.point2 = points.point0.shift(92.0479806305003, 131.18279286933938 * sizeFactor) + points.point2Cp2 = points.point2.shift(286.4630945432234, 43.38779202725112 * sizeFactor) + points.point2Cp1 = points.point2.shift(208.11590506019132, 16.689416556608613 * sizeFactor) + points.point1 = points.point0.shift(80.96712201455671, 37.967861804426136 * sizeFactor) + points.point1Cp2 = points.point1.shift(266.0887375411011, 17.372462375840676 * sizeFactor) + points.point1Cp1 = points.point1.shift(86.08762325510818, 17.602020395397776 * sizeFactor) + + points.dartPoint0 = points.point4.clone() + points.dartPoint0Cp1 = points.dartPoint0.shift(10, 15.674240045373793 * sizeFactor) + points.dartPoint1 = points.point0.shift(93.69495535762911, 79.06034303618978 * sizeFactor) + points.dartPoint1Cp1 = points.dartPoint1.shift( + 190.57289744169927, + 19.19488590744941 * sizeFactor + ) + points.dartPoint1Cp2 = points.dartPoint1.shift( + 206.69161019830457, + 18.019174148667343 * sizeFactor + ) + points.dartPoint2 = points.point3.clone() + points.dartPoint2Cp2 = points.dartPoint2.shift(345, 15.211717490145492 * sizeFactor) + + let lowerWidth = store.get('halfOfBack') - store.get('head2width') + let tsAdjustment = + store.get('thirdSeam') - + new Path() + .move(points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .length() + + let x = utils.circlesIntersect(points.dartPoint0, tsAdjustment, points.point0, lowerWidth) + if (x) { + points.point5 = x[0].clone() + } else { + log.error('Could not make the lower part of head3 fit the other parts!') + } + + points.point5Cp1 = points.point5.shift(359.48476820979687, 24.91000716579583 * sizeFactor) + + points.gridAnchor = points.dartPoint1.clone() + + paths.thirdSeam1 = new Path() + .move(points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .setText(complete ? '18' : '', textAttribute) + .addClass('hidden') + + paths.thirdSeam2 = new Path() + .move(points.point4) + .line(points.point5) + .setText(complete ? '18' : '', textAttribute) + .addClass('hidden') + + paths.back = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .setText(complete ? '19' : '', textAttribute) + .addClass('hidden') + + paths.bottom = new Path() + .move(points.point5) + .line(points.point0) + .setText(complete ? '21' : '', textAttribute) + .addClass('hidden') + + paths.dart = new Path() + .move(points.dartPoint0) + .curve(points.dartPoint0Cp1, points.dartPoint1Cp2, points.dartPoint1) + .curve(points.dartPoint1Cp1, points.dartPoint2Cp2, points.dartPoint2) + + paths.seam = new Path() + .move(points.point0) + .join(paths.back) + .join(paths.thirdSeam1) + .line(points.point4) + .join(paths.thirdSeam2) + .join(paths.bottom) + .close() + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + points.title = points.point4 + .shiftFractionTowards(points.point1, 0.25) + .shiftFractionTowards(points.point0, 0.25) + macro('title', { + nr: 5, + at: points.title, + scale: 0.5, + title: 'head' + '3', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + // .attr('data-text', 'hello') + // .attr('data-text-class', 'center') + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + points.pointX = new Path() + .move(points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .edge('right') + + macro('hd', { + from: points.dartPoint2, + to: points.point2, + y: points.point2.y - sa - 15, + id: 'topDartToTop', + }) + macro('hd', { + from: points.dartPoint2, + to: points.pointX, + y: points.point2.y - sa - 25, + id: 'totalWidth', + }) + macro('hd', { + from: points.dartPoint2, + to: points.point5, + y: points.point0.y + sa + 15, + id: 'topDartToBottomLeft', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.dartPoint0, + to: points.point5, + y: points.point0.y + sa + 5, + id: 'bottomDartToBottomLeft', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.dartPoint2, + to: points.point0, + y: points.point0.y + sa + 25, + id: 'topDartToBottomRight', + }) + macro('hd', { + from: points.dartPoint2, + to: points.dartPoint1, + y: points.dartPoint2.y, + id: 'topDartToDartPoint', + }) + + macro('vd', { + from: points.point2, + to: points.dartPoint1, + x: points.pointX.x + sa + 15, + id: 'dartPointToTop', + }) + macro('vd', { + from: points.dartPoint1, + to: points.point0, + x: points.pointX.x + sa + 15, + id: 'dartPointToBottom', + }) + macro('vd', { + from: points.point2, + to: points.pointX, + x: points.pointX.x + sa + 25, + id: 'rightToTop', + }) + macro('vd', { + from: points.dartPoint2, + to: points.point2, + x: points.dartPoint2.x - sa - 15, + id: 'topDartToTop', + }) + macro('vd', { + from: points.dartPoint0, + to: points.dartPoint2, + x: points.dartPoint2.x - sa - 15, + id: 'dartHeight', + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + from: points.point5, + to: points.dartPoint0, + x: points.dartPoint2.x - sa - 15, + id: 'bottomDartToTop', + }) + + return part + }, +} diff --git a/designs/skully/src/index.mjs b/designs/skully/src/index.mjs new file mode 100644 index 00000000000..0a31fa45090 --- /dev/null +++ b/designs/skully/src/index.mjs @@ -0,0 +1,53 @@ +// Skully + +import { Design } from '@freesewing/core' +import { data } from '../data.mjs' +// Parts +import { cheek } from './cheek.mjs' +import { cheekbone } from './cheekbone.mjs' +import { eye } from './eye.mjs' +import { forehead } from './forehead.mjs' +import { head1 } from './head1.mjs' +import { head2 } from './head2.mjs' +import { head3 } from './head3.mjs' +import { jawfloor } from './jawfloor.mjs' +import { lowerjaw } from './lowerjaw.mjs' +import { lowermouth } from './lowermouth.mjs' +import { nose } from './nose.mjs' +import { uppermouth } from './uppermouth.mjs' + +// Create new design +const Skully = new Design({ + data, + parts: [ + cheek, + cheekbone, + eye, + forehead, + head1, + head2, + head3, + jawfloor, + lowerjaw, + lowermouth, + nose, + uppermouth, + ], +}) + +// Named exports +export { + cheek, + cheekbone, + eye, + forehead, + head1, + head2, + head3, + jawfloor, + lowerjaw, + lowermouth, + nose, + uppermouth, + Skully, +} diff --git a/designs/skully/src/jawfloor.mjs b/designs/skully/src/jawfloor.mjs new file mode 100644 index 00000000000..02e57e54b6e --- /dev/null +++ b/designs/skully/src/jawfloor.mjs @@ -0,0 +1,188 @@ +import { cheek } from './cheek.mjs' +import { lowerjaw } from './lowerjaw.mjs' + +export const jawfloor = { + name: 'skully.jawfloor', + after: [cheek, lowerjaw], + draft: ({ Point, Path, points, paths, sa, complete, store, macro, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point0Cp1 = points.point0.shift(271.5282081165893, 13.423774618191423 * sizeFactor) + points.point1 = points.point0.shift(329.79784303240206, 56.7574974166409 * sizeFactor) + points.point1Cp1 = points.point1.shift(0.11113474162861184, 14.951028125182583 * sizeFactor) + points.point1Cp2 = points.point1.shift(180.11102743493262, 10.32101937794903 * sizeFactor) + points.point2 = points.point0.shift(341.7834753138606, 84.52734739124374 * sizeFactor) + points.point2Cp1 = points.point2.shift(0.270382570357072, 8.900099100571891 * sizeFactor) + points.point2Cp2 = points.point2.shift(180.28237864410448, 8.319101033164598 * sizeFactor) + points.point3 = points.point0.shift(343.81344080631544, 113.99173416524552 * sizeFactor) + points.point3Cp1 = points.point3.shift(339.59546305762336, 4.204834955143868 * sizeFactor) + points.point3Cp2 = points.point3.shift(159.590412018152, 8.47076366096944 * sizeFactor) + points.point4 = points.point0.shift(340.4669995939806, 139.17462884448446 * sizeFactor) + points.point4Cp2 = points.point4.shift(166.50426671920425, 8.612823288562234 * sizeFactor) + points.point5 = points.point0.shift(3.560698409188234, 135.3172211952344 * sizeFactor) + + points.point6 = points.point0.shift(90.34672828513591, 8.097148263432018 * sizeFactor) + points.point0Cp2 = points.point0.shift(89.35665584015415, 4.809303171978241 * sizeFactor) + + points.point5 = points.point5.shift(0, points.point4.dist(points.point5) / 3) + points.point5Cp2 = points.point5.shift(270, points.point4.dist(points.point5) / 3) + + points.gridAnchor = points.point5.clone() + + macro('mirror', { + mirror: [points.point5, points.point6], + points: [ + 'point0', + 'point0Cp1', + 'point0Cp2', + 'point1Cp2', + 'point1', + 'point1Cp1', + 'point2Cp2', + 'point2', + 'point2Cp1', + 'point3Cp2', + 'point3', + 'point3Cp1', + 'point4Cp2', + 'point4', + 'point4', + 'point5Cp2', + 'point5', + 'point6', + ], + prefix: 'm', + }) + + paths.bottomJaw1 = new Path() + .move(points.point6) + ._curve(points.point0Cp2, points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .setText(complete ? 'jawBottom' + ' (15)' : '', textAttribute) + .addClass('hidden') + + paths.bottomJaw2 = new Path() + .move(points.mPoint4) + .curve(points.mPoint4Cp2, points.mPoint3Cp1, points.mPoint3) + .curve(points.mPoint3Cp2, points.mPoint2Cp1, points.mPoint2) + .curve(points.mPoint2Cp2, points.mPoint1Cp1, points.mPoint1) + .curve(points.mPoint1Cp2, points.mPoint0Cp1, points.mPoint0) + .curve_(points.mPoint0Cp2, points.point6) + .setText(complete ? 'jawBottom' + ' (15)' : '', textAttribute) + .addClass('hidden') + + paths.back = new Path() + .move(points.point4) + .curve(points.point4, points.point5Cp2, points.point5) + .curve(points.mPoint5Cp2, points.mPoint4, points.mPoint4) + .setText(complete ? '21' : '', textAttribute) + .addClass('hidden') + + paths.seam = new Path() + .move(points.point6) + .join(paths.bottomJaw1) + .join(paths.back) + .join(paths.bottomJaw2) + .close() + + store.set( + 'backOfLowerJaw', + new Path().move(points.point4).curve(points.point4, points.point5Cp2, points.point5).length() + ) + + store.cutlist.addCut({ cut: 1, from: 'Fabric' }) + + points.title = points.point6.shiftFractionTowards(points.point5, 0.5) + macro('title', { + nr: 8, + at: points.title, + scale: 0.5, + title: 'jawfloor', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + macro('hd', { + from: points.mPoint0, + to: points.mPoint5, + y: points.mPoint4.y - sa - 15, + id: 'width', + }) + macro('hd', { + from: points.point4, + to: points.point5, + y: points.point4.y + sa + 15, + id: 'bottomRightToRight', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.point2, + to: points.point4, + y: points.point4.y + sa + 15, + id: 'indentToBottomRight', + }) + macro('hd', { + from: points.point1, + to: points.point2, + y: points.point4.y + sa + 15, + id: 'outdentToIndent', + }) + macro('hd', { + from: points.point0, + to: points.point1, + y: points.point4.y + sa + 15, + id: 'leftToOutdent', + }) + + macro('vd', { + from: points.point1, + to: points.mPoint1, + x: points.mPoint1.x, + id: 'outdentHeight', + }) + macro('vd', { + from: points.point2, + to: points.mPoint2, + x: points.mPoint2.x, + id: 'indentHeight', + }) + macro('vd', { + from: points.point3, + to: points.mPoint3, + x: points.mPoint3.x, + id: 'anotherHeight', + }) + macro('vd', { + from: points.point4, + to: points.mPoint4, + x: points.mPoint4.x, + id: 'totalHeight', + }) + macro('vd', { + from: points.mPoint4, + to: points.point5, + x: points.point5.x + sa + 15, + id: 'middleToTop', + }) + macro('vd', { + from: points.mPoint5, + to: points.point4, + x: points.mPoint5.x + sa + 15, + id: 'bottomToMiddle', + }) + + return part + }, +} diff --git a/designs/skully/src/lowerjaw.mjs b/designs/skully/src/lowerjaw.mjs new file mode 100644 index 00000000000..ffeddf8e0cb --- /dev/null +++ b/designs/skully/src/lowerjaw.mjs @@ -0,0 +1,195 @@ +import { cheek } from './cheek.mjs' +import { uppermouth } from './uppermouth.mjs' + +export const lowerjaw = { + name: 'skully.lowerjaw', + after: [cheek, uppermouth], + draft: ({ Point, Path, points, paths, sa, complete, log, store, macro, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point1 = points.point0.shift(174.91311161963839, 43.0264648094635 * sizeFactor) + points.point2 = points.point0.shift(240.9901082422603, 82.64382533498798 * sizeFactor) + points.point3 = points.point0.shift(251.1601763775522, 106.01579184725264 * sizeFactor) + points.point4 = points.point0.shift(276.6440430845334, 116.75813357963548 * sizeFactor) + points.point5 = points.point0.shift(264.48800048134507, 50.78381912578058 * sizeFactor) + + const mouthTop = store.get('mouthTop') + + points.point0 = new Point(0, 0) + points.point0Cp2 = points.point0.shift(354.9481781658739, 16.659715303689914 * sizeFactor) + points.point1 = points.point0.shift(264.91311161963836, 43.0264648094635 * sizeFactor) + points.point1Cp1 = points.point1.shift(0, 53.02160375733651 * sizeFactor) + points.point2 = points.point0.shift(331.14662128979205, 83.05325951149062 * sizeFactor) + points.point2Cp1 = points.point2.shift(23.491413537740165, 11.818521142681087 * sizeFactor) + points.point2Cp2 = points.point2.shift(203.48599545649284, 6.360957553702122 * sizeFactor) + points.point3 = points.point0.shift(341.2414817357221, 106.45865437980989 * sizeFactor) + points.point3Cp1 = points.point3.shift(83.22770461819215, 15.755934754878917 * sizeFactor) + points.point3Cp2 = points.point3.shift(263.2247839478168, 8.959567958333654 * sizeFactor) + points.point4 = points.point0.shift(6.617587088273078, 117.22282297600707 * sizeFactor) + points.point4Cp1 = points.point4.shift(171.59670910061834, 40.160161877163844 * sizeFactor) + points.point4Cp2 = points.point4.shift(255.77964223723035, 21.208879767682262 * sizeFactor) + points.point5 = points.point0.shift(354.81977589032454, 54.026610044075944 * sizeFactor) + points.point5Cp1 = points.point5.shift(166.25960112580196, 20.659041530160696 * sizeFactor) + points.point5Cp2 = points.point5.shift(76.26126036953632, 34.11095664483535 * sizeFactor) + points.point0 = new Point(0, 0) + + let iterations = 0 + var p + do { + iterations++ + + points.point5Cp1 = points.point5.shift(166.25960112580196, 20.659041530160696 * sizeFactor) + points.point5Cp2 = points.point5.shift(76.26126036953632, 34.11095664483535 * sizeFactor) + p = new Path().move(points.point5).curve(points.point5Cp1, points.point0Cp2, points.point0) + + points.point5 = points.point5.shift(270, (mouthTop - p.length()) * 0.5) + } while (iterations < 100 && (mouthTop - p.length() > 1 || mouthTop - p.length() < -1)) + if (iterations >= 100) { + log.error('Something is not quite right here!') + } + + points.point4 = points.point4.shift( + 355, + store.get('lowerJaw') - + new Path() + .move(points.point4) + .curve(points.point4Cp1, points.point5Cp2, points.point5) + .length() + ) + points.point4Cp1 = points.point4.shift(171.59670910061834, 40.160161877163844 * sizeFactor) + points.point4Cp2 = points.point4.shift(255.77964223723035, 21.208879767682262 * sizeFactor) + + paths.mouthBottom = new Path() + .move(points.point5) + .curve(points.point5Cp1, points.point0Cp2, points.point0) + .setText(complete ? 'mouthBottom' + ' (13)' : '', textAttribute) + .addClass('hidden') + + paths.lowerJaw = new Path() + .move(points.point4) + .curve(points.point4Cp1, points.point5Cp2, points.point5) + .setText(complete ? 'lowerJaw' + ' (14)' : '', textAttribute) + .addClass('hidden') + + paths.front = new Path() + .move(points.point0) + .line(points.point1) + .setText(complete ? '12' : '', textAttribute) + + paths.bottomJaw = new Path() + .move(points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .setText(complete ? 'jawBottom' + '(15)' : '', textAttribute) + .addClass('hidden') + + paths.seam = new Path() + .move(points.point0) + .join(paths.front) + .join(paths.bottomJaw) + .join(paths.lowerJaw) + .join(paths.mouthBottom) + .close() + + store.set('bottomJaw', paths.bottomJaw.length()) + + store.cutlist.addCut({ cut: 2, from: 'Fabric' }) + + points.gridAnchor = points.point5.clone() + points.title = points.point1.shiftFractionTowards(points.point4, 0.25) + macro('title', { + nr: 11, + at: points.title, + scale: 0.4, + title: 'lowerJaw', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + paths.sa = paths.seam.offset(sa).trim().attr('class', 'fabric sa') + } + + points.pointY = new Path() + .move(points.point4) + .curve(points.point4Cp1, points.point5Cp2, points.point5) + .edge('top') + + macro('hd', { + from: points.point0, + to: points.point5, + y: points.pointY.y - sa - 15, + id: 'leftTopToTopHook', + }) + macro('hd', { + from: points.pointY, + to: points.point4, + y: points.pointY.y - sa - 15, + id: 'topToRight', + }) + macro('hd', { + from: points.point1, + to: points.point5, + y: points.pointY.y - sa - 25, + id: 'leftBottomToTopHook', + }) + macro('hd', { + from: points.point5, + to: points.point4, + y: points.pointY.y - sa - 25, + id: 'topHookToRight', + }) + macro('hd', { + from: points.point1, + to: points.point3, + y: points.point1.y + sa + 15, + id: 'bottomLeftToRightCorner', + }) + macro('hd', { + from: points.point3, + to: points.point4, + y: points.point1.y + sa + 15, + id: 'rightCornerToRight', + noStartMarker: true, + noEndMarker: true, + }) + + macro('vd', { + from: points.point1, + to: points.point5, + x: points.point1.x - sa - 15, + id: 'bottomToTopHook', + }) + macro('vd', { + from: points.point1, + to: points.point0, + x: points.point1.x - sa - 25, + id: 'bottomToTopLeft', + }) + macro('vd', { + from: points.point1, + to: points.pointY, + x: points.point1.x - sa - 35, + id: 'totalHeight', + }) + macro('vd', { + from: points.pointY, + to: points.point3, + x: points.point4.x + sa + 25, + id: 'rightCornerToTop', + }) + macro('vd', { + from: points.point4, + to: points.point3, + x: points.point4.x + sa + 15, + id: 'rightCornerToRight', + }) + + return part + }, +} diff --git a/designs/skully/src/lowermouth.mjs b/designs/skully/src/lowermouth.mjs new file mode 100644 index 00000000000..948c7bda011 --- /dev/null +++ b/designs/skully/src/lowermouth.mjs @@ -0,0 +1,89 @@ +import { cheek } from './cheek.mjs' + +export const lowermouth = { + name: 'skully.lowermouth', + after: cheek, + draft: ({ Point, Path, points, paths, sa, complete, store, macro, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point1 = points.point0.shift(270, 66.14600000000002 * sizeFactor) + points.point1Cp1 = points.point1.shift(0, 0 * sizeFactor) + points.point0Cp2 = points.point0.shift(0, 0 * sizeFactor) + + points.point2 = points.point0.shift(219.80599709691597, 51.66121657491237 * sizeFactor) + + points.point0 = new Point(0, 0) + points.point0Cp1 = points.point0.shift(0, 0 * sizeFactor) + points.point1 = points.point0.shift(222.41579397130369, 49.03292752740774 * sizeFactor) + points.point2 = points.point0.shift(270, 66.14600000000002 * sizeFactor) + points.point2Cp2 = points.point2.shift(0, 0 * sizeFactor) + points.point1.x = points.point0.x - points.point0.dist(points.point2) / 2 + points.point1Cp1 = points.point1.shift(270, 33.0746752291626 * sizeFactor) + points.point1Cp2 = points.point1.shift(90, 33.0746752291626 * sizeFactor) + + paths.mouth1 = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .setText(complete ? 'mouthBottom' + ' (13)' : '', textAttribute) + .addClass('hidden') + paths.mouth2 = new Path() + .move(points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .setText(complete ? 'mouthBottom' + ' (13)' : '', textAttribute) + .addClass('hidden') + + paths.backOfMouth = new Path() + .move(points.point2) + .line(points.point0) + .setText(complete ? 'backOfMouth' + ' (11)' : '', textAttribute) + .addClass('hidden') + + store.set('mouthWidth', points.point0.dist(points.point2)) + + paths.seam = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .curve(points.point1Cp1, points.point2Cp2, points.point2) + .line(points.point0) + .close() + + store.cutlist.addCut({ cut: 1, from: 'Fabric' }) + + points.gridAnchor = points.point1.clone() + points.title = points.point0 + .shiftFractionTowards(points.point2, 0.25) + .shiftFractionTowards(points.point1, 0.6) + macro('title', { + nr: 10, + at: points.title, + scale: 0.25, + rotation: 90, + title: 'lowerMouth', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + macro('hd', { + from: points.point1, + to: points.point0, + y: points.point0.y - sa - 15, + id: 'width', + }) + macro('vd', { + from: points.point0, + to: points.point2, + x: points.point0.x + sa + 15, + id: 'height', + }) + + return part + }, +} diff --git a/designs/skully/src/nose.mjs b/designs/skully/src/nose.mjs new file mode 100644 index 00000000000..5acea1301a6 --- /dev/null +++ b/designs/skully/src/nose.mjs @@ -0,0 +1,215 @@ +import { cheek } from './cheek.mjs' +import { eye } from './eye.mjs' +import { forehead } from './forehead.mjs' + +export const nose = { + name: 'skully.nose', + after: [cheek, forehead, eye], + draft: ({ + Point, + Path, + points, + paths, + Snippet, + snippets, + sa, + complete, + log, + store, + macro, + part, + }) => { + const textAttribute = 'text-xs center' + + const noseSide = store.get('noseSide') + const noseHeight = store.get('noseHeight') + + points.point0 = new Point(0, 0) + points.point2 = points.point0.shift(90, noseHeight) + points.point0Cp1 = points.point0.shift(315, noseHeight) + points.point2Cp2 = points.point2.shift(325, noseHeight / 3) + + paths.p1 = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point2Cp2, points.point2) + .hide() + + points.pRotate = points.point0.shift(30, noseHeight) + + paths.p0p1 = new Path().move(points.point0).line(points.point2).setClass('dashed mark') + + points.point1 = points.pRotate.shiftTowards(points.point2, noseHeight * -1) + + points.point1Cp2 = points.point1.shift(points.point1.angle(points.point2) + 55, noseHeight / 3) + + var iterations = 0 + var pl + do { + iterations++ + + points.point1 = points.point1.rotate(-0.5, points.point2) + points.point1Cp2 = points.point1Cp2.rotate(-0.5, points.point2) + points.point0Cp1 = points.point0Cp1.rotate(-0.5, points.point2) + paths.p1 = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .setText(complete ? 'nose' + ' (10)' : '', textAttribute) + + pl = paths.p1.length() + } while (iterations < 100 && pl - noseSide > 1) + if (iterations >= 100) { + log.error('Generating nose could not be made to fit in 100 iterations!') + } + + points.pMiddle1 = points.point2.shiftFractionTowards(points.point1, 0.5) + + points.point3 = points.point1.flipX() + points.point3Cp1 = points.point1Cp2.flipX() + points.point0Cp2 = points.point0Cp1.flipX() + points.pMiddle2 = points.pMiddle1.flipX() + + paths.p2 = new Path() + .move(points.point3) + .curve(points.point3Cp1, points.point0Cp2, points.point0) + .setText(complete ? 'nose' + ' (10)' : '', textAttribute) + + paths.seam = new Path() + .move(points.point0) + .join(paths.p1) + .line(points.point2) + .line(points.point3) + .join(paths.p2) + .close() + + store.cutlist.addCut({ cut: 1, from: 'Fabric' }) + + points.gridAnchor = points.point0.clone() + points.title = points.point0.shiftFractionTowards(points.point3, 0.5) + macro('title', { + nr: 12, + at: points.title, + scale: 0.15, + rotation: 325, + title: 'nose', + }) + + snippets.n1 = new Snippet('bnotch', points.point0) + snippets.n2 = new Snippet('notch', points.point1) + snippets.n3 = new Snippet('notch', points.point2) + snippets.n4 = new Snippet('notch', points.point3) + + macro('sewtogether', { + from: points.point1.shiftFractionTowards(points.point2, 0.25), + to: points.point1.shiftFractionTowards(points.point2, 0.75), + hinge: true, + id: 'st1', + }) + macro('sewtogether', { + from: points.point2.shiftFractionTowards(points.point3, 0.25), + to: points.point2.shiftFractionTowards(points.point3, 0.75), + hinge: true, + id: 'st2', + }) + + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + // Doing a trim() on the SA will remove the wrong part of the SA ;-) + // paths.sa = paths.seam.offset(sa).trim().attr('class', 'fabric sa') + const pathSA1 = new Path() + .move(points.point0) + .join(paths.p1) + .line(points.point2) + .offset(sa) + .addClass('hidden') + const pathSA2 = new Path() + .move(points.point2) + .line(points.point3) + .curve(points.point3Cp1, points.point0Cp2, points.point0) + .offset(sa) + .addClass('hidden') + const pSa1 = pathSA1.intersectsX(0)[0] + paths.sa1 = pathSA1.split(pSa1)[1].hide() + const pSa2 = pathSA2.intersectsX(0)[0] + paths.sa2 = pathSA2.split(pSa2)[0].hide() + paths.sa = new Path() + .move(pSa1) + .join(paths.sa1) + .join(paths.sa2) + .close() + .attr('class', 'fabric sa') + } + + points.pointY1 = new Path() + .move(points.point0) + .curve(points.point0Cp1, points.point1Cp2, points.point1) + .edge('bottom') + points.pointY2 = new Path() + .move(points.point0) + .curve(points.point0Cp2, points.point3Cp1, points.point3) + .edge('bottom') + + macro('vd', { + from: points.point2, + to: points.point1, + x: points.point1.x + sa + 5, + id: 'heightRight', + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + from: points.pointY1, + to: points.point2, + x: points.point3.x - sa - 5, + id: 'heightLeft', + noStartMarker: true, + noEndMarker: true, + }) + + macro('hd', { + from: points.point0, + to: points.point1, + y: points.point2.y - sa - 5, + id: 'widthRight', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.point3, + to: points.point0, + y: points.point2.y - sa - 5, + id: 'widthLeft', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.pointY1, + to: points.point1, + y: points.pointY2.y + sa + 5, + id: 'bottomToRight', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.pointY2, + to: points.pointY1, + y: points.pointY2.y + sa + 5, + id: 'leftToRight', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.point3, + to: points.pointY2, + y: points.pointY2.y + sa + 5, + id: 'leftToBottom', + noStartMarker: true, + noEndMarker: true, + }) + + return part + }, +} diff --git a/designs/skully/src/uppermouth.mjs b/designs/skully/src/uppermouth.mjs new file mode 100644 index 00000000000..10f69ff03ec --- /dev/null +++ b/designs/skully/src/uppermouth.mjs @@ -0,0 +1,305 @@ +import { cheek } from './cheek.mjs' +import { head1 } from './head1.mjs' +import { lowermouth } from './lowermouth.mjs' + +export const uppermouth = { + name: 'skully.uppermouth', + after: [cheek, head1, lowermouth], + draft: ({ Point, Path, points, paths, sa, complete, store, macro, part }) => { + const textAttribute = 'text-xs center' + const sizeFactor = store.get('sizeFactor') + + points.point0 = new Point(0, 0) + points.point6 = points.point0.shift(0.11139916029446559, 128.58224303534288 * sizeFactor) + points.point6Cp2 = points.point6.shift(269.8182450112891, 5.359026963917993 * sizeFactor) + points.point5 = points.point0.shift(328.14341716244707, 120.52788940738986 * sizeFactor) + points.point5Cp1 = points.point5.shift(29.114015378370315, 25.571930803128662 * sizeFactor) + points.point4 = points.point0.shift(317.9233666855834, 95.68080416154534 * sizeFactor) + points.point4Cp2 = points.point4.shift(178.12857030706965, 15.433231709528583 * sizeFactor) + points.point3 = points.point0.shift(312.29520434983914, 55.53156468171955 * sizeFactor) + points.point3Cp2 = points.point3.shift(90, 6.745097849549684 * sizeFactor) + points.point3Cp1 = points.point3.shift(270, 23.140963009347697 * sizeFactor) + points.point2 = points.point0.shift(312.62624217423604, 44.01273783803957 * sizeFactor) + points.point2Cp1 = points.point2.shift(358.24231642721344, 5.05337768230318 * sizeFactor) + points.point1 = points.point0.shift(270, 32.77328218228992 * sizeFactor) + + points.point1 = points.point1.shift( + 90, + points.point0.dist(points.point1) - store.get('mouthWidth') / 2 + ) + points.point2 = points.point2.shift( + 90, + points.point0.dist(points.point1) - store.get('mouthWidth') / 2 + ) + points.point2Cp1 = points.point2.shift(358.24231642721344, 5.05337768230318 * sizeFactor) + points.point3 = points.point3.shift( + 90, + points.point0.dist(points.point1) - store.get('mouthWidth') / 2 + ) + points.point3Cp1 = points.point3.shift(270, 23.140963009347697 * sizeFactor) + points.point3Cp2 = points.point3.shift(90, 6.745097849549684 * sizeFactor) + points.point4 = points.point4.shift( + 90, + points.point0.dist(points.point1) - store.get('mouthWidth') / 2 + ) + points.point4Cp2 = points.point4.shift(178.12857030706965, 15.433231709528583 * sizeFactor) + + points.point5 = points.point4.shift( + 0, + store.get('upperJaw') - + new Path() + .move(points.point1) + .line(points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .length() + ) + points.point5Cp1 = points.point5.shift(0, 9 * sizeFactor) + + points.point6 = new Point(points.point5.x, points.point0.y).shift(0, points.point5.x * 0.2) + points.point6Cp2 = points.point6.shift(270, 5 * sizeFactor) + + points.pointM1 = points.point0.shift(180, store.get('mouthWidth') / 2) + points.pointM1Cp1 = points.pointM1.shift(270, 33.0746752291626 * sizeFactor) + + paths.backOfUpperJaw = new Path() + .move(points.point5) + .curve(points.point5Cp1, points.point6Cp2, points.point6) + .setText(complete ? 'not sewn' : '', textAttribute) + .addClass('hidden') + + points.lowerJaw = paths.backOfUpperJaw.shiftAlong(store.get('upperJawToLowerJaw')) + var ljAngle = points.lowerJaw.angle( + paths.backOfUpperJaw.shiftAlong(store.get('upperJawToLowerJaw') + 1) + ) + + store.set('halfOfBack', paths.backOfUpperJaw.length() - store.get('upperJawToLowerJaw')) + + points.point2ToLowerJaw = points.point2.shift(0, points.point2.dist(points.lowerJaw) / 2) + points.lowerJawToPoint2 = points.lowerJaw.shift( + ljAngle + 90, + points.point2.dist(points.lowerJaw) / 3 + ) + + macro('mirror', { + mirror: [points.pointM1, points.point6], + points: [ + 'point0', + 'lowerJaw', + 'lowerJawToPoint2', + 'point2ToLowerJaw', + 'pointM1Cp1', + 'point1', + 'point2', + 'point2Cp1', + 'point3', + 'point3Cp1', + 'point3Cp2', + 'point4', + 'point4Cp2', + 'point5', + 'point5Cp1', + 'point6Cp2', + ], + prefix: 'm', + }) + + paths.upperJaw1 = new Path() + .move(points.point1) + .line(points.point2) + .curve(points.point2Cp1, points.point3Cp2, points.point3) + .curve(points.point3Cp1, points.point4Cp2, points.point4) + .line(points.point5) + .setText(complete ? 'upperJaw' + ' (16)' : '', textAttribute) + .addClass('hidden') + + paths.upperJaw2 = new Path() + .move(points.mPoint5) + .line(points.mPoint4) + .curve(points.mPoint4Cp2, points.mPoint3Cp1, points.mPoint3) + .curve(points.mPoint3Cp2, points.mPoint2Cp1, points.mPoint2) + .line(points.mPoint1) + .setText(complete ? 'upperJaw' + ' (16)' : '', textAttribute) + .addClass('hidden') + + paths.front1 = new Path() + .move(points.pointM1) + .curve_(points.pointM1Cp1, points.point1) + .setText(complete ? '(16)' : '', textAttribute) + .addClass('hidden') + + paths.front2 = new Path() + .move(points.mPoint1) + .curve_(points.mPointM1Cp1, points.pointM1) + .setText(complete ? '(16)' : '', textAttribute) + .addClass('hidden') + + paths.backOfUpperJaw.curve(points.mPoint6Cp2, points.mPoint5Cp1, points.mPoint5) + + paths.seam = new Path() + .move(points.point1) + .join(paths.upperJaw1) + .join(paths.backOfUpperJaw) + .join(paths.upperJaw2) + .join(paths.front2) + .join(paths.front1) + .close() + + paths.backOfMouth = new Path() + .move(points.mPoint1) + .line(points.point1) + .setText(complete ? 'backOfMouth' + ' (11)' : '', textAttribute) + .setClass('dashed') + + paths.lowerJaw1 = new Path() + .move(points.point2) + .curve(points.point2ToLowerJaw, points.lowerJawToPoint2, points.lowerJaw) + .setText(complete ? 'lowerJaw' + ' (14)' : '', textAttribute) + .setClass('dashed') + paths.lowerJaw2 = new Path() + .move(points.mPoint2) + .curve(points.mPoint2ToLowerJaw, points.mLowerJawToPoint2, points.mLowerJaw) + .setText(complete ? 'lowerJaw' + ' (14)' : '', textAttribute) + .setClass('dashed') + + paths.backOfUpperJaw1 = new Path() + .move(points.point5) + .line(points.lowerJaw) + .setText(complete ? '21' : '', textAttribute) + .addClass('hidden') + paths.backOfUpperJaw2 = new Path() + .move(points.mLowerJaw) + .line(points.mPoint5) + .setText(complete ? '21' : '', textAttribute) + .addClass('hidden') + + store.set('lowerJaw', paths.lowerJaw1.length() + points.point1.dist(points.point2)) + + store.cutlist.addCut({ cut: 1, from: 'Fabric' }) + + points.gridAnchor = points.point0.clone() + points.title = points.pointM1.shiftFractionTowards(points.point6, 0.5) + macro('title', { + nr: 7, + at: points.title, + scale: 0.5, + title: 'upperMouth', + }) + // points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5) + // snippets.logo = new Snippet('logo', points.logo) + // points.text = points.logo + // .shift(-90, w / 8) + + if (sa) { + // Doing a trim() here has a weird issue. Part of the SA, related to + // the point1->point2 line, will disappear. + // paths.sa = paths.seam.offset(sa).trim().attr('class', 'fabric sa') + paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') + } + + macro('hd', { + from: points.pointM1, + to: points.point1, + y: points.point5.y + sa + 15, + id: 'leftToBOM', + }) + macro('hd', { + from: points.point1, + to: points.point3, + y: points.point5.y + sa + 15, + id: 'BOMtoCorner', + }) + macro('hd', { + from: points.point3, + to: points.point5, + y: points.point5.y + sa + 15, + id: 'cornerToRight', + }) + macro('hd', { + from: points.point5, + to: points.point6, + y: points.point5.y + sa + 15, + id: 'rightToMiddle', + noStartMarker: true, + noEndMarker: true, + }) + macro('hd', { + from: points.pointM1, + to: points.point6, + y: points.mPoint5.y - sa - 15, + id: 'totalWidth', + }) + + macro('vd', { + from: points.point6, + to: points.point5, + x: points.point6.x + sa + 15, + id: 'bottomToMiddle', + }) + macro('vd', { + from: points.mPoint5, + to: points.point6, + x: points.point6.x + sa + 15, + id: 'middleToTop', + }) + macro('vd', { + from: points.mPoint1, + to: points.mPoint5, + x: points.pointM1.x - sa - 15, + id: 'topBOMtoTop', + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + from: points.point1, + to: points.mPoint1, + x: points.pointM1.x - sa - 15, + id: 'BOMheight1', + }) + macro('vd', { + from: points.point5, + to: points.point1, + x: points.pointM1.x - sa - 15, + id: 'bottomToBottomBOM', + noStartMarker: true, + noEndMarker: true, + }) + macro('vd', { + from: points.point2, + to: points.mPoint2, + x: points.point2.x, + id: 'BOMheight2', + }) + + macro('ld', { + from: points.point5, + to: points.lowerJaw, + d: 5, + id: 'bottomLowerJawIndicator', + noStartMarker: true, + noEndMarker: true, + }) + macro('ld', { + from: points.lowerJaw, + to: points.point6, + d: 5, + id: 'bottomLowerJawIndicatorToMiddle', + }) + macro('ld', { + from: points.point6, + to: points.mLowerJaw, + d: 5, + id: 'topLowerJawIndicatorToMiddle', + }) + macro('ld', { + from: points.mLowerJaw, + to: points.mPoint5, + d: 5, + id: 'topLowerJawIndicator', + noStartMarker: true, + noEndMarker: true, + }) + + return part + }, +} diff --git a/designs/skully/tests/shared.test.mjs b/designs/skully/tests/shared.test.mjs new file mode 100644 index 00000000000..2b25b6104ed --- /dev/null +++ b/designs/skully/tests/shared.test.mjs @@ -0,0 +1,16 @@ +// This file is auto-generated | Any changes you make will be overwritten. +import { Skully } from '../src/index.mjs' + +// Shared tests +import { testPatternConfig } from '../../../tests/designs/config.mjs' +import { testPatternDrafting } from '../../../tests/designs/drafting.mjs' +import { testPatternSampling } from '../../../tests/designs/sampling.mjs' + +// Test config +testPatternConfig(Skully) + +// Test drafting - Change the second parameter to `true` to log errors +testPatternDrafting(Skully, false) + +// Test sampling - Change the second parameter to `true` to log errors +testPatternSampling(Skully, false) diff --git a/markdown/org/docs/designs/skully/cutting/en.md b/markdown/org/docs/designs/skully/cutting/en.md new file mode 100644 index 00000000000..c90f41cda7a --- /dev/null +++ b/markdown/org/docs/designs/skully/cutting/en.md @@ -0,0 +1,16 @@ +--- +title: "Skully: Cutting Instructions" +--- + +- **Main Fabric** + - Cut **2 Cheek** + - Cut **2 Forehead** + - Cut **2 Head part 1** + - Cut **2 Head part 2** + - Cut **2 Head part 3** + - Cut **2 Cheekbone** + - Cut **1 Upper Mouth** + - Cut **1 Jaw Floor** + - Cut **2 Eye ** + - Cut **1 Lower Mouth ** + - Cut **2 Lower Jaw ** diff --git a/markdown/org/docs/designs/skully/en.md b/markdown/org/docs/designs/skully/en.md new file mode 100644 index 00000000000..3f413a0467e --- /dev/null +++ b/markdown/org/docs/designs/skully/en.md @@ -0,0 +1,8 @@ +--- +title: Skully +--- + +import { DesignInfo } from 'shared/components/designs/info.mjs' + + + diff --git a/markdown/org/docs/designs/skully/fabric/en.md b/markdown/org/docs/designs/skully/fabric/en.md new file mode 100644 index 00000000000..d3361fe60f1 --- /dev/null +++ b/markdown/org/docs/designs/skully/fabric/en.md @@ -0,0 +1,21 @@ +--- +title: "Skully: Fabric Options" +--- + +## Main Fabric + +This plush toy is best made from a felt type of fabric. This will provide extra rigidity to keep the shape +correct, while still allowing it to be a plush toy. Thin and stretchy fabrics are not well suited, because +the shape will change considerably due to tensions from the stuffing. + +## Hair + +Skully needs hair. Embrodery floss works very well, and can be had in all colors. + +## Stuffing + +Since this is a plush toy, it will need to be stuffed with material. Most of the time you'll want to use polyester fiberfill (polyfill), but if you have a lot of fabric scraps, you can use shredded scrap fabric. However this may be heavier and less soft than fiberfill. It's also worth thinking about whether your Hi may be at risk of getting dirty, or want to go for a swim, as not all stuffing options are washable. + +## Needle + +Skully has traded his sword for a needle. A needle this size is mostly sold as upholstery needles. This will come in handy when doing some of the touch-ups at the end of the construction. \ No newline at end of file diff --git a/markdown/org/docs/designs/skully/instructions/en.md b/markdown/org/docs/designs/skully/instructions/en.md new file mode 100644 index 00000000000..d77de935ce7 --- /dev/null +++ b/markdown/org/docs/designs/skully/instructions/en.md @@ -0,0 +1,65 @@ +--- +title: "Skully: Sewing Instructions" +--- + + + + +A lot of the smaller seams (eyes, nose) are best sewn by hand. + +Most of the seams will benefit from being basted before being sewn. + + + +## Step 1: The darts + +There are six darts that need to be closed first. One on each, forhead, head2, and head3 parts. Pin and sew them closed, then remove the bulk by trimming the darts and give them a good press. Repeat for the all six darts. + + +## Step 2: The eyes + +Sew together the sides of the eye, so you will make a cone. Trim away any bulk. Repeat for the other eye. + +## Step 3: The nose + +Like the eyes, the nose too has parts that need to be sewn together. There are two of these sides that need to be sew together. This creates two connected cones. This is very finicky, so take your time. + +## Step 4: The head + + + +The Skully pattern is set up to be sewn-by-numbers. Every seam is numbered. Please start at '1', and +keep going until you reach '21'. This is the seam through which you will fill Skully, so only close +it partly. + + + +When you are sewing together the individual parts, you will be making two halves of the skull. + +Sewing the eyes and nose to the cheek and forehead parts is best done by hand. You will have to align the different notches to their corresponding ones on the other part. + +Sewing the lowerJaw to the lowerMouth and upperMouth is challenging. You will first be sewing a normal seam between the lowerJaw parts and the lowerMouth part. You will then have to continue this seam along +the dashed line (14) on the upperMouth part. Basting or lots of pins are your friend. And make sure you +first visualize how this will get together before doing the final sewing. + +The back of the upperMouth is not sewn to anything. It is just there to provide stability. + +## Step 5: Hair + +Now is the time to add hair to skully. When putting the embroidery floss in, make sure you add knots on the inside, or else it is very easy to pull Skully's hair out later. + +## Step 6: Stuffing + +- Fill the plush toy with stuffing through the opening you left, making sure to fill all the parts +well. The areas in the front are the hardest to get to. +- _Slipsticth_ or _whipstitch_ the opening closed. + +## Step 7: Tweaks + +You can use the long upholstery needle to add some tweaks to Skully. Adding some stitches to attach the back of the eyes to corner of seams 14 and 21 right through the skull will help to keep the eyes from popping out, and can help with giving the head more form. The same applies to the nose. + +It is also a good idea to add stitches between seams 5 and 14, along the length of both seams. This will make the cheek bones more pronounced and adds to the overall shape of the skull. + +## Step 7: Enjoy! + +That's it, you are all done. Start planning what pirate sewing ship you'll be joining! \ No newline at end of file diff --git a/markdown/org/docs/designs/skully/measurements/en.md b/markdown/org/docs/designs/skully/measurements/en.md new file mode 100644 index 00000000000..96e37b1b50e --- /dev/null +++ b/markdown/org/docs/designs/skully/measurements/en.md @@ -0,0 +1,7 @@ +--- +title: "Skully: Optional Measurements" +--- + + +Skully does not require any measurements, but it can use the head circumference measurement. If used, Skully will be approximately the same size as your head. + diff --git a/markdown/org/docs/designs/skully/needs/en.md b/markdown/org/docs/designs/skully/needs/en.md new file mode 100644 index 00000000000..4d4e8186ec1 --- /dev/null +++ b/markdown/org/docs/designs/skully/needs/en.md @@ -0,0 +1,19 @@ +--- +title: "Skully: What You Need" +--- + +To make Skully, you will need the following: + +- [Basic sewing supplies](/docs/sewing/basic-sewing-supplies) +- About 0.5 meters (0.6 yards) of a suitable fabric ([see Skully Fabric options](/docs/patterns/skully/fabric/)) +- Stuffing +- Embroidery floss for the hair +- Appropriately sized upholstery needle + + + +This list is based on a default Skully and you may need less or more fabric dependant on the [size you are making Skully](/docs/patterns/skully/options/size/). + +For instance a 300% Skully will need 1.5 meters (0.5 meter x 300% = 1.5 meters) and a 50% skully will need 0.25 meters (0.5 meter x 50% = 0.25 meters). + + diff --git a/markdown/org/docs/designs/skully/notes/en.md b/markdown/org/docs/designs/skully/notes/en.md new file mode 100644 index 00000000000..429e33c2e58 --- /dev/null +++ b/markdown/org/docs/designs/skully/notes/en.md @@ -0,0 +1,6 @@ +--- +title: "Skully: Designer Notes" +--- + +Wouter designed this. They have not written any notes (yet) + diff --git a/markdown/org/docs/designs/skully/options/en.md b/markdown/org/docs/designs/skully/options/en.md new file mode 100644 index 00000000000..5c1b5d5e938 --- /dev/null +++ b/markdown/org/docs/designs/skully/options/en.md @@ -0,0 +1,5 @@ +--- +title: "Skully: Design Options" +--- + + diff --git a/markdown/org/docs/designs/skully/options/size/en.md b/markdown/org/docs/designs/skully/options/size/en.md new file mode 100644 index 00000000000..77bb4ae0f34 --- /dev/null +++ b/markdown/org/docs/designs/skully/options/size/en.md @@ -0,0 +1,8 @@ +--- +title: "Size" +--- + +Skully can be made in different sizes. The default is about 75% of a normal human head (about 16cm high). + +If you set the percentage to 100%, and you enter your own head measurwement, Skully will +be approximately the size of your head. \ No newline at end of file diff --git a/markdown/org/docs/patterns/skully/cutting/en.md b/markdown/org/docs/patterns/skully/cutting/en.md new file mode 100644 index 00000000000..01e220f4f78 --- /dev/null +++ b/markdown/org/docs/patterns/skully/cutting/en.md @@ -0,0 +1,17 @@ +--- +title: "Skully (the logo): Cutting Instructions" +--- + +- **Main fabric** + - Cut **2 cheek** parts + - Cut **2 forehead** parts + - Cut **2 head1** parts + - Cut **2 head2** parts + - Cut **2 head3** parts + - Cut **2 cheekbone** parts + - Cut **1 lowermouth** part + - Cut **1 jawFloor** part + - Cut **2 eye** parts + - Cut **1 uppermouth** part + - Cut **2 lowerJaw** parts + - Cut **1 nose** part diff --git a/markdown/org/docs/patterns/skully/en.md b/markdown/org/docs/patterns/skully/en.md new file mode 100644 index 00000000000..d6a21c48edd --- /dev/null +++ b/markdown/org/docs/patterns/skully/en.md @@ -0,0 +1,5 @@ +--- +title: Skully (the logo) +--- + + diff --git a/markdown/org/docs/patterns/skully/fabric/en.md b/markdown/org/docs/patterns/skully/fabric/en.md new file mode 100644 index 00000000000..0207ee38b5f --- /dev/null +++ b/markdown/org/docs/patterns/skully/fabric/en.md @@ -0,0 +1,19 @@ +--- +title: "Skully (the logo): Fabric Options" +--- + +## Main Fabric + +This plush toy is best made from a felt type fabrics. This will provide extra rigidity to keep the shape correct, while still allowing it to be a plush toy. Thin and stretchy fabrics are not well suited, because the shape will change considerably due to tensions from the stuffing. + +## Stuffing + +Since this is a plush toy, it will need to be stuffed with material. Most of the time you'll want to use polyester fiberfill (polyfill), but if you have a lot of fabric scraps, you can use shredded scrap fabric. However this may be heavier and less soft than fiberfill. It's also worth thinking about whether your Skully may be at risk of getting dirty as not all stuffing options are washable. + +## Hair + +Skully needs hair. Embroidery floss works very well, and can be had in all colors. + +## Needle + +Skully has traded his sword for a needle. A needle this size is mostly sold as upholstery needles. This will come in handy when doing some of the touch-ups at the end of the construction. diff --git a/markdown/org/docs/patterns/skully/instructions/en.md b/markdown/org/docs/patterns/skully/instructions/en.md new file mode 100644 index 00000000000..dec7c90c099 --- /dev/null +++ b/markdown/org/docs/patterns/skully/instructions/en.md @@ -0,0 +1,72 @@ +--- +title: "Skully (the logo): Sewing Instructions" +--- + + + +A lot of the smaller seams (eyes, nose) are best sewn by hand. + +Most of the seams will benefit from being basted before being sewn. + + + +## Step 1: The darts + +There are three darts that need to be closed first. Pin and sew them, then remove the extra fabric and +give them a good press. Repeat for the other three darts. + +## Step 2: The eyes + +Sew together the sides of the eye, so you will make a cone. Cut away any excess seam allowance. Repeat for the other eye + +## Step 3: The nose + +Like the eyes, the nose has seams that need to be sewn together. Sew the two straight seams together creating two connected cones. This is very finicky, so take your time. + +## Step 4: The head + + + +The Skully pattern is set up to be sewn-by-numbers. Every seam is numbered. Please start at '1', and +keep going until you reach '21'. This is the seam through which you will fill Skully, so only close +it partly. + + + +When you are sewing together the individual parts, you will be making two halves of the skull. + +Sewing the eyes and nose to the cheek and forehead parts is best done by hand. You will have to align +the different notches to their corresponding ones on the other part. + +Sewing the lowerJaw to the lowerMouth and upperMouth is challenging. You will be making a normal seam +between the lowerJaw parts and the lowerMouth part. You will then have to continue this seam along +the dashed line (14) on the upperMouth part. Baste or lots of pins are your friend. And make sure you +first visualize how this will get together before doing the final sewing. + +The back of the upperMouth is not sewn to anything. It is just there to provide stability. + +## Step 5: Hair + +Now is the time to add hair to skully. When putting the embroidery floss in, make sure you add knots +on the inside, or else it is very easy to pull Skully's hair out later. I threaded two pieces of floss +through a needle, and stick it from the outside through the head. Then make an overhand knot, and push +the needle back out. You should make shorter hair towards the outside, and longer in the middle. + +## Step 6: Stuffing + +- Fill the plush toy with stuffing through the opening you left, making sure to fill all the parts +well. The areas in the front are the hardest to get to. +- _Slipsticth_ or _whipstitch_ the opening closed. + +## Step 6: Tweaks + +You can use the long upholstery needle to add some tweaks to Skully. Adding some stitches, attaching +the back of the eyes to corner of seams 14 and 21 right through the skull helps with keeping the +eyes from popping out, and can help with giving the head more form. The same applies to the nose. + +It is also a good isea to add stitches between seams 5 and 14, along the length of both seams. This +will make the cheek bones more pronounced and adds to the overall shape of the skull. + +## Step 7: Enjoy! + +That's it, you are all done. Start planning what pirate sewing ship you'll be joining! diff --git a/markdown/org/docs/patterns/skully/measurements/en.md b/markdown/org/docs/patterns/skully/measurements/en.md new file mode 100644 index 00000000000..775cb2dd71e --- /dev/null +++ b/markdown/org/docs/patterns/skully/measurements/en.md @@ -0,0 +1,7 @@ +--- +title: "Skully (the logo): Required Measurements" +--- + + +Skully does not require any measurements, but it can use the head circumference measurement. If used, Skully will be approximately 75%, or any other percentage, of the size of your head. + diff --git a/markdown/org/docs/patterns/skully/needs/en.md b/markdown/org/docs/patterns/skully/needs/en.md new file mode 100644 index 00000000000..3076ce09f7e --- /dev/null +++ b/markdown/org/docs/patterns/skully/needs/en.md @@ -0,0 +1,19 @@ +--- +title: "Skully (the logo): What You Need" +--- + +To make Skully, you will need the following: + +- [Basic sewing supplies](/docs/sewing/basic-sewing-supplies) +- About 0.5 meters (0.6 yards) of a suitable fabric ([see Skully Fabric options](/docs/patterns/skully/fabric/)) +- Stuffing +- Embroidery floss for the hair +- Appropriately sized upholstery needle + + + +This list is based on a default Skully and you may need less or more fabric dependant on the [size you are making Skully](/docs/patterns/skully/options/size/). + +For instance a 300% Skully will need 1.5 meters (0.5 meter x 300% = 1.5 meters) and a 50% skully will need 0.25 meters (0.5 meter x 50% = 0.25 meters). + + diff --git a/markdown/org/docs/patterns/skully/options/en.md b/markdown/org/docs/patterns/skully/options/en.md new file mode 100644 index 00000000000..e46afcd03e3 --- /dev/null +++ b/markdown/org/docs/patterns/skully/options/en.md @@ -0,0 +1,5 @@ +--- +title: "Skully (the logo): Design Options" +--- + + diff --git a/markdown/org/docs/patterns/skully/options/size/en.md b/markdown/org/docs/patterns/skully/options/size/en.md new file mode 100644 index 00000000000..820dcbea848 --- /dev/null +++ b/markdown/org/docs/patterns/skully/options/size/en.md @@ -0,0 +1,10 @@ +--- +title: "Size" +--- + +Skully can be made in different sizes. The default is about 75% of an averge human head. +This is a percentage of the default head circumference. + +If you set the percentage to 100%, and you enter your own head measurwement, Skully will +be approximately the size of your head. + diff --git a/sites/lab/hooks/use-design.mjs b/sites/lab/hooks/use-design.mjs index 83b9911c4ec..36915b374ec 100644 --- a/sites/lab/hooks/use-design.mjs +++ b/sites/lab/hooks/use-design.mjs @@ -37,6 +37,7 @@ import { Sandy as sandy } from '@freesewing/sandy' import { Shin as shin } from '@freesewing/shin' import { Simon as simon } from '@freesewing/simon' import { Simone as simone } from '@freesewing/simone' +import { Skully as skully } from '@freesewing/skully' import { Sven as sven } from '@freesewing/sven' import { Tamiko as tamiko } from '@freesewing/tamiko' import { Teagan as teagan } from '@freesewing/teagan' @@ -85,6 +86,7 @@ const designs = { shin, simon, simone, + skully, sven, tamiko, teagan,