@pinepaper.studio/mcp-server 1.6.28 → 1.6.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/SECURITY.md +2 -3
- package/dist/agent/export-manager.js +125 -125
- package/dist/assets/repositories/fontawesome.d.ts.map +1 -1
- package/dist/assets/repositories/fontawesome.js +2 -1
- package/dist/assets/repositories/fontawesome.js.map +1 -1
- package/dist/assets/repositories/iconify.d.ts.map +1 -1
- package/dist/assets/repositories/iconify.js +4 -3
- package/dist/assets/repositories/iconify.js.map +1 -1
- package/dist/browser/puppeteer-controller.js +38 -23
- package/dist/build-info.json +2 -2
- package/dist/cli.js +54 -54
- package/dist/execution/canvas-state.js +25 -25
- package/dist/i18n/locales/en.js +22 -22
- package/dist/i18n/locales/fil.js +44 -44
- package/dist/i18n/locales/is.js +22 -22
- package/dist/i18n/locales/ur.js +22 -22
- package/dist/index.js +5559 -5559
- package/dist/ontology/upstream-vocabulary.js +4 -4
- package/dist/tools/craft-tools.js +18 -18
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +2816 -2815
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/effect-check.js +68 -68
- package/dist/tools/engine-methods.d.ts.map +1 -1
- package/dist/tools/engine-methods.js +1 -1
- package/dist/tools/engine-methods.js.map +1 -1
- package/dist/tools/handlers/font.js +22 -22
- package/dist/tools/handlers/generate.d.ts.map +1 -1
- package/dist/tools/handlers/generate.js +2 -1
- package/dist/tools/handlers/generate.js.map +1 -1
- package/dist/tools/handlers.js +16 -16
- package/dist/tools/lane.js +64 -64
- package/dist/tools/p5-compat/p5-helpers.js +341 -341
- package/dist/tools/timeline.js +82 -82
- package/dist/types/code-generator.d.ts.map +1 -1
- package/dist/types/code-generator.js +6616 -5859
- package/dist/types/code-generator.js.map +1 -1
- package/dist/types/schemas.d.ts +2 -0
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/types/schemas.js +2 -0
- package/dist/types/schemas.js.map +1 -1
- package/dist/utils/safe-fetch.d.ts +8 -0
- package/dist/utils/safe-fetch.d.ts.map +1 -1
- package/dist/utils/safe-fetch.js +125 -34
- package/dist/utils/safe-fetch.js.map +1 -1
- package/dist/vendor/design/device-mockup-generator.js +167 -150
- package/dist/vendor/design/recursive-subdivision-generator.js +107 -107
- package/dist/vendor/design/textile-weave-generator.js +429 -429
- package/dist/vendor/design/ui-kit-runtime.js +674 -674
- package/manifest.json +1 -1
- package/package.json +7 -4
|
@@ -31,58 +31,58 @@ export function generatePlainWeaveCode(opts = {}) {
|
|
|
31
31
|
const slubJitter = opts.slubJitter ?? 0;
|
|
32
32
|
const opacity = opts.opacity ?? 0.85;
|
|
33
33
|
const prefix = opts.idPrefix ?? "plain_weave";
|
|
34
|
-
return
|
|
35
|
-
(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
to: [vx + jitterX, y1]
|
|
49
|
-
|
|
50
|
-
strokeWidth: strokeWidth,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
34
|
+
return ("// Plain Weave / Tabby Vector Generator\n(function() {\n const items = [];\n const x0 = " +
|
|
35
|
+
String(x) +
|
|
36
|
+
", y0 = " +
|
|
37
|
+
String(y) +
|
|
38
|
+
", x1 = " +
|
|
39
|
+
String(x + w) +
|
|
40
|
+
", y1 = " +
|
|
41
|
+
String(y + h) +
|
|
42
|
+
";\n const pitch = " +
|
|
43
|
+
String(pitch) +
|
|
44
|
+
";\n const strokeWidth = " +
|
|
45
|
+
String(threadWidth) +
|
|
46
|
+
";\n const slubJitter = " +
|
|
47
|
+
String(slubJitter) +
|
|
48
|
+
";\n\n // Vertical Warp threads\n let colIdx = 0;\n for (let vx = x0; vx <= x1; vx += pitch) {\n const jitterX = slubJitter ? (Math.sin(colIdx * 1.7) * slubJitter * 2) : 0;\n const warp = new paper.Path.Line({\n from: [vx + jitterX, y0],\n to: [vx + jitterX, y1],\n strokeColor: \"" +
|
|
49
|
+
String(warpColor) +
|
|
50
|
+
"\",\n strokeWidth: strokeWidth,\n strokeCap: \"round\",\n dashArray: [pitch, pitch],\n dashOffset: (colIdx % 2 === 0) ? 0 : pitch,\n opacity: " +
|
|
51
|
+
String(opacity) +
|
|
52
|
+
"\n });\n const id = \"" +
|
|
53
|
+
String(prefix) +
|
|
54
|
+
"_warp_\" + colIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(warp, id, { source: \"weave_generator\", weave: \"plain\", role: \"warp\" });\n items.push(warp);\n colIdx++;\n }\n\n // Horizontal Weft threads\n let rowIdx = 0;\n for (let vy = y0; vy <= y1; vy += pitch) {\n const jitterY = slubJitter ? (Math.cos(rowIdx * 1.7) * slubJitter * 2) : 0;\n const weft = new paper.Path.Line({\n from: [x0, vy + jitterY],\n to: [x1, vy + jitterY],\n strokeColor: \"" +
|
|
55
|
+
String(weftColor) +
|
|
56
|
+
"\",\n strokeWidth: strokeWidth,\n strokeCap: \"round\",\n dashArray: [pitch, pitch],\n dashOffset: (rowIdx % 2 === 0) ? pitch : 0,\n opacity: " +
|
|
57
|
+
String(opacity) +
|
|
58
|
+
"\n });\n const id = \"" +
|
|
59
|
+
String(prefix) +
|
|
60
|
+
"_weft_\" + rowIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(weft, id, { source: \"weave_generator\", weave: \"plain\", role: \"weft\" });\n items.push(weft);\n rowIdx++;\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(group, \"" +
|
|
61
|
+
String(prefix) +
|
|
62
|
+
"_group\", { source: \"weave_generator\", weave: \"plain\" });\n return group;\n})();"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
);
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
88
|
* Generate Paper.js code for a Twill / Herringbone Weave.
|
|
@@ -103,80 +103,80 @@ export function generateTwillWeaveCode(opts = {}) {
|
|
|
103
103
|
const weftColor = opts.weftColor ?? "rgba(203, 213, 225, 0.5)";
|
|
104
104
|
const opacity = opts.opacity ?? 0.9;
|
|
105
105
|
const prefix = opts.idPrefix ?? (isHerringbone ? "herringbone_weave" : "twill_weave");
|
|
106
|
-
return
|
|
107
|
-
(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
to: [x1, vy],
|
|
162
|
-
strokeColor: "${weftColor}",
|
|
163
|
-
strokeWidth: ${threadWidth},
|
|
164
|
-
strokeCap: "round",
|
|
165
|
-
dashArray: [floatLen, pitch],
|
|
166
|
-
dashOffset: phase,
|
|
167
|
-
opacity: ${opacity}
|
|
168
|
-
});
|
|
169
|
-
const id = "${prefix}_weft_" + rowIdx;
|
|
170
|
-
if (typeof app.registerItem === "function") app.registerItem(weft, id, { source: "weave_generator", weave: "twill", role: "weft" });
|
|
171
|
-
items.push(weft);
|
|
172
|
-
}
|
|
173
|
-
rowIdx++;
|
|
174
|
-
}
|
|
106
|
+
return ("// Twill Weave & Herringbone Vector Generator\n(function() {\n const items = [];\n const x0 = " +
|
|
107
|
+
String(x) +
|
|
108
|
+
", y0 = " +
|
|
109
|
+
String(y) +
|
|
110
|
+
", x1 = " +
|
|
111
|
+
String(x + w) +
|
|
112
|
+
", y1 = " +
|
|
113
|
+
String(y + h) +
|
|
114
|
+
";\n const pitch = " +
|
|
115
|
+
String(pitch) +
|
|
116
|
+
";\n const floatLen = pitch * " +
|
|
117
|
+
String(floatRatio) +
|
|
118
|
+
";\n const isHerringbone = " +
|
|
119
|
+
String(isHerringbone) +
|
|
120
|
+
";\n const chevronWidth = " +
|
|
121
|
+
String(chevronW) +
|
|
122
|
+
";\n\n // Warp lines (base grid)\n let colIdx = 0;\n for (let vx = x0; vx <= x1; vx += pitch) {\n const warp = new paper.Path.Line({\n from: [vx, y0],\n to: [vx, y1],\n strokeColor: \"" +
|
|
123
|
+
String(warpColor) +
|
|
124
|
+
"\",\n strokeWidth: " +
|
|
125
|
+
String(threadWidth) +
|
|
126
|
+
",\n strokeCap: \"round\",\n opacity: " +
|
|
127
|
+
String(opacity * 0.7) +
|
|
128
|
+
"\n });\n const id = \"" +
|
|
129
|
+
String(prefix) +
|
|
130
|
+
"_warp_\" + colIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(warp, id, { source: \"weave_generator\", weave: \"twill\", role: \"warp\" });\n items.push(warp);\n colIdx++;\n }\n\n // Weft float lines with diagonal stepped offsets\n let rowIdx = 0;\n for (let vy = y0; vy <= y1; vy += pitch) {\n if (isHerringbone) {\n // Split into chevron blocks with reversing slants\n for (let bx = x0; bx < x1; bx += chevronWidth) {\n const segEnd = Math.min(x1, bx + chevronWidth);\n const blockIdx = Math.floor((bx - x0) / chevronWidth);\n const dir = (blockIdx % 2 === 0) ? 1 : -1;\n const phase = dir === 1 ? ((rowIdx * pitch) % (f" +
|
|
131
|
+
"loatLen * 2)) : (((1000 - rowIdx) * pitch) % (floatLen * 2));\n const weftSeg = new paper.Path.Line({\n from: [bx, vy],\n to: [segEnd, vy],\n strokeColor: \"" +
|
|
132
|
+
String(weftColor) +
|
|
133
|
+
"\",\n strokeWidth: " +
|
|
134
|
+
String(threadWidth) +
|
|
135
|
+
",\n strokeCap: \"round\",\n dashArray: [floatLen, pitch],\n dashOffset: phase,\n opacity: " +
|
|
136
|
+
String(opacity) +
|
|
137
|
+
"\n });\n const id = \"" +
|
|
138
|
+
String(prefix) +
|
|
139
|
+
"_weft_\" + rowIdx + \"_\" + blockIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(weftSeg, id, { source: \"weave_generator\", weave: \"herringbone\", role: \"weft\" });\n items.push(weftSeg);\n }\n } else {\n // Classic diagonal twill\n const phase = (rowIdx * pitch) % (floatLen * 2);\n const weft = new paper.Path.Line({\n from: [x0, vy],\n to: [x1, vy],\n strokeColor: \"" +
|
|
140
|
+
String(weftColor) +
|
|
141
|
+
"\",\n strokeWidth: " +
|
|
142
|
+
String(threadWidth) +
|
|
143
|
+
",\n strokeCap: \"round\",\n dashArray: [floatLen, pitch],\n dashOffset: phase,\n opacity: " +
|
|
144
|
+
String(opacity) +
|
|
145
|
+
"\n });\n const id = \"" +
|
|
146
|
+
String(prefix) +
|
|
147
|
+
"_weft_\" + rowIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(weft, id, { source: \"weave_generator\", weave: \"twill\", role: \"weft\" });\n items.push(weft);\n }\n rowIdx++;\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(group, \"" +
|
|
148
|
+
String(prefix) +
|
|
149
|
+
"_group\", { source: \"weave_generator\", weave: isHerringbone ? \"herringbone\" : \"twill\" });\n return group;\n})();"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
175
161
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
);
|
|
180
180
|
}
|
|
181
181
|
/**
|
|
182
182
|
* Generate Paper.js code for a Basketweave (Panama) pattern.
|
|
@@ -195,54 +195,54 @@ export function generateBasketWeaveCode(opts = {}) {
|
|
|
195
195
|
const colorB = opts.colorB ?? opts.weftColor ?? "rgba(217, 119, 6, 0.6)";
|
|
196
196
|
const opacity = opts.opacity ?? 0.85;
|
|
197
197
|
const prefix = opts.idPrefix ?? "basket_weave";
|
|
198
|
-
return
|
|
199
|
-
(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const offset = t * pitch + pitch / 2
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
from: [vx, vy + offset]
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
198
|
+
return ("// Basketweave Vector Generator\n(function() {\n const items = [];\n const x0 = " +
|
|
199
|
+
String(x) +
|
|
200
|
+
", y0 = " +
|
|
201
|
+
String(y) +
|
|
202
|
+
", x1 = " +
|
|
203
|
+
String(x + w) +
|
|
204
|
+
", y1 = " +
|
|
205
|
+
String(y + h) +
|
|
206
|
+
";\n const pitch = " +
|
|
207
|
+
String(pitch) +
|
|
208
|
+
";\n const bundleSize = " +
|
|
209
|
+
String(bundleSize) +
|
|
210
|
+
";\n const bundleGap = " +
|
|
211
|
+
String(bundleGap) +
|
|
212
|
+
";\n const blockSize = (bundleSize * pitch) + bundleGap;\n const threadWidth = " +
|
|
213
|
+
String(threadWidth) +
|
|
214
|
+
";\n\n let rIdx = 0;\n for (let vy = y0; vy <= y1; vy += blockSize) {\n let cIdx = 0;\n for (let vx = x0; vx <= x1; vx += blockSize) {\n const isHorizontal = (rIdx + cIdx) % 2 === 0;\n for (let t = 0; t < bundleSize; t++) {\n const offset = t * pitch + pitch / 2;\n let line;\n if (isHorizontal) {\n line = new paper.Path.Line({\n from: [vx, vy + offset],\n to: [Math.min(x1, vx + blockSize - bundleGap), vy + offset],\n strokeColor: \"" +
|
|
215
|
+
String(colorA) +
|
|
216
|
+
"\",\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n opacity: " +
|
|
217
|
+
String(opacity) +
|
|
218
|
+
"\n });\n } else {\n line = new paper.Path.Line({\n from: [vx + offset, vy],\n to: [vx + offset, Math.min(y1, vy + blockSize - bundleGap)],\n strokeColor: \"" +
|
|
219
|
+
String(colorB) +
|
|
220
|
+
"\",\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n opacity: " +
|
|
221
|
+
String(opacity) +
|
|
222
|
+
"\n });\n }\n items.push(line);\n }\n cIdx++;\n }\n rIdx++;\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(group, \"" +
|
|
223
|
+
String(prefix) +
|
|
224
|
+
"_group\", { source: \"weave_generator\", weave: \"basket\" });\n return group;\n})();"
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
241
240
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
);
|
|
246
246
|
}
|
|
247
247
|
/**
|
|
248
248
|
* Generate Paper.js code for tactile 3D Embroidered Knots (French knots, bullion coils, knot anchors).
|
|
@@ -256,130 +256,130 @@ export function generateKnotCode(opts = {}) {
|
|
|
256
256
|
const defaultShadow = opts.shadowColor ?? opts.defaultShadow ?? "rgba(15, 23, 42, 0.4)";
|
|
257
257
|
const prefix = opts.idPrefix ?? "embroidery_knot";
|
|
258
258
|
const serializedKnots = JSON.stringify(knots);
|
|
259
|
-
return
|
|
260
|
-
(
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
const defCol = "
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const kr = k.radius || defR
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const sh =
|
|
275
|
-
const knotParts =
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
// 2. French knot coil body outer thread
|
|
344
|
-
const body = new paper.Path.Circle({
|
|
345
|
-
center: [kx, ky],
|
|
346
|
-
radius: kr,
|
|
347
|
-
fillColor: col,
|
|
348
|
-
strokeColor: "#f8fafc",
|
|
349
|
-
strokeWidth: 1
|
|
350
|
-
});
|
|
351
|
-
knotParts.push(body);
|
|
352
|
-
|
|
353
|
-
// 3. Inner coiled thread wrap
|
|
354
|
-
const innerCoil = new paper.Path.Circle({
|
|
355
|
-
center: [kx + kr * 0.1, ky + kr * 0.1],
|
|
356
|
-
radius: Math.max(1, kr * 0.55),
|
|
357
|
-
fillColor: null,
|
|
358
|
-
strokeColor: col,
|
|
359
|
-
strokeWidth: Math.max(0.8, kr * 0.28)
|
|
360
|
-
});
|
|
361
|
-
knotParts.push(innerCoil);
|
|
362
|
-
|
|
363
|
-
// 4. Specular glint highlight
|
|
364
|
-
const glint = new paper.Path.Circle({
|
|
365
|
-
center: [kx - kr * 0.32, ky - kr * 0.32],
|
|
366
|
-
radius: Math.max(0.8, kr * 0.3),
|
|
367
|
-
fillColor: hi,
|
|
368
|
-
strokeColor: null
|
|
369
|
-
});
|
|
370
|
-
knotParts.push(glint);
|
|
371
|
-
}
|
|
259
|
+
return ("// Embroidered Knots & Anchor Relief Vector Generator\n(function() {\n const items = [];\n const knotList = " +
|
|
260
|
+
String(serializedKnots) +
|
|
261
|
+
";\n const knotType = \"" +
|
|
262
|
+
String(knotType) +
|
|
263
|
+
"\";\n const defR = " +
|
|
264
|
+
String(defaultRadius) +
|
|
265
|
+
";\n const defCol = \"" +
|
|
266
|
+
String(defaultColor) +
|
|
267
|
+
"\";\n const defHi = \"" +
|
|
268
|
+
String(defaultHighlight) +
|
|
269
|
+
"\";\n const defShadow = \"" +
|
|
270
|
+
String(defaultShadow) +
|
|
271
|
+
"\";\n\n knotList.forEach((k, idx) => {\n const kx = k.x, ky = k.y;\n const kr = k.radius || defR;\n const col = k.color || defCol;\n const hi = k.highlightColor || defHi;\n const sh = k.shadowColor || defShadow;\n const knotParts = [];\n\n if (knotType === \"bullion_roll\") {\n // Bullion roll coils along directional vector\n const len = k.length || (kr * 4);\n const angRad = ((k.angle || 0) * Math.PI) / 180;\n const dx = Math.cos(angRad);\n const dy = Math.sin(angRad);\n const steps = Math.max(3, Math.round(len / (kr * 0.8)));\n\n // Base shadow line\n const baseShadow = new paper.Path.Line({\n from: [kx + 1, ky + 1.5]," +
|
|
272
|
+
"\n to: [kx + dx * len + 1, ky + dy * len + 1.5],\n strokeColor: sh,\n strokeWidth: kr * 1.8,\n strokeCap: \"round\"\n });\n knotParts.push(baseShadow);\n\n // Overlapping coil loops\n for (let s = 0; s < steps; s++) {\n const t = s / steps;\n const cx = kx + dx * (len * t);\n const cy = ky + dy * (len * t);\n const coil = new paper.Path.Circle({\n center: [cx, cy],\n radius: kr,\n fillColor: col,\n strokeColor: hi,\n strokeWidth: 0.8\n });\n knotParts.push(coil);\n }\n } else if (knotType === \"knot_anchor\") {\n // Anchor tack cross stitches\n" +
|
|
273
|
+
" const tackLen = kr * 1.5;\n const line1 = new paper.Path.Line({\n from: [kx - tackLen, ky - tackLen],\n to: [kx + tackLen, ky + tackLen],\n strokeColor: col,\n strokeWidth: Math.max(1, kr * 0.4),\n strokeCap: \"round\"\n });\n const line2 = new paper.Path.Line({\n from: [kx - tackLen, ky + tackLen],\n to: [kx + tackLen, ky - tackLen],\n strokeColor: col,\n strokeWidth: Math.max(1, kr * 0.4),\n strokeCap: \"round\"\n });\n const centerDot = new paper.Path.Circle({\n center: [kx, ky],\n radius: kr * 0.6,\n fillColor: hi\n });\n knotParts.push(line1, line2, cente" +
|
|
274
|
+
"rDot);\n } else {\n // Standard tactile French knot relief\n // 1. French knot shadow crescent anchor beneath knot\n const shadow = new paper.Path.Circle({\n center: [kx + 1, ky + 1.5],\n radius: kr,\n fillColor: sh,\n strokeColor: null\n });\n knotParts.push(shadow);\n\n // 2. French knot coil body outer thread\n const body = new paper.Path.Circle({\n center: [kx, ky],\n radius: kr,\n fillColor: col,\n strokeColor: \"#f8fafc\",\n strokeWidth: 1\n });\n knotParts.push(body);\n\n // 3. Inner coiled thread wrap\n const innerCoil = new paper.Path.Circle({\n center: [" +
|
|
275
|
+
"kx + kr * 0.1, ky + kr * 0.1],\n radius: Math.max(1, kr * 0.55),\n fillColor: null,\n strokeColor: col,\n strokeWidth: Math.max(0.8, kr * 0.28)\n });\n knotParts.push(innerCoil);\n\n // 4. Specular glint highlight\n const glint = new paper.Path.Circle({\n center: [kx - kr * 0.32, ky - kr * 0.32],\n radius: Math.max(0.8, kr * 0.3),\n fillColor: hi,\n strokeColor: null\n });\n knotParts.push(glint);\n }\n\n const knotGroup = new paper.Group(knotParts);\n const id = \"" +
|
|
276
|
+
String(prefix) +
|
|
277
|
+
"_\" + idx;\n if (typeof app.registerItem === \"function\") app.registerItem(knotGroup, id, { source: \"knot_generator\", x: kx, y: ky, radius: kr });\n items.push(knotGroup);\n });\n\n const masterGroup = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(masterGroup, \"" +
|
|
278
|
+
String(prefix) +
|
|
279
|
+
"_collection\", { source: \"knot_generator\", count: items.length });\n return masterGroup;\n})();"
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
372
342
|
|
|
373
|
-
const knotGroup = new paper.Group(knotParts);
|
|
374
|
-
const id = "${prefix}_" + idx;
|
|
375
|
-
if (typeof app.registerItem === "function") app.registerItem(knotGroup, id, { source: "knot_generator", x: kx, y: ky, radius: kr });
|
|
376
|
-
items.push(knotGroup);
|
|
377
|
-
});
|
|
378
343
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
);
|
|
383
383
|
}
|
|
384
384
|
/**
|
|
385
385
|
* Generate Paper.js code for Japanese Sashiko geometric folk embroidery.
|
|
@@ -401,141 +401,141 @@ export function generateSashikoCode(opts = {}) {
|
|
|
401
401
|
const concentricArcs = Math.max(1, opts.concentricArcs ?? 3);
|
|
402
402
|
const opacity = opts.opacity ?? 0.92;
|
|
403
403
|
const prefix = opts.idPrefix ?? `sashiko_${pattern}`;
|
|
404
|
-
return
|
|
405
|
-
(
|
|
406
|
-
const items = []
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
for (let cx = x0 - R + offsetX; cx <= x1 + R; cx += R * 2) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
const
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
404
|
+
return ("// Sashiko Geometric Folk Embroidery Generator (" +
|
|
405
|
+
String(pattern) +
|
|
406
|
+
")\n(function() {\n const items = [];\n const x0 = " +
|
|
407
|
+
String(x) +
|
|
408
|
+
", y0 = " +
|
|
409
|
+
String(y) +
|
|
410
|
+
", x1 = " +
|
|
411
|
+
String(x + w) +
|
|
412
|
+
", y1 = " +
|
|
413
|
+
String(y + h) +
|
|
414
|
+
";\n const threadColor = \"" +
|
|
415
|
+
String(threadColor) +
|
|
416
|
+
"\";\n const threadWidth = " +
|
|
417
|
+
String(threadWidth) +
|
|
418
|
+
";\n const stitchLen = " +
|
|
419
|
+
String(stitchLen) +
|
|
420
|
+
";\n const gapLen = " +
|
|
421
|
+
String(gapLen) +
|
|
422
|
+
";\n const vertexGap = " +
|
|
423
|
+
String(vertexGap) +
|
|
424
|
+
";\n const scale = " +
|
|
425
|
+
String(scale) +
|
|
426
|
+
";\n const concentricArcs = " +
|
|
427
|
+
String(concentricArcs) +
|
|
428
|
+
";\n const opacity = " +
|
|
429
|
+
String(opacity) +
|
|
430
|
+
";\n\n // 0. Ground cloth plate\n const bgPlate = new paper.Path.Rectangle({\n point: [x0, y0],\n size: [x1 - x0, y1 - y0],\n fillColor: \"" +
|
|
431
|
+
String(groundColor) +
|
|
432
|
+
"\",\n strokeColor: null\n });\n items.push(bgPlate);\n\n if (\"" +
|
|
433
|
+
String(pattern) +
|
|
434
|
+
"\" === \"seigaiha\") {\n // Seigaiha: Overlapping concentric ocean wave arcs with staggered centers\n const R = scale;\n const dy = R * 0.55;\n let row = 0;\n for (let cy = y0 + R * 0.4; cy <= y1 + R; cy += dy) {\n const offsetX = (row % 2 === 0) ? 0 : R;\n let col = 0;\n for (let cx = x0 - R + offsetX; cx <= x1 + R; cx += R * 2) {\n for (let a = 1; a <= concentricArcs; a++) {\n const arcR = (R * a) / concentricArcs;\n const fromPt = [cx - arcR + vertexGap * 0.5, cy - vertexGap * 0.2];\n const throughPt = [cx, cy - arcR];\n const toPt = [cx + arcR - vertexGap * 0.5, cy - vertexGap * 0.2];\n const arc = new pa" +
|
|
435
|
+
"per.Path.Arc(fromPt, throughPt, toPt);\n arc.strokeColor = threadColor;\n arc.strokeWidth = threadWidth;\n arc.strokeCap = \"round\";\n arc.dashArray = [stitchLen, gapLen];\n arc.opacity = opacity;\n items.push(arc);\n }\n col++;\n }\n row++;\n }\n } else if (\"" +
|
|
436
|
+
String(pattern) +
|
|
437
|
+
"\" === \"asanoha\") {\n // Asanoha: Hexagonal star / hemp-leaf isometric lattice with vertex gap clearance\n const S = scale;\n const H = S * Math.sqrt(3) / 2;\n let rIdx = 0;\n for (let py = y0; py <= y1 + H; py += H) {\n const offX = (rIdx % 2 === 0) ? 0 : S * 0.5;\n for (let px = x0 - S + offX; px <= x1 + S; px += S) {\n const mx = px;\n const my = py;\n const angles = [0, 60, 120, 180, 240, 300];\n angles.forEach(angDeg => {\n const rad = (angDeg * Math.PI) / 180;\n const targetX = mx + Math.cos(rad) * S * 0.55;\n const targetY = my + Math.sin(rad) * S * 0.55;\n\n const startX = mx + Math.cos(rad) " +
|
|
438
|
+
"* vertexGap;\n const startY = my + Math.sin(rad) * vertexGap;\n const endX = targetX - Math.cos(rad) * vertexGap;\n const endY = targetY - Math.sin(rad) * vertexGap;\n\n const spoke = new paper.Path.Line({\n from: [startX, startY],\n to: [endX, endY],\n strokeColor: threadColor,\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n dashArray: [stitchLen, gapLen],\n opacity: opacity\n });\n items.push(spoke);\n });\n }\n rIdx++;\n }\n } else {\n // Hishi / Kaki no Hana: Diamond grid with vertex gap junctions\n const P = scale;\n for" +
|
|
439
|
+
" (let diag = -Math.max(w, h); diag <= w + h; diag += P) {\n for (let t = 0; t <= w + h; t += P) {\n const p1x = t + vertexGap;\n const p1y = t + diag + vertexGap;\n const p2x = t + P - vertexGap;\n const p2y = t + P + diag - vertexGap;\n if (p1x >= x0 - P && p1x <= x1 + P && p1y >= y0 - P && p1y <= y1 + P) {\n const seg1 = new paper.Path.Line({\n from: [p1x, p1y],\n to: [p2x, p2y],\n strokeColor: threadColor,\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n dashArray: [stitchLen, gapLen],\n opacity: opacity\n });\n items.push(seg1);\n }" +
|
|
440
|
+
"\n\n const q1x = t + vertexGap;\n const q1y = -t + diag + vertexGap;\n const q2x = t + P - vertexGap;\n const q2y = -(t + P) + diag - vertexGap;\n if (q1x >= x0 - P && q1x <= x1 + P && q1y >= y0 - P && q1y <= y1 + P) {\n const seg2 = new paper.Path.Line({\n from: [q1x, q1y],\n to: [q2x, q2y],\n strokeColor: threadColor,\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n dashArray: [stitchLen, gapLen],\n opacity: opacity\n });\n items.push(seg2);\n }\n }\n }\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem " +
|
|
441
|
+
"=== \"function\") {\n app.registerItem(group, \"" +
|
|
442
|
+
String(prefix) +
|
|
443
|
+
"_group\", {\n source: \"sashiko_generator\",\n pattern: \"" +
|
|
444
|
+
String(pattern) +
|
|
445
|
+
"\",\n stitchCount: items.length\n });\n }\n return group;\n})();"
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
);
|
|
539
539
|
}
|
|
540
540
|
/**
|
|
541
541
|
* Master dispatcher for textile and embroidery vector code generation.
|