@pooder/kit 4.0.0 → 4.2.0
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/.test-dist/src/CanvasService.js +83 -0
- package/.test-dist/src/ViewportSystem.js +75 -0
- package/.test-dist/src/background.js +203 -0
- package/.test-dist/src/constraints.js +153 -0
- package/.test-dist/src/coordinate.js +74 -0
- package/.test-dist/src/dieline.js +758 -0
- package/.test-dist/src/feature.js +687 -0
- package/.test-dist/src/featureComplete.js +31 -0
- package/.test-dist/src/featureDraft.js +31 -0
- package/.test-dist/src/film.js +167 -0
- package/.test-dist/src/geometry.js +292 -0
- package/.test-dist/src/image.js +421 -0
- package/.test-dist/src/index.js +31 -0
- package/.test-dist/src/mirror.js +104 -0
- package/.test-dist/src/ruler.js +383 -0
- package/.test-dist/src/tracer.js +448 -0
- package/.test-dist/src/units.js +30 -0
- package/.test-dist/src/white-ink.js +310 -0
- package/.test-dist/tests/run.js +60 -0
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +54 -5
- package/dist/index.d.ts +54 -5
- package/dist/index.js +584 -190
- package/dist/index.mjs +581 -189
- package/package.json +3 -2
- package/src/CanvasService.ts +7 -0
- package/src/ViewportSystem.ts +92 -0
- package/src/background.ts +230 -230
- package/src/constraints.ts +207 -0
- package/src/coordinate.ts +106 -106
- package/src/dieline.ts +194 -75
- package/src/feature.ts +239 -147
- package/src/featureComplete.ts +45 -0
- package/src/film.ts +194 -194
- package/src/geometry.ts +4 -0
- package/src/image.ts +512 -512
- package/src/index.ts +1 -0
- package/src/mirror.ts +128 -128
- package/src/ruler.ts +508 -500
- package/src/tracer.ts +570 -570
- package/src/units.ts +27 -0
- package/src/white-ink.ts +373 -373
- package/tests/run.ts +81 -0
- package/tsconfig.test.json +15 -0
package/dist/index.js
CHANGED
|
@@ -38,7 +38,9 @@ __export(index_exports, {
|
|
|
38
38
|
ImageTool: () => ImageTool,
|
|
39
39
|
MirrorTool: () => MirrorTool,
|
|
40
40
|
RulerTool: () => RulerTool,
|
|
41
|
-
WhiteInkTool: () => WhiteInkTool
|
|
41
|
+
WhiteInkTool: () => WhiteInkTool,
|
|
42
|
+
formatMm: () => formatMm,
|
|
43
|
+
parseLengthToMm: () => parseLengthToMm
|
|
42
44
|
});
|
|
43
45
|
module.exports = __toCommonJS(index_exports);
|
|
44
46
|
|
|
@@ -717,6 +719,29 @@ var Coordinate = class {
|
|
|
717
719
|
}
|
|
718
720
|
};
|
|
719
721
|
|
|
722
|
+
// src/units.ts
|
|
723
|
+
function parseLengthToMm(input, defaultUnit) {
|
|
724
|
+
var _a, _b;
|
|
725
|
+
if (typeof input === "number") {
|
|
726
|
+
if (!Number.isFinite(input)) return 0;
|
|
727
|
+
return Coordinate.convertUnit(input, defaultUnit, "mm");
|
|
728
|
+
}
|
|
729
|
+
const raw = input.trim();
|
|
730
|
+
if (!raw) return 0;
|
|
731
|
+
const match = raw.match(/^([+-]?\d+(?:\.\d+)?)\s*(px|mm|cm|in)?$/i);
|
|
732
|
+
if (!match) return 0;
|
|
733
|
+
const value = Number(match[1]);
|
|
734
|
+
if (!Number.isFinite(value)) return 0;
|
|
735
|
+
const unit = (_b = (_a = match[2]) == null ? void 0 : _a.toLowerCase()) != null ? _b : defaultUnit;
|
|
736
|
+
return Coordinate.convertUnit(value, unit, "mm");
|
|
737
|
+
}
|
|
738
|
+
function formatMm(valueMm, displayUnit, fractionDigits = 2) {
|
|
739
|
+
if (!Number.isFinite(valueMm)) return "0";
|
|
740
|
+
const value = Coordinate.convertUnit(valueMm, "mm", displayUnit);
|
|
741
|
+
const rounded = Number(value.toFixed(fractionDigits));
|
|
742
|
+
return rounded.toString();
|
|
743
|
+
}
|
|
744
|
+
|
|
720
745
|
// src/geometry.ts
|
|
721
746
|
var import_paper2 = __toESM(require("paper"));
|
|
722
747
|
function resolveFeaturePosition(feature, geometry) {
|
|
@@ -948,7 +973,7 @@ var DielineTool = class {
|
|
|
948
973
|
name: "DielineTool"
|
|
949
974
|
};
|
|
950
975
|
this.state = {
|
|
951
|
-
|
|
976
|
+
displayUnit: "mm",
|
|
952
977
|
shape: "rect",
|
|
953
978
|
width: 500,
|
|
954
979
|
height: 500,
|
|
@@ -994,50 +1019,88 @@ var DielineTool = class {
|
|
|
994
1019
|
const configService = context.services.get("ConfigurationService");
|
|
995
1020
|
if (configService) {
|
|
996
1021
|
const s = this.state;
|
|
997
|
-
s.
|
|
1022
|
+
s.displayUnit = configService.get("dieline.displayUnit", s.displayUnit);
|
|
998
1023
|
s.shape = configService.get("dieline.shape", s.shape);
|
|
999
|
-
s.width =
|
|
1000
|
-
|
|
1001
|
-
|
|
1024
|
+
s.width = parseLengthToMm(
|
|
1025
|
+
configService.get("dieline.width", s.width),
|
|
1026
|
+
"mm"
|
|
1027
|
+
);
|
|
1028
|
+
s.height = parseLengthToMm(
|
|
1029
|
+
configService.get("dieline.height", s.height),
|
|
1030
|
+
"mm"
|
|
1031
|
+
);
|
|
1032
|
+
s.radius = parseLengthToMm(
|
|
1033
|
+
configService.get("dieline.radius", s.radius),
|
|
1034
|
+
"mm"
|
|
1035
|
+
);
|
|
1002
1036
|
s.padding = configService.get("dieline.padding", s.padding);
|
|
1003
|
-
s.offset =
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1037
|
+
s.offset = parseLengthToMm(
|
|
1038
|
+
configService.get("dieline.offset", s.offset),
|
|
1039
|
+
"mm"
|
|
1040
|
+
);
|
|
1041
|
+
s.mainLine.width = configService.get(
|
|
1042
|
+
"dieline.strokeWidth",
|
|
1043
|
+
s.mainLine.width
|
|
1044
|
+
);
|
|
1045
|
+
s.mainLine.color = configService.get(
|
|
1046
|
+
"dieline.strokeColor",
|
|
1047
|
+
s.mainLine.color
|
|
1048
|
+
);
|
|
1049
|
+
s.mainLine.dashLength = configService.get(
|
|
1050
|
+
"dieline.dashLength",
|
|
1051
|
+
s.mainLine.dashLength
|
|
1052
|
+
);
|
|
1007
1053
|
s.mainLine.style = configService.get("dieline.style", s.mainLine.style);
|
|
1008
|
-
s.offsetLine.width = configService.get(
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1054
|
+
s.offsetLine.width = configService.get(
|
|
1055
|
+
"dieline.offsetStrokeWidth",
|
|
1056
|
+
s.offsetLine.width
|
|
1057
|
+
);
|
|
1058
|
+
s.offsetLine.color = configService.get(
|
|
1059
|
+
"dieline.offsetStrokeColor",
|
|
1060
|
+
s.offsetLine.color
|
|
1061
|
+
);
|
|
1062
|
+
s.offsetLine.dashLength = configService.get(
|
|
1063
|
+
"dieline.offsetDashLength",
|
|
1064
|
+
s.offsetLine.dashLength
|
|
1065
|
+
);
|
|
1066
|
+
s.offsetLine.style = configService.get(
|
|
1067
|
+
"dieline.offsetStyle",
|
|
1068
|
+
s.offsetLine.style
|
|
1069
|
+
);
|
|
1012
1070
|
s.insideColor = configService.get("dieline.insideColor", s.insideColor);
|
|
1013
|
-
s.outsideColor = configService.get(
|
|
1014
|
-
|
|
1071
|
+
s.outsideColor = configService.get(
|
|
1072
|
+
"dieline.outsideColor",
|
|
1073
|
+
s.outsideColor
|
|
1074
|
+
);
|
|
1075
|
+
s.showBleedLines = configService.get(
|
|
1076
|
+
"dieline.showBleedLines",
|
|
1077
|
+
s.showBleedLines
|
|
1078
|
+
);
|
|
1015
1079
|
s.features = configService.get("dieline.features", s.features);
|
|
1016
1080
|
s.pathData = configService.get("dieline.pathData", s.pathData);
|
|
1017
1081
|
configService.onAnyChange((e) => {
|
|
1018
1082
|
if (e.key.startsWith("dieline.")) {
|
|
1019
|
-
console.log(`[DielineTool] Config change detected: ${e.key} -> ${e.value}`);
|
|
1020
1083
|
switch (e.key) {
|
|
1021
|
-
case "dieline.
|
|
1022
|
-
s.
|
|
1084
|
+
case "dieline.displayUnit":
|
|
1085
|
+
s.displayUnit = e.value;
|
|
1023
1086
|
break;
|
|
1024
1087
|
case "dieline.shape":
|
|
1025
1088
|
s.shape = e.value;
|
|
1026
1089
|
break;
|
|
1027
1090
|
case "dieline.width":
|
|
1028
|
-
s.width = e.value;
|
|
1091
|
+
s.width = parseLengthToMm(e.value, "mm");
|
|
1029
1092
|
break;
|
|
1030
1093
|
case "dieline.height":
|
|
1031
|
-
s.height = e.value;
|
|
1094
|
+
s.height = parseLengthToMm(e.value, "mm");
|
|
1032
1095
|
break;
|
|
1033
1096
|
case "dieline.radius":
|
|
1034
|
-
s.radius = e.value;
|
|
1097
|
+
s.radius = parseLengthToMm(e.value, "mm");
|
|
1035
1098
|
break;
|
|
1036
1099
|
case "dieline.padding":
|
|
1037
1100
|
s.padding = e.value;
|
|
1038
1101
|
break;
|
|
1039
1102
|
case "dieline.offset":
|
|
1040
|
-
s.offset = e.value;
|
|
1103
|
+
s.offset = parseLengthToMm(e.value, "mm");
|
|
1041
1104
|
break;
|
|
1042
1105
|
case "dieline.strokeWidth":
|
|
1043
1106
|
s.mainLine.width = e.value;
|
|
@@ -1096,11 +1159,11 @@ var DielineTool = class {
|
|
|
1096
1159
|
return {
|
|
1097
1160
|
[import_core2.ContributionPointIds.CONFIGURATIONS]: [
|
|
1098
1161
|
{
|
|
1099
|
-
id: "dieline.
|
|
1162
|
+
id: "dieline.displayUnit",
|
|
1100
1163
|
type: "select",
|
|
1101
|
-
label: "Unit",
|
|
1102
|
-
options: ["
|
|
1103
|
-
default: s.
|
|
1164
|
+
label: "Display Unit",
|
|
1165
|
+
options: ["mm", "cm", "in"],
|
|
1166
|
+
default: s.displayUnit
|
|
1104
1167
|
},
|
|
1105
1168
|
{
|
|
1106
1169
|
id: "dieline.shape",
|
|
@@ -1112,7 +1175,7 @@ var DielineTool = class {
|
|
|
1112
1175
|
{
|
|
1113
1176
|
id: "dieline.width",
|
|
1114
1177
|
type: "number",
|
|
1115
|
-
label: "Width",
|
|
1178
|
+
label: "Width (mm)",
|
|
1116
1179
|
min: 10,
|
|
1117
1180
|
max: 2e3,
|
|
1118
1181
|
default: s.width
|
|
@@ -1120,7 +1183,7 @@ var DielineTool = class {
|
|
|
1120
1183
|
{
|
|
1121
1184
|
id: "dieline.height",
|
|
1122
1185
|
type: "number",
|
|
1123
|
-
label: "Height",
|
|
1186
|
+
label: "Height (mm)",
|
|
1124
1187
|
min: 10,
|
|
1125
1188
|
max: 2e3,
|
|
1126
1189
|
default: s.height
|
|
@@ -1128,7 +1191,7 @@ var DielineTool = class {
|
|
|
1128
1191
|
{
|
|
1129
1192
|
id: "dieline.radius",
|
|
1130
1193
|
type: "number",
|
|
1131
|
-
label: "Corner Radius",
|
|
1194
|
+
label: "Corner Radius (mm)",
|
|
1132
1195
|
min: 0,
|
|
1133
1196
|
max: 500,
|
|
1134
1197
|
default: s.radius
|
|
@@ -1143,7 +1206,7 @@ var DielineTool = class {
|
|
|
1143
1206
|
{
|
|
1144
1207
|
id: "dieline.offset",
|
|
1145
1208
|
type: "number",
|
|
1146
|
-
label: "Bleed Offset",
|
|
1209
|
+
label: "Bleed Offset (mm)",
|
|
1147
1210
|
min: -100,
|
|
1148
1211
|
max: 100,
|
|
1149
1212
|
default: s.offset
|
|
@@ -1234,6 +1297,31 @@ var DielineTool = class {
|
|
|
1234
1297
|
}
|
|
1235
1298
|
],
|
|
1236
1299
|
[import_core2.ContributionPointIds.COMMANDS]: [
|
|
1300
|
+
{
|
|
1301
|
+
command: "updateFeaturePosition",
|
|
1302
|
+
title: "Update Feature Position",
|
|
1303
|
+
handler: (groupId, x, y) => {
|
|
1304
|
+
var _a;
|
|
1305
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
1306
|
+
"ConfigurationService"
|
|
1307
|
+
);
|
|
1308
|
+
if (!configService) return;
|
|
1309
|
+
const features = configService.get("dieline.features") || [];
|
|
1310
|
+
let changed = false;
|
|
1311
|
+
const newFeatures = features.map((f) => {
|
|
1312
|
+
if (f.groupId === groupId) {
|
|
1313
|
+
if (f.x !== x || f.y !== y) {
|
|
1314
|
+
changed = true;
|
|
1315
|
+
return { ...f, x, y };
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
return f;
|
|
1319
|
+
});
|
|
1320
|
+
if (changed) {
|
|
1321
|
+
configService.update("dieline.features", newFeatures);
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
},
|
|
1237
1325
|
{
|
|
1238
1326
|
command: "getGeometry",
|
|
1239
1327
|
title: "Get Geometry",
|
|
@@ -1339,7 +1427,7 @@ var DielineTool = class {
|
|
|
1339
1427
|
const layer = this.getLayer();
|
|
1340
1428
|
if (!layer) return;
|
|
1341
1429
|
const {
|
|
1342
|
-
|
|
1430
|
+
displayUnit,
|
|
1343
1431
|
shape,
|
|
1344
1432
|
radius,
|
|
1345
1433
|
offset,
|
|
@@ -1350,15 +1438,13 @@ var DielineTool = class {
|
|
|
1350
1438
|
showBleedLines,
|
|
1351
1439
|
features
|
|
1352
1440
|
} = this.state;
|
|
1353
|
-
|
|
1441
|
+
const { width, height } = this.state;
|
|
1354
1442
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1355
1443
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1356
1444
|
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
paddingPx
|
|
1361
|
-
);
|
|
1445
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
1446
|
+
this.canvasService.viewport.updatePhysical(width, height);
|
|
1447
|
+
const layout = this.canvasService.viewport.layout;
|
|
1362
1448
|
const scale = layout.scale;
|
|
1363
1449
|
const cx = layout.offsetX + layout.width / 2;
|
|
1364
1450
|
const cy = layout.offsetY + layout.height / 2;
|
|
@@ -1545,15 +1631,22 @@ var DielineTool = class {
|
|
|
1545
1631
|
}
|
|
1546
1632
|
getGeometry() {
|
|
1547
1633
|
if (!this.canvasService) return null;
|
|
1548
|
-
const {
|
|
1634
|
+
const {
|
|
1635
|
+
displayUnit,
|
|
1636
|
+
shape,
|
|
1637
|
+
width,
|
|
1638
|
+
height,
|
|
1639
|
+
radius,
|
|
1640
|
+
offset,
|
|
1641
|
+
mainLine,
|
|
1642
|
+
pathData
|
|
1643
|
+
} = this.state;
|
|
1549
1644
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1550
1645
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1551
1646
|
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
paddingPx
|
|
1556
|
-
);
|
|
1647
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
1648
|
+
this.canvasService.viewport.updatePhysical(width, height);
|
|
1649
|
+
const layout = this.canvasService.viewport.layout;
|
|
1557
1650
|
const scale = layout.scale;
|
|
1558
1651
|
const cx = layout.offsetX + layout.width / 2;
|
|
1559
1652
|
const cy = layout.offsetY + layout.height / 2;
|
|
@@ -1561,14 +1654,14 @@ var DielineTool = class {
|
|
|
1561
1654
|
const visualHeight = layout.height;
|
|
1562
1655
|
return {
|
|
1563
1656
|
shape,
|
|
1564
|
-
unit,
|
|
1657
|
+
unit: "mm",
|
|
1658
|
+
displayUnit,
|
|
1565
1659
|
x: cx,
|
|
1566
1660
|
y: cy,
|
|
1567
1661
|
width: visualWidth,
|
|
1568
1662
|
height: visualHeight,
|
|
1569
1663
|
radius: radius * scale,
|
|
1570
1664
|
offset: offset * scale,
|
|
1571
|
-
// Pass scale to help other tools (like FeatureTool) convert units
|
|
1572
1665
|
scale,
|
|
1573
1666
|
strokeWidth: mainLine.width,
|
|
1574
1667
|
pathData
|
|
@@ -1578,15 +1671,13 @@ var DielineTool = class {
|
|
|
1578
1671
|
if (!this.canvasService) return null;
|
|
1579
1672
|
const userLayer = this.canvasService.getLayer("user");
|
|
1580
1673
|
if (!userLayer) return null;
|
|
1581
|
-
const { shape, width, height, radius, features,
|
|
1674
|
+
const { shape, width, height, radius, features, pathData } = this.state;
|
|
1582
1675
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1583
1676
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1584
1677
|
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
paddingPx
|
|
1589
|
-
);
|
|
1678
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
1679
|
+
this.canvasService.viewport.updatePhysical(width, height);
|
|
1680
|
+
const layout = this.canvasService.viewport.layout;
|
|
1590
1681
|
const scale = layout.scale;
|
|
1591
1682
|
const cx = layout.offsetX + layout.width / 2;
|
|
1592
1683
|
const cy = layout.offsetY + layout.height / 2;
|
|
@@ -1801,13 +1892,158 @@ var FilmTool = class {
|
|
|
1801
1892
|
// src/feature.ts
|
|
1802
1893
|
var import_core4 = require("@pooder/core");
|
|
1803
1894
|
var import_fabric4 = require("fabric");
|
|
1895
|
+
|
|
1896
|
+
// src/constraints.ts
|
|
1897
|
+
var ConstraintRegistry = class {
|
|
1898
|
+
static register(type, handler) {
|
|
1899
|
+
this.handlers.set(type, handler);
|
|
1900
|
+
}
|
|
1901
|
+
static apply(x, y, feature, context) {
|
|
1902
|
+
if (!feature.constraints || !feature.constraints.type) {
|
|
1903
|
+
return { x, y };
|
|
1904
|
+
}
|
|
1905
|
+
const handler = this.handlers.get(feature.constraints.type);
|
|
1906
|
+
if (handler) {
|
|
1907
|
+
return handler(x, y, feature, context);
|
|
1908
|
+
}
|
|
1909
|
+
return { x, y };
|
|
1910
|
+
}
|
|
1911
|
+
};
|
|
1912
|
+
ConstraintRegistry.handlers = /* @__PURE__ */ new Map();
|
|
1913
|
+
var edgeConstraint = (x, y, feature, context) => {
|
|
1914
|
+
var _a;
|
|
1915
|
+
const { dielineWidth, dielineHeight } = context;
|
|
1916
|
+
const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
|
|
1917
|
+
const allowedEdges = params.allowedEdges || [
|
|
1918
|
+
"top",
|
|
1919
|
+
"bottom",
|
|
1920
|
+
"left",
|
|
1921
|
+
"right"
|
|
1922
|
+
];
|
|
1923
|
+
const confine = params.confine || false;
|
|
1924
|
+
const offset = params.offset || 0;
|
|
1925
|
+
const distances = [];
|
|
1926
|
+
if (allowedEdges.includes("top"))
|
|
1927
|
+
distances.push({ edge: "top", dist: y * dielineHeight });
|
|
1928
|
+
if (allowedEdges.includes("bottom"))
|
|
1929
|
+
distances.push({ edge: "bottom", dist: (1 - y) * dielineHeight });
|
|
1930
|
+
if (allowedEdges.includes("left"))
|
|
1931
|
+
distances.push({ edge: "left", dist: x * dielineWidth });
|
|
1932
|
+
if (allowedEdges.includes("right"))
|
|
1933
|
+
distances.push({ edge: "right", dist: (1 - x) * dielineWidth });
|
|
1934
|
+
if (distances.length === 0) return { x, y };
|
|
1935
|
+
distances.sort((a, b) => a.dist - b.dist);
|
|
1936
|
+
const nearest = distances[0].edge;
|
|
1937
|
+
let newX = x;
|
|
1938
|
+
let newY = y;
|
|
1939
|
+
const fw = feature.width || 0;
|
|
1940
|
+
const fh = feature.height || 0;
|
|
1941
|
+
switch (nearest) {
|
|
1942
|
+
case "top":
|
|
1943
|
+
newY = 0 + offset / dielineHeight;
|
|
1944
|
+
if (confine) {
|
|
1945
|
+
const minX = fw / 2 / dielineWidth;
|
|
1946
|
+
const maxX = 1 - minX;
|
|
1947
|
+
newX = Math.max(minX, Math.min(newX, maxX));
|
|
1948
|
+
}
|
|
1949
|
+
break;
|
|
1950
|
+
case "bottom":
|
|
1951
|
+
newY = 1 - offset / dielineHeight;
|
|
1952
|
+
if (confine) {
|
|
1953
|
+
const minX = fw / 2 / dielineWidth;
|
|
1954
|
+
const maxX = 1 - minX;
|
|
1955
|
+
newX = Math.max(minX, Math.min(newX, maxX));
|
|
1956
|
+
}
|
|
1957
|
+
break;
|
|
1958
|
+
case "left":
|
|
1959
|
+
newX = 0 + offset / dielineWidth;
|
|
1960
|
+
if (confine) {
|
|
1961
|
+
const minY = fh / 2 / dielineHeight;
|
|
1962
|
+
const maxY = 1 - minY;
|
|
1963
|
+
newY = Math.max(minY, Math.min(newY, maxY));
|
|
1964
|
+
}
|
|
1965
|
+
break;
|
|
1966
|
+
case "right":
|
|
1967
|
+
newX = 1 - offset / dielineWidth;
|
|
1968
|
+
if (confine) {
|
|
1969
|
+
const minY = fh / 2 / dielineHeight;
|
|
1970
|
+
const maxY = 1 - minY;
|
|
1971
|
+
newY = Math.max(minY, Math.min(newY, maxY));
|
|
1972
|
+
}
|
|
1973
|
+
break;
|
|
1974
|
+
}
|
|
1975
|
+
return { x: newX, y: newY };
|
|
1976
|
+
};
|
|
1977
|
+
var internalConstraint = (x, y, feature, context) => {
|
|
1978
|
+
var _a;
|
|
1979
|
+
const { dielineWidth, dielineHeight } = context;
|
|
1980
|
+
const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
|
|
1981
|
+
const margin = params.margin || 0;
|
|
1982
|
+
const fw = feature.width || 0;
|
|
1983
|
+
const fh = feature.height || 0;
|
|
1984
|
+
const minX = (margin + fw / 2) / dielineWidth;
|
|
1985
|
+
const maxX = 1 - (margin + fw / 2) / dielineWidth;
|
|
1986
|
+
const minY = (margin + fh / 2) / dielineHeight;
|
|
1987
|
+
const maxY = 1 - (margin + fh / 2) / dielineHeight;
|
|
1988
|
+
const clampedX = minX > maxX ? 0.5 : Math.max(minX, Math.min(x, maxX));
|
|
1989
|
+
const clampedY = minY > maxY ? 0.5 : Math.max(minY, Math.min(y, maxY));
|
|
1990
|
+
return { x: clampedX, y: clampedY };
|
|
1991
|
+
};
|
|
1992
|
+
var tangentBottomConstraint = (x, y, feature, context) => {
|
|
1993
|
+
var _a;
|
|
1994
|
+
const { dielineWidth, dielineHeight } = context;
|
|
1995
|
+
const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
|
|
1996
|
+
const gap = params.gap || 0;
|
|
1997
|
+
const confineX = params.confineX !== false;
|
|
1998
|
+
const extentY = feature.shape === "circle" ? feature.radius || 0 : (feature.height || 0) / 2;
|
|
1999
|
+
const newY = 1 + (extentY + gap) / dielineHeight;
|
|
2000
|
+
let newX = x;
|
|
2001
|
+
if (confineX) {
|
|
2002
|
+
const extentX = feature.shape === "circle" ? feature.radius || 0 : (feature.width || 0) / 2;
|
|
2003
|
+
const minX = extentX / dielineWidth;
|
|
2004
|
+
const maxX = 1 - extentX / dielineWidth;
|
|
2005
|
+
newX = minX > maxX ? 0.5 : Math.max(minX, Math.min(newX, maxX));
|
|
2006
|
+
}
|
|
2007
|
+
return { x: newX, y: newY };
|
|
2008
|
+
};
|
|
2009
|
+
ConstraintRegistry.register("edge", edgeConstraint);
|
|
2010
|
+
ConstraintRegistry.register("internal", internalConstraint);
|
|
2011
|
+
ConstraintRegistry.register("tangent-bottom", tangentBottomConstraint);
|
|
2012
|
+
|
|
2013
|
+
// src/featureComplete.ts
|
|
2014
|
+
function validateFeaturesStrict(features, context) {
|
|
2015
|
+
var _a;
|
|
2016
|
+
const eps = 1e-6;
|
|
2017
|
+
const issues = [];
|
|
2018
|
+
for (const f of features) {
|
|
2019
|
+
if (!((_a = f.constraints) == null ? void 0 : _a.type)) continue;
|
|
2020
|
+
const constrained = ConstraintRegistry.apply(f.x, f.y, f, context);
|
|
2021
|
+
if (Math.abs(constrained.x - f.x) > eps || Math.abs(constrained.y - f.y) > eps) {
|
|
2022
|
+
issues.push({
|
|
2023
|
+
featureId: f.id,
|
|
2024
|
+
groupId: f.groupId,
|
|
2025
|
+
reason: "Position violates constraint strategy"
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
return { ok: issues.length === 0, issues: issues.length ? issues : void 0 };
|
|
2030
|
+
}
|
|
2031
|
+
function completeFeaturesStrict(features, context, update) {
|
|
2032
|
+
const validation = validateFeaturesStrict(features, context);
|
|
2033
|
+
if (!validation.ok) return validation;
|
|
2034
|
+
const next = JSON.parse(JSON.stringify(features || []));
|
|
2035
|
+
update(next);
|
|
2036
|
+
return { ok: true };
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
// src/feature.ts
|
|
1804
2040
|
var FeatureTool = class {
|
|
1805
2041
|
constructor(options) {
|
|
1806
2042
|
this.id = "pooder.kit.feature";
|
|
1807
2043
|
this.metadata = {
|
|
1808
2044
|
name: "FeatureTool"
|
|
1809
2045
|
};
|
|
1810
|
-
this.
|
|
2046
|
+
this.workingFeatures = [];
|
|
1811
2047
|
this.isUpdatingConfig = false;
|
|
1812
2048
|
this.isToolActive = false;
|
|
1813
2049
|
this.handleMoving = null;
|
|
@@ -1833,12 +2069,15 @@ var FeatureTool = class {
|
|
|
1833
2069
|
"ConfigurationService"
|
|
1834
2070
|
);
|
|
1835
2071
|
if (configService) {
|
|
1836
|
-
|
|
2072
|
+
const features = configService.get("dieline.features", []) || [];
|
|
2073
|
+
this.workingFeatures = this.cloneFeatures(features);
|
|
1837
2074
|
configService.onAnyChange((e) => {
|
|
1838
2075
|
if (this.isUpdatingConfig) return;
|
|
1839
2076
|
if (e.key === "dieline.features") {
|
|
1840
|
-
|
|
2077
|
+
const next = e.value || [];
|
|
2078
|
+
this.workingFeatures = this.cloneFeatures(next);
|
|
1841
2079
|
this.redraw();
|
|
2080
|
+
this.emitWorkingChange();
|
|
1842
2081
|
}
|
|
1843
2082
|
});
|
|
1844
2083
|
}
|
|
@@ -1896,27 +2135,151 @@ var FeatureTool = class {
|
|
|
1896
2135
|
command: "clearFeatures",
|
|
1897
2136
|
title: "Clear Features",
|
|
1898
2137
|
handler: () => {
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
);
|
|
1903
|
-
if (configService) {
|
|
1904
|
-
configService.update("dieline.features", []);
|
|
1905
|
-
}
|
|
2138
|
+
this.setWorkingFeatures([]);
|
|
2139
|
+
this.redraw();
|
|
2140
|
+
this.emitWorkingChange();
|
|
1906
2141
|
return true;
|
|
1907
2142
|
}
|
|
2143
|
+
},
|
|
2144
|
+
{
|
|
2145
|
+
command: "getWorkingFeatures",
|
|
2146
|
+
title: "Get Working Features",
|
|
2147
|
+
handler: () => {
|
|
2148
|
+
return this.cloneFeatures(this.workingFeatures);
|
|
2149
|
+
}
|
|
2150
|
+
},
|
|
2151
|
+
{
|
|
2152
|
+
command: "setWorkingFeatures",
|
|
2153
|
+
title: "Set Working Features",
|
|
2154
|
+
handler: async (features) => {
|
|
2155
|
+
await this.refreshGeometry();
|
|
2156
|
+
this.setWorkingFeatures(this.cloneFeatures(features || []));
|
|
2157
|
+
this.redraw();
|
|
2158
|
+
this.emitWorkingChange();
|
|
2159
|
+
return { ok: true };
|
|
2160
|
+
}
|
|
2161
|
+
},
|
|
2162
|
+
{
|
|
2163
|
+
command: "updateWorkingGroupPosition",
|
|
2164
|
+
title: "Update Working Group Position",
|
|
2165
|
+
handler: (groupId, x, y) => {
|
|
2166
|
+
return this.updateWorkingGroupPosition(groupId, x, y);
|
|
2167
|
+
}
|
|
2168
|
+
},
|
|
2169
|
+
{
|
|
2170
|
+
command: "completeFeatures",
|
|
2171
|
+
title: "Complete Features",
|
|
2172
|
+
handler: () => {
|
|
2173
|
+
return this.completeFeatures();
|
|
2174
|
+
}
|
|
1908
2175
|
}
|
|
1909
2176
|
]
|
|
1910
2177
|
};
|
|
1911
2178
|
}
|
|
1912
|
-
|
|
2179
|
+
cloneFeatures(features) {
|
|
2180
|
+
return JSON.parse(JSON.stringify(features || []));
|
|
2181
|
+
}
|
|
2182
|
+
emitWorkingChange() {
|
|
1913
2183
|
var _a;
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
2184
|
+
(_a = this.context) == null ? void 0 : _a.eventBus.emit("feature:working:change", {
|
|
2185
|
+
features: this.cloneFeatures(this.workingFeatures)
|
|
2186
|
+
});
|
|
2187
|
+
}
|
|
2188
|
+
async refreshGeometry() {
|
|
2189
|
+
if (!this.context) return;
|
|
2190
|
+
const commandService = this.context.services.get("CommandService");
|
|
2191
|
+
if (!commandService) return;
|
|
2192
|
+
try {
|
|
2193
|
+
const g = await Promise.resolve(commandService.executeCommand("getGeometry"));
|
|
2194
|
+
if (g) this.currentGeometry = g;
|
|
2195
|
+
} catch (e) {
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
setWorkingFeatures(next) {
|
|
2199
|
+
this.workingFeatures = next;
|
|
2200
|
+
}
|
|
2201
|
+
updateWorkingGroupPosition(groupId, x, y) {
|
|
2202
|
+
var _a, _b, _c;
|
|
2203
|
+
if (!groupId) return { ok: false };
|
|
2204
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get("ConfigurationService");
|
|
2205
|
+
if (!configService) return { ok: false };
|
|
2206
|
+
const dielineWidth = parseLengthToMm(
|
|
2207
|
+
(_b = configService.get("dieline.width")) != null ? _b : 500,
|
|
2208
|
+
"mm"
|
|
2209
|
+
);
|
|
2210
|
+
const dielineHeight = parseLengthToMm(
|
|
2211
|
+
(_c = configService.get("dieline.height")) != null ? _c : 500,
|
|
2212
|
+
"mm"
|
|
2213
|
+
);
|
|
2214
|
+
let changed = false;
|
|
2215
|
+
const next = this.workingFeatures.map((f) => {
|
|
2216
|
+
if (f.groupId !== groupId) return f;
|
|
2217
|
+
let nx = x;
|
|
2218
|
+
let ny = y;
|
|
2219
|
+
if (f.constraints && dielineWidth > 0 && dielineHeight > 0) {
|
|
2220
|
+
const constrained = ConstraintRegistry.apply(nx, ny, f, {
|
|
2221
|
+
dielineWidth,
|
|
2222
|
+
dielineHeight
|
|
2223
|
+
});
|
|
2224
|
+
nx = constrained.x;
|
|
2225
|
+
ny = constrained.y;
|
|
2226
|
+
}
|
|
2227
|
+
if (f.x !== nx || f.y !== ny) {
|
|
2228
|
+
changed = true;
|
|
2229
|
+
return { ...f, x: nx, y: ny };
|
|
2230
|
+
}
|
|
2231
|
+
return f;
|
|
2232
|
+
});
|
|
2233
|
+
if (!changed) return { ok: true };
|
|
2234
|
+
this.setWorkingFeatures(next);
|
|
2235
|
+
this.redraw();
|
|
2236
|
+
this.enforceConstraints();
|
|
2237
|
+
this.emitWorkingChange();
|
|
2238
|
+
return { ok: true };
|
|
2239
|
+
}
|
|
2240
|
+
completeFeatures() {
|
|
2241
|
+
var _a, _b, _c;
|
|
2242
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get("ConfigurationService");
|
|
2243
|
+
if (!configService) {
|
|
2244
|
+
return {
|
|
2245
|
+
ok: false,
|
|
2246
|
+
issues: [
|
|
2247
|
+
{ featureId: "unknown", reason: "ConfigurationService not found" }
|
|
2248
|
+
]
|
|
2249
|
+
};
|
|
2250
|
+
}
|
|
2251
|
+
const dielineWidth = parseLengthToMm(
|
|
2252
|
+
(_b = configService.get("dieline.width")) != null ? _b : 500,
|
|
2253
|
+
"mm"
|
|
1917
2254
|
);
|
|
1918
|
-
const
|
|
1919
|
-
|
|
2255
|
+
const dielineHeight = parseLengthToMm(
|
|
2256
|
+
(_c = configService.get("dieline.height")) != null ? _c : 500,
|
|
2257
|
+
"mm"
|
|
2258
|
+
);
|
|
2259
|
+
const result = completeFeaturesStrict(
|
|
2260
|
+
this.workingFeatures,
|
|
2261
|
+
{ dielineWidth, dielineHeight },
|
|
2262
|
+
(next) => {
|
|
2263
|
+
this.isUpdatingConfig = true;
|
|
2264
|
+
try {
|
|
2265
|
+
configService.update("dieline.features", next);
|
|
2266
|
+
} finally {
|
|
2267
|
+
this.isUpdatingConfig = false;
|
|
2268
|
+
}
|
|
2269
|
+
this.workingFeatures = this.cloneFeatures(next);
|
|
2270
|
+
this.emitWorkingChange();
|
|
2271
|
+
}
|
|
2272
|
+
);
|
|
2273
|
+
if (!result.ok) {
|
|
2274
|
+
return {
|
|
2275
|
+
ok: false,
|
|
2276
|
+
issues: result.issues
|
|
2277
|
+
};
|
|
2278
|
+
}
|
|
2279
|
+
return { ok: true };
|
|
2280
|
+
}
|
|
2281
|
+
addFeature(type) {
|
|
2282
|
+
if (!this.canvasService) return false;
|
|
1920
2283
|
const newFeature = {
|
|
1921
2284
|
id: Date.now().toString(),
|
|
1922
2285
|
operation: type,
|
|
@@ -1925,28 +2288,17 @@ var FeatureTool = class {
|
|
|
1925
2288
|
x: 0.5,
|
|
1926
2289
|
y: 0,
|
|
1927
2290
|
// Top edge
|
|
1928
|
-
width:
|
|
1929
|
-
height:
|
|
2291
|
+
width: 10,
|
|
2292
|
+
height: 10,
|
|
1930
2293
|
rotation: 0
|
|
1931
2294
|
};
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
[]
|
|
1936
|
-
);
|
|
1937
|
-
configService.update("dieline.features", [...current, newFeature]);
|
|
1938
|
-
}
|
|
2295
|
+
this.setWorkingFeatures([...this.workingFeatures || [], newFeature]);
|
|
2296
|
+
this.redraw();
|
|
2297
|
+
this.emitWorkingChange();
|
|
1939
2298
|
return true;
|
|
1940
2299
|
}
|
|
1941
2300
|
addDoubleLayerHole() {
|
|
1942
|
-
var _a;
|
|
1943
2301
|
if (!this.canvasService) return false;
|
|
1944
|
-
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
1945
|
-
"ConfigurationService"
|
|
1946
|
-
);
|
|
1947
|
-
const unit = (configService == null ? void 0 : configService.get("dieline.unit", "mm")) || "mm";
|
|
1948
|
-
const lugRadius = Coordinate.convertUnit(20, "mm", unit);
|
|
1949
|
-
const holeRadius = Coordinate.convertUnit(15, "mm", unit);
|
|
1950
2302
|
const groupId = Date.now().toString();
|
|
1951
2303
|
const timestamp = Date.now();
|
|
1952
2304
|
const lug = {
|
|
@@ -1957,8 +2309,7 @@ var FeatureTool = class {
|
|
|
1957
2309
|
placement: "edge",
|
|
1958
2310
|
x: 0.5,
|
|
1959
2311
|
y: 0,
|
|
1960
|
-
radius:
|
|
1961
|
-
// 20mm
|
|
2312
|
+
radius: 20,
|
|
1962
2313
|
rotation: 0
|
|
1963
2314
|
};
|
|
1964
2315
|
const hole = {
|
|
@@ -1969,17 +2320,12 @@ var FeatureTool = class {
|
|
|
1969
2320
|
placement: "edge",
|
|
1970
2321
|
x: 0.5,
|
|
1971
2322
|
y: 0,
|
|
1972
|
-
radius:
|
|
1973
|
-
// 15mm
|
|
2323
|
+
radius: 15,
|
|
1974
2324
|
rotation: 0
|
|
1975
2325
|
};
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
[]
|
|
1980
|
-
);
|
|
1981
|
-
configService.update("dieline.features", [...current, lug, hole]);
|
|
1982
|
-
}
|
|
2326
|
+
this.setWorkingFeatures([...this.workingFeatures || [], lug, hole]);
|
|
2327
|
+
this.redraw();
|
|
2328
|
+
this.emitWorkingChange();
|
|
1983
2329
|
return true;
|
|
1984
2330
|
}
|
|
1985
2331
|
getGeometryForFeature(geometry, feature) {
|
|
@@ -2023,12 +2369,12 @@ var FeatureTool = class {
|
|
|
2023
2369
|
if ((_b = target.data) == null ? void 0 : _b.isGroup) {
|
|
2024
2370
|
const indices = (_c = target.data) == null ? void 0 : _c.indices;
|
|
2025
2371
|
if (indices && indices.length > 0) {
|
|
2026
|
-
feature = this.
|
|
2372
|
+
feature = this.workingFeatures[indices[0]];
|
|
2027
2373
|
}
|
|
2028
2374
|
} else {
|
|
2029
2375
|
const index = (_d = target.data) == null ? void 0 : _d.index;
|
|
2030
2376
|
if (index !== void 0) {
|
|
2031
|
-
feature = this.
|
|
2377
|
+
feature = this.workingFeatures[index];
|
|
2032
2378
|
}
|
|
2033
2379
|
}
|
|
2034
2380
|
const geometry = this.getGeometryForFeature(
|
|
@@ -2049,7 +2395,7 @@ var FeatureTool = class {
|
|
|
2049
2395
|
}
|
|
2050
2396
|
if (!this.handleModified) {
|
|
2051
2397
|
this.handleModified = (e) => {
|
|
2052
|
-
var _a, _b, _c
|
|
2398
|
+
var _a, _b, _c;
|
|
2053
2399
|
const target = e.target;
|
|
2054
2400
|
if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "feature-marker") return;
|
|
2055
2401
|
if ((_b = target.data) == null ? void 0 : _b.isGroup) {
|
|
@@ -2057,11 +2403,11 @@ var FeatureTool = class {
|
|
|
2057
2403
|
const indices = (_c = groupObj.data) == null ? void 0 : _c.indices;
|
|
2058
2404
|
if (!indices) return;
|
|
2059
2405
|
const groupCenter = new import_fabric4.Point(groupObj.left, groupObj.top);
|
|
2060
|
-
const newFeatures = [...this.
|
|
2406
|
+
const newFeatures = [...this.workingFeatures];
|
|
2061
2407
|
const { x, y } = this.currentGeometry;
|
|
2062
2408
|
groupObj.getObjects().forEach((child, i) => {
|
|
2063
2409
|
const originalIndex = indices[i];
|
|
2064
|
-
const feature = this.
|
|
2410
|
+
const feature = this.workingFeatures[originalIndex];
|
|
2065
2411
|
const geometry = this.getGeometryForFeature(
|
|
2066
2412
|
this.currentGeometry,
|
|
2067
2413
|
feature
|
|
@@ -2079,18 +2425,8 @@ var FeatureTool = class {
|
|
|
2079
2425
|
y: normalizedY
|
|
2080
2426
|
};
|
|
2081
2427
|
});
|
|
2082
|
-
this.
|
|
2083
|
-
|
|
2084
|
-
"ConfigurationService"
|
|
2085
|
-
);
|
|
2086
|
-
if (configService) {
|
|
2087
|
-
this.isUpdatingConfig = true;
|
|
2088
|
-
try {
|
|
2089
|
-
configService.update("dieline.features", this.features);
|
|
2090
|
-
} finally {
|
|
2091
|
-
this.isUpdatingConfig = false;
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2428
|
+
this.setWorkingFeatures(newFeatures);
|
|
2429
|
+
this.emitWorkingChange();
|
|
2094
2430
|
} else {
|
|
2095
2431
|
this.syncFeatureFromCanvas(target);
|
|
2096
2432
|
}
|
|
@@ -2124,6 +2460,23 @@ var FeatureTool = class {
|
|
|
2124
2460
|
this.canvasService.requestRenderAll();
|
|
2125
2461
|
}
|
|
2126
2462
|
constrainPosition(p, geometry, limit, feature) {
|
|
2463
|
+
if (feature && feature.constraints) {
|
|
2464
|
+
const minX = geometry.x - geometry.width / 2;
|
|
2465
|
+
const minY = geometry.y - geometry.height / 2;
|
|
2466
|
+
const nx = geometry.width > 0 ? (p.x - minX) / geometry.width : 0.5;
|
|
2467
|
+
const ny = geometry.height > 0 ? (p.y - minY) / geometry.height : 0.5;
|
|
2468
|
+
const scale2 = geometry.scale || 1;
|
|
2469
|
+
const dielineWidth = geometry.width / scale2;
|
|
2470
|
+
const dielineHeight = geometry.height / scale2;
|
|
2471
|
+
const constrained = ConstraintRegistry.apply(nx, ny, feature, {
|
|
2472
|
+
dielineWidth,
|
|
2473
|
+
dielineHeight
|
|
2474
|
+
});
|
|
2475
|
+
return {
|
|
2476
|
+
x: minX + constrained.x * geometry.width,
|
|
2477
|
+
y: minY + constrained.y * geometry.height
|
|
2478
|
+
};
|
|
2479
|
+
}
|
|
2127
2480
|
if (feature && feature.placement === "internal") {
|
|
2128
2481
|
const minX = geometry.x - geometry.width / 2;
|
|
2129
2482
|
const maxX = geometry.x + geometry.width / 2;
|
|
@@ -2134,10 +2487,13 @@ var FeatureTool = class {
|
|
|
2134
2487
|
y: Math.max(minY, Math.min(maxY, p.y))
|
|
2135
2488
|
};
|
|
2136
2489
|
}
|
|
2137
|
-
const nearest = getNearestPointOnDieline(
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2490
|
+
const nearest = getNearestPointOnDieline(
|
|
2491
|
+
{ x: p.x, y: p.y },
|
|
2492
|
+
{
|
|
2493
|
+
...geometry,
|
|
2494
|
+
features: []
|
|
2495
|
+
}
|
|
2496
|
+
);
|
|
2141
2497
|
const dx = p.x - nearest.x;
|
|
2142
2498
|
const dy = p.y - nearest.y;
|
|
2143
2499
|
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
@@ -2154,9 +2510,9 @@ var FeatureTool = class {
|
|
|
2154
2510
|
var _a;
|
|
2155
2511
|
if (!this.currentGeometry || !this.context) return;
|
|
2156
2512
|
const index = (_a = target.data) == null ? void 0 : _a.index;
|
|
2157
|
-
if (index === void 0 || index < 0 || index >= this.
|
|
2513
|
+
if (index === void 0 || index < 0 || index >= this.workingFeatures.length)
|
|
2158
2514
|
return;
|
|
2159
|
-
const feature = this.
|
|
2515
|
+
const feature = this.workingFeatures[index];
|
|
2160
2516
|
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
2161
2517
|
const { width, height, x, y } = geometry;
|
|
2162
2518
|
const left = x - width / 2;
|
|
@@ -2169,20 +2525,10 @@ var FeatureTool = class {
|
|
|
2169
2525
|
y: normalizedY
|
|
2170
2526
|
// Could also update rotation if we allowed rotating markers
|
|
2171
2527
|
};
|
|
2172
|
-
const newFeatures = [...this.
|
|
2528
|
+
const newFeatures = [...this.workingFeatures];
|
|
2173
2529
|
newFeatures[index] = updatedFeature;
|
|
2174
|
-
this.
|
|
2175
|
-
|
|
2176
|
-
"ConfigurationService"
|
|
2177
|
-
);
|
|
2178
|
-
if (configService) {
|
|
2179
|
-
this.isUpdatingConfig = true;
|
|
2180
|
-
try {
|
|
2181
|
-
configService.update("dieline.features", this.features);
|
|
2182
|
-
} finally {
|
|
2183
|
-
this.isUpdatingConfig = false;
|
|
2184
|
-
}
|
|
2185
|
-
}
|
|
2530
|
+
this.setWorkingFeatures(newFeatures);
|
|
2531
|
+
this.emitWorkingChange();
|
|
2186
2532
|
}
|
|
2187
2533
|
redraw() {
|
|
2188
2534
|
if (!this.canvasService || !this.currentGeometry) return;
|
|
@@ -2193,7 +2539,7 @@ var FeatureTool = class {
|
|
|
2193
2539
|
return ((_a = obj.data) == null ? void 0 : _a.type) === "feature-marker";
|
|
2194
2540
|
});
|
|
2195
2541
|
existing.forEach((obj) => canvas.remove(obj));
|
|
2196
|
-
if (!this.
|
|
2542
|
+
if (!this.workingFeatures || this.workingFeatures.length === 0) {
|
|
2197
2543
|
this.canvasService.requestRenderAll();
|
|
2198
2544
|
return;
|
|
2199
2545
|
}
|
|
@@ -2201,7 +2547,7 @@ var FeatureTool = class {
|
|
|
2201
2547
|
const finalScale = scale;
|
|
2202
2548
|
const groups = {};
|
|
2203
2549
|
const singles = [];
|
|
2204
|
-
this.
|
|
2550
|
+
this.workingFeatures.forEach((f, i) => {
|
|
2205
2551
|
if (f.groupId) {
|
|
2206
2552
|
if (!groups[f.groupId]) groups[f.groupId] = [];
|
|
2207
2553
|
groups[f.groupId].push({ feature: f, index: i });
|
|
@@ -2269,25 +2615,6 @@ var FeatureTool = class {
|
|
|
2269
2615
|
lockScalingY: true,
|
|
2270
2616
|
data: { type: "feature-marker", index, isGroup: false }
|
|
2271
2617
|
});
|
|
2272
|
-
marker.set("opacity", 0);
|
|
2273
|
-
marker.on("mouseover", () => {
|
|
2274
|
-
marker.set("opacity", 1);
|
|
2275
|
-
canvas.requestRenderAll();
|
|
2276
|
-
});
|
|
2277
|
-
marker.on("mouseout", () => {
|
|
2278
|
-
if (canvas.getActiveObject() !== marker) {
|
|
2279
|
-
marker.set("opacity", 0);
|
|
2280
|
-
canvas.requestRenderAll();
|
|
2281
|
-
}
|
|
2282
|
-
});
|
|
2283
|
-
marker.on("selected", () => {
|
|
2284
|
-
marker.set("opacity", 1);
|
|
2285
|
-
canvas.requestRenderAll();
|
|
2286
|
-
});
|
|
2287
|
-
marker.on("deselected", () => {
|
|
2288
|
-
marker.set("opacity", 0);
|
|
2289
|
-
canvas.requestRenderAll();
|
|
2290
|
-
});
|
|
2291
2618
|
canvas.add(marker);
|
|
2292
2619
|
canvas.bringObjectToFront(marker);
|
|
2293
2620
|
});
|
|
@@ -2324,25 +2651,6 @@ var FeatureTool = class {
|
|
|
2324
2651
|
indices: members.map((m) => m.index)
|
|
2325
2652
|
}
|
|
2326
2653
|
});
|
|
2327
|
-
groupObj.set("opacity", 0);
|
|
2328
|
-
groupObj.on("mouseover", () => {
|
|
2329
|
-
groupObj.set("opacity", 1);
|
|
2330
|
-
canvas.requestRenderAll();
|
|
2331
|
-
});
|
|
2332
|
-
groupObj.on("mouseout", () => {
|
|
2333
|
-
if (canvas.getActiveObject() !== groupObj) {
|
|
2334
|
-
groupObj.set("opacity", 0);
|
|
2335
|
-
canvas.requestRenderAll();
|
|
2336
|
-
}
|
|
2337
|
-
});
|
|
2338
|
-
groupObj.on("selected", () => {
|
|
2339
|
-
groupObj.set("opacity", 1);
|
|
2340
|
-
canvas.requestRenderAll();
|
|
2341
|
-
});
|
|
2342
|
-
groupObj.on("deselected", () => {
|
|
2343
|
-
groupObj.set("opacity", 0);
|
|
2344
|
-
canvas.requestRenderAll();
|
|
2345
|
-
});
|
|
2346
2654
|
canvas.add(groupObj);
|
|
2347
2655
|
canvas.bringObjectToFront(groupObj);
|
|
2348
2656
|
});
|
|
@@ -2361,12 +2669,12 @@ var FeatureTool = class {
|
|
|
2361
2669
|
if ((_a = marker.data) == null ? void 0 : _a.isGroup) {
|
|
2362
2670
|
const indices = (_b = marker.data) == null ? void 0 : _b.indices;
|
|
2363
2671
|
if (indices && indices.length > 0) {
|
|
2364
|
-
feature = this.
|
|
2672
|
+
feature = this.workingFeatures[indices[0]];
|
|
2365
2673
|
}
|
|
2366
2674
|
} else {
|
|
2367
2675
|
const index = (_c = marker.data) == null ? void 0 : _c.index;
|
|
2368
2676
|
if (index !== void 0) {
|
|
2369
|
-
feature = this.
|
|
2677
|
+
feature = this.workingFeatures[index];
|
|
2370
2678
|
}
|
|
2371
2679
|
}
|
|
2372
2680
|
const geometry = this.getGeometryForFeature(
|
|
@@ -3090,7 +3398,7 @@ var RulerTool = class {
|
|
|
3090
3398
|
// Dieline context for sync
|
|
3091
3399
|
this.dielineWidth = 500;
|
|
3092
3400
|
this.dielineHeight = 500;
|
|
3093
|
-
this.
|
|
3401
|
+
this.dielineDisplayUnit = "mm";
|
|
3094
3402
|
this.dielinePadding = 40;
|
|
3095
3403
|
this.dielineOffset = 0;
|
|
3096
3404
|
if (options) {
|
|
@@ -3114,7 +3422,10 @@ var RulerTool = class {
|
|
|
3114
3422
|
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
3115
3423
|
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
3116
3424
|
this.fontSize = configService.get("ruler.fontSize", this.fontSize);
|
|
3117
|
-
this.
|
|
3425
|
+
this.dielineDisplayUnit = configService.get(
|
|
3426
|
+
"dieline.displayUnit",
|
|
3427
|
+
this.dielineDisplayUnit
|
|
3428
|
+
);
|
|
3118
3429
|
this.dielineWidth = configService.get("dieline.width", this.dielineWidth);
|
|
3119
3430
|
this.dielineHeight = configService.get(
|
|
3120
3431
|
"dieline.height",
|
|
@@ -3137,7 +3448,8 @@ var RulerTool = class {
|
|
|
3137
3448
|
shouldUpdate = true;
|
|
3138
3449
|
}
|
|
3139
3450
|
} else if (e.key.startsWith("dieline.")) {
|
|
3140
|
-
if (e.key === "dieline.
|
|
3451
|
+
if (e.key === "dieline.displayUnit")
|
|
3452
|
+
this.dielineDisplayUnit = e.value;
|
|
3141
3453
|
if (e.key === "dieline.width") this.dielineWidth = e.value;
|
|
3142
3454
|
if (e.key === "dieline.height") this.dielineHeight = e.value;
|
|
3143
3455
|
if (e.key === "dieline.padding") this.dielinePadding = e.value;
|
|
@@ -3324,26 +3636,27 @@ var RulerTool = class {
|
|
|
3324
3636
|
const width = this.canvasService.canvas.width || 800;
|
|
3325
3637
|
const height = this.canvasService.canvas.height || 600;
|
|
3326
3638
|
const paddingPx = this.resolvePadding(width, height);
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3639
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
3640
|
+
this.canvasService.viewport.updatePhysical(
|
|
3641
|
+
this.dielineWidth,
|
|
3642
|
+
this.dielineHeight
|
|
3331
3643
|
);
|
|
3644
|
+
const layout = this.canvasService.viewport.layout;
|
|
3332
3645
|
const scale = layout.scale;
|
|
3333
3646
|
const offsetX = layout.offsetX;
|
|
3334
3647
|
const offsetY = layout.offsetY;
|
|
3335
3648
|
const visualWidth = layout.width;
|
|
3336
3649
|
const visualHeight = layout.height;
|
|
3337
|
-
const
|
|
3338
|
-
const
|
|
3339
|
-
const expandPixels =
|
|
3650
|
+
const rawOffsetMm = this.dielineOffset || 0;
|
|
3651
|
+
const effectiveOffsetMm = rawOffsetMm > 0 ? rawOffsetMm : 0;
|
|
3652
|
+
const expandPixels = effectiveOffsetMm * scale;
|
|
3340
3653
|
const gap = this.gap || 15;
|
|
3341
3654
|
const rulerLeft = offsetX - expandPixels;
|
|
3342
3655
|
const rulerTop = offsetY - expandPixels;
|
|
3343
3656
|
const rulerRight = offsetX + visualWidth + expandPixels;
|
|
3344
3657
|
const rulerBottom = offsetY + visualHeight + expandPixels;
|
|
3345
|
-
const
|
|
3346
|
-
const
|
|
3658
|
+
const displayWidthMm = this.dielineWidth + effectiveOffsetMm * 2;
|
|
3659
|
+
const displayHeightMm = this.dielineHeight + effectiveOffsetMm * 2;
|
|
3347
3660
|
const topRulerY = rulerTop - gap;
|
|
3348
3661
|
const topRulerXStart = rulerLeft;
|
|
3349
3662
|
const topRulerXEnd = rulerRight;
|
|
@@ -3386,8 +3699,8 @@ var RulerTool = class {
|
|
|
3386
3699
|
}
|
|
3387
3700
|
)
|
|
3388
3701
|
);
|
|
3389
|
-
const widthStr =
|
|
3390
|
-
const topTextContent = `${widthStr} ${this.
|
|
3702
|
+
const widthStr = formatMm(displayWidthMm, this.dielineDisplayUnit);
|
|
3703
|
+
const topTextContent = `${widthStr} ${this.dielineDisplayUnit}`;
|
|
3391
3704
|
const topText = new import_fabric7.Text(topTextContent, {
|
|
3392
3705
|
left: topRulerXStart + (rulerRight - rulerLeft) / 2,
|
|
3393
3706
|
top: topRulerY,
|
|
@@ -3442,8 +3755,8 @@ var RulerTool = class {
|
|
|
3442
3755
|
}
|
|
3443
3756
|
)
|
|
3444
3757
|
);
|
|
3445
|
-
const heightStr =
|
|
3446
|
-
const leftTextContent = `${heightStr} ${this.
|
|
3758
|
+
const heightStr = formatMm(displayHeightMm, this.dielineDisplayUnit);
|
|
3759
|
+
const leftTextContent = `${heightStr} ${this.dielineDisplayUnit}`;
|
|
3447
3760
|
const leftText = new import_fabric7.Text(leftTextContent, {
|
|
3448
3761
|
left: leftRulerX,
|
|
3449
3762
|
top: leftRulerYStart + (rulerBottom - rulerTop) / 2,
|
|
@@ -3555,6 +3868,81 @@ var MirrorTool = class {
|
|
|
3555
3868
|
|
|
3556
3869
|
// src/CanvasService.ts
|
|
3557
3870
|
var import_fabric8 = require("fabric");
|
|
3871
|
+
|
|
3872
|
+
// src/ViewportSystem.ts
|
|
3873
|
+
var ViewportSystem = class {
|
|
3874
|
+
constructor(containerSize = { width: 0, height: 0 }, physicalSize = { width: 0, height: 0 }, padding = 40) {
|
|
3875
|
+
this._containerSize = { width: 0, height: 0 };
|
|
3876
|
+
this._physicalSize = { width: 0, height: 0 };
|
|
3877
|
+
this._padding = 0;
|
|
3878
|
+
this._layout = {
|
|
3879
|
+
scale: 1,
|
|
3880
|
+
offsetX: 0,
|
|
3881
|
+
offsetY: 0,
|
|
3882
|
+
width: 0,
|
|
3883
|
+
height: 0
|
|
3884
|
+
};
|
|
3885
|
+
this._containerSize = containerSize;
|
|
3886
|
+
this._physicalSize = physicalSize;
|
|
3887
|
+
this._padding = padding;
|
|
3888
|
+
this.updateLayout();
|
|
3889
|
+
}
|
|
3890
|
+
get layout() {
|
|
3891
|
+
return this._layout;
|
|
3892
|
+
}
|
|
3893
|
+
get scale() {
|
|
3894
|
+
return this._layout.scale;
|
|
3895
|
+
}
|
|
3896
|
+
get offset() {
|
|
3897
|
+
return { x: this._layout.offsetX, y: this._layout.offsetY };
|
|
3898
|
+
}
|
|
3899
|
+
updateContainer(width, height) {
|
|
3900
|
+
if (this._containerSize.width === width && this._containerSize.height === height)
|
|
3901
|
+
return;
|
|
3902
|
+
this._containerSize = { width, height };
|
|
3903
|
+
this.updateLayout();
|
|
3904
|
+
}
|
|
3905
|
+
updatePhysical(width, height) {
|
|
3906
|
+
if (this._physicalSize.width === width && this._physicalSize.height === height)
|
|
3907
|
+
return;
|
|
3908
|
+
this._physicalSize = { width, height };
|
|
3909
|
+
this.updateLayout();
|
|
3910
|
+
}
|
|
3911
|
+
setPadding(padding) {
|
|
3912
|
+
if (this._padding === padding) return;
|
|
3913
|
+
this._padding = padding;
|
|
3914
|
+
this.updateLayout();
|
|
3915
|
+
}
|
|
3916
|
+
updateLayout() {
|
|
3917
|
+
this._layout = Coordinate.calculateLayout(
|
|
3918
|
+
this._containerSize,
|
|
3919
|
+
this._physicalSize,
|
|
3920
|
+
this._padding
|
|
3921
|
+
);
|
|
3922
|
+
}
|
|
3923
|
+
toPixel(value) {
|
|
3924
|
+
return value * this._layout.scale;
|
|
3925
|
+
}
|
|
3926
|
+
toPhysical(value) {
|
|
3927
|
+
return this._layout.scale === 0 ? 0 : value / this._layout.scale;
|
|
3928
|
+
}
|
|
3929
|
+
toPixelPoint(point) {
|
|
3930
|
+
return {
|
|
3931
|
+
x: point.x * this._layout.scale + this._layout.offsetX,
|
|
3932
|
+
y: point.y * this._layout.scale + this._layout.offsetY
|
|
3933
|
+
};
|
|
3934
|
+
}
|
|
3935
|
+
// Convert screen coordinate (e.g. mouse event) to physical coordinate (relative to content origin)
|
|
3936
|
+
toPhysicalPoint(point) {
|
|
3937
|
+
if (this._layout.scale === 0) return { x: 0, y: 0 };
|
|
3938
|
+
return {
|
|
3939
|
+
x: (point.x - this._layout.offsetX) / this._layout.scale,
|
|
3940
|
+
y: (point.y - this._layout.offsetY) / this._layout.scale
|
|
3941
|
+
};
|
|
3942
|
+
}
|
|
3943
|
+
};
|
|
3944
|
+
|
|
3945
|
+
// src/CanvasService.ts
|
|
3558
3946
|
var CanvasService = class {
|
|
3559
3947
|
constructor(el, options) {
|
|
3560
3948
|
if (el instanceof import_fabric8.Canvas) {
|
|
@@ -3565,6 +3953,10 @@ var CanvasService = class {
|
|
|
3565
3953
|
...options
|
|
3566
3954
|
});
|
|
3567
3955
|
}
|
|
3956
|
+
this.viewport = new ViewportSystem();
|
|
3957
|
+
if (this.canvas.width !== void 0 && this.canvas.height !== void 0) {
|
|
3958
|
+
this.viewport.updateContainer(this.canvas.width, this.canvas.height);
|
|
3959
|
+
}
|
|
3568
3960
|
if (options == null ? void 0 : options.eventBus) {
|
|
3569
3961
|
this.setEventBus(options.eventBus);
|
|
3570
3962
|
}
|
|
@@ -3645,5 +4037,7 @@ var CanvasService = class {
|
|
|
3645
4037
|
ImageTool,
|
|
3646
4038
|
MirrorTool,
|
|
3647
4039
|
RulerTool,
|
|
3648
|
-
WhiteInkTool
|
|
4040
|
+
WhiteInkTool,
|
|
4041
|
+
formatMm,
|
|
4042
|
+
parseLengthToMm
|
|
3649
4043
|
});
|