1
0
Fork 0

Merge pull request #3919 from freesewing/develop

Get up to date with develop
This commit is contained in:
Wouter van Wageningen 2023-04-26 23:24:53 -07:00 committed by GitHub
commit e9ab680c53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
394 changed files with 9683 additions and 6225 deletions

View file

@ -12,8 +12,12 @@ export const bannerMacros = {
}
so.path.attr('data-text-dy', so.dy).attr('data-text-class', `${so.className} center`)
const spacer = ' '.repeat(so.spaces)
let banner = spacer
for (let i = 0; i < so.repeat; i++) banner += so.text + '&#160;'.repeat(so.spaces)
so.path.attr('data-text', banner)
for (let i = 0; i < so.repeat; i++) {
so.path.attr('data-text', spacer)
so.path.attr('data-text', so.text)
}
so.path.attr('data-text', spacer)
},
}

View file

@ -0,0 +1,103 @@
export const cutlistStores = [
['cutlist.addCut', addCut],
['cutlist.removeCut', removeCut],
['cutlist.setGrain', setGrain],
['cutlist.setCutOnFold', setCutOnFold],
['cutlist.getCutFabrics', getCutFabrics],
]
export const cutlistHooks = {
prePartDraft: [
function (pattern) {
const injectedPart = pattern.config.inject[pattern.activePart]
if (!injectedPart) return
const store = pattern.setStores[pattern.activeSet]
const injectedCutlist = store.get(['cutlist', injectedPart], {})
store.set(['cutlist', pattern.activePart], { ...injectedCutlist })
},
],
}
/**
* Add a set of cutting instructions for the part
* @param {Store} store the Store
* @param {Object} so a set of cutting instructions for a material
* @param {number} so.cut = 2 the number of pieces to cut from the specified fabric
* @param {string} so.material = fabric the name of the material to cut from
* @param {boolean} so.identical = false should even numbers of pieces be cut in the same direction or mirrored
* @param {boolean} so.bias = false should the pieces in these cutting instructions be cut on the bias
* @param {boolean} so.ignoreOnFold should these cutting instructions ignore any cutOnFold information set by the part
*/
function addCut(store, so = {}) {
const { cut = 2, material = 'fabric', identical = false, bias = false, ignoreOnFold = false } = so
const partName = store.get('activePart')
if (cut === false) {
if (material === false) store.unset(['cutlist', partName, 'materials'])
else store.unset(['cutlist', partName, 'materials', material])
return store
}
if (!(Number.isInteger(cut) && cut > -1)) {
store.log.error(`Tried to set cut to a value that is not a positive integer`)
return store
}
if (typeof material !== 'string') {
store.log.warning(`Tried to set material to a value that is not a string`)
return store
}
const path = ['cutlist', partName, 'materials', material]
const existing = store.get(path, [])
store.set(path, existing.concat({ cut, identical, bias, ignoreOnFold }))
return store
}
/** Method to remove the cut info */
function removeCut(store, material = false) {
return addCut(store, { cut: false, material })
}
/** Method to add the grain info */
function setGrain(store, grain = false) {
const partName = store.get('activePart')
const path = ['cutlist', partName, 'grain']
if (grain === false) return store.unset(path)
if (typeof grain !== 'number') {
store.log.error('Called part.setGrain() with a value that is not a number')
return store
}
return store.set(path, grain)
}
/** Method to add the cutOnFold info */
function setCutOnFold(store, p1, p2) {
const partName = store.get('activePart')
const path = ['cutlist', partName, 'cutOnFold']
if (p1 === false && typeof p2 === 'undefined') {
return store.unset(path)
}
if (!isNaN(p1.x) && !isNaN(p1.y) && !isNaN(p2.x) && !isNaN(p2.y)) {
store.set(path, [p1, p2])
} else
store.log.error('Called part.setCutOnFold() but at least one parameter is not a Point instance')
return store
}
/** Get a list of fabrics used by the pattern for the given settings */
function getCutFabrics(store, settings) {
const cutlist = store.get('cutlist')
const list = settings.only ? [].concat(settings.only) : Object.keys(cutlist)
const fabrics = []
list.forEach((partName) => {
if (!cutlist[partName]?.materials) {
return
}
for (var m in cutlist[partName].materials) {
if (!fabrics.includes(m)) fabrics.push(m)
}
})
return fabrics
}

View file

@ -18,17 +18,15 @@ export const cutonfoldDefs = [
// Export macros
export const cutonfoldMacros = {
cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, scale }) {
cutonfold: function (so, { points, paths, Path, complete, store, scale }) {
if (so === false) {
delete points.cutonfoldFrom
delete points.cutonfoldTo
delete points.cutonfoldVia1
delete points.cutonfoldVia2
delete paths.cutonfold
// setCutOnFold relies on plugin-cutlist
if (typeof setCutOnFold === 'function') {
setCutOnFold(false) // Restore default
}
delete paths.cutonfoldCutonfold
store.cutlist.setCutOnFold(false) // Restore default
return true
}
so = {
@ -37,10 +35,11 @@ export const cutonfoldMacros = {
prefix: 'cutonfold',
...so,
}
if (typeof setCutOnFold === 'function') {
setCutOnFold(so.from, so.to)
if (so.grainline) setGrain(so.from.angle(so.to))
}
// store in cutlist
store.cutlist.setCutOnFold(so.from, so.to)
if (so.grainline) store.cutlist.setGrain(so.from.angle(so.to))
if (complete) {
points[so.prefix + 'From'] = so.from.shiftFractionTowards(so.to, so.margin / 100)
points[so.prefix + 'To'] = so.to.shiftFractionTowards(so.from, so.margin / 100)

View file

@ -20,22 +20,22 @@ const dflts = { text: 'grainline' }
// Export macros
export const grainlineMacros = {
grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
grainline: function (so = {}, { points, paths, Path, complete, store }) {
if (so === false) {
delete points.grainlineFrom
delete points.grainlineTo
delete paths.grainline
setGrain(90) // Restoring default
if (store.cutlist?.setGrain) store.cutlist.setGrain(90) // Restoring default
return true
}
so = {
...dflts,
...so,
}
// setGrain relies on plugin-cutlist
if (typeof setGrain === 'function') {
setGrain(so.from.angle(so.to))
}
// store in cutlist
store.cutlist.setGrain(so.from.angle(so.to))
if (complete) {
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)

View file

@ -8,6 +8,7 @@ import { bannerMacros } from './banner.mjs'
import { bannerboxMacros } from './bannerbox.mjs'
import { bartackMacros } from './bartack.mjs'
import { crossboxMacros } from './crossbox.mjs'
import { cutlistStores, cutlistHooks } from './cutlist.mjs'
import { scaleboxMacros } from './scalebox.mjs'
import { titleMacros } from './title.mjs'
// Defs and Macros
@ -41,6 +42,7 @@ export const plugin = {
}
},
],
prePartDraft: [...cutlistHooks.prePartDraft],
},
macros: {
...bannerMacros,
@ -55,6 +57,7 @@ export const plugin = {
...sewtogetherMacros,
...titleMacros,
},
store: [...cutlistStores],
}
export const annotationsPlugin = plugin

View file

@ -1,8 +1,9 @@
const titleMacro = function (so, { points, scale, locale, store }) {
const titleMacro = function (so, { points, scale, locale, store, part }) {
const prefix = so.prefix || ''
let overwrite = !so.append
// Passing `false` will remove the title
if (so === false) {
if (so === false || overwrite) {
for (const id of [
`_${prefix}_titleNr`,
`_${prefix}_titleName`,
@ -11,7 +12,8 @@ const titleMacro = function (so, { points, scale, locale, store }) {
`_${prefix}_exportDate`,
])
delete points[id]
return true
if (so === false) return true
}
const transform = function (anchor) {
@ -20,44 +22,72 @@ const titleMacro = function (so, { points, scale, locale, store }) {
return `matrix(${so.scale}, 0, 0, ${so.scale}, ${cx}, ${cy}) rotate(${so.rotation} ${anchor.x} ${anchor.y})`
}
let shift = 8
const nextPoint = (text, textClass, shiftAmt = shift) => {
const newPoint = so.at.shift(-90 - so.rotation, shiftAmt * so.scale).addText(text, textClass)
newPoint.attr('data-text-transform', transform(newPoint))
return newPoint
}
const defaults = {
scale: 1,
rotation: 0,
cutlist: true,
}
so = { ...defaults, ...so }
so.scale = so.scale * scale
let overwrite = true
if (so.append) overwrite = false
points[`_${prefix}_titleNr`] = so.at
.clone()
.attr('data-text', so.nr, overwrite)
.attr('data-text-class', 'text-4xl fill-note font-bold')
.attr('data-text-transform', transform(so.at))
let shift = 8
if (so.title) {
points[`_${prefix}_titleName`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
.attr('data-text', so.title)
.attr('data-text-class', 'text-lg fill-current font-bold')
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, 13 * so.scale)))
points[`_${prefix}_titleName`] = nextPoint(so.title, 'text-lg fill-current font-bold')
shift += 8
}
// Cut List instructions
const partCutlist = store.get(['cutlist', part.name])
// if there's a cutlist and it should be included
if (so.cutlist && partCutlist?.materials) {
// get the default cutonfold
const cutonfold = partCutlist.cutOnFold
// each material
for (const material in partCutlist.materials) {
// each set of instructions
partCutlist.materials[material].forEach(({ cut, identical, bias, ignoreOnFold }, c) => {
// make a new point for this set of instructions
const cutPoint = nextPoint('plugin:cut', 'text-md fill-current').addText(cut)
// if they're not identical, add that to the point's text
if (!identical && cut > 1) cutPoint.addText('plugin:mirrored')
// if they should be cut on the fold add that, with bias or without
if (cutonfold && !ignoreOnFold)
cutPoint.addText(bias ? 'plugin:onFoldAndBias' : 'plugin:onFoldLower')
// otherwise if they should be on the bias, say so
else if (bias) cutPoint.addText('plugin:onBias')
// add 'from' the material
cutPoint.addText('plugin:from').addText('plugin:' + material)
// save and shift
points[`_${prefix}_titleCut_${material}_${c}`] = cutPoint
shift += 8
})
}
}
let name = store.data?.name || 'No Name'
name = name.replace('@freesewing/', '')
points[`_${prefix}_titlePattern`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
.attr('data-text', name)
.attr('data-text', 'v' + (store.data?.version || 'No Version'))
.attr('data-text-class', 'fill-note')
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
name += ' v' + (store.data?.version || 'No Version')
points[`_${prefix}_titlePattern`] = nextPoint(name, 'fill-note')
if (store.data.for) {
shift += 8
points[`_${prefix}_titleFor`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
.attr('data-text', '( ' + store.data.for + ' )')
.attr('data-text-class', 'fill-current font-bold')
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
points[`_${prefix}_titleFor`] = nextPoint(`( ${store.data.for} )`, 'fill-current font-bold')
}
shift += 6
const now = new Date()
@ -65,20 +95,13 @@ const titleMacro = function (so, { points, scale, locale, store }) {
let mins = now.getMinutes()
if (hours < 10) hours = `0${hours}`
if (mins < 10) mins = `0${mins}`
points[`_${prefix}_exportDate`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
.attr(
'data-text',
now.toLocaleDateString(locale || 'en', {
weekday: 'long',
year: 'numeric',
month: 'short',
day: 'numeric',
})
)
.attr('data-text', `@ ${hours}:${mins}`)
.attr('data-text-class', 'text-sm')
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
const exportDate = now.toLocaleDateString(locale || 'en', {
weekday: 'long',
year: 'numeric',
month: 'short',
day: 'numeric',
})
points[`_${prefix}_exportDate`] = nextPoint(`${exportDate}@ ${hours}:${mins}`, 'text-sm')
}
// Export macros