diff --git a/designs/plugintest/src/index.mjs b/designs/plugintest/src/index.mjs index d03850e167c..b6f9f731ee8 100644 --- a/designs/plugintest/src/index.mjs +++ b/designs/plugintest/src/index.mjs @@ -9,11 +9,12 @@ import { measurements } from './plugin-measurements.mjs' import { mirror } from './plugin-mirror.mjs' import { round } from './plugin-round.mjs' import { sprinkle } from './plugin-sprinkle.mjs' +import { ringsector } from './plugin-ringsector.mjs' // Setup our new design const Plugintest = new Design({ data, - parts: [annotations, flip, gore, i18nStack, measurements, mirror, round, sprinkle], + parts: [annotations, flip, gore, i18nStack, measurements, mirror, round, sprinkle, ringsector], }) // Named exports @@ -26,6 +27,7 @@ export { mirror, round, sprinkle, + ringsector, Plugintest, i18n, } diff --git a/designs/plugintest/src/plugin-mirror.mjs b/designs/plugintest/src/plugin-mirror.mjs index 80909636d44..0f7ff4c19da 100644 --- a/designs/plugintest/src/plugin-mirror.mjs +++ b/designs/plugintest/src/plugin-mirror.mjs @@ -63,7 +63,7 @@ const pluginMirror = ({ macro('bannerbox', { topLeft: new Point(options.mirrorLine === 'b' ? -35 : 5, -25), bottomRight: new Point(65, 50), - text: 'plugin = measurements', + text: 'plugin = mirror', ...store.get('bannerbox.plugin'), }) } diff --git a/designs/plugintest/src/plugin-ringsector.mjs b/designs/plugintest/src/plugin-ringsector.mjs new file mode 100644 index 00000000000..98c967a76b9 --- /dev/null +++ b/designs/plugintest/src/plugin-ringsector.mjs @@ -0,0 +1,33 @@ +import { ringsectorPlugin } from '@freesewing/plugin-ringsector' +import { base } from './base.mjs' + +const pluginRingsector = ({ points, Point, paths, options, macro, part, store }) => { + if (['ringsector', 'all'].indexOf(options.plugin) !== -1) { + const pathId = macro('ringsector', { + angle: options.ringsectorAngle, + insideRadius: options.ringsectorInsideRadius, + outsideRadius: options.ringsectorOutsideRadius, + }).paths.path + + macro('bannerbox', { + topLeft: paths[pathId].edge('topLeft'), + bottomRight: paths[pathId].edge('bottomRight'), + text: 'macro = ringsector', + ...store.get('bannerbox.macro'), + }) + } + + return part +} + +export const ringsector = { + name: 'plugintest.ringsector', + plugins: ringsectorPlugin, + after: base, + options: { + ringsectorInsideRadius: { count: 30, min: 10, max: 50, menu: 'ringsector' }, + ringsectorOutsideRadius: { count: 60, min: 60, max: 120, menu: 'ringsector' }, + ringsectorAngle: { deg: 75, min: 30, max: 120, menu: 'ringsector' }, + }, + draft: pluginRingsector, +} diff --git a/designs/sandy/src/curved-waistband.mjs b/designs/sandy/src/curved-waistband.mjs index 60c500163ff..c2cad07de0c 100644 --- a/designs/sandy/src/curved-waistband.mjs +++ b/designs/sandy/src/curved-waistband.mjs @@ -31,20 +31,12 @@ export function draftCurvedWaistband({ ) // Call the RingSector macro to draft the waistband - macro('ringsector', { + const ids = macro('ringsector', { angle: an + anExtra, insideRadius: rad, outsideRadius: rad + absoluteOptions.waistbandWidth, }) - const storeRoot = [ - 'parts', - part.name, - 'macros', - '@freesewing/plugin-ringsector', - 'ids', - 'ringsector', - ] - const pathId = store.get([...storeRoot, 'paths', 'path']) + const pathId = ids.paths.path paths.seam = paths[pathId].clone().addClass('fabric') paths[pathId].hide() @@ -52,7 +44,7 @@ export function draftCurvedWaistband({ * Macros ensure they can be used more than once in a part, and will generate unique (and complex) * point names. Since we're only calling the macro once here, we will simplify these names */ - for (const [shortId, uid] of Object.entries(store.get([...storeRoot, 'points']))) { + for (const [shortId, uid] of Object.entries(ids.points)) { points[shortId] = points[uid].copy() // Some points are rotated, we need those too if (points[uid + 'Rotated']) points[shortId + 'Rotated'] = points[uid + 'Rotated'].copy() diff --git a/designs/sandy/src/skirt.mjs b/designs/sandy/src/skirt.mjs index 5d12d36e3ec..adcca37b83f 100644 --- a/designs/sandy/src/skirt.mjs +++ b/designs/sandy/src/skirt.mjs @@ -86,21 +86,13 @@ function sandySkirt({ radiusWaist + store.get('fullLength') * options.lengthBonus - absoluteOptions.waistbandWidth // Call the RingSector macro to draft the part - macro('ringsector', { + const ids = macro('ringsector', { angle: an, insideRadius: radiusWaist, outsideRadius: radiusHem, rotate: true, }) - const storeRoot = [ - 'parts', - part.name, - 'macros', - '@freesewing/plugin-ringsector', - 'ids', - 'ringsector', - ] - const pathId = store.get([...storeRoot, 'paths', 'path']) + const pathId = ids.paths.path paths.seam = paths[pathId].clone().addClass('fabric') paths[pathId].hide() @@ -108,7 +100,7 @@ function sandySkirt({ * Macros ensure they can be used more than once in a part, and will generate unique (and complex) * point names. Since we're only calling the macro once here, we will simplify these names */ - for (const [shortId, uid] of Object.entries(store.get([...storeRoot, 'points']))) { + for (const [shortId, uid] of Object.entries(ids.points)) { points[shortId] = points[uid].copy() // Some points are rotated, we need those too if (points[uid + 'Rotated']) points[shortId + 'Rotated'] = points[uid + 'Rotated'].copy() diff --git a/packages/core/src/part.mjs b/packages/core/src/part.mjs index 86744cb236f..d7db8b1cb81 100644 --- a/packages/core/src/part.mjs +++ b/packages/core/src/part.mjs @@ -359,8 +359,20 @@ Part.prototype.__macroClosure = function (props) { const self = this const method = function (key, args) { const macro = utils.__macroName(key) - if (typeof self[macro] === 'function') return self[macro](args, props) - else if ('context' in self) + let parentMacro + if (typeof self[macro] === 'function') { + if ('context' in self) { + parentMacro = self.context.store.get('activeMacro', false) + self.context.store.set('activeMacro', key) + } + const result = self[macro](args, props) + if ('context' in self) { + if (parentMacro) self.context.store.set('activeMacro', parentMacro) + else self.context.store.unset('activeMacro') + } + + return result + } else if ('context' in self) self.context.store.log.warn('Unknown macro `' + key + '` used in ' + self.name) } diff --git a/packages/core/src/store.mjs b/packages/core/src/store.mjs index 2547f214189..3560e3b51c9 100644 --- a/packages/core/src/store.mjs +++ b/packages/core/src/store.mjs @@ -2,8 +2,20 @@ import set from 'lodash.set' import unset from 'lodash.unset' import get from 'lodash.get' -// Don't allow setting of these top-level keys in the store -const avoid = ['set', 'setIfUnset', 'push', 'unset', 'get', 'extend'] +/* + * Don't allow setting of these top-level keys in the store + */ +const avoid = [ + 'set', + 'setIfUnset', + 'push', + 'unset', + 'get', + 'extend', + 'generateMacroIds', + 'getMacroIds', + 'removeMacroNodes', +] ////////////////////////////////////////////// // CONSTRUCTOR // @@ -18,8 +30,7 @@ const avoid = ['set', 'setIfUnset', 'push', 'unset', 'get', 'extend'] */ export function Store(methods = []) { /* - * Default logging methods - * You can override these with a plugin + * Default logging containers */ const logs = { debug: [], @@ -27,6 +38,11 @@ export function Store(methods = []) { warn: [], error: [], } + + /* + * Default logging methods + * You can override these with a plugin + */ this.log = { debug: function (...data) { logs.debug.push(...data) @@ -42,17 +58,73 @@ export function Store(methods = []) { logs.error.push(...data) }, } + + /* + * Attach logs object + */ this.logs = logs + /* + * Method to generate macro IDs + */ + this.generateMacroIds = function (keys, id, macro = false) { + if (!macro) macro = this.get('activeMacro') + const ids = {} + for (const key of keys) ids[key] = `__macro_${macro}_${id}_${key}` + + return ids + } + + /* + * Method to store macro IDs + */ + this.storeMacroIds = function (id, ids, macro = false, part = false) { + if (!macro) macro = this.get('activeMacro') + if (!part) part = this.get('activePart') + this.set(['parts', part, 'macros', macro, 'ids', id], ids) + } + + /* + * Method to retrieve macro IDs + */ + this.getMacroIds = function (id, macro = false, part = false) { + if (!macro) macro = this.get('activeMacro') + if (!part) part = this.get('activePart') + + return this.get(['parts', part, 'macros', macro, 'ids', id], false) + } + + /* + * Method to remove nodes added by a macro + */ + this.removeMacroNodes = function (id, macro, part) { + const toRemove = this.getMacroIds(id, macro, part.name) + if (toRemove) { + if (toRemove.points) { + for (const nodeId of Object.values(toRemove.points)) delete part.points[nodeId] + } + if (toRemove.paths) { + for (const nodeId of Object.values(toRemove.paths)) delete part.paths[nodeId] + } + } + + return this.getMacroIds(id, macro) + } + + /* + * Add fallback packing algorithm + */ + this.pack = fallbackPacker + + /* + * Attache passed-in methods + */ for (const [path, method] of methods) { if (avoid.indexOf(path) !== -1) { this.log.warn(`You cannot overwrite \`store.${path}()\``) } else set(this, path, method) } - // Fallback packing algorithm - this.pack = fallbackPacker - return this } diff --git a/packages/core/tests/part.test.mjs b/packages/core/tests/part.test.mjs index deeaf4c781e..87590e29afb 100644 --- a/packages/core/tests/part.test.mjs +++ b/packages/core/tests/part.test.mjs @@ -363,4 +363,72 @@ describe('Part', () => { expect(typeof pattern.parts[0].to.paths.line).to.equal('object') expect(pattern.parts[0].to.paths.curve.ops[1].cp2.x).to.equal(200) }) + + it('Should set/unset the name of the active macro', () => { + const activeMacro = [] + const plugin = { + name: 'testplugin', + version: '0.0.1', + macros: { + macro1: (config, { part, store }) => { + activeMacro.push(store.activeMacro) + return part + }, + }, + } + const part = { + name: 'test', + draft: ({ macro, part }) => { + activeMacro.push(part.activeMacro) + macro('macro1') + activeMacro.push(part.activeMacro) + + return part + }, + } + const design = new Design({ parts: [part], plugins: [plugin] }) + const pattern = new design() + pattern.draft() + expect(activeMacro[0]).to.equal(undefined) + expect(activeMacro[1]).to.equal('macro1') + expect(activeMacro[2]).to.equal(undefined) + }) + + it('Should set/unset the name of the active macro in a nested macro', () => { + const activeMacro = [] + const plugin = { + name: 'testplugin', + version: '0.0.1', + macros: { + macro1: (config, { macro, part, store }) => { + activeMacro.push(store.activeMacro) + macro('macro2') + activeMacro.push(store.activeMacro) + return part + }, + macro2: (config, { part, store }) => { + activeMacro.push(store.activeMacro) + return part + }, + }, + } + const part = { + name: 'test', + draft: ({ macro, part }) => { + activeMacro.push(part.activeMacro) + macro('macro1') + activeMacro.push(part.activeMacro) + + return part + }, + } + const design = new Design({ parts: [part], plugins: [plugin] }) + const pattern = new design() + pattern.draft() + expect(activeMacro[0]).to.equal(undefined) + expect(activeMacro[1]).to.equal('macro1') + expect(activeMacro[2]).to.equal('macro2') + expect(activeMacro[3]).to.equal('macro1') + expect(activeMacro[4]).to.equal(undefined) + }) }) diff --git a/plugins/plugin-annotations/src/banner.mjs b/plugins/plugin-annotations/src/banner.mjs index 64e190c8bb3..ed3b2843214 100644 --- a/plugins/plugin-annotations/src/banner.mjs +++ b/plugins/plugin-annotations/src/banner.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the bannner macro */ @@ -15,12 +13,8 @@ const macroDefaults = { /* * The rmbanner macro */ -const rmbanner = function (id = macroDefaults.id, { paths, store, part }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', 'banner', 'ids', id, 'paths'], {}) - )) - delete paths[pid] -} +const rmbanner = (id = macroDefaults.id, { store, part }) => + store.removeMacroNodes(id, 'banner', part) const banner = function (config, { part, paths, store, complete }) { /* @@ -36,7 +30,7 @@ const banner = function (config, { part, paths, store, complete }) { /* * Get the list of IDs */ - const ids = getIds(['banner'], mc.id, 'banner') + const ids = store.generateMacroIds(['banner'], mc.id) /* * Prepare the path to hold the banner text @@ -57,9 +51,12 @@ const banner = function (config, { part, paths, store, complete }) { /* * Store all IDs in the store so we can remove this macro with rmbanner */ - store.set(['parts', part.name, 'macros', 'banner', 'ids', mc.id, 'paths'], ids) + store.storeMacroIds(mc.id, { paths: ids }) - return store.getMacroIds(config.id, 'banner') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros diff --git a/plugins/plugin-annotations/src/bannerbox.mjs b/plugins/plugin-annotations/src/bannerbox.mjs index 60d3892a670..4acbfbd6d21 100644 --- a/plugins/plugin-annotations/src/bannerbox.mjs +++ b/plugins/plugin-annotations/src/bannerbox.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the bannerbox macro */ @@ -20,12 +18,9 @@ const macroDefaults = { * Removing all this is easy as all IDs are available in the store * and all we need to remove are paths. */ -const rmbannerbox = function (id = macroDefaults.id, { paths, store, part, macro }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', 'bannerbox', 'ids', id, 'paths'], {}) - )) - delete paths[pid] +const rmbannerbox = (id = macroDefaults.id, { macro, store, part }) => { macro('rmbanner', id) + return store.removeMacroNodes(id, 'bannerbox', part) } /* @@ -64,7 +59,7 @@ const bannerbox = function (config, { Point, paths, Path, part, macro, log, stor /* * Get the list of IDs */ - const ids = getIds(['box'], mc.id, 'bannerbox') + const ids = store.generateMacroIds(['box'], mc.id) /* * Calculate the offset from the bounding box @@ -99,9 +94,12 @@ const bannerbox = function (config, { Point, paths, Path, part, macro, log, stor /* * Store all IDs in the store so we can remove this macro with rmtitle */ - store.set(['parts', part.name, 'macros', 'bannerbox', 'ids', mc.id, 'paths'], ids) + store.storeMacroIds(mc.id, { paths: ids }) - return store.getMacroIds(mc.id, 'bannerbox') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } export const bannerboxMacros = { bannerbox, rmbannerbox } diff --git a/plugins/plugin-annotations/src/bartack.mjs b/plugins/plugin-annotations/src/bartack.mjs index 0f762732aff..dc73e6325bd 100644 --- a/plugins/plugin-annotations/src/bartack.mjs +++ b/plugins/plugin-annotations/src/bartack.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the bartack macro */ @@ -122,26 +120,25 @@ function createBartack(config, props) { /* * Get the list of IDs */ - const ids = getIds(['stitches'], mc.id, name) + const ids = props.store.generateMacroIds(['stitches'], mc.id) paths[ids.stitches] = bartackPath(guide, mc, props).attr('class', mc.classes) /* * Store all IDs in the store so we can remove this macro with rm[name] */ - props.store.set(['parts', props.part.name, 'macros', name, 'ids', mc.id, 'paths'], ids) + props.store.storeMacroIds(mc.id, { paths: ids }) - return props.store.getMacroIds(mc.id, name) + /* + * Returning ids is a best practice for FreeSewing macros + */ + return props.store.getMacroIds(mc.id) } /* * The method that will remove all macros */ -const removeBartack = function (name = 'bartack', id = macroDefaults.id, { paths, store, part }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', name, 'ids', id, 'paths'], {}) - )) - delete paths[pid] -} +const removeBartack = (name = 'bartack', id = macroDefaults.id, { store, part }) => + store.removeMacroNodes(id, name, part) /* * The rmbartackalong and rmbartackfractionalong macros just call rmbartack with the correct name diff --git a/plugins/plugin-annotations/src/crossbox.mjs b/plugins/plugin-annotations/src/crossbox.mjs index 6df9648a0a1..a793e77f063 100644 --- a/plugins/plugin-annotations/src/crossbox.mjs +++ b/plugins/plugin-annotations/src/crossbox.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the title macro */ @@ -17,14 +15,8 @@ const macroDefaults = { /* * The rmcrossbox macro */ -const rmcrossbox = function (id = macroDefaults.id, { paths, points, store, part }) { - const both = store.get(['parts', part.name, 'macros', 'title', 'ids', id], { - paths: {}, - points: {}, - }) - for (const pid of Object.values(both.points)) delete points[pid] - for (const pid of Object.values(both.paths)) delete paths[pid] -} +const rmcrossbox = (id = macroDefaults.id, { store, part }) => + store.removeMacroNodes(id, 'crossbox', part) /* * The crossbox macro @@ -62,7 +54,7 @@ const crossbox = function (config, { points, Point, paths, Path, complete, store /* * Get the list of IDs */ - const flatIds = getIds(['box', 'cross', 'text'], mc.id, 'crossbox') + const flatIds = store.generateMacroIds(['box', 'cross', 'text'], mc.id) const ids = { paths: { box: flatIds.box, @@ -118,9 +110,12 @@ const crossbox = function (config, { points, Point, paths, Path, complete, store * Store all IDs in the store so we can remove this macro with rmtitle * Just make sure to keep points and paths apart */ - store.set(['parts', part.name, 'macros', 'title', 'ids', mc.id], ids) + store.storeMacroIds(mc.id, ids) - return store.getMacroIds(mc.id, 'crossbox') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros diff --git a/plugins/plugin-annotations/src/cutonfold.mjs b/plugins/plugin-annotations/src/cutonfold.mjs index 1907edd6026..b4d2acef199 100644 --- a/plugins/plugin-annotations/src/cutonfold.mjs +++ b/plugins/plugin-annotations/src/cutonfold.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the cutonfold macro */ @@ -36,12 +34,8 @@ export const cutonfoldDefs = [ /* * The rmcutonfold macro */ -const rmcutonfold = function (id = macroDefaults.id, { paths, store, part }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', 'cutonfold', 'ids', id, 'paths'], {}) - )) - delete paths[pid] -} +const rmcutonfold = (id = macroDefaults.id, { store, part }) => + store.removeMacroNodes(id, 'cutonfold', part) /* * The cutonfold macro @@ -86,7 +80,7 @@ const cutonfold = function (config, { paths, Path, complete, store, scale, log, /* * Get the list of IDs */ - const ids = getIds(['line'], mc.id, 'cutonfold') + const ids = store.generateMacroIds(['line'], mc.id) /* * Draw the path @@ -106,9 +100,12 @@ const cutonfold = function (config, { paths, Path, complete, store, scale, log, /* * Store all IDs in the store so we can remove this macro with rmcutonfold */ - store.set(['parts', part.name, 'macros', 'cutonfold', 'ids', mc.id, 'paths'], ids) + store.storeMacroIds(mc.id, { paths: ids }) - return store.getMacroIds(mc.id, 'cutonfold') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros diff --git a/plugins/plugin-annotations/src/dimensions.mjs b/plugins/plugin-annotations/src/dimensions.mjs index baf3704b6b9..af868db0b4a 100644 --- a/plugins/plugin-annotations/src/dimensions.mjs +++ b/plugins/plugin-annotations/src/dimensions.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - // Export defs export const dimensionsDefs = [ { @@ -122,7 +120,7 @@ const addDimension = (config, props, type) => { /* * Get the list of IDs */ - const ids = getIds(['line', 'from', 'to'], mc.id, type) + const ids = props.store.generateMacroIds(['line', 'from', 'to'], mc.id) /* * Draw the dimension @@ -150,28 +148,28 @@ const addDimension = (config, props, type) => { /* * Store all IDs in the store so we can remove this macro with rm variants */ - props.store.set(['parts', props.part.name, 'macros', type, 'ids', mc.id, 'paths'], ids) + props.store.storeMacroIds(mc.id, { paths: ids }) - return props.store.getMacroIds(mc.id, type) + /* + * Returning ids is a best practice for FreeSewing macros + */ + return props.store.getMacroIds(mc.id) } /* * This method handles the 'remove' part for all macros */ -const removeDimension = function (id = macroDefaults.id, { paths, store, part }, type) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', type, 'ids', id, 'paths'], {}) - )) - delete paths[pid] +const removeDimension = function (id = macroDefaults.id, { store, part }, type) { + return store.removeMacroNodes(id, type, part) } /* * This method removes all dimensions of a given type */ const removeDimensionType = function ({ paths, store, part }, type) { - for (const ids of Object.values(store.get(['parts', part.name, 'macros', type, 'ids'], {}))) { - for (const pid of Object.values(ids.paths)) delete paths[pid] - } + // Get all macro IDs of the given type + const ids = store.get(['parts', part.name, 'macros', type, 'ids'], {}) + for (const id in ids) store.removeMacroNodes(id, type, part) } /* diff --git a/plugins/plugin-annotations/src/grainline.mjs b/plugins/plugin-annotations/src/grainline.mjs index c1145736a09..9455100400a 100644 --- a/plugins/plugin-annotations/src/grainline.mjs +++ b/plugins/plugin-annotations/src/grainline.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the grainline macro */ @@ -34,12 +32,8 @@ export const grainlineDefs = [ /* * The rmgrainline macro */ -const rmgrainline = function (id = macroDefaults.id, { paths, store, part }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', 'grainline', 'ids', id, 'paths'], {}) - )) - delete paths[pid] -} +const rmgrainline = (id = macroDefaults.id, { store, part }) => + store.removeMacroNodes(id, 'grainline', part) /* * The grainline macro @@ -80,7 +74,7 @@ const grainline = function (config = {}, { paths, Path, Point, complete, store, /* * Get the list of IDs */ - const ids = getIds(['line'], mc.id, 'grainline') + const ids = store.generateMacroIds(['line'], mc.id) /* * Draw the path @@ -98,9 +92,12 @@ const grainline = function (config = {}, { paths, Path, Point, complete, store, /* * Store all IDs in the store so we can remove this macro with rmgrainline */ - store.set(['parts', part.name, 'macros', 'grainline', 'ids', mc.id, 'paths'], ids) + store.storeMacroIds(mc.id, { paths: ids }) - return store.getMacroIds(mc.id, 'grainline') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros diff --git a/plugins/plugin-annotations/src/index.mjs b/plugins/plugin-annotations/src/index.mjs index f654133c72e..aecfadcddbe 100644 --- a/plugins/plugin-annotations/src/index.mjs +++ b/plugins/plugin-annotations/src/index.mjs @@ -21,7 +21,6 @@ import { pleatMacros, pleatDefs } from './pleat.mjs' import { sewtogetherMacros, sewtogetherDefs } from './sewtogether.mjs' // Only stores import { flagStores } from './flag.mjs' -import { utilsStores } from './utils.mjs' export const plugin = { name, @@ -62,7 +61,7 @@ export const plugin = { ...sewtogetherMacros, ...titleMacros, }, - store: [...cutlistStores, ...flagStores, ...utilsStores], + store: [...cutlistStores, ...flagStores], } export const annotationsPlugin = plugin diff --git a/plugins/plugin-annotations/src/pleat.mjs b/plugins/plugin-annotations/src/pleat.mjs index 87e900b3f1b..fb34c5a1b74 100644 --- a/plugins/plugin-annotations/src/pleat.mjs +++ b/plugins/plugin-annotations/src/pleat.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the pleat macro */ @@ -29,12 +27,8 @@ export const pleatDefs = [ /* * The rmpleat macro */ -const rmpleat = function (id = macroDefaults.id, { paths, store, part }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', 'pleat', 'ids', id, 'paths'], {}) - )) - delete paths[pid] -} +const rmpleat = (id = macroDefaults.id, { store, part }) => + store.removeMacroNodes(id, 'rmpleat', part) /* * The pleat macro @@ -71,7 +65,7 @@ const pleat = function (config, { paths, Path, log, Point, complete, scale, stor * Get the list of IDs * Initialize the verticle cadence */ - const ids = getIds(['from', 'to', 'arrow'], mc.id, 'pleat') + const ids = store.generateMacroIds(['from', 'to', 'arrow'], mc.id) const toIn = mc.to.shift(mc.from.shiftTowards(mc.to, 0.1).angle(mc.to) + 90, mc.margin * scale) const fromIn = mc.from.shift( @@ -109,9 +103,12 @@ const pleat = function (config, { paths, Path, log, Point, complete, scale, stor /* * Store all IDs in the store so we can remove this macro with rmpleat */ - store.set(['parts', part.name, 'macros', 'pleat', 'ids', mc.id, 'paths'], ids) + store.storeMacroIds(mc.id, { paths: ids }) - return store.getMacroIds(mc.id, 'pleat') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros diff --git a/plugins/plugin-annotations/src/scalebox.mjs b/plugins/plugin-annotations/src/scalebox.mjs index 4ee6e26438b..1c2f856a381 100644 --- a/plugins/plugin-annotations/src/scalebox.mjs +++ b/plugins/plugin-annotations/src/scalebox.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the title macro */ @@ -65,9 +63,7 @@ const sizes = { */ const removeScaleAnnotation = function (id = false, { paths, points, store, part }, type) { if (!id) id = type - const both = store.get(['parts', part.name, 'macros', type, 'ids', id], { paths: {}, points: {} }) - for (const pid of Object.values(both.points)) delete points[pid] - for (const pid of Object.values(both.paths)) delete paths[pid] + return store.removeMacroNodes(id, type, part) } /* @@ -114,7 +110,7 @@ const scalebox = function ( /* * Get the list of IDs */ - const ids = getIds( + const ids = store.generateMacroIds( [ 'metric', 'imperial', @@ -125,8 +121,7 @@ const scalebox = function ( 'textText', 'textLink', ], - mc.id, - 'scalebox' + mc.id ) /* @@ -245,7 +240,7 @@ const scalebox = function ( /* * Store all IDs in the store so we can remove this macro with rmscaleboc */ - store.set(['parts', part.name, 'macros', 'scalebox', 'ids', mc.id], { + store.storeMacroIds(mc.id, { points: { textLead: ids.textLead, textMetric: ids.textMetric, @@ -260,7 +255,10 @@ const scalebox = function ( }, }) - return store.getMacroIds(mc.id, 'scalebox') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } /* @@ -306,7 +304,7 @@ const miniscale = function ( /* * Get the list of IDs */ - const ids = getIds(['metric', 'imperial', 'textMetric', 'textImperial'], mc.id, 'miniscale') + const ids = store.generateMacroIds(['metric', 'imperial', 'textMetric', 'textImperial'], mc.id) /* * Box points (no need to add these to the part) @@ -384,7 +382,7 @@ const miniscale = function ( /* * Store all IDs in the store so we can remove this macro with rmscaleboc */ - store.set(['parts', part.name, 'macros', 'miniscale', 'ids', mc.id], { + store.storeMacroIds(mc.id, { points: { textMetric: ids.textMetric, textImperial: ids.textImperial, @@ -394,6 +392,11 @@ const miniscale = function ( imperial: ids.imperial, }, }) + + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros diff --git a/plugins/plugin-annotations/src/sewtogether.mjs b/plugins/plugin-annotations/src/sewtogether.mjs index 9d5ee9befe5..1a2de63230e 100644 --- a/plugins/plugin-annotations/src/sewtogether.mjs +++ b/plugins/plugin-annotations/src/sewtogether.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the sewtogether macro */ @@ -42,12 +40,8 @@ export const sewtogetherDefs = [ /* * The rmsewtogether macro */ -const rmsewtogether = function (id = macroDefaults.id, { paths, store, part }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', 'sewtogether', 'ids', id, 'paths'], {}) - )) - delete paths[pid] -} +const rmsewtogether = (id = macroDefaults.id, { store, part }) => + store.removeMacroNodes(id, 'sewtogether', part) /* * The sewtogether macro @@ -89,7 +83,7 @@ const sewtogether = function (config, { paths, Path, log, Point, complete, sa, s * Get the list of IDs * Initialize the verticle cadence */ - const ids = getIds(['curve', 'hinge'], mc.id, 'sewtogether') + const ids = store.generateMacroIds(['curve', 'hinge'], mc.id) /* * Draw the curve @@ -124,9 +118,12 @@ const sewtogether = function (config, { paths, Path, log, Point, complete, sa, s /* * Store all IDs in the store so we can remove this macro with rmsewtogether */ - store.set(['parts', part.name, 'macros', 'sewtogether', 'ids', mc.id, 'paths'], ids) + store.storeMacroIds(mc.id, { paths: ids }) - return store.getMacroIds(mc.id, 'sewtogether') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros diff --git a/plugins/plugin-annotations/src/title.mjs b/plugins/plugin-annotations/src/title.mjs index 628d3d3fbf8..79af07f8031 100644 --- a/plugins/plugin-annotations/src/title.mjs +++ b/plugins/plugin-annotations/src/title.mjs @@ -1,5 +1,3 @@ -import { getIds } from './utils.mjs' - /* * Defaults for the title macro */ @@ -24,24 +22,10 @@ const macroDefaults = { }, } -/* - * Removing all this is easy as all IDs are available in the store - * and all we need to remove are points. - */ -const removeTitleMacro = function (id = macroDefaults.id, { points, store, part }) { - for (const pid of Object.values( - store.get(['parts', part.name, 'macros', 'title', 'ids', id, 'points'], {}) - )) - delete points[pid] -} - /* * The title macro */ -const addTitleMacro = function ( - config, - { Point, points, scale, locale, store, part, log, complete } -) { +const title = function (config, { Point, points, scale, locale, store, part, log, complete }) { /* * Don't add a title when complete is false, unless force is true */ @@ -92,7 +76,7 @@ const addTitleMacro = function ( * Get the list of IDs * Initialize the verticle cadence */ - const ids = getIds(['cutlist', 'date', 'for', 'name', 'nr', 'title'], mc.id, 'title') + const ids = store.generateMacroIds(['cutlist', 'date', 'for', 'name', 'nr', 'title'], mc.id) let shift = mc.dy @@ -229,13 +213,16 @@ const addTitleMacro = function ( /* * Store all IDs in the store so we can remove this macro with rmtitle */ - store.set(['parts', part.name, 'macros', 'title', 'ids', mc.id, 'points'], ids) + store.storeMacroIds(mc.id, { points: ids }) - return store.getMacroIds(mc.id, 'title') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) } // Export macros export const titleMacros = { - title: addTitleMacro, - rmtitle: removeTitleMacro, + title, + rmtitle: (id = macroDefaults.id, { store, part }) => store.removeMacroNodes(id, 'title', part), } diff --git a/plugins/plugin-annotations/src/utils.mjs b/plugins/plugin-annotations/src/utils.mjs deleted file mode 100644 index 8f7ec92a279..00000000000 --- a/plugins/plugin-annotations/src/utils.mjs +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Helper method to get the various IDs for a macro - */ -export const getIds = (keys, id, macroName) => { - const ids = {} - for (const key of keys) ids[key] = `__macro_${macroName}_${id}_${key}` - - return ids -} - -/* - * Helper method to get an existing macro id - */ -const getIdsFromStore = (store, id, macroName, partName = false) => { - if (!partName) partName = store.activePart - const data = store.get(['parts', partName, 'macros', macroName, 'ids', id]) - - return data ? data : false -} - -/* - * Add these to the store - */ -export const utilsStores = [ - ['createMacroIds', (store, keys, id, macroName) => getIds(keys, id, macroName)], - ['getMacroIds', getIdsFromStore], -] diff --git a/plugins/plugin-ringsector/src/index.mjs b/plugins/plugin-ringsector/src/index.mjs index 03e13214a20..633ea59b7f6 100644 --- a/plugins/plugin-ringsector/src/index.mjs +++ b/plugins/plugin-ringsector/src/index.mjs @@ -66,7 +66,7 @@ export const plugin = { * Get the list of IDs */ const ids = getIds(keys, id) - const pathId = getIds(['path'], id).path + const pathIds = getIds(['path'], id) /** * Calculates the distance of the control point for the internal @@ -145,8 +145,8 @@ export const plugin = { points[ids[id] + 'Rotated'].rotate(deg, points[ids.in2Flipped]) } } - // Return the path of the full ring sector - paths[pathId] = new Path() + // Construct the path of the full ring sector + paths[pathIds.path] = new Path() .move(points[ids.in2Flipped]) .curve(points[ids.in2cFlipped], points[ids.in1cFlipped], points[ids.in1]) .curve(points[ids.in1c], points[ids.in2c], points[ids.in2]) @@ -158,8 +158,15 @@ export const plugin = { /* * Store all IDs in the store so we can remove this macro with rmringsector */ - store.set(['parts', part.name, 'macros', name, 'ids', id, 'paths'], { path: pathId }) - store.set(['parts', part.name, 'macros', name, 'ids', id, 'points'], ids) + store.storeMacroIds(mc.id, { + paths: pathIds, + points: ids, + }) + + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) }, }, } diff --git a/plugins/plugin-round/src/index.mjs b/plugins/plugin-round/src/index.mjs index 072dec71f91..0243c736ffa 100644 --- a/plugins/plugin-round/src/index.mjs +++ b/plugins/plugin-round/src/index.mjs @@ -1,5 +1,4 @@ import { name, version } from '../data.mjs' -import { getIds } from './utils.mjs' /* * These are the keys for macro IDs @@ -22,7 +21,9 @@ export const plugin = { hide = true, } = mc let { radius = 66.6 } = mc - const ids = getIds([...pointKeys, ...pathKeys], id, name) + const pointIds = store.generateMacroIds(pointKeys, id) + const pathIds = store.generateMacroIds(pathKeys, id) + const ids = { ...pointIds, ...pathIds } const fd = from.dist(via) const td = to.dist(via) @@ -41,16 +42,15 @@ export const plugin = { /* * Store all IDs in the store so we can remove this macro with rmtitle */ - store.set( - ['parts', part.name, 'macros', 'round', 'ids', mc.id, 'points'], - getIds(pointKeys, id, name) - ) - store.set( - ['parts', part.name, 'macros', 'round', 'ids', mc.id, 'paths'], - getIds(pathKeys, id, name) - ) + store.storeMacroIds(mc.id, { + paths: pathIds, + points: pointIds, + }) - return store.getMacroIds(id, 'round') + /* + * Returning ids is a best practice for FreeSewing macros + */ + return store.getMacroIds(mc.id) }, }, } diff --git a/plugins/plugin-round/src/utils.mjs b/plugins/plugin-round/src/utils.mjs deleted file mode 100644 index f513c13fca8..00000000000 --- a/plugins/plugin-round/src/utils.mjs +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Helper method to get the various IDs for a macro - */ -export const getIds = (keys, id, macroName) => { - const ids = {} - for (const key of keys) ids[key] = `__macro_${macroName}_${id}_${key}` - - return ids -}