1
0
Fork 0

feat(core): Better support for macro removal an node id tracking

This commit is contained in:
Joost De Cock 2023-10-18 16:00:15 +02:00
parent 7939c1bc45
commit cb106578b3
24 changed files with 327 additions and 223 deletions

View file

@ -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,
}

View file

@ -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'),
})
}

View file

@ -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,
}

View file

@ -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()

View file

@ -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()

View file

@ -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)
}

View file

@ -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
}

View file

@ -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)
})
})

View file

@ -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

View file

@ -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 }

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)
}
/*

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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),
}

View file

@ -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],
]

View file

@ -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)
},
},
}

View file

@ -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)
},
},
}

View file

@ -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
}