@abi-software/scaffoldvuer 0.1.50-beta-2 → 0.1.52-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/scaffoldvuer",
3
- "version": "0.1.50-beta-2",
3
+ "version": "0.1.52-beta.1",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,23 +22,22 @@
22
22
  "*.js"
23
23
  ],
24
24
  "dependencies": {
25
- "@abi-software/svg-sprite": "^0.1.13",
26
- "axios": "^0.21.1",
25
+ "@abi-software/svg-sprite": "^0.1.14",
26
+ "axios": "^0.21.2",
27
27
  "core-js": "^3.3.2",
28
28
  "current-script-polyfill": "^1.0.0",
29
29
  "element-ui": "^2.13.0",
30
30
  "google-spreadsheet": "^3.1.15",
31
31
  "lodash": "^4.17.21",
32
- "physiomeportal": "^0.4.27",
33
32
  "query-string": "^6.11.1",
34
33
  "vue": "^2.6.10",
35
34
  "vue-drag-resize": "^1.3.2",
36
35
  "vue-router": "^3.5.1",
37
- "zincjs": "^0.40.0"
36
+ "zincjs": "^0.50.0-beta.0"
38
37
  },
39
38
  "devDependencies": {
40
39
  "@vue/cli-plugin-babel": "^4.0.0",
41
- "@vue/cli-plugin-eslint": "^4.0.0",
40
+ "@vue/cli-plugin-eslint": "^4.5.15",
42
41
  "@vue/cli-service": "^4.5.13",
43
42
  "babel-eslint": "^10.0.3",
44
43
  "babel-plugin-component": "^1.1.1",
package/src/App.vue CHANGED
@@ -18,6 +18,7 @@
18
18
  :region="region"
19
19
  :view-u-r-l="viewURL"
20
20
  @scaffold-selected="onSelected"
21
+ @scaffold-navigated="onNavigated"
21
22
  @timeChanged="updateCurrentTime"
22
23
  />
23
24
  <el-popover
@@ -100,16 +101,69 @@
100
101
  >
101
102
  Restore Settings
102
103
  </el-button>
104
+ <el-button
105
+ size="mini"
106
+ @click="exportGLB()"
107
+ >
108
+ Export GLTF
109
+ </el-button>
103
110
  </el-row>
104
- <el-row :gutter="20">
105
- <el-row :gutter="20">
111
+ <el-row :gutter="30">
112
+ <el-col
113
+ :span="7"
114
+ :offset="11"
115
+ >
116
+ <el-switch
117
+ v-model="syncMode"
118
+ active-text="Sync Mode"
119
+ active-color="#8300bf"
120
+ />
121
+ </el-col>
122
+ </el-row>
123
+ <el-row :gutter="30">
124
+ <el-col
125
+ :span="7"
126
+ :offset="4"
127
+ >
106
128
  <el-switch
107
129
  v-model="render"
108
130
  active-text="Rendering"
109
131
  active-color="#8300bf"
110
132
  />
111
- </el-row>
133
+ </el-col>
134
+ <el-col
135
+ :span="8"
136
+ :offset="1"
137
+ >
138
+ <el-switch
139
+ v-model="renderInfoOn"
140
+ active-text="Renderer Info"
141
+ active-color="#8300bf"
142
+ />
143
+ </el-col>
112
144
  </el-row>
145
+ <template v-if="renderInfoOn && rendererInfo">
146
+ <el-row>
147
+ <el-col
148
+ v-for="(value, name) in rendererInfo.memory"
149
+ :key="name"
150
+ :offset="4"
151
+ :span="6"
152
+ >
153
+ {{ name }} : {{ value }}
154
+ </el-col>
155
+ </el-row>
156
+ <el-row>
157
+ <el-col
158
+ v-for="(value, name) in rendererInfo.render"
159
+ :key="name"
160
+ :offset="1"
161
+ :span="6"
162
+ >
163
+ {{ name }} : {{ value }}
164
+ </el-col>
165
+ </el-row>
166
+ </template>
113
167
  <el-input
114
168
  v-model="input"
115
169
  type="textarea"
@@ -199,6 +253,7 @@ export default {
199
253
  selectedCoordinates: undefined,
200
254
  helpMode: false,
201
255
  displayMarkers: true,
256
+ syncMode: false,
202
257
  currentTime: 0,
203
258
  displayMinimap: true,
204
259
  tumbleOn: false,
@@ -212,7 +267,9 @@ export default {
212
267
  },
213
268
  render: true,
214
269
  region: "",
215
- viewURL: ""
270
+ viewURL: "",
271
+ renderInfoOn: false,
272
+ rendererInfo: undefined
216
273
  };
217
274
  },
218
275
  watch: {
@@ -226,14 +283,43 @@ export default {
226
283
  handler: "parseQuery",
227
284
  deep: true,
228
285
  immediate: true
286
+ },
287
+ syncMode: function(val) {
288
+ this.$refs.scaffold.toggleSyncControl(val);
229
289
  }
230
290
  },
231
291
 
232
292
  mounted: function() {
233
293
  this._sceneSettings = [];
234
294
  this.selectedCoordinates = this.$refs.scaffold.getDynamicSelectedCoordinates();
295
+ this.rendererInfo = this.$refs.scaffold.getRendererInfo();
235
296
  },
236
297
  methods: {
298
+ exportGLTF: function() {
299
+ this.$refs.scaffold.exportGLTF(false)
300
+ .then(data =>{
301
+ let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data));
302
+ let hrefElement = document.createElement("a");
303
+ document.body.append(hrefElement);
304
+ hrefElement.download = `export.gltf`;
305
+ hrefElement.href = dataStr;
306
+ hrefElement.click();
307
+ hrefElement.remove();
308
+ })
309
+ },
310
+ exportGLB: function() {
311
+ this.$refs.scaffold.exportGLTF(true)
312
+ .then(data =>{
313
+ let blob = new Blob([data], {type: "octet/stream"});
314
+ let url = window.URL.createObjectURL(blob);
315
+ let hrefElement = document.createElement("a");
316
+ document.body.append(hrefElement);
317
+ hrefElement.download = `export.glb`;
318
+ hrefElement.href = url;
319
+ hrefElement.click();
320
+ hrefElement.remove();
321
+ })
322
+ },
237
323
  saveSettings: function() {
238
324
  this._sceneSettings.push(this.$refs.scaffold.getState());
239
325
  },
@@ -266,6 +352,9 @@ export default {
266
352
  });
267
353
  }
268
354
  },
355
+ onNavigated: function(data) {
356
+ console.log(data);
357
+ },
269
358
  parseInput: function() {
270
359
  if (this.$route.query.url !== this.input)
271
360
  this.$router.replace({
@@ -325,6 +414,12 @@ body {
325
414
 
326
415
  .options-container {
327
416
  text-align: center;
417
+ .el-row {
418
+ margin-bottom: 8px;
419
+ &:last-child {
420
+ margin-bottom: 0;
421
+ }
422
+ }
328
423
  }
329
424
 
330
425
  .vuer {
@@ -7,7 +7,7 @@
7
7
  element-loading-spinner="el-icon-loading"
8
8
  element-loading-background="rgba(0, 0, 0, 0.3)"
9
9
  >
10
- <SvgSpriteColor />
10
+ <map-svg-sprite-color />
11
11
  <div
12
12
  id="organsDisplayArea"
13
13
  ref="display"
@@ -76,13 +76,13 @@
76
76
  <el-tabs type="card">
77
77
  <el-tab-pane label="Animate scaffold">
78
78
  <el-row class="tab-content">
79
- <SvgIcon
79
+ <map-svg-icon
80
80
  v-if="isPlaying"
81
81
  icon="pause"
82
82
  class="icon-button video-button"
83
83
  @click.native="play(false)"
84
84
  />
85
- <SvgIcon
85
+ <map-svg-icon
86
86
  v-else
87
87
  icon="play"
88
88
  class="video-button icon-button"
@@ -146,7 +146,7 @@
146
146
  trigger="manual"
147
147
  popper-class="scaffold-popper left-popper non-selectable"
148
148
  >
149
- <SvgIcon
149
+ <map-svg-icon
150
150
  slot="reference"
151
151
  icon="zoomIn"
152
152
  class="icon-button zoomIn"
@@ -163,7 +163,7 @@
163
163
  trigger="manual"
164
164
  popper-class="scaffold-popper popper-zoomout non-selectable"
165
165
  >
166
- <SvgIcon
166
+ <map-svg-icon
167
167
  slot="reference"
168
168
  icon="zoomOut"
169
169
  class="icon-button zoomOut"
@@ -184,7 +184,7 @@
184
184
  <br>
185
185
  window
186
186
  </div>
187
- <SvgIcon
187
+ <map-svg-icon
188
188
  slot="reference"
189
189
  icon="fitWindow"
190
190
  class="icon-button fitWindow"
@@ -222,7 +222,7 @@
222
222
  trigger="manual"
223
223
  popper-class="scaffold-popper right-popper non-selectable"
224
224
  >
225
- <SvgIcon
225
+ <map-svg-icon
226
226
  slot="reference"
227
227
  v-popover:backgroundPopover
228
228
  icon="changeBckgd"
@@ -241,7 +241,7 @@
241
241
  import Vue from "vue";
242
242
  import OpacityControls from "./OpacityControls";
243
243
  import TraditionalControls from "./TraditionalControls";
244
- import { SvgIcon, SvgSpriteColor } from "@abi-software/svg-sprite";
244
+ import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
245
245
 
246
246
  import {
247
247
  Col,
@@ -268,10 +268,8 @@ Vue.use(Slider);
268
268
  Vue.use(TabPane);
269
269
  Vue.use(Tabs);
270
270
 
271
- const OrgansViewer = require("physiomeportal/src/modules/organsRenderer")
272
- .OrgansViewer;
273
- const EventNotifier = require("physiomeportal/src/utilities/eventNotifier")
274
- .EventNotifier;
271
+ const OrgansViewer = require("../scripts/organsRenderer").OrgansViewer;
272
+ const EventNotifier = require("../scripts/eventNotifier").EventNotifier;
275
273
 
276
274
  /**
277
275
  * A vue component of the scaffold viewer.
@@ -283,8 +281,8 @@ export default {
283
281
  name: "ScaffoldVuer",
284
282
  components: {
285
283
  OpacityControls,
286
- SvgIcon,
287
- SvgSpriteColor,
284
+ MapSvgIcon,
285
+ MapSvgSpriteColor,
288
286
  TraditionalControls
289
287
  },
290
288
  props: {
@@ -535,7 +533,6 @@ export default {
535
533
  this.$module.addOrganPartAddedCallback(this.organsAdded);
536
534
  this.$module.initialiseRenderer(this.$refs.display);
537
535
  this.toggleRendering(this.render);
538
- this.$module.toolTip = undefined;
539
536
  this.ro = new ResizeObserver(this.adjustLayout).observe(
540
537
  this.$refs.scaffoldContainer
541
538
  );
@@ -695,6 +692,12 @@ export default {
695
692
  }
696
693
  }
697
694
  },
695
+ getRendererInfo: function() {
696
+ if (this.$module.zincRenderer) {
697
+ return this.$module.zincRenderer.getThreeJSRenderer().info;
698
+ }
699
+ return undefined;
700
+ },
698
701
  /**
699
702
  * Function used to rotate the scene.
700
703
  * Also called when the associated button is pressed.
@@ -721,9 +724,9 @@ export default {
721
724
  let id = event.identifiers[0].data.id
722
725
  ? event.identifiers[0].data.id
723
726
  : event.identifiers[0].data.group;
724
- this.$refs.traditionalControl.changeActiveByName(id);
727
+ this.$refs.traditionalControl.changeActiveByName(id, true);
725
728
  } else {
726
- this.$refs.traditionalControl.removeActive();
729
+ this.$refs.traditionalControl.removeActive(true);
727
730
  }
728
731
  }
729
732
  /**
@@ -739,8 +742,8 @@ export default {
739
742
  let id = event.identifiers[0].data.id
740
743
  ? event.identifiers[0].data.id
741
744
  : event.identifiers[0].data.group;
742
- this.$refs.traditionalControl.changeHoverByName(id);
743
- } else this.$refs.traditionalControl.removeHover();
745
+ this.$refs.traditionalControl.changeHoverByName(id, true);
746
+ } else this.$refs.traditionalControl.removeHover(true);
744
747
  }
745
748
  /**
746
749
  * Triggers when an object has been highlighted
@@ -781,30 +784,52 @@ export default {
781
784
  this.$module.updateTime(normalizedTime);
782
785
  },
783
786
  /**
784
- * Set the selected zinc object
787
+ * A callback used by children components. Set the selected zinc object
785
788
  *
786
789
  * @param {object} object Zinc object
787
790
  */
788
- objectSelected: function(object) {
791
+ objectSelected: function(object, propagate) {
789
792
  if (object !== this.selectedObject) {
790
793
  this.selectedObject = object;
791
794
  this.$refs.opacityControl.setObject(this.selectedObject);
792
- if (object) this.$module.setSelectedByZincObject(object, true);
793
- else this.$module.setSelectedByObjects([], true);
795
+ if (object) this.$module.setSelectedByZincObject(object, propagate);
796
+ else this.$module.setSelectedByObjects([], propagate);
794
797
  }
795
798
  },
796
799
  /**
797
- * Set the highlighted zinc object
800
+ * A callback used by children components. Set the highlighted zinc object
798
801
  *
799
802
  * @param {object} object Zinc object
800
803
  */
801
- objectHovered: function(object) {
804
+ objectHovered: function(object, propagate) {
802
805
  if (object !== this.hoveredObject) {
803
806
  this.hoveredObject = object;
804
- if (object) this.$module.setHighlightedByZincObject(object, true);
805
- else this.$module.setHighlightedByObjects([], true);
807
+ if (object) this.$module.setHighlightedByZincObject(object, propagate);
808
+ else this.$module.setHighlightedByObjects([], propagate);
806
809
  }
807
810
  },
811
+ /**
812
+ * Set the selected by name.
813
+ *
814
+ * @param {name} name Name of the region
815
+ */
816
+ changeActiveByName: function(name, propagate) {
817
+ if (name === undefined)
818
+ this.$refs.traditionalControl.removeActive(propagate);
819
+ else
820
+ this.$refs.traditionalControl.changeActiveByName(name, propagate);
821
+ },
822
+ /**
823
+ * Set the highlighted by name.
824
+ *
825
+ * @param {name} name Name of the region
826
+ */
827
+ changeHighlightedByName: function(name, propagate) {
828
+ if (name === undefined)
829
+ this.$refs.traditionalControl.removeHover(propagate);
830
+ else
831
+ this.$refs.traditionalControl.changeHoverByName(name, propagate);
832
+ },
808
833
  /**
809
834
  * Start the animation.
810
835
  *
@@ -955,6 +980,9 @@ export default {
955
980
  }
956
981
  }
957
982
  },
983
+ exportGLTF: function(binary) {
984
+ return this.$module.scene.exportGLTF(binary);
985
+ },
958
986
  /**
959
987
  * Function used for reading in new scaffold metadata and a custom
960
988
  * viewport. This function will ignore the state prop and
@@ -1011,7 +1039,6 @@ export default {
1011
1039
  },
1012
1040
  /**
1013
1041
  * Callback using ResizeObserver.
1014
-
1015
1042
  */
1016
1043
  adjustLayout: function() {
1017
1044
  let width = this.$refs.scaffoldContainer.clientWidth;
@@ -1035,6 +1062,14 @@ export default {
1035
1062
  if (this.$module.zincRenderer) {
1036
1063
  this.$module.zincRenderer.onWindowResize();
1037
1064
  }
1065
+ },
1066
+ syncControlCallback: function() {
1067
+ const payload = this.$module.NDCCameraControl.getPanZoom();
1068
+ this.$emit("scaffold-navigated", payload);
1069
+ },
1070
+ toggleSyncControl: function(flag) {
1071
+ this.$module.toggleSyncControl(flag);
1072
+ this.$module.setSyncControlCallback(this.syncControlCallback);
1038
1073
  }
1039
1074
  }
1040
1075
  };
@@ -130,7 +130,6 @@ export default {
130
130
  tmpArray = uniq(tmpArray.concat(this.module.sceneData.pointset));
131
131
  this.sortedPrimitiveGroups = orderBy(tmpArray);
132
132
  this.module.addOrganPartAddedCallback(this.organsAdded);
133
- this.module.graphicsHighlight.selectColour = 0x444444;
134
133
  },
135
134
  destroyed: function() {
136
135
  this.sortedPrimitiveGroups = undefined;
@@ -153,47 +152,41 @@ export default {
153
152
  /**
154
153
  * Select a region by its name.
155
154
  */
156
- changeActiveByName: function(name) {
155
+ changeActiveByName: function(name, propagate) {
157
156
  let targetObject = this.getFirstZincObjectWithGroupName(name);
158
157
  if (targetObject && targetObject.getVisibility()) {
159
158
  this.activeRegion = name;
160
- /**
161
- * Triggers when an item has been selected.
162
- *
163
- * @property {object} target selected object.
164
- */
165
- this.$emit("object-selected", targetObject);
159
+ this.$emit("object-selected", targetObject, propagate);
160
+ } else {
161
+ this.removeActive(propagate);
166
162
  }
167
- this.removeHover();
163
+ this.removeHover(propagate);
168
164
  },
169
165
  /**
170
166
  * Hover a region by its name.
171
167
  */
172
- changeHoverByName: function(name) {
168
+ changeHoverByName: function(name, propagate) {
173
169
  let targetObject = this.getFirstZincObjectWithGroupName(name);
174
170
  if (targetObject) {
175
171
  this.hoverRegion = name;
176
- /**
177
- * Triggers when an item has been hovered over.
178
- *
179
- * @property {object} target hovered object.
180
- */
181
- this.$emit("object-hovered", targetObject);
172
+ this.$emit("object-hovered", targetObject, propagate);
173
+ } else {
174
+ this.removeHover(propagate);
182
175
  }
183
176
  },
184
177
  /**
185
178
  * Unselect the current selected region.
186
179
  */
187
- removeActive: function() {
180
+ removeActive: function(propagate) {
188
181
  this.activeRegion = "";
189
- this.$emit("object-selected", undefined);
182
+ this.$emit("object-selected", undefined, propagate);
190
183
  },
191
184
  /**
192
185
  * Unselect the current hover region.
193
186
  */
194
- removeHover: function() {
187
+ removeHover: function(propagate) {
195
188
  this.hoverRegion = "";
196
- this.$emit("object-hovered", undefined);
189
+ this.$emit("object-hovered", undefined, propagate);
197
190
  },
198
191
  /**
199
192
  * Reset the controls.
@@ -236,7 +229,7 @@ export default {
236
229
  }
237
230
  },
238
231
  checkboxHover: function(name) {
239
- this.changeHoverByName(name);
232
+ this.changeHoverByName(name, true);
240
233
  },
241
234
  itemClicked: function(name, event) {
242
235
  if (
@@ -245,7 +238,7 @@ export default {
245
238
  event.target.classList.contains("el-checkbox__original")
246
239
  )
247
240
  ) {
248
- this.changeActiveByName(name);
241
+ this.changeActiveByName(name, true);
249
242
  event.preventDefault();
250
243
  }
251
244
  },
@@ -272,10 +265,10 @@ export default {
272
265
  this.module.changeOrganPartsVisibility(item, event);
273
266
  if (event == false) {
274
267
  if (this.activeRegion === item) {
275
- this.removeActive();
268
+ this.removeActive(true);
276
269
  }
277
270
  if (this.hoverRegion === item) {
278
- this.removeHover();
271
+ this.removeHover(true);
279
272
  }
280
273
  }
281
274
  },
@@ -0,0 +1,80 @@
1
+ const MODULE_CHANGE = { ALL: 0, DESTROYED: 1, NAME_CHANGED: 2, SETTINGS_CHANGED: 3 };
2
+
3
+ const BaseModule = function() {
4
+ this.typeName = "Base Module";
5
+ this.instanceName = "default";
6
+ this.onChangedCallbacks = [];
7
+ /** Notifier handle for informing other modules of any changes **/
8
+ this.eventNotifiers = [];
9
+ }
10
+
11
+ BaseModule.prototype.setName = function(name) {
12
+ if (name && this.instanceName !== name) {
13
+ this.instanceName = name;
14
+ const callbackArray = this.onChangedCallbacks.slice();
15
+ for (let i = 0; i < callbackArray.length; i++) {
16
+ callbackArray[i]( this, MODULE_CHANGE.NAME_CHANGED );
17
+ }
18
+ }
19
+ }
20
+
21
+ BaseModule.prototype.settingsChanged = function() {
22
+ const callbackArray = this.onChangedCallbacks.slice();
23
+ for (let i = 0; i < callbackArray.length; i++) {
24
+ callbackArray[i]( this, MODULE_CHANGE.SETTINGS_CHANGED );
25
+ }
26
+ }
27
+
28
+ BaseModule.prototype.exportSettings = function() {
29
+ const settings = {};
30
+ settings.dialog = this.typeName;
31
+ settings.name = this.instanceName;
32
+ return settings;
33
+ }
34
+
35
+ BaseModule.prototype.importSettings = function(settings) {
36
+ if (settings.dialog == this.typeName) {
37
+ this.setName(settings.name);
38
+ return true;
39
+ }
40
+ return false;
41
+ }
42
+
43
+ BaseModule.prototype.publishChanges = function(annotations, eventType) {
44
+ for (let i = 0; i < this.eventNotifiers.length; i++) {
45
+ this.eventNotifiers[i].publish(this, eventType, annotations);
46
+ }
47
+ }
48
+
49
+ BaseModule.prototype.getName = function() {
50
+ return this.instanceName;
51
+ }
52
+
53
+ BaseModule.prototype.destroy = function() {
54
+ //Make a temorary copy as the array may be altered during the loop
55
+ const callbackArray = this.onChangedCallbacks.slice();
56
+ for (let i = 0; i < callbackArray.length; i++) {
57
+ callbackArray[i]( this, MODULE_CHANGE.DESTROYED );
58
+ }
59
+
60
+ delete this;
61
+ }
62
+
63
+ BaseModule.prototype.addChangedCallback = function(callback) {
64
+ if (this.onChangedCallbacks.includes(callback) == false)
65
+ this.onChangedCallbacks.push(callback);
66
+ }
67
+
68
+ BaseModule.prototype.removeChangedCallback = function(callback) {
69
+ const index = this.onChangedCallbacks.indexOf(callback);
70
+ if (index > -1) {
71
+ this.onChangedCallbacks.splice(index, 1);
72
+ }
73
+ }
74
+
75
+ BaseModule.prototype.addNotifier = function(eventNotifier) {
76
+ this.eventNotifiers.push(eventNotifier);
77
+ }
78
+
79
+ exports.BaseModule = BaseModule;
80
+ exports.MODULE_CHANGE = MODULE_CHANGE;