@pooder/kit 6.1.2 → 6.2.1
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/extensions/background/BackgroundTool.js +177 -5
- package/.test-dist/src/extensions/constraintUtils.js +44 -0
- package/.test-dist/src/extensions/dieline/DielineTool.js +52 -409
- package/.test-dist/src/extensions/dieline/featureResolution.js +29 -0
- package/.test-dist/src/extensions/dieline/model.js +83 -0
- package/.test-dist/src/extensions/dieline/renderBuilder.js +227 -0
- package/.test-dist/src/extensions/feature/FeatureTool.js +156 -45
- package/.test-dist/src/extensions/featureCoordinates.js +21 -0
- package/.test-dist/src/extensions/featurePlacement.js +46 -0
- package/.test-dist/src/extensions/image/ImageTool.js +281 -25
- package/.test-dist/src/extensions/ruler/RulerTool.js +24 -1
- package/.test-dist/src/shared/constants/layers.js +3 -1
- package/.test-dist/tests/run.js +25 -0
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +47 -13
- package/dist/index.d.ts +47 -13
- package/dist/index.js +1325 -977
- package/dist/index.mjs +1311 -966
- package/package.json +1 -1
- package/src/extensions/background/BackgroundTool.ts +264 -4
- package/src/extensions/dieline/DielineTool.ts +67 -548
- package/src/extensions/dieline/model.ts +165 -1
- package/src/extensions/dieline/renderBuilder.ts +301 -0
- package/src/extensions/feature/FeatureTool.ts +190 -47
- package/src/extensions/featureCoordinates.ts +35 -0
- package/src/extensions/featurePlacement.ts +118 -0
- package/src/extensions/image/ImageTool.ts +139 -157
- package/src/extensions/ruler/RulerTool.ts +24 -2
- package/src/shared/constants/layers.ts +2 -0
- package/tests/run.ts +37 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildDielineRenderBundle = buildDielineRenderBundle;
|
|
4
|
+
const geometry_1 = require("../geometry");
|
|
5
|
+
const featurePlacement_1 = require("../featurePlacement");
|
|
6
|
+
const layers_1 = require("../../shared/constants/layers");
|
|
7
|
+
const DEFAULT_IDS = {
|
|
8
|
+
inside: "dieline.inside",
|
|
9
|
+
bleedZone: "dieline.bleed-zone",
|
|
10
|
+
offsetBorder: "dieline.offset-border",
|
|
11
|
+
border: "dieline.border",
|
|
12
|
+
clip: "dieline.clip.image",
|
|
13
|
+
clipSource: "dieline.effect.clip-path",
|
|
14
|
+
};
|
|
15
|
+
function buildDielineRenderBundle(options) {
|
|
16
|
+
const ids = { ...DEFAULT_IDS, ...(options.ids || {}) };
|
|
17
|
+
const { state, sceneLayout, canvasWidth, canvasHeight, hasImages, createHatchPattern, includeImageClipEffect = true, clipTargetPassIds = [layers_1.IMAGE_OBJECT_LAYER_ID], clipVisibility, } = options;
|
|
18
|
+
const { shape, shapeStyle, radius, mainLine, offsetLine, insideColor } = state;
|
|
19
|
+
const scale = sceneLayout.scale;
|
|
20
|
+
const cx = sceneLayout.trimRect.centerX;
|
|
21
|
+
const cy = sceneLayout.trimRect.centerY;
|
|
22
|
+
const visualWidth = sceneLayout.trimRect.width;
|
|
23
|
+
const visualHeight = sceneLayout.trimRect.height;
|
|
24
|
+
const visualRadius = radius * scale;
|
|
25
|
+
const cutW = sceneLayout.cutRect.width;
|
|
26
|
+
const cutH = sceneLayout.cutRect.height;
|
|
27
|
+
const visualOffset = (cutW - visualWidth) / 2;
|
|
28
|
+
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
29
|
+
const placements = (0, featurePlacement_1.resolveFeaturePlacements)(state.features || [], {
|
|
30
|
+
shape,
|
|
31
|
+
shapeStyle,
|
|
32
|
+
pathData: state.pathData,
|
|
33
|
+
customSourceWidthPx: state.customSourceWidthPx,
|
|
34
|
+
customSourceHeightPx: state.customSourceHeightPx,
|
|
35
|
+
canvasWidth,
|
|
36
|
+
canvasHeight,
|
|
37
|
+
x: cx,
|
|
38
|
+
y: cy,
|
|
39
|
+
width: visualWidth,
|
|
40
|
+
height: visualHeight,
|
|
41
|
+
radius: visualRadius,
|
|
42
|
+
scale,
|
|
43
|
+
});
|
|
44
|
+
const absoluteFeatures = (0, featurePlacement_1.projectPlacedFeatures)(placements, {
|
|
45
|
+
x: cx,
|
|
46
|
+
y: cy,
|
|
47
|
+
width: visualWidth,
|
|
48
|
+
height: visualHeight,
|
|
49
|
+
}, scale);
|
|
50
|
+
const cutFeatures = (0, featurePlacement_1.projectPlacedFeatures)(placements.filter((placement) => !placement.feature.skipCut), {
|
|
51
|
+
x: cx,
|
|
52
|
+
y: cy,
|
|
53
|
+
width: cutW,
|
|
54
|
+
height: cutH,
|
|
55
|
+
}, scale);
|
|
56
|
+
const common = {
|
|
57
|
+
shape,
|
|
58
|
+
shapeStyle,
|
|
59
|
+
pathData: state.pathData,
|
|
60
|
+
customSourceWidthPx: state.customSourceWidthPx,
|
|
61
|
+
customSourceHeightPx: state.customSourceHeightPx,
|
|
62
|
+
canvasWidth,
|
|
63
|
+
canvasHeight,
|
|
64
|
+
};
|
|
65
|
+
const specs = [];
|
|
66
|
+
if (insideColor &&
|
|
67
|
+
insideColor !== "transparent" &&
|
|
68
|
+
insideColor !== "rgba(0,0,0,0)" &&
|
|
69
|
+
!hasImages) {
|
|
70
|
+
specs.push({
|
|
71
|
+
id: ids.inside,
|
|
72
|
+
type: "path",
|
|
73
|
+
space: "screen",
|
|
74
|
+
data: { id: ids.inside, type: "dieline" },
|
|
75
|
+
props: {
|
|
76
|
+
pathData: (0, geometry_1.generateDielinePath)({
|
|
77
|
+
...common,
|
|
78
|
+
width: cutW,
|
|
79
|
+
height: cutH,
|
|
80
|
+
radius: cutR,
|
|
81
|
+
x: cx,
|
|
82
|
+
y: cy,
|
|
83
|
+
features: cutFeatures,
|
|
84
|
+
}),
|
|
85
|
+
fill: insideColor,
|
|
86
|
+
stroke: null,
|
|
87
|
+
selectable: false,
|
|
88
|
+
evented: false,
|
|
89
|
+
originX: "left",
|
|
90
|
+
originY: "top",
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (Math.abs(visualOffset) > 0.0001) {
|
|
95
|
+
const trimPathInput = {
|
|
96
|
+
...common,
|
|
97
|
+
width: visualWidth,
|
|
98
|
+
height: visualHeight,
|
|
99
|
+
radius: visualRadius,
|
|
100
|
+
x: cx,
|
|
101
|
+
y: cy,
|
|
102
|
+
features: cutFeatures,
|
|
103
|
+
};
|
|
104
|
+
const cutPathInput = {
|
|
105
|
+
...common,
|
|
106
|
+
width: cutW,
|
|
107
|
+
height: cutH,
|
|
108
|
+
radius: cutR,
|
|
109
|
+
x: cx,
|
|
110
|
+
y: cy,
|
|
111
|
+
features: cutFeatures,
|
|
112
|
+
};
|
|
113
|
+
if (state.showBleedLines !== false) {
|
|
114
|
+
const pattern = createHatchPattern?.(mainLine.color);
|
|
115
|
+
if (pattern) {
|
|
116
|
+
specs.push({
|
|
117
|
+
id: ids.bleedZone,
|
|
118
|
+
type: "path",
|
|
119
|
+
space: "screen",
|
|
120
|
+
data: { id: ids.bleedZone, type: "dieline" },
|
|
121
|
+
props: {
|
|
122
|
+
pathData: (0, geometry_1.generateBleedZonePath)(trimPathInput, cutPathInput, visualOffset),
|
|
123
|
+
fill: pattern,
|
|
124
|
+
stroke: null,
|
|
125
|
+
selectable: false,
|
|
126
|
+
evented: false,
|
|
127
|
+
objectCaching: false,
|
|
128
|
+
originX: "left",
|
|
129
|
+
originY: "top",
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
specs.push({
|
|
135
|
+
id: ids.offsetBorder,
|
|
136
|
+
type: "path",
|
|
137
|
+
space: "screen",
|
|
138
|
+
data: { id: ids.offsetBorder, type: "dieline" },
|
|
139
|
+
props: {
|
|
140
|
+
pathData: (0, geometry_1.generateDielinePath)(cutPathInput),
|
|
141
|
+
fill: null,
|
|
142
|
+
stroke: offsetLine.style === "hidden" ? null : offsetLine.color,
|
|
143
|
+
strokeWidth: offsetLine.width,
|
|
144
|
+
strokeDashArray: offsetLine.style === "dashed"
|
|
145
|
+
? [offsetLine.dashLength, offsetLine.dashLength]
|
|
146
|
+
: undefined,
|
|
147
|
+
selectable: false,
|
|
148
|
+
evented: false,
|
|
149
|
+
originX: "left",
|
|
150
|
+
originY: "top",
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
specs.push({
|
|
155
|
+
id: ids.border,
|
|
156
|
+
type: "path",
|
|
157
|
+
space: "screen",
|
|
158
|
+
data: { id: ids.border, type: "dieline" },
|
|
159
|
+
props: {
|
|
160
|
+
pathData: (0, geometry_1.generateDielinePath)({
|
|
161
|
+
...common,
|
|
162
|
+
width: visualWidth,
|
|
163
|
+
height: visualHeight,
|
|
164
|
+
radius: visualRadius,
|
|
165
|
+
x: cx,
|
|
166
|
+
y: cy,
|
|
167
|
+
features: absoluteFeatures,
|
|
168
|
+
}),
|
|
169
|
+
fill: "transparent",
|
|
170
|
+
stroke: mainLine.style === "hidden" ? null : mainLine.color,
|
|
171
|
+
strokeWidth: mainLine.width,
|
|
172
|
+
strokeDashArray: mainLine.style === "dashed"
|
|
173
|
+
? [mainLine.dashLength, mainLine.dashLength]
|
|
174
|
+
: undefined,
|
|
175
|
+
selectable: false,
|
|
176
|
+
evented: false,
|
|
177
|
+
originX: "left",
|
|
178
|
+
originY: "top",
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
if (!includeImageClipEffect) {
|
|
182
|
+
return { specs, effects: [] };
|
|
183
|
+
}
|
|
184
|
+
const clipPathData = (0, geometry_1.generateDielinePath)({
|
|
185
|
+
...common,
|
|
186
|
+
width: cutW,
|
|
187
|
+
height: cutH,
|
|
188
|
+
radius: cutR,
|
|
189
|
+
x: cx,
|
|
190
|
+
y: cy,
|
|
191
|
+
features: cutFeatures,
|
|
192
|
+
});
|
|
193
|
+
if (!clipPathData) {
|
|
194
|
+
return { specs, effects: [] };
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
specs,
|
|
198
|
+
effects: [
|
|
199
|
+
{
|
|
200
|
+
type: "clipPath",
|
|
201
|
+
id: ids.clip,
|
|
202
|
+
visibility: clipVisibility,
|
|
203
|
+
targetPassIds: clipTargetPassIds,
|
|
204
|
+
source: {
|
|
205
|
+
id: ids.clipSource,
|
|
206
|
+
type: "path",
|
|
207
|
+
space: "screen",
|
|
208
|
+
data: {
|
|
209
|
+
id: ids.clipSource,
|
|
210
|
+
type: "dieline-effect",
|
|
211
|
+
effect: "clipPath",
|
|
212
|
+
},
|
|
213
|
+
props: {
|
|
214
|
+
pathData: clipPathData,
|
|
215
|
+
fill: "#000000",
|
|
216
|
+
stroke: null,
|
|
217
|
+
originX: "left",
|
|
218
|
+
originY: "top",
|
|
219
|
+
selectable: false,
|
|
220
|
+
evented: false,
|
|
221
|
+
excludeFromExport: true,
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FeatureTool = void 0;
|
|
4
4
|
const core_1 = require("@pooder/core");
|
|
5
|
-
const
|
|
5
|
+
const fabric_1 = require("fabric");
|
|
6
6
|
const constraints_1 = require("../constraints");
|
|
7
7
|
const featureComplete_1 = require("../featureComplete");
|
|
8
|
+
const featurePlacement_1 = require("../featurePlacement");
|
|
8
9
|
const sceneLayoutModel_1 = require("../../shared/scene/sceneLayoutModel");
|
|
9
10
|
const layers_1 = require("../../shared/constants/layers");
|
|
10
11
|
const subscriptions_1 = require("../../shared/runtime/subscriptions");
|
|
11
12
|
const sessionState_1 = require("../../shared/runtime/sessionState");
|
|
13
|
+
const renderBuilder_1 = require("../dieline/renderBuilder");
|
|
14
|
+
const model_1 = require("../dieline/model");
|
|
12
15
|
const FEATURE_STROKE_WIDTH = 2;
|
|
13
16
|
const DEFAULT_RECT_SIZE = 10;
|
|
14
17
|
const DEFAULT_CIRCLE_RADIUS = 5;
|
|
@@ -24,7 +27,9 @@ class FeatureTool {
|
|
|
24
27
|
this.isFeatureSessionActive = false;
|
|
25
28
|
this.sessionOriginalFeatures = null;
|
|
26
29
|
this.hasWorkingChanges = false;
|
|
27
|
-
this.
|
|
30
|
+
this.markerSpecs = [];
|
|
31
|
+
this.sessionDielineSpecs = [];
|
|
32
|
+
this.sessionDielineEffects = [];
|
|
28
33
|
this.renderSeq = 0;
|
|
29
34
|
this.subscriptions = new subscriptions_1.SubscriptionBag();
|
|
30
35
|
this.handleMoving = null;
|
|
@@ -34,7 +39,7 @@ class FeatureTool {
|
|
|
34
39
|
this.onToolActivated = (event) => {
|
|
35
40
|
this.isToolActive = event.id === this.id;
|
|
36
41
|
if (!this.isToolActive) {
|
|
37
|
-
this.
|
|
42
|
+
this.suspendFeatureSession();
|
|
38
43
|
}
|
|
39
44
|
this.updateVisibility();
|
|
40
45
|
};
|
|
@@ -51,16 +56,35 @@ class FeatureTool {
|
|
|
51
56
|
return;
|
|
52
57
|
}
|
|
53
58
|
this.renderProducerDisposable?.dispose();
|
|
54
|
-
this.renderProducerDisposable = this.canvasService.registerRenderProducer(this.id, () =>
|
|
55
|
-
passes
|
|
59
|
+
this.renderProducerDisposable = this.canvasService.registerRenderProducer(this.id, () => {
|
|
60
|
+
const passes = [
|
|
56
61
|
{
|
|
57
62
|
id: layers_1.FEATURE_OVERLAY_LAYER_ID,
|
|
58
63
|
stack: 880,
|
|
59
64
|
order: 0,
|
|
60
|
-
|
|
65
|
+
replace: true,
|
|
66
|
+
objects: this.markerSpecs,
|
|
61
67
|
},
|
|
62
|
-
]
|
|
63
|
-
|
|
68
|
+
];
|
|
69
|
+
if (this.isSessionVisible()) {
|
|
70
|
+
passes.push({
|
|
71
|
+
id: layers_1.DIELINE_LAYER_ID,
|
|
72
|
+
stack: 700,
|
|
73
|
+
order: 0,
|
|
74
|
+
replace: false,
|
|
75
|
+
visibility: { op: "const", value: false },
|
|
76
|
+
objects: [],
|
|
77
|
+
}, {
|
|
78
|
+
id: layers_1.FEATURE_DIELINE_LAYER_ID,
|
|
79
|
+
stack: 705,
|
|
80
|
+
order: 0,
|
|
81
|
+
replace: true,
|
|
82
|
+
effects: this.sessionDielineEffects,
|
|
83
|
+
objects: this.sessionDielineSpecs,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return { passes };
|
|
87
|
+
}, { priority: 350 });
|
|
64
88
|
const configService = context.services.get("ConfigurationService");
|
|
65
89
|
if (configService) {
|
|
66
90
|
const features = (configService.get("dieline.features", []) ||
|
|
@@ -71,13 +95,22 @@ class FeatureTool {
|
|
|
71
95
|
if (this.isUpdatingConfig)
|
|
72
96
|
return;
|
|
73
97
|
if (e.key === "dieline.features") {
|
|
74
|
-
if (this.isFeatureSessionActive)
|
|
98
|
+
if (this.isFeatureSessionActive && this.hasFeatureSessionDraft()) {
|
|
75
99
|
return;
|
|
100
|
+
}
|
|
101
|
+
if (this.hasFeatureSessionDraft()) {
|
|
102
|
+
this.clearFeatureSessionState();
|
|
103
|
+
}
|
|
76
104
|
const next = (e.value || []);
|
|
77
105
|
this.workingFeatures = this.cloneFeatures(next);
|
|
78
106
|
this.hasWorkingChanges = false;
|
|
79
107
|
this.redraw();
|
|
80
108
|
this.emitWorkingChange();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (e.key.startsWith("size.") || e.key.startsWith("dieline.")) {
|
|
112
|
+
void this.refreshGeometry();
|
|
113
|
+
this.redraw({ enforceConstraints: true });
|
|
81
114
|
}
|
|
82
115
|
});
|
|
83
116
|
}
|
|
@@ -88,7 +121,8 @@ class FeatureTool {
|
|
|
88
121
|
}
|
|
89
122
|
deactivate(context) {
|
|
90
123
|
this.subscriptions.disposeAll();
|
|
91
|
-
this.
|
|
124
|
+
this.restoreCommittedFeaturesToConfig();
|
|
125
|
+
this.clearFeatureSessionState();
|
|
92
126
|
this.dirtyTrackerDisposable?.dispose();
|
|
93
127
|
this.dirtyTrackerDisposable = undefined;
|
|
94
128
|
this.teardown();
|
|
@@ -98,6 +132,9 @@ class FeatureTool {
|
|
|
98
132
|
updateVisibility() {
|
|
99
133
|
this.redraw();
|
|
100
134
|
}
|
|
135
|
+
isSessionVisible() {
|
|
136
|
+
return this.isToolActive && this.isFeatureSessionActive;
|
|
137
|
+
}
|
|
101
138
|
contribute() {
|
|
102
139
|
return {
|
|
103
140
|
[core_1.ContributionPointIds.TOOLS]: [
|
|
@@ -124,15 +161,16 @@ class FeatureTool {
|
|
|
124
161
|
if (this.isFeatureSessionActive) {
|
|
125
162
|
return { ok: true };
|
|
126
163
|
}
|
|
127
|
-
|
|
128
|
-
|
|
164
|
+
if (!this.hasFeatureSessionDraft()) {
|
|
165
|
+
const original = this.getCommittedFeatures();
|
|
166
|
+
this.sessionOriginalFeatures = this.cloneFeatures(original);
|
|
167
|
+
this.setWorkingFeatures(this.cloneFeatures(original));
|
|
168
|
+
this.hasWorkingChanges = false;
|
|
169
|
+
}
|
|
129
170
|
this.isFeatureSessionActive = true;
|
|
130
171
|
await this.refreshGeometry();
|
|
131
|
-
this.setWorkingFeatures(this.cloneFeatures(original));
|
|
132
|
-
this.hasWorkingChanges = false;
|
|
133
172
|
this.redraw();
|
|
134
173
|
this.emitWorkingChange();
|
|
135
|
-
this.updateCommittedFeatures([]);
|
|
136
174
|
return { ok: true };
|
|
137
175
|
},
|
|
138
176
|
},
|
|
@@ -168,25 +206,6 @@ class FeatureTool {
|
|
|
168
206
|
return true;
|
|
169
207
|
},
|
|
170
208
|
},
|
|
171
|
-
{
|
|
172
|
-
command: "getWorkingFeatures",
|
|
173
|
-
title: "Get Working Features",
|
|
174
|
-
handler: () => {
|
|
175
|
-
return this.cloneFeatures(this.workingFeatures);
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
command: "setWorkingFeatures",
|
|
180
|
-
title: "Set Working Features",
|
|
181
|
-
handler: async (features) => {
|
|
182
|
-
await this.refreshGeometry();
|
|
183
|
-
this.setWorkingFeatures(this.cloneFeatures(features || []));
|
|
184
|
-
this.hasWorkingChanges = true;
|
|
185
|
-
this.redraw();
|
|
186
|
-
this.emitWorkingChange();
|
|
187
|
-
return { ok: true };
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
209
|
{
|
|
191
210
|
command: "rollbackFeatureSession",
|
|
192
211
|
title: "Rollback Feature Session",
|
|
@@ -251,16 +270,24 @@ class FeatureTool {
|
|
|
251
270
|
this.isUpdatingConfig = false;
|
|
252
271
|
}
|
|
253
272
|
}
|
|
273
|
+
hasFeatureSessionDraft() {
|
|
274
|
+
return Array.isArray(this.sessionOriginalFeatures);
|
|
275
|
+
}
|
|
254
276
|
clearFeatureSessionState() {
|
|
255
277
|
this.isFeatureSessionActive = false;
|
|
256
278
|
this.sessionOriginalFeatures = null;
|
|
257
279
|
}
|
|
258
|
-
|
|
259
|
-
if (!this.
|
|
280
|
+
restoreCommittedFeaturesToConfig() {
|
|
281
|
+
if (!this.hasFeatureSessionDraft())
|
|
260
282
|
return;
|
|
261
283
|
const original = this.cloneFeatures(this.sessionOriginalFeatures || this.getCommittedFeatures());
|
|
262
284
|
this.updateCommittedFeatures(original);
|
|
263
|
-
|
|
285
|
+
}
|
|
286
|
+
suspendFeatureSession() {
|
|
287
|
+
if (!this.isFeatureSessionActive)
|
|
288
|
+
return;
|
|
289
|
+
this.restoreCommittedFeaturesToConfig();
|
|
290
|
+
this.isFeatureSessionActive = false;
|
|
264
291
|
}
|
|
265
292
|
emitWorkingChange() {
|
|
266
293
|
this.context?.eventBus.emit("feature:working:change", {
|
|
@@ -281,9 +308,7 @@ class FeatureTool {
|
|
|
281
308
|
catch (e) { }
|
|
282
309
|
}
|
|
283
310
|
async resetWorkingFeaturesFromSource() {
|
|
284
|
-
const next = this.cloneFeatures(this.
|
|
285
|
-
? this.sessionOriginalFeatures
|
|
286
|
-
: this.getCommittedFeatures());
|
|
311
|
+
const next = this.cloneFeatures(this.sessionOriginalFeatures || this.getCommittedFeatures());
|
|
287
312
|
await this.refreshGeometry();
|
|
288
313
|
this.setWorkingFeatures(next);
|
|
289
314
|
this.hasWorkingChanges = false;
|
|
@@ -493,11 +518,35 @@ class FeatureTool {
|
|
|
493
518
|
this.handleSceneGeometryChange = null;
|
|
494
519
|
}
|
|
495
520
|
this.renderSeq += 1;
|
|
496
|
-
this.
|
|
521
|
+
this.markerSpecs = [];
|
|
522
|
+
this.sessionDielineSpecs = [];
|
|
523
|
+
this.sessionDielineEffects = [];
|
|
497
524
|
this.renderProducerDisposable?.dispose();
|
|
498
525
|
this.renderProducerDisposable = undefined;
|
|
499
526
|
void this.canvasService.flushRenderFromProducers();
|
|
500
527
|
}
|
|
528
|
+
createHatchPattern(color = "rgba(0, 0, 0, 0.3)") {
|
|
529
|
+
if (typeof document === "undefined") {
|
|
530
|
+
return undefined;
|
|
531
|
+
}
|
|
532
|
+
const size = 20;
|
|
533
|
+
const canvas = document.createElement("canvas");
|
|
534
|
+
canvas.width = size;
|
|
535
|
+
canvas.height = size;
|
|
536
|
+
const ctx = canvas.getContext("2d");
|
|
537
|
+
if (ctx) {
|
|
538
|
+
ctx.clearRect(0, 0, size, size);
|
|
539
|
+
ctx.strokeStyle = color;
|
|
540
|
+
ctx.lineWidth = 1;
|
|
541
|
+
ctx.beginPath();
|
|
542
|
+
ctx.moveTo(0, size);
|
|
543
|
+
ctx.lineTo(size, 0);
|
|
544
|
+
ctx.stroke();
|
|
545
|
+
}
|
|
546
|
+
return new fabric_1.Pattern({
|
|
547
|
+
source: canvas,
|
|
548
|
+
});
|
|
549
|
+
}
|
|
501
550
|
getDraggableMarkerTarget(target) {
|
|
502
551
|
if (!this.isFeatureSessionActive || !this.isToolActive)
|
|
503
552
|
return null;
|
|
@@ -567,6 +616,7 @@ class FeatureTool {
|
|
|
567
616
|
next[index] = updatedFeature;
|
|
568
617
|
this.setWorkingFeatures(next);
|
|
569
618
|
this.hasWorkingChanges = true;
|
|
619
|
+
this.redraw();
|
|
570
620
|
this.emitWorkingChange();
|
|
571
621
|
}
|
|
572
622
|
syncGroupFromCanvas(target) {
|
|
@@ -605,6 +655,7 @@ class FeatureTool {
|
|
|
605
655
|
return;
|
|
606
656
|
this.setWorkingFeatures(next);
|
|
607
657
|
this.hasWorkingChanges = true;
|
|
658
|
+
this.redraw();
|
|
608
659
|
this.emitWorkingChange();
|
|
609
660
|
}
|
|
610
661
|
redraw(options = {}) {
|
|
@@ -614,7 +665,10 @@ class FeatureTool {
|
|
|
614
665
|
if (!this.canvasService)
|
|
615
666
|
return;
|
|
616
667
|
const seq = ++this.renderSeq;
|
|
617
|
-
this.
|
|
668
|
+
this.markerSpecs = this.buildMarkerSpecs();
|
|
669
|
+
const sessionRender = this.buildSessionDielineRender();
|
|
670
|
+
this.sessionDielineSpecs = sessionRender.specs;
|
|
671
|
+
this.sessionDielineEffects = sessionRender.effects;
|
|
618
672
|
if (seq !== this.renderSeq)
|
|
619
673
|
return;
|
|
620
674
|
await this.canvasService.flushRenderFromProducers();
|
|
@@ -624,7 +678,47 @@ class FeatureTool {
|
|
|
624
678
|
this.enforceConstraints();
|
|
625
679
|
}
|
|
626
680
|
}
|
|
627
|
-
|
|
681
|
+
buildSessionDielineRender() {
|
|
682
|
+
if (!this.isSessionVisible() || !this.canvasService) {
|
|
683
|
+
return { specs: [], effects: [] };
|
|
684
|
+
}
|
|
685
|
+
const configService = this.getConfigService();
|
|
686
|
+
if (!configService) {
|
|
687
|
+
return { specs: [], effects: [] };
|
|
688
|
+
}
|
|
689
|
+
const sceneLayout = (0, sceneLayoutModel_1.computeSceneLayout)(this.canvasService, (0, sceneLayoutModel_1.readSizeState)(configService));
|
|
690
|
+
if (!sceneLayout) {
|
|
691
|
+
return { specs: [], effects: [] };
|
|
692
|
+
}
|
|
693
|
+
const state = (0, model_1.readDielineState)(configService);
|
|
694
|
+
state.features = this.cloneFeatures(this.workingFeatures);
|
|
695
|
+
return (0, renderBuilder_1.buildDielineRenderBundle)({
|
|
696
|
+
state,
|
|
697
|
+
sceneLayout,
|
|
698
|
+
canvasWidth: sceneLayout.canvasWidth || this.canvasService.canvas.width || 800,
|
|
699
|
+
canvasHeight: sceneLayout.canvasHeight || this.canvasService.canvas.height || 600,
|
|
700
|
+
hasImages: this.hasImageItems(),
|
|
701
|
+
createHatchPattern: (color) => this.createHatchPattern(color),
|
|
702
|
+
clipTargetPassIds: [layers_1.IMAGE_OBJECT_LAYER_ID],
|
|
703
|
+
clipVisibility: { op: "const", value: true },
|
|
704
|
+
ids: {
|
|
705
|
+
inside: "feature.session.dieline.inside",
|
|
706
|
+
bleedZone: "feature.session.dieline.bleed-zone",
|
|
707
|
+
offsetBorder: "feature.session.dieline.offset-border",
|
|
708
|
+
border: "feature.session.dieline.border",
|
|
709
|
+
clip: "feature.session.dieline.clip.image",
|
|
710
|
+
clipSource: "feature.session.dieline.effect.clip-path",
|
|
711
|
+
},
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
hasImageItems() {
|
|
715
|
+
const configService = this.getConfigService();
|
|
716
|
+
if (!configService)
|
|
717
|
+
return false;
|
|
718
|
+
const items = configService.get("image.items", []);
|
|
719
|
+
return Array.isArray(items) && items.length > 0;
|
|
720
|
+
}
|
|
721
|
+
buildMarkerSpecs() {
|
|
628
722
|
if (!this.isFeatureSessionActive ||
|
|
629
723
|
!this.currentGeometry ||
|
|
630
724
|
this.workingFeatures.length === 0) {
|
|
@@ -632,9 +726,26 @@ class FeatureTool {
|
|
|
632
726
|
}
|
|
633
727
|
const groups = new Map();
|
|
634
728
|
const singles = [];
|
|
635
|
-
this.workingFeatures
|
|
729
|
+
const placements = (0, featurePlacement_1.resolveFeaturePlacements)(this.workingFeatures, {
|
|
730
|
+
shape: this.currentGeometry.shape,
|
|
731
|
+
shapeStyle: this.currentGeometry.shapeStyle,
|
|
732
|
+
pathData: this.currentGeometry.pathData,
|
|
733
|
+
customSourceWidthPx: this.currentGeometry.customSourceWidthPx,
|
|
734
|
+
customSourceHeightPx: this.currentGeometry.customSourceHeightPx,
|
|
735
|
+
x: this.currentGeometry.x,
|
|
736
|
+
y: this.currentGeometry.y,
|
|
737
|
+
width: this.currentGeometry.width,
|
|
738
|
+
height: this.currentGeometry.height,
|
|
739
|
+
radius: this.currentGeometry.radius,
|
|
740
|
+
scale: this.currentGeometry.scale || 1,
|
|
741
|
+
});
|
|
742
|
+
placements.forEach((placement, index) => {
|
|
743
|
+
const feature = placement.feature;
|
|
636
744
|
const geometry = this.getGeometryForFeature(this.currentGeometry, feature);
|
|
637
|
-
const position =
|
|
745
|
+
const position = {
|
|
746
|
+
x: placement.centerX,
|
|
747
|
+
y: placement.centerY,
|
|
748
|
+
};
|
|
638
749
|
const scale = geometry.scale || 1;
|
|
639
750
|
const marker = {
|
|
640
751
|
feature,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveFeaturePosition = resolveFeaturePosition;
|
|
4
|
+
exports.normalizePointInGeometry = normalizePointInGeometry;
|
|
5
|
+
function resolveFeaturePosition(feature, geometry) {
|
|
6
|
+
const { x, y, width, height } = geometry;
|
|
7
|
+
const left = x - width / 2;
|
|
8
|
+
const top = y - height / 2;
|
|
9
|
+
return {
|
|
10
|
+
x: left + feature.x * width,
|
|
11
|
+
y: top + feature.y * height,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function normalizePointInGeometry(point, geometry) {
|
|
15
|
+
const left = geometry.x - geometry.width / 2;
|
|
16
|
+
const top = geometry.y - geometry.height / 2;
|
|
17
|
+
return {
|
|
18
|
+
x: geometry.width > 0 ? (point.x - left) / geometry.width : 0.5,
|
|
19
|
+
y: geometry.height > 0 ? (point.y - top) / geometry.height : 0.5,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveFeaturePlacements = resolveFeaturePlacements;
|
|
4
|
+
exports.projectPlacedFeatures = projectPlacedFeatures;
|
|
5
|
+
const constraints_1 = require("./constraints");
|
|
6
|
+
const featureCoordinates_1 = require("./featureCoordinates");
|
|
7
|
+
function scaleFeatureForRender(feature, scale, x, y) {
|
|
8
|
+
return {
|
|
9
|
+
...feature,
|
|
10
|
+
x,
|
|
11
|
+
y,
|
|
12
|
+
width: feature.width !== undefined ? feature.width * scale : undefined,
|
|
13
|
+
height: feature.height !== undefined ? feature.height * scale : undefined,
|
|
14
|
+
radius: feature.radius !== undefined ? feature.radius * scale : undefined,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function resolveFeaturePlacements(features, geometry) {
|
|
18
|
+
const dielineWidth = geometry.scale > 0 ? geometry.width / geometry.scale : geometry.width;
|
|
19
|
+
const dielineHeight = geometry.scale > 0 ? geometry.height / geometry.scale : geometry.height;
|
|
20
|
+
return (features || []).map((feature) => {
|
|
21
|
+
const activeConstraints = feature.constraints?.filter((constraint) => !constraint.validateOnly);
|
|
22
|
+
const constrained = constraints_1.ConstraintRegistry.apply(feature.x, feature.y, feature, {
|
|
23
|
+
dielineWidth,
|
|
24
|
+
dielineHeight,
|
|
25
|
+
geometry,
|
|
26
|
+
}, activeConstraints);
|
|
27
|
+
const center = (0, featureCoordinates_1.resolveFeaturePosition)({
|
|
28
|
+
...feature,
|
|
29
|
+
x: constrained.x,
|
|
30
|
+
y: constrained.y,
|
|
31
|
+
}, geometry);
|
|
32
|
+
return {
|
|
33
|
+
feature,
|
|
34
|
+
normalizedX: constrained.x,
|
|
35
|
+
normalizedY: constrained.y,
|
|
36
|
+
centerX: center.x,
|
|
37
|
+
centerY: center.y,
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function projectPlacedFeatures(placements, geometry, scale) {
|
|
42
|
+
return placements.map((placement) => {
|
|
43
|
+
const normalized = (0, featureCoordinates_1.normalizePointInGeometry)({ x: placement.centerX, y: placement.centerY }, geometry);
|
|
44
|
+
return scaleFeatureForRender(placement.feature, scale, normalized.x, normalized.y);
|
|
45
|
+
});
|
|
46
|
+
}
|