@abi-software/scaffoldvuer 0.1.52-beta.0 → 0.1.52-beta.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/scaffoldvuer",
3
- "version": "0.1.52-beta.0",
3
+ "version": "0.1.52-beta.3",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,7 +33,7 @@
33
33
  "vue": "^2.6.10",
34
34
  "vue-drag-resize": "^1.3.2",
35
35
  "vue-router": "^3.5.1",
36
- "zincjs": "^0.41.2"
36
+ "zincjs": "^1.0.0-alpha-3"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@vue/cli-plugin-babel": "^4.0.0",
@@ -47,8 +47,9 @@
47
47
  "node-sass": "^4.14.1",
48
48
  "raw-loader": "^0.5.1",
49
49
  "sass-loader": "^8.0.2",
50
+ "simple-dropzone": "^0.8.1",
50
51
  "vue-cli-plugin-styleguidist": "^4.32.2",
51
- "vue-styleguidist": "^4.38.1",
52
+ "vue-styleguidist": "^4.44.22",
52
53
  "vue-template-compiler": "^2.6.10",
53
54
  "webpack-node-externals": "^2.5.2"
54
55
  },
package/src/App.vue CHANGED
@@ -4,22 +4,29 @@
4
4
  rel="stylesheet"
5
5
  href="https://fonts.googleapis.com/css?family=Asap:400,400i,500,600,700&display=swap"
6
6
  >
7
- <ScaffoldVuer
8
- ref="scaffold"
9
- class="vuer"
10
- :display-u-i="displayUI"
11
- :url="url"
12
- :help-mode="helpMode"
13
- :display-minimap="displayMinimap"
14
- :display-markers="displayMarkers"
15
- :minimap-settings="minimapSettings"
16
- :show-colour-picker="showColourPicker"
17
- :render="render"
18
- :region="region"
19
- :view-u-r-l="viewURL"
20
- @scaffold-selected="onSelected"
21
- @timeChanged="updateCurrentTime"
22
- />
7
+ <drop-zone
8
+ ref="dropzone"
9
+ @files-drop="onFilesDrop"
10
+ >
11
+ <ScaffoldVuer
12
+ ref="scaffold"
13
+ class="vuer"
14
+ :display-u-i="displayUI"
15
+ :url="url"
16
+ :help-mode="helpMode"
17
+ :display-minimap="displayMinimap"
18
+ :display-markers="displayMarkers"
19
+ :minimap-settings="minimapSettings"
20
+ :show-colour-picker="showColourPicker"
21
+ :render="render"
22
+ :region="region"
23
+ :view-u-r-l="viewURL"
24
+ @on-ready="onReady"
25
+ @scaffold-selected="onSelected"
26
+ @scaffold-navigated="onNavigated"
27
+ @timeChanged="updateCurrentTime"
28
+ />
29
+ </drop-zone>
23
30
  <el-popover
24
31
  placement="bottom"
25
32
  trigger="click"
@@ -87,7 +94,7 @@
87
94
  Capture
88
95
  </el-button>
89
96
  </el-row>
90
- <el-row :gutter="20">
97
+ <el-row :gutter="10">
91
98
  <el-button
92
99
  size="mini"
93
100
  @click="saveSettings()"
@@ -103,10 +110,52 @@
103
110
  <el-button
104
111
  size="mini"
105
112
  @click="exportGLB()"
113
+ >
114
+ Export GLB
115
+ </el-button>
116
+ <el-button
117
+ size="mini"
118
+ @click="exportGLTF()"
106
119
  >
107
120
  Export GLTF
108
121
  </el-button>
109
122
  </el-row>
123
+ <el-row :gutter="30">
124
+ <el-col
125
+ :span="7"
126
+ :offset="2"
127
+ >
128
+ <el-switch
129
+ v-model="syncMode"
130
+ active-text="Sync Mode"
131
+ active-color="#8300bf"
132
+ />
133
+ <el-row v-if="syncMode">
134
+ <el-input-number
135
+ v-model="zoom"
136
+ :min="1.0"
137
+ :controls="false"
138
+ placeholder="Please input"
139
+ label="zoom"
140
+ />
141
+ <el-input-number
142
+ v-model="pos[0]"
143
+ :min="-1.0"
144
+ :max="1.0"
145
+ :controls="false"
146
+ placeholder="Please input"
147
+ label="x"
148
+ />
149
+ <el-input-number
150
+ v-model="pos[1]"
151
+ :min="-1.0"
152
+ :max="1.0"
153
+ :controls="false"
154
+ label="y"
155
+ />
156
+ </el-row>
157
+ </el-col>
158
+ </el-row>
110
159
  <el-row :gutter="30">
111
160
  <el-col
112
161
  :span="7"
@@ -188,9 +237,10 @@
188
237
  <script>
189
238
  /* eslint-disable no-alert, no-console */
190
239
  import { ScaffoldVuer } from "./components/index.js";
240
+ import DropZone from "./components/DropZone.vue";
191
241
  import ModelsTable from "./components/ModelsTable.vue";
192
242
  import Vue from "vue";
193
- import { Button, Col, Icon, Input, Popover, Row, Switch } from "element-ui";
243
+ import { Button, Col, Icon, Input, InputNumber, Popover, Row, Switch } from "element-ui";
194
244
  import lang from "element-ui/lib/locale/lang/en";
195
245
  import locale from "element-ui/lib/locale";
196
246
 
@@ -199,36 +249,15 @@ Vue.use(Button);
199
249
  Vue.use(Col);
200
250
  Vue.use(Icon);
201
251
  Vue.use(Input);
252
+ Vue.use(InputNumber);
202
253
  Vue.use(Popover);
203
254
  Vue.use(Row);
204
255
  Vue.use(Switch);
205
256
 
206
- /*
207
- const alignToObject = function(cameracontrol, scene) {
208
- var object = scene.findGeometriesWithGroupName("Endocardium of left atrium")[0];
209
- const boundingBox = object.getBoundingBox();
210
- if (boundingBox) {
211
- const radius = boundingBox.min.distanceTo(boundingBox.max)/2.0;
212
- const centreX = (boundingBox.min.x + boundingBox.max.x) / 2.0;
213
- const centreY = (boundingBox.min.y + boundingBox.max.y) / 2.0;
214
- const centreZ = (boundingBox.min.z + boundingBox.max.z) / 2.0;
215
- const clip_factor = 8.0;
216
- const endingViewport = cameracontrol.getViewportFromCentreAndRadius(centreX, centreY, centreZ, radius, 40, radius * clip_factor );
217
- const startingViewport = cameracontrol.getCurrentViewport();
218
- cameracontrol.cameraTransition(startingViewport, endingViewport, 1500);
219
- cameracontrol.enableCameraTransition();
220
- }
221
- setTimeout(function(){ tumble(cameracontrol) }, 2000);
222
- }
223
-
224
- const tumble = function(cameracontrol) {
225
- cameracontrol.enableAutoTumble();
226
- cameracontrol.autoTumble([1.0, 0.0], Math.PI / 2, true);
227
- }
228
- */
229
257
  export default {
230
258
  name: "App",
231
259
  components: {
260
+ DropZone,
232
261
  ScaffoldVuer,
233
262
  ModelsTable
234
263
  },
@@ -239,9 +268,10 @@ export default {
239
268
  displayUI: true,
240
269
  selectedCoordinates: undefined,
241
270
  helpMode: false,
242
- displayMarkers: true,
271
+ displayMarkers: false,
272
+ syncMode: false,
243
273
  currentTime: 0,
244
- displayMinimap: true,
274
+ displayMinimap: false,
245
275
  tumbleOn: false,
246
276
  showColourPicker: true,
247
277
  minimapSettings: {
@@ -255,7 +285,9 @@ export default {
255
285
  region: "",
256
286
  viewURL: "",
257
287
  renderInfoOn: false,
258
- rendererInfo: undefined
288
+ rendererInfo: undefined,
289
+ zoom: 1,
290
+ pos: [0, 0],
259
291
  };
260
292
  },
261
293
  watch: {
@@ -269,9 +301,11 @@ export default {
269
301
  handler: "parseQuery",
270
302
  deep: true,
271
303
  immediate: true
304
+ },
305
+ syncMode: function(val) {
306
+ this.$refs.scaffold.toggleSyncControl(val);
272
307
  }
273
308
  },
274
-
275
309
  mounted: function() {
276
310
  this._sceneSettings = [];
277
311
  this.selectedCoordinates = this.$refs.scaffold.getDynamicSelectedCoordinates();
@@ -327,6 +361,9 @@ export default {
327
361
  cameracontrol.stopAutoTumble();
328
362
  }
329
363
  },
364
+ onReady: function() {
365
+ this.$refs.dropzone.revokeURLs();
366
+ },
330
367
  onSelected: function(data) {
331
368
  if (data && data[0].data.group) {
332
369
  delete this.$route.query["viewURL"];
@@ -335,11 +372,23 @@ export default {
335
372
  });
336
373
  }
337
374
  },
375
+ onNavigated: function(data) {
376
+ this.zoom = data.zoom;
377
+ this.pos[0] = data.target[0];
378
+ this.pos[1] = data.target[1];
379
+ },
380
+ onFilesDrop: function(metaURL) {
381
+ this.input = metaURL;
382
+ },
338
383
  parseInput: function() {
339
- if (this.$route.query.url !== this.input)
384
+ if (this.$route.query.url !== this.input) {
385
+ const queries = {...this.$route.query};
386
+ if (this.input && this.input !== "")
387
+ queries.url = this.input;
340
388
  this.$router.replace({
341
389
  query: { ...this.$route.query, url: this.input }
342
390
  });
391
+ }
343
392
  },
344
393
  updateCurrentTime: function(val) {
345
394
  this.currentTime = val;
@@ -0,0 +1,91 @@
1
+ <template>
2
+ <div
3
+ ref="dropEl"
4
+ class="dropzone"
5
+ >
6
+ <slot />
7
+ <input
8
+ ref="fileInput"
9
+ type="file"
10
+ >
11
+ </div>
12
+ </template>
13
+
14
+ <script>
15
+ /* eslint-disable no-alert, no-console */
16
+ import { SimpleDropzone } from "simple-dropzone";
17
+ import path from "path";
18
+
19
+ export default {
20
+ name: "DropZone",
21
+ data: function () {
22
+ return {
23
+ objectURLs: [],
24
+ };
25
+ },
26
+ mounted: function () {
27
+ const dropCtrl = new SimpleDropzone(
28
+ this.$refs.dropEl,
29
+ this.$refs.fileInput
30
+ );
31
+ dropCtrl.on("drop", ({ files }) => {
32
+ this.localDrop(files);
33
+ });
34
+ },
35
+ methods: {
36
+ createObjectURLs: function (text, list) {
37
+ let content = text;
38
+ for (const [key, file] of Object.entries(list)) {
39
+ if (content.includes(key)) {
40
+ const objectURL = URL.createObjectURL(file);
41
+ content = content.replace(key, objectURL);
42
+ this.objectURLs.push(objectURL);
43
+ }
44
+ }
45
+ let blob = new Blob([content], { type: "application/json" });
46
+ const metaURL = URL.createObjectURL(blob);
47
+ this.objectURLs.push(metaURL);
48
+ this.$emit("files-drop", metaURL);
49
+ },
50
+ revokeURLs: function () {
51
+ this.objectURLs.forEach(objectURL => URL.revokeObjectURL(objectURL));
52
+ this.objectURLs = [];
53
+ },
54
+ localDrop: function (fileMap) {
55
+ const dataMaps = {};
56
+ let list = {};
57
+ let metadata = undefined;
58
+ const flatarray = Array.from(fileMap);
59
+ let rootPath = "";
60
+ for (let i = 0; i < flatarray.length; i++) {
61
+ if (flatarray[i][1].name.includes("metadata.json")) {
62
+ rootPath = flatarray[i][0].replace(flatarray[i][1].name, "");
63
+ metadata = { rootPath, file: flatarray[i][1] };
64
+ break;
65
+ }
66
+ }
67
+ if (metadata) {
68
+ flatarray.forEach(([filePath, file]) => {
69
+ if (file.name.match(/\.(json)$/)) {
70
+ const relativePath = path.relative(rootPath, filePath);
71
+ list[relativePath] = file;
72
+ }
73
+ });
74
+ const metaFileURL = URL.createObjectURL(metadata.file);
75
+ fetch(metaFileURL)
76
+ .then((response) => response.text())
77
+ .then((text) => this.createObjectURLs(text, list));
78
+ URL.revokeObjectURL(metaFileURL);
79
+ }
80
+ },
81
+ },
82
+ };
83
+ </script>
84
+
85
+ <style scoped lang="scss">
86
+ .dropzone {
87
+ position: absolute;
88
+ width: 100%;
89
+ height: 100%;
90
+ }
91
+ </style>
@@ -0,0 +1,117 @@
1
+ <template>
2
+ <div :style="position" class="tooltipContainer">
3
+ <el-popover
4
+ ref="tooltip"
5
+ v-model="display"
6
+ placement="top"
7
+ :append-to-body="false"
8
+ trigger="manual"
9
+ popper-class="tooltip-popper non-selectable"
10
+ >
11
+ <div>{{ label }}</div>
12
+ <i v-popover:tooltip />
13
+ </el-popover>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ /* eslint-disable no-alert, no-console */
19
+ import Vue from "vue";
20
+ import { Popover } from "element-ui";
21
+ import lang from "element-ui/lib/locale/lang/en";
22
+ import locale from "element-ui/lib/locale";
23
+
24
+ locale.use(lang);
25
+ Vue.use(Popover);
26
+
27
+ /**
28
+ * A component to control the opacity of the target object.
29
+ */
30
+ export default {
31
+ name: "ScaffoldTooltip",
32
+ props: {
33
+ label: {
34
+ type: String,
35
+ default: "",
36
+ },
37
+ visible: {
38
+ type: Boolean,
39
+ default: false,
40
+ },
41
+ x: {
42
+ type: Number,
43
+ default: 200,
44
+ },
45
+ y: {
46
+ type: Number,
47
+ default: 200,
48
+ },
49
+ },
50
+ data: function () {
51
+ return {
52
+ display: false,
53
+ };
54
+ },
55
+ computed: {
56
+ position: function () {
57
+ return { left: this.x + "px", top: this.y - 30 + "px" };
58
+ },
59
+ },
60
+ watch: {
61
+ label: {
62
+ handler: function () {
63
+ if (this.visible && this.label && this.label !== "")
64
+ this.display = true;
65
+ else this.display = false;
66
+ },
67
+ immediate: true,
68
+ },
69
+ visible: {
70
+ handler: function () {
71
+ if (this.visible && this.label && this.label !== "")
72
+ this.display = true;
73
+ else this.display = false;
74
+ },
75
+ immediate: true,
76
+ },
77
+ },
78
+ };
79
+ </script>
80
+
81
+ <!-- Add "scoped" attribute to limit CSS to this component only -->
82
+ <style scoped lang="scss">
83
+ @import "~element-ui/packages/theme-chalk/src/popover";
84
+
85
+ ::v-deep .tooltip-popper {
86
+ padding: 2px 6px;
87
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
88
+ font-size: 16px;
89
+ color: $app-primary-color;
90
+ background-color: #fff;
91
+ border: 1px solid $app-primary-color;
92
+ border-radius: 4px;
93
+ white-space: nowrap;
94
+ min-width: unset;
95
+ pointer-events: none;
96
+
97
+ &.el-popper[x-placement^="top"] {
98
+ .popper__arrow {
99
+ border-top-color: $app-primary-color !important;
100
+ &:after {
101
+ border-top-color: #fff !important;
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ .tooltipContainer {
108
+ position: absolute;
109
+ height: 50px;
110
+ z-index: 2;
111
+ }
112
+
113
+ ::v-deep .non-selectable {
114
+ user-select: none;
115
+ pointer-events: none;
116
+ }
117
+ </style>