import { getIds } from './utils.mjs' /* * Defaults for the sewtogether macro */ const macroDefaults = { classes: { curve: 'dotted note stroke-sm', hinge: 'note dotted stroke-sm', text: 'center fill-note text-xs', }, id: 'sewtogether', force: false, text: 'plugin-annotations:sewTogether', } // Export defs export const sewtogetherDefs = [ { name: 'sewTogetherStart', def: ` `, }, { name: 'sewTogetherEnd', def: ` `, }, { name: 'sewTogetherCross', def: ` `, }, ] /* * 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] } /* * The sewtogether macro */ const sewtogether = function (config, { paths, Path, log, Point, complete, sa, store, part }) { /* * Don't add a title when complete is false, unless force is true */ if (!complete && !config.force) return /* * Merge macro defaults with user-provided config to create the macro config (mc) */ const mc = { ...macroDefaults, ...config, classes: macroDefaults.classes, } if (config.classes) mc.classes = { ...mc.classes, ...config.classes } /* * Make sure mc.from and mc.to are Point instances */ if (!mc.from || typeof mc.from.attr !== 'function') { log.warn(`Sewtogether macro called without a valid from point. Using (0,0) for from.`) mc.from = new Point(0, 0) } if (!mc.to || typeof mc.to.attr !== 'function') { log.warn(`Sewtogether macro called without a valid to point. Using (666,666) for to.`) mc.to = new Point(666, 666) } /* * Ensure we have a middle point */ if (!mc.middle) mc.middle = mc.from.shiftFractionTowards(mc.to, 0.5) /* * Get the list of IDs * Initialize the verticle cadence */ const ids = getIds(['curve', 'hinge'], mc.id, 'sewtogether') /* * Draw the curve */ const fromCp = mc.from.shift(mc.from.angle(mc.middle) + 90, mc.from.dist(mc.middle) / 1.5) const toCp = mc.to.shift(mc.to.angle(mc.middle) - 90, mc.to.dist(mc.middle) / 1.5) paths[ids.curve] = new Path() .move(mc.from) .curve(fromCp, toCp, mc.to) .attr('class', mc.classes.curve) .attr('marker-start', 'url(#sewTogetherStart)') .attr('marker-end', 'url(#sewTogetherEnd)') .addText(mc.text, mc.classes.text) /* * Draw the hinge, if needed */ if (mc.hinge) { const hinge = mc.middle.shift( mc.middle.angle(mc.to) + Math.abs(mc.middle.angle(mc.from) - mc.middle.angle(mc.to)) / 2 + (sa ? 180 : 0), sa ? sa : mc.from.dist(mc.middle) / 4 ) paths[ids.hinge] = new Path() .move(mc.middle) .line(hinge) .attr('marker-start', 'url(#sewTogetherCross)') .attr('class', mc.classes.hinge) } else delete ids.hinge /* * 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) } // Export macros export const sewtogetherMacros = { sewtogether, rmsewtogether }