@sapui5/sap.ui.vbm 1.140.0 → 1.142.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapui5/sap.ui.vbm",
3
- "version": "1.140.0",
3
+ "version": "1.142.0",
4
4
  "description": "SAPUI5 Library sap.ui.vbm",
5
5
  "homepage": "https://sap.github.io/ui5-tooling/pages/SAPUI5/",
6
6
  "author": "SAP SE (https://www.sap.com)",
@@ -3,7 +3,7 @@
3
3
  <name>sap.ui.vbm</name>
4
4
  <vendor>SAP SE</vendor>
5
5
  <copyright>SAP UI development toolkit for HTML5 (SAPUI5) (c) Copyright 2009-2012 SAP AG. All rights reserved</copyright>
6
- <version>1.140.0</version>
6
+ <version>1.142.0</version>
7
7
 
8
8
  <documentation>SAP UI library: sap.ui.vbm</documentation>
9
9
 
@@ -24,7 +24,7 @@ sap.ui.define([
24
24
  * @param {string} [sId] id for the new control, generated automatically if no id is given
25
25
  * @param {object} [mSettings] initial settings for the new object
26
26
  * @author SAP SE
27
- * @version 1.140.0
27
+ * @version 1.142.0
28
28
  * @extends sap.ui.core.Element
29
29
  * @constructor
30
30
  * @public
@@ -47,7 +47,7 @@ sap.ui.define([
47
47
  * @param {string} [sId] id for the new control, generated automatically if no id is given
48
48
  * @param {object} [mSettings] initial settings for the new object
49
49
  * @author SAP SE
50
- * @version 1.140.0
50
+ * @version 1.142.0
51
51
  * @extends sap.ui.core.Element
52
52
  * @constructor
53
53
  * @public
@@ -117,11 +117,12 @@ sap.ui.define([
117
117
  "_sap_ui_vbm_shared_ChartDataPointBorderHoverSelectedColor",
118
118
  "_sap_ui_vbm_shared_ChartDataPointNotSelectedBackgroundOpacity"
119
119
  ] });
120
-
121
- AnalyticMap.DefaultRegionColor = values?values["_sap_ui_vbm_shared_ChoroplethRegionBG"] : "rgb(213,218,221)";
122
- AnalyticMap.DefaultRegionColorBorder = values?values["_sap_ui_vbm_shared_ChoroplethRegionBorder"] : "rgb(255,255,255)";
123
- AnalyticMap.AltBorderColor = values?values["_sap_ui_vbm_shared_ChartDataPointBorderHoverSelectedColor"] : "#676767";
124
- nonSelectOpacity = values?values["_sap_ui_vbm_shared_ChartDataPointNotSelectedBackgroundOpacity"] : "0.6";
120
+ const isValues= Object.keys(values || {}).length > 0;
121
+
122
+ AnalyticMap.DefaultRegionColor = isValues?values["_sap_ui_vbm_shared_ChoroplethRegionBG"] : "rgb(213,218,221)";
123
+ AnalyticMap.DefaultRegionColorBorder = isValues?values["_sap_ui_vbm_shared_ChoroplethRegionBorder"] : "rgb(255,255,255)";
124
+ AnalyticMap.AltBorderColor = isValues?values["_sap_ui_vbm_shared_ChartDataPointBorderHoverSelectedColor"] : "#676767";
125
+ nonSelectOpacity = isValues?values["_sap_ui_vbm_shared_ChartDataPointNotSelectedBackgroundOpacity"] : "0.6";
125
126
 
126
127
  AnalyticMap.DefaultRegionNonSelectColor = "RHLSA(0;1;1;" + nonSelectOpacity + ")";
127
128
 
@@ -992,8 +993,9 @@ sap.ui.define([
992
993
  "_sap_ui_vbm_shared_ChoroplethRegionBG",
993
994
  "_sap_ui_vbm_shared_ChoroplethRegionBorder"
994
995
  ] });
995
- sColC = AnalyticMap.DefaultRegionColor = oColValues? oColValues["_sap_ui_vbm_shared_ChoroplethRegionBG"] : AnalyticMap.DefaultRegionColor;
996
- sColCB = AnalyticMap.DefaultRegionColorBorder = oColValues? oColValues["_sap_ui_vbm_shared_ChoroplethRegionBorder"] : AnalyticMap.DefaultRegionColorBorder;
996
+ const isValues= Object.keys(oColValues || {}).length > 0;
997
+ sColC = AnalyticMap.DefaultRegionColor = isValues? oColValues["_sap_ui_vbm_shared_ChoroplethRegionBG"] : AnalyticMap.DefaultRegionColor;
998
+ sColCB = AnalyticMap.DefaultRegionColorBorder = isValues? oColValues["_sap_ui_vbm_shared_ChoroplethRegionBorder"] : AnalyticMap.DefaultRegionColorBorder;
997
999
  if (this.getPlugin()) { // plug-in mode -> make sure color format matches plugin requirements
998
1000
  sColC = window.VBI.Utilities.String2VBColor(sColC);
999
1001
  sColCB = window.VBI.Utilities.String2VBColor(sColCB);
@@ -23,7 +23,7 @@ sap.ui.define([
23
23
  *
24
24
  * @public
25
25
  * @author SAP SE
26
- * @version 1.140.0
26
+ * @version 1.142.0
27
27
  * @extends sap.ui.core.Control
28
28
  * @alias sap.ui.vbm.Viewport
29
29
  */
@@ -341,10 +341,11 @@ sap.ui.define([
341
341
  "_sap_ui_vbm_shared_ChartGood",
342
342
  "_sap_ui_vbm_shared_ChartNeutral"] });
343
343
 
344
- VoBase.prototype.DefaultColorBad = colorParams? colorParams["_sap_ui_vbm_shared_ChartBad"] : "rgb(211, 32, 48)";
345
- VoBase.prototype.DefaultColorCritical = colorParams? colorParams["_sap_ui_vbm_shared_ChartCritical"] : "rgb(225, 123, 36)";
346
- VoBase.prototype.DefaultColorGood = colorParams? colorParams["_sap_ui_vbm_shared_ChartGood"] : "rgb(97, 166, 86)";
347
- VoBase.prototype.DefaultColorNeutral = colorParams? colorParams["_sap_ui_vbm_shared_ChartNeutral"] : "rgb(132, 143, 148)";
344
+ const isValues= Object.keys(colorParams || {}).length > 0;
345
+ VoBase.prototype.DefaultColorBad = isValues? colorParams["_sap_ui_vbm_shared_ChartBad"] : "rgb(211, 32, 48)";
346
+ VoBase.prototype.DefaultColorCritical = isValues? colorParams["_sap_ui_vbm_shared_ChartCritical"] : "rgb(225, 123, 36)";
347
+ VoBase.prototype.DefaultColorGood = isValues? colorParams["_sap_ui_vbm_shared_ChartGood"] : "rgb(97, 166, 86)";
348
+ VoBase.prototype.DefaultColorNeutral = isValues? colorParams["_sap_ui_vbm_shared_ChartNeutral"] : "rgb(132, 143, 148)";
348
349
 
349
350
  // VO Interface implementation ..............................................//
350
351
 
@@ -22,7 +22,7 @@ sap.ui.define([
22
22
  *
23
23
  * @private
24
24
  * @author SAP SE
25
- * @version 1.140.0
25
+ * @version 1.142.0
26
26
  * @alias sap.ui.vbm.adapter3d.ColladaBounds
27
27
  */
28
28
  var ColladaBounds = BaseObject.extend("sap.ui.vbm.adapter3d.ColladaBounds", /** @lends sap.ui.vbm.adapter3d.ColladaBounds.prototype */ {
@@ -83,7 +83,7 @@ sap.ui.define([
83
83
  *
84
84
  * @private
85
85
  * @author SAP SE
86
- * @version 1.140.0
86
+ * @version 1.142.0
87
87
  * @alias sap.ui.vbm.adapter3d.DragDropHandler
88
88
  */
89
89
  var DragDropHandler = BaseObject.extend("sap.ui.vbm.adapter3d.DragDropHandler", /** @lends sap.ui.vbm.adapter3d.DragDropHandler.prototype */ {
@@ -29,7 +29,7 @@ sap.ui.define([
29
29
  *
30
30
  * @private
31
31
  * @author SAP SE
32
- * @version 1.140.0
32
+ * @version 1.142.0
33
33
  * @alias sap.ui.vbm.adapter3d.ModelHandler
34
34
  */
35
35
  var ModelHandler = BaseObject.extend("sap.ui.vbm.adapter3d.ModelHandler", /** @lends sap.ui.vbm.adapter3d.ModelHandler.prototype */ {
@@ -377,7 +377,7 @@ sap.ui.define([
377
377
  *
378
378
  * @private
379
379
  * @author SAP SE
380
- * @version 1.140.0
380
+ * @version 1.142.0
381
381
  * @alias sap.ui.vbm.adapter3d.ObjectFactory
382
382
  */
383
383
  var ObjectFactory = BaseObject.extend("sap.ui.vbm.adapter3d.ObjectFactory", /** @lends sap.ui.vbm.adapter3d.ObjectFactory.prototype */ {});
@@ -32,7 +32,7 @@ sap.ui.define([
32
32
  *
33
33
  * @private
34
34
  * @author SAP SE
35
- * @version 1.140.0
35
+ * @version 1.142.0
36
36
  * @alias sap.ui.vbm.adapter3d.PolygonHandler
37
37
  */
38
38
  var PolygonHandler = BaseObject.extend("sap.ui.vbm.adapter3d.PolygonHandler", /** @lends sap.ui.vbm.adapter3d.PolygonHandler.prototype */ {
@@ -7,7 +7,7 @@ sap.ui.define([
7
7
  var Vector2 = THREE.Vector2;
8
8
  var _frustum = new THREE.Frustum;
9
9
  var _center = new THREE.Vector3;
10
- var _tmpPoint = new THREE.Vector3;
10
+ //var _tmpPoint = new THREE.Vector3;
11
11
  var _vecNear = new THREE.Vector3;
12
12
  var _vecTopLeft = new THREE.Vector3;
13
13
  var _vecTopRight = new THREE.Vector3;
@@ -39,7 +39,7 @@ sap.ui.define([
39
39
  *
40
40
  * @private
41
41
  * @author SAP SE
42
- * @version 1.140.0
42
+ * @version 1.142.0
43
43
  * @alias sap.ui.vbm.adapter3d.RectangleTracker
44
44
  */
45
45
  var RectangleTracker = BaseObject.extend("sap.ui.vbm.adapter3d.RectangleTracker", /** @lends sap.ui.vbm.adapter3d.RectangleTracker.prototype */ {
@@ -55,9 +55,11 @@ sap.ui.define([
55
55
  this._selected = new Set();
56
56
  this._renderer = this._renderer;
57
57
  this.init();
58
- var helper = new THREE.CameraHelper(this._camera);
59
- helper.geometry.setDrawRange(0, 0);
60
- this._addToScene(helper, this._scene, true, 1);
58
+ if (!this._adapter._cameraHelper) {
59
+ this._adapter._cameraHelper = new THREE.CameraHelper(this._camera);
60
+ this._adapter._cameraHelper.geometry.setDrawRange(0, 0);
61
+ this._addToScene(this._adapter._cameraHelper, this._scene, true, 1);
62
+ }
61
63
  this._snapBox = new THREE.BoxHelper(undefined, 0x00ffff);
62
64
  // invisible, layer #1 (disable hit test)
63
65
  this._addToScene(this._snapBox, this._scene, false, 1);
@@ -148,82 +150,17 @@ sap.ui.define([
148
150
  };
149
151
 
150
152
  RectangleTracker.prototype._onPointerDown = function (event) {
153
+ if (event.button !== 0) {
154
+ return; // Don't start selection if it's not the left button
155
+ }
151
156
  this._updateController(true);
152
157
  this.onSelectStart(event);
153
- var that = this;
154
158
  event.cursor = event.cursor || this._getXY(event);
155
159
  this._mouseDown = true;
156
160
  var rect = this._viewport.getDomRef().getBoundingClientRect();
157
161
  startPoint.x = (event.cursor.x / rect.width) * 2 - 1;
158
162
  startPoint.y = -(event.cursor.y / rect.height) * 2 + 1;
159
- var dataMap = new Map();
160
- var dataType;
161
- var keyAlias;
162
- if (!event.ctrlKey) {
163
- this._selected.forEach(function (item) {
164
- if (item.type != 'InstancedMesh' || item.type != 'PlaneGeometry') {
165
- var obj = {};
166
- if (item._sapInstance != undefined) {
167
- var val = item._sapInstance;
168
- item._sapInstance["VB:s"] = "false";
169
- that._adapter._sceneBuilder.updateHotInstance(val);
170
- dataType = item._sapInstance.voGroup.datasource; // VO group data source linked to a DataType by name
171
- keyAlias = that._adapter._parser.getAttributeAlias(dataType, item._sapInstance.voGroup.keyAttributeName);
172
- obj[keyAlias] = item._sapInstance.id;
173
- obj["VB:s"] = "false";
174
- } else if (item.userData.name == "ColladaBounds") {
175
- if (item.userData._sapInstance["VB:s"] == "true") {
176
- var instance = item.userData._sapInstance;
177
- var selectionChanges = that._adapter._changeSelection(instance, "toggle", false);
178
- that._adapter._sceneBuilder.updateSelection(selectionChanges.selected, selectionChanges.deselected);
179
- dataType = item.userData._sapInstance.voGroup.datasource; // VO group data source linked to a DataType by name
180
- keyAlias = that._adapter._parser.getAttributeAlias(dataType, item.userData._sapInstance.voGroup.keyAttributeName);
181
- obj[keyAlias] = item.userData.id;
182
- obj["VB:s"] = "false";
183
- }
184
- }
185
-
186
- var existingData = dataMap.get(dataType);
187
- if (existingData != undefined ) {
188
- // Check if there's already an entry for this dataType
189
- var existingEntry = existingData.find(function (entry) {
190
- return entry.name === dataType;
191
- });
192
-
193
- if (existingEntry) {
194
- // If an entry exists for this dataType, push the new object to its E array if it's not already present
195
- var existingObject = existingEntry.E.find(function (e) {
196
- if (item._sapInstance != undefined)
197
- return e[keyAlias] === item._sapInstance.id
198
- else
199
- return e[keyAlias] === item.userData.id;
200
- });
201
- if (!existingObject && JSON.stringify(obj) !== '{}' ) {
202
- // If the object doesn't exist, push it to the E array
203
- existingEntry.E.push(obj);
204
- }
205
- }
206
- } else {
207
- // If no data exists for this dataType, create a new array and add the object
208
- dataMap.set(dataType, [{
209
- name: dataType,
210
- E: [obj]
211
- }]);
212
- }
213
- }
214
- });
215
-
216
- if (dataMap != undefined) {
217
- var payload = that._constructPayload(dataMap);
218
- if (payload.Data.Merge.N.length > 0) {
219
- this._adapter.fireSubmit({
220
- data: JSON.stringify(payload)
221
- });
222
- }
223
- }
224
- }
225
-
226
- this._selected.clear();
163
+ this._previousSelected = new Set(this._selected);
227
164
  };
228
165
 
229
166
  RectangleTracker.prototype._onPointerMove = function (event) {
@@ -239,102 +176,132 @@ sap.ui.define([
239
176
  // this._cameraControls.enableRotate = false;
240
177
  // }
241
178
  }
242
- RectangleTracker.prototype._onPointerUp = function (event) {
243
- this._updateController(true);
244
- if (!this._mouseDown) {
245
- var that = this;
246
- event.cursor = event.cursor || this._getXY(event);
247
- var rect = this._viewport.getDomRef().getBoundingClientRect();
248
- endPoint.x = (event.cursor.x / rect.width) * 2 - 1;
249
- endPoint.y = -(event.cursor.y / rect.height) * 2 + 1;
250
- endPoint.z = 0.5
251
- var isSelected = this.selecting(_frustum);
252
- var dataMap = new Map();
253
- var dataType;
254
- var keyAlias;
255
- var obj = {};
256
- if (isSelected.length > 0) {
257
- for (var i = 0; i < isSelected.length; i++) {
258
- this._selected.add(isSelected[i]);
179
+ RectangleTracker.prototype.buildEntry = function (item, selected, items) {
180
+ let dataType, keyAlias;
181
+ let obj = {};
182
+
183
+ if (item._sapInstance != undefined) {
184
+ const val = item._sapInstance;
185
+ item._sapInstance["VB:s"] = selected ? "true" : "false";
186
+ // maybe updateHotInstance only for selected?
187
+ this._adapter._sceneBuilder.updateHotInstance(val);
188
+ dataType = item._sapInstance.voGroup.datasource;
189
+ keyAlias = this._adapter._parser.getAttributeAlias(dataType, item._sapInstance.voGroup.keyAttributeName);
190
+ obj[keyAlias] = item._sapInstance.id;
191
+ obj["VB:s"] = selected ? "true" : "false";
192
+ } else if (item.userData.name === "ColladaBounds") {
193
+ if (selected === true) {
194
+ var id = item.userData.id;
195
+ var meshCount = item.userData.count;
196
+ var count = 0;
197
+ items.forEach(function (itemA) {
198
+ if (itemA.userData.id == id)
199
+ count++;
200
+ });
201
+ if (count == meshCount) {
202
+ var instance = item.userData._sapInstance;
203
+ var selectionChanges = this._adapter._changeSelection(instance, "select", false);
204
+ this._adapter._sceneBuilder.updateSelection(selectionChanges.selected, selectionChanges.deselected);
205
+ dataType = item.userData._sapInstance.voGroup.datasource; // VO group data source linked to a DataType by name
206
+ keyAlias = this._adapter._parser.getAttributeAlias(dataType, item.userData._sapInstance.voGroup.keyAttributeName);
207
+ obj[keyAlias] = item.userData.id;
208
+ obj["VB:s"] = "true";
259
209
  }
260
- }
261
- this._selected.forEach(function (item) {
262
- obj = {};
263
- if (item.type != 'InstancedMesh' || item.type != 'PlaneGeometry') {
264
- if (item._sapInstance != undefined) {
265
- var val = item._sapInstance;
266
- item._sapInstance["VB:s"] = "true";
267
- that._adapter._sceneBuilder.updateHotInstance(val);
268
- dataType = item._sapInstance.voGroup.datasource; // VO group data source linked to a DataType by name
269
- keyAlias = that._adapter._parser.getAttributeAlias(dataType, item._sapInstance.voGroup.keyAttributeName);
270
- obj[keyAlias] = item._sapInstance.id;
271
- obj["VB:s"] = "true";
272
- // that._adapter._handleHover(val);
273
- } else if (item.userData.name == "ColladaBounds") {
274
- var id = item.userData.id;
275
- var meshCount = item.userData.count;
276
- var count = 0;
277
- that._selected.forEach(function (itemA) {
278
- if (itemA.userData.id == id)
279
- count++;
280
- });
281
- if (count == meshCount) {
282
- var instance = item.userData._sapInstance;
283
- var selectionChanges = that._adapter._changeSelection(instance, "select", false);
284
- that._adapter._sceneBuilder.updateSelection(selectionChanges.selected, selectionChanges.deselected);
285
- dataType = item.userData._sapInstance.voGroup.datasource; // VO group data source linked to a DataType by name
286
- keyAlias = that._adapter._parser.getAttributeAlias(dataType, item.userData._sapInstance.voGroup.keyAttributeName);
287
- obj[keyAlias] = item.userData.id;
288
- obj["VB:s"] = "true";
289
- }
290
- }
291
-
292
-
293
- var existingData = dataMap.get(dataType);
294
- if (existingData != undefined) {
295
- // Check if there's already an entry for this dataType
296
- var existingEntry = existingData.find(function (entry) {
297
- return entry.name === dataType;
298
- });
299
- if (existingEntry) {
300
- // If an entry exists for this dataType, push the new object to its E array if it's not already present
301
- var existingObject = existingEntry.E.find(function (e) {
302
- if (item._sapInstance != undefined)
303
- return e[keyAlias] === item._sapInstance.id
304
- else
305
- return e[keyAlias] === item.userData.id;
306
- });
307
- if (!existingObject && JSON.stringify(obj) !== '{}') {
308
- // If the object doesn't exist, push it to the E array
309
- existingEntry.E.push(obj);
310
- }
311
- }
312
- } else {
313
- // If no data exists for this dataType, create a new array and add the object
314
- dataMap.set(dataType, [{
315
- name: dataType,
316
- E: [obj]
317
- }]);
318
- }
319
-
210
+ } else {
211
+ if (item.userData._sapInstance["VB:s"] == "true") {
212
+ var instance = item.userData._sapInstance;
213
+ var selectionChanges = this._adapter._changeSelection(instance, "toggle", false);
214
+ this._adapter._sceneBuilder.updateSelection(selectionChanges.selected, selectionChanges.deselected);
215
+ // your ColladaBounds logic with selected/deselected
216
+ dataType = item.userData._sapInstance.voGroup.datasource;
217
+ keyAlias = this._adapter._parser.getAttributeAlias(dataType, item.userData._sapInstance.voGroup.keyAttributeName);
218
+ obj[keyAlias] = item.userData.id;
219
+ obj["VB:s"] = selected ? "true" : "false";
320
220
  }
321
- });
221
+ }
222
+ }
223
+
224
+ return { dataType, keyAlias, obj };
225
+ };
226
+
227
+ RectangleTracker.prototype.addToDataMap = function (dataMap, dataType, obj, keyAlias, item) {
228
+ if (!dataType || !obj) return;
229
+ const existingData = dataMap.get(dataType);
230
+ if (existingData) {
231
+ const existingEntry = existingData.find(entry => entry.name === dataType);
232
+ if (existingEntry) {
233
+ const existingObject = existingEntry.E.find(e => {
234
+ if (item._sapInstance != undefined)
235
+ return e[keyAlias] === item._sapInstance.id;
236
+ else
237
+ return e[keyAlias] === item.userData.id;
238
+ });
239
+ if (!existingObject && JSON.stringify(obj) !== '{}') existingEntry.E.push(obj);
240
+ }
241
+ } else {
242
+ dataMap.set(dataType, [{ name: dataType, E: [obj] }]);
243
+ }
244
+ };
245
+
246
+ RectangleTracker.prototype._onPointerUp = function (event) {
247
+ this._updateController(true);
248
+ if (this._mouseDown) return;
322
249
 
250
+ event.cursor = event.cursor || this._getXY(event);
251
+ var rect = this._viewport.getDomRef().getBoundingClientRect();
252
+ endPoint.x = (event.cursor.x / rect.width) * 2 - 1;
253
+ endPoint.y = -(event.cursor.y / rect.height) * 2 + 1;
254
+ endPoint.z = 0.5
255
+
256
+ const inside = this.selecting(_frustum); // all objects in rectangle
257
+ if (inside.length === 0) {
258
+ this._mouseDown = false;
259
+ this._dom.style.cursor = this._hovered ? "pointer" : "auto";
260
+ this.onSelectOver();
261
+ return;
323
262
  }
324
- if (dataMap != undefined) {
325
- var payload = that._constructPayload(dataMap);
263
+ // build new selection set
264
+ const newSelected = new Set(inside);
265
+
266
+ // deselect items not in rectangle anymore
267
+ var deselected = [...this._previousSelected].filter(i => !newSelected.has(i));
268
+
269
+ // select items newly in rectangle
270
+ //const newlySelected = [...newSelected].filter(i => !this._previousSelected.has(i));
271
+
272
+ // update your internal set
273
+ this._selected.clear();
274
+ newSelected.forEach(i => this._selected.add(i));
275
+
276
+ // build a single dataMap for deselection + selection
277
+ const dataMap = new Map();
278
+
279
+ // handle deselection
280
+ deselected.forEach(item => {
281
+ const { dataType, keyAlias, obj } = this.buildEntry(item, false, deselected); // VB:s false
282
+ this.addToDataMap(dataMap, dataType, obj, keyAlias, item);
283
+ });
284
+
285
+ // handle selection
286
+ inside.forEach(item => {
287
+ const { dataType, keyAlias, obj } = this.buildEntry(item, true, inside); // VB:s true
288
+ this.addToDataMap(dataMap, dataType, obj, keyAlias, item);
289
+ });
290
+
291
+ if (dataMap.size > 0) {
292
+ const payload = this._constructPayload(dataMap);
326
293
  if (payload.Data.Merge.N.length > 0) {
327
- this._adapter.fireSubmit({
328
- data: JSON.stringify(payload)
329
- });
294
+ this._adapter.fireSubmit({ data: JSON.stringify(payload) });
330
295
  }
331
296
  }
297
+
332
298
  this._mouseDown = false;
333
299
  this._dom.style.cursor = this._hovered ? "pointer" : "auto";
334
300
  this._updateController(true);
335
301
  this.onSelectOver();
336
302
  };
337
303
 
304
+
338
305
  RectangleTracker.prototype._constructPayload = function (dataMap) {
339
306
  var payload = {
340
307
  version: "2.0",
@@ -420,6 +387,14 @@ sap.ui.define([
420
387
  this.startPoint = startPoint || this.startPoint;
421
388
  this.endPoint = endPoint || this.endPoint;
422
389
  this.collection = [];
390
+ const dx = Math.abs(endPoint.x - startPoint.x);
391
+ const dy = Math.abs(endPoint.y - startPoint.y);
392
+
393
+ // if less than 2-3 pixels movement => treat as click, skip updateFrustum
394
+ if (dx < 0.002 && dy < 0.002) {
395
+ // 👉 handle as simple click (use raycaster for single object select)
396
+ return;
397
+ }
423
398
  this.updateFrustum(this.startPoint, this.endPoint);
424
399
  this.searchChildInFrustum(_frustum, this._scene);
425
400
  this._scene.remove(this._planeMesh);
@@ -447,18 +422,20 @@ sap.ui.define([
447
422
 
448
423
  if (this._camera.isPerspectiveCamera) {
449
424
 
450
- _tmpPoint = startPoint;
451
- _tmpPoint.x = Math.min(startPoint.x, endPoint.x);
452
- _tmpPoint.y = Math.max(startPoint.y, endPoint.y);
453
- endPoint.x = Math.max(startPoint.x, endPoint.x);
454
- endPoint.y = Math.min(startPoint.y, endPoint.y);
425
+ // Normalize rectangle regardless of drag direction
426
+ var minX = Math.min(startPoint.x, endPoint.x);
427
+ var maxX = Math.max(startPoint.x, endPoint.x);
428
+ var minY = Math.min(startPoint.y, endPoint.y);
429
+ var maxY = Math.max(startPoint.y, endPoint.y);
455
430
 
456
- _vecNear.setFromMatrixPosition(this._camera.matrixWorld);
457
- _vecTopLeft.copy(_tmpPoint);
458
- _vecTopRight.set(endPoint.x, _tmpPoint.y, 0);
459
- _vecDownRight.copy(endPoint);
460
- _vecDownLeft.set(_tmpPoint.x, endPoint.y, 0);
461
431
 
432
+ _vecNear.setFromMatrixPosition(this._camera.matrixWorld);
433
+ // Define corners in NDC (normalized device coordinates)
434
+ _vecTopLeft.set(minX, maxY, 0);
435
+ _vecTopRight.set(maxX, maxY, 0);
436
+ _vecDownRight.set(maxX, minY, 0);
437
+ _vecDownLeft.set(minX, minY, 0);
438
+
462
439
  _vecTopLeft.unproject(this._camera);
463
440
  _vecTopRight.unproject(this._camera);
464
441
  _vecDownRight.unproject(this._camera);
@@ -467,9 +444,12 @@ sap.ui.define([
467
444
  _vectemp1.copy(_vecTopLeft).sub(_vecNear);
468
445
  _vectemp2.copy(_vecTopRight).sub(_vecNear);
469
446
  _vectemp3.copy(_vecDownRight).sub(_vecNear);
447
+ _vectemp4.copy(_vecDownLeft).sub(_vecNear)
448
+
470
449
  _vectemp1.normalize();
471
450
  _vectemp2.normalize();
472
451
  _vectemp3.normalize();
452
+ _vectemp4.normalize();
473
453
 
474
454
 
475
455
  _vectemp1.multiplyScalar(this.deep);
@@ -479,6 +459,7 @@ sap.ui.define([
479
459
  _vectemp1.sub(_vecNear);
480
460
  _vectemp2.sub(_vecNear);
481
461
  _vectemp3.sub(_vecNear);
462
+ _vectemp4.sub(_vecNear);
482
463
 
483
464
  var planes = _frustum.planes;
484
465
 
@@ -492,7 +473,7 @@ sap.ui.define([
492
473
  }
493
474
 
494
475
 
495
- }
476
+ };
496
477
 
497
478
  RectangleTracker.prototype.searchChildInFrustum = function (frustum, object) {
498
479
  var count = 0;
@@ -47,7 +47,7 @@ sap.ui.define([
47
47
  *
48
48
  * @private
49
49
  * @author SAP SE
50
- * @version 1.140.0
50
+ * @version 1.142.0
51
51
  * @alias sap.ui.vbm.adapter3d.SceneBuilder
52
52
  */
53
53
  var SceneBuilder = BaseObject.extend("sap.ui.vbm.adapter3d.SceneBuilder", /** @lends sap.ui.vbm.adapter3d.SceneBuilder.prototype */ {
@@ -56,7 +56,7 @@ sap.ui.define([
56
56
  *
57
57
  * @private
58
58
  * @author SAP SE
59
- * @version 1.140.0
59
+ * @version 1.142.0
60
60
  * @alias sap.ui.vbm.adapter3d.VBIJSONParser
61
61
  */
62
62
  var VBIJSONParser = BaseObject.extend("sap.ui.vbm.adapter3d.VBIJSONParser", /** @lends sap.ui.vbm.adapter3d.VBIJSONParser.prototype */ {
@@ -20,7 +20,7 @@ sap.ui.define([
20
20
  * @namespace
21
21
  * @alias sap.ui.vbm
22
22
  * @author SAP SE
23
- * @version 1.140.0
23
+ * @version 1.142.0
24
24
  * @public
25
25
  */
26
26
 
@@ -46,7 +46,7 @@ sap.ui.define([
46
46
  "sap.ui.vbm.ClusterBase", "sap.ui.vbm.ClusterTree", "sap.ui.vbm.ClusterGrid", "sap.ui.vbm.ClusterDistance", "sap.ui.vbm.Heatmap",
47
47
  "sap.ui.vbm.HeatPoint", "sap.ui.vbm.ClusterContainer", "sap.ui.vbm.Adapter", "sap.ui.vbm.Adapter3D"
48
48
  ],
49
- version: "1.140.0"
49
+ version: "1.142.0"
50
50
  });
51
51
 
52
52
  sap.ui.loader.config({
@@ -163,7 +163,9 @@ sap.ui.define([
163
163
  let markerCoordinates = marker.geometry.coordinates;
164
164
  if (marker.geometry.type === 'Point') {
165
165
  // create a DOM element for the marker (parent div)
166
- const el = VectorUtils.createSpotElement(marker);
166
+ let createdSpot = VectorUtils.createSpotElement(marker, spotid);
167
+ const el = createdSpot.spotEl;
168
+ spotid = createdSpot.spotId;
167
169
  if (marker.properties.Label) {
168
170
  const child_e1 = VectorUtils.createMarkerLabel(marker.properties.Label, marker.properties.LabelBGColor);
169
171
  el.appendChild(child_e1);
@@ -180,7 +182,7 @@ sap.ui.define([
180
182
  let spot = new maplibregl.Marker({
181
183
  element: el,
182
184
  draggable: true,
183
- offset: [0, -20]
185
+ anchor: 'bottom'
184
186
  }).setLngLat(marker.geometry.coordinates)
185
187
  .on('dragend', onDragEnd)
186
188
  .addTo(map);
@@ -514,15 +516,21 @@ sap.ui.define([
514
516
  }
515
517
  } else if (marker.geometry.type == "LineString") {
516
518
 
517
- const colorStr = marker.properties.LineColor;
518
- let textColor = '#000000'; // Default color
519
-
520
- if (colorStr) {
521
- const [r, g, b, a] = VectorUtils.parseRGBAString(colorStr);
522
- textColor = VectorUtils.getContrastTextColor(r, g, b);
523
- marker.properties.labelHaloColor = `rgba(${r}, ${g}, ${b}, ${a})`;
519
+ if (marker.properties.Label) {
520
+ const midpoint = getMidpoint(marker.geometry.coordinates);
521
+
522
+ const routeLabelEl = VectorUtils.createRouteLabel(
523
+ marker.properties.Label,
524
+ marker.properties.LabelBGColor
525
+ );
526
+
527
+ new maplibregl.Marker({
528
+ element: routeLabelEl,
529
+ anchor: 'left',
530
+ })
531
+ .setLngLat(midpoint)
532
+ .addTo(map);
524
533
  }
525
- marker.properties.textColor = textColor;
526
534
  const coords = marker.geometry.coordinates;
527
535
  const startCoord = coords[0]; // First coordinate
528
536
  const endCoord = coords[coords.length - 1]; // Last coordinate
@@ -621,29 +629,17 @@ sap.ui.define([
621
629
  },
622
630
  'filter': ['==', '$type', 'LineString']
623
631
  });
624
-
625
- map.addLayer({
626
- id: 'line-labels',
627
- type: 'symbol',
628
- source: 'geojson-source',
629
- layout: {
630
- 'symbol-placement': 'line-center',
631
- 'text-field': ['get', 'Label'],
632
- 'text-font': ['Open Sans Regular', 'Arial Unicode MS Regular'],
633
- 'text-size': 14,
634
- 'text-rotation-alignment': 'map',
635
- 'text-keep-upright': true
636
- },
637
- paint: {
638
- 'text-color': ['get', 'lineLabelTextColor'],
639
- 'text-halo-color': ['get', 'labelHaloColor'],
640
- 'text-halo-width': 4,
641
- 'text-halo-blur': 0.8,
642
- 'text-opacity': ['get', 'opacity']
643
- },
644
-
645
- filter: ['all', ['==', ['get', 'ShowLabel'], true]]
646
- });
632
+
633
+ function getMidpoint(coords) {
634
+ if (coords.length < 2) return coords[0];
635
+
636
+ const start = coords[0];
637
+ const end = coords[coords.length - 1];
638
+ const midLng = (start[0] + end[0]) / 2;
639
+ const midLat = (start[1] + end[1]) / 2;
640
+
641
+ return [midLng, midLat];
642
+ }
647
643
 
648
644
  // Create a new FeatureCollection for the points
649
645
  const pointGeoJSON = {
@@ -933,7 +929,7 @@ sap.ui.define([
933
929
  PayloadGenerator.onMapContextMenu(coords, currentZoom, currentCenter, screenX, screenY);
934
930
  }
935
931
  };
936
-
932
+
937
933
  var that = this;
938
934
  map.on('idle', () => {
939
935
  const container = map.getContainer();
@@ -12,7 +12,7 @@ sap.ui.define([
12
12
  *
13
13
  * @private
14
14
  * @author SAP SE
15
- * @version 1.140.0
15
+ * @version 1.142.0
16
16
  * @alias sap.ui.vbm.vector.PayloadGenerator
17
17
  */
18
18
  var adapter = {};
@@ -12,7 +12,7 @@ sap.ui.define([
12
12
  *
13
13
  * @private
14
14
  * @author SAP SE
15
- * @version 1.140.0
15
+ * @version 1.142.0
16
16
  * @alias sap.ui.vbm.vector.RectangularSelection
17
17
  */
18
18
 
@@ -223,12 +223,10 @@ sap.ui.define([
223
223
  "Image": currSpot.I ? currSpot.I : "",
224
224
  "base64": resources.find(resource => resource.name === currSpot.I)?.value || defaultbase64,
225
225
  "Key": currSpot.K ? currSpot.K : "",
226
- "Scale": currSpot.S ? currSpot.S : "",
226
+ "Scale": currSpot.S ? currSpot.S : "1;1;1",
227
227
  "DisplayRole": currSpot.R ? currSpot.R : "",
228
228
  "DragData": currSpot.DD ? currSpot.DD : "",
229
229
  "Alignment": currSpot.AL ? currSpot.AL : "",
230
- "height": resources.find(resource => resource.name === currSpot.I) ? '45px' : '30px',
231
- "width": resources.find(resource => resource.name === currSpot.I) ? '45px' : '24px',
232
230
  "menu": menus,
233
231
  "type": "{00100000-2012-0004-B001-64592B8DB964}"
234
232
  };
@@ -273,15 +271,12 @@ sap.ui.define([
273
271
  "Image": currSpot.I ? currSpot.I : "",
274
272
  "base64": resources.find(resource => resource.name === currSpot.I)?.value || defaultbase64,
275
273
  "Key": currSpot.K ? currSpot.K : "",
276
- "Scale": currSpot.S ? currSpot.S : "",
274
+ "Scale": currSpot.S ? currSpot.S : "1;1;1",
277
275
  "DisplayRole": currSpot.R ? currSpot.R : "",
278
276
  "DragData": currSpot.DD ? currSpot.DD : "",
279
277
  "Alignment": currSpot.AL ? currSpot.AL : "",
280
- "height": resources.find(resource => resource.name === currSpot.I) ? '45px' : '30px',
281
- "width": resources.find(resource => resource.name === currSpot.I) ? '45px' : '24px',
282
278
  "type": "{00100000-2012-0004-B001-64592B8DB964}"
283
-
284
- };
279
+ };
285
280
 
286
281
  let coord_array = currSpot.A.split(";");
287
282
 
@@ -361,7 +356,6 @@ sap.ui.define([
361
356
  routeProperties["opacity"] = opacity;
362
357
  }
363
358
 
364
- //itearate through the route points and add the coordinates to the GeoJSON
365
359
  let coord_array = currRoute.H.split(";");
366
360
  let coord_collection = [];
367
361
 
@@ -369,6 +363,7 @@ sap.ui.define([
369
363
  coord_collection.push([Number(coord_array[i]), Number(coord_array[i + 1])])
370
364
  }
371
365
 
366
+
372
367
  let geometry = {
373
368
  "coordinates": coord_collection,
374
369
  "type": "LineString"
@@ -747,12 +742,27 @@ sap.ui.define([
747
742
  // code block
748
743
  }
749
744
  }
750
-
751
745
  }
752
746
  }
753
747
  }
754
748
 
755
-
749
+ featureCollection = Object.values(
750
+ featureCollection.reduce((acc, f) => {
751
+ const key = f.properties?.Key;
752
+ if (!key) return acc; // skip if no key
753
+
754
+ if (!acc[key]) {
755
+ acc[key] = { ...f };
756
+ } else {
757
+ // Merge properties if duplicate found
758
+ acc[key].properties = {
759
+ ...acc[key].properties,
760
+ ...f.properties
761
+ };
762
+ }
763
+ return acc;
764
+ }, {})
765
+ );
756
766
  if (obj.SAPVB.Data.Remove) {
757
767
 
758
768
  let del = obj.SAPVB.Data.Remove;
@@ -814,6 +824,13 @@ sap.ui.define([
814
824
  }
815
825
  }
816
826
 
827
+ if (obj.SAPVB.Data.Set && (typeof obj.SAPVB.Data.Set === 'object') && !(jQuery.isEmptyObject(obj.SAPVB.Data.Set))) {
828
+ if (!Array.isArray(obj.SAPVB.Data.Set) && !(obj.SAPVB.Data.Set.name) && !(obj.SAPVB.Data.Set.type)) {
829
+ //Full Update - Replace complete Data Section
830
+ featureCollection.splice(0, featureCollection.length);
831
+ }
832
+ }
833
+
817
834
  }
818
835
 
819
836
  // Get the datatypes
@@ -34,18 +34,27 @@ sap.ui.define([
34
34
  });
35
35
  };
36
36
 
37
- VectorUtils.createSpotElement = (marker) => {
38
- // create a DOM element for the marker (parent div)
37
+ VectorUtils.createSpotElement = (marker, spotid) => {
39
38
  const el = document.createElement('div');
40
-
41
- // Set background image for the marker
42
- var base64decoded = "data:image/png;base64," + marker.properties.base64;
39
+ const base64decoded = "data:image/png;base64," + (marker.properties.base64 || "");
40
+ el.id = '__mapmarker' + spotid++;
43
41
  el.style.backgroundImage = `url(${base64decoded})`;
44
- el.style.width = marker.properties.width;
45
- el.style.height = marker.properties.height;
46
- el.style.backgroundSize = 'cover'; // Ensure image fits
47
- return el;
42
+ el.style.backgroundSize = 'cover';
43
+ el.style.display = 'inline-block';
44
+ el.style.transform = 'translate(-50%, -100%)';
45
+
46
+ // load the image to get natural size
47
+ const img = new Image();
48
+ img.src = base64decoded;
49
+ img.onload = () => {
50
+ const scaleParts = (marker.properties.Scale || "1;1;1").split(';').map(Number);
51
+ const [sx, sy] = scaleParts.some(isNaN) ? [1, 1] : [scaleParts[0], scaleParts[1]];
52
+ el.style.width = `${img.naturalWidth * sx}px`;
53
+ el.style.height = `${img.naturalHeight * sy}px`;
54
+ };
55
+ return {spotEl:el, spotId:spotid};
48
56
  };
57
+
49
58
  VectorUtils.isAccepted = (drag, drop) => {
50
59
  var validDrop = drag.some(item => drop.includes(item));
51
60
  return validDrop;
@@ -252,8 +261,43 @@ sap.ui.define([
252
261
  obj.style.color = textColor;
253
262
  obj.style.fontFamily = 'Arial, sans-serif';
254
263
  obj.style.fontSize = '14px';
264
+ obj.style.padding = '2px 6px';
265
+ obj.style.borderRadius = '4px';
266
+ obj.style.whiteSpace = 'pre-wrap';
267
+ obj.style.boxSizing = 'border-box';
268
+ obj.style.textAlign = 'center';
269
+
255
270
  return obj;
256
271
  }
272
+
273
+ VectorUtils.createRouteLabel = (label, labelcolor) => {
274
+ let r, g, b, a;
275
+ const obj = document.createElement('div');
276
+ obj.className = 'route-label';
277
+ obj.textContent = label;
278
+
279
+ if (!labelcolor) {
280
+ [r, g, b, a] = [211, 211, 211, 1];
281
+ } else {
282
+ [r, g, b, a] = VectorUtils.parseRGBAString(labelcolor);
283
+ }
284
+
285
+ const textColor = VectorUtils.getContrastTextColor(r, g, b);
286
+
287
+ obj.style.backgroundColor = `rgba(${r}, ${g}, ${b}, ${a})`;
288
+ obj.style.border = `2px solid rgba(${r}, ${g}, ${b}, ${a})`;
289
+ obj.style.color = textColor;
290
+ obj.style.fontFamily = 'Arial, sans-serif';
291
+ obj.style.fontSize = '14px';
292
+ obj.style.padding = '2px 6px';
293
+ obj.style.borderRadius = '4px';
294
+ obj.style.whiteSpace = 'pre-wrap';
295
+ obj.style.boxSizing = 'border-box';
296
+ obj.style.textAlign = 'center';
297
+
298
+ return obj;
299
+ };
300
+
257
301
  VectorUtils.rgbaToHexAndOpacity = (rgbaString) => {
258
302
  const rgbaRegex = /rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d*\.?\d+)\s*\)/i;
259
303
  const match = rgbaString.match(rgbaRegex);