@geode/opengeodeweb-front 10.18.2 → 10.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/FeedBack/ErrorBanner.vue +1 -0
- package/app/components/GlassCard.vue +1 -0
- package/app/components/HybridRenderingView.vue +2 -0
- package/app/components/HybridViewerTooltip.vue +216 -0
- package/app/components/InfraConnected.vue +1 -0
- package/app/components/Inspector/InspectionButton.vue +1 -0
- package/app/components/Viewer/Options/Sliders/Size.vue +1 -0
- package/app/components/Viewer/Options/Sliders/Width.vue +1 -0
- package/app/composables/run_function_when_microservices_connected.js +1 -0
- package/app/stores/hybrid_viewer.js +38 -34
- package/app/stores/treeview.js +1 -0
- package/commitlint.config.js +1 -0
- package/internal/stores/hybrid_viewer.js +40 -4
- package/internal/stores/hybrid_viewer_highlight.js +113 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import HybridViewerTooltip from "@ogw_front/components/HybridViewerTooltip";
|
|
2
3
|
import ViewToolbar from "@ogw_front/components/ViewToolbar";
|
|
3
4
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
4
5
|
import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
@@ -60,6 +61,7 @@ async function handleClick(event) {
|
|
|
60
61
|
<div data-testid="hybridViewer" class="fill-height" style="position: relative; height: 100%">
|
|
61
62
|
<ViewToolbar />
|
|
62
63
|
<slot name="ui"></slot>
|
|
64
|
+
<HybridViewerTooltip :container-width="elementWidth" :container-height="elementHeight" />
|
|
63
65
|
<v-col
|
|
64
66
|
class="pa-0"
|
|
65
67
|
ref="viewer"
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import GlassCard from "@ogw_front/components/GlassCard";
|
|
3
|
+
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
4
|
+
|
|
5
|
+
const TOOLTIP_SCREEN_MARGIN = 10;
|
|
6
|
+
|
|
7
|
+
const { containerWidth, containerHeight } = defineProps({
|
|
8
|
+
containerWidth: {
|
|
9
|
+
type: Number,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
containerHeight: {
|
|
13
|
+
type: Number,
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const hybridViewerStore = useHybridViewerStore();
|
|
19
|
+
|
|
20
|
+
const tooltipRef = useTemplateRef("tooltip");
|
|
21
|
+
const { width: tooltipWidth, height: tooltipHeight } = useElementSize(tooltipRef);
|
|
22
|
+
|
|
23
|
+
const tooltipStyle = computed(() => {
|
|
24
|
+
if (!hybridViewerStore.hoverData) {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
const mouseX = hybridViewerStore.hoverPosition.x;
|
|
28
|
+
const mouseY = hybridViewerStore.hoverPosition.y;
|
|
29
|
+
const measuredTooltipWidth = tooltipWidth.value;
|
|
30
|
+
const measuredTooltipHeight = tooltipHeight.value;
|
|
31
|
+
const tooltipOffsetGap = 20;
|
|
32
|
+
|
|
33
|
+
let left = mouseX + tooltipOffsetGap;
|
|
34
|
+
if (left + measuredTooltipWidth > containerWidth) {
|
|
35
|
+
left = mouseX - measuredTooltipWidth - tooltipOffsetGap;
|
|
36
|
+
}
|
|
37
|
+
if (left < 0) {
|
|
38
|
+
left = TOOLTIP_SCREEN_MARGIN;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let top = mouseY - measuredTooltipHeight - tooltipOffsetGap;
|
|
42
|
+
if (top < 0) {
|
|
43
|
+
top = mouseY + tooltipOffsetGap;
|
|
44
|
+
}
|
|
45
|
+
if (top + measuredTooltipHeight > containerHeight) {
|
|
46
|
+
top = containerHeight - measuredTooltipHeight - TOOLTIP_SCREEN_MARGIN;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
left: `${left}px`,
|
|
51
|
+
top: `${top}px`,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const originalIndex = computed(() => {
|
|
56
|
+
const attributes = hybridViewerStore.hoverData?.attributes || {};
|
|
57
|
+
const originalId =
|
|
58
|
+
attributes.vtkOriginalCellIds ??
|
|
59
|
+
attributes.vtkOriginalPointIds ??
|
|
60
|
+
hybridViewerStore.hoverData?.pickedId;
|
|
61
|
+
if (originalId === undefined) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
return Math.floor(Number(originalId));
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const hasOtherAttributes = computed(() => {
|
|
68
|
+
const attributes = hybridViewerStore.hoverData?.attributes || {};
|
|
69
|
+
return Object.keys(attributes).some(
|
|
70
|
+
(key) => key !== "vtkOriginalCellIds" && key !== "vtkOriginalPointIds",
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
function capitalize(val) {
|
|
75
|
+
if (!val) {
|
|
76
|
+
return "";
|
|
77
|
+
}
|
|
78
|
+
const spaced = val.replaceAll("_", " ");
|
|
79
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function formatAttributeValue(val) {
|
|
83
|
+
if (Array.isArray(val)) {
|
|
84
|
+
const formattedValues = val.map((value) => {
|
|
85
|
+
if (typeof value === "number") {
|
|
86
|
+
if (Number.isInteger(value)) {
|
|
87
|
+
return String(value);
|
|
88
|
+
}
|
|
89
|
+
return Number(value).toFixed(3);
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
});
|
|
93
|
+
return `[ ${formattedValues.join(", ")} ]`;
|
|
94
|
+
}
|
|
95
|
+
if (typeof val === "number") {
|
|
96
|
+
return Number.isInteger(val) ? String(val) : Number(val).toFixed(4);
|
|
97
|
+
}
|
|
98
|
+
return val;
|
|
99
|
+
}
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
<template>
|
|
103
|
+
<GlassCard
|
|
104
|
+
v-if="hybridViewerStore.hoverData"
|
|
105
|
+
ref="tooltip"
|
|
106
|
+
variant="panel"
|
|
107
|
+
padding="pa-3"
|
|
108
|
+
rounded="lg"
|
|
109
|
+
class="floating-tooltip"
|
|
110
|
+
:style="tooltipStyle"
|
|
111
|
+
>
|
|
112
|
+
<v-container fluid class="pa-0 tooltip-container">
|
|
113
|
+
<v-row no-gutters class="flex-column ga-1">
|
|
114
|
+
<v-col>
|
|
115
|
+
<span class="tooltip-label">Name:</span>
|
|
116
|
+
<span class="tooltip-value">
|
|
117
|
+
{{
|
|
118
|
+
hybridViewerStore.hoverData.component?.name ||
|
|
119
|
+
hybridViewerStore.hoverData.component?.id ||
|
|
120
|
+
hybridViewerStore.hoverData.blockName ||
|
|
121
|
+
hybridViewerStore.hoverData.modelName ||
|
|
122
|
+
`${capitalize(hybridViewerStore.hoverData.fieldType.toLowerCase())} #${hybridViewerStore.hoverData.pickedId}`
|
|
123
|
+
}}
|
|
124
|
+
</span>
|
|
125
|
+
</v-col>
|
|
126
|
+
<v-col>
|
|
127
|
+
<span class="tooltip-label">Id:</span>
|
|
128
|
+
<span class="tooltip-value-dim font-mono">
|
|
129
|
+
{{ hybridViewerStore.hoverData.component?.id || hybridViewerStore.hoverData.modelId }}
|
|
130
|
+
</span>
|
|
131
|
+
</v-col>
|
|
132
|
+
<v-col v-if="originalIndex !== undefined">
|
|
133
|
+
<span class="tooltip-label">Index:</span>
|
|
134
|
+
<span class="tooltip-value font-mono">
|
|
135
|
+
{{ originalIndex }}
|
|
136
|
+
</span>
|
|
137
|
+
</v-col>
|
|
138
|
+
<v-col v-if="hybridViewerStore.hoverData.component?.type">
|
|
139
|
+
<span class="tooltip-label">Type:</span>
|
|
140
|
+
<span class="tooltip-value">
|
|
141
|
+
{{ hybridViewerStore.hoverData.component.type }}
|
|
142
|
+
</span>
|
|
143
|
+
</v-col>
|
|
144
|
+
</v-row>
|
|
145
|
+
<template v-if="hasOtherAttributes">
|
|
146
|
+
<v-divider class="my-2" opacity="0.15" />
|
|
147
|
+
<v-row no-gutters class="flex-column ga-1">
|
|
148
|
+
<v-col
|
|
149
|
+
v-if="hybridViewerStore.hoverData.attributes.coordinates"
|
|
150
|
+
class="d-flex justify-space-between ga-3"
|
|
151
|
+
>
|
|
152
|
+
<span class="tooltip-label">Position:</span>
|
|
153
|
+
<span class="tooltip-value font-mono">
|
|
154
|
+
[ {{ Number(hybridViewerStore.hoverData.attributes.coordinates[0]).toFixed(3) }},
|
|
155
|
+
{{ Number(hybridViewerStore.hoverData.attributes.coordinates[1]).toFixed(3) }},
|
|
156
|
+
{{ Number(hybridViewerStore.hoverData.attributes.coordinates[2]).toFixed(3) }} ]
|
|
157
|
+
</span>
|
|
158
|
+
</v-col>
|
|
159
|
+
<template v-for="(val, name) in hybridViewerStore.hoverData.attributes" :key="name">
|
|
160
|
+
<v-col
|
|
161
|
+
v-if="
|
|
162
|
+
name !== 'coordinates' &&
|
|
163
|
+
name !== 'vtkOriginalCellIds' &&
|
|
164
|
+
name !== 'vtkOriginalPointIds'
|
|
165
|
+
"
|
|
166
|
+
class="d-flex justify-space-between ga-3"
|
|
167
|
+
>
|
|
168
|
+
<span class="tooltip-label">{{ capitalize(name) }}:</span>
|
|
169
|
+
<span class="tooltip-value font-mono">
|
|
170
|
+
{{ formatAttributeValue(val) }}
|
|
171
|
+
</span>
|
|
172
|
+
</v-col>
|
|
173
|
+
</template>
|
|
174
|
+
</v-row>
|
|
175
|
+
</template>
|
|
176
|
+
</v-container>
|
|
177
|
+
</GlassCard>
|
|
178
|
+
</template>
|
|
179
|
+
|
|
180
|
+
<style scoped>
|
|
181
|
+
.floating-tooltip {
|
|
182
|
+
position: absolute;
|
|
183
|
+
pointer-events: none;
|
|
184
|
+
z-index: 10000;
|
|
185
|
+
min-width: 200px;
|
|
186
|
+
max-width: 450px;
|
|
187
|
+
transition: opacity 0.15s ease;
|
|
188
|
+
}
|
|
189
|
+
.font-mono {
|
|
190
|
+
font-family: monospace !important;
|
|
191
|
+
}
|
|
192
|
+
.tooltip-container {
|
|
193
|
+
min-width: 220px;
|
|
194
|
+
color: white;
|
|
195
|
+
font-size: 0.875rem;
|
|
196
|
+
}
|
|
197
|
+
.tooltip-label {
|
|
198
|
+
color: #bdbdbd;
|
|
199
|
+
font-weight: bold;
|
|
200
|
+
}
|
|
201
|
+
.tooltip-value {
|
|
202
|
+
color: #a7ffeb;
|
|
203
|
+
font-weight: 500;
|
|
204
|
+
}
|
|
205
|
+
.tooltip-value-dim {
|
|
206
|
+
color: #eeeeee;
|
|
207
|
+
font-size: 0.75rem !important;
|
|
208
|
+
}
|
|
209
|
+
.tooltip-label + .tooltip-value,
|
|
210
|
+
.tooltip-label + .tooltip-value-dim {
|
|
211
|
+
margin-left: 4px;
|
|
212
|
+
}
|
|
213
|
+
.justify-space-between > .tooltip-value {
|
|
214
|
+
margin-left: 0 !important;
|
|
215
|
+
}
|
|
216
|
+
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
3
3
|
import { useGeodeStore } from "@ogw_front/stores/geode";
|
|
4
|
+
|
|
4
5
|
const schema = schemas.opengeodeweb_back.inspect_file;
|
|
5
6
|
|
|
6
7
|
const emit = defineEmits(["update_values", "increment_step", "decrement_step"]);
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACTOR_COLOR,
|
|
3
3
|
BACKGROUND_COLOR,
|
|
4
|
-
HOVER_THROTTLE_MS,
|
|
5
4
|
WHEEL_TIME_OUT_MS,
|
|
6
5
|
computeAverageBrightness,
|
|
7
6
|
performAddItem,
|
|
7
|
+
performClear,
|
|
8
8
|
performClearHoverHighlight,
|
|
9
9
|
performClickPicking,
|
|
10
|
-
|
|
10
|
+
performRemoveItem,
|
|
11
11
|
performSetContainer,
|
|
12
|
+
performSetVisibility,
|
|
12
13
|
performSetZScaling,
|
|
13
14
|
} from "@ogw_internal/stores/hybrid_viewer";
|
|
14
15
|
import {
|
|
@@ -19,6 +20,10 @@ import {
|
|
|
19
20
|
performSetCamera,
|
|
20
21
|
performSyncRemoteCamera,
|
|
21
22
|
} from "@ogw_internal/stores/hybrid_viewer_camera";
|
|
23
|
+
import {
|
|
24
|
+
createClearHoverData,
|
|
25
|
+
createHoverHighlight,
|
|
26
|
+
} from "@ogw_internal/stores/hybrid_viewer_highlight";
|
|
22
27
|
import { newInstance as vtkActor } from "@kitware/vtk.js/Rendering/Core/Actor";
|
|
23
28
|
import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
|
|
24
29
|
import { newInstance as vtkMapper } from "@kitware/vtk.js/Rendering/Core/Mapper";
|
|
@@ -30,6 +35,7 @@ import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
|
30
35
|
|
|
31
36
|
import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";
|
|
32
37
|
|
|
38
|
+
// oxlint-disable max-lines-per-function max-statements
|
|
33
39
|
export const useHybridViewerStore = defineStore("hybridViewer", () => {
|
|
34
40
|
const dataStore = useDataStore();
|
|
35
41
|
const hybridDb = reactive({});
|
|
@@ -41,6 +47,8 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
|
|
|
41
47
|
const is_picking = ref(false);
|
|
42
48
|
const is_hover_highlight = ref(false);
|
|
43
49
|
const hover_highlight_field_type = ref("CELL");
|
|
50
|
+
const hoverData = ref(undefined);
|
|
51
|
+
const hoverPosition = ref({ x: 0, y: 0 });
|
|
44
52
|
const zScale = ref(1);
|
|
45
53
|
let imageStyle = undefined;
|
|
46
54
|
let viewStream = undefined;
|
|
@@ -106,20 +114,14 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
|
|
|
106
114
|
}
|
|
107
115
|
|
|
108
116
|
function removeItem(id) {
|
|
109
|
-
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
genericRenderWindow.value.getRenderer().removeActor(hybridDb[id].actor);
|
|
113
|
-
genericRenderWindow.value.getRenderWindow().render();
|
|
114
|
-
delete hybridDb[id];
|
|
117
|
+
performRemoveItem(id, { genericRenderWindow: genericRenderWindow.value, hybridDb });
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
function setVisibility(id, visibility) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
genericRenderWindow.value.getRenderWindow().render();
|
|
121
|
+
performSetVisibility(id, visibility, {
|
|
122
|
+
genericRenderWindow: genericRenderWindow.value,
|
|
123
|
+
hybridDb,
|
|
124
|
+
});
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
async function setZScaling(z_scale) {
|
|
@@ -184,20 +186,27 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
|
|
|
184
186
|
return viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.render);
|
|
185
187
|
}
|
|
186
188
|
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
189
|
+
const hoverTimeoutRef = ref(undefined);
|
|
190
|
+
const currentHoverId = ref(undefined);
|
|
191
|
+
|
|
192
|
+
const clearHoverData = createClearHoverData(hoverTimeoutRef, hoverData, currentHoverId);
|
|
193
|
+
|
|
194
|
+
const hoverHighlight = createHoverHighlight({
|
|
195
|
+
genericRenderWindow,
|
|
196
|
+
is_hover_highlight,
|
|
197
|
+
viewerStore,
|
|
198
|
+
viewer_schemas,
|
|
199
|
+
hover_highlight_field_type,
|
|
200
|
+
hybridDb,
|
|
201
|
+
hoverData,
|
|
202
|
+
hoverPosition,
|
|
203
|
+
currentHoverId,
|
|
204
|
+
hoverTimeoutRef,
|
|
205
|
+
clearHoverData,
|
|
206
|
+
});
|
|
199
207
|
|
|
200
208
|
function clearHoverHighlight() {
|
|
209
|
+
clearHoverData();
|
|
201
210
|
performClearHoverHighlight({
|
|
202
211
|
viewerStore,
|
|
203
212
|
viewer_schemas,
|
|
@@ -220,7 +229,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
|
|
|
220
229
|
viewerStore,
|
|
221
230
|
viewer_schemas,
|
|
222
231
|
syncRemoteCamera,
|
|
223
|
-
|
|
232
|
+
hoverHighlight,
|
|
224
233
|
wheelTimeoutMs: WHEEL_TIME_OUT_MS,
|
|
225
234
|
wheelEventEndTimeout,
|
|
226
235
|
wheelTimeoutSetter: (timeout) => (wheelEventEndTimeout = timeout),
|
|
@@ -266,14 +275,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
|
|
|
266
275
|
}
|
|
267
276
|
|
|
268
277
|
function clear() {
|
|
269
|
-
|
|
270
|
-
for (const actor of renderer.getActors()) {
|
|
271
|
-
renderer.removeActor(actor);
|
|
272
|
-
}
|
|
273
|
-
genericRenderWindow.value.getRenderWindow().render();
|
|
274
|
-
for (const id of Object.keys(hybridDb)) {
|
|
275
|
-
delete hybridDb[id];
|
|
276
|
-
}
|
|
278
|
+
performClear({ genericRenderWindow: genericRenderWindow.value, hybridDb });
|
|
277
279
|
}
|
|
278
280
|
|
|
279
281
|
return {
|
|
@@ -297,6 +299,8 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
|
|
|
297
299
|
is_hover_highlight,
|
|
298
300
|
hover_highlight_field_type,
|
|
299
301
|
clearHoverHighlight,
|
|
302
|
+
hoverData,
|
|
303
|
+
hoverPosition,
|
|
300
304
|
clear,
|
|
301
305
|
exportStores,
|
|
302
306
|
importStores,
|
package/app/stores/treeview.js
CHANGED
|
@@ -3,6 +3,7 @@ import { defineStore } from "pinia";
|
|
|
3
3
|
import { ref, toRaw, watch } from "vue";
|
|
4
4
|
import { compareSelections } from "@ogw_front/utils/treeview";
|
|
5
5
|
import { database } from "@ogw_internal/database/database";
|
|
6
|
+
|
|
6
7
|
const PANEL_WIDTH = 300;
|
|
7
8
|
|
|
8
9
|
export const useTreeviewStore = defineStore("treeview", () => {
|
package/commitlint.config.js
CHANGED
|
@@ -16,6 +16,7 @@ const ACTOR_COLOR = [
|
|
|
16
16
|
];
|
|
17
17
|
const WHEEL_TIME_OUT_MS = 600;
|
|
18
18
|
const HOVER_THROTTLE_MS = 50;
|
|
19
|
+
const HOVER_TIMEOUT_MS = 500;
|
|
19
20
|
|
|
20
21
|
const SAMPLE_SIZE = 10;
|
|
21
22
|
const TOTAL_CHANNELS = 400;
|
|
@@ -112,7 +113,7 @@ function performHoverHighlight(event, options) {
|
|
|
112
113
|
}
|
|
113
114
|
const rect = container.getBoundingClientRect();
|
|
114
115
|
viewerStore.request(
|
|
115
|
-
viewer_schemas.opengeodeweb_viewer.viewer.
|
|
116
|
+
viewer_schemas.opengeodeweb_viewer.viewer.highlight,
|
|
116
117
|
{
|
|
117
118
|
x: Math.round(event.clientX - rect.left),
|
|
118
119
|
y: Math.round(rect.height - (event.clientY - rect.top)),
|
|
@@ -127,7 +128,7 @@ function performHoverHighlight(event, options) {
|
|
|
127
128
|
|
|
128
129
|
function performClearHoverHighlight(options) {
|
|
129
130
|
const { viewerStore, viewer_schemas, hover_highlight_field_type, hybridDb } = options;
|
|
130
|
-
viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.
|
|
131
|
+
viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.highlight, {
|
|
131
132
|
x: -1,
|
|
132
133
|
y: -1,
|
|
133
134
|
field_type: hover_highlight_field_type.value,
|
|
@@ -200,7 +201,7 @@ function performSetContainer(options) {
|
|
|
200
201
|
viewerStore,
|
|
201
202
|
viewer_schemas,
|
|
202
203
|
syncRemoteCamera,
|
|
203
|
-
|
|
204
|
+
hoverHighlight,
|
|
204
205
|
wheelTimeoutMs,
|
|
205
206
|
wheelEventEndTimeout,
|
|
206
207
|
wheelTimeoutSetter,
|
|
@@ -251,7 +252,7 @@ function performSetContainer(options) {
|
|
|
251
252
|
},
|
|
252
253
|
});
|
|
253
254
|
|
|
254
|
-
useEventListener(container, "mousemove",
|
|
255
|
+
useEventListener(container, "mousemove", hoverHighlight);
|
|
255
256
|
useEventListener(container, "wheel", () => {
|
|
256
257
|
is_moving.value = true;
|
|
257
258
|
if (imageStyle) {
|
|
@@ -268,11 +269,43 @@ function performSetContainer(options) {
|
|
|
268
269
|
});
|
|
269
270
|
}
|
|
270
271
|
|
|
272
|
+
function performRemoveItem(id, options) {
|
|
273
|
+
const { genericRenderWindow, hybridDb } = options;
|
|
274
|
+
if (!hybridDb[id]) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
genericRenderWindow.getRenderer().removeActor(hybridDb[id].actor);
|
|
278
|
+
genericRenderWindow.getRenderWindow().render();
|
|
279
|
+
delete hybridDb[id];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function performSetVisibility(id, visibility, options) {
|
|
283
|
+
const { genericRenderWindow, hybridDb } = options;
|
|
284
|
+
if (!hybridDb[id]) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
hybridDb[id].actor.setVisibility(visibility);
|
|
288
|
+
genericRenderWindow.getRenderWindow().render();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function performClear(options) {
|
|
292
|
+
const { genericRenderWindow, hybridDb } = options;
|
|
293
|
+
const renderer = genericRenderWindow.getRenderer();
|
|
294
|
+
for (const actor of renderer.getActors()) {
|
|
295
|
+
renderer.removeActor(actor);
|
|
296
|
+
}
|
|
297
|
+
genericRenderWindow.getRenderWindow().render();
|
|
298
|
+
for (const id of Object.keys(hybridDb)) {
|
|
299
|
+
delete hybridDb[id];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
271
303
|
export {
|
|
272
304
|
BACKGROUND_COLOR,
|
|
273
305
|
ACTOR_COLOR,
|
|
274
306
|
WHEEL_TIME_OUT_MS,
|
|
275
307
|
HOVER_THROTTLE_MS,
|
|
308
|
+
HOVER_TIMEOUT_MS,
|
|
276
309
|
computeAverageBrightness,
|
|
277
310
|
performAddItem,
|
|
278
311
|
performClearHoverHighlight,
|
|
@@ -280,4 +313,7 @@ export {
|
|
|
280
313
|
performHoverHighlight,
|
|
281
314
|
performSetContainer,
|
|
282
315
|
performSetZScaling,
|
|
316
|
+
performRemoveItem,
|
|
317
|
+
performSetVisibility,
|
|
318
|
+
performClear,
|
|
283
319
|
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { HOVER_THROTTLE_MS, HOVER_TIMEOUT_MS, performHoverHighlight } from "./hybrid_viewer";
|
|
2
|
+
import { database } from "@ogw_internal/database/database.js";
|
|
3
|
+
|
|
4
|
+
function createClearHoverData(hoverTimeoutRef, hoverData, currentHoverId) {
|
|
5
|
+
return function clearHoverData() {
|
|
6
|
+
if (hoverTimeoutRef.value) {
|
|
7
|
+
clearTimeout(hoverTimeoutRef.value);
|
|
8
|
+
hoverTimeoutRef.value = undefined;
|
|
9
|
+
}
|
|
10
|
+
hoverData.value = undefined;
|
|
11
|
+
currentHoverId.value = undefined;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function createHoverHighlight(options) {
|
|
16
|
+
const {
|
|
17
|
+
genericRenderWindow,
|
|
18
|
+
is_hover_highlight,
|
|
19
|
+
viewerStore,
|
|
20
|
+
viewer_schemas,
|
|
21
|
+
hover_highlight_field_type,
|
|
22
|
+
hybridDb,
|
|
23
|
+
hoverData,
|
|
24
|
+
hoverPosition,
|
|
25
|
+
currentHoverId,
|
|
26
|
+
hoverTimeoutRef,
|
|
27
|
+
clearHoverData,
|
|
28
|
+
} = options;
|
|
29
|
+
|
|
30
|
+
return useThrottleFn((event) => {
|
|
31
|
+
const containerElement = genericRenderWindow.value?.getContainer();
|
|
32
|
+
let relativeMousePosition = { x: 0, y: 0 };
|
|
33
|
+
if (containerElement) {
|
|
34
|
+
const containerRect = containerElement.getBoundingClientRect();
|
|
35
|
+
relativeMousePosition = {
|
|
36
|
+
x: event.clientX - containerRect.left,
|
|
37
|
+
y: event.clientY - containerRect.top,
|
|
38
|
+
};
|
|
39
|
+
} else {
|
|
40
|
+
relativeMousePosition = { x: event.clientX, y: event.clientY };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
performHoverHighlight(event, {
|
|
44
|
+
is_hover_highlight,
|
|
45
|
+
genericRenderWindow: genericRenderWindow.value,
|
|
46
|
+
viewerStore,
|
|
47
|
+
viewer_schemas,
|
|
48
|
+
hover_highlight_field_type,
|
|
49
|
+
hybridDb,
|
|
50
|
+
onResponse: async (response) => {
|
|
51
|
+
const isResponseValid =
|
|
52
|
+
response && response.id && response.picked_id !== undefined && response.picked_id !== -1;
|
|
53
|
+
if (!is_hover_highlight.value || !isResponseValid) {
|
|
54
|
+
clearHoverData();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const hoverKey = `${response.id}_${response.field_type}_${response.picked_id}`;
|
|
59
|
+
if (currentHoverId.value === hoverKey) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (hoverTimeoutRef.value) {
|
|
64
|
+
clearTimeout(hoverTimeoutRef.value);
|
|
65
|
+
hoverTimeoutRef.value = undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
hoverData.value = undefined;
|
|
69
|
+
currentHoverId.value = hoverKey;
|
|
70
|
+
|
|
71
|
+
let componentInfo = undefined;
|
|
72
|
+
let modelName = undefined;
|
|
73
|
+
|
|
74
|
+
const modelRecord = await database.data.get(response.id);
|
|
75
|
+
if (modelRecord) {
|
|
76
|
+
modelName = modelRecord.name;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (response.geode_id) {
|
|
80
|
+
const component = await database.model_components
|
|
81
|
+
.where("[id+geode_id]")
|
|
82
|
+
.equals([response.id, response.geode_id])
|
|
83
|
+
.first();
|
|
84
|
+
if (component) {
|
|
85
|
+
componentInfo = {
|
|
86
|
+
name: component.name,
|
|
87
|
+
id: component.geode_id,
|
|
88
|
+
type: component.type,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const newHoverData = {
|
|
94
|
+
modelId: response.id,
|
|
95
|
+
modelName,
|
|
96
|
+
blockName: response.geode_id,
|
|
97
|
+
pickedId: response.picked_id,
|
|
98
|
+
fieldType: response.field_type,
|
|
99
|
+
component: componentInfo,
|
|
100
|
+
attributes: response.attributes || {},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
hoverTimeoutRef.value = setTimeout(() => {
|
|
104
|
+
hoverPosition.value = relativeMousePosition;
|
|
105
|
+
hoverData.value = newHoverData;
|
|
106
|
+
hoverTimeoutRef.value = undefined;
|
|
107
|
+
}, HOVER_TIMEOUT_MS);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}, HOVER_THROTTLE_MS);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export { createClearHoverData, createHoverHighlight };
|
package/package.json
CHANGED