diff --git a/plugins/plugin-annotations/src/bartack.mjs b/plugins/plugin-annotations/src/bartack.mjs index 08348779166..dc03ba4beca 100644 --- a/plugins/plugin-annotations/src/bartack.mjs +++ b/plugins/plugin-annotations/src/bartack.mjs @@ -1,3 +1,25 @@ +import { getIds } from './utils.mjs' + +/* + * Defaults for the bartack macro + */ +const macroDefaults = { + anchor: false, + angle: 0, + bartackAlong: false, + bartackFractionAlong: false, + classes: 'stroke-sm stroke-mark', + density: 3, + end: 1, + from: false, + id: 'bartack', + length: 15, + path: false, + start: 0, + to: false, + width: 3, +} + // Method that draws the actual bartack const drawBartack = (pointList, { Path }) => { let path = new Path().move(pointList.path1[0]) @@ -10,9 +32,9 @@ const drawBartack = (pointList, { Path }) => { } // Helper method to generate the points to draw on later -const getPoints = (path, so) => { - let path1 = path.offset(so.width / 2) - let path2 = path.offset(so.width / -2) +const getPoints = (path, mc) => { + let path1 = path.offset(mc.width / 2) + let path2 = path.offset(mc.width / -2) let len = path1.length() let len2 = path2.length() @@ -28,7 +50,7 @@ const getPoints = (path, so) => { path1: [path1.start()], path2: [path2.start()], } - let steps = Math.ceil((len / so.width) * so.density) + let steps = Math.ceil((len / mc.width) * mc.density) for (let i = 1; i < steps; i++) { points.path1.push(path1.shiftFractionAlong((1 / steps) * i)) points.path2.push(path2.shiftFractionAlong((1 / steps) * i)) @@ -37,88 +59,138 @@ const getPoints = (path, so) => { return points } -const bartackPath = (path, so, props) => (path ? drawBartack(getPoints(path, so), props) : null) +const bartackPath = (path, mc, props) => (path ? drawBartack(getPoints(path, mc), props) : null) -function createBartack(so, props) { - const defaults = { - width: 3, - length: 15, - density: 3, - angle: 0, - prefix: '', - suffix: '', - anchor: false, - path: false, - from: false, - to: false, - start: 0, - end: 1, - bartackAlong: false, - bartackFractionAlong: false, - } - so = { ...defaults, ...so } +/* + * This method creates the actual bartack + */ +function createBartack(config, props) { + /* + * Don't add a bartack when complete is false, unless force is true + */ + if (!props.complete && !config.force) return + /* + * Merge macro defaults with user-provided config to create the macro config (mc) + */ + const mc = { ...macroDefaults, ...config } + + /* + * Destructure what we need from props + */ const { Path, paths } = props - // Handle negative angle - if (so.angle < 0) so.angle = 360 + (so.angle % -360) + /* + * Handle negative angle + */ + if (mc.angle < 0) mc.angle = 360 + (mc.angle % -360) + /* + * Construct the guide path + */ let guide = false - - if (so.anchor) + let name = 'bartack' + if (mc.anchor) // Anchor + angle + length - guide = new Path().move(so.anchor).line(so.anchor.shift(so.angle, so.length)) - else if (so.from && so.to) + guide = new Path().move(mc.anchor).line(mc.anchor.shift(mc.angle, mc.length)) + else if (mc.from && mc.to) // From to - guide = new Path().move(so.from).line(so.to) - else if (so.path) { + guide = new Path().move(mc.from).line(mc.to) + else if (mc.path) { // Along path let start = false let end = false - if (so.bartackAlong) guide = so.path.clone() - else if (so.bartackFractionAlong) { - if (so.start === so.end) return null - if (so.start > so.end) { - const newEnd = so.start - so.start = so.end - so.end = newEnd + name = 'bartackalong' + if (mc.bartackAlong) guide = mc.path.clone() + else if (mc.bartackFractionAlong) { + name = 'bartackfractionalong' + if (mc.start === mc.end) return null + if (mc.start > mc.end) { + const newEnd = mc.start + mc.start = mc.end + mc.end = newEnd } - if (so.start > 0) start = so.path.shiftFractionAlong(so.start) - if (so.end < 1) end = so.path.shiftFractionAlong(so.end) - if (start && end) guide = so.path.split(start).pop().split(end).shift() - else if (start) guide = so.path.split(start).pop() - else if (end) guide = so.path.split(end).shift() - else guide = so.path.clone() + if (mc.start > 0) start = mc.path.shiftFractionAlong(mc.start) + if (mc.end < 1) end = mc.path.shiftFractionAlong(mc.end) + if (start && end) guide = mc.path.split(start).pop().split(end).shift() + else if (start) guide = mc.path.split(start).pop() + else if (end) guide = mc.path.split(end).shift() + else guide = mc.path.clone() } } - paths[`${so.prefix}bartack${so.suffix}`] = bartackPath(guide, so, props).attr( - 'class', - 'stroke-sm stroke-mark' + /* + * Get the list of IDs + */ + const ids = getIds(['stitches'], mc.id, name) + 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) +} + +/* + * 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] +} + +/* + * The rmbartackalong and rmbartackfractionalong macros just call rmbartack with the correct name + */ +const rmbartack = (id, props) => removeBartack('bartack', id, props) +const rmbartackAlong = (id, props) => removeBartack('bartackalong', id, props) +const rmbartackFractionAlong = (id, props) => removeBartack('bartackfractionalong', id, props) + +/* + * The bartack macro + */ +const bartack = (config, props) => createBartack(config, props) + +/* + * The bartackAlong macro + */ +const bartackAlong = (config, props) => + createBartack( + { + ...config, + bartackFractionAlong: false, + bartackAlong: true, + anchor: false, + from: false, + to: false, + }, + props ) - return true -} +/* + * The bartackFractionAlong macro + */ +const bartackFractionAlong = (config, props) => + createBartack( + { + ...config, + bartackFractionAlong: true, + bartackAlong: false, + anchor: false, + from: false, + to: false, + }, + props + ) // Export macros export const bartackMacros = { - bartack: function (so, props) { - return createBartack(so, props) - }, - bartackAlong: function (so, props) { - so.bartackFractionAlong = false - so.bartackAlong = true - so.anchor = false - so.from = false - so.to = false - return createBartack(so, props) - }, - bartackFractionAlong: function (so, props) { - so.bartackFractionAlong = true - so.bartackAlong = false - so.anchor = false - so.from = false - so.to = false - return createBartack(so, props) - }, + bartack, + bartackAlong, + bartackFractionAlong, + rmbartack, + rmbartackAlong, + rmbartackFractionAlong, }