These are some changes in the way the monorepo is structured,
that are aimed at making it easier to get started.
There are two important changes:
**Multiple workspaces**
We had a yarn workspaces setup at `packages/*`. But our monorepo has
grown to 92 packages which can be overwhelming for people not familiar
with the package names.
To remedy this, I've split it into 4 different workspaces:
- `designs/*`: Holds FreeSewing designs (think patterns)
- `plugins/*`: Holds FreeSewing plugins
- `packages/*`: Holds other packages published on NPM
- `sites/*`: Holds software that is not published as an NPM package,
such as our various websites and backend API
This should make it easier to find things, and to answer questions like
*where do I find the code for the plugins*.
**Updated reconfigure script to handle build order**
One problem when bootstrapping the repo is inter-dependencies between
packages. For example, building a pattern will only work once
`plugin-bundle` is built. Which will only work once all plugins in the
bundle or built. And that will only work when `core` is built, and so
on.
This can be frustrating for new users as `yarn buildall` will fail.
And it gets overlooked by seasoned devs because they're likely to have
every package built in their repo so this issue doesn't concern them.
To remedy this, we now have a `config/build-order.mjs` file and the
updated `/scripts/reconfigure.mjs` script will enforce the build order
so that things *just work*.
This pattern uses a method to generate teeth which depends on a lot
of Path.shiftAlong() invocations.
This causes the pattern to be a bit sluggish, with a render taking
around 160ms (which is too slow to feel instantaneous for the user) and
the unit tests timing out because some individual tests take longer than
2 seconds. When extending the timeout, running all tests clocks in just
over 14 seconds which is slow.
This PR replaces this method with an optimized one that is a lot faster.
(all tests now complete in 2.11 seconds).
To do this,it does some things differnet, and cuts some corners:
- It does not use the Path object, but rather the low-level Bezier
object directly
- It generates teeth for only half the mouth and will mirror them to the
other side
- It uses a symmetric cubic Bezier curve so we don't need to walk the
path in steps that are determined by distance, but can just walk it at
regular intervals of the t value. As it happens, that can be done in
one pass by using Bezier.getLUT()
The corners I cut:
- Because of the symmetric Bezier the path is ever so
slightly different, but the difference is minimal.provides ai
- Since we generate half of the mouth/teeth and then mirror, we need and
even number of teeth, so I've changed the upper teeth from 15 to 14