@aics/vole-app 3.3.1 → 3.4.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/es/aics-image-viewer/components/App/index.js +1 -0
- package/es/aics-image-viewer/components/BottomPanel/index.js +48 -19
- package/es/aics-image-viewer/components/BottomPanel/styles.css +16 -7
- package/es/aics-image-viewer/components/CellViewerCanvasWrapper/index.js +39 -19
- package/es/aics-image-viewer/components/ControlPanel/index.js +2 -0
- package/es/aics-image-viewer/components/dimension_sliders/AxisClipSliders.js +148 -0
- package/es/aics-image-viewer/components/dimension_sliders/RotationSliders.js +167 -0
- package/es/aics-image-viewer/components/dimension_sliders/SliderRows.js +167 -0
- package/es/aics-image-viewer/components/{AxisClipSliders → dimension_sliders}/styles.css +7 -1
- package/es/aics-image-viewer/components/shared/NumericInput/index.js +4 -2
- package/es/aics-image-viewer/components/shared/SliderRow/index.js +2 -0
- package/es/aics-image-viewer/components/shared/SliderRow/styles.css +2 -1
- package/es/aics-image-viewer/shared/constants.js +1 -1
- package/es/aics-image-viewer/shared/utils/camera.js +122 -0
- package/es/aics-image-viewer/shared/utils/test/camera.test.js +127 -0
- package/es/aics-image-viewer/shared/utils/test/urlParsing.test.js +23 -702
- package/es/aics-image-viewer/shared/utils/urlParsing.js +14 -828
- package/es/aics-image-viewer/state/deserialize.js +437 -0
- package/es/aics-image-viewer/state/serialize.js +145 -0
- package/es/aics-image-viewer/state/test/deserialize.test.js +432 -0
- package/es/aics-image-viewer/state/test/serialize.test.js +97 -0
- package/es/aics-image-viewer/state/test/test_data.js +168 -0
- package/es/aics-image-viewer/state/types.js +265 -1
- package/package.json +2 -1
- package/type-declarations/aics-image-viewer/components/App/types.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/BottomPanel/index.d.ts +6 -3
- package/type-declarations/aics-image-viewer/components/CellViewerCanvasWrapper/index.d.ts +1 -0
- package/type-declarations/aics-image-viewer/components/{AxisClipSliders/index.d.ts → dimension_sliders/AxisClipSliders.d.ts} +2 -3
- package/type-declarations/aics-image-viewer/components/dimension_sliders/RotationSliders.d.ts +6 -0
- package/type-declarations/aics-image-viewer/components/dimension_sliders/SliderRows.d.ts +31 -0
- package/type-declarations/aics-image-viewer/components/shared/NumericInput/index.d.ts +1 -0
- package/type-declarations/aics-image-viewer/components/shared/SliderRow/index.d.ts +3 -1
- package/type-declarations/aics-image-viewer/shared/utils/camera.d.ts +19 -0
- package/type-declarations/aics-image-viewer/shared/utils/urlParsing.d.ts +1 -307
- package/type-declarations/aics-image-viewer/state/deserialize.d.ts +70 -0
- package/type-declarations/aics-image-viewer/state/serialize.d.ts +20 -0
- package/type-declarations/aics-image-viewer/state/types.d.ts +216 -0
- package/es/aics-image-viewer/components/AxisClipSliders/index.js +0 -295
|
@@ -5,37 +5,66 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
5
5
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
6
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
7
7
|
import { Button, Drawer } from "antd";
|
|
8
|
-
import React, { useCallback, useState } from "react";
|
|
8
|
+
import React, { useCallback, useEffect, useState } from "react";
|
|
9
9
|
import ViewerIcon from "../shared/ViewerIcon";
|
|
10
10
|
import "./styles.css";
|
|
11
11
|
var BottomPanel = function BottomPanel(_ref) {
|
|
12
|
-
var
|
|
12
|
+
var _contents$page;
|
|
13
|
+
var contents = _ref.contents,
|
|
13
14
|
openProp = _ref.open,
|
|
14
|
-
|
|
15
|
+
pageProp = _ref.pageIndex,
|
|
15
16
|
height = _ref.height,
|
|
16
|
-
|
|
17
|
+
onPageChange = _ref.onPageChange;
|
|
17
18
|
var _useState = useState(true),
|
|
18
19
|
_useState2 = _slicedToArray(_useState, 2),
|
|
19
20
|
openState = _useState2[0],
|
|
20
21
|
setOpenState = _useState2[1];
|
|
22
|
+
var _useState3 = useState(0),
|
|
23
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
24
|
+
pageState = _useState4[0],
|
|
25
|
+
setPageState = _useState4[1];
|
|
21
26
|
var open = openProp !== null && openProp !== void 0 ? openProp : openState;
|
|
22
|
-
var
|
|
27
|
+
var page = pageProp !== null && pageProp !== void 0 ? pageProp : pageState;
|
|
28
|
+
var setPage = useCallback(function (index) {
|
|
29
|
+
var nextOpen = !open || index !== page;
|
|
23
30
|
if (openProp === undefined) {
|
|
24
|
-
setOpenState(
|
|
31
|
+
setOpenState(nextOpen);
|
|
25
32
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
var optionsButton = /*#__PURE__*/React.createElement(Button, {
|
|
29
|
-
className: "options-button",
|
|
30
|
-
size: "small",
|
|
31
|
-
onClick: toggleDrawer
|
|
32
|
-
}, title || "Options", /*#__PURE__*/React.createElement(ViewerIcon, {
|
|
33
|
-
type: "closePanel",
|
|
34
|
-
className: "button-arrow",
|
|
35
|
-
style: {
|
|
36
|
-
fontSize: "15px"
|
|
33
|
+
if (pageProp === undefined) {
|
|
34
|
+
setPageState(index);
|
|
37
35
|
}
|
|
38
|
-
|
|
36
|
+
onPageChange === null || onPageChange === void 0 || onPageChange(nextOpen ? index : null);
|
|
37
|
+
}, [open, openProp, page, pageProp, onPageChange]);
|
|
38
|
+
|
|
39
|
+
// If length of `contents` decreases, ensure we're still on a valid page
|
|
40
|
+
useEffect(function () {
|
|
41
|
+
if (page >= contents.length && contents.length > 0) {
|
|
42
|
+
var nextPage = contents.length - 1;
|
|
43
|
+
if (pageProp === undefined) {
|
|
44
|
+
setPageState(nextPage);
|
|
45
|
+
}
|
|
46
|
+
onPageChange === null || onPageChange === void 0 || onPageChange(open ? nextPage : null);
|
|
47
|
+
}
|
|
48
|
+
}, [contents.length, onPageChange, open, page, pageProp]);
|
|
49
|
+
var optionsButton = /*#__PURE__*/React.createElement("div", {
|
|
50
|
+
className: "options-button-container"
|
|
51
|
+
}, contents.map(function (_ref2, index) {
|
|
52
|
+
var title = _ref2.title;
|
|
53
|
+
return /*#__PURE__*/React.createElement(Button, {
|
|
54
|
+
key: index,
|
|
55
|
+
className: open && page === index ? "options-button button-open" : "options-button",
|
|
56
|
+
size: "small",
|
|
57
|
+
onClick: function onClick() {
|
|
58
|
+
return setPage(index);
|
|
59
|
+
}
|
|
60
|
+
}, title, /*#__PURE__*/React.createElement(ViewerIcon, {
|
|
61
|
+
type: "closePanel",
|
|
62
|
+
className: "button-arrow",
|
|
63
|
+
style: {
|
|
64
|
+
fontSize: "15px"
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
}).reverse());
|
|
39
68
|
return /*#__PURE__*/React.createElement("div", {
|
|
40
69
|
className: "bottom-panel"
|
|
41
70
|
}, /*#__PURE__*/React.createElement(Drawer, {
|
|
@@ -49,6 +78,6 @@ var BottomPanel = function BottomPanel(_ref) {
|
|
|
49
78
|
height: height !== null && height !== void 0 ? height : 190
|
|
50
79
|
}, /*#__PURE__*/React.createElement("div", {
|
|
51
80
|
className: "drawer-body-wrapper"
|
|
52
|
-
}, children)));
|
|
81
|
+
}, open !== null && ((_contents$page = contents[page]) === null || _contents$page === void 0 ? void 0 : _contents$page.children))));
|
|
53
82
|
};
|
|
54
83
|
export default BottomPanel;
|
|
@@ -46,18 +46,27 @@
|
|
|
46
46
|
color:white;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
.bottom-panel .options-button-container{
|
|
50
|
+
position:absolute;
|
|
51
|
+
right:0;
|
|
52
|
+
}
|
|
53
|
+
|
|
49
54
|
.bottom-panel .options-button{
|
|
55
|
+
bottom:0;
|
|
56
|
+
transition:bottom 0.1s linear;
|
|
50
57
|
border:none;
|
|
51
58
|
box-shadow:none;
|
|
52
59
|
margin-right:0.8em;
|
|
53
60
|
margin-bottom:0.2em;
|
|
54
|
-
position:absolute;
|
|
55
|
-
right:0;
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
.bottom-panel .button-arrow{
|
|
59
64
|
transform:rotate(270deg);
|
|
60
|
-
transition:transform 0.
|
|
65
|
+
transition:transform 0.1s linear !important;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.bottom-panel .options-button.button-open .button-arrow{
|
|
69
|
+
transform:rotate(90deg);
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
.bottom-panel .drawer-body-wrapper{
|
|
@@ -65,6 +74,10 @@
|
|
|
65
74
|
width:100%;
|
|
66
75
|
}
|
|
67
76
|
|
|
77
|
+
.bottom-panel .ant-drawer.ant-drawer-open .options-button:not(.button-open){
|
|
78
|
+
bottom:0.8em;
|
|
79
|
+
}
|
|
80
|
+
|
|
68
81
|
.bottom-panel .ant-drawer.ant-drawer-open .ant-drawer-content-wrapper{
|
|
69
82
|
transform:none;
|
|
70
83
|
box-shadow:none;
|
|
@@ -79,7 +92,3 @@
|
|
|
79
92
|
.bottom-panel .ant-drawer.ant-drawer-open .ant-drawer-title .ant-btn.ant-btn-default{
|
|
80
93
|
background-color:var(--color-controlpanel-drawer-bg);
|
|
81
94
|
}
|
|
82
|
-
|
|
83
|
-
.bottom-panel .ant-drawer.ant-drawer-open .button-arrow{
|
|
84
|
-
transform:rotate(90deg);
|
|
85
|
-
}
|
|
@@ -9,8 +9,9 @@ import React from "react";
|
|
|
9
9
|
import { CLIPPING_PANEL_HEIGHT_DEFAULT, CLIPPING_PANEL_HEIGHT_TALL } from "../../shared/constants";
|
|
10
10
|
import { ViewMode } from "../../shared/enums";
|
|
11
11
|
import { select, useViewerState } from "../../state/store";
|
|
12
|
-
import AxisClipSliders from "../AxisClipSliders";
|
|
13
12
|
import BottomPanel from "../BottomPanel";
|
|
13
|
+
import { AxisClipSliders } from "../dimension_sliders/AxisClipSliders";
|
|
14
|
+
import { RotationSliders } from "../dimension_sliders/RotationSliders";
|
|
14
15
|
import "./styles.css";
|
|
15
16
|
var ViewerWrapper = function ViewerWrapper(props) {
|
|
16
17
|
var view3dviewerRef = /*#__PURE__*/React.createRef();
|
|
@@ -47,6 +48,36 @@ var ViewerWrapper = function ViewerWrapper(props) {
|
|
|
47
48
|
var time = useViewerState(select("time"));
|
|
48
49
|
var scene = useViewerState(select("scene"));
|
|
49
50
|
var clippingPanelTall = numTimesteps > 1 && numScenes > 1 && viewMode === ViewMode.threeD;
|
|
51
|
+
var bottomPanelContents = [];
|
|
52
|
+
if (visibleControls.axisClipSliders && !!props.image) {
|
|
53
|
+
bottomPanelContents.push({
|
|
54
|
+
title: "Clipping",
|
|
55
|
+
children: /*#__PURE__*/React.createElement(AxisClipSliders, {
|
|
56
|
+
mode: viewMode,
|
|
57
|
+
image: props.image,
|
|
58
|
+
changeViewerSetting: changeViewerSetting,
|
|
59
|
+
numSlices: props.numSlices,
|
|
60
|
+
numSlicesLoaded: props.numSlicesLoaded,
|
|
61
|
+
numScenes: numScenes,
|
|
62
|
+
region: region,
|
|
63
|
+
slices: slice,
|
|
64
|
+
numTimesteps: numTimesteps,
|
|
65
|
+
time: time,
|
|
66
|
+
scene: scene,
|
|
67
|
+
playControls: props.playControls,
|
|
68
|
+
playingAxis: props.playingAxis
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (visibleControls.rotationSliders) {
|
|
73
|
+
bottomPanelContents.push({
|
|
74
|
+
title: "Rotation",
|
|
75
|
+
children: /*#__PURE__*/React.createElement(RotationSliders, {
|
|
76
|
+
view3d: props.view3d,
|
|
77
|
+
disable: viewMode !== ViewMode.threeD
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
}
|
|
50
81
|
return /*#__PURE__*/React.createElement("div", {
|
|
51
82
|
className: "cell-canvas",
|
|
52
83
|
style: _objectSpread(_objectSpread({}, STYLES.viewer), {}, {
|
|
@@ -56,25 +87,14 @@ var ViewerWrapper = function ViewerWrapper(props) {
|
|
|
56
87
|
ref: view3dviewerRef,
|
|
57
88
|
style: STYLES.view3d
|
|
58
89
|
}), /*#__PURE__*/React.createElement(BottomPanel, {
|
|
59
|
-
title: "Clipping",
|
|
60
90
|
open: props.clippingPanelOpen,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
numSlicesLoaded: props.numSlicesLoaded,
|
|
69
|
-
numScenes: numScenes,
|
|
70
|
-
region: region,
|
|
71
|
-
slices: slice,
|
|
72
|
-
numTimesteps: numTimesteps,
|
|
73
|
-
time: time,
|
|
74
|
-
scene: scene,
|
|
75
|
-
playControls: props.playControls,
|
|
76
|
-
playingAxis: props.playingAxis
|
|
77
|
-
})), renderOverlay());
|
|
91
|
+
onPageChange: function onPageChange(open) {
|
|
92
|
+
var _props$onClippingPane;
|
|
93
|
+
return (_props$onClippingPane = props.onClippingPanelOpenChange) === null || _props$onClippingPane === void 0 ? void 0 : _props$onClippingPane.call(props, open !== null);
|
|
94
|
+
},
|
|
95
|
+
height: clippingPanelTall ? CLIPPING_PANEL_HEIGHT_TALL : CLIPPING_PANEL_HEIGHT_DEFAULT,
|
|
96
|
+
contents: bottomPanelContents
|
|
97
|
+
}), renderOverlay());
|
|
78
98
|
};
|
|
79
99
|
export default ViewerWrapper;
|
|
80
100
|
var STYLES = {
|
|
@@ -110,6 +110,8 @@ function ControlPanel(props) {
|
|
|
110
110
|
icon: typeof icon === "string" ? icon : undefined
|
|
111
111
|
}, _typeof(icon) === "object" && icon));
|
|
112
112
|
};
|
|
113
|
+
|
|
114
|
+
// TODO this can just be a component...?
|
|
113
115
|
var renderAdvancedSettings = function renderAdvancedSettings() {
|
|
114
116
|
var items = [{
|
|
115
117
|
key: 0,
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
3
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
4
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
5
|
+
import React, { useEffect } from "react";
|
|
6
|
+
import { activeAxisMap } from "../../shared/types";
|
|
7
|
+
import { DimensionSliderRow, IndexSliderRow, PlaySliderRow } from "./SliderRows";
|
|
8
|
+
var AXES = ["x", "y", "z"];
|
|
9
|
+
export var AxisClipSliders = function AxisClipSliders(props) {
|
|
10
|
+
var activeAxis = activeAxisMap[props.mode];
|
|
11
|
+
var pauseOnInput = function pauseOnInput(axis) {
|
|
12
|
+
// Pause on slider input unless user is scrubbing along the playing axis (playback is held while this is happening)
|
|
13
|
+
if (!props.playControls.playHolding || props.playingAxis !== axis) {
|
|
14
|
+
props.playControls.pause();
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var updateRegion = function updateRegion(axis, minval, maxval) {
|
|
18
|
+
pauseOnInput(axis);
|
|
19
|
+
var changeViewerSetting = props.changeViewerSetting,
|
|
20
|
+
numSlices = props.numSlices;
|
|
21
|
+
// get a value from 0-1
|
|
22
|
+
var max = numSlices[axis];
|
|
23
|
+
var start = minval / max;
|
|
24
|
+
var end = maxval / max;
|
|
25
|
+
changeViewerSetting("region", _defineProperty({}, axis, [start, end]));
|
|
26
|
+
};
|
|
27
|
+
var updateSlice = function updateSlice(axis, slice) {
|
|
28
|
+
pauseOnInput(axis);
|
|
29
|
+
props.changeViewerSetting("slice", _defineProperty({}, axis, slice / props.numSlices[axis]));
|
|
30
|
+
};
|
|
31
|
+
var updateTime = function updateTime(time) {
|
|
32
|
+
pauseOnInput("t");
|
|
33
|
+
props.changeViewerSetting("time", time);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Pause when view mode or volume size has changed
|
|
37
|
+
useEffect(function () {
|
|
38
|
+
return props.playControls.pause();
|
|
39
|
+
}, [props.mode, props.image, props.playControls]);
|
|
40
|
+
var handlePlayPause = function handlePlayPause(axis, willPlay) {
|
|
41
|
+
if (willPlay) {
|
|
42
|
+
props.playControls.play(axis);
|
|
43
|
+
} else {
|
|
44
|
+
props.playControls.pause();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var create2dAxisSlider = function create2dAxisSlider(axis) {
|
|
48
|
+
var numSlices = props.numSlices[axis];
|
|
49
|
+
var numSlicesLoaded = props.numSlicesLoaded[axis];
|
|
50
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
51
|
+
key: axis + numSlices + numSlicesLoaded,
|
|
52
|
+
className: "slider-row slider-".concat(axis)
|
|
53
|
+
}, /*#__PURE__*/React.createElement(PlaySliderRow, {
|
|
54
|
+
label: axis.toUpperCase(),
|
|
55
|
+
val: Math.round(props.slices[axis] * numSlices),
|
|
56
|
+
max: numSlices,
|
|
57
|
+
onChange: function onChange(val) {
|
|
58
|
+
return updateSlice(axis, val);
|
|
59
|
+
},
|
|
60
|
+
onStart: function onStart() {
|
|
61
|
+
return props.playControls.startHold(axis);
|
|
62
|
+
},
|
|
63
|
+
onEnd: function onEnd() {
|
|
64
|
+
return props.playControls.endHold();
|
|
65
|
+
},
|
|
66
|
+
playing: props.playingAxis === axis,
|
|
67
|
+
onTogglePlayback: function onTogglePlayback(willPlay) {
|
|
68
|
+
return handlePlayPause(axis, willPlay);
|
|
69
|
+
},
|
|
70
|
+
updateWhileSliding: numSlices === numSlicesLoaded
|
|
71
|
+
}));
|
|
72
|
+
};
|
|
73
|
+
var create3dAxisSlider = function create3dAxisSlider(axis) {
|
|
74
|
+
var numSlices = props.numSlices[axis];
|
|
75
|
+
if (numSlices === 1) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
var region = props.region[axis];
|
|
79
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
80
|
+
key: axis + numSlices + "3d",
|
|
81
|
+
className: "slider-row slider-".concat(axis)
|
|
82
|
+
}, /*#__PURE__*/React.createElement(DimensionSliderRow, {
|
|
83
|
+
label: axis.toUpperCase(),
|
|
84
|
+
val: [Math.round(region[0] * numSlices), Math.round(region[1] * numSlices)],
|
|
85
|
+
min: 0,
|
|
86
|
+
max: numSlices,
|
|
87
|
+
onSlide: function onSlide(values) {
|
|
88
|
+
return updateRegion(axis, values[0], values[1]);
|
|
89
|
+
},
|
|
90
|
+
onStart: function onStart() {
|
|
91
|
+
return props.playControls.startHold(axis);
|
|
92
|
+
},
|
|
93
|
+
onEnd: function onEnd() {
|
|
94
|
+
return props.playControls.endHold();
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
};
|
|
98
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
99
|
+
className: activeAxis ? "clip-sliders clip-sliders-2d" : "clip-sliders"
|
|
100
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
101
|
+
className: "slider-group"
|
|
102
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
103
|
+
className: "slider-group-title"
|
|
104
|
+
}, "ROI"), /*#__PURE__*/React.createElement("span", {
|
|
105
|
+
className: "slider-group-rows"
|
|
106
|
+
}, activeAxis ? create2dAxisSlider(activeAxis) : AXES.map(create3dAxisSlider))), props.numTimesteps > 1 && /*#__PURE__*/React.createElement("span", {
|
|
107
|
+
className: "slider-group"
|
|
108
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
109
|
+
className: "slider-group-title"
|
|
110
|
+
}, "Time"), /*#__PURE__*/React.createElement("span", {
|
|
111
|
+
className: "slider-group-rows"
|
|
112
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
113
|
+
className: "slider-row slider-t"
|
|
114
|
+
}, /*#__PURE__*/React.createElement(PlaySliderRow, {
|
|
115
|
+
label: "",
|
|
116
|
+
val: props.time,
|
|
117
|
+
max: props.numTimesteps,
|
|
118
|
+
playing: props.playingAxis === "t",
|
|
119
|
+
onTogglePlayback: function onTogglePlayback(willPlay) {
|
|
120
|
+
return handlePlayPause("t", willPlay);
|
|
121
|
+
},
|
|
122
|
+
onChange: function onChange(time) {
|
|
123
|
+
return updateTime(time);
|
|
124
|
+
},
|
|
125
|
+
onStart: function onStart() {
|
|
126
|
+
return props.playControls.startHold("t");
|
|
127
|
+
},
|
|
128
|
+
onEnd: function onEnd() {
|
|
129
|
+
return props.playControls.endHold();
|
|
130
|
+
}
|
|
131
|
+
})))), props.numScenes > 1 && /*#__PURE__*/React.createElement("span", {
|
|
132
|
+
className: "slider-group"
|
|
133
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
134
|
+
className: "slider-group-title"
|
|
135
|
+
}, "Scene"), /*#__PURE__*/React.createElement("span", {
|
|
136
|
+
className: "slider-group-rows"
|
|
137
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
138
|
+
className: "slider-row slider-scene"
|
|
139
|
+
}, /*#__PURE__*/React.createElement(IndexSliderRow, {
|
|
140
|
+
label: "",
|
|
141
|
+
val: props.scene,
|
|
142
|
+
max: props.numScenes,
|
|
143
|
+
onChange: function onChange(scene) {
|
|
144
|
+
props.changeViewerSetting("scene", scene);
|
|
145
|
+
props.changeViewerSetting("useExactScaleLevel", false);
|
|
146
|
+
}
|
|
147
|
+
})))));
|
|
148
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
8
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
10
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
11
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
12
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
13
|
+
import { Button, Space } from "antd";
|
|
14
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
15
|
+
import { ViewMode } from "../../shared/enums";
|
|
16
|
+
import { applyMatrix, defaultOrientedCamera, getRotationAngles, rotationMatrix, useCameraCallback } from "../../shared/utils/camera";
|
|
17
|
+
import { select, useViewerState } from "../../state/store";
|
|
18
|
+
import { DimensionSliderRow } from "./SliderRows";
|
|
19
|
+
|
|
20
|
+
/** Convert an angle from degrees to radians */
|
|
21
|
+
var toRadians = function toRadians(deg) {
|
|
22
|
+
return deg * (Math.PI / 180);
|
|
23
|
+
};
|
|
24
|
+
/** Convert an angle from radians to degrees */
|
|
25
|
+
var toDegrees = function toDegrees(rad) {
|
|
26
|
+
return rad * (180 / Math.PI);
|
|
27
|
+
};
|
|
28
|
+
export var RotationSliders = function RotationSliders(_ref) {
|
|
29
|
+
var view3d = _ref.view3d,
|
|
30
|
+
disable = _ref.disable;
|
|
31
|
+
var _useState = useState(function () {
|
|
32
|
+
return getRotationAngles(view3d.getCameraState());
|
|
33
|
+
}),
|
|
34
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
35
|
+
rotation = _useState2[0],
|
|
36
|
+
setRotation = _useState2[1];
|
|
37
|
+
var autorotate = useViewerState(select("autorotate"));
|
|
38
|
+
var viewMode = useViewerState(select("viewMode"));
|
|
39
|
+
var changeViewerSetting = useViewerState(select("changeViewerSetting"));
|
|
40
|
+
|
|
41
|
+
// Set to `true` when user interacts with this component, `false` when they click on the canvas or start autorotate.
|
|
42
|
+
// While `hasControlRef.current === true`, this component's state propagates *down* to `view3d`
|
|
43
|
+
// While `hasControlRef.current === false`, `view3d`'s camera state is synced *up* to this component.
|
|
44
|
+
// TODO are there any other events besides the above that cause the volume to rotate? Ideally this would be an event
|
|
45
|
+
// that `View3d` would let us track directly.
|
|
46
|
+
var hasControlRef = useRef(false);
|
|
47
|
+
var handleRotate = useCallback(function (axis, deg) {
|
|
48
|
+
hasControlRef.current = true;
|
|
49
|
+
if (autorotate) {
|
|
50
|
+
changeViewerSetting("autorotate", false);
|
|
51
|
+
}
|
|
52
|
+
setRotation(function (current) {
|
|
53
|
+
return _objectSpread(_objectSpread({}, current), {}, _defineProperty({}, axis, toRadians(deg)));
|
|
54
|
+
});
|
|
55
|
+
}, [autorotate, changeViewerSetting]);
|
|
56
|
+
var handleJump = useCallback(function (x, y, z) {
|
|
57
|
+
hasControlRef.current = true;
|
|
58
|
+
setRotation({
|
|
59
|
+
x: x,
|
|
60
|
+
y: y,
|
|
61
|
+
z: z
|
|
62
|
+
});
|
|
63
|
+
}, []);
|
|
64
|
+
var jumpXMinus = useCallback(function () {
|
|
65
|
+
return handleJump(0, -Math.PI / 2, 0);
|
|
66
|
+
}, [handleJump]);
|
|
67
|
+
var jumpXPlus = useCallback(function () {
|
|
68
|
+
return handleJump(0, Math.PI / 2, 0);
|
|
69
|
+
}, [handleJump]);
|
|
70
|
+
var jumpYMinus = useCallback(function () {
|
|
71
|
+
return handleJump(Math.PI / 2, 0, -Math.PI / 2);
|
|
72
|
+
}, [handleJump]);
|
|
73
|
+
var jumpYPlus = useCallback(function () {
|
|
74
|
+
return handleJump(-Math.PI / 2, 0, -Math.PI / 2);
|
|
75
|
+
}, [handleJump]);
|
|
76
|
+
var jumpZMinus = useCallback(function () {
|
|
77
|
+
return handleJump(Math.PI, 0, -Math.PI);
|
|
78
|
+
}, [handleJump]);
|
|
79
|
+
var jumpZPlus = useCallback(function () {
|
|
80
|
+
return handleJump(0, 0, 0);
|
|
81
|
+
}, [handleJump]);
|
|
82
|
+
|
|
83
|
+
// Take away control when autorotate is enabled
|
|
84
|
+
useEffect(function () {
|
|
85
|
+
if (autorotate) {
|
|
86
|
+
hasControlRef.current = false;
|
|
87
|
+
}
|
|
88
|
+
}, [autorotate]);
|
|
89
|
+
var rotateCameraTo = useCameraCallback(function (state, rotation) {
|
|
90
|
+
var matrix = rotationMatrix(rotation.x, rotation.y, rotation.z);
|
|
91
|
+
return applyMatrix(defaultOrientedCamera(state), matrix);
|
|
92
|
+
}, view3d);
|
|
93
|
+
|
|
94
|
+
// Sync down rotation state while this component is "in control."
|
|
95
|
+
useEffect(function () {
|
|
96
|
+
if (hasControlRef.current && viewMode === ViewMode.threeD) {
|
|
97
|
+
rotateCameraTo(rotation);
|
|
98
|
+
}
|
|
99
|
+
}, [rotateCameraTo, rotation, viewMode]);
|
|
100
|
+
|
|
101
|
+
// Set up event listeners on mount.
|
|
102
|
+
useEffect(function () {
|
|
103
|
+
// TODO this is *extremely brittle*: setting this clears away any other listener for render events.
|
|
104
|
+
// At time of writing, `setOnRenderCallback` appears not to be used anywhere else in either this package or
|
|
105
|
+
// vole-core, but that could change at any time.
|
|
106
|
+
// Ideally `View3d` would have an `addEventListener`/`removeEventListener` model.
|
|
107
|
+
view3d.setOnRenderCallback(function () {
|
|
108
|
+
if (!hasControlRef.current) {
|
|
109
|
+
setRotation(getRotationAngles(view3d.getCameraState()));
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
var clickListener = function clickListener() {
|
|
113
|
+
return hasControlRef.current = false;
|
|
114
|
+
};
|
|
115
|
+
view3d.getDOMElement().addEventListener("mousedown", clickListener);
|
|
116
|
+
return function () {
|
|
117
|
+
return view3d.getDOMElement().removeEventListener("mousedown", clickListener);
|
|
118
|
+
};
|
|
119
|
+
}, [view3d]);
|
|
120
|
+
var createRotateSlider = function createRotateSlider(axis) {
|
|
121
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
122
|
+
key: "".concat(axis, "-rotate"),
|
|
123
|
+
className: "slider-row slider-".concat(axis)
|
|
124
|
+
}, /*#__PURE__*/React.createElement(DimensionSliderRow, {
|
|
125
|
+
label: axis.toUpperCase(),
|
|
126
|
+
val: [toDegrees(rotation[axis])],
|
|
127
|
+
min: -180,
|
|
128
|
+
max: 180,
|
|
129
|
+
hideMax: true,
|
|
130
|
+
onSlide: function onSlide(_ref2) {
|
|
131
|
+
var _ref3 = _slicedToArray(_ref2, 1),
|
|
132
|
+
deg = _ref3[0];
|
|
133
|
+
return handleRotate(axis, deg);
|
|
134
|
+
},
|
|
135
|
+
unitSymbol: "\xB0"
|
|
136
|
+
}));
|
|
137
|
+
};
|
|
138
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
139
|
+
className: "clip-sliders clip-sliders-2d"
|
|
140
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
141
|
+
className: "slider-group"
|
|
142
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
143
|
+
className: "slider-group-title"
|
|
144
|
+
}, "Rotate"), disable ? /*#__PURE__*/React.createElement("span", {
|
|
145
|
+
className: "axis-slider-container"
|
|
146
|
+
}, /*#__PURE__*/React.createElement("i", null, "Unavailable in 2d mode")) : /*#__PURE__*/React.createElement("span", {
|
|
147
|
+
className: "slider-group-rows"
|
|
148
|
+
}, createRotateSlider("x"), createRotateSlider("y"), createRotateSlider("z"))), !disable && /*#__PURE__*/React.createElement("span", {
|
|
149
|
+
className: "slider-group"
|
|
150
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
151
|
+
className: "slider-group-title group-title-extra"
|
|
152
|
+
}, "Jump to"), /*#__PURE__*/React.createElement("span", {
|
|
153
|
+
className: "slider-group-rows"
|
|
154
|
+
}, /*#__PURE__*/React.createElement(Space.Compact, null, /*#__PURE__*/React.createElement(Button, {
|
|
155
|
+
onClick: jumpXMinus
|
|
156
|
+
}, "-X"), /*#__PURE__*/React.createElement(Button, {
|
|
157
|
+
onClick: jumpXPlus
|
|
158
|
+
}, "+X"), /*#__PURE__*/React.createElement(Button, {
|
|
159
|
+
onClick: jumpYMinus
|
|
160
|
+
}, "-Y"), /*#__PURE__*/React.createElement(Button, {
|
|
161
|
+
onClick: jumpYPlus
|
|
162
|
+
}, "+Y"), /*#__PURE__*/React.createElement(Button, {
|
|
163
|
+
onClick: jumpZMinus
|
|
164
|
+
}, "-Z"), /*#__PURE__*/React.createElement(Button, {
|
|
165
|
+
onClick: jumpZPlus
|
|
166
|
+
}, "+Z")))));
|
|
167
|
+
};
|