@geode/opengeodeweb-front 9.9.0 → 9.10.0-rc.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.
Files changed (85) hide show
  1. package/assets/viewer_svgs/edged_curve_edges.svg +67 -0
  2. package/assets/viewer_svgs/edged_curve_points.svg +95 -0
  3. package/assets/viewer_svgs/grid_2d_cells.svg +78 -0
  4. package/assets/viewer_svgs/grid_2d_edges.svg +71 -0
  5. package/assets/viewer_svgs/grid_2d_points.svg +108 -0
  6. package/assets/viewer_svgs/grid_3d_cells.svg +76 -0
  7. package/assets/viewer_svgs/grid_3d_edges.svg +72 -0
  8. package/assets/viewer_svgs/grid_3d_facets.svg +102 -0
  9. package/assets/viewer_svgs/grid_3d_points.svg +172 -0
  10. package/assets/viewer_svgs/point_set_points.svg +86 -0
  11. package/assets/viewer_svgs/solid_edges.svg +96 -0
  12. package/assets/viewer_svgs/solid_facets.svg +119 -0
  13. package/assets/viewer_svgs/solid_points.svg +134 -0
  14. package/assets/viewer_svgs/solid_polyhedra.svg +103 -0
  15. package/assets/viewer_svgs/surface_edges.svg +73 -0
  16. package/assets/viewer_svgs/surface_points.svg +115 -0
  17. package/assets/viewer_svgs/surface_triangles.svg +92 -0
  18. package/components/ContextMenu.vue +123 -0
  19. package/components/ContextMenuItem.vue +90 -0
  20. package/components/EdgedCurve/EdgesOptions.vue +14 -0
  21. package/components/EdgedCurve/PointsOptions.vue +14 -0
  22. package/components/Generic/Mesh/EdgesOptions.vue +48 -0
  23. package/components/Generic/Mesh/PointsOptions.vue +73 -0
  24. package/components/Generic/Mesh/PolygonsOptions.vue +65 -0
  25. package/components/Generic/Mesh/PolyhedraOptions.vue +58 -0
  26. package/components/Generic/Model/EdgesOptions.vue +29 -0
  27. package/components/Generic/Model/PointsOptions.vue +53 -0
  28. package/components/Grid/2D/CellsOptions.vue +15 -0
  29. package/components/Grid/2D/EdgesOptions.vue +14 -0
  30. package/components/Grid/2D/PointsOptions.vue +14 -0
  31. package/components/Grid/3D/CellsOptions.vue +15 -0
  32. package/components/Grid/3D/EdgesOptions.vue +14 -0
  33. package/components/Grid/3D/FacetsOptions.vue +15 -0
  34. package/components/Grid/3D/PointsOptions.vue +14 -0
  35. package/components/HybridRenderingView.vue +41 -0
  36. package/components/HybridSolid/EdgesOptions.vue +14 -0
  37. package/components/HybridSolid/PointsOptions.vue +14 -0
  38. package/components/HybridSolid/PolygonsOptions.vue +14 -0
  39. package/components/HybridSolid/PolyhedraOptions.vue +14 -0
  40. package/components/Options/ColorPicker.vue +25 -0
  41. package/components/Options/ColoringTypeSelector.vue +125 -0
  42. package/components/Options/PolygonAttributeSelector.vue +59 -0
  43. package/components/Options/PolyhedronAttributeSelector.vue +63 -0
  44. package/components/Options/TextureItem.vue +116 -0
  45. package/components/Options/TexturesSelector.vue +67 -0
  46. package/components/Options/VertexAttributeSelector.vue +60 -0
  47. package/components/Options/VisibilitySwitch.vue +14 -0
  48. package/components/PointSet/PointsOptions.vue +14 -0
  49. package/components/PointSet/SpecificPointsOptions.vue +74 -0
  50. package/components/PolygonalSurface/EdgesOptions.vue +14 -0
  51. package/components/PolygonalSurface/PointsOptions.vue +14 -0
  52. package/components/PolygonalSurface/PolygonsOptions.vue +14 -0
  53. package/components/Solid/EdgesOptions.vue +14 -0
  54. package/components/Solid/PointsOptions.vue +14 -0
  55. package/components/Solid/PolygonsOptions.vue +14 -0
  56. package/components/Solid/PolyhedraOptions.vue +14 -0
  57. package/components/TetrahedralSolid/TetrahedraOptions.vue +15 -0
  58. package/components/TetrahedralSolid/TrianglesOptions.vue +15 -0
  59. package/components/TriangulatedSurface/EdgesOptions.vue +14 -0
  60. package/components/TriangulatedSurface/PointsOptions.vue +14 -0
  61. package/components/TriangulatedSurface/TrianglesOptions.vue +15 -0
  62. package/components/VeaseViewToolbar.vue +107 -0
  63. package/components/Viewer/BreadCrumb.vue +61 -0
  64. package/components/Viewer/Tree/ObjectTree.vue +170 -0
  65. package/components/Viewer/TreeComponent.vue +93 -0
  66. package/components/Viewer/TreeObject.vue +100 -0
  67. package/internal_stores/data_style_state.js +18 -0
  68. package/internal_stores/mesh/edges.js +106 -0
  69. package/internal_stores/mesh/index.js +50 -0
  70. package/internal_stores/mesh/points.js +131 -0
  71. package/internal_stores/mesh/polygons.js +159 -0
  72. package/internal_stores/mesh/polyhedra.js +136 -0
  73. package/internal_stores/model/blocks.js +60 -0
  74. package/internal_stores/model/corners.js +63 -0
  75. package/internal_stores/model/edges.js +47 -0
  76. package/internal_stores/model/index.js +154 -0
  77. package/internal_stores/model/lines.js +81 -0
  78. package/internal_stores/model/points.js +61 -0
  79. package/internal_stores/model/surfaces.js +60 -0
  80. package/package.json +1 -1
  81. package/stores/data_base.js +148 -0
  82. package/stores/data_style.js +57 -0
  83. package/stores/hybrid_viewer.js +193 -0
  84. package/stores/menu.js +182 -0
  85. package/stores/treeview.js +64 -0
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <ViewerGenericMeshPointsOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="SolidPoints"
5
+ />
6
+ </template>
7
+
8
+ <script setup>
9
+ import SolidPoints from "@ogw_f/assets/viewer_svgs/solid_points.svg"
10
+
11
+ const props = defineProps({
12
+ itemProps: { type: Object, required: true },
13
+ })
14
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <ViewerGenericMeshPolygonsOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="SolidFacets"
5
+ />
6
+ </template>
7
+
8
+ <script setup>
9
+ import SolidFacets from "@ogw_f/assets/viewer_svgs/solid_facets.svg"
10
+
11
+ const props = defineProps({
12
+ itemProps: { type: Object, required: true },
13
+ })
14
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <ViewerGenericMeshPolyhedraOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="SolidPolyhedra"
5
+ />
6
+ </template>
7
+
8
+ <script setup>
9
+ import SolidPolyhedra from "@ogw_f/assets/viewer_svgs/solid_polyhedra.svg"
10
+
11
+ const props = defineProps({
12
+ itemProps: { type: Object, required: true },
13
+ })
14
+ </script>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <ViewerGenericMeshPolyhedraOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="TetrahedralSolidTetrahedra"
5
+ tooltip="Tetrahedra options"
6
+ />
7
+ </template>
8
+
9
+ <script setup>
10
+ import TetrahedralSolidTetrahedra from "@ogw_f/assets/viewer_svgs/solid_polyhedra.svg"
11
+
12
+ const props = defineProps({
13
+ itemProps: { type: Object, required: true },
14
+ })
15
+ </script>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <ViewerGenericMeshPolygonsOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="TetrahedralSolidTriangles"
5
+ tooltip="Triangles options"
6
+ />
7
+ </template>
8
+
9
+ <script setup>
10
+ import TetrahedralSolidTriangles from "@ogw_f/assets/viewer_svgs/solid_facets.svg"
11
+
12
+ const props = defineProps({
13
+ itemProps: { type: Object, required: true },
14
+ })
15
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <ViewerGenericMeshEdgesOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="SurfaceEdges"
5
+ />
6
+ </template>
7
+
8
+ <script setup>
9
+ import SurfaceEdges from "@ogw_f/assets/viewer_svgs/surface_edges.svg"
10
+
11
+ const props = defineProps({
12
+ itemProps: { type: Object, required: true },
13
+ })
14
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <ViewerGenericMeshPointsOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="TriangulatedSurfaceEdgesPoints"
5
+ />
6
+ </template>
7
+
8
+ <script setup>
9
+ import TriangulatedSurfaceEdgesPoints from "@ogw_f/assets/viewer_svgs/surface_points.svg"
10
+
11
+ const props = defineProps({
12
+ itemProps: { type: Object, required: true },
13
+ })
14
+ </script>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <ViewerGenericMeshPolygonsOptions
3
+ :itemProps="props.itemProps"
4
+ :btn_image="TriangulatedSurfaceEdgesTriangles"
5
+ tooltip="Triangles options"
6
+ />
7
+ </template>
8
+
9
+ <script setup>
10
+ import TriangulatedSurfaceEdgesTriangles from "@ogw_f/assets/viewer_svgs/surface_triangles.svg"
11
+
12
+ const props = defineProps({
13
+ itemProps: { type: Object, required: true },
14
+ })
15
+ </script>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <v-container :class="[$style.floatToolbar, 'pa-0']" width="auto">
3
+ <v-row
4
+ v-for="camera_option in camera_options"
5
+ :key="camera_option.icon"
6
+ dense
7
+ >
8
+ <v-col>
9
+ <v-btn
10
+ density="comfortable"
11
+ icon
12
+ @click.stop="camera_option.action"
13
+ v-tooltip:left="camera_option.tooltip"
14
+ >
15
+ <v-icon :icon="camera_option.icon" size="32" />
16
+ </v-btn>
17
+ </v-col>
18
+ </v-row>
19
+ </v-container>
20
+ <Screenshot :show_dialog="take_screenshot" @close="take_screenshot = false" />
21
+ <ZScaling
22
+ v-if="showZScaling"
23
+ v-model="zScale"
24
+ :width="400"
25
+ @close="handleZScalingClose"
26
+ />
27
+ </template>
28
+
29
+ <script setup>
30
+ import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"
31
+
32
+ const hybridViewerStore = useHybridViewerStore()
33
+ const take_screenshot = ref(false)
34
+ const showZScaling = ref(false)
35
+ const grid_scale = ref(false)
36
+ const zScale = ref(hybridViewerStore.zScale)
37
+
38
+ watch(
39
+ () => hybridViewerStore.zScale,
40
+ (newVal) => {
41
+ zScale.value = newVal
42
+ },
43
+ )
44
+
45
+ const handleZScalingClose = async () => {
46
+ await hybridViewerStore.setZScaling(zScale.value)
47
+ showZScaling.value = false
48
+ }
49
+
50
+ const camera_options = [
51
+ {
52
+ tooltip: "Reset camera",
53
+ icon: "mdi-cube-scan",
54
+ action: () => {
55
+ const { genericRenderWindow } = storeToRefs(hybridViewerStore)
56
+ const renderWindow = genericRenderWindow.value.value.getRenderWindow()
57
+ const renderer = renderWindow.getRenderers()[0]
58
+ renderer.resetCamera()
59
+ renderWindow.render()
60
+ hybridViewerStore.syncRemoteCamera()
61
+ },
62
+ },
63
+ {
64
+ tooltip: "Take a screenshot",
65
+ icon: "mdi-camera",
66
+ action: () => {
67
+ take_screenshot.value = !take_screenshot.value
68
+ },
69
+ },
70
+ {
71
+ tooltip: "Toggle grid scale",
72
+ icon: "mdi-ruler-square",
73
+ action: () => {
74
+ viewer_call(
75
+ {
76
+ schema: schemas.opengeodeweb_viewer.viewer.grid_scale,
77
+ params: {
78
+ visibility: !grid_scale.value,
79
+ },
80
+ },
81
+ {
82
+ response_function: () => {
83
+ grid_scale.value = !grid_scale.value
84
+ },
85
+ },
86
+ )
87
+ },
88
+ },
89
+ {
90
+ tooltip: "Z Scaling Control",
91
+ icon: "mdi-sort",
92
+ action: () => {
93
+ showZScaling.value = !showZScaling.value
94
+ },
95
+ },
96
+ ]
97
+ </script>
98
+
99
+ <style module>
100
+ .floatToolbar {
101
+ position: absolute;
102
+ z-index: 2;
103
+ right: 20px;
104
+ top: 20px;
105
+ background-color: rgba(0, 0, 0, 0);
106
+ }
107
+ </style>
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <v-breadcrumbs class="mb-n10 breadcrumb-container">
3
+ <div class="d-flex align-center gap-2 ml-2 mt-2 mb-1">
4
+ <v-menu v-if="treeviewStore.isAdditionnalTreeDisplayed" offset-y>
5
+ <template v-slot:activator="{ props }">
6
+ <v-btn
7
+ icon
8
+ variant="text"
9
+ size="medium"
10
+ v-bind="props"
11
+ @click="goBackToFileTree"
12
+ >
13
+ <v-icon size="large">mdi-file-tree</v-icon>
14
+ </v-btn>
15
+ <span class="text-h5 font-weight-bold">/</span>
16
+ <v-icon size="x-large">
17
+ {{
18
+ selectedTree && selectedTree.icon
19
+ ? selectedTree.icon
20
+ : "mdi-shape-outline"
21
+ }}
22
+ </v-icon>
23
+ <span class="text-subtitle-1 font-weight-regular align-center mt-1">
24
+ Model Explorer ({{ metaDatas.displayed_name }})
25
+ </span>
26
+ </template>
27
+ </v-menu>
28
+
29
+ <div v-else class="d-flex align-center gap-2">
30
+ <v-icon size="large">mdi-file-tree</v-icon>
31
+ <span class="text-subtitle-1 font-weight-regular align-center mt-1">
32
+ Objects
33
+ </span>
34
+ </div>
35
+ </div>
36
+ </v-breadcrumbs>
37
+ </template>
38
+
39
+ <script setup>
40
+ const treeviewStore = use_treeview_store()
41
+
42
+ const selectedTree = computed(() => treeviewStore.selectedTree)
43
+
44
+ const goBackToFileTree = () => {
45
+ treeviewStore.displayFileTree()
46
+ }
47
+
48
+ const model_id = computed(() => treeviewStore.model_id)
49
+
50
+ const metaDatas = computed(() =>
51
+ useDataBaseStore().itemMetaDatas(model_id.value),
52
+ )
53
+ </script>
54
+
55
+ <style scoped>
56
+ .breadcrumb-container {
57
+ max-width: 100%;
58
+ overflow: hidden;
59
+ white-space: nowrap;
60
+ }
61
+ </style>
@@ -0,0 +1,170 @@
1
+ <template>
2
+ <v-container
3
+ class="treeview-container"
4
+ :style="{ width: `${treeviewStore.panelWidth}px` }"
5
+ >
6
+ <v-row
7
+ class="resizable-panel"
8
+ :style="{ width: `${treeviewStore.panelWidth}px` }"
9
+ >
10
+ <div class="scrollable-wrapper">
11
+ <v-sheet
12
+ style="max-height: calc(90vh)"
13
+ class="transparent-treeview scrollbar-hover"
14
+ >
15
+ <v-row v-if="treeviewStore.items.length > 0">
16
+ <v-col>
17
+ <ViewerBreadCrumb
18
+ :selectedTree="selectedTree"
19
+ :treeOptions="treeOptions"
20
+ @update:selectedTree="selectedTree = $event"
21
+ />
22
+ </v-col>
23
+ </v-row>
24
+ <v-row>
25
+ <v-col>
26
+ <ViewerTreeObject
27
+ v-if="!treeviewStore.isAdditionnalTreeDisplayed"
28
+ @show-menu="handleTreeMenu"
29
+ />
30
+ <ViewerTreeComponent
31
+ v-else
32
+ @show-menu="handleTreeMenu"
33
+ :id="treeviewStore.model_id"
34
+ />
35
+ </v-col>
36
+ </v-row>
37
+ </v-sheet>
38
+ </div>
39
+ <div class="resizer" @mousedown="onResizeStart"></div>
40
+ </v-row>
41
+ </v-container>
42
+ </template>
43
+
44
+ <script setup>
45
+ const treeviewStore = use_treeview_store()
46
+ const menuStore = useMenuStore()
47
+ const cardContainer = useTemplateRef("cardContainer")
48
+ const containerWidth = ref(window.innerWidth)
49
+ const containerHeight = ref(window.innerHeight)
50
+
51
+ const menuX = ref(0)
52
+ const menuY = ref(0)
53
+ const id = ref(null)
54
+
55
+ const emit = defineEmits(["show-menu", "position-menu"])
56
+
57
+ function handleTreeMenu({ event, itemId }) {
58
+ menuX.value = event.clientX
59
+ menuY.value = event.clientY
60
+ id.value = itemId
61
+
62
+ menuStore.openMenu(itemId, event.clientX, event.clientY)
63
+ }
64
+
65
+ function onResizeStart(event) {
66
+ const startWidth = treeviewStore.panelWidth
67
+ const startX = event.clientX
68
+
69
+ const resize = (e) => {
70
+ const deltaX = e.clientX - startX
71
+ const newWidth = Math.max(
72
+ 150,
73
+ Math.min(startWidth + deltaX, window.innerWidth),
74
+ )
75
+ treeviewStore.setPanelWidth(newWidth)
76
+ document.body.style.userSelect = "none"
77
+ }
78
+
79
+ const stopResize = () => {
80
+ document.removeEventListener("mousemove", resize)
81
+ document.removeEventListener("mouseup", stopResize)
82
+ document.body.style.userSelect = ""
83
+ }
84
+
85
+ document.addEventListener("mousemove", resize)
86
+ document.addEventListener("mouseup", stopResize)
87
+ }
88
+
89
+ onMounted(() => {
90
+ containerWidth.value = window.innerWidth
91
+ containerHeight.value = window.innerHeight
92
+
93
+ window.addEventListener("resize", () => {
94
+ containerWidth.value = window.innerWidth
95
+ containerHeight.value = window.innerHeight
96
+ })
97
+ })
98
+
99
+ onUnmounted(() => {
100
+ window.removeEventListener("resize")
101
+ })
102
+ </script>
103
+
104
+ <style scoped>
105
+ .treeview-container {
106
+ position: absolute;
107
+ z-index: 2;
108
+ left: 0;
109
+ top: 0;
110
+ background-color: transparent;
111
+ border-radius: 16px;
112
+ padding: 8px;
113
+ display: flex;
114
+ box-sizing: border-box;
115
+ }
116
+
117
+ .resizable-panel {
118
+ display: flex;
119
+ height: 100%;
120
+ position: relative;
121
+ box-sizing: border-box;
122
+ }
123
+
124
+ .scrollable-wrapper {
125
+ overflow-y: auto;
126
+ padding-right: 6px;
127
+ flex: 1;
128
+ }
129
+
130
+ .resizer {
131
+ position: absolute;
132
+ top: 0;
133
+ right: 0;
134
+ width: 6px;
135
+ height: 100%;
136
+ cursor: ew-resize;
137
+ background-color: transparent;
138
+ z-index: 15;
139
+ }
140
+
141
+ .resizer:hover {
142
+ background-color: #999;
143
+ }
144
+
145
+ .resizer:active {
146
+ background-color: #666;
147
+ }
148
+
149
+ .transparent-treeview {
150
+ background-color: transparent;
151
+ margin: 4px 0;
152
+ }
153
+
154
+ .scrollbar-hover {
155
+ overflow-x: hidden;
156
+ }
157
+
158
+ .scrollbar-hover::-webkit-scrollbar {
159
+ width: 5px;
160
+ }
161
+
162
+ .scrollbar-hover::-webkit-scrollbar-thumb {
163
+ background-color: transparent;
164
+ }
165
+
166
+ .scrollbar-hover:hover::-webkit-scrollbar-thumb {
167
+ background-color: rgba(0, 0, 0, 0.3);
168
+ border-radius: 10px;
169
+ }
170
+ </style>
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <v-treeview
3
+ v-model:selected="mesh_components_selection"
4
+ :items="items"
5
+ class="transparent-treeview"
6
+ item-value="id"
7
+ select-strategy="classic"
8
+ selectable
9
+ >
10
+ <template #title="{ item }">
11
+ <span class="treeview-item">{{ item.title }}</span>
12
+ </template>
13
+ </v-treeview>
14
+ </template>
15
+
16
+ <script setup>
17
+ const dataStyleStore = useDataStyleStore()
18
+ const dataBaseStore = useDataBaseStore()
19
+
20
+ const props = defineProps({ id: { type: String, required: true } })
21
+
22
+ const items = dataBaseStore.formatedMeshComponents(props.id)
23
+ const mesh_components_selection = ref(
24
+ dataStyleStore.visibleMeshComponents(props.id),
25
+ )
26
+
27
+ watch(
28
+ mesh_components_selection,
29
+ (current, previous) => {
30
+ if (!previous) previous = []
31
+ else {
32
+ const { added, removed } = compareSelections(current, previous)
33
+
34
+ const [added_corners, added_lines, added_surfaces, added_blocks] =
35
+ sortMeshComponents(added)
36
+ const [
37
+ removed_corners,
38
+ removed_lines,
39
+ removed_surfaces,
40
+ removed_blocks,
41
+ ] = sortMeshComponents(removed)
42
+ if (added_corners.length > 0)
43
+ dataStyleStore.setCornerVisibility(props.id, added_corners, true)
44
+ if (added_lines.length > 0)
45
+ dataStyleStore.setLineVisibility(props.id, added_lines, true)
46
+ if (added_surfaces.length > 0)
47
+ dataStyleStore.setSurfaceVisibility(props.id, added_surfaces, true)
48
+ if (added_blocks.length > 0)
49
+ dataStyleStore.setBlockVisibility(props.id, added_blocks, true)
50
+
51
+ if (removed_corners.length > 0)
52
+ dataStyleStore.setCornerVisibility(props.id, removed_corners, false)
53
+ if (removed_lines.length > 0)
54
+ dataStyleStore.setLineVisibility(props.id, removed_lines, false)
55
+ if (removed_surfaces.length > 0)
56
+ dataStyleStore.setSurfaceVisibility(props.id, removed_surfaces, false)
57
+ if (removed_blocks.length > 0)
58
+ dataStyleStore.setBlockVisibility(props.id, removed_blocks, false)
59
+ }
60
+ },
61
+ { immediate: true, deep: true },
62
+ )
63
+
64
+ function sortMeshComponents(items) {
65
+ var corner_ids = [],
66
+ line_ids = [],
67
+ surface_ids = [],
68
+ block_ids = []
69
+ for (const item of items) {
70
+ const item_type = dataBaseStore.meshComponentType(props.id, item)
71
+ if (item_type === "corner") corner_ids.push(item)
72
+ else if (item_type === "line") line_ids.push(item)
73
+ else if (item_type === "surface") surface_ids.push(item)
74
+ else if (item_type === "block") block_ids.push(item)
75
+ }
76
+ return [corner_ids, line_ids, surface_ids, block_ids]
77
+ }
78
+ </script>
79
+
80
+ <style scoped>
81
+ .treeview-item {
82
+ white-space: nowrap;
83
+ overflow: hidden;
84
+ text-overflow: ellipsis;
85
+ max-width: 100%;
86
+ display: inline-block;
87
+ }
88
+
89
+ .transparent-treeview {
90
+ background-color: transparent;
91
+ margin: 4px 0;
92
+ }
93
+ </style>
@@ -0,0 +1,100 @@
1
+ <template>
2
+ <v-treeview
3
+ v-model:selected="treeviewStore.selection"
4
+ :items="treeviewStore.items"
5
+ return-object
6
+ class="transparent-treeview"
7
+ item-value="id"
8
+ select-strategy="classic"
9
+ selectable
10
+ >
11
+ <template #title="{ item }">
12
+ <span
13
+ class="treeview-item"
14
+ @click.right.stop="
15
+ isLeafNode(item)
16
+ ? emit('show-menu', { event: $event, itemId: item.id })
17
+ : null
18
+ "
19
+ >
20
+ {{ item.title }}
21
+ </span>
22
+ </template>
23
+
24
+ <template #append="{ item }">
25
+ <v-btn
26
+ v-if="isModel(item)"
27
+ icon="mdi-magnify-expand"
28
+ size="medium"
29
+ class="ml-8"
30
+ variant="text"
31
+ v-tooltip="'Model\'s mesh components'"
32
+ @click.stop="treeviewStore.displayAdditionalTree(item.id)"
33
+ />
34
+ </template>
35
+ </v-treeview>
36
+ </template>
37
+
38
+ <script setup>
39
+ const treeviewStore = use_treeview_store()
40
+ const dataStyleStore = useDataStyleStore()
41
+ const dataBaseStore = useDataBaseStore()
42
+ const emit = defineEmits(["show-menu"])
43
+
44
+ function isLeafNode(item) {
45
+ return !item.children || item.children.length === 0
46
+ }
47
+
48
+ watch(
49
+ () => treeviewStore.selection,
50
+ (current, previous) => {
51
+ if (!previous) previous = []
52
+ const { added, removed } = compareSelections(current, previous)
53
+
54
+ added.forEach((item) => {
55
+ dataStyleStore.setVisibility(item.id, true)
56
+ })
57
+
58
+ removed.forEach((item) => {
59
+ dataStyleStore.setVisibility(item.id, false)
60
+
61
+ const objectMeta = dataBaseStore.itemMetaDatas(item.id)
62
+ if (objectMeta.object_type === "mesh") {
63
+ if (dataBaseStore.db[item.id]?.mesh_components_selection) {
64
+ dataBaseStore.db[item.id].mesh_components_selection = []
65
+ }
66
+ if (dataStyleStore.visibleMeshComponentIds?.[item.id]) {
67
+ dataStyleStore.updateVisibleMeshComponents(item.id, [])
68
+ }
69
+ }
70
+ })
71
+ },
72
+ { immediate: true },
73
+ )
74
+
75
+ function isModel(item) {
76
+ return item.object_type === "model"
77
+ }
78
+
79
+ onMounted(() => {
80
+ const savedSelection = treeviewStore.selection
81
+ if (savedSelection && savedSelection.length > 0) {
82
+ treeviewStore.selection = savedSelection
83
+ }
84
+ })
85
+ </script>
86
+
87
+ <style scoped>
88
+ .transparent-treeview {
89
+ background-color: transparent;
90
+ margin: 4px 0;
91
+ }
92
+
93
+ .treeview-item {
94
+ white-space: nowrap;
95
+ overflow: hidden;
96
+ text-overflow: ellipsis;
97
+ max-width: 100%;
98
+ display: inline-block;
99
+ }
100
+ </style>
@@ -0,0 +1,18 @@
1
+ import { reactive, computed } from "vue"
2
+
3
+ export default function useDataStyleState() {
4
+ const styles = reactive({})
5
+
6
+ const objectVisibility = computed(() => (id) => styles[id]?.visibility)
7
+ const selectedObjects = computed(() => {
8
+ const selection = []
9
+ for (const [id, value] of Object.entries(styles)) {
10
+ if (value.visibility === true) {
11
+ selection.push(id)
12
+ }
13
+ }
14
+ return selection
15
+ })
16
+
17
+ return { styles, objectVisibility, selectedObjects }
18
+ }