cloudmr-ux 4.6.3 → 4.6.6
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/CmrComponents/niivue-viewer/CloudMrNiivuePanel.js +1 -1
- package/dist/CmrComponents/niivue-viewer/CloudMrNiivueViewer.js +36 -10
- package/dist/CmrComponents/niivue-viewer/NiivuePatcher.js +28 -60
- package/dist/CmrComponents/niivue-viewer/PenDraftOverlay.d.ts +3 -5
- package/dist/CmrComponents/niivue-viewer/PenDraftOverlay.js +1 -7
- package/dist/CmrComponents/niivue-viewer/ShapeDraftOverlay.d.ts +2 -3
- package/dist/CmrComponents/niivue-viewer/ShapeDraftOverlay.js +2 -7
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/DrawColorPlatte.d.ts +3 -1
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/DrawColorPlatte.js +28 -15
- package/dist/CmrComponents/niivue-viewer/shapeDraftUtils.d.ts +0 -17
- package/dist/CmrComponents/niivue-viewer/shapeDraftUtils.js +10 -26
- package/package.json +1 -1
|
@@ -186,7 +186,7 @@ export function CloudMrNiivuePanel(props) {
|
|
|
186
186
|
left: 0,
|
|
187
187
|
width: "100%",
|
|
188
188
|
height: "100%"
|
|
189
|
-
} }), props.shapeDraft && (_jsx(ShapeDraftOverlay, { nv: props.nv, draft: props.shapeDraft, onDraftChange: props.onShapeDraftChange,
|
|
189
|
+
} }), props.shapeDraft && (_jsx(ShapeDraftOverlay, { nv: props.nv, draft: props.shapeDraft, onDraftChange: props.onShapeDraftChange, overlayKey: props.mms })), props.penDraft && (_jsx(PenDraftOverlay, { nv: props.nv, draft: props.penDraft, onDraftChange: props.onPenDraftChange, overlayKey: props.mms }))] }))] })), _jsxs(Box, __assign({ sx: {
|
|
190
190
|
width: {
|
|
191
191
|
xs: "100%",
|
|
192
192
|
md: "35%"
|
|
@@ -832,12 +832,6 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
832
832
|
(_a = nv.cloudMrCancelPolyline) === null || _a === void 0 ? void 0 : _a.call(nv);
|
|
833
833
|
}
|
|
834
834
|
}
|
|
835
|
-
function syncActiveShapeDraftRef() {
|
|
836
|
-
nv._cloudMrActiveShapeDraft = shapeDraftRef.current;
|
|
837
|
-
}
|
|
838
|
-
function clearActiveShapeDraftRef() {
|
|
839
|
-
nv._cloudMrActiveShapeDraft = null;
|
|
840
|
-
}
|
|
841
835
|
function cancelPenDraftHandler() {
|
|
842
836
|
var _a;
|
|
843
837
|
var draft = penDraftRef.current;
|
|
@@ -926,7 +920,6 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
926
920
|
setShapeDraft(null);
|
|
927
921
|
shapeDraftRef.current = null;
|
|
928
922
|
nv._cloudMrShapeDraftActive = false;
|
|
929
|
-
clearActiveShapeDraftRef();
|
|
930
923
|
if (drawShapeToolRef.current) {
|
|
931
924
|
nvSetDrawingEnabled(true);
|
|
932
925
|
}
|
|
@@ -939,7 +932,6 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
939
932
|
setShapeDraft(null);
|
|
940
933
|
shapeDraftRef.current = null;
|
|
941
934
|
nv._cloudMrShapeDraftActive = false;
|
|
942
|
-
clearActiveShapeDraftRef();
|
|
943
935
|
if (drawShapeToolRef.current) {
|
|
944
936
|
nvSetDrawingEnabled(true);
|
|
945
937
|
}
|
|
@@ -948,13 +940,11 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
948
940
|
function onShapeDraftChange(draft) {
|
|
949
941
|
setShapeDraft(draft);
|
|
950
942
|
shapeDraftRef.current = draft;
|
|
951
|
-
syncActiveShapeDraftRef();
|
|
952
943
|
}
|
|
953
944
|
nv.onShapeDraftReady = function (draft) {
|
|
954
945
|
setShapeDraft(draft);
|
|
955
946
|
shapeDraftRef.current = draft;
|
|
956
947
|
nv._cloudMrShapeDraftActive = true;
|
|
957
|
-
syncActiveShapeDraftRef();
|
|
958
948
|
nvSetDrawingEnabled(false);
|
|
959
949
|
};
|
|
960
950
|
nv.onApplyActiveDraft = function () {
|
|
@@ -971,6 +961,32 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
971
961
|
React.useEffect(function () {
|
|
972
962
|
nv._cloudMrShapeDraftActive = shapeDraft != null;
|
|
973
963
|
}, [shapeDraft]);
|
|
964
|
+
React.useEffect(function () {
|
|
965
|
+
if (!shapeDraft && !penDraft) {
|
|
966
|
+
return undefined;
|
|
967
|
+
}
|
|
968
|
+
var canvas = document.getElementById("niiCanvas");
|
|
969
|
+
if (!canvas) {
|
|
970
|
+
return undefined;
|
|
971
|
+
}
|
|
972
|
+
var applyOnRightClick = function (event) {
|
|
973
|
+
var _a;
|
|
974
|
+
event.preventDefault();
|
|
975
|
+
event.stopPropagation();
|
|
976
|
+
(_a = nv.onApplyActiveDraft) === null || _a === void 0 ? void 0 : _a.call(nv);
|
|
977
|
+
};
|
|
978
|
+
var onMouseDown = function (event) {
|
|
979
|
+
if (event.button === 2) {
|
|
980
|
+
applyOnRightClick(event);
|
|
981
|
+
}
|
|
982
|
+
};
|
|
983
|
+
canvas.addEventListener("mousedown", onMouseDown, true);
|
|
984
|
+
canvas.addEventListener("contextmenu", applyOnRightClick, true);
|
|
985
|
+
return function () {
|
|
986
|
+
canvas.removeEventListener("mousedown", onMouseDown, true);
|
|
987
|
+
canvas.removeEventListener("contextmenu", applyOnRightClick, true);
|
|
988
|
+
};
|
|
989
|
+
}, [shapeDraft, penDraft]);
|
|
974
990
|
React.useEffect(function () {
|
|
975
991
|
if (!shapeDraft && !penDraft) {
|
|
976
992
|
return undefined;
|
|
@@ -984,6 +1000,16 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
984
1000
|
else if (penDraft) {
|
|
985
1001
|
cancelPenDraftHandler();
|
|
986
1002
|
}
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
if (event.key === "Enter") {
|
|
1006
|
+
event.preventDefault();
|
|
1007
|
+
if (shapeDraft) {
|
|
1008
|
+
applyShapeDraft();
|
|
1009
|
+
}
|
|
1010
|
+
else if (penDraft) {
|
|
1011
|
+
applyPenDraftHandler();
|
|
1012
|
+
}
|
|
987
1013
|
}
|
|
988
1014
|
};
|
|
989
1015
|
window.addEventListener("keydown", onKeyDown);
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
captureDeferredShapeDraft,
|
|
7
7
|
captureShapeDraftFromClick,
|
|
8
8
|
isDraftTooSmall,
|
|
9
|
-
isVoxelPartOfDraft,
|
|
10
9
|
redrawDraftShape,
|
|
11
10
|
shouldDeferShapeCommit,
|
|
12
11
|
} from "./shapeDraftUtils.js";
|
|
@@ -1469,85 +1468,54 @@ Niivue.prototype.cloudMrResetPolyline = function cloudMrResetPolyline() {
|
|
|
1469
1468
|
resetPolylineState(this);
|
|
1470
1469
|
};
|
|
1471
1470
|
|
|
1471
|
+
const RIGHT_MOUSE_BUTTON = 2;
|
|
1472
|
+
|
|
1472
1473
|
function cloudMrHasApplyableDraft(nv) {
|
|
1473
1474
|
return !!(nv._cloudMrShapeDraftActive || nv._cloudMrPenDraftActive);
|
|
1474
1475
|
}
|
|
1475
1476
|
|
|
1476
|
-
function
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
function canReopenShapeDraftOnClick(nv) {
|
|
1485
|
-
const penType = nv.opts.penType;
|
|
1486
|
-
return (
|
|
1487
|
-
nv.opts.deferShapeCommit &&
|
|
1488
|
-
nv.opts.drawingEnabled &&
|
|
1489
|
-
!nv._cloudMrShapeDraftActive &&
|
|
1490
|
-
!nv._cloudMrPenDraftActive &&
|
|
1491
|
-
(penType === NI_PEN_TYPE.RECTANGLE || penType === NI_PEN_TYPE.ELLIPSE)
|
|
1492
|
-
);
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
function cloudMrOpenShapeDraftFromClick(nv) {
|
|
1496
|
-
const reopenDraft = captureShapeDraftFromClick(nv);
|
|
1497
|
-
if (!reopenDraft) return false;
|
|
1498
|
-
redrawDraftShape(nv, reopenDraft);
|
|
1499
|
-
nv._cloudMrSuppressDrawingChangedMouseUp = true;
|
|
1500
|
-
if (typeof nv.onShapeDraftReady === "function") {
|
|
1501
|
-
nv.onShapeDraftReady(reopenDraft);
|
|
1477
|
+
function cloudMrTryApplyDraftOnRightClick(nv, event) {
|
|
1478
|
+
if (!cloudMrHasApplyableDraft(nv)) {
|
|
1479
|
+
return false;
|
|
1480
|
+
}
|
|
1481
|
+
event.preventDefault();
|
|
1482
|
+
event.stopPropagation();
|
|
1483
|
+
if (typeof nv.onApplyActiveDraft === "function") {
|
|
1484
|
+
nv.onApplyActiveDraft();
|
|
1502
1485
|
}
|
|
1503
1486
|
return true;
|
|
1504
1487
|
}
|
|
1505
1488
|
|
|
1506
1489
|
/**
|
|
1507
|
-
* Re-enter rectangle/ellipse edit mode when clicking an existing
|
|
1490
|
+
* Re-enter rectangle/ellipse edit mode when clicking an existing applied ROI.
|
|
1508
1491
|
*/
|
|
1509
1492
|
function cloudMrTryReopenShapeDraftOnClick(nv) {
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
*/
|
|
1520
|
-
function cloudMrTrySwitchShapeDraftOnMouseDown(nv) {
|
|
1521
|
-
if (!nv._cloudMrShapeDraftActive || nv._cloudMrPenDraftActive) {
|
|
1522
|
-
return false;
|
|
1523
|
-
}
|
|
1524
|
-
if (!nv.opts.deferShapeCommit || !nv.opts.drawingEnabled) {
|
|
1525
|
-
return false;
|
|
1526
|
-
}
|
|
1527
|
-
|
|
1528
|
-
const vox = voxFromMouse(nv);
|
|
1529
|
-
if (!vox || isClickOnActiveShapeDraft(nv)) {
|
|
1493
|
+
const penType = nv.opts.penType;
|
|
1494
|
+
if (
|
|
1495
|
+
!nv.opts.deferShapeCommit ||
|
|
1496
|
+
!nv.opts.drawingEnabled ||
|
|
1497
|
+
nv._cloudMrShapeDraftActive ||
|
|
1498
|
+
nv._cloudMrPenDraftActive ||
|
|
1499
|
+
!isClickWithoutDrag(nv.uiData) ||
|
|
1500
|
+
(penType !== NI_PEN_TYPE.RECTANGLE && penType !== NI_PEN_TYPE.ELLIPSE)
|
|
1501
|
+
) {
|
|
1530
1502
|
return false;
|
|
1531
1503
|
}
|
|
1532
1504
|
|
|
1533
|
-
const
|
|
1534
|
-
if (!
|
|
1535
|
-
const dx = dims[1];
|
|
1536
|
-
const dy = dims[2];
|
|
1537
|
-
const idx = vox[0] + vox[1] * dx + vox[2] * dx * dy;
|
|
1538
|
-
if (!nv.drawBitmap[idx]) {
|
|
1539
|
-
return false;
|
|
1540
|
-
}
|
|
1505
|
+
const reopenDraft = captureShapeDraftFromClick(nv);
|
|
1506
|
+
if (!reopenDraft) return false;
|
|
1541
1507
|
|
|
1542
|
-
|
|
1543
|
-
|
|
1508
|
+
redrawDraftShape(nv, reopenDraft);
|
|
1509
|
+
nv._cloudMrSuppressDrawingChangedMouseUp = true;
|
|
1510
|
+
if (typeof nv.onShapeDraftReady === "function") {
|
|
1511
|
+
nv.onShapeDraftReady(reopenDraft);
|
|
1544
1512
|
}
|
|
1545
|
-
return
|
|
1513
|
+
return true;
|
|
1546
1514
|
}
|
|
1547
1515
|
|
|
1548
1516
|
const _mouseDownListener = Niivue.prototype.mouseDownListener;
|
|
1549
1517
|
Niivue.prototype.mouseDownListener = function cloudMrMouseDownListener(e) {
|
|
1550
|
-
if (e.button ===
|
|
1518
|
+
if (e.button === RIGHT_MOUSE_BUTTON && cloudMrTryApplyDraftOnRightClick(this, e)) {
|
|
1551
1519
|
return;
|
|
1552
1520
|
}
|
|
1553
1521
|
if (shouldDeferFreehandCommit(this) && this.drawBitmap) {
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Adjust handles for polyline (vertex drag) or freehand (move only) drafts.
|
|
3
|
-
* @param {{ nv: any, draft: any, onDraftChange: (d: any) => void, onApplyDraft?: () => void, overlayKey?: unknown }} props
|
|
4
3
|
*/
|
|
5
|
-
export function PenDraftOverlay({ nv, draft, onDraftChange,
|
|
4
|
+
export function PenDraftOverlay({ nv, draft, onDraftChange, overlayKey }: {
|
|
6
5
|
nv: any;
|
|
7
6
|
draft: any;
|
|
8
|
-
onDraftChange:
|
|
9
|
-
|
|
10
|
-
overlayKey?: unknown;
|
|
7
|
+
onDraftChange: any;
|
|
8
|
+
overlayKey: any;
|
|
11
9
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
12
10
|
export default PenDraftOverlay;
|
|
@@ -29,10 +29,9 @@ function cloneFreehandDraft(draft) {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Adjust handles for polyline (vertex drag) or freehand (move only) drafts.
|
|
32
|
-
* @param {{ nv: any, draft: any, onDraftChange: (d: any) => void, onApplyDraft?: () => void, overlayKey?: unknown }} props
|
|
33
32
|
*/
|
|
34
33
|
export function PenDraftOverlay(_a) {
|
|
35
|
-
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange,
|
|
34
|
+
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange, overlayKey = _a.overlayKey;
|
|
36
35
|
var dragRef = useRef(null);
|
|
37
36
|
var draftRef = useRef(draft);
|
|
38
37
|
draftRef.current = draft;
|
|
@@ -110,7 +109,6 @@ export function PenDraftOverlay(_a) {
|
|
|
110
109
|
onDraftChange(nextDraft);
|
|
111
110
|
}, [nv, onDraftChange]);
|
|
112
111
|
finishDragRef.current = function () {
|
|
113
|
-
var hadDrag = dragRef.current != null;
|
|
114
112
|
dragRef.current = null;
|
|
115
113
|
if (onPointerMoveRef.current) {
|
|
116
114
|
window.removeEventListener("pointermove", onPointerMoveRef.current);
|
|
@@ -118,10 +116,6 @@ export function PenDraftOverlay(_a) {
|
|
|
118
116
|
if (finishDragRef.current) {
|
|
119
117
|
window.removeEventListener("pointerup", finishDragRef.current);
|
|
120
118
|
}
|
|
121
|
-
// Auto-apply as soon as the user releases the handle after a move/resize
|
|
122
|
-
if (hadDrag && onApplyDraft) {
|
|
123
|
-
onApplyDraft();
|
|
124
|
-
}
|
|
125
119
|
};
|
|
126
120
|
onPointerMoveRef.current = function (event) {
|
|
127
121
|
var drag = dragRef.current;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay handles for adjusting a rectangle/ellipse draft before commit.
|
|
3
|
-
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void,
|
|
3
|
+
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void, overlayKey?: unknown }} props
|
|
4
4
|
*/
|
|
5
|
-
export function ShapeDraftOverlay({ nv, draft, onDraftChange,
|
|
5
|
+
export function ShapeDraftOverlay({ nv, draft, onDraftChange, overlayKey }: {
|
|
6
6
|
nv: any;
|
|
7
7
|
draft: import('./shapeDraftUtils').ShapeDraft;
|
|
8
8
|
onDraftChange: (d: any) => void;
|
|
9
|
-
onApplyDraft?: (() => void) | undefined;
|
|
10
9
|
overlayKey?: unknown;
|
|
11
10
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
12
11
|
export default ShapeDraftOverlay;
|
|
@@ -25,11 +25,11 @@ var HANDLE_SIZE = 10;
|
|
|
25
25
|
var ACCENT = "#580f8b";
|
|
26
26
|
/**
|
|
27
27
|
* Overlay handles for adjusting a rectangle/ellipse draft before commit.
|
|
28
|
-
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void,
|
|
28
|
+
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void, overlayKey?: unknown }} props
|
|
29
29
|
*/
|
|
30
30
|
export function ShapeDraftOverlay(_a) {
|
|
31
31
|
var _b;
|
|
32
|
-
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange,
|
|
32
|
+
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange, overlayKey = _a.overlayKey;
|
|
33
33
|
var dragRef = useRef(null);
|
|
34
34
|
var draftRef = useRef(draft);
|
|
35
35
|
draftRef.current = draft;
|
|
@@ -84,7 +84,6 @@ export function ShapeDraftOverlay(_a) {
|
|
|
84
84
|
onDraftChange(nextDraft);
|
|
85
85
|
}, [nv, onDraftChange]);
|
|
86
86
|
finishDragRef.current = function () {
|
|
87
|
-
var hadDrag = dragRef.current != null;
|
|
88
87
|
dragRef.current = null;
|
|
89
88
|
if (onPointerMoveRef.current) {
|
|
90
89
|
window.removeEventListener("pointermove", onPointerMoveRef.current);
|
|
@@ -92,10 +91,6 @@ export function ShapeDraftOverlay(_a) {
|
|
|
92
91
|
if (finishDragRef.current) {
|
|
93
92
|
window.removeEventListener("pointerup", finishDragRef.current);
|
|
94
93
|
}
|
|
95
|
-
// Auto-apply as soon as the user releases the handle after a move/resize
|
|
96
|
-
if (hadDrag && onApplyDraft) {
|
|
97
|
-
onApplyDraft();
|
|
98
|
-
}
|
|
99
94
|
};
|
|
100
95
|
onPointerMoveRef.current = function (event) {
|
|
101
96
|
var drag = dragRef.current;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export default function DrawColorPlatte({ expanded, updateDrawPen, setDrawingEnabled, showPenModes, penDrawMode, onPenDrawModeChange, polylineVertexCount, penDraftActive, onCancelPenDraft, onFillPenDraft, brushSize, updateBrushSize, shapeDraftActive, onCancelShapeDraft, }: {
|
|
1
|
+
export default function DrawColorPlatte({ expanded, updateDrawPen, setDrawingEnabled, showPenModes, penDrawMode, onPenDrawModeChange, polylineVertexCount, penDraftActive, onApplyPenDraft, onCancelPenDraft, onFillPenDraft, brushSize, updateBrushSize, shapeDraftActive, onApplyShapeDraft, onCancelShapeDraft, }: {
|
|
2
2
|
expanded: any;
|
|
3
3
|
updateDrawPen: any;
|
|
4
4
|
setDrawingEnabled: any;
|
|
@@ -7,10 +7,12 @@ export default function DrawColorPlatte({ expanded, updateDrawPen, setDrawingEna
|
|
|
7
7
|
onPenDrawModeChange: any;
|
|
8
8
|
polylineVertexCount?: number | undefined;
|
|
9
9
|
penDraftActive?: boolean | undefined;
|
|
10
|
+
onApplyPenDraft: any;
|
|
10
11
|
onCancelPenDraft: any;
|
|
11
12
|
onFillPenDraft: any;
|
|
12
13
|
brushSize?: number | undefined;
|
|
13
14
|
updateBrushSize: any;
|
|
14
15
|
shapeDraftActive?: boolean | undefined;
|
|
16
|
+
onApplyShapeDraft: any;
|
|
15
17
|
onCancelShapeDraft: any;
|
|
16
18
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -11,13 +11,12 @@ var __assign = (this && this.__assign) || function () {
|
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
/**
|
|
14
|
-
* Pen palette adds freehand vs polyline mode; pen/shape drafts show Cancel while adjusting.
|
|
15
|
-
* Shapes are applied automatically on mouse release.
|
|
14
|
+
* Pen palette adds freehand vs polyline mode; pen/shape drafts show Apply/Cancel while adjusting.
|
|
16
15
|
*/
|
|
17
16
|
import { Stack, IconButton, Button, Tooltip, Typography } from "@mui/material";
|
|
18
17
|
import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord";
|
|
18
|
+
import CheckIcon from "@mui/icons-material/Check";
|
|
19
19
|
import CloseIcon from "@mui/icons-material/Close";
|
|
20
|
-
import FormatColorFillIcon from "@mui/icons-material/FormatColorFill";
|
|
21
20
|
import { BrushSizeSlider } from "./BrushSizeSlider";
|
|
22
21
|
var FILLED_COLORS = [
|
|
23
22
|
{ sx: { color: "red" } },
|
|
@@ -38,7 +37,7 @@ var modeBtnSx = function (active) { return ({
|
|
|
38
37
|
px: 0.75
|
|
39
38
|
}); };
|
|
40
39
|
export default function DrawColorPlatte(_a) {
|
|
41
|
-
var expanded = _a.expanded, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.showPenModes, showPenModes = _b === void 0 ? false : _b, _c = _a.penDrawMode, penDrawMode = _c === void 0 ? "freehand" : _c, onPenDrawModeChange = _a.onPenDrawModeChange, _d = _a.polylineVertexCount, polylineVertexCount = _d === void 0 ? 0 : _d, _e = _a.penDraftActive, penDraftActive = _e === void 0 ? false : _e, onCancelPenDraft = _a.onCancelPenDraft, onFillPenDraft = _a.onFillPenDraft, _f = _a.brushSize, brushSize = _f === void 0 ? 1 : _f, updateBrushSize = _a.updateBrushSize, _g = _a.shapeDraftActive, shapeDraftActive = _g === void 0 ? false : _g, onCancelShapeDraft = _a.onCancelShapeDraft;
|
|
40
|
+
var expanded = _a.expanded, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.showPenModes, showPenModes = _b === void 0 ? false : _b, _c = _a.penDrawMode, penDrawMode = _c === void 0 ? "freehand" : _c, onPenDrawModeChange = _a.onPenDrawModeChange, _d = _a.polylineVertexCount, polylineVertexCount = _d === void 0 ? 0 : _d, _e = _a.penDraftActive, penDraftActive = _e === void 0 ? false : _e, onApplyPenDraft = _a.onApplyPenDraft, onCancelPenDraft = _a.onCancelPenDraft, onFillPenDraft = _a.onFillPenDraft, _f = _a.brushSize, brushSize = _f === void 0 ? 1 : _f, updateBrushSize = _a.updateBrushSize, _g = _a.shapeDraftActive, shapeDraftActive = _g === void 0 ? false : _g, onApplyShapeDraft = _a.onApplyShapeDraft, onCancelShapeDraft = _a.onCancelShapeDraft;
|
|
42
41
|
return (_jsxs(Stack, __assign({ style: {
|
|
43
42
|
position: "absolute",
|
|
44
43
|
top: "100%",
|
|
@@ -63,22 +62,36 @@ export default function DrawColorPlatte(_a) {
|
|
|
63
62
|
py: 0.25,
|
|
64
63
|
px: 0.75,
|
|
65
64
|
"& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
|
|
66
|
-
} }, { children: "Cancel" })) })), penDrawMode === "polyline" && polylineVertexCount >= 3 && (_jsx(Tooltip, __assign({ title: "Fill interior (keeps outline editable until
|
|
65
|
+
} }, { children: "Cancel" })) })), _jsxs(Stack, __assign({ direction: "row", alignItems: "center", spacing: 1 }, { children: [penDrawMode === "polyline" && polylineVertexCount >= 3 && (_jsx(Tooltip, __assign({ title: "Fill interior (keeps outline editable until Apply)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "fill polyline", onClick: function () { return onFillPenDraft === null || onFillPenDraft === void 0 ? void 0 : onFillPenDraft(); }, sx: {
|
|
66
|
+
color: "#c9a0e8",
|
|
67
|
+
fontSize: ACTION_FONT_SIZE,
|
|
68
|
+
textTransform: "none",
|
|
69
|
+
minWidth: 0,
|
|
70
|
+
py: 0.25,
|
|
71
|
+
px: 0.75
|
|
72
|
+
} }, { children: "Fill" })) }))), _jsx(Tooltip, __assign({ title: "Apply shape (enter or right-click)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "apply pen draft", onClick: function () { return onApplyPenDraft === null || onApplyPenDraft === void 0 ? void 0 : onApplyPenDraft(); }, startIcon: _jsx(CheckIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
|
|
73
|
+
color: "#c9a0e8",
|
|
74
|
+
fontSize: ACTION_FONT_SIZE,
|
|
75
|
+
textTransform: "none",
|
|
76
|
+
minWidth: 0,
|
|
77
|
+
py: 0.25,
|
|
78
|
+
px: 0.75,
|
|
79
|
+
"& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
|
|
80
|
+
} }, { children: "Apply" })) }))] }))] }))), shapeDraftActive && expanded && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1, py: 0.5, borderTop: "1px solid #555", width: "100%" } }, { children: [_jsx(Tooltip, __assign({ title: "Cancel shape (Esc)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "cancel shape", onClick: function () { return onCancelShapeDraft === null || onCancelShapeDraft === void 0 ? void 0 : onCancelShapeDraft(); }, startIcon: _jsx(CloseIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
|
|
81
|
+
color: "#ccc",
|
|
82
|
+
fontSize: ACTION_FONT_SIZE,
|
|
83
|
+
textTransform: "none",
|
|
84
|
+
minWidth: 0,
|
|
85
|
+
py: 0.25,
|
|
86
|
+
px: 0.75,
|
|
87
|
+
"& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
|
|
88
|
+
} }, { children: "Cancel" })) })), _jsx(Tooltip, __assign({ title: "Apply shape (enter or right-click)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "apply shape", onClick: function () { return onApplyShapeDraft === null || onApplyShapeDraft === void 0 ? void 0 : onApplyShapeDraft(); }, startIcon: _jsx(CheckIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
|
|
67
89
|
color: "#c9a0e8",
|
|
68
90
|
fontSize: ACTION_FONT_SIZE,
|
|
69
91
|
textTransform: "none",
|
|
70
92
|
minWidth: 0,
|
|
71
93
|
py: 0.25,
|
|
72
94
|
px: 0.75,
|
|
73
|
-
ml: "auto",
|
|
74
95
|
"& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
|
|
75
|
-
} }, { children: "
|
|
76
|
-
color: "#ccc",
|
|
77
|
-
fontSize: ACTION_FONT_SIZE,
|
|
78
|
-
textTransform: "none",
|
|
79
|
-
minWidth: 0,
|
|
80
|
-
py: 0.25,
|
|
81
|
-
px: 0.75,
|
|
82
|
-
"& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
|
|
83
|
-
} }, { children: "Cancel" })) })) })))] })));
|
|
96
|
+
} }, { children: "Apply" })) }))] })))] })));
|
|
84
97
|
}
|
|
@@ -49,27 +49,10 @@ export function captureDeferredShapeDraft(nv: any): {
|
|
|
49
49
|
baseBitmap: Uint8Array | null;
|
|
50
50
|
};
|
|
51
51
|
export function shouldDeferShapeCommit(nv: any): any;
|
|
52
|
-
/**
|
|
53
|
-
* Flood-fill a connected voxel cluster from a seed.
|
|
54
|
-
* @returns {{ label: number, visited: Set<number>, voxels: [number,number,number][], bounds: object } | null}
|
|
55
|
-
*/
|
|
56
|
-
export function floodFillClusterFromVox(nv: any, seedVox: any): {
|
|
57
|
-
label: number;
|
|
58
|
-
visited: Set<number>;
|
|
59
|
-
voxels: [number, number, number][];
|
|
60
|
-
bounds: object;
|
|
61
|
-
} | null;
|
|
62
|
-
/** True when a voxel belongs to the live draft overlay (drawn on top of baseBitmap). */
|
|
63
|
-
export function isVoxelPartOfDraft(nv: any, draft: any, seedVox: any): boolean;
|
|
64
|
-
export function eraseClusterFromBitmap(bitmap: any, visited: any): Uint8Array;
|
|
65
|
-
/** Guess rectangle vs ellipse from the filled voxel pattern, not the active tool. */
|
|
66
|
-
export function inferShapePenTypeFromCluster(cluster: any, axCorSag: any): 1 | 2;
|
|
67
52
|
/**
|
|
68
53
|
* When the user clicks on an existing filled ROI while the rectangle/ellipse tool
|
|
69
54
|
* is active (but no draft is currently open), flood-fill the clicked cluster to
|
|
70
55
|
* reconstruct a ShapeDraft so the bounding-box overlay reappears for re-editing.
|
|
71
|
-
*
|
|
72
|
-
* Returns null if the click didn't land on a labeled voxel.
|
|
73
56
|
*/
|
|
74
57
|
export function captureShapeDraftFromClick(nv: any): {
|
|
75
58
|
ptA: any[];
|
|
@@ -210,11 +210,18 @@ function inferAxCorSagFromBounds(x1, y1, z1, x2, y2, z2, fallback) {
|
|
|
210
210
|
return 2;
|
|
211
211
|
return fallback;
|
|
212
212
|
}
|
|
213
|
+
function sliceKey(axCorSag, x, y, z) {
|
|
214
|
+
if (axCorSag === 0)
|
|
215
|
+
return "".concat(x, ",").concat(y);
|
|
216
|
+
if (axCorSag === 1)
|
|
217
|
+
return "".concat(x, ",").concat(z);
|
|
218
|
+
return "".concat(y, ",").concat(z);
|
|
219
|
+
}
|
|
213
220
|
/**
|
|
214
221
|
* Flood-fill a connected voxel cluster from a seed.
|
|
215
222
|
* @returns {{ label: number, visited: Set<number>, voxels: [number,number,number][], bounds: object } | null}
|
|
216
223
|
*/
|
|
217
|
-
|
|
224
|
+
function floodFillClusterFromVox(nv, seedVox) {
|
|
218
225
|
var _a;
|
|
219
226
|
var dims = (_a = nv.back) === null || _a === void 0 ? void 0 : _a.dims;
|
|
220
227
|
if (!dims || !nv.drawBitmap || !seedVox)
|
|
@@ -274,36 +281,15 @@ export function floodFillClusterFromVox(nv, seedVox) {
|
|
|
274
281
|
bounds: { x1: x1, y1: y1, z1: z1, x2: x2, y2: y2, z2: z2 }
|
|
275
282
|
};
|
|
276
283
|
}
|
|
277
|
-
|
|
278
|
-
export function isVoxelPartOfDraft(nv, draft, seedVox) {
|
|
279
|
-
var _a;
|
|
280
|
-
if (!(draft === null || draft === void 0 ? void 0 : draft.baseBitmap) || !(nv === null || nv === void 0 ? void 0 : nv.drawBitmap) || !seedVox)
|
|
281
|
-
return false;
|
|
282
|
-
var dims = (_a = nv.back) === null || _a === void 0 ? void 0 : _a.dims;
|
|
283
|
-
if (!dims)
|
|
284
|
-
return false;
|
|
285
|
-
var dx = dims[1];
|
|
286
|
-
var dy = dims[2];
|
|
287
|
-
var idx = voxelIndex(seedVox[0], seedVox[1], seedVox[2], dx, dy);
|
|
288
|
-
return (nv.drawBitmap[idx] === draft.penValue &&
|
|
289
|
-
draft.baseBitmap[idx] !== draft.penValue);
|
|
290
|
-
}
|
|
291
|
-
export function eraseClusterFromBitmap(bitmap, visited) {
|
|
284
|
+
function eraseClusterFromBitmap(bitmap, visited) {
|
|
292
285
|
var next = new Uint8Array(bitmap);
|
|
293
286
|
visited.forEach(function (idx) {
|
|
294
287
|
next[idx] = 0;
|
|
295
288
|
});
|
|
296
289
|
return next;
|
|
297
290
|
}
|
|
298
|
-
function sliceKey(axCorSag, x, y, z) {
|
|
299
|
-
if (axCorSag === 0)
|
|
300
|
-
return "".concat(x, ",").concat(y);
|
|
301
|
-
if (axCorSag === 1)
|
|
302
|
-
return "".concat(x, ",").concat(z);
|
|
303
|
-
return "".concat(y, ",").concat(z);
|
|
304
|
-
}
|
|
305
291
|
/** Guess rectangle vs ellipse from the filled voxel pattern, not the active tool. */
|
|
306
|
-
|
|
292
|
+
function inferShapePenTypeFromCluster(cluster, axCorSag) {
|
|
307
293
|
var bounds = cluster.bounds, voxels = cluster.voxels;
|
|
308
294
|
var x1 = bounds.x1, y1 = bounds.y1, z1 = bounds.z1, x2 = bounds.x2, y2 = bounds.y2, z2 = bounds.z2;
|
|
309
295
|
var filled = new Set();
|
|
@@ -358,8 +344,6 @@ export function inferShapePenTypeFromCluster(cluster, axCorSag) {
|
|
|
358
344
|
* When the user clicks on an existing filled ROI while the rectangle/ellipse tool
|
|
359
345
|
* is active (but no draft is currently open), flood-fill the clicked cluster to
|
|
360
346
|
* reconstruct a ShapeDraft so the bounding-box overlay reappears for re-editing.
|
|
361
|
-
*
|
|
362
|
-
* Returns null if the click didn't land on a labeled voxel.
|
|
363
347
|
*/
|
|
364
348
|
export function captureShapeDraftFromClick(nv) {
|
|
365
349
|
var seedVox = voxFromMouse(nv);
|