2023-02-19 16:24:46 +02:00
|
|
|
const prefix = 'mirroredOnFold'
|
|
|
|
|
2023-03-01 12:34:18 -06:00
|
|
|
const opTypes = ['to', 'cp1', 'cp2']
|
2023-03-02 09:36:09 -06:00
|
|
|
const getRotationAngle = (grainAngle, partGrain) => {
|
|
|
|
let toRotate = Math.abs(grainAngle - partGrain)
|
|
|
|
if (toRotate >= 180) toRotate -= 180
|
|
|
|
return toRotate
|
|
|
|
}
|
2023-03-01 12:34:18 -06:00
|
|
|
export const cutLayoutPlugin = function (material, grainAngle) {
|
2023-02-27 17:47:34 -06:00
|
|
|
return {
|
|
|
|
hooks: {
|
|
|
|
postPartDraft: (pattern) => {
|
2023-03-01 12:34:18 -06:00
|
|
|
const part = pattern.parts[pattern.activeSet][pattern.activePart]
|
|
|
|
if (pattern.activePart.startsWith('cut.') || pattern.activePart === 'fabric' || part.hidden)
|
|
|
|
return
|
2023-02-19 16:24:46 +02:00
|
|
|
|
2023-03-02 09:36:09 -06:00
|
|
|
let partCutlist = pattern.setStores[pattern.activeSet].get(['cutlist', pattern.activePart])
|
2023-03-09 11:20:17 -06:00
|
|
|
if (!partCutlist) return
|
2023-02-23 23:30:38 +02:00
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
if (partCutlist.materials ? !partCutlist.materials[material] : material !== 'fabric') {
|
2023-03-01 12:34:18 -06:00
|
|
|
part.hide()
|
2023-02-27 17:47:34 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
const handleFoldAndGrain = (macro, grainSpec, ignoreOnFold) => {
|
|
|
|
if (!ignoreOnFold && partCutlist.cutOnFold)
|
|
|
|
macro('mirrorOnFold', { fold: partCutlist.cutOnFold })
|
2023-03-02 09:36:09 -06:00
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
if (grainSpec !== undefined) macro('rotateToGrain', { grainAngle, partGrain: grainSpec })
|
2023-03-01 12:34:18 -06:00
|
|
|
}
|
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
const matCutConfig = partCutlist.materials?.[material]
|
|
|
|
if (matCutConfig) {
|
|
|
|
const activePart = pattern.config.parts[pattern.activePart]
|
|
|
|
|
|
|
|
// hide the part so that all others can inherit from it and be manipulated separately
|
|
|
|
part.hide()
|
2023-02-27 18:30:26 -06:00
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
matCutConfig.forEach(({ cut, identical, bias, ignoreOnFold }, i) => {
|
|
|
|
const cGrain = partCutlist.grain ? partCutlist.grain + (bias ? 45 : 0) : undefined
|
|
|
|
for (let c = 0; c < cut; c++) {
|
|
|
|
const dupPartName = `cut.${pattern.activePart}.${material}_${c + i + 1}`
|
2023-03-02 09:36:09 -06:00
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
pattern.addPart({
|
|
|
|
name: dupPartName,
|
|
|
|
from: activePart,
|
|
|
|
draft: ({ part, macro }) => {
|
|
|
|
handleFoldAndGrain(macro, cGrain, ignoreOnFold)
|
2023-03-02 09:36:09 -06:00
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
if (!identical && c % 2 === 1) macro('flip')
|
2023-03-02 09:36:09 -06:00
|
|
|
|
2023-03-09 11:20:17 -06:00
|
|
|
return part
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
2023-02-27 17:47:34 -06:00
|
|
|
})
|
2023-03-09 11:20:17 -06:00
|
|
|
} else {
|
|
|
|
const { macro } = part.shorthand()
|
|
|
|
handleFoldAndGrain(partCutlist.grain)
|
2023-02-23 23:30:38 +02:00
|
|
|
}
|
2023-02-27 17:47:34 -06:00
|
|
|
},
|
2023-02-19 16:24:46 +02:00
|
|
|
},
|
2023-02-27 17:47:34 -06:00
|
|
|
macros: {
|
|
|
|
mirrorOnFold: ({ fold }, { paths, snippets, utils, macro, points }) => {
|
|
|
|
const mirrorPaths = []
|
|
|
|
for (const p in paths) {
|
|
|
|
if (!paths[p].hidden && !p.startsWith(prefix)) mirrorPaths.push(paths[p])
|
|
|
|
}
|
2023-02-19 16:24:46 +02:00
|
|
|
|
2023-02-27 17:47:34 -06:00
|
|
|
const mirrorPoints = []
|
|
|
|
const snippetsByType = {}
|
|
|
|
for (var s in snippets) {
|
|
|
|
const snip = snippets[s]
|
|
|
|
if (['logo'].indexOf(snip.def) > -1) continue
|
2023-02-19 16:24:46 +02:00
|
|
|
|
2023-02-27 17:47:34 -06:00
|
|
|
snippetsByType[snip.def] = snippetsByType[snip.def] || []
|
2023-02-19 16:24:46 +02:00
|
|
|
|
2023-02-27 17:47:34 -06:00
|
|
|
mirrorPoints.push(snip.anchor)
|
|
|
|
for (var pName in points) {
|
|
|
|
if (points[pName] === snip.anchor) {
|
|
|
|
snippetsByType[snip.def].push(prefix + utils.capitalize(pName))
|
|
|
|
break
|
|
|
|
}
|
2023-02-19 16:24:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-27 17:47:34 -06:00
|
|
|
let unnamed = 0
|
|
|
|
macro('mirror', {
|
|
|
|
paths: Object.values(mirrorPaths),
|
|
|
|
points: mirrorPoints,
|
|
|
|
mirror: fold,
|
|
|
|
prefix,
|
2023-03-08 17:06:46 -06:00
|
|
|
nameFormat: () => {
|
2023-02-27 17:47:34 -06:00
|
|
|
unnamed++
|
|
|
|
return `${prefix}_${unnamed}`
|
|
|
|
},
|
2023-02-19 16:24:46 +02:00
|
|
|
})
|
2023-02-27 17:47:34 -06:00
|
|
|
|
|
|
|
for (var def in snippetsByType) {
|
|
|
|
macro('sprinkle', {
|
|
|
|
snippet: def,
|
|
|
|
on: snippetsByType[def],
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2023-03-01 12:34:18 -06:00
|
|
|
rotateToGrain: ({ partGrain, grainAngle }, { paths, snippets, Point, points }) => {
|
2023-03-02 09:36:09 -06:00
|
|
|
if (partGrain === undefined) return
|
|
|
|
|
|
|
|
const toRotate = getRotationAngle(grainAngle, partGrain)
|
|
|
|
if (toRotate === 0) return
|
2023-03-01 12:34:18 -06:00
|
|
|
|
2023-03-02 09:36:09 -06:00
|
|
|
const pivot = new Point(0, 0)
|
2023-03-01 12:34:18 -06:00
|
|
|
|
|
|
|
for (const pathName in paths) {
|
|
|
|
const path = paths[pathName]
|
|
|
|
if (paths[pathName].hidden) continue
|
|
|
|
|
|
|
|
path.ops.forEach((op) => {
|
|
|
|
opTypes.forEach((t) => {
|
|
|
|
if (op[t]) op[t] = op[t].rotate(toRotate, pivot)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const snippetName in snippets) {
|
|
|
|
snippets[snippetName].anchor = snippets[snippetName].anchor.rotate(toRotate, pivot)
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const pointName in points) {
|
|
|
|
const point = points[pointName]
|
|
|
|
const pointAttrs = point.attributes
|
|
|
|
if (Object.keys(pointAttrs.list).length) {
|
|
|
|
points[pointName] = point.rotate(toRotate, pivot)
|
|
|
|
points[pointName].attributes = pointAttrs.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2023-02-19 16:24:46 +02:00
|
|
|
},
|
2023-02-27 17:47:34 -06:00
|
|
|
}
|
2023-02-19 16:24:46 +02:00
|
|
|
}
|