copper3d 3.4.6 → 3.4.8
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/dist/Utils/segmentation/DrawToolCore.d.ts +19 -2
- package/dist/Utils/segmentation/DrawToolCore.js +58 -13
- package/dist/Utils/segmentation/DrawToolCore.js.map +1 -1
- package/dist/Utils/segmentation/NrrdTools.d.ts +0 -1
- package/dist/Utils/segmentation/NrrdTools.js +8 -7
- package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
- package/dist/Utils/segmentation/core/types.d.ts +0 -1
- package/dist/Utils/segmentation/core/types.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/gui.d.ts +0 -1
- package/dist/Utils/segmentation/coreTools/gui.js +21 -29
- package/dist/Utils/segmentation/coreTools/gui.js.map +1 -1
- package/dist/Utils/segmentation/tools/DrawingTool.d.ts +9 -2
- package/dist/Utils/segmentation/tools/DrawingTool.js +28 -19
- package/dist/Utils/segmentation/tools/DrawingTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/ToolHost.d.ts +2 -3
- package/dist/Utils/utils.d.ts +0 -1
- package/dist/Utils/utils.js +0 -80
- package/dist/Utils/utils.js.map +1 -1
- package/dist/bundle.esm.js +115 -147
- package/dist/bundle.umd.js +115 -147
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/types/Utils/segmentation/DrawToolCore.d.ts +19 -2
- package/dist/types/Utils/segmentation/NrrdTools.d.ts +0 -1
- package/dist/types/Utils/segmentation/core/types.d.ts +0 -1
- package/dist/types/Utils/segmentation/coreTools/gui.d.ts +0 -1
- package/dist/types/Utils/segmentation/tools/DrawingTool.d.ts +9 -2
- package/dist/types/Utils/segmentation/tools/ToolHost.d.ts +2 -3
- package/dist/types/Utils/utils.d.ts +0 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/bundle.umd.js
CHANGED
|
@@ -40614,86 +40614,6 @@ void main() {
|
|
|
40614
40614
|
}
|
|
40615
40615
|
return url;
|
|
40616
40616
|
}
|
|
40617
|
-
function switchEraserSize(size, urls) {
|
|
40618
|
-
let url = "";
|
|
40619
|
-
if (!!urls && urls.length > 0) {
|
|
40620
|
-
if (size <= 3) {
|
|
40621
|
-
url = `url(${urls[0]}) 3 3, crosshair`;
|
|
40622
|
-
}
|
|
40623
|
-
else if (3 < size && size <= 8) {
|
|
40624
|
-
url = `url(${urls[1]}) 8 8, crosshair`;
|
|
40625
|
-
}
|
|
40626
|
-
else if (8 < size && size <= 13) {
|
|
40627
|
-
url = `url(${urls[2]}) 13 13, crosshair`;
|
|
40628
|
-
}
|
|
40629
|
-
else if (13 < size && size <= 18) {
|
|
40630
|
-
url = `url(${urls[3]}) 18 18, crosshair`;
|
|
40631
|
-
}
|
|
40632
|
-
else if (18 < size && size <= 23) {
|
|
40633
|
-
url = `url(${urls[4]}) 23 23, crosshair`;
|
|
40634
|
-
}
|
|
40635
|
-
else if (23 < size && size <= 28) {
|
|
40636
|
-
url = `url(${urls[5]}) 28 28, crosshair`;
|
|
40637
|
-
}
|
|
40638
|
-
else if (28 < size && size <= 33) {
|
|
40639
|
-
url = `url(${urls[6]}) 33 33, crosshair`;
|
|
40640
|
-
}
|
|
40641
|
-
else if (33 < size && size <= 38) {
|
|
40642
|
-
url = `url(${urls[7]}) 38 38, crosshair`;
|
|
40643
|
-
}
|
|
40644
|
-
else if (38 < size && size <= 43) {
|
|
40645
|
-
url = `url(${urls[8]}) 43 43, crosshair`;
|
|
40646
|
-
}
|
|
40647
|
-
else if (43 < size && size <= 48) {
|
|
40648
|
-
url = `url(${urls[9]}) 48 48, crosshair`;
|
|
40649
|
-
}
|
|
40650
|
-
else if (48 < size && size <= 53) {
|
|
40651
|
-
url = `url(${urls[10]}) 52 52, crosshair`;
|
|
40652
|
-
}
|
|
40653
|
-
else {
|
|
40654
|
-
url = `url(${urls[11]}) 52 52, crosshair`;
|
|
40655
|
-
}
|
|
40656
|
-
}
|
|
40657
|
-
else {
|
|
40658
|
-
if (size <= 3) {
|
|
40659
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_3.png) 3 3, crosshair`;
|
|
40660
|
-
}
|
|
40661
|
-
else if (3 < size && size <= 8) {
|
|
40662
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_8.png) 8 8, crosshair`;
|
|
40663
|
-
}
|
|
40664
|
-
else if (8 < size && size <= 13) {
|
|
40665
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_13.png) 13 13, crosshair`;
|
|
40666
|
-
}
|
|
40667
|
-
else if (13 < size && size <= 18) {
|
|
40668
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_18.png) 18 18, crosshair`;
|
|
40669
|
-
}
|
|
40670
|
-
else if (18 < size && size <= 23) {
|
|
40671
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_23.png) 23 23, crosshair`;
|
|
40672
|
-
}
|
|
40673
|
-
else if (23 < size && size <= 28) {
|
|
40674
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_28.png) 28 28, crosshair`;
|
|
40675
|
-
}
|
|
40676
|
-
else if (28 < size && size <= 33) {
|
|
40677
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_33.png) 33 33, crosshair`;
|
|
40678
|
-
}
|
|
40679
|
-
else if (33 < size && size <= 38) {
|
|
40680
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_38.png) 38 38, crosshair`;
|
|
40681
|
-
}
|
|
40682
|
-
else if (38 < size && size <= 43) {
|
|
40683
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_43.png) 43 43, crosshair`;
|
|
40684
|
-
}
|
|
40685
|
-
else if (43 < size && size <= 48) {
|
|
40686
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_48.png) 48 48, crosshair`;
|
|
40687
|
-
}
|
|
40688
|
-
else if (48 < size && size <= 53) {
|
|
40689
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_52.png) 52 52, crosshair`;
|
|
40690
|
-
}
|
|
40691
|
-
else {
|
|
40692
|
-
url = `url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_52.png) 52 52, crosshair`;
|
|
40693
|
-
}
|
|
40694
|
-
}
|
|
40695
|
-
return url;
|
|
40696
|
-
}
|
|
40697
40617
|
function throttle(callback, wait) {
|
|
40698
40618
|
let start = 0;
|
|
40699
40619
|
return function (event) {
|
|
@@ -73010,10 +72930,7 @@ void main() {
|
|
|
73010
72930
|
.name("BrushAndEraserSize")
|
|
73011
72931
|
.min(5)
|
|
73012
72932
|
.max(50)
|
|
73013
|
-
.step(1)
|
|
73014
|
-
.onChange(() => {
|
|
73015
|
-
updateGuiBrushAndEraserSize();
|
|
73016
|
-
});
|
|
72933
|
+
.step(1);
|
|
73017
72934
|
actionsFolder.add(configs.gui_states.mode, "eraser").onChange((value) => {
|
|
73018
72935
|
updateGuiEraserState();
|
|
73019
72936
|
});
|
|
@@ -73141,37 +73058,33 @@ void main() {
|
|
|
73141
73058
|
configs.gui_states.viewConfig.readyToUpdate = true;
|
|
73142
73059
|
});
|
|
73143
73060
|
actionsFolder.open();
|
|
73144
|
-
|
|
73145
|
-
|
|
73146
|
-
|
|
73147
|
-
|
|
73148
|
-
|
|
73149
|
-
|
|
73150
|
-
|
|
73151
|
-
const updatePencilState = () => {
|
|
73152
|
-
if (configs.gui_states.mode.pencil) {
|
|
73153
|
-
// add canvas brush circle move event listeners
|
|
73154
|
-
configs.drawingCanvas.removeEventListener("mouseover", configs.drawingPrameters.handleOnDrawingBrushCricleMove);
|
|
73155
|
-
configs.drawingCanvas.removeEventListener("mouseout", configs.drawingPrameters.handleOnDrawingBrushCricleMove);
|
|
73061
|
+
// Add/remove the hover-tracking listeners that feed the brush/eraser preview
|
|
73062
|
+
// ring (mouseOver position). Present for brush & eraser, removed for pencil.
|
|
73063
|
+
const setBrushHoverTracking = (enabled) => {
|
|
73064
|
+
const handler = configs.drawingPrameters.handleOnDrawingBrushCricleMove;
|
|
73065
|
+
if (enabled) {
|
|
73066
|
+
configs.drawingCanvas.addEventListener("mouseover", handler);
|
|
73067
|
+
configs.drawingCanvas.addEventListener("mouseout", handler);
|
|
73156
73068
|
}
|
|
73157
73069
|
else {
|
|
73158
|
-
|
|
73159
|
-
configs.drawingCanvas.
|
|
73160
|
-
configs.drawingCanvas.addEventListener("mouseout", configs.drawingPrameters.handleOnDrawingBrushCricleMove);
|
|
73070
|
+
configs.drawingCanvas.removeEventListener("mouseover", handler);
|
|
73071
|
+
configs.drawingCanvas.removeEventListener("mouseout", handler);
|
|
73161
73072
|
}
|
|
73073
|
+
};
|
|
73074
|
+
const updatePencilState = () => {
|
|
73075
|
+
// Pencil has no preview ring; brush keeps the hover-tracking listeners.
|
|
73076
|
+
setBrushHoverTracking(!configs.gui_states.mode.pencil);
|
|
73162
73077
|
configs.drawingCanvas.style.cursor = configs.gui_states.viewConfig.defaultPaintCursor;
|
|
73163
73078
|
};
|
|
73164
73079
|
const updateGuiEraserState = () => {
|
|
73165
|
-
//
|
|
73080
|
+
// The eraser shows a dashed preview ring (rendered in DrawToolCore.start),
|
|
73081
|
+
// so it needs the same hover-tracking as the brush. The canvas keeps the
|
|
73082
|
+
// default paint cursor; the ring conveys size (resize via Shift+wheel).
|
|
73166
73083
|
if (configs.gui_states.mode.eraser) {
|
|
73167
|
-
|
|
73168
|
-
? (configs.drawingCanvas.style.cursor = switchEraserSize(configs.gui_states.drawing.brushAndEraserSize, configs.eraserUrls))
|
|
73169
|
-
: (configs.drawingCanvas.style.cursor = switchEraserSize(configs.gui_states.drawing.brushAndEraserSize));
|
|
73170
|
-
}
|
|
73171
|
-
else {
|
|
73172
|
-
configs.drawingCanvas.style.cursor =
|
|
73173
|
-
configs.gui_states.viewConfig.defaultPaintCursor;
|
|
73084
|
+
setBrushHoverTracking(true);
|
|
73174
73085
|
}
|
|
73086
|
+
configs.drawingCanvas.style.cursor =
|
|
73087
|
+
configs.gui_states.viewConfig.defaultPaintCursor;
|
|
73175
73088
|
};
|
|
73176
73089
|
const updateGuiSphereState = () => {
|
|
73177
73090
|
var _a, _b, _c, _d;
|
|
@@ -73227,7 +73140,6 @@ void main() {
|
|
|
73227
73140
|
min: 5,
|
|
73228
73141
|
max: 50,
|
|
73229
73142
|
step: 1,
|
|
73230
|
-
onChange: updateGuiBrushAndEraserSize,
|
|
73231
73143
|
},
|
|
73232
73144
|
eraser: {
|
|
73233
73145
|
name: "Eraser",
|
|
@@ -74956,18 +74868,11 @@ void main() {
|
|
|
74956
74868
|
this.drawingLines = [];
|
|
74957
74869
|
this.isPainting = true;
|
|
74958
74870
|
this.ctx.protectedData.isDrawing = true;
|
|
74959
|
-
//
|
|
74960
|
-
|
|
74961
|
-
|
|
74962
|
-
|
|
74963
|
-
|
|
74964
|
-
? switchEraserSize(this.ctx.gui_states.drawing.brushAndEraserSize, urls)
|
|
74965
|
-
: switchEraserSize(this.ctx.gui_states.drawing.brushAndEraserSize);
|
|
74966
|
-
}
|
|
74967
|
-
else {
|
|
74968
|
-
this.ctx.protectedData.canvases.drawingCanvas.style.cursor =
|
|
74969
|
-
this.ctx.gui_states.viewConfig.defaultPaintCursor;
|
|
74970
|
-
}
|
|
74871
|
+
// Brush and eraser both show their size via the dashed/solid preview ring
|
|
74872
|
+
// rendered in DrawToolCore.start(); the canvas keeps the default paint
|
|
74873
|
+
// cursor underneath. (The eraser previously swapped in a sized PNG cursor.)
|
|
74874
|
+
this.ctx.protectedData.canvases.drawingCanvas.style.cursor =
|
|
74875
|
+
this.ctx.gui_states.viewConfig.defaultPaintCursor;
|
|
74971
74876
|
// Record draw start position
|
|
74972
74877
|
this.ctx.nrrd_states.interaction.drawStartPos.x = e.offsetX;
|
|
74973
74878
|
this.ctx.nrrd_states.interaction.drawStartPos.y = e.offsetY;
|
|
@@ -75105,20 +75010,37 @@ void main() {
|
|
|
75105
75010
|
return handler;
|
|
75106
75011
|
}
|
|
75107
75012
|
/**
|
|
75108
|
-
* Render brush
|
|
75013
|
+
* Render the size-preview ring for the brush / eraser on the drawing context.
|
|
75014
|
+
*
|
|
75015
|
+
* - Brush: solid outline in the current brush colour.
|
|
75016
|
+
* - Eraser: red dashed outline (matches the sphereEraser preview), so the
|
|
75017
|
+
* eraser no longer needs a sized PNG cursor — the ring tracks the live
|
|
75018
|
+
* `brushAndEraserSize` and is what the user resizes with Shift+wheel.
|
|
75019
|
+
*
|
|
75020
|
+
* Only the pencil has no preview ring (its stroke width is fixed).
|
|
75109
75021
|
*/
|
|
75110
|
-
renderBrushPreview(ctx,
|
|
75022
|
+
renderBrushPreview(ctx, _width, _height) {
|
|
75111
75023
|
if (this.ctx.gui_states.mode.pencil ||
|
|
75112
|
-
this.ctx.gui_states.mode.eraser ||
|
|
75113
75024
|
!this.ctx.nrrd_states.interaction.mouseOver) {
|
|
75114
75025
|
return;
|
|
75115
75026
|
}
|
|
75116
|
-
|
|
75117
|
-
|
|
75027
|
+
const isEraser = this.ctx.gui_states.mode.eraser;
|
|
75028
|
+
// No clearRect here: DrawToolCore.start() clears drawingCtx once per frame
|
|
75029
|
+
// before compositing, and this ring is now drawn on top of the mask so it
|
|
75030
|
+
// stays visible during an active stroke (e.g. while Shift+wheel resizing).
|
|
75031
|
+
ctx.save();
|
|
75118
75032
|
ctx.beginPath();
|
|
75119
75033
|
ctx.arc(this.ctx.nrrd_states.interaction.mouseOverX, this.ctx.nrrd_states.interaction.mouseOverY, this.ctx.gui_states.drawing.brushAndEraserSize / 2 + 1, 0, Math.PI * 2);
|
|
75120
|
-
|
|
75034
|
+
if (isEraser) {
|
|
75035
|
+
ctx.strokeStyle = "#ff4444";
|
|
75036
|
+
ctx.lineWidth = 2;
|
|
75037
|
+
ctx.setLineDash([4, 4]);
|
|
75038
|
+
}
|
|
75039
|
+
else {
|
|
75040
|
+
ctx.strokeStyle = this.ctx.gui_states.drawing.brushColor;
|
|
75041
|
+
}
|
|
75121
75042
|
ctx.stroke();
|
|
75043
|
+
ctx.restore();
|
|
75122
75044
|
}
|
|
75123
75045
|
// ── Brush mode: direct voxel write ────────────────────────────
|
|
75124
75046
|
/**
|
|
@@ -76259,7 +76181,6 @@ void main() {
|
|
|
76259
76181
|
handleOnContrastMouseUp: (ev) => { },
|
|
76260
76182
|
handleOnContrastMouseLeave: (ev) => { },
|
|
76261
76183
|
};
|
|
76262
|
-
this.eraserUrls = [];
|
|
76263
76184
|
this.pencilUrls = [];
|
|
76264
76185
|
this.undoManager = new UndoManager();
|
|
76265
76186
|
/** Slice index recorded when paintOnCanvas() starts, guards stale-click */
|
|
@@ -76334,7 +76255,6 @@ void main() {
|
|
|
76334
76255
|
filterDrawedImage: (axis, index) => this.renderer.filterDrawedImage(axis, index),
|
|
76335
76256
|
getVolumeForLayer: (layer) => this.renderer.getVolumeForLayer(layer),
|
|
76336
76257
|
pushUndoDelta: (delta) => this.undoManager.push(delta),
|
|
76337
|
-
getEraserUrls: () => this.eraserUrls,
|
|
76338
76258
|
renderSliceToCanvas: (layer, axis, sliceIndex, buffer, ctx, w, h) => this.renderer.renderSliceToCanvas(layer, axis, sliceIndex, buffer, ctx, w, h),
|
|
76339
76259
|
getOrCreateSliceBuffer: (axis) => this.renderer.getOrCreateSliceBuffer(axis),
|
|
76340
76260
|
});
|
|
@@ -76346,7 +76266,6 @@ void main() {
|
|
|
76346
76266
|
getOrCreateSliceBuffer: (axis) => this.renderer.getOrCreateSliceBuffer(axis),
|
|
76347
76267
|
setEmptyCanvasSize: (axis) => this.setEmptyCanvasSize(axis),
|
|
76348
76268
|
reloadMasksFromVolume: () => this.reloadMasksFromVolume(),
|
|
76349
|
-
getEraserUrls: () => this.eraserUrls,
|
|
76350
76269
|
});
|
|
76351
76270
|
}
|
|
76352
76271
|
initDrawToolCore() {
|
|
@@ -76501,6 +76420,12 @@ void main() {
|
|
|
76501
76420
|
});
|
|
76502
76421
|
// Register wheel handler with EventRouter
|
|
76503
76422
|
this.eventRouter.setWheelHandler((e) => {
|
|
76423
|
+
// Shift + wheel resizes the brush/eraser (like sphereBrush/sphereEraser
|
|
76424
|
+
// radius), independent of whether the left button is held. Consumes the
|
|
76425
|
+
// event so it never falls through to zoom/slice. Pencil is excluded even
|
|
76426
|
+
// though it also uses Shift — see tryBrushEraserResizeWheel.
|
|
76427
|
+
if (this.tryBrushEraserResizeWheel(e))
|
|
76428
|
+
return;
|
|
76504
76429
|
if (this.activeWheelMode === 'zoom') {
|
|
76505
76430
|
this.drawingPrameters.handleMouseZoomSliceWheel(e);
|
|
76506
76431
|
}
|
|
@@ -76514,8 +76439,47 @@ void main() {
|
|
|
76514
76439
|
// Bind all event listeners
|
|
76515
76440
|
this.eventRouter.bindAll();
|
|
76516
76441
|
}
|
|
76517
|
-
|
|
76518
|
-
|
|
76442
|
+
/**
|
|
76443
|
+
* Shift + mouse-wheel resize for the brush and eraser tools.
|
|
76444
|
+
*
|
|
76445
|
+
* Mirrors the sphereBrush/sphereEraser "scroll to change radius" UX so the
|
|
76446
|
+
* user no longer has to reach for the B&E Size slider mid-annotation. Active
|
|
76447
|
+
* whenever the EventRouter is in `draw` mode (i.e. Shift is held — with or
|
|
76448
|
+
* without the left button down) and the current tool is brush or eraser.
|
|
76449
|
+
*
|
|
76450
|
+
* Pencil is deliberately excluded: it also draws with Shift, but its stroke
|
|
76451
|
+
* width is fixed and unrelated to `brushAndEraserSize`. Sphere-family tools
|
|
76452
|
+
* keep their own wheel-radius handler (`activeWheelMode === 'sphereBrush'`).
|
|
76453
|
+
*
|
|
76454
|
+
* `gui_states.mode` is the source of truth for the active tool here, not
|
|
76455
|
+
* `eventRouter.getGuiTool()` — the latter is only updated for sphere tools.
|
|
76456
|
+
*
|
|
76457
|
+
* @returns true if the event was handled (and should not fall through to
|
|
76458
|
+
* the zoom/slice/sphere wheel handlers).
|
|
76459
|
+
*/
|
|
76460
|
+
tryBrushEraserResizeWheel(e) {
|
|
76461
|
+
// `draw` mode means Shift is held and neither crosshair nor contrast is
|
|
76462
|
+
// active (EventRouter only enters it for drawing tools under those rules),
|
|
76463
|
+
// so it doubles as the "Shift held, not blocked" gate.
|
|
76464
|
+
if (this.eventRouter.getMode() !== 'draw')
|
|
76465
|
+
return false;
|
|
76466
|
+
const mode = this.state.gui_states.mode;
|
|
76467
|
+
// Brush = no flag set; eraser = mode.eraser. Exclude pencil and all
|
|
76468
|
+
// sphere-family tools.
|
|
76469
|
+
if (mode.pencil || mode.sphere || mode.sphereBrush || mode.sphereEraser) {
|
|
76470
|
+
return false;
|
|
76471
|
+
}
|
|
76472
|
+
e.preventDefault();
|
|
76473
|
+
const drawing = this.state.gui_states.drawing;
|
|
76474
|
+
// Step/bounds match the B&E Size slider config (min 5, max 50, step 1).
|
|
76475
|
+
const next = Math.max(5, Math.min(50, drawing.brushAndEraserSize + (e.deltaY < 0 ? 1 : -1)));
|
|
76476
|
+
if (next === drawing.brushAndEraserSize)
|
|
76477
|
+
return true;
|
|
76478
|
+
drawing.brushAndEraserSize = next;
|
|
76479
|
+
// Both brush and eraser draw a size-preview ring in start() that reads
|
|
76480
|
+
// brushAndEraserSize live, so the new size shows up on the next frame with
|
|
76481
|
+
// no extra work here.
|
|
76482
|
+
return true;
|
|
76519
76483
|
}
|
|
76520
76484
|
setPencilIconUrls(urls) {
|
|
76521
76485
|
this.pencilUrls = urls;
|
|
@@ -76684,6 +76648,7 @@ void main() {
|
|
|
76684
76648
|
this.state.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.state.nrrd_states.view.changedWidth, this.state.nrrd_states.view.changedHeight);
|
|
76685
76649
|
this.state.protectedData.ctxes.drawingCtx.globalAlpha =
|
|
76686
76650
|
this.state.gui_states.drawing.globalAlpha;
|
|
76651
|
+
const currentMode = this.eventRouter.getMode();
|
|
76687
76652
|
if (this.state.protectedData.isDrawing) {
|
|
76688
76653
|
this.state.protectedData.ctxes.drawingLayerMasterCtx.lineCap = "round";
|
|
76689
76654
|
this.state.protectedData.ctxes.drawingLayerMasterCtx.globalAlpha = 1;
|
|
@@ -76692,16 +76657,18 @@ void main() {
|
|
|
76692
76657
|
target.ctx.globalAlpha = 1;
|
|
76693
76658
|
}
|
|
76694
76659
|
}
|
|
76695
|
-
else {
|
|
76696
|
-
|
|
76697
|
-
if (currentMode === 'draw') {
|
|
76698
|
-
this.drawingTool.renderBrushPreview(this.state.protectedData.ctxes.drawingCtx, this.state.nrrd_states.view.changedWidth, this.state.nrrd_states.view.changedHeight);
|
|
76699
|
-
}
|
|
76700
|
-
else if (currentMode === 'crosshair' || this.eventRouter.isCrosshairEnabled()) {
|
|
76701
|
-
this.crosshairTool.renderCrosshair(this.state.protectedData.ctxes.drawingCtx, this.state.nrrd_states.view.changedWidth, this.state.nrrd_states.view.changedHeight);
|
|
76702
|
-
}
|
|
76660
|
+
else if (currentMode === 'crosshair' || this.eventRouter.isCrosshairEnabled()) {
|
|
76661
|
+
this.crosshairTool.renderCrosshair(this.state.protectedData.ctxes.drawingCtx, this.state.nrrd_states.view.changedWidth, this.state.nrrd_states.view.changedHeight);
|
|
76703
76662
|
}
|
|
76704
76663
|
this.state.protectedData.ctxes.drawingCtx.drawImage(this.state.protectedData.canvases.drawingCanvasLayerMaster, 0, 0);
|
|
76664
|
+
// Brush/eraser size ring is drawn AFTER the mask composite so it stays
|
|
76665
|
+
// visible during an active stroke (not just on hover) — e.g. while the
|
|
76666
|
+
// user resizes with Shift+wheel mid-paint. Gated on draw mode so it only
|
|
76667
|
+
// shows for brush/eraser with Shift held (renderBrushPreview itself
|
|
76668
|
+
// skips pencil and the no-hover case).
|
|
76669
|
+
if (currentMode === 'draw') {
|
|
76670
|
+
this.drawingTool.renderBrushPreview(this.state.protectedData.ctxes.drawingCtx);
|
|
76671
|
+
}
|
|
76705
76672
|
if (this.state.gui_states.mode.sphere
|
|
76706
76673
|
|| this.state.gui_states.mode.sphereBrush
|
|
76707
76674
|
|| this.state.gui_states.mode.sphereEraser) {
|
|
@@ -78413,7 +78380,6 @@ void main() {
|
|
|
78413
78380
|
nrrd_states: this.state.nrrd_states,
|
|
78414
78381
|
drawingCanvas: this.state.protectedData.canvases.drawingCanvas,
|
|
78415
78382
|
drawingPrameters: this.drawCore.drawingPrameters,
|
|
78416
|
-
eraserUrls: this.drawCore.eraserUrls,
|
|
78417
78383
|
pencilUrls: this.drawCore.pencilUrls,
|
|
78418
78384
|
mainPreSlices: this.state.protectedData.mainPreSlices,
|
|
78419
78385
|
protectedData: this.state.protectedData,
|
|
@@ -78446,13 +78412,18 @@ void main() {
|
|
|
78446
78412
|
this.guiCallbacks = {
|
|
78447
78413
|
updatePencilState: this.guiParameterSettings.pencil.onChange,
|
|
78448
78414
|
updateEraserState: this.guiParameterSettings.eraser.onChange,
|
|
78449
|
-
updateBrushAndEraserSize: this.guiParameterSettings.brushAndEraserSize.onChange,
|
|
78450
78415
|
updateSphereState: this.guiParameterSettings.sphere.onChange,
|
|
78451
78416
|
updateCalDistance: this.guiParameterSettings.activeSphereType.onChange,
|
|
78452
78417
|
updateWindowHigh: this.guiParameterSettings.windowHigh.onChange,
|
|
78453
78418
|
updateWindowLow: this.guiParameterSettings.windowLow.onChange,
|
|
78454
78419
|
finishContrastAdjustment: this.guiParameterSettings.windowHigh.onFinished,
|
|
78455
78420
|
};
|
|
78421
|
+
// setupGUI may run AFTER images are loaded (e.g. the register/origin-switch load
|
|
78422
|
+
// path), in which case the on-load syncGuiParameterSettings() ran while
|
|
78423
|
+
// guiParameterSettings was still undefined and silently skipped the binding. Bind
|
|
78424
|
+
// now so the window slider reflects the current volume's real min/max/window instead
|
|
78425
|
+
// of the default 0/0 (which froze the slider and turned the image white on zoom).
|
|
78426
|
+
this.syncGuiParameterSettings();
|
|
78456
78427
|
}
|
|
78457
78428
|
/**
|
|
78458
78429
|
* Sync guiParameterSettings with current volume metadata.
|
|
@@ -78559,9 +78530,9 @@ void main() {
|
|
|
78559
78530
|
return this.state.gui_states.drawing.globalAlpha;
|
|
78560
78531
|
}
|
|
78561
78532
|
setBrushSize(size) {
|
|
78562
|
-
|
|
78533
|
+
// No cursor side-effect needed: the brush/eraser preview ring reads this
|
|
78534
|
+
// value live each frame (see DrawingTool.renderBrushPreview).
|
|
78563
78535
|
this.state.gui_states.drawing.brushAndEraserSize = Math.max(5, Math.min(50, size));
|
|
78564
|
-
(_a = this.guiCallbacks) === null || _a === void 0 ? void 0 : _a.updateBrushAndEraserSize();
|
|
78565
78536
|
}
|
|
78566
78537
|
getBrushSize() {
|
|
78567
78538
|
return this.state.gui_states.drawing.brushAndEraserSize;
|
|
@@ -78796,9 +78767,6 @@ void main() {
|
|
|
78796
78767
|
enableContrastDragEvents(callback) {
|
|
78797
78768
|
this.drawCore.setupConrastEvents(callback);
|
|
78798
78769
|
}
|
|
78799
|
-
setEraserUrls(urls) {
|
|
78800
|
-
this.drawCore.setEraserUrls(urls);
|
|
78801
|
-
}
|
|
78802
78770
|
setPencilIconUrls(urls) {
|
|
78803
78771
|
this.drawCore.setPencilIconUrls(urls);
|
|
78804
78772
|
}
|
|
@@ -79488,7 +79456,7 @@ void main() {
|
|
|
79488
79456
|
}
|
|
79489
79457
|
|
|
79490
79458
|
// import * as kiwrious from "copper3d_plugin_heart_k";
|
|
79491
|
-
const REVISION = "v3.4.
|
|
79459
|
+
const REVISION = "v3.4.8-beta";
|
|
79492
79460
|
console.log(`%cCopper3D Visualisation %cBeta:${REVISION}`, "padding: 3px;color:white; background:#023047", "padding: 3px;color:white; background:#f50a25");
|
|
79493
79461
|
|
|
79494
79462
|
exports.CHANNEL_COLORS = CHANNEL_COLORS;
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,6 @@ import type { ToolMode, IAnnotationCallbacks } from "./Utils/segmentation/core/t
|
|
|
25
25
|
import { CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "./Utils/segmentation/core/index";
|
|
26
26
|
import type { LayerId, ChannelValue } from "./Utils/segmentation/core/index";
|
|
27
27
|
import "./css/style.css";
|
|
28
|
-
export declare const REVISION = "v3.4.
|
|
28
|
+
export declare const REVISION = "v3.4.8-beta";
|
|
29
29
|
export { copperRenderer, copperRendererOnDemond, copperMSceneRenderer, setHDRFilePath, addLabelToScene, convert3DPostoScreenPos, convertScreenPosto3DPos, addBoxHelper, fullScreenListenner, configKiwriousHeart, copperScene, copperSceneOnDemond, copperMScene, CameraViewPoint, kiwrious, NrrdTools, loading, Copper3dTrackballControls, createTexture2D_NRRD, MeshNodeTool, throttle, removeGuiFolderChilden, CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss, GaussianSmoother, };
|
|
30
30
|
export type { positionType, screenPosType, optsType, nrrdMeshesType, nrrdSliceType, SensorDecodedValue_kiwrious, SensorReadResult_kiwrious, HeartRateResult_kiwrious, loadingBarType, IPaintImage, exportPaintImageType, IOptVTKLoader, ICommXYZ, IGUIStates, IGuiParameterSettings, INrrdStates, NrrdState, GuiState, IGuiMeta, ToolMode, IAnnotationCallbacks, LayerId, ChannelValue, };
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { MeshNodeTool } from "./Utils/MeshNodeTool";
|
|
|
21
21
|
import { removeGuiFolderChilden } from "./Utils/segmentation/coreTools/gui";
|
|
22
22
|
import { CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "./Utils/segmentation/core/index";
|
|
23
23
|
import "./css/style.css";
|
|
24
|
-
export const REVISION = "v3.4.
|
|
24
|
+
export const REVISION = "v3.4.8-beta";
|
|
25
25
|
console.log(`%cCopper3D Visualisation %cBeta:${REVISION}`, "padding: 3px;color:white; background:#023047", "padding: 3px;color:white; background:#f50a25");
|
|
26
26
|
export { copperRenderer, copperRendererOnDemond, copperMSceneRenderer, setHDRFilePath, addLabelToScene, convert3DPostoScreenPos, convertScreenPosto3DPos, addBoxHelper, fullScreenListenner, configKiwriousHeart, copperScene, copperSceneOnDemond, copperMScene, CameraViewPoint, kiwrious, NrrdTools, loading, Copper3dTrackballControls, createTexture2D_NRRD, MeshNodeTool, throttle, removeGuiFolderChilden, CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss, GaussianSmoother, };
|
|
27
27
|
//# sourceMappingURL=index.js.map
|
|
@@ -30,7 +30,6 @@ export declare class DrawToolCore {
|
|
|
30
30
|
readonly renderer: RenderingUtils;
|
|
31
31
|
drawingPrameters: IDrawingEvents;
|
|
32
32
|
contrastEventPrameters: IContrastEvents;
|
|
33
|
-
eraserUrls: string[];
|
|
34
33
|
pencilUrls: string[];
|
|
35
34
|
undoManager: UndoManager;
|
|
36
35
|
eventRouter: EventRouter;
|
|
@@ -59,7 +58,25 @@ export declare class DrawToolCore {
|
|
|
59
58
|
constructor(container: HTMLElement, state: CanvasState);
|
|
60
59
|
private initTools;
|
|
61
60
|
private initDrawToolCore;
|
|
62
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Shift + mouse-wheel resize for the brush and eraser tools.
|
|
63
|
+
*
|
|
64
|
+
* Mirrors the sphereBrush/sphereEraser "scroll to change radius" UX so the
|
|
65
|
+
* user no longer has to reach for the B&E Size slider mid-annotation. Active
|
|
66
|
+
* whenever the EventRouter is in `draw` mode (i.e. Shift is held — with or
|
|
67
|
+
* without the left button down) and the current tool is brush or eraser.
|
|
68
|
+
*
|
|
69
|
+
* Pencil is deliberately excluded: it also draws with Shift, but its stroke
|
|
70
|
+
* width is fixed and unrelated to `brushAndEraserSize`. Sphere-family tools
|
|
71
|
+
* keep their own wheel-radius handler (`activeWheelMode === 'sphereBrush'`).
|
|
72
|
+
*
|
|
73
|
+
* `gui_states.mode` is the source of truth for the active tool here, not
|
|
74
|
+
* `eventRouter.getGuiTool()` — the latter is only updated for sphere tools.
|
|
75
|
+
*
|
|
76
|
+
* @returns true if the event was handled (and should not fall through to
|
|
77
|
+
* the zoom/slice/sphere wheel handlers).
|
|
78
|
+
*/
|
|
79
|
+
private tryBrushEraserResizeWheel;
|
|
63
80
|
setPencilIconUrls(urls: string[]): void;
|
|
64
81
|
private setCurrentLayer;
|
|
65
82
|
draw(opts?: IDrawOpts): void;
|
|
@@ -110,7 +110,6 @@ export declare class NrrdTools {
|
|
|
110
110
|
setBaseDrawDisplayCanvasesSize(size: number): void;
|
|
111
111
|
setDisplaySliceIndexPanel(panel: HTMLDivElement): void;
|
|
112
112
|
enableContrastDragEvents(callback: (step: number, towards: "horizental" | "vertical") => void): void;
|
|
113
|
-
setEraserUrls(urls: string[]): void;
|
|
114
113
|
setPencilIconUrls(urls: string[]): void;
|
|
115
114
|
/**
|
|
116
115
|
* Switch all contrast slices' orientation
|
|
@@ -65,9 +65,16 @@ export declare class DrawingTool extends BaseTool {
|
|
|
65
65
|
*/
|
|
66
66
|
createBrushTrackingHandler(): (e: MouseEvent) => void;
|
|
67
67
|
/**
|
|
68
|
-
* Render brush
|
|
68
|
+
* Render the size-preview ring for the brush / eraser on the drawing context.
|
|
69
|
+
*
|
|
70
|
+
* - Brush: solid outline in the current brush colour.
|
|
71
|
+
* - Eraser: red dashed outline (matches the sphereEraser preview), so the
|
|
72
|
+
* eraser no longer needs a sized PNG cursor — the ring tracks the live
|
|
73
|
+
* `brushAndEraserSize` and is what the user resizes with Shift+wheel.
|
|
74
|
+
*
|
|
75
|
+
* Only the pencil has no preview ring (its stroke width is fixed).
|
|
69
76
|
*/
|
|
70
|
-
renderBrushPreview(ctx: CanvasRenderingContext2D,
|
|
77
|
+
renderBrushPreview(ctx: CanvasRenderingContext2D, _width?: number, _height?: number): void;
|
|
71
78
|
/**
|
|
72
79
|
* Convert display (zoomed) coordinates to 3D voxel coordinates.
|
|
73
80
|
* Same logic as SphereBrushTool.canvasToVoxelCenter.
|
|
@@ -41,7 +41,6 @@ export interface ToolHost {
|
|
|
41
41
|
} | undefined;
|
|
42
42
|
pushUndoDelta(delta: MaskDelta): void;
|
|
43
43
|
pushUndoGroup(deltas: MaskDelta[]): void;
|
|
44
|
-
getEraserUrls(): string[];
|
|
45
44
|
enableCrosshair(): void;
|
|
46
45
|
setUpSphereOrigins(mouseX: number, mouseY: number, sliceIndex: number): void;
|
|
47
46
|
zoomActionAfterDrawSphere(): void;
|
|
@@ -64,7 +63,7 @@ export type ZoomHostDeps = Pick<ToolHost, 'resetPaintAreaUIPosition' | 'resizePa
|
|
|
64
63
|
/** SphereTool host dependencies */
|
|
65
64
|
export type SphereHostDeps = Pick<ToolHost, 'setEmptyCanvasSize' | 'drawImageOnEmptyImage' | 'enableCrosshair' | 'setUpSphereOrigins'>;
|
|
66
65
|
/** DrawingTool host dependencies */
|
|
67
|
-
export type DrawingHostDeps = Pick<ToolHost, 'setCurrentLayer' | 'compositeAllLayers' | 'syncLayerSliceData' | 'filterDrawedImage' | 'getVolumeForLayer' | 'pushUndoDelta' | '
|
|
66
|
+
export type DrawingHostDeps = Pick<ToolHost, 'setCurrentLayer' | 'compositeAllLayers' | 'syncLayerSliceData' | 'filterDrawedImage' | 'getVolumeForLayer' | 'pushUndoDelta' | 'renderSliceToCanvas' | 'getOrCreateSliceBuffer'>;
|
|
68
67
|
/** DragSliceTool host dependencies */
|
|
69
68
|
export type DragSliceHostDeps = Pick<ToolHost, 'setSyncsliceNum' | 'setIsDrawFalse' | 'flipDisplayImageByAxis' | 'setEmptyCanvasSize' | 'getOrCreateSliceBuffer' | 'renderSliceToCanvas' | 'refreshSphereOverlay' | 'compositeAllLayers'>;
|
|
70
69
|
/** LayerChannelManager host dependencies */
|
|
@@ -74,4 +73,4 @@ export type SliceRenderHostDeps = Pick<ToolHost, 'compositeAllLayers' | 'getOrCr
|
|
|
74
73
|
/** DataLoader host dependencies */
|
|
75
74
|
export type DataLoaderHostDeps = Pick<ToolHost, 'invalidateSliceBuffer' | 'setDisplaySlicesBaseOnAxis' | 'afterLoadSlice' | 'setEmptyCanvasSize' | 'syncLayerSliceData' | 'reloadMasksFromVolume' | 'resetZoom'>;
|
|
76
75
|
/** SphereBrushTool host dependencies */
|
|
77
|
-
export type SphereBrushHostDeps = Pick<ToolHost, 'getVolumeForLayer' | 'compositeAllLayers' | 'pushUndoGroup' | 'renderSliceToCanvas' | 'getOrCreateSliceBuffer' | 'setEmptyCanvasSize' | 'reloadMasksFromVolume'
|
|
76
|
+
export type SphereBrushHostDeps = Pick<ToolHost, 'getVolumeForLayer' | 'compositeAllLayers' | 'pushUndoGroup' | 'renderSliceToCanvas' | 'getOrCreateSliceBuffer' | 'setEmptyCanvasSize' | 'reloadMasksFromVolume'>;
|
|
@@ -7,7 +7,6 @@ export declare function loading(loadingGif?: string): {
|
|
|
7
7
|
progress: HTMLDivElement;
|
|
8
8
|
};
|
|
9
9
|
export declare function switchPencilIcon(icon: string, urls?: string[]): string;
|
|
10
|
-
export declare function switchEraserSize(size: number, urls?: string[]): string;
|
|
11
10
|
export declare function throttle(callback: (event: MouseEvent) => void, wait: number): (event: MouseEvent) => void;
|
|
12
11
|
/**
|
|
13
12
|
* Cubic-Lagrange basis function
|
package/dist/types/index.d.ts
CHANGED
|
@@ -25,6 +25,6 @@ import type { ToolMode, IAnnotationCallbacks } from "./Utils/segmentation/core/t
|
|
|
25
25
|
import { CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "./Utils/segmentation/core/index";
|
|
26
26
|
import type { LayerId, ChannelValue } from "./Utils/segmentation/core/index";
|
|
27
27
|
import "./css/style.css";
|
|
28
|
-
export declare const REVISION = "v3.4.
|
|
28
|
+
export declare const REVISION = "v3.4.8-beta";
|
|
29
29
|
export { copperRenderer, copperRendererOnDemond, copperMSceneRenderer, setHDRFilePath, addLabelToScene, convert3DPostoScreenPos, convertScreenPosto3DPos, addBoxHelper, fullScreenListenner, configKiwriousHeart, copperScene, copperSceneOnDemond, copperMScene, CameraViewPoint, kiwrious, NrrdTools, loading, Copper3dTrackballControls, createTexture2D_NRRD, MeshNodeTool, throttle, removeGuiFolderChilden, CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss, GaussianSmoother, };
|
|
30
30
|
export type { positionType, screenPosType, optsType, nrrdMeshesType, nrrdSliceType, SensorDecodedValue_kiwrious, SensorReadResult_kiwrious, HeartRateResult_kiwrious, loadingBarType, IPaintImage, exportPaintImageType, IOptVTKLoader, ICommXYZ, IGUIStates, IGuiParameterSettings, INrrdStates, NrrdState, GuiState, IGuiMeta, ToolMode, IAnnotationCallbacks, LayerId, ChannelValue, };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "copper3d",
|
|
3
3
|
"description": "A 3d visualisation package base on threejs provides multiple scenes and Nrrd image load funtion.",
|
|
4
|
-
"version": "3.4.
|
|
4
|
+
"version": "3.4.8",
|
|
5
5
|
"main": "dist/bundle.umd.js",
|
|
6
6
|
"moudle": "dist/bundle.esm.js",
|
|
7
7
|
"types": "dist/types/index.d.ts",
|