From 631ea8a50d241d876edf89d473142f76b0cf3c25 Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sun, 11 Jun 2023 14:10:17 +0200 Subject: [PATCH 1/2] feat(core): New mergeOptions method and passing mergedOtions to toAbs When using toAbs for all but the most trivial cases, one needs access to the options. Unlike measurements which are always there, options aren't always set since they are only set when they differ from the default. This would shift a lot of responsibility on the pattern designer who would have to check whether an option is set, and if it's not use the default which in turn depends on what type of an option it is (and it's pct for example you have to remember to divide it by 100 and so on). This feels footgun-y so instead I've added a `mergeOptions` method that merges the options passed by the user with the defaults from the pattern config so that you have a simple object with all option values. This should get passed to `toAbs()` as the 3rd parameter. --- packages/core/src/index.mjs | 2 ++ packages/core/src/pattern/pattern-drafter.mjs | 8 +++++-- packages/core/src/utils.mjs | 23 +++++++++++++++++++ .../workbench/menus/design-options/index.mjs | 2 +- .../workbench/menus/design-options/values.mjs | 9 ++++++-- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/packages/core/src/index.mjs b/packages/core/src/index.mjs index 8735fe5411b..85ab05ed4b7 100644 --- a/packages/core/src/index.mjs +++ b/packages/core/src/index.mjs @@ -26,6 +26,7 @@ import { lineIntersectsCircle, lineIntersectsCurve, linesIntersect, + mergeOptions, pctBasedOn, pointOnBeam, pointOnCurve, @@ -70,6 +71,7 @@ export { lineIntersectsCircle, lineIntersectsCurve, linesIntersect, + mergeOptions, pctBasedOn, pointOnBeam, pointOnCurve, diff --git a/packages/core/src/pattern/pattern-drafter.mjs b/packages/core/src/pattern/pattern-drafter.mjs index e9db84e1549..d5c82f36bbd 100644 --- a/packages/core/src/pattern/pattern-drafter.mjs +++ b/packages/core/src/pattern/pattern-drafter.mjs @@ -1,6 +1,6 @@ import { PatternDraftQueue } from './pattern-draft-queue.mjs' import { Part } from '../part.mjs' -import { __macroName } from '../utils.mjs' +import { __macroName, mergeOptions } from '../utils.mjs' /** * A class to handle drafting a pattern @@ -202,7 +202,11 @@ PatternDrafter.prototype.__loadAbsoluteOptionsSet = function (set) { */ PatternDrafter.prototype.__snappedPercentageOption = function (optionName, set) { const conf = this.pattern.config.options[optionName] - const abs = conf.toAbs(this.pattern.settings[set].options[optionName], this.pattern.settings[set]) + const abs = conf.toAbs( + this.pattern.settings[set].options[optionName], + this.pattern.settings[set], + mergeOptions(this.pattern.settings[set], this.pattern.config.options) + ) // Handle units-specific config - Side-step immutability for the snap conf let snapConf = conf.snap if (!Array.isArray(snapConf) && snapConf.metric && snapConf.imperial) diff --git a/packages/core/src/utils.mjs b/packages/core/src/utils.mjs index 7fbc23f4e5e..e8f19c5c036 100644 --- a/packages/core/src/utils.mjs +++ b/packages/core/src/utils.mjs @@ -441,6 +441,29 @@ export function lineIntersectsCurve(start, end, from, cp1, cp2, to) { else return intersections } +/** + * Helper method to merge passed in options with default options from the pattern config + * + * @param {object} settings - The settings passed to the pattern + * @param {object} optionsConfig - The pattern's options config + * @return {object} result - An object with the merged options and their values + */ +export function mergeOptions(settings, optionsConfig) { + const merged = typeof settings.options === 'undefined' ? {} : { ...settings.option } + for (const [key, option] of Object.entries(optionsConfig)) { + if (typeof option === 'object') { + if (typeof option.pct !== 'undefined') merged[key] = option.pct / 100 + else if (typeof option.mm !== 'undefined') merged[key] = option.mm + else if (typeof option.deg !== 'undefined') merged[key] = option.deg + else if (typeof option.count !== 'undefined') merged[key] = option.count + else if (typeof option.bool !== 'undefined') merged[key] = option.bool + else if (typeof option.dflt !== 'undefined') merged[key] = option.dflt + } else merged[key] = option + } + + return merged +} + /** * Helper method to calculate abolute option value based on a measurement * diff --git a/sites/shared/components/workbench/menus/design-options/index.mjs b/sites/shared/components/workbench/menus/design-options/index.mjs index 770f4a3f517..6829d5707dd 100644 --- a/sites/shared/components/workbench/menus/design-options/index.mjs +++ b/sites/shared/components/workbench/menus/design-options/index.mjs @@ -90,7 +90,7 @@ export const DesignOptions = ({ name: 'design-options:designOptions', language, ns: menuNs, - passProps: { settings }, + passProps: { settings, patternConfig }, updateFunc: (name, value) => update.settings(['options', ...name], value), }} /> diff --git a/sites/shared/components/workbench/menus/design-options/values.mjs b/sites/shared/components/workbench/menus/design-options/values.mjs index dd935ea3867..c1f2f1909b1 100644 --- a/sites/shared/components/workbench/menus/design-options/values.mjs +++ b/sites/shared/components/workbench/menus/design-options/values.mjs @@ -1,14 +1,19 @@ import { formatMm, formatPercentage } from 'shared/utils.mjs' import { ListValue, HighlightedValue, PlainValue, BoolValue } from '../shared/values' +import { mergeOptions } from '@freesewing/core' /** Displays the current percentatge value, and the absolute value if configured */ -export const PctOptionValue = ({ config, current, settings, changed }) => { +export const PctOptionValue = ({ config, current, settings, changed, patternConfig }) => { const val = changed ? current : config.pct / 100 return ( {formatPercentage(val)} - {config.toAbs && settings.measurements ? ` | ${formatMm(config.toAbs(val, settings))}` : null} + {config.toAbs && settings.measurements + ? ` | ${formatMm( + config.toAbs(val, settings, mergeOptions(settings, patternConfig.options)) + )}` + : null} ) } From a532a6e010f7964dfc17af5770c92edbe2e5fb3b Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sun, 11 Jun 2023 15:57:16 +0200 Subject: [PATCH 2/2] feat(markdown): Docs for utils.mergeOptions() --- markdown/dev/reference/api/en.md | 1 + .../api/part/config/options/pct/toabs/en.md | 9 ++++++- .../reference/api/utils/mergeoptions/en.md | 27 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 markdown/dev/reference/api/utils/mergeoptions/en.md diff --git a/markdown/dev/reference/api/en.md b/markdown/dev/reference/api/en.md index 22e71c3ee43..f9fb71d4d66 100644 --- a/markdown/dev/reference/api/en.md +++ b/markdown/dev/reference/api/en.md @@ -74,6 +74,7 @@ The following named exports are **utility methods**: | `lineIntersectsCircle` | See the [lineIntersectsCircle](/reference/api/utils/lineintersectscircle) documentation | | `lineIntersectsCurve` | See the [lineIntersectsCurve](/reference/api/utils/lineintersectscurve) documentation | | `linesIntersect` | See the [linesIntersect](/reference/api/utils/linesintersect) documentation | +| `mergeOptions` | See the [mergeOptions](/reference/api/utils/mergeoptions) documentation | | `pctBasedOn` | See the [pctBasedOn](/reference/api/utils/pctbasedon) documentation | | `pointOnBeam` | See the [pointOnBeam](/reference/api/utils/pointonbeam) documentation | | `pointOnCurve` | See the [pointOnCurve](/reference/api/utils/pointoncurve) documentation | diff --git a/markdown/dev/reference/api/part/config/options/pct/toabs/en.md b/markdown/dev/reference/api/part/config/options/pct/toabs/en.md index 3b20d5df34a..f32d3dbf4ff 100644 --- a/markdown/dev/reference/api/part/config/options/pct/toabs/en.md +++ b/markdown/dev/reference/api/part/config/options/pct/toabs/en.md @@ -17,16 +17,23 @@ The `toAbs` property should hold a function with the following signature: ```js -function toAbs(percentage, settings) { +function toAbs(percentage, settings, mergeOptions) { // return value in millimeter here } ``` The first parameter is the percentage value provided by the user (for example `0.5` for `50%`). + The second parameter holds the pattern's [settings](/reference/settings) object which holds -- among other things -- the measurements provided by the user. +The third parameter should be the return value of +[utils.mergeOptions()](/reference/api/utils/mergeoptions), which provides an +object with all option values populated. Although this parameter is not +required for simple values based on measurements, it is often required when the +result depends on several options. + ## Example In our example above, let's say that the `chestEase` option is diff --git a/markdown/dev/reference/api/utils/mergeoptions/en.md b/markdown/dev/reference/api/utils/mergeoptions/en.md new file mode 100644 index 00000000000..e38a054f3a5 --- /dev/null +++ b/markdown/dev/reference/api/utils/mergeoptions/en.md @@ -0,0 +1,27 @@ +--- +title: utils.mergeOptions() +--- + +The `utils.mergeOptions()` function merges the user-provided options with the +options from the pattern configuration. + +## Signature + +```js +float deg2rad(object settings, object optionsConfig) +``` + +## Notes + +Typically the only options that are passed as part of settings to the pattern +are those that differ from the defaults. This means that if you want to check +an option outside a draft method, you need to check whether the option is set, +and if it's not get the default value from the pattern config. Furthermore, +where the default is stored and whether or not it should be further transformed +depends on the option type. + +This method exists to facilitate this. You pass it the user-provided settings, +and the pattern config options key, and it will return an object where all +options are populated with the user-provided values, or their defaults if the +user did not provide any input. +