@abi-software/scaffoldvuer 0.1.52-beta.1 → 0.1.52-beta.4

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.1",
3
+ "version": "0.1.52-beta.4",
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.50.0-beta.0"
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,23 +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
- @scaffold-navigated="onNavigated"
22
- @timeChanged="updateCurrentTime"
23
- />
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>
24
30
  <el-popover
25
31
  placement="bottom"
26
32
  trigger="click"
@@ -88,7 +94,7 @@
88
94
  Capture
89
95
  </el-button>
90
96
  </el-row>
91
- <el-row :gutter="20">
97
+ <el-row :gutter="10">
92
98
  <el-button
93
99
  size="mini"
94
100
  @click="saveSettings()"
@@ -104,6 +110,12 @@
104
110
  <el-button
105
111
  size="mini"
106
112
  @click="exportGLB()"
113
+ >
114
+ Export GLB
115
+ </el-button>
116
+ <el-button
117
+ size="mini"
118
+ @click="exportGLTF()"
107
119
  >
108
120
  Export GLTF
109
121
  </el-button>
@@ -111,13 +123,37 @@
111
123
  <el-row :gutter="30">
112
124
  <el-col
113
125
  :span="7"
114
- :offset="11"
126
+ :offset="2"
115
127
  >
116
128
  <el-switch
117
129
  v-model="syncMode"
118
130
  active-text="Sync Mode"
119
131
  active-color="#8300bf"
120
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>
121
157
  </el-col>
122
158
  </el-row>
123
159
  <el-row :gutter="30">
@@ -201,9 +237,10 @@
201
237
  <script>
202
238
  /* eslint-disable no-alert, no-console */
203
239
  import { ScaffoldVuer } from "./components/index.js";
240
+ import DropZone from "./components/DropZone.vue";
204
241
  import ModelsTable from "./components/ModelsTable.vue";
205
242
  import Vue from "vue";
206
- import { Button, Col, Icon, Input, Popover, Row, Switch } from "element-ui";
243
+ import { Button, Col, Icon, Input, InputNumber, Popover, Row, Switch } from "element-ui";
207
244
  import lang from "element-ui/lib/locale/lang/en";
208
245
  import locale from "element-ui/lib/locale";
209
246
 
@@ -212,36 +249,15 @@ Vue.use(Button);
212
249
  Vue.use(Col);
213
250
  Vue.use(Icon);
214
251
  Vue.use(Input);
252
+ Vue.use(InputNumber);
215
253
  Vue.use(Popover);
216
254
  Vue.use(Row);
217
255
  Vue.use(Switch);
218
256
 
219
- /*
220
- const alignToObject = function(cameracontrol, scene) {
221
- var object = scene.findGeometriesWithGroupName("Endocardium of left atrium")[0];
222
- const boundingBox = object.getBoundingBox();
223
- if (boundingBox) {
224
- const radius = boundingBox.min.distanceTo(boundingBox.max)/2.0;
225
- const centreX = (boundingBox.min.x + boundingBox.max.x) / 2.0;
226
- const centreY = (boundingBox.min.y + boundingBox.max.y) / 2.0;
227
- const centreZ = (boundingBox.min.z + boundingBox.max.z) / 2.0;
228
- const clip_factor = 8.0;
229
- const endingViewport = cameracontrol.getViewportFromCentreAndRadius(centreX, centreY, centreZ, radius, 40, radius * clip_factor );
230
- const startingViewport = cameracontrol.getCurrentViewport();
231
- cameracontrol.cameraTransition(startingViewport, endingViewport, 1500);
232
- cameracontrol.enableCameraTransition();
233
- }
234
- setTimeout(function(){ tumble(cameracontrol) }, 2000);
235
- }
236
-
237
- const tumble = function(cameracontrol) {
238
- cameracontrol.enableAutoTumble();
239
- cameracontrol.autoTumble([1.0, 0.0], Math.PI / 2, true);
240
- }
241
- */
242
257
  export default {
243
258
  name: "App",
244
259
  components: {
260
+ DropZone,
245
261
  ScaffoldVuer,
246
262
  ModelsTable
247
263
  },
@@ -252,10 +268,10 @@ export default {
252
268
  displayUI: true,
253
269
  selectedCoordinates: undefined,
254
270
  helpMode: false,
255
- displayMarkers: true,
271
+ displayMarkers: false,
256
272
  syncMode: false,
257
273
  currentTime: 0,
258
- displayMinimap: true,
274
+ displayMinimap: false,
259
275
  tumbleOn: false,
260
276
  showColourPicker: true,
261
277
  minimapSettings: {
@@ -269,7 +285,9 @@ export default {
269
285
  region: "",
270
286
  viewURL: "",
271
287
  renderInfoOn: false,
272
- rendererInfo: undefined
288
+ rendererInfo: undefined,
289
+ zoom: 1,
290
+ pos: [0, 0],
273
291
  };
274
292
  },
275
293
  watch: {
@@ -288,7 +306,6 @@ export default {
288
306
  this.$refs.scaffold.toggleSyncControl(val);
289
307
  }
290
308
  },
291
-
292
309
  mounted: function() {
293
310
  this._sceneSettings = [];
294
311
  this.selectedCoordinates = this.$refs.scaffold.getDynamicSelectedCoordinates();
@@ -344,6 +361,9 @@ export default {
344
361
  cameracontrol.stopAutoTumble();
345
362
  }
346
363
  },
364
+ onReady: function() {
365
+ this.$refs.dropzone.revokeURLs();
366
+ },
347
367
  onSelected: function(data) {
348
368
  if (data && data[0].data.group) {
349
369
  delete this.$route.query["viewURL"];
@@ -353,13 +373,22 @@ export default {
353
373
  }
354
374
  },
355
375
  onNavigated: function(data) {
356
- console.log(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;
357
382
  },
358
383
  parseInput: function() {
359
- 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;
360
388
  this.$router.replace({
361
389
  query: { ...this.$route.query, url: this.input }
362
390
  });
391
+ }
363
392
  },
364
393
  updateCurrentTime: function(val) {
365
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,126 @@
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
+ &.el-popper[x-placement^="bottom"] {
107
+ .popper__arrow {
108
+ border-bottom-color: $app-primary-color !important;
109
+ &:after {
110
+ border-bottom-color: #fff !important;
111
+ }
112
+ }
113
+ }
114
+ }
115
+
116
+ .tooltipContainer {
117
+ position: absolute;
118
+ height: 50px;
119
+ z-index: 2;
120
+ }
121
+
122
+ ::v-deep .non-selectable {
123
+ user-select: none;
124
+ pointer-events: none;
125
+ }
126
+ </style>