@configura/babylon-view 2.1.0-alpha.3 → 2.2.0-alpha.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.
Files changed (134) hide show
  1. package/.eslintrc.json +5 -5
  2. package/LICENSE +201 -201
  3. package/README.md +1 -1
  4. package/dist/animation/AnimatableObject.d.ts +8 -8
  5. package/dist/animation/AnimatableObject.js +3 -3
  6. package/dist/animation/animator/Animator.d.ts +33 -33
  7. package/dist/animation/animator/Animator.js +58 -58
  8. package/dist/animation/animator/AnimatorEasing.d.ts +16 -16
  9. package/dist/animation/animator/AnimatorEasing.js +31 -31
  10. package/dist/animation/animator/AnimatorEasingMatrix.d.ts +14 -14
  11. package/dist/animation/animator/AnimatorEasingMatrix.js +16 -16
  12. package/dist/animation/animator/AnimatorHighlight.d.ts +16 -16
  13. package/dist/animation/animator/AnimatorHighlight.js +32 -32
  14. package/dist/animation/animator/AnimatorPointToPoint.d.ts +8 -8
  15. package/dist/animation/animator/AnimatorPointToPoint.js +14 -14
  16. package/dist/animation/animator/AnimatorQueue.d.ts +13 -13
  17. package/dist/animation/animator/AnimatorQueue.js +57 -57
  18. package/dist/animation/animator/AnimatorScale.d.ts +8 -8
  19. package/dist/animation/animator/AnimatorScale.js +13 -13
  20. package/dist/animation/animator/AnimatorSpin.d.ts +10 -10
  21. package/dist/animation/animator/AnimatorSpin.js +13 -13
  22. package/dist/animation/animator/EasingFunctions.d.ts +35 -35
  23. package/dist/animation/animator/EasingFunctions.js +137 -137
  24. package/dist/animation/coordinator/Coordinator.d.ts +28 -28
  25. package/dist/animation/coordinator/Coordinator.js +53 -53
  26. package/dist/animation/coordinator/CoordinatorDropAndSpin.d.ts +22 -22
  27. package/dist/animation/coordinator/CoordinatorDropAndSpin.js +138 -138
  28. package/dist/animation/coordinator/CoordinatorIdentity.d.ts +11 -11
  29. package/dist/animation/coordinator/CoordinatorIdentity.js +14 -14
  30. package/dist/animation/coordinator/CoordinatorNodeQueues.d.ts +18 -18
  31. package/dist/animation/coordinator/CoordinatorNodeQueues.js +50 -50
  32. package/dist/animation/coordinator/CoordinatorPulse.d.ts +21 -21
  33. package/dist/animation/coordinator/CoordinatorPulse.js +47 -47
  34. package/dist/animation/coordinator/CoordinatorPulseBounce.d.ts +14 -14
  35. package/dist/animation/coordinator/CoordinatorPulseBounce.js +35 -35
  36. package/dist/animation/coordinator/CoordinatorPulseHighlight.d.ts +13 -13
  37. package/dist/animation/coordinator/CoordinatorPulseHighlight.js +29 -29
  38. package/dist/animation/coordinator/CoordinatorPulseInflate.d.ts +14 -14
  39. package/dist/animation/coordinator/CoordinatorPulseInflate.js +23 -23
  40. package/dist/camera/CameraCreator.d.ts +5 -5
  41. package/dist/camera/CameraCreator.js +4 -4
  42. package/dist/camera/CfgOrbitalCamera.d.ts +76 -76
  43. package/dist/camera/CfgOrbitalCamera.js +277 -281
  44. package/dist/camera/CfgOrbitalCameraControlProps.d.ts +14 -14
  45. package/dist/camera/CfgOrbitalCameraControlProps.js +7 -7
  46. package/dist/camera/GradingApplier.d.ts +3 -3
  47. package/dist/camera/GradingApplier.js +48 -48
  48. package/dist/engine/EngineCreator.d.ts +3 -3
  49. package/dist/engine/EngineCreator.js +10 -10
  50. package/dist/geometry/CfgGeometry.d.ts +29 -29
  51. package/dist/geometry/CfgGeometry.js +146 -146
  52. package/dist/geometry/CfgMesh.d.ts +10 -10
  53. package/dist/geometry/CfgMesh.js +38 -38
  54. package/dist/geometry/geoSplitter.d.ts +8 -8
  55. package/dist/geometry/geoSplitter.js +192 -192
  56. package/dist/geometry/stretch/CfgMorphTarget.d.ts +15 -15
  57. package/dist/geometry/stretch/CfgMorphTarget.js +65 -65
  58. package/dist/geometry/stretch/CfgStretchData.d.ts +116 -116
  59. package/dist/geometry/stretch/CfgStretchData.js +347 -350
  60. package/dist/geometry/stretch/CfgStretchMorphGeometry.d.ts +16 -16
  61. package/dist/geometry/stretch/CfgStretchMorphGeometry.js +95 -95
  62. package/dist/index.d.ts +16 -16
  63. package/dist/index.js +16 -16
  64. package/dist/io/CfgHistoryToCameraConfConnector.d.ts +31 -31
  65. package/dist/io/CfgHistoryToCameraConfConnector.js +90 -90
  66. package/dist/io/CfgIOCameraConfConnector.d.ts +35 -35
  67. package/dist/io/CfgIOCameraConfConnector.js +81 -81
  68. package/dist/io/CfgObservableStateToCameraConfConnector.d.ts +10 -10
  69. package/dist/io/CfgObservableStateToCameraConfConnector.js +11 -11
  70. package/dist/io/CfgWindowMessageToCameraConfConnector.d.ts +10 -10
  71. package/dist/io/CfgWindowMessageToCameraConfConnector.js +11 -11
  72. package/dist/light/CfgDirectionalLight.d.ts +8 -8
  73. package/dist/light/CfgDirectionalLight.js +18 -18
  74. package/dist/light/CfgHemisphericLight.d.ts +7 -7
  75. package/dist/light/CfgHemisphericLight.js +17 -17
  76. package/dist/light/CfgPointLight.d.ts +8 -8
  77. package/dist/light/CfgPointLight.js +18 -18
  78. package/dist/light/DefaultLightRig.d.ts +19 -19
  79. package/dist/light/DefaultLightRig.js +77 -77
  80. package/dist/light/LightRigCreator.d.ts +9 -9
  81. package/dist/light/LightRigCreator.js +3 -3
  82. package/dist/material/CfgMaterial.d.ts +68 -68
  83. package/dist/material/CfgMaterial.js +482 -482
  84. package/dist/material/DummyMaterialCreator.d.ts +4 -4
  85. package/dist/material/DummyMaterialCreator.js +15 -15
  86. package/dist/material/material.d.ts +18 -18
  87. package/dist/material/material.js +128 -128
  88. package/dist/material/texture.d.ts +14 -14
  89. package/dist/material/texture.js +306 -306
  90. package/dist/nodes/CfgContentRootNode.d.ts +19 -19
  91. package/dist/nodes/CfgContentRootNode.js +75 -75
  92. package/dist/nodes/CfgDeferredMeshNode.d.ts +55 -55
  93. package/dist/nodes/CfgDeferredMeshNode.js +378 -378
  94. package/dist/nodes/CfgProductNode.d.ts +127 -127
  95. package/dist/nodes/CfgProductNode.js +598 -598
  96. package/dist/nodes/CfgSymNode.d.ts +50 -50
  97. package/dist/nodes/CfgSymNode.js +249 -249
  98. package/dist/nodes/CfgSymRootNode.d.ts +45 -45
  99. package/dist/nodes/CfgSymRootNode.js +240 -229
  100. package/dist/nodes/CfgTransformNode.d.ts +33 -33
  101. package/dist/nodes/CfgTransformNode.js +83 -83
  102. package/dist/scene/SceneCreator.d.ts +6 -6
  103. package/dist/scene/SceneCreator.js +22 -22
  104. package/dist/utilities/CfgBoundingBox.d.ts +21 -21
  105. package/dist/utilities/CfgBoundingBox.js +81 -81
  106. package/dist/utilities/anchor/anchor.d.ts +50 -50
  107. package/dist/utilities/anchor/anchor.js +133 -133
  108. package/dist/utilities/anchor/anchorMap.d.ts +20 -20
  109. package/dist/utilities/anchor/anchorMap.js +111 -111
  110. package/dist/utilities/utilities3D.d.ts +70 -70
  111. package/dist/utilities/utilities3D.js +259 -265
  112. package/dist/utilities/utilitiesColor.d.ts +18 -18
  113. package/dist/utilities/utilitiesColor.js +50 -50
  114. package/dist/utilities/utilitiesImage.d.ts +6 -6
  115. package/dist/utilities/utilitiesImage.js +107 -107
  116. package/dist/utilities/utilitiesSymRootIdentifier.d.ts +7 -7
  117. package/dist/utilities/utilitiesSymRootIdentifier.js +26 -26
  118. package/dist/view/BaseView.d.ts +78 -78
  119. package/dist/view/BaseView.js +303 -303
  120. package/dist/view/BaseViewConfiguration.d.ts +32 -32
  121. package/dist/view/BaseViewConfiguration.js +10 -10
  122. package/dist/view/RenderEnv.d.ts +43 -43
  123. package/dist/view/RenderEnv.js +7 -7
  124. package/dist/view/SingleProductDefaultCameraView.d.ts +38 -38
  125. package/dist/view/SingleProductDefaultCameraView.js +149 -149
  126. package/dist/view/SingleProductDefaultCameraViewConfiguration.d.ts +44 -44
  127. package/dist/view/SingleProductDefaultCameraViewConfiguration.js +11 -11
  128. package/dist/view/SingleProductView.d.ts +44 -44
  129. package/dist/view/SingleProductView.js +212 -212
  130. package/dist/view/SingleProductViewConfiguration.d.ts +32 -32
  131. package/dist/view/SingleProductViewConfiguration.js +19 -19
  132. package/package.json +12 -7
  133. package/dist/camera/CfgArcRotateCameraPointersInput.d.ts +0 -27
  134. package/dist/camera/CfgArcRotateCameraPointersInput.js +0 -266
@@ -1,281 +1,277 @@
1
- import { PointerEventTypes } from "@babylonjs/core";
2
- import { ArcRotateCamera } from "@babylonjs/core/Cameras/arcRotateCamera.js";
3
- import { Vector3 } from "@babylonjs/core/Maths/math.vector.js";
4
- import { degToRad, normalizeAngle, Observable } from "@configura/web-utilities";
5
- import { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
6
- import { boundingBoxesAreSignificantlyDifferent, measureLongestDistanceToCorner, } from "../utilities/utilities3D.js";
7
- import { CfgArcRotateCameraPointersInput } from "./CfgArcRotateCameraPointersInput.js";
8
- import { orbitalCameraControlPropsEquals, } from "./CfgOrbitalCameraControlProps.js";
9
- const NEAREST_ALLOWED_TO_BETA_LIMITS = 0.1;
10
- export const MAX_UPPER_BETA_LIMIT = Math.PI - NEAREST_ALLOWED_TO_BETA_LIMITS;
11
- export const MIN_LOWER_BETA_LIMIT = NEAREST_ALLOWED_TO_BETA_LIMITS;
12
- const defaultOrbitalCameraConfig = {
13
- fov: degToRad(30),
14
- mouseWheelSpeedFactor: 200,
15
- pinchZoomFactor: 100,
16
- inertia: 0.93,
17
- keyboardSpeedFactor: 0.002,
18
- pointerSpeedFactor: 2000,
19
- keepCameraFromGettingTooCloseFactor: 1.5,
20
- significantBoundingBoxSizeChangeShrinkFactor: 0.4,
21
- significantBoundingBoxSizeChangeGrowFactor: 0.1,
22
- };
23
- // Babylon initializes radius to this to avoid divide by zero
24
- const BABYLON_DO_NOT_DIVIDE_BY_ZERO_MAGIC_CONSTANT = 0.0001;
25
- // This is a workaround as you are not allowed to override fields with accessors.
26
- // By adding this abstract field this becomes possible. This is a hack.
27
- class WorkaroundCfgOrbitalCamera extends ArcRotateCamera {
28
- }
29
- export class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
30
- constructor(scene, _canvas, config) {
31
- super("CfgOrbitalCamera", 0, degToRad(90), 50, new Vector3(0, 0, 0), scene);
32
- this._canvas = _canvas;
33
- this._currentBoundingBox = new CfgBoundingBox();
34
- this._latestSignificantChangeBoundingBox = new CfgBoundingBox();
35
- this._disableSubFloorCam = false;
36
- this._lowestAllowedCameraHeight = undefined;
37
- this._pointerDown = false;
38
- this.disableAutomaticSizing = false;
39
- this.disableZoom = false;
40
- this._externalControlHasHappened = false;
41
- this._radius = 0;
42
- this._boundCameraListener = () => {
43
- // This is a cheap operation, so it's acceptable to do it
44
- // for every update (even if no radius-change has happened)
45
- this._applyNoSneakPeeking();
46
- this._notifyCameraControlListeners();
47
- };
48
- this._pointerUpDownCallback = (p, s) => {
49
- if (p.type === PointerEventTypes.POINTERUP) {
50
- this._pointerDown = false;
51
- this._notifyCameraControlListeners();
52
- }
53
- if (p.type === PointerEventTypes.POINTERDOWN) {
54
- this._pointerDown = true;
55
- }
56
- };
57
- this.attachControl(_canvas, // This parameters is not actually used for anything. But still required.
58
- false, // No panning with keyboard
59
- false // No panning with mouse
60
- );
61
- // Workaround for touch issues on iOS, see comments in CfgArcRotateCameraPointersInput.ts
62
- this.inputs.removeByType("ArcRotateCameraPointersInput");
63
- this.inputs.add(new CfgArcRotateCameraPointersInput());
64
- // Make sure to disable all forms of "panning", which for the ArcRotateCamera is defined
65
- // as movement sideways without rotation to keep the camera centered on the target.
66
- // The settings above for attachControl will not disable two-finger touch.
67
- this.panningAxis = Vector3.Zero();
68
- this.panningDistanceLimit = 0;
69
- this.panningSensibility = 0;
70
- this.panningInertia = 0;
71
- this._config = Object.assign(Object.assign({}, defaultOrbitalCameraConfig), config);
72
- const keyboardInput = this.inputs.attached["keyboard"];
73
- keyboardInput.angularSpeed = this._config.keyboardSpeedFactor;
74
- this.fov = this._config.fov;
75
- this.inertia = this._config.inertia;
76
- this.angularSensibilityX = this.angularSensibilityY = this._config.pointerSpeedFactor;
77
- scene.onPointerObservable.add(this._pointerUpDownCallback, PointerEventTypes.POINTERUP | PointerEventTypes.POINTERDOWN);
78
- this.onViewMatrixChangedObservable.add(this._boundCameraListener);
79
- }
80
- dispose() {
81
- this.detachControl(this._canvas);
82
- this.onViewMatrixChangedObservable.removeCallback(this._boundCameraListener);
83
- this._scene.onPointerObservable.removeCallback(this._pointerUpDownCallback);
84
- super.dispose();
85
- }
86
- set disableSubFloorCam(v) {
87
- this._disableSubFloorCam = v;
88
- }
89
- set lowestAllowedCameraHeight(v) {
90
- this._lowestAllowedCameraHeight = v;
91
- }
92
- get lowestAllowedCameraHeight() {
93
- if (this._lowestAllowedCameraHeight !== undefined) {
94
- if (this._disableSubFloorCam) {
95
- return Math.max(0, this._lowestAllowedCameraHeight);
96
- }
97
- return this._lowestAllowedCameraHeight;
98
- }
99
- if (this._disableSubFloorCam) {
100
- return 0;
101
- }
102
- return undefined;
103
- }
104
- forceRadius(r) {
105
- this._radius = r;
106
- }
107
- set radius(r) {
108
- if (this.disableZoom) {
109
- return;
110
- }
111
- this._radius = r;
112
- }
113
- get radius() {
114
- return this._radius;
115
- }
116
- get _orbitalCameraControlProps() {
117
- return {
118
- distance: this.radius === BABYLON_DO_NOT_DIVIDE_BY_ZERO_MAGIC_CONSTANT
119
- ? undefined
120
- : this.radius,
121
- yaw: normalizeAngle(this.alpha),
122
- pitch: this.beta,
123
- distanceWasAutoSet: this.radius === this._currentMinDistanceToFitModelInView,
124
- committed: !(this._isMoving || this._pointerDown),
125
- };
126
- }
127
- frameRenderNeeded() {
128
- const externalControlHasHappened = this._externalControlHasHappened;
129
- if (externalControlHasHappened) {
130
- this._externalControlHasHappened = false;
131
- }
132
- return this._isMoving || externalControlHasHappened;
133
- }
134
- get _isMoving() {
135
- return (this.useAutoRotationBehavior ||
136
- this.inertialAlphaOffset !== 0 ||
137
- this.inertialBetaOffset !== 0 ||
138
- this.inertialPanningX !== 0 ||
139
- this.inertialPanningY !== 0 ||
140
- this.inertialRadiusOffset !== 0);
141
- }
142
- _notifyCameraControlListeners() {
143
- if (this._orbitalCameraControlObservable === undefined) {
144
- return;
145
- }
146
- const orbitalCameraControlProps = this._orbitalCameraControlProps;
147
- if (this._previousOrbitalCameraControlProps !== undefined &&
148
- orbitalCameraControlPropsEquals(this._previousOrbitalCameraControlProps, orbitalCameraControlProps)) {
149
- return;
150
- }
151
- this._orbitalCameraControlObservable.notifyAll(orbitalCameraControlProps, this._orbitalCameraControlObservable);
152
- this._previousOrbitalCameraControlProps = orbitalCameraControlProps;
153
- }
154
- get cameraControlObservable() {
155
- if (this._orbitalCameraControlObservable === undefined) {
156
- this._orbitalCameraControlObservable = new Observable();
157
- this._orbitalCameraControlObservable.listen((c) => {
158
- const { distance, yaw, pitch, distanceWasAutoSet } = c;
159
- let change = false;
160
- if (distanceWasAutoSet !== true &&
161
- distance !== undefined &&
162
- distance !== this.radius) {
163
- this.forceRadius(distance);
164
- change = true;
165
- }
166
- if (yaw !== undefined && yaw !== this.alpha) {
167
- this.alpha = yaw;
168
- change = true;
169
- }
170
- if (pitch !== undefined && pitch !== this.beta) {
171
- this.beta = pitch;
172
- change = true;
173
- }
174
- if (change) {
175
- this._externalControlHasHappened = true;
176
- this._notifyCameraControlListeners();
177
- }
178
- }, this._orbitalCameraControlObservable);
179
- }
180
- return this._orbitalCameraControlObservable;
181
- }
182
- /**
183
- * @param force true makes the camera distance adapt to the new bounds, even if they have
184
- * not changed significantly. false makes the camera distance not adapt even if the
185
- * bounding box size change is significant.
186
- */
187
- setContentBoundingBox(newBoundingBox, force) {
188
- this._currentBoundingBox = newBoundingBox;
189
- const significantChange = boundingBoxesAreSignificantlyDifferent(this._latestSignificantChangeBoundingBox, newBoundingBox, this._config.significantBoundingBoxSizeChangeShrinkFactor, this._config.significantBoundingBoxSizeChangeGrowFactor);
190
- if (!significantChange && force !== true) {
191
- return;
192
- }
193
- this._latestSignificantChangeBoundingBox = newBoundingBox;
194
- this._applyAdaptToContentBoundingBox(force);
195
- this._applyNoSneakPeeking();
196
- }
197
- _applyAdaptToContentBoundingBox(force) {
198
- const bb = this._currentBoundingBox;
199
- if (bb.isEmpty) {
200
- return;
201
- }
202
- // Keeps the camera from recomputing angles and distance
203
- const pre = [this.alpha, this.beta, this.radius];
204
- this.target = bb.center;
205
- if (this.disableAutomaticSizing) {
206
- return;
207
- }
208
- [this.alpha, this.beta, this.radius] = pre;
209
- this._updateCameraLimits();
210
- const minDistanceToFitModelInView = this._currentMinDistanceToFitModelInView;
211
- const minDistanceToKeepCameraOutOfModel = this._currentMinDistanceToKeepCameraOutOfModel;
212
- if (minDistanceToFitModelInView !== undefined) {
213
- if (force !== false && (force === true || this.radius < minDistanceToFitModelInView)) {
214
- this.forceRadius(minDistanceToFitModelInView);
215
- }
216
- }
217
- if (minDistanceToKeepCameraOutOfModel !== undefined &&
218
- minDistanceToFitModelInView !== undefined) {
219
- this.lowerRadiusLimit =
220
- minDistanceToKeepCameraOutOfModel *
221
- this._config.keepCameraFromGettingTooCloseFactor;
222
- this.upperRadiusLimit = minDistanceToFitModelInView * 2;
223
- this.wheelPrecision =
224
- this._config.mouseWheelSpeedFactor / minDistanceToKeepCameraOutOfModel;
225
- this.pinchPrecision = this._config.pinchZoomFactor / minDistanceToKeepCameraOutOfModel;
226
- this.speed = minDistanceToKeepCameraOutOfModel * 0.1;
227
- }
228
- }
229
- refreshCameraNearFar() {
230
- const minDistanceToKeepCameraOutOfModel = this._currentMinDistanceToKeepCameraOutOfModel;
231
- if (minDistanceToKeepCameraOutOfModel === undefined) {
232
- return;
233
- }
234
- const cameraDistance = this.radius;
235
- const extraSpaceFactor = 1.5; // Because when zooming fast it seems the limits do not keep up
236
- const graceDistance = minDistanceToKeepCameraOutOfModel * extraSpaceFactor;
237
- this.minZ = cameraDistance - graceDistance;
238
- this.maxZ = cameraDistance + graceDistance;
239
- }
240
- _applyNoSneakPeeking() {
241
- //It might be impolite to look at a Cfg models underside
242
- const noPeekLimit = this._calculateNoPeekingLimit();
243
- if (noPeekLimit === undefined || !isFinite(noPeekLimit)) {
244
- this.upperBetaLimit = MAX_UPPER_BETA_LIMIT;
245
- return;
246
- }
247
- this.upperBetaLimit = Math.min(MAX_UPPER_BETA_LIMIT, Math.PI / 2 - noPeekLimit);
248
- }
249
- _updateCameraLimits() {
250
- const bb = this._currentBoundingBox;
251
- const fovVertical = this.fov;
252
- const aspect = this.getEngine().getScreenAspectRatio();
253
- const bbAdjustedForCameraPosition = bb.clone().translate(this.target.negate());
254
- const longestDistanceToCornerInXYZSpace = measureLongestDistanceToCorner(bbAdjustedForCameraPosition, [0, 1, 2]);
255
- const longestDistanceToCornerInXZPlane = measureLongestDistanceToCorner(bbAdjustedForCameraPosition, [0, 2]);
256
- const fovHorizontalRad = 2 * Math.atan(Math.tan(fovVertical / 2) * aspect);
257
- const maxAllowedHeight = longestDistanceToCornerInXYZSpace * 2;
258
- const maxAllowedWidth = longestDistanceToCornerInXZPlane * 2; //Because the model can not be tilted, only spun
259
- const minDistanceToFitInViewFromWidth = maxAllowedWidth / (2 * Math.tan(fovHorizontalRad / 2));
260
- const minDistanceToFitInViewFromHeight = maxAllowedHeight / (2 * Math.tan(fovVertical / 2));
261
- const minDistanceToFitModelInView = Math.max(minDistanceToFitInViewFromWidth, minDistanceToFitInViewFromHeight);
262
- this._currentMinDistanceToKeepCameraOutOfModel = isFinite(longestDistanceToCornerInXYZSpace)
263
- ? longestDistanceToCornerInXYZSpace
264
- : undefined;
265
- this._currentMinDistanceToFitModelInView = isFinite(minDistanceToFitModelInView)
266
- ? minDistanceToFitModelInView
267
- : undefined;
268
- }
269
- _calculateNoPeekingLimit() {
270
- const bb = this._currentBoundingBox;
271
- if (bb.isEmpty || this.lowestAllowedCameraHeight === undefined) {
272
- return undefined;
273
- }
274
- const bottomDepth = bb.minimum.y -
275
- this.target.y +
276
- (bb.maximum.y - bb.minimum.y) * this.lowestAllowedCameraHeight;
277
- const cameraDistance = this.radius;
278
- const lowestAngleUnderHorizonRad = Math.asin(bottomDepth / cameraDistance);
279
- return lowestAngleUnderHorizonRad;
280
- }
281
- }
1
+ import { PointerEventTypes } from "@babylonjs/core";
2
+ import { ArcRotateCamera } from "@babylonjs/core/Cameras/arcRotateCamera.js";
3
+ import { Vector3 } from "@babylonjs/core/Maths/math.vector.js";
4
+ import { degToRad, normalizeAngle, Observable } from "@configura/web-utilities";
5
+ import { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
6
+ import { boundingBoxesAreSignificantlyDifferent, measureLongestDistanceToCorner, } from "../utilities/utilities3D.js";
7
+ import { orbitalCameraControlPropsEquals, } from "./CfgOrbitalCameraControlProps.js";
8
+ const NEAREST_ALLOWED_TO_BETA_LIMITS = 0.1;
9
+ export const MAX_UPPER_BETA_LIMIT = Math.PI - NEAREST_ALLOWED_TO_BETA_LIMITS;
10
+ export const MIN_LOWER_BETA_LIMIT = NEAREST_ALLOWED_TO_BETA_LIMITS;
11
+ const defaultOrbitalCameraConfig = {
12
+ fov: degToRad(30),
13
+ mouseWheelSpeedFactor: 200,
14
+ pinchZoomFactor: 100,
15
+ inertia: 0.93,
16
+ keyboardSpeedFactor: 0.002,
17
+ pointerSpeedFactor: 2000,
18
+ keepCameraFromGettingTooCloseFactor: 1.5,
19
+ significantBoundingBoxSizeChangeShrinkFactor: 0.4,
20
+ significantBoundingBoxSizeChangeGrowFactor: 0.1,
21
+ };
22
+ // Babylon initializes radius to this to avoid divide by zero
23
+ const BABYLON_DO_NOT_DIVIDE_BY_ZERO_MAGIC_CONSTANT = 0.0001;
24
+ // This is a workaround as you are not allowed to override fields with accessors.
25
+ // By adding this abstract field this becomes possible. This is a hack.
26
+ class WorkaroundCfgOrbitalCamera extends ArcRotateCamera {
27
+ }
28
+ export class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
29
+ constructor(scene, _canvas, config) {
30
+ super("CfgOrbitalCamera", 0, degToRad(90), 50, new Vector3(0, 0, 0), scene);
31
+ this._canvas = _canvas;
32
+ this._currentBoundingBox = new CfgBoundingBox();
33
+ this._latestSignificantChangeBoundingBox = new CfgBoundingBox();
34
+ this._disableSubFloorCam = false;
35
+ this._lowestAllowedCameraHeight = undefined;
36
+ this._pointerDown = false;
37
+ this.disableAutomaticSizing = false;
38
+ this.disableZoom = false;
39
+ this._externalControlHasHappened = false;
40
+ this._radius = 0;
41
+ this._boundCameraListener = () => {
42
+ // This is a cheap operation, so it's acceptable to do it
43
+ // for every update (even if no radius-change has happened)
44
+ this._applyNoSneakPeeking();
45
+ this._notifyCameraControlListeners();
46
+ };
47
+ this._pointerUpDownCallback = (p, s) => {
48
+ if (p.type === PointerEventTypes.POINTERUP) {
49
+ this._pointerDown = false;
50
+ this._notifyCameraControlListeners();
51
+ }
52
+ if (p.type === PointerEventTypes.POINTERDOWN) {
53
+ this._pointerDown = true;
54
+ }
55
+ };
56
+ this.attachControl(_canvas, // This parameters is not actually used for anything. But still required.
57
+ false, // No panning with keyboard
58
+ false // No panning with mouse
59
+ );
60
+ // Make sure to disable all forms of "panning", which for the ArcRotateCamera is defined
61
+ // as movement sideways without rotation to keep the camera centered on the target.
62
+ // The settings above for attachControl will not disable two-finger touch.
63
+ this.panningAxis = Vector3.Zero();
64
+ this.panningDistanceLimit = 0;
65
+ this.panningSensibility = 0;
66
+ this.panningInertia = 0;
67
+ this._config = Object.assign(Object.assign({}, defaultOrbitalCameraConfig), config);
68
+ const keyboardInput = this.inputs.attached["keyboard"];
69
+ keyboardInput.angularSpeed = this._config.keyboardSpeedFactor;
70
+ this.fov = this._config.fov;
71
+ this.inertia = this._config.inertia;
72
+ this.angularSensibilityX = this.angularSensibilityY = this._config.pointerSpeedFactor;
73
+ scene.onPointerObservable.add(this._pointerUpDownCallback, PointerEventTypes.POINTERUP | PointerEventTypes.POINTERDOWN);
74
+ this.onViewMatrixChangedObservable.add(this._boundCameraListener);
75
+ }
76
+ dispose() {
77
+ this.detachControl();
78
+ this.onViewMatrixChangedObservable.removeCallback(this._boundCameraListener);
79
+ this._scene.onPointerObservable.removeCallback(this._pointerUpDownCallback);
80
+ super.dispose();
81
+ }
82
+ set disableSubFloorCam(v) {
83
+ this._disableSubFloorCam = v;
84
+ }
85
+ set lowestAllowedCameraHeight(v) {
86
+ this._lowestAllowedCameraHeight = v;
87
+ }
88
+ get lowestAllowedCameraHeight() {
89
+ if (this._lowestAllowedCameraHeight !== undefined) {
90
+ if (this._disableSubFloorCam) {
91
+ return Math.max(0, this._lowestAllowedCameraHeight);
92
+ }
93
+ return this._lowestAllowedCameraHeight;
94
+ }
95
+ if (this._disableSubFloorCam) {
96
+ return 0;
97
+ }
98
+ return undefined;
99
+ }
100
+ forceRadius(r) {
101
+ this._radius = r;
102
+ }
103
+ set radius(r) {
104
+ if (this.disableZoom) {
105
+ return;
106
+ }
107
+ this._radius = r;
108
+ }
109
+ get radius() {
110
+ return this._radius;
111
+ }
112
+ get _orbitalCameraControlProps() {
113
+ return {
114
+ distance: this.radius === BABYLON_DO_NOT_DIVIDE_BY_ZERO_MAGIC_CONSTANT
115
+ ? undefined
116
+ : this.radius,
117
+ yaw: normalizeAngle(this.alpha),
118
+ pitch: this.beta,
119
+ distanceWasAutoSet: this.radius === this._currentMinDistanceToFitModelInView,
120
+ committed: !(this._isMoving || this._pointerDown),
121
+ };
122
+ }
123
+ frameRenderNeeded() {
124
+ const externalControlHasHappened = this._externalControlHasHappened;
125
+ if (externalControlHasHappened) {
126
+ this._externalControlHasHappened = false;
127
+ }
128
+ return this._isMoving || externalControlHasHappened;
129
+ }
130
+ get _isMoving() {
131
+ return (this.useAutoRotationBehavior ||
132
+ this.inertialAlphaOffset !== 0 ||
133
+ this.inertialBetaOffset !== 0 ||
134
+ this.inertialPanningX !== 0 ||
135
+ this.inertialPanningY !== 0 ||
136
+ this.inertialRadiusOffset !== 0);
137
+ }
138
+ _notifyCameraControlListeners() {
139
+ if (this._orbitalCameraControlObservable === undefined) {
140
+ return;
141
+ }
142
+ const orbitalCameraControlProps = this._orbitalCameraControlProps;
143
+ if (this._previousOrbitalCameraControlProps !== undefined &&
144
+ orbitalCameraControlPropsEquals(this._previousOrbitalCameraControlProps, orbitalCameraControlProps)) {
145
+ return;
146
+ }
147
+ this._orbitalCameraControlObservable.notifyAll(orbitalCameraControlProps, this._orbitalCameraControlObservable);
148
+ this._previousOrbitalCameraControlProps = orbitalCameraControlProps;
149
+ }
150
+ get cameraControlObservable() {
151
+ if (this._orbitalCameraControlObservable === undefined) {
152
+ this._orbitalCameraControlObservable = new Observable();
153
+ this._orbitalCameraControlObservable.listen((c) => {
154
+ const { distance, yaw, pitch, distanceWasAutoSet } = c;
155
+ let change = false;
156
+ if (distanceWasAutoSet !== true &&
157
+ distance !== undefined &&
158
+ distance !== this.radius) {
159
+ this.forceRadius(distance);
160
+ change = true;
161
+ }
162
+ if (yaw !== undefined && yaw !== this.alpha) {
163
+ this.alpha = yaw;
164
+ change = true;
165
+ }
166
+ if (pitch !== undefined && pitch !== this.beta) {
167
+ this.beta = pitch;
168
+ change = true;
169
+ }
170
+ if (change) {
171
+ this._externalControlHasHappened = true;
172
+ this._notifyCameraControlListeners();
173
+ }
174
+ }, this._orbitalCameraControlObservable);
175
+ }
176
+ return this._orbitalCameraControlObservable;
177
+ }
178
+ /**
179
+ * @param force true makes the camera distance adapt to the new bounds, even if they have
180
+ * not changed significantly. false makes the camera distance not adapt even if the
181
+ * bounding box size change is significant.
182
+ */
183
+ setContentBoundingBox(newBoundingBox, force) {
184
+ this._currentBoundingBox = newBoundingBox;
185
+ const significantChange = boundingBoxesAreSignificantlyDifferent(this._latestSignificantChangeBoundingBox, newBoundingBox, this._config.significantBoundingBoxSizeChangeShrinkFactor, this._config.significantBoundingBoxSizeChangeGrowFactor);
186
+ if (!significantChange && force !== true) {
187
+ return;
188
+ }
189
+ this._latestSignificantChangeBoundingBox = newBoundingBox;
190
+ this._applyAdaptToContentBoundingBox(force);
191
+ this._applyNoSneakPeeking();
192
+ }
193
+ _applyAdaptToContentBoundingBox(force) {
194
+ const bb = this._currentBoundingBox;
195
+ if (bb.isEmpty) {
196
+ return;
197
+ }
198
+ // Keeps the camera from recomputing angles and distance
199
+ const pre = [this.alpha, this.beta, this.radius];
200
+ this.target = bb.center;
201
+ if (this.disableAutomaticSizing) {
202
+ return;
203
+ }
204
+ [this.alpha, this.beta, this.radius] = pre;
205
+ this._updateCameraLimits();
206
+ const minDistanceToFitModelInView = this._currentMinDistanceToFitModelInView;
207
+ const minDistanceToKeepCameraOutOfModel = this._currentMinDistanceToKeepCameraOutOfModel;
208
+ if (minDistanceToFitModelInView !== undefined) {
209
+ if (force !== false && (force === true || this.radius < minDistanceToFitModelInView)) {
210
+ this.forceRadius(minDistanceToFitModelInView);
211
+ }
212
+ }
213
+ if (minDistanceToKeepCameraOutOfModel !== undefined &&
214
+ minDistanceToFitModelInView !== undefined) {
215
+ this.lowerRadiusLimit =
216
+ minDistanceToKeepCameraOutOfModel *
217
+ this._config.keepCameraFromGettingTooCloseFactor;
218
+ this.upperRadiusLimit = minDistanceToFitModelInView * 2;
219
+ this.wheelPrecision =
220
+ this._config.mouseWheelSpeedFactor / minDistanceToKeepCameraOutOfModel;
221
+ this.pinchPrecision = this._config.pinchZoomFactor / minDistanceToKeepCameraOutOfModel;
222
+ this.speed = minDistanceToKeepCameraOutOfModel * 0.1;
223
+ }
224
+ }
225
+ refreshCameraNearFar() {
226
+ const minDistanceToKeepCameraOutOfModel = this._currentMinDistanceToKeepCameraOutOfModel;
227
+ if (minDistanceToKeepCameraOutOfModel === undefined) {
228
+ return;
229
+ }
230
+ const cameraDistance = this.radius;
231
+ const extraSpaceFactor = 1.5; // Because when zooming fast it seems the limits do not keep up
232
+ const graceDistance = minDistanceToKeepCameraOutOfModel * extraSpaceFactor;
233
+ this.minZ = cameraDistance - graceDistance;
234
+ this.maxZ = cameraDistance + graceDistance;
235
+ }
236
+ _applyNoSneakPeeking() {
237
+ //It might be impolite to look at a Cfg models underside
238
+ const noPeekLimit = this._calculateNoPeekingLimit();
239
+ if (noPeekLimit === undefined || !isFinite(noPeekLimit)) {
240
+ this.upperBetaLimit = MAX_UPPER_BETA_LIMIT;
241
+ return;
242
+ }
243
+ this.upperBetaLimit = Math.min(MAX_UPPER_BETA_LIMIT, Math.PI / 2 - noPeekLimit);
244
+ }
245
+ _updateCameraLimits() {
246
+ const bb = this._currentBoundingBox;
247
+ const fovVertical = this.fov;
248
+ const aspect = this.getEngine().getScreenAspectRatio();
249
+ const bbAdjustedForCameraPosition = bb.clone().translate(this.target.negate());
250
+ const longestDistanceToCornerInXYZSpace = measureLongestDistanceToCorner(bbAdjustedForCameraPosition, [0, 1, 2]);
251
+ const longestDistanceToCornerInXZPlane = measureLongestDistanceToCorner(bbAdjustedForCameraPosition, [0, 2]);
252
+ const fovHorizontalRad = 2 * Math.atan(Math.tan(fovVertical / 2) * aspect);
253
+ const maxAllowedHeight = longestDistanceToCornerInXYZSpace * 2;
254
+ const maxAllowedWidth = longestDistanceToCornerInXZPlane * 2; //Because the model can not be tilted, only spun
255
+ const minDistanceToFitInViewFromWidth = maxAllowedWidth / (2 * Math.tan(fovHorizontalRad / 2));
256
+ const minDistanceToFitInViewFromHeight = maxAllowedHeight / (2 * Math.tan(fovVertical / 2));
257
+ const minDistanceToFitModelInView = Math.max(minDistanceToFitInViewFromWidth, minDistanceToFitInViewFromHeight);
258
+ this._currentMinDistanceToKeepCameraOutOfModel = isFinite(longestDistanceToCornerInXYZSpace)
259
+ ? longestDistanceToCornerInXYZSpace
260
+ : undefined;
261
+ this._currentMinDistanceToFitModelInView = isFinite(minDistanceToFitModelInView)
262
+ ? minDistanceToFitModelInView
263
+ : undefined;
264
+ }
265
+ _calculateNoPeekingLimit() {
266
+ const bb = this._currentBoundingBox;
267
+ if (bb.isEmpty || this.lowestAllowedCameraHeight === undefined) {
268
+ return undefined;
269
+ }
270
+ const bottomDepth = bb.minimum.y -
271
+ this.target.y +
272
+ (bb.maximum.y - bb.minimum.y) * this.lowestAllowedCameraHeight;
273
+ const cameraDistance = this.radius;
274
+ const lowestAngleUnderHorizonRad = Math.asin(bottomDepth / cameraDistance);
275
+ return lowestAngleUnderHorizonRad;
276
+ }
277
+ }
@@ -1,15 +1,15 @@
1
- export interface CfgOrbitalCameraBasicProps {
2
- distance?: number;
3
- yaw?: number;
4
- pitch?: number;
5
- }
6
- /**
7
- * @param distanceWasAutoSet Indicates that the camera distance was auto set. If true when setting
8
- * camera settings @param distance will be ignored.
9
- */
10
- export interface CfgOrbitalCameraControlProps extends CfgOrbitalCameraBasicProps {
11
- distanceWasAutoSet?: boolean;
12
- committed?: boolean;
13
- }
14
- export declare function orbitalCameraControlPropsEquals(left: CfgOrbitalCameraControlProps, right: CfgOrbitalCameraControlProps, ignoreCommitted?: boolean): boolean;
1
+ export interface CfgOrbitalCameraBasicProps {
2
+ distance?: number;
3
+ yaw?: number;
4
+ pitch?: number;
5
+ }
6
+ /**
7
+ * @param distanceWasAutoSet Indicates that the camera distance was auto set. If true when setting
8
+ * camera settings @param distance will be ignored.
9
+ */
10
+ export interface CfgOrbitalCameraControlProps extends CfgOrbitalCameraBasicProps {
11
+ distanceWasAutoSet?: boolean;
12
+ committed?: boolean;
13
+ }
14
+ export declare function orbitalCameraControlPropsEquals(left: CfgOrbitalCameraControlProps, right: CfgOrbitalCameraControlProps, ignoreCommitted?: boolean): boolean;
15
15
  //# sourceMappingURL=CfgOrbitalCameraControlProps.d.ts.map
@@ -1,7 +1,7 @@
1
- export function orbitalCameraControlPropsEquals(left, right, ignoreCommitted = false) {
2
- return (((left.distanceWasAutoSet && right.distanceWasAutoSet) ||
3
- left.distance === right.distance) &&
4
- left.yaw === right.yaw &&
5
- left.pitch === right.pitch &&
6
- (ignoreCommitted || left.committed === right.committed));
7
- }
1
+ export function orbitalCameraControlPropsEquals(left, right, ignoreCommitted = false) {
2
+ return (((left.distanceWasAutoSet && right.distanceWasAutoSet) ||
3
+ left.distance === right.distance) &&
4
+ left.yaw === right.yaw &&
5
+ left.pitch === right.pitch &&
6
+ (ignoreCommitted || left.committed === right.committed));
7
+ }
@@ -1,4 +1,4 @@
1
- import { Camera } from "@babylonjs/core/Cameras/camera.js";
2
- export declare type GradingApplier = (camera: Camera) => void;
3
- export declare const getDefaultGradingApplier: () => GradingApplier;
1
+ import { Camera } from "@babylonjs/core/Cameras/camera.js";
2
+ export declare type GradingApplier = (camera: Camera) => void;
3
+ export declare const getDefaultGradingApplier: () => GradingApplier;
4
4
  //# sourceMappingURL=GradingApplier.d.ts.map