@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.mjs
CHANGED
|
@@ -677,6 +677,29 @@ var Coordinate = class {
|
|
|
677
677
|
}
|
|
678
678
|
};
|
|
679
679
|
|
|
680
|
+
// src/units.ts
|
|
681
|
+
function parseLengthToMm(input, defaultUnit) {
|
|
682
|
+
var _a, _b;
|
|
683
|
+
if (typeof input === "number") {
|
|
684
|
+
if (!Number.isFinite(input)) return 0;
|
|
685
|
+
return Coordinate.convertUnit(input, defaultUnit, "mm");
|
|
686
|
+
}
|
|
687
|
+
const raw = input.trim();
|
|
688
|
+
if (!raw) return 0;
|
|
689
|
+
const match = raw.match(/^([+-]?\d+(?:\.\d+)?)\s*(px|mm|cm|in)?$/i);
|
|
690
|
+
if (!match) return 0;
|
|
691
|
+
const value = Number(match[1]);
|
|
692
|
+
if (!Number.isFinite(value)) return 0;
|
|
693
|
+
const unit = (_b = (_a = match[2]) == null ? void 0 : _a.toLowerCase()) != null ? _b : defaultUnit;
|
|
694
|
+
return Coordinate.convertUnit(value, unit, "mm");
|
|
695
|
+
}
|
|
696
|
+
function formatMm(valueMm, displayUnit, fractionDigits = 2) {
|
|
697
|
+
if (!Number.isFinite(valueMm)) return "0";
|
|
698
|
+
const value = Coordinate.convertUnit(valueMm, "mm", displayUnit);
|
|
699
|
+
const rounded = Number(value.toFixed(fractionDigits));
|
|
700
|
+
return rounded.toString();
|
|
701
|
+
}
|
|
702
|
+
|
|
680
703
|
// src/geometry.ts
|
|
681
704
|
import paper2 from "paper";
|
|
682
705
|
function resolveFeaturePosition(feature, geometry) {
|
|
@@ -908,7 +931,7 @@ var DielineTool = class {
|
|
|
908
931
|
name: "DielineTool"
|
|
909
932
|
};
|
|
910
933
|
this.state = {
|
|
911
|
-
|
|
934
|
+
displayUnit: "mm",
|
|
912
935
|
shape: "rect",
|
|
913
936
|
width: 500,
|
|
914
937
|
height: 500,
|
|
@@ -954,50 +977,88 @@ var DielineTool = class {
|
|
|
954
977
|
const configService = context.services.get("ConfigurationService");
|
|
955
978
|
if (configService) {
|
|
956
979
|
const s = this.state;
|
|
957
|
-
s.
|
|
980
|
+
s.displayUnit = configService.get("dieline.displayUnit", s.displayUnit);
|
|
958
981
|
s.shape = configService.get("dieline.shape", s.shape);
|
|
959
|
-
s.width =
|
|
960
|
-
|
|
961
|
-
|
|
982
|
+
s.width = parseLengthToMm(
|
|
983
|
+
configService.get("dieline.width", s.width),
|
|
984
|
+
"mm"
|
|
985
|
+
);
|
|
986
|
+
s.height = parseLengthToMm(
|
|
987
|
+
configService.get("dieline.height", s.height),
|
|
988
|
+
"mm"
|
|
989
|
+
);
|
|
990
|
+
s.radius = parseLengthToMm(
|
|
991
|
+
configService.get("dieline.radius", s.radius),
|
|
992
|
+
"mm"
|
|
993
|
+
);
|
|
962
994
|
s.padding = configService.get("dieline.padding", s.padding);
|
|
963
|
-
s.offset =
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
995
|
+
s.offset = parseLengthToMm(
|
|
996
|
+
configService.get("dieline.offset", s.offset),
|
|
997
|
+
"mm"
|
|
998
|
+
);
|
|
999
|
+
s.mainLine.width = configService.get(
|
|
1000
|
+
"dieline.strokeWidth",
|
|
1001
|
+
s.mainLine.width
|
|
1002
|
+
);
|
|
1003
|
+
s.mainLine.color = configService.get(
|
|
1004
|
+
"dieline.strokeColor",
|
|
1005
|
+
s.mainLine.color
|
|
1006
|
+
);
|
|
1007
|
+
s.mainLine.dashLength = configService.get(
|
|
1008
|
+
"dieline.dashLength",
|
|
1009
|
+
s.mainLine.dashLength
|
|
1010
|
+
);
|
|
967
1011
|
s.mainLine.style = configService.get("dieline.style", s.mainLine.style);
|
|
968
|
-
s.offsetLine.width = configService.get(
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1012
|
+
s.offsetLine.width = configService.get(
|
|
1013
|
+
"dieline.offsetStrokeWidth",
|
|
1014
|
+
s.offsetLine.width
|
|
1015
|
+
);
|
|
1016
|
+
s.offsetLine.color = configService.get(
|
|
1017
|
+
"dieline.offsetStrokeColor",
|
|
1018
|
+
s.offsetLine.color
|
|
1019
|
+
);
|
|
1020
|
+
s.offsetLine.dashLength = configService.get(
|
|
1021
|
+
"dieline.offsetDashLength",
|
|
1022
|
+
s.offsetLine.dashLength
|
|
1023
|
+
);
|
|
1024
|
+
s.offsetLine.style = configService.get(
|
|
1025
|
+
"dieline.offsetStyle",
|
|
1026
|
+
s.offsetLine.style
|
|
1027
|
+
);
|
|
972
1028
|
s.insideColor = configService.get("dieline.insideColor", s.insideColor);
|
|
973
|
-
s.outsideColor = configService.get(
|
|
974
|
-
|
|
1029
|
+
s.outsideColor = configService.get(
|
|
1030
|
+
"dieline.outsideColor",
|
|
1031
|
+
s.outsideColor
|
|
1032
|
+
);
|
|
1033
|
+
s.showBleedLines = configService.get(
|
|
1034
|
+
"dieline.showBleedLines",
|
|
1035
|
+
s.showBleedLines
|
|
1036
|
+
);
|
|
975
1037
|
s.features = configService.get("dieline.features", s.features);
|
|
976
1038
|
s.pathData = configService.get("dieline.pathData", s.pathData);
|
|
977
1039
|
configService.onAnyChange((e) => {
|
|
978
1040
|
if (e.key.startsWith("dieline.")) {
|
|
979
|
-
console.log(`[DielineTool] Config change detected: ${e.key} -> ${e.value}`);
|
|
980
1041
|
switch (e.key) {
|
|
981
|
-
case "dieline.
|
|
982
|
-
s.
|
|
1042
|
+
case "dieline.displayUnit":
|
|
1043
|
+
s.displayUnit = e.value;
|
|
983
1044
|
break;
|
|
984
1045
|
case "dieline.shape":
|
|
985
1046
|
s.shape = e.value;
|
|
986
1047
|
break;
|
|
987
1048
|
case "dieline.width":
|
|
988
|
-
s.width = e.value;
|
|
1049
|
+
s.width = parseLengthToMm(e.value, "mm");
|
|
989
1050
|
break;
|
|
990
1051
|
case "dieline.height":
|
|
991
|
-
s.height = e.value;
|
|
1052
|
+
s.height = parseLengthToMm(e.value, "mm");
|
|
992
1053
|
break;
|
|
993
1054
|
case "dieline.radius":
|
|
994
|
-
s.radius = e.value;
|
|
1055
|
+
s.radius = parseLengthToMm(e.value, "mm");
|
|
995
1056
|
break;
|
|
996
1057
|
case "dieline.padding":
|
|
997
1058
|
s.padding = e.value;
|
|
998
1059
|
break;
|
|
999
1060
|
case "dieline.offset":
|
|
1000
|
-
s.offset = e.value;
|
|
1061
|
+
s.offset = parseLengthToMm(e.value, "mm");
|
|
1001
1062
|
break;
|
|
1002
1063
|
case "dieline.strokeWidth":
|
|
1003
1064
|
s.mainLine.width = e.value;
|
|
@@ -1056,11 +1117,11 @@ var DielineTool = class {
|
|
|
1056
1117
|
return {
|
|
1057
1118
|
[ContributionPointIds2.CONFIGURATIONS]: [
|
|
1058
1119
|
{
|
|
1059
|
-
id: "dieline.
|
|
1120
|
+
id: "dieline.displayUnit",
|
|
1060
1121
|
type: "select",
|
|
1061
|
-
label: "Unit",
|
|
1062
|
-
options: ["
|
|
1063
|
-
default: s.
|
|
1122
|
+
label: "Display Unit",
|
|
1123
|
+
options: ["mm", "cm", "in"],
|
|
1124
|
+
default: s.displayUnit
|
|
1064
1125
|
},
|
|
1065
1126
|
{
|
|
1066
1127
|
id: "dieline.shape",
|
|
@@ -1072,7 +1133,7 @@ var DielineTool = class {
|
|
|
1072
1133
|
{
|
|
1073
1134
|
id: "dieline.width",
|
|
1074
1135
|
type: "number",
|
|
1075
|
-
label: "Width",
|
|
1136
|
+
label: "Width (mm)",
|
|
1076
1137
|
min: 10,
|
|
1077
1138
|
max: 2e3,
|
|
1078
1139
|
default: s.width
|
|
@@ -1080,7 +1141,7 @@ var DielineTool = class {
|
|
|
1080
1141
|
{
|
|
1081
1142
|
id: "dieline.height",
|
|
1082
1143
|
type: "number",
|
|
1083
|
-
label: "Height",
|
|
1144
|
+
label: "Height (mm)",
|
|
1084
1145
|
min: 10,
|
|
1085
1146
|
max: 2e3,
|
|
1086
1147
|
default: s.height
|
|
@@ -1088,7 +1149,7 @@ var DielineTool = class {
|
|
|
1088
1149
|
{
|
|
1089
1150
|
id: "dieline.radius",
|
|
1090
1151
|
type: "number",
|
|
1091
|
-
label: "Corner Radius",
|
|
1152
|
+
label: "Corner Radius (mm)",
|
|
1092
1153
|
min: 0,
|
|
1093
1154
|
max: 500,
|
|
1094
1155
|
default: s.radius
|
|
@@ -1103,7 +1164,7 @@ var DielineTool = class {
|
|
|
1103
1164
|
{
|
|
1104
1165
|
id: "dieline.offset",
|
|
1105
1166
|
type: "number",
|
|
1106
|
-
label: "Bleed Offset",
|
|
1167
|
+
label: "Bleed Offset (mm)",
|
|
1107
1168
|
min: -100,
|
|
1108
1169
|
max: 100,
|
|
1109
1170
|
default: s.offset
|
|
@@ -1194,6 +1255,31 @@ var DielineTool = class {
|
|
|
1194
1255
|
}
|
|
1195
1256
|
],
|
|
1196
1257
|
[ContributionPointIds2.COMMANDS]: [
|
|
1258
|
+
{
|
|
1259
|
+
command: "updateFeaturePosition",
|
|
1260
|
+
title: "Update Feature Position",
|
|
1261
|
+
handler: (groupId, x, y) => {
|
|
1262
|
+
var _a;
|
|
1263
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
1264
|
+
"ConfigurationService"
|
|
1265
|
+
);
|
|
1266
|
+
if (!configService) return;
|
|
1267
|
+
const features = configService.get("dieline.features") || [];
|
|
1268
|
+
let changed = false;
|
|
1269
|
+
const newFeatures = features.map((f) => {
|
|
1270
|
+
if (f.groupId === groupId) {
|
|
1271
|
+
if (f.x !== x || f.y !== y) {
|
|
1272
|
+
changed = true;
|
|
1273
|
+
return { ...f, x, y };
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
return f;
|
|
1277
|
+
});
|
|
1278
|
+
if (changed) {
|
|
1279
|
+
configService.update("dieline.features", newFeatures);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
},
|
|
1197
1283
|
{
|
|
1198
1284
|
command: "getGeometry",
|
|
1199
1285
|
title: "Get Geometry",
|
|
@@ -1299,7 +1385,7 @@ var DielineTool = class {
|
|
|
1299
1385
|
const layer = this.getLayer();
|
|
1300
1386
|
if (!layer) return;
|
|
1301
1387
|
const {
|
|
1302
|
-
|
|
1388
|
+
displayUnit,
|
|
1303
1389
|
shape,
|
|
1304
1390
|
radius,
|
|
1305
1391
|
offset,
|
|
@@ -1310,15 +1396,13 @@ var DielineTool = class {
|
|
|
1310
1396
|
showBleedLines,
|
|
1311
1397
|
features
|
|
1312
1398
|
} = this.state;
|
|
1313
|
-
|
|
1399
|
+
const { width, height } = this.state;
|
|
1314
1400
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1315
1401
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1316
1402
|
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
paddingPx
|
|
1321
|
-
);
|
|
1403
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
1404
|
+
this.canvasService.viewport.updatePhysical(width, height);
|
|
1405
|
+
const layout = this.canvasService.viewport.layout;
|
|
1322
1406
|
const scale = layout.scale;
|
|
1323
1407
|
const cx = layout.offsetX + layout.width / 2;
|
|
1324
1408
|
const cy = layout.offsetY + layout.height / 2;
|
|
@@ -1505,15 +1589,22 @@ var DielineTool = class {
|
|
|
1505
1589
|
}
|
|
1506
1590
|
getGeometry() {
|
|
1507
1591
|
if (!this.canvasService) return null;
|
|
1508
|
-
const {
|
|
1592
|
+
const {
|
|
1593
|
+
displayUnit,
|
|
1594
|
+
shape,
|
|
1595
|
+
width,
|
|
1596
|
+
height,
|
|
1597
|
+
radius,
|
|
1598
|
+
offset,
|
|
1599
|
+
mainLine,
|
|
1600
|
+
pathData
|
|
1601
|
+
} = this.state;
|
|
1509
1602
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1510
1603
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1511
1604
|
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
paddingPx
|
|
1516
|
-
);
|
|
1605
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
1606
|
+
this.canvasService.viewport.updatePhysical(width, height);
|
|
1607
|
+
const layout = this.canvasService.viewport.layout;
|
|
1517
1608
|
const scale = layout.scale;
|
|
1518
1609
|
const cx = layout.offsetX + layout.width / 2;
|
|
1519
1610
|
const cy = layout.offsetY + layout.height / 2;
|
|
@@ -1521,14 +1612,14 @@ var DielineTool = class {
|
|
|
1521
1612
|
const visualHeight = layout.height;
|
|
1522
1613
|
return {
|
|
1523
1614
|
shape,
|
|
1524
|
-
unit,
|
|
1615
|
+
unit: "mm",
|
|
1616
|
+
displayUnit,
|
|
1525
1617
|
x: cx,
|
|
1526
1618
|
y: cy,
|
|
1527
1619
|
width: visualWidth,
|
|
1528
1620
|
height: visualHeight,
|
|
1529
1621
|
radius: radius * scale,
|
|
1530
1622
|
offset: offset * scale,
|
|
1531
|
-
// Pass scale to help other tools (like FeatureTool) convert units
|
|
1532
1623
|
scale,
|
|
1533
1624
|
strokeWidth: mainLine.width,
|
|
1534
1625
|
pathData
|
|
@@ -1538,15 +1629,13 @@ var DielineTool = class {
|
|
|
1538
1629
|
if (!this.canvasService) return null;
|
|
1539
1630
|
const userLayer = this.canvasService.getLayer("user");
|
|
1540
1631
|
if (!userLayer) return null;
|
|
1541
|
-
const { shape, width, height, radius, features,
|
|
1632
|
+
const { shape, width, height, radius, features, pathData } = this.state;
|
|
1542
1633
|
const canvasW = this.canvasService.canvas.width || 800;
|
|
1543
1634
|
const canvasH = this.canvasService.canvas.height || 600;
|
|
1544
1635
|
const paddingPx = this.resolvePadding(canvasW, canvasH);
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
paddingPx
|
|
1549
|
-
);
|
|
1636
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
1637
|
+
this.canvasService.viewport.updatePhysical(width, height);
|
|
1638
|
+
const layout = this.canvasService.viewport.layout;
|
|
1550
1639
|
const scale = layout.scale;
|
|
1551
1640
|
const cx = layout.offsetX + layout.width / 2;
|
|
1552
1641
|
const cy = layout.offsetY + layout.height / 2;
|
|
@@ -1765,13 +1854,158 @@ import {
|
|
|
1765
1854
|
ContributionPointIds as ContributionPointIds4
|
|
1766
1855
|
} from "@pooder/core";
|
|
1767
1856
|
import { Circle, Group, Point, Rect as Rect2 } from "fabric";
|
|
1857
|
+
|
|
1858
|
+
// src/constraints.ts
|
|
1859
|
+
var ConstraintRegistry = class {
|
|
1860
|
+
static register(type, handler) {
|
|
1861
|
+
this.handlers.set(type, handler);
|
|
1862
|
+
}
|
|
1863
|
+
static apply(x, y, feature, context) {
|
|
1864
|
+
if (!feature.constraints || !feature.constraints.type) {
|
|
1865
|
+
return { x, y };
|
|
1866
|
+
}
|
|
1867
|
+
const handler = this.handlers.get(feature.constraints.type);
|
|
1868
|
+
if (handler) {
|
|
1869
|
+
return handler(x, y, feature, context);
|
|
1870
|
+
}
|
|
1871
|
+
return { x, y };
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
ConstraintRegistry.handlers = /* @__PURE__ */ new Map();
|
|
1875
|
+
var edgeConstraint = (x, y, feature, context) => {
|
|
1876
|
+
var _a;
|
|
1877
|
+
const { dielineWidth, dielineHeight } = context;
|
|
1878
|
+
const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
|
|
1879
|
+
const allowedEdges = params.allowedEdges || [
|
|
1880
|
+
"top",
|
|
1881
|
+
"bottom",
|
|
1882
|
+
"left",
|
|
1883
|
+
"right"
|
|
1884
|
+
];
|
|
1885
|
+
const confine = params.confine || false;
|
|
1886
|
+
const offset = params.offset || 0;
|
|
1887
|
+
const distances = [];
|
|
1888
|
+
if (allowedEdges.includes("top"))
|
|
1889
|
+
distances.push({ edge: "top", dist: y * dielineHeight });
|
|
1890
|
+
if (allowedEdges.includes("bottom"))
|
|
1891
|
+
distances.push({ edge: "bottom", dist: (1 - y) * dielineHeight });
|
|
1892
|
+
if (allowedEdges.includes("left"))
|
|
1893
|
+
distances.push({ edge: "left", dist: x * dielineWidth });
|
|
1894
|
+
if (allowedEdges.includes("right"))
|
|
1895
|
+
distances.push({ edge: "right", dist: (1 - x) * dielineWidth });
|
|
1896
|
+
if (distances.length === 0) return { x, y };
|
|
1897
|
+
distances.sort((a, b) => a.dist - b.dist);
|
|
1898
|
+
const nearest = distances[0].edge;
|
|
1899
|
+
let newX = x;
|
|
1900
|
+
let newY = y;
|
|
1901
|
+
const fw = feature.width || 0;
|
|
1902
|
+
const fh = feature.height || 0;
|
|
1903
|
+
switch (nearest) {
|
|
1904
|
+
case "top":
|
|
1905
|
+
newY = 0 + offset / dielineHeight;
|
|
1906
|
+
if (confine) {
|
|
1907
|
+
const minX = fw / 2 / dielineWidth;
|
|
1908
|
+
const maxX = 1 - minX;
|
|
1909
|
+
newX = Math.max(minX, Math.min(newX, maxX));
|
|
1910
|
+
}
|
|
1911
|
+
break;
|
|
1912
|
+
case "bottom":
|
|
1913
|
+
newY = 1 - offset / dielineHeight;
|
|
1914
|
+
if (confine) {
|
|
1915
|
+
const minX = fw / 2 / dielineWidth;
|
|
1916
|
+
const maxX = 1 - minX;
|
|
1917
|
+
newX = Math.max(minX, Math.min(newX, maxX));
|
|
1918
|
+
}
|
|
1919
|
+
break;
|
|
1920
|
+
case "left":
|
|
1921
|
+
newX = 0 + offset / dielineWidth;
|
|
1922
|
+
if (confine) {
|
|
1923
|
+
const minY = fh / 2 / dielineHeight;
|
|
1924
|
+
const maxY = 1 - minY;
|
|
1925
|
+
newY = Math.max(minY, Math.min(newY, maxY));
|
|
1926
|
+
}
|
|
1927
|
+
break;
|
|
1928
|
+
case "right":
|
|
1929
|
+
newX = 1 - offset / dielineWidth;
|
|
1930
|
+
if (confine) {
|
|
1931
|
+
const minY = fh / 2 / dielineHeight;
|
|
1932
|
+
const maxY = 1 - minY;
|
|
1933
|
+
newY = Math.max(minY, Math.min(newY, maxY));
|
|
1934
|
+
}
|
|
1935
|
+
break;
|
|
1936
|
+
}
|
|
1937
|
+
return { x: newX, y: newY };
|
|
1938
|
+
};
|
|
1939
|
+
var internalConstraint = (x, y, feature, context) => {
|
|
1940
|
+
var _a;
|
|
1941
|
+
const { dielineWidth, dielineHeight } = context;
|
|
1942
|
+
const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
|
|
1943
|
+
const margin = params.margin || 0;
|
|
1944
|
+
const fw = feature.width || 0;
|
|
1945
|
+
const fh = feature.height || 0;
|
|
1946
|
+
const minX = (margin + fw / 2) / dielineWidth;
|
|
1947
|
+
const maxX = 1 - (margin + fw / 2) / dielineWidth;
|
|
1948
|
+
const minY = (margin + fh / 2) / dielineHeight;
|
|
1949
|
+
const maxY = 1 - (margin + fh / 2) / dielineHeight;
|
|
1950
|
+
const clampedX = minX > maxX ? 0.5 : Math.max(minX, Math.min(x, maxX));
|
|
1951
|
+
const clampedY = minY > maxY ? 0.5 : Math.max(minY, Math.min(y, maxY));
|
|
1952
|
+
return { x: clampedX, y: clampedY };
|
|
1953
|
+
};
|
|
1954
|
+
var tangentBottomConstraint = (x, y, feature, context) => {
|
|
1955
|
+
var _a;
|
|
1956
|
+
const { dielineWidth, dielineHeight } = context;
|
|
1957
|
+
const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
|
|
1958
|
+
const gap = params.gap || 0;
|
|
1959
|
+
const confineX = params.confineX !== false;
|
|
1960
|
+
const extentY = feature.shape === "circle" ? feature.radius || 0 : (feature.height || 0) / 2;
|
|
1961
|
+
const newY = 1 + (extentY + gap) / dielineHeight;
|
|
1962
|
+
let newX = x;
|
|
1963
|
+
if (confineX) {
|
|
1964
|
+
const extentX = feature.shape === "circle" ? feature.radius || 0 : (feature.width || 0) / 2;
|
|
1965
|
+
const minX = extentX / dielineWidth;
|
|
1966
|
+
const maxX = 1 - extentX / dielineWidth;
|
|
1967
|
+
newX = minX > maxX ? 0.5 : Math.max(minX, Math.min(newX, maxX));
|
|
1968
|
+
}
|
|
1969
|
+
return { x: newX, y: newY };
|
|
1970
|
+
};
|
|
1971
|
+
ConstraintRegistry.register("edge", edgeConstraint);
|
|
1972
|
+
ConstraintRegistry.register("internal", internalConstraint);
|
|
1973
|
+
ConstraintRegistry.register("tangent-bottom", tangentBottomConstraint);
|
|
1974
|
+
|
|
1975
|
+
// src/featureComplete.ts
|
|
1976
|
+
function validateFeaturesStrict(features, context) {
|
|
1977
|
+
var _a;
|
|
1978
|
+
const eps = 1e-6;
|
|
1979
|
+
const issues = [];
|
|
1980
|
+
for (const f of features) {
|
|
1981
|
+
if (!((_a = f.constraints) == null ? void 0 : _a.type)) continue;
|
|
1982
|
+
const constrained = ConstraintRegistry.apply(f.x, f.y, f, context);
|
|
1983
|
+
if (Math.abs(constrained.x - f.x) > eps || Math.abs(constrained.y - f.y) > eps) {
|
|
1984
|
+
issues.push({
|
|
1985
|
+
featureId: f.id,
|
|
1986
|
+
groupId: f.groupId,
|
|
1987
|
+
reason: "Position violates constraint strategy"
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
return { ok: issues.length === 0, issues: issues.length ? issues : void 0 };
|
|
1992
|
+
}
|
|
1993
|
+
function completeFeaturesStrict(features, context, update) {
|
|
1994
|
+
const validation = validateFeaturesStrict(features, context);
|
|
1995
|
+
if (!validation.ok) return validation;
|
|
1996
|
+
const next = JSON.parse(JSON.stringify(features || []));
|
|
1997
|
+
update(next);
|
|
1998
|
+
return { ok: true };
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
// src/feature.ts
|
|
1768
2002
|
var FeatureTool = class {
|
|
1769
2003
|
constructor(options) {
|
|
1770
2004
|
this.id = "pooder.kit.feature";
|
|
1771
2005
|
this.metadata = {
|
|
1772
2006
|
name: "FeatureTool"
|
|
1773
2007
|
};
|
|
1774
|
-
this.
|
|
2008
|
+
this.workingFeatures = [];
|
|
1775
2009
|
this.isUpdatingConfig = false;
|
|
1776
2010
|
this.isToolActive = false;
|
|
1777
2011
|
this.handleMoving = null;
|
|
@@ -1797,12 +2031,15 @@ var FeatureTool = class {
|
|
|
1797
2031
|
"ConfigurationService"
|
|
1798
2032
|
);
|
|
1799
2033
|
if (configService) {
|
|
1800
|
-
|
|
2034
|
+
const features = configService.get("dieline.features", []) || [];
|
|
2035
|
+
this.workingFeatures = this.cloneFeatures(features);
|
|
1801
2036
|
configService.onAnyChange((e) => {
|
|
1802
2037
|
if (this.isUpdatingConfig) return;
|
|
1803
2038
|
if (e.key === "dieline.features") {
|
|
1804
|
-
|
|
2039
|
+
const next = e.value || [];
|
|
2040
|
+
this.workingFeatures = this.cloneFeatures(next);
|
|
1805
2041
|
this.redraw();
|
|
2042
|
+
this.emitWorkingChange();
|
|
1806
2043
|
}
|
|
1807
2044
|
});
|
|
1808
2045
|
}
|
|
@@ -1860,27 +2097,151 @@ var FeatureTool = class {
|
|
|
1860
2097
|
command: "clearFeatures",
|
|
1861
2098
|
title: "Clear Features",
|
|
1862
2099
|
handler: () => {
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
);
|
|
1867
|
-
if (configService) {
|
|
1868
|
-
configService.update("dieline.features", []);
|
|
1869
|
-
}
|
|
2100
|
+
this.setWorkingFeatures([]);
|
|
2101
|
+
this.redraw();
|
|
2102
|
+
this.emitWorkingChange();
|
|
1870
2103
|
return true;
|
|
1871
2104
|
}
|
|
2105
|
+
},
|
|
2106
|
+
{
|
|
2107
|
+
command: "getWorkingFeatures",
|
|
2108
|
+
title: "Get Working Features",
|
|
2109
|
+
handler: () => {
|
|
2110
|
+
return this.cloneFeatures(this.workingFeatures);
|
|
2111
|
+
}
|
|
2112
|
+
},
|
|
2113
|
+
{
|
|
2114
|
+
command: "setWorkingFeatures",
|
|
2115
|
+
title: "Set Working Features",
|
|
2116
|
+
handler: async (features) => {
|
|
2117
|
+
await this.refreshGeometry();
|
|
2118
|
+
this.setWorkingFeatures(this.cloneFeatures(features || []));
|
|
2119
|
+
this.redraw();
|
|
2120
|
+
this.emitWorkingChange();
|
|
2121
|
+
return { ok: true };
|
|
2122
|
+
}
|
|
2123
|
+
},
|
|
2124
|
+
{
|
|
2125
|
+
command: "updateWorkingGroupPosition",
|
|
2126
|
+
title: "Update Working Group Position",
|
|
2127
|
+
handler: (groupId, x, y) => {
|
|
2128
|
+
return this.updateWorkingGroupPosition(groupId, x, y);
|
|
2129
|
+
}
|
|
2130
|
+
},
|
|
2131
|
+
{
|
|
2132
|
+
command: "completeFeatures",
|
|
2133
|
+
title: "Complete Features",
|
|
2134
|
+
handler: () => {
|
|
2135
|
+
return this.completeFeatures();
|
|
2136
|
+
}
|
|
1872
2137
|
}
|
|
1873
2138
|
]
|
|
1874
2139
|
};
|
|
1875
2140
|
}
|
|
1876
|
-
|
|
2141
|
+
cloneFeatures(features) {
|
|
2142
|
+
return JSON.parse(JSON.stringify(features || []));
|
|
2143
|
+
}
|
|
2144
|
+
emitWorkingChange() {
|
|
1877
2145
|
var _a;
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
2146
|
+
(_a = this.context) == null ? void 0 : _a.eventBus.emit("feature:working:change", {
|
|
2147
|
+
features: this.cloneFeatures(this.workingFeatures)
|
|
2148
|
+
});
|
|
2149
|
+
}
|
|
2150
|
+
async refreshGeometry() {
|
|
2151
|
+
if (!this.context) return;
|
|
2152
|
+
const commandService = this.context.services.get("CommandService");
|
|
2153
|
+
if (!commandService) return;
|
|
2154
|
+
try {
|
|
2155
|
+
const g = await Promise.resolve(commandService.executeCommand("getGeometry"));
|
|
2156
|
+
if (g) this.currentGeometry = g;
|
|
2157
|
+
} catch (e) {
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
setWorkingFeatures(next) {
|
|
2161
|
+
this.workingFeatures = next;
|
|
2162
|
+
}
|
|
2163
|
+
updateWorkingGroupPosition(groupId, x, y) {
|
|
2164
|
+
var _a, _b, _c;
|
|
2165
|
+
if (!groupId) return { ok: false };
|
|
2166
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get("ConfigurationService");
|
|
2167
|
+
if (!configService) return { ok: false };
|
|
2168
|
+
const dielineWidth = parseLengthToMm(
|
|
2169
|
+
(_b = configService.get("dieline.width")) != null ? _b : 500,
|
|
2170
|
+
"mm"
|
|
2171
|
+
);
|
|
2172
|
+
const dielineHeight = parseLengthToMm(
|
|
2173
|
+
(_c = configService.get("dieline.height")) != null ? _c : 500,
|
|
2174
|
+
"mm"
|
|
2175
|
+
);
|
|
2176
|
+
let changed = false;
|
|
2177
|
+
const next = this.workingFeatures.map((f) => {
|
|
2178
|
+
if (f.groupId !== groupId) return f;
|
|
2179
|
+
let nx = x;
|
|
2180
|
+
let ny = y;
|
|
2181
|
+
if (f.constraints && dielineWidth > 0 && dielineHeight > 0) {
|
|
2182
|
+
const constrained = ConstraintRegistry.apply(nx, ny, f, {
|
|
2183
|
+
dielineWidth,
|
|
2184
|
+
dielineHeight
|
|
2185
|
+
});
|
|
2186
|
+
nx = constrained.x;
|
|
2187
|
+
ny = constrained.y;
|
|
2188
|
+
}
|
|
2189
|
+
if (f.x !== nx || f.y !== ny) {
|
|
2190
|
+
changed = true;
|
|
2191
|
+
return { ...f, x: nx, y: ny };
|
|
2192
|
+
}
|
|
2193
|
+
return f;
|
|
2194
|
+
});
|
|
2195
|
+
if (!changed) return { ok: true };
|
|
2196
|
+
this.setWorkingFeatures(next);
|
|
2197
|
+
this.redraw();
|
|
2198
|
+
this.enforceConstraints();
|
|
2199
|
+
this.emitWorkingChange();
|
|
2200
|
+
return { ok: true };
|
|
2201
|
+
}
|
|
2202
|
+
completeFeatures() {
|
|
2203
|
+
var _a, _b, _c;
|
|
2204
|
+
const configService = (_a = this.context) == null ? void 0 : _a.services.get("ConfigurationService");
|
|
2205
|
+
if (!configService) {
|
|
2206
|
+
return {
|
|
2207
|
+
ok: false,
|
|
2208
|
+
issues: [
|
|
2209
|
+
{ featureId: "unknown", reason: "ConfigurationService not found" }
|
|
2210
|
+
]
|
|
2211
|
+
};
|
|
2212
|
+
}
|
|
2213
|
+
const dielineWidth = parseLengthToMm(
|
|
2214
|
+
(_b = configService.get("dieline.width")) != null ? _b : 500,
|
|
2215
|
+
"mm"
|
|
1881
2216
|
);
|
|
1882
|
-
const
|
|
1883
|
-
|
|
2217
|
+
const dielineHeight = parseLengthToMm(
|
|
2218
|
+
(_c = configService.get("dieline.height")) != null ? _c : 500,
|
|
2219
|
+
"mm"
|
|
2220
|
+
);
|
|
2221
|
+
const result = completeFeaturesStrict(
|
|
2222
|
+
this.workingFeatures,
|
|
2223
|
+
{ dielineWidth, dielineHeight },
|
|
2224
|
+
(next) => {
|
|
2225
|
+
this.isUpdatingConfig = true;
|
|
2226
|
+
try {
|
|
2227
|
+
configService.update("dieline.features", next);
|
|
2228
|
+
} finally {
|
|
2229
|
+
this.isUpdatingConfig = false;
|
|
2230
|
+
}
|
|
2231
|
+
this.workingFeatures = this.cloneFeatures(next);
|
|
2232
|
+
this.emitWorkingChange();
|
|
2233
|
+
}
|
|
2234
|
+
);
|
|
2235
|
+
if (!result.ok) {
|
|
2236
|
+
return {
|
|
2237
|
+
ok: false,
|
|
2238
|
+
issues: result.issues
|
|
2239
|
+
};
|
|
2240
|
+
}
|
|
2241
|
+
return { ok: true };
|
|
2242
|
+
}
|
|
2243
|
+
addFeature(type) {
|
|
2244
|
+
if (!this.canvasService) return false;
|
|
1884
2245
|
const newFeature = {
|
|
1885
2246
|
id: Date.now().toString(),
|
|
1886
2247
|
operation: type,
|
|
@@ -1889,28 +2250,17 @@ var FeatureTool = class {
|
|
|
1889
2250
|
x: 0.5,
|
|
1890
2251
|
y: 0,
|
|
1891
2252
|
// Top edge
|
|
1892
|
-
width:
|
|
1893
|
-
height:
|
|
2253
|
+
width: 10,
|
|
2254
|
+
height: 10,
|
|
1894
2255
|
rotation: 0
|
|
1895
2256
|
};
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
[]
|
|
1900
|
-
);
|
|
1901
|
-
configService.update("dieline.features", [...current, newFeature]);
|
|
1902
|
-
}
|
|
2257
|
+
this.setWorkingFeatures([...this.workingFeatures || [], newFeature]);
|
|
2258
|
+
this.redraw();
|
|
2259
|
+
this.emitWorkingChange();
|
|
1903
2260
|
return true;
|
|
1904
2261
|
}
|
|
1905
2262
|
addDoubleLayerHole() {
|
|
1906
|
-
var _a;
|
|
1907
2263
|
if (!this.canvasService) return false;
|
|
1908
|
-
const configService = (_a = this.context) == null ? void 0 : _a.services.get(
|
|
1909
|
-
"ConfigurationService"
|
|
1910
|
-
);
|
|
1911
|
-
const unit = (configService == null ? void 0 : configService.get("dieline.unit", "mm")) || "mm";
|
|
1912
|
-
const lugRadius = Coordinate.convertUnit(20, "mm", unit);
|
|
1913
|
-
const holeRadius = Coordinate.convertUnit(15, "mm", unit);
|
|
1914
2264
|
const groupId = Date.now().toString();
|
|
1915
2265
|
const timestamp = Date.now();
|
|
1916
2266
|
const lug = {
|
|
@@ -1921,8 +2271,7 @@ var FeatureTool = class {
|
|
|
1921
2271
|
placement: "edge",
|
|
1922
2272
|
x: 0.5,
|
|
1923
2273
|
y: 0,
|
|
1924
|
-
radius:
|
|
1925
|
-
// 20mm
|
|
2274
|
+
radius: 20,
|
|
1926
2275
|
rotation: 0
|
|
1927
2276
|
};
|
|
1928
2277
|
const hole = {
|
|
@@ -1933,17 +2282,12 @@ var FeatureTool = class {
|
|
|
1933
2282
|
placement: "edge",
|
|
1934
2283
|
x: 0.5,
|
|
1935
2284
|
y: 0,
|
|
1936
|
-
radius:
|
|
1937
|
-
// 15mm
|
|
2285
|
+
radius: 15,
|
|
1938
2286
|
rotation: 0
|
|
1939
2287
|
};
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
[]
|
|
1944
|
-
);
|
|
1945
|
-
configService.update("dieline.features", [...current, lug, hole]);
|
|
1946
|
-
}
|
|
2288
|
+
this.setWorkingFeatures([...this.workingFeatures || [], lug, hole]);
|
|
2289
|
+
this.redraw();
|
|
2290
|
+
this.emitWorkingChange();
|
|
1947
2291
|
return true;
|
|
1948
2292
|
}
|
|
1949
2293
|
getGeometryForFeature(geometry, feature) {
|
|
@@ -1987,12 +2331,12 @@ var FeatureTool = class {
|
|
|
1987
2331
|
if ((_b = target.data) == null ? void 0 : _b.isGroup) {
|
|
1988
2332
|
const indices = (_c = target.data) == null ? void 0 : _c.indices;
|
|
1989
2333
|
if (indices && indices.length > 0) {
|
|
1990
|
-
feature = this.
|
|
2334
|
+
feature = this.workingFeatures[indices[0]];
|
|
1991
2335
|
}
|
|
1992
2336
|
} else {
|
|
1993
2337
|
const index = (_d = target.data) == null ? void 0 : _d.index;
|
|
1994
2338
|
if (index !== void 0) {
|
|
1995
|
-
feature = this.
|
|
2339
|
+
feature = this.workingFeatures[index];
|
|
1996
2340
|
}
|
|
1997
2341
|
}
|
|
1998
2342
|
const geometry = this.getGeometryForFeature(
|
|
@@ -2013,7 +2357,7 @@ var FeatureTool = class {
|
|
|
2013
2357
|
}
|
|
2014
2358
|
if (!this.handleModified) {
|
|
2015
2359
|
this.handleModified = (e) => {
|
|
2016
|
-
var _a, _b, _c
|
|
2360
|
+
var _a, _b, _c;
|
|
2017
2361
|
const target = e.target;
|
|
2018
2362
|
if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "feature-marker") return;
|
|
2019
2363
|
if ((_b = target.data) == null ? void 0 : _b.isGroup) {
|
|
@@ -2021,11 +2365,11 @@ var FeatureTool = class {
|
|
|
2021
2365
|
const indices = (_c = groupObj.data) == null ? void 0 : _c.indices;
|
|
2022
2366
|
if (!indices) return;
|
|
2023
2367
|
const groupCenter = new Point(groupObj.left, groupObj.top);
|
|
2024
|
-
const newFeatures = [...this.
|
|
2368
|
+
const newFeatures = [...this.workingFeatures];
|
|
2025
2369
|
const { x, y } = this.currentGeometry;
|
|
2026
2370
|
groupObj.getObjects().forEach((child, i) => {
|
|
2027
2371
|
const originalIndex = indices[i];
|
|
2028
|
-
const feature = this.
|
|
2372
|
+
const feature = this.workingFeatures[originalIndex];
|
|
2029
2373
|
const geometry = this.getGeometryForFeature(
|
|
2030
2374
|
this.currentGeometry,
|
|
2031
2375
|
feature
|
|
@@ -2043,18 +2387,8 @@ var FeatureTool = class {
|
|
|
2043
2387
|
y: normalizedY
|
|
2044
2388
|
};
|
|
2045
2389
|
});
|
|
2046
|
-
this.
|
|
2047
|
-
|
|
2048
|
-
"ConfigurationService"
|
|
2049
|
-
);
|
|
2050
|
-
if (configService) {
|
|
2051
|
-
this.isUpdatingConfig = true;
|
|
2052
|
-
try {
|
|
2053
|
-
configService.update("dieline.features", this.features);
|
|
2054
|
-
} finally {
|
|
2055
|
-
this.isUpdatingConfig = false;
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2390
|
+
this.setWorkingFeatures(newFeatures);
|
|
2391
|
+
this.emitWorkingChange();
|
|
2058
2392
|
} else {
|
|
2059
2393
|
this.syncFeatureFromCanvas(target);
|
|
2060
2394
|
}
|
|
@@ -2088,6 +2422,23 @@ var FeatureTool = class {
|
|
|
2088
2422
|
this.canvasService.requestRenderAll();
|
|
2089
2423
|
}
|
|
2090
2424
|
constrainPosition(p, geometry, limit, feature) {
|
|
2425
|
+
if (feature && feature.constraints) {
|
|
2426
|
+
const minX = geometry.x - geometry.width / 2;
|
|
2427
|
+
const minY = geometry.y - geometry.height / 2;
|
|
2428
|
+
const nx = geometry.width > 0 ? (p.x - minX) / geometry.width : 0.5;
|
|
2429
|
+
const ny = geometry.height > 0 ? (p.y - minY) / geometry.height : 0.5;
|
|
2430
|
+
const scale2 = geometry.scale || 1;
|
|
2431
|
+
const dielineWidth = geometry.width / scale2;
|
|
2432
|
+
const dielineHeight = geometry.height / scale2;
|
|
2433
|
+
const constrained = ConstraintRegistry.apply(nx, ny, feature, {
|
|
2434
|
+
dielineWidth,
|
|
2435
|
+
dielineHeight
|
|
2436
|
+
});
|
|
2437
|
+
return {
|
|
2438
|
+
x: minX + constrained.x * geometry.width,
|
|
2439
|
+
y: minY + constrained.y * geometry.height
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2091
2442
|
if (feature && feature.placement === "internal") {
|
|
2092
2443
|
const minX = geometry.x - geometry.width / 2;
|
|
2093
2444
|
const maxX = geometry.x + geometry.width / 2;
|
|
@@ -2098,10 +2449,13 @@ var FeatureTool = class {
|
|
|
2098
2449
|
y: Math.max(minY, Math.min(maxY, p.y))
|
|
2099
2450
|
};
|
|
2100
2451
|
}
|
|
2101
|
-
const nearest = getNearestPointOnDieline(
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2452
|
+
const nearest = getNearestPointOnDieline(
|
|
2453
|
+
{ x: p.x, y: p.y },
|
|
2454
|
+
{
|
|
2455
|
+
...geometry,
|
|
2456
|
+
features: []
|
|
2457
|
+
}
|
|
2458
|
+
);
|
|
2105
2459
|
const dx = p.x - nearest.x;
|
|
2106
2460
|
const dy = p.y - nearest.y;
|
|
2107
2461
|
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
@@ -2118,9 +2472,9 @@ var FeatureTool = class {
|
|
|
2118
2472
|
var _a;
|
|
2119
2473
|
if (!this.currentGeometry || !this.context) return;
|
|
2120
2474
|
const index = (_a = target.data) == null ? void 0 : _a.index;
|
|
2121
|
-
if (index === void 0 || index < 0 || index >= this.
|
|
2475
|
+
if (index === void 0 || index < 0 || index >= this.workingFeatures.length)
|
|
2122
2476
|
return;
|
|
2123
|
-
const feature = this.
|
|
2477
|
+
const feature = this.workingFeatures[index];
|
|
2124
2478
|
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
2125
2479
|
const { width, height, x, y } = geometry;
|
|
2126
2480
|
const left = x - width / 2;
|
|
@@ -2133,20 +2487,10 @@ var FeatureTool = class {
|
|
|
2133
2487
|
y: normalizedY
|
|
2134
2488
|
// Could also update rotation if we allowed rotating markers
|
|
2135
2489
|
};
|
|
2136
|
-
const newFeatures = [...this.
|
|
2490
|
+
const newFeatures = [...this.workingFeatures];
|
|
2137
2491
|
newFeatures[index] = updatedFeature;
|
|
2138
|
-
this.
|
|
2139
|
-
|
|
2140
|
-
"ConfigurationService"
|
|
2141
|
-
);
|
|
2142
|
-
if (configService) {
|
|
2143
|
-
this.isUpdatingConfig = true;
|
|
2144
|
-
try {
|
|
2145
|
-
configService.update("dieline.features", this.features);
|
|
2146
|
-
} finally {
|
|
2147
|
-
this.isUpdatingConfig = false;
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2492
|
+
this.setWorkingFeatures(newFeatures);
|
|
2493
|
+
this.emitWorkingChange();
|
|
2150
2494
|
}
|
|
2151
2495
|
redraw() {
|
|
2152
2496
|
if (!this.canvasService || !this.currentGeometry) return;
|
|
@@ -2157,7 +2501,7 @@ var FeatureTool = class {
|
|
|
2157
2501
|
return ((_a = obj.data) == null ? void 0 : _a.type) === "feature-marker";
|
|
2158
2502
|
});
|
|
2159
2503
|
existing.forEach((obj) => canvas.remove(obj));
|
|
2160
|
-
if (!this.
|
|
2504
|
+
if (!this.workingFeatures || this.workingFeatures.length === 0) {
|
|
2161
2505
|
this.canvasService.requestRenderAll();
|
|
2162
2506
|
return;
|
|
2163
2507
|
}
|
|
@@ -2165,7 +2509,7 @@ var FeatureTool = class {
|
|
|
2165
2509
|
const finalScale = scale;
|
|
2166
2510
|
const groups = {};
|
|
2167
2511
|
const singles = [];
|
|
2168
|
-
this.
|
|
2512
|
+
this.workingFeatures.forEach((f, i) => {
|
|
2169
2513
|
if (f.groupId) {
|
|
2170
2514
|
if (!groups[f.groupId]) groups[f.groupId] = [];
|
|
2171
2515
|
groups[f.groupId].push({ feature: f, index: i });
|
|
@@ -2233,25 +2577,6 @@ var FeatureTool = class {
|
|
|
2233
2577
|
lockScalingY: true,
|
|
2234
2578
|
data: { type: "feature-marker", index, isGroup: false }
|
|
2235
2579
|
});
|
|
2236
|
-
marker.set("opacity", 0);
|
|
2237
|
-
marker.on("mouseover", () => {
|
|
2238
|
-
marker.set("opacity", 1);
|
|
2239
|
-
canvas.requestRenderAll();
|
|
2240
|
-
});
|
|
2241
|
-
marker.on("mouseout", () => {
|
|
2242
|
-
if (canvas.getActiveObject() !== marker) {
|
|
2243
|
-
marker.set("opacity", 0);
|
|
2244
|
-
canvas.requestRenderAll();
|
|
2245
|
-
}
|
|
2246
|
-
});
|
|
2247
|
-
marker.on("selected", () => {
|
|
2248
|
-
marker.set("opacity", 1);
|
|
2249
|
-
canvas.requestRenderAll();
|
|
2250
|
-
});
|
|
2251
|
-
marker.on("deselected", () => {
|
|
2252
|
-
marker.set("opacity", 0);
|
|
2253
|
-
canvas.requestRenderAll();
|
|
2254
|
-
});
|
|
2255
2580
|
canvas.add(marker);
|
|
2256
2581
|
canvas.bringObjectToFront(marker);
|
|
2257
2582
|
});
|
|
@@ -2288,25 +2613,6 @@ var FeatureTool = class {
|
|
|
2288
2613
|
indices: members.map((m) => m.index)
|
|
2289
2614
|
}
|
|
2290
2615
|
});
|
|
2291
|
-
groupObj.set("opacity", 0);
|
|
2292
|
-
groupObj.on("mouseover", () => {
|
|
2293
|
-
groupObj.set("opacity", 1);
|
|
2294
|
-
canvas.requestRenderAll();
|
|
2295
|
-
});
|
|
2296
|
-
groupObj.on("mouseout", () => {
|
|
2297
|
-
if (canvas.getActiveObject() !== groupObj) {
|
|
2298
|
-
groupObj.set("opacity", 0);
|
|
2299
|
-
canvas.requestRenderAll();
|
|
2300
|
-
}
|
|
2301
|
-
});
|
|
2302
|
-
groupObj.on("selected", () => {
|
|
2303
|
-
groupObj.set("opacity", 1);
|
|
2304
|
-
canvas.requestRenderAll();
|
|
2305
|
-
});
|
|
2306
|
-
groupObj.on("deselected", () => {
|
|
2307
|
-
groupObj.set("opacity", 0);
|
|
2308
|
-
canvas.requestRenderAll();
|
|
2309
|
-
});
|
|
2310
2616
|
canvas.add(groupObj);
|
|
2311
2617
|
canvas.bringObjectToFront(groupObj);
|
|
2312
2618
|
});
|
|
@@ -2325,12 +2631,12 @@ var FeatureTool = class {
|
|
|
2325
2631
|
if ((_a = marker.data) == null ? void 0 : _a.isGroup) {
|
|
2326
2632
|
const indices = (_b = marker.data) == null ? void 0 : _b.indices;
|
|
2327
2633
|
if (indices && indices.length > 0) {
|
|
2328
|
-
feature = this.
|
|
2634
|
+
feature = this.workingFeatures[indices[0]];
|
|
2329
2635
|
}
|
|
2330
2636
|
} else {
|
|
2331
2637
|
const index = (_c = marker.data) == null ? void 0 : _c.index;
|
|
2332
2638
|
if (index !== void 0) {
|
|
2333
|
-
feature = this.
|
|
2639
|
+
feature = this.workingFeatures[index];
|
|
2334
2640
|
}
|
|
2335
2641
|
}
|
|
2336
2642
|
const geometry = this.getGeometryForFeature(
|
|
@@ -3060,7 +3366,7 @@ var RulerTool = class {
|
|
|
3060
3366
|
// Dieline context for sync
|
|
3061
3367
|
this.dielineWidth = 500;
|
|
3062
3368
|
this.dielineHeight = 500;
|
|
3063
|
-
this.
|
|
3369
|
+
this.dielineDisplayUnit = "mm";
|
|
3064
3370
|
this.dielinePadding = 40;
|
|
3065
3371
|
this.dielineOffset = 0;
|
|
3066
3372
|
if (options) {
|
|
@@ -3084,7 +3390,10 @@ var RulerTool = class {
|
|
|
3084
3390
|
this.textColor = configService.get("ruler.textColor", this.textColor);
|
|
3085
3391
|
this.lineColor = configService.get("ruler.lineColor", this.lineColor);
|
|
3086
3392
|
this.fontSize = configService.get("ruler.fontSize", this.fontSize);
|
|
3087
|
-
this.
|
|
3393
|
+
this.dielineDisplayUnit = configService.get(
|
|
3394
|
+
"dieline.displayUnit",
|
|
3395
|
+
this.dielineDisplayUnit
|
|
3396
|
+
);
|
|
3088
3397
|
this.dielineWidth = configService.get("dieline.width", this.dielineWidth);
|
|
3089
3398
|
this.dielineHeight = configService.get(
|
|
3090
3399
|
"dieline.height",
|
|
@@ -3107,7 +3416,8 @@ var RulerTool = class {
|
|
|
3107
3416
|
shouldUpdate = true;
|
|
3108
3417
|
}
|
|
3109
3418
|
} else if (e.key.startsWith("dieline.")) {
|
|
3110
|
-
if (e.key === "dieline.
|
|
3419
|
+
if (e.key === "dieline.displayUnit")
|
|
3420
|
+
this.dielineDisplayUnit = e.value;
|
|
3111
3421
|
if (e.key === "dieline.width") this.dielineWidth = e.value;
|
|
3112
3422
|
if (e.key === "dieline.height") this.dielineHeight = e.value;
|
|
3113
3423
|
if (e.key === "dieline.padding") this.dielinePadding = e.value;
|
|
@@ -3294,26 +3604,27 @@ var RulerTool = class {
|
|
|
3294
3604
|
const width = this.canvasService.canvas.width || 800;
|
|
3295
3605
|
const height = this.canvasService.canvas.height || 600;
|
|
3296
3606
|
const paddingPx = this.resolvePadding(width, height);
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3607
|
+
this.canvasService.viewport.setPadding(paddingPx);
|
|
3608
|
+
this.canvasService.viewport.updatePhysical(
|
|
3609
|
+
this.dielineWidth,
|
|
3610
|
+
this.dielineHeight
|
|
3301
3611
|
);
|
|
3612
|
+
const layout = this.canvasService.viewport.layout;
|
|
3302
3613
|
const scale = layout.scale;
|
|
3303
3614
|
const offsetX = layout.offsetX;
|
|
3304
3615
|
const offsetY = layout.offsetY;
|
|
3305
3616
|
const visualWidth = layout.width;
|
|
3306
3617
|
const visualHeight = layout.height;
|
|
3307
|
-
const
|
|
3308
|
-
const
|
|
3309
|
-
const expandPixels =
|
|
3618
|
+
const rawOffsetMm = this.dielineOffset || 0;
|
|
3619
|
+
const effectiveOffsetMm = rawOffsetMm > 0 ? rawOffsetMm : 0;
|
|
3620
|
+
const expandPixels = effectiveOffsetMm * scale;
|
|
3310
3621
|
const gap = this.gap || 15;
|
|
3311
3622
|
const rulerLeft = offsetX - expandPixels;
|
|
3312
3623
|
const rulerTop = offsetY - expandPixels;
|
|
3313
3624
|
const rulerRight = offsetX + visualWidth + expandPixels;
|
|
3314
3625
|
const rulerBottom = offsetY + visualHeight + expandPixels;
|
|
3315
|
-
const
|
|
3316
|
-
const
|
|
3626
|
+
const displayWidthMm = this.dielineWidth + effectiveOffsetMm * 2;
|
|
3627
|
+
const displayHeightMm = this.dielineHeight + effectiveOffsetMm * 2;
|
|
3317
3628
|
const topRulerY = rulerTop - gap;
|
|
3318
3629
|
const topRulerXStart = rulerLeft;
|
|
3319
3630
|
const topRulerXEnd = rulerRight;
|
|
@@ -3356,8 +3667,8 @@ var RulerTool = class {
|
|
|
3356
3667
|
}
|
|
3357
3668
|
)
|
|
3358
3669
|
);
|
|
3359
|
-
const widthStr =
|
|
3360
|
-
const topTextContent = `${widthStr} ${this.
|
|
3670
|
+
const widthStr = formatMm(displayWidthMm, this.dielineDisplayUnit);
|
|
3671
|
+
const topTextContent = `${widthStr} ${this.dielineDisplayUnit}`;
|
|
3361
3672
|
const topText = new Text(topTextContent, {
|
|
3362
3673
|
left: topRulerXStart + (rulerRight - rulerLeft) / 2,
|
|
3363
3674
|
top: topRulerY,
|
|
@@ -3412,8 +3723,8 @@ var RulerTool = class {
|
|
|
3412
3723
|
}
|
|
3413
3724
|
)
|
|
3414
3725
|
);
|
|
3415
|
-
const heightStr =
|
|
3416
|
-
const leftTextContent = `${heightStr} ${this.
|
|
3726
|
+
const heightStr = formatMm(displayHeightMm, this.dielineDisplayUnit);
|
|
3727
|
+
const leftTextContent = `${heightStr} ${this.dielineDisplayUnit}`;
|
|
3417
3728
|
const leftText = new Text(leftTextContent, {
|
|
3418
3729
|
left: leftRulerX,
|
|
3419
3730
|
top: leftRulerYStart + (rulerBottom - rulerTop) / 2,
|
|
@@ -3527,6 +3838,81 @@ var MirrorTool = class {
|
|
|
3527
3838
|
|
|
3528
3839
|
// src/CanvasService.ts
|
|
3529
3840
|
import { Canvas, Group as Group3 } from "fabric";
|
|
3841
|
+
|
|
3842
|
+
// src/ViewportSystem.ts
|
|
3843
|
+
var ViewportSystem = class {
|
|
3844
|
+
constructor(containerSize = { width: 0, height: 0 }, physicalSize = { width: 0, height: 0 }, padding = 40) {
|
|
3845
|
+
this._containerSize = { width: 0, height: 0 };
|
|
3846
|
+
this._physicalSize = { width: 0, height: 0 };
|
|
3847
|
+
this._padding = 0;
|
|
3848
|
+
this._layout = {
|
|
3849
|
+
scale: 1,
|
|
3850
|
+
offsetX: 0,
|
|
3851
|
+
offsetY: 0,
|
|
3852
|
+
width: 0,
|
|
3853
|
+
height: 0
|
|
3854
|
+
};
|
|
3855
|
+
this._containerSize = containerSize;
|
|
3856
|
+
this._physicalSize = physicalSize;
|
|
3857
|
+
this._padding = padding;
|
|
3858
|
+
this.updateLayout();
|
|
3859
|
+
}
|
|
3860
|
+
get layout() {
|
|
3861
|
+
return this._layout;
|
|
3862
|
+
}
|
|
3863
|
+
get scale() {
|
|
3864
|
+
return this._layout.scale;
|
|
3865
|
+
}
|
|
3866
|
+
get offset() {
|
|
3867
|
+
return { x: this._layout.offsetX, y: this._layout.offsetY };
|
|
3868
|
+
}
|
|
3869
|
+
updateContainer(width, height) {
|
|
3870
|
+
if (this._containerSize.width === width && this._containerSize.height === height)
|
|
3871
|
+
return;
|
|
3872
|
+
this._containerSize = { width, height };
|
|
3873
|
+
this.updateLayout();
|
|
3874
|
+
}
|
|
3875
|
+
updatePhysical(width, height) {
|
|
3876
|
+
if (this._physicalSize.width === width && this._physicalSize.height === height)
|
|
3877
|
+
return;
|
|
3878
|
+
this._physicalSize = { width, height };
|
|
3879
|
+
this.updateLayout();
|
|
3880
|
+
}
|
|
3881
|
+
setPadding(padding) {
|
|
3882
|
+
if (this._padding === padding) return;
|
|
3883
|
+
this._padding = padding;
|
|
3884
|
+
this.updateLayout();
|
|
3885
|
+
}
|
|
3886
|
+
updateLayout() {
|
|
3887
|
+
this._layout = Coordinate.calculateLayout(
|
|
3888
|
+
this._containerSize,
|
|
3889
|
+
this._physicalSize,
|
|
3890
|
+
this._padding
|
|
3891
|
+
);
|
|
3892
|
+
}
|
|
3893
|
+
toPixel(value) {
|
|
3894
|
+
return value * this._layout.scale;
|
|
3895
|
+
}
|
|
3896
|
+
toPhysical(value) {
|
|
3897
|
+
return this._layout.scale === 0 ? 0 : value / this._layout.scale;
|
|
3898
|
+
}
|
|
3899
|
+
toPixelPoint(point) {
|
|
3900
|
+
return {
|
|
3901
|
+
x: point.x * this._layout.scale + this._layout.offsetX,
|
|
3902
|
+
y: point.y * this._layout.scale + this._layout.offsetY
|
|
3903
|
+
};
|
|
3904
|
+
}
|
|
3905
|
+
// Convert screen coordinate (e.g. mouse event) to physical coordinate (relative to content origin)
|
|
3906
|
+
toPhysicalPoint(point) {
|
|
3907
|
+
if (this._layout.scale === 0) return { x: 0, y: 0 };
|
|
3908
|
+
return {
|
|
3909
|
+
x: (point.x - this._layout.offsetX) / this._layout.scale,
|
|
3910
|
+
y: (point.y - this._layout.offsetY) / this._layout.scale
|
|
3911
|
+
};
|
|
3912
|
+
}
|
|
3913
|
+
};
|
|
3914
|
+
|
|
3915
|
+
// src/CanvasService.ts
|
|
3530
3916
|
var CanvasService = class {
|
|
3531
3917
|
constructor(el, options) {
|
|
3532
3918
|
if (el instanceof Canvas) {
|
|
@@ -3537,6 +3923,10 @@ var CanvasService = class {
|
|
|
3537
3923
|
...options
|
|
3538
3924
|
});
|
|
3539
3925
|
}
|
|
3926
|
+
this.viewport = new ViewportSystem();
|
|
3927
|
+
if (this.canvas.width !== void 0 && this.canvas.height !== void 0) {
|
|
3928
|
+
this.viewport.updateContainer(this.canvas.width, this.canvas.height);
|
|
3929
|
+
}
|
|
3540
3930
|
if (options == null ? void 0 : options.eventBus) {
|
|
3541
3931
|
this.setEventBus(options.eventBus);
|
|
3542
3932
|
}
|
|
@@ -3616,5 +4006,7 @@ export {
|
|
|
3616
4006
|
ImageTool,
|
|
3617
4007
|
MirrorTool,
|
|
3618
4008
|
RulerTool,
|
|
3619
|
-
WhiteInkTool
|
|
4009
|
+
WhiteInkTool,
|
|
4010
|
+
formatMm,
|
|
4011
|
+
parseLengthToMm
|
|
3620
4012
|
};
|