@configura/babylon-view 1.6.1 → 2.0.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.
@@ -58,8 +58,13 @@ export declare class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
58
58
  frameRenderNeeded(): boolean;
59
59
  private _notifyCameraControlListeners;
60
60
  get cameraControlObservable(): Observable<CfgOrbitalCameraControlProps>;
61
- setContentBoundingBox(newBoundingBox: CfgBoundingBox, force: boolean): void;
62
- _applyAdaptToContentBoundingBox(force: boolean): void;
61
+ /**
62
+ * @param force true makes the camera distance adapt to the new bounds, even if they have
63
+ * not changed significantly. false makes the camera distance not adapt even if the
64
+ * bounding box size change is significant.
65
+ */
66
+ setContentBoundingBox(newBoundingBox: CfgBoundingBox, force: boolean | undefined): void;
67
+ private _applyAdaptToContentBoundingBox;
63
68
  refreshCameraNearFar(): void;
64
69
  private _applyNoSneakPeeking;
65
70
  private _updateCameraLimits;
@@ -1,6 +1,6 @@
1
1
  import { ArcRotateCamera } from "@babylonjs/core/Cameras/arcRotateCamera.js";
2
2
  import { Vector3 } from "@babylonjs/core/Maths/math.vector.js";
3
- import { degToRad, Observable } from "@configura/web-utilities";
3
+ import { degToRad, normalizeAngle, Observable } from "@configura/web-utilities";
4
4
  import { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
5
5
  import { boundingBoxesAreSignificantlyDifferent, measureLongestDistanceToCorner, } from "../utilities/utilities3D.js";
6
6
  import { CfgArcRotateCameraPointersInput } from "./CfgArcRotateCameraPointersInput.js";
@@ -19,6 +19,8 @@ const defaultOrbitalCameraConfig = {
19
19
  significantBoundingBoxSizeChangeShrinkFactor: 0.4,
20
20
  significantBoundingBoxSizeChangeGrowFactor: 0.1,
21
21
  };
22
+ // Babylon initializes radius to this to avoid divide by zero
23
+ const BABYLON_DO_NOT_DIVIDE_BY_ZERO_MAGIC_CONSTANT = 0.0001;
22
24
  // This is a workaround as you are not allowed to override fields with accessors.
23
25
  // By adding this abstract field this becomes possible. This is a hack.
24
26
  class WorkaroundCfgOrbitalCamera extends ArcRotateCamera {
@@ -35,9 +37,7 @@ export class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
35
37
  this.disableZoom = false;
36
38
  this._externalControlHasHappened = false;
37
39
  this._radius = 0;
38
- this._boundNotifyCameraControlListeners = () => {
39
- this._notifyCameraControlListeners();
40
- };
40
+ this._boundNotifyCameraControlListeners = () => this._notifyCameraControlListeners();
41
41
  this.attachControl(_canvas, // This parameters is not actually used for anything. But still required.
42
42
  false, // No panning with keyboard
43
43
  false // No panning with mouse
@@ -97,9 +97,12 @@ export class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
97
97
  }
98
98
  get _orbitalCameraControlProps() {
99
99
  return {
100
- distance: this.radius,
101
- yaw: this.alpha,
100
+ distance: this.radius === BABYLON_DO_NOT_DIVIDE_BY_ZERO_MAGIC_CONSTANT
101
+ ? undefined
102
+ : this.radius,
103
+ yaw: normalizeAngle(this.alpha),
102
104
  pitch: this.beta,
105
+ distanceWasAutoSet: this.radius === this._currentMinDistanceToFitModelInView,
103
106
  };
104
107
  }
105
108
  frameRenderNeeded() {
@@ -131,9 +134,11 @@ export class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
131
134
  if (this._orbitalCameraControlObservable === undefined) {
132
135
  this._orbitalCameraControlObservable = new Observable();
133
136
  this._orbitalCameraControlObservable.listen((c) => {
134
- const { distance, yaw, pitch } = c;
137
+ const { distance, yaw, pitch, distanceWasAutoSet } = c;
135
138
  let change = false;
136
- if (distance !== undefined && distance !== this.radius) {
139
+ if (distanceWasAutoSet !== true &&
140
+ distance !== undefined &&
141
+ distance !== this.radius) {
137
142
  this.forceRadius(distance);
138
143
  change = true;
139
144
  }
@@ -153,10 +158,15 @@ export class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
153
158
  }
154
159
  return this._orbitalCameraControlObservable;
155
160
  }
161
+ /**
162
+ * @param force true makes the camera distance adapt to the new bounds, even if they have
163
+ * not changed significantly. false makes the camera distance not adapt even if the
164
+ * bounding box size change is significant.
165
+ */
156
166
  setContentBoundingBox(newBoundingBox, force) {
157
167
  this._currentBoundingBox = newBoundingBox;
158
168
  const significantChange = boundingBoxesAreSignificantlyDifferent(this._latestSignificantChangeBoundingBox, newBoundingBox, this._config.significantBoundingBoxSizeChangeShrinkFactor, this._config.significantBoundingBoxSizeChangeGrowFactor);
159
- if (!significantChange && !force) {
169
+ if (!significantChange && force !== true) {
160
170
  return;
161
171
  }
162
172
  this._latestSignificantChangeBoundingBox = newBoundingBox;
@@ -168,18 +178,18 @@ export class CfgOrbitalCamera extends WorkaroundCfgOrbitalCamera {
168
178
  if (bb.isEmpty) {
169
179
  return;
170
180
  }
171
- // Keeps the camera from recomputing angles
172
- const pre = [this.alpha, this.beta];
181
+ // Keeps the camera from recomputing angles and distance
182
+ const pre = [this.alpha, this.beta, this.radius];
173
183
  this.target = bb.center;
174
184
  if (this.disableAutomaticSizing) {
175
185
  return;
176
186
  }
177
- [this.alpha, this.beta] = pre;
187
+ [this.alpha, this.beta, this.radius] = pre;
178
188
  this._updateCameraLimits();
179
189
  const minDistanceToFitModelInView = this._currentMinDistanceToFitModelInView;
180
190
  const minDistanceToKeepCameraOutOfModel = this._currentMinDistanceToKeepCameraOutOfModel;
181
191
  if (minDistanceToFitModelInView !== undefined) {
182
- if (force || this.radius < minDistanceToFitModelInView) {
192
+ if (force !== false && (force === true || this.radius < minDistanceToFitModelInView)) {
183
193
  this.forceRadius(minDistanceToFitModelInView);
184
194
  }
185
195
  }
@@ -1,7 +1,12 @@
1
+ /**
2
+ * @param distanceWasAutoSet Indicates that the camera distance was auto set. If true when setting
3
+ * camera settings @param distance will be ignored.
4
+ */
1
5
  export interface CfgOrbitalCameraControlProps {
2
6
  distance?: number;
3
7
  yaw?: number;
4
8
  pitch?: number;
9
+ distanceWasAutoSet?: boolean;
5
10
  }
6
11
  export declare function orbitalCameraControlPropsEquals(left: CfgOrbitalCameraControlProps, right: CfgOrbitalCameraControlProps): boolean;
7
12
  //# sourceMappingURL=CfgOrbitalCameraControlProps.d.ts.map
@@ -1,3 +1,6 @@
1
1
  export function orbitalCameraControlPropsEquals(left, right) {
2
- return left.distance === right.distance && left.yaw === right.yaw && left.pitch === right.pitch;
2
+ return (((left.distanceWasAutoSet && right.distanceWasAutoSet) ||
3
+ left.distance === right.distance) &&
4
+ left.yaw === right.yaw &&
5
+ left.pitch === right.pitch);
3
6
  }
@@ -1,8 +1,8 @@
1
1
  import { Matrix, Vector3 } from "@babylonjs/core/Maths/math.vector.js";
2
- import { LengthValue, StretchMap } from "@configura/web-api";
2
+ import { StretchMap } from "@configura/web-api";
3
3
  import { SymNode } from "@configura/web-core/dist/cm/format/cmsym/SymNode.js";
4
4
  import { DetailLevel } from "@configura/web-core/dist/cm/geometry/DetailMask.js";
5
- import { Logger } from "@configura/web-utilities";
5
+ import { LengthValue, Logger } from "@configura/web-utilities";
6
6
  /**
7
7
  * How far along from sp to ep is a point on a plane crossing the sp to ep line?
8
8
  * 1 means at ep, 0 means at sp.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,9 @@ export * from "./animation/coordinator/CoordinatorPulseBounce.js";
3
3
  export * from "./animation/coordinator/CoordinatorPulseHighlight.js";
4
4
  export * from "./animation/coordinator/CoordinatorPulseInflate.js";
5
5
  export * from "./camera/CfgOrbitalCameraControlProps.js";
6
+ export * from "./io/CfgHistoryToCameraConfConnector.js";
7
+ export * from "./io/CfgObservableStateToCameraConfConnector.js";
8
+ export * from "./io/CfgWindowMessageToCameraConfConnector.js";
6
9
  export * from "./utilities/utilities3D.js";
7
10
  export * from "./view/BaseView.js";
8
11
  export * from "./view/BaseViewConfiguration.js";
package/dist/index.js CHANGED
@@ -3,6 +3,9 @@ export * from "./animation/coordinator/CoordinatorPulseBounce.js";
3
3
  export * from "./animation/coordinator/CoordinatorPulseHighlight.js";
4
4
  export * from "./animation/coordinator/CoordinatorPulseInflate.js";
5
5
  export * from "./camera/CfgOrbitalCameraControlProps.js";
6
+ export * from "./io/CfgHistoryToCameraConfConnector.js";
7
+ export * from "./io/CfgObservableStateToCameraConfConnector.js";
8
+ export * from "./io/CfgWindowMessageToCameraConfConnector.js";
6
9
  export * from "./utilities/utilities3D.js";
7
10
  export * from "./view/BaseView.js";
8
11
  export * from "./view/BaseViewConfiguration.js";
@@ -0,0 +1,30 @@
1
+ import { CfgHistoryManager, CfgHistoryManagerSendData } from "@configura/web-api";
2
+ import { Observable } from "@configura/web-utilities";
3
+ import { CfgOrbitalCameraControlProps } from "../camera/CfgOrbitalCameraControlProps.js";
4
+ import { CfgCameraConfMessage, CfgIOCameraConfConnector } from "./CfgIOCameraConfConnector.js";
5
+ /**
6
+ * Instantiating this will make the browser history (and URL) update with the orientation
7
+ * of the Camera. It always use replace in the history API, so it will never add frames
8
+ * to the history stack.
9
+ */
10
+ export declare class CfgHistoryToCameraConfConnector extends CfgIOCameraConfConnector<CfgHistoryManagerSendData<CfgCameraConfMessage>> {
11
+ private readonly defaults;
12
+ private readonly _qsKeyYaw;
13
+ private readonly _qsKeyPitch;
14
+ private readonly _qsKeyDistance;
15
+ /**
16
+ * @param defaults The default camera settings.
17
+ * @param cameraControl Connects with the Camera.
18
+ * @param qsKeyYaw The Query String key for Yaw.
19
+ * @param qsKeyPitch The Query String key for Pitch.
20
+ * @param qsKeyDistance The Query String key for Distance.
21
+ * @returns The instance and the initial camera orientation.
22
+ */
23
+ static make(manager: CfgHistoryManager, defaults: CfgOrbitalCameraControlProps, cameraControl: Observable<CfgOrbitalCameraControlProps>, qsKeyYaw?: string, qsKeyPitch?: string, qsKeyDistance?: string): {
24
+ instance: CfgHistoryToCameraConfConnector;
25
+ initial: CfgOrbitalCameraControlProps;
26
+ };
27
+ private constructor();
28
+ protected makeSendData(cameraConf: CfgOrbitalCameraControlProps, initial: boolean): CfgHistoryManagerSendData<CfgCameraConfMessage>;
29
+ }
30
+ //# sourceMappingURL=CfgHistoryToCameraConfConnector.d.ts.map
@@ -0,0 +1,80 @@
1
+ import { CfgHistoryManager } from "@configura/web-api";
2
+ import { degToRad, radToDeg } from "@configura/web-utilities";
3
+ import { CfgIOCameraConfConnector } from "./CfgIOCameraConfConnector.js";
4
+ const YAW_QS_KEY = "stageyaw";
5
+ const PITCH_QS_KEY = "stagepitch";
6
+ const DISTANCE_QS_KEY = "stagedistance";
7
+ /**
8
+ * @returns if the key is set in qsMap return the value as a number, or else undefined
9
+ */
10
+ const qsAsNumber = (qsMap, key) => {
11
+ const asString = qsMap.get(key);
12
+ if (asString === undefined) {
13
+ return undefined;
14
+ }
15
+ const asNumber = parseFloat(asString);
16
+ if (!isFinite(asNumber)) {
17
+ return undefined;
18
+ }
19
+ return asNumber;
20
+ };
21
+ /**
22
+ * If the number is set, round it and add to the map
23
+ */
24
+ const addToMapAndRound = (map, key, value, def) => {
25
+ if (value === undefined || value === def) {
26
+ map.set(key, undefined);
27
+ return;
28
+ }
29
+ const timesHundredString = `${Math.round(100 * value)}`;
30
+ const decimalPlace = timesHundredString.length - 2;
31
+ map.set(key, `${timesHundredString.substring(0, decimalPlace)}.${timesHundredString.substring(decimalPlace)}`);
32
+ };
33
+ const degToRadOrUndefined = (v) => v && degToRad(v);
34
+ const radToDegOrUndefined = (v) => v && radToDeg(v);
35
+ /**
36
+ * Instantiating this will make the browser history (and URL) update with the orientation
37
+ * of the Camera. It always use replace in the history API, so it will never add frames
38
+ * to the history stack.
39
+ */
40
+ export class CfgHistoryToCameraConfConnector extends CfgIOCameraConfConnector {
41
+ constructor(manager, defaults, initial, cameraControl, _qsKeyYaw, _qsKeyPitch, _qsKeyDistance) {
42
+ super(manager, initial, cameraControl);
43
+ this.defaults = defaults;
44
+ this._qsKeyYaw = _qsKeyYaw;
45
+ this._qsKeyPitch = _qsKeyPitch;
46
+ this._qsKeyDistance = _qsKeyDistance;
47
+ }
48
+ /**
49
+ * @param defaults The default camera settings.
50
+ * @param cameraControl Connects with the Camera.
51
+ * @param qsKeyYaw The Query String key for Yaw.
52
+ * @param qsKeyPitch The Query String key for Pitch.
53
+ * @param qsKeyDistance The Query String key for Distance.
54
+ * @returns The instance and the initial camera orientation.
55
+ */
56
+ static make(manager, defaults, cameraControl, qsKeyYaw = YAW_QS_KEY, qsKeyPitch = PITCH_QS_KEY, qsKeyDistance = DISTANCE_QS_KEY) {
57
+ var _a, _b;
58
+ const qsKeyValues = CfgHistoryManager.currentQsKeyValues();
59
+ const initial = {
60
+ yaw: (_a = degToRadOrUndefined(qsAsNumber(qsKeyValues, qsKeyYaw))) !== null && _a !== void 0 ? _a : defaults.yaw,
61
+ pitch: (_b = degToRadOrUndefined(qsAsNumber(qsKeyValues, qsKeyPitch))) !== null && _b !== void 0 ? _b : defaults.pitch,
62
+ distance: qsAsNumber(qsKeyValues, qsKeyDistance !== null && qsKeyDistance !== void 0 ? qsKeyDistance : defaults.distance),
63
+ };
64
+ const instance = new CfgHistoryToCameraConfConnector(manager, defaults, initial, cameraControl, qsKeyYaw, qsKeyPitch, qsKeyDistance);
65
+ return { instance, initial };
66
+ }
67
+ makeSendData(cameraConf, initial) {
68
+ const qsKeyValues = new Map();
69
+ if (!initial) {
70
+ addToMapAndRound(qsKeyValues, this._qsKeyYaw, radToDegOrUndefined(cameraConf.yaw), radToDegOrUndefined(this.defaults.yaw));
71
+ addToMapAndRound(qsKeyValues, this._qsKeyPitch, radToDegOrUndefined(cameraConf.pitch), radToDegOrUndefined(this.defaults.pitch));
72
+ addToMapAndRound(qsKeyValues, this._qsKeyDistance, cameraConf.distanceWasAutoSet ? undefined : cameraConf.distance, this.defaults.distance);
73
+ }
74
+ return {
75
+ message: this.makeMessage(cameraConf, initial),
76
+ qsKeyValues,
77
+ useHistoryPush: false,
78
+ };
79
+ }
80
+ }
@@ -0,0 +1,36 @@
1
+ import { CfgIOManager } from "@configura/web-api";
2
+ import { Observable } from "@configura/web-utilities";
3
+ import { CfgOrbitalCameraControlProps } from "../camera/CfgOrbitalCameraControlProps.js";
4
+ export declare type CfgCameraConfMessage = {
5
+ version: string;
6
+ initial: boolean;
7
+ cameraConf: CfgOrbitalCameraControlProps;
8
+ };
9
+ export declare const STAGE_CAMERA_CONF_MESSAGE_KEY = "stagecameraconf";
10
+ export declare const STAGE_CAMERA_MESSAGE_VERSION = "1.0";
11
+ declare type CameraConfMessageCallback = (message: CfgCameraConfMessage) => Promise<void>;
12
+ declare type CameraConfCallback = (conf: CfgOrbitalCameraControlProps) => Promise<void>;
13
+ /**
14
+ * Base class for connecting the camera configuration to an IO channel
15
+ */
16
+ export declare abstract class CfgIOCameraConfConnector<S> {
17
+ private readonly _ioManager;
18
+ private readonly _cameraControl;
19
+ private _stopListenToMessage;
20
+ private _stopListenToProdConf;
21
+ constructor(_ioManager: CfgIOManager<S>, initialCameraConf: CfgOrbitalCameraControlProps, _cameraControl: Observable<CfgOrbitalCameraControlProps>);
22
+ destroy: () => void;
23
+ private _delayId;
24
+ private _send;
25
+ protected abstract makeSendData(cameraConf: CfgOrbitalCameraControlProps, initial: boolean): S;
26
+ makeMessage(cameraConf: CfgOrbitalCameraControlProps, initial: boolean): CfgCameraConfMessage;
27
+ makeMessageListener(callback: CameraConfMessageCallback): (message: unknown) => Promise<void>;
28
+ /**
29
+ * Register the callback to listen for Product Configuration messages
30
+ * @returns A function which when called will cancel listening
31
+ */
32
+ listenForMessage(callback: CameraConfMessageCallback): () => void;
33
+ listenForCamera(callback: CameraConfCallback): () => void;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=CfgIOCameraConfConnector.d.ts.map
@@ -0,0 +1,82 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ // Chrome is not happy if history updates are sent to rapidly.
11
+ // And message receivers probably don't want to get flooded either.
12
+ const THROTTLING_DELAY = 100;
13
+ export const STAGE_CAMERA_CONF_MESSAGE_KEY = "stagecameraconf";
14
+ export const STAGE_CAMERA_MESSAGE_VERSION = "1.0";
15
+ /**
16
+ * Base class for connecting the camera configuration to an IO channel
17
+ */
18
+ export class CfgIOCameraConfConnector {
19
+ constructor(_ioManager, initialCameraConf, _cameraControl) {
20
+ this._ioManager = _ioManager;
21
+ this._cameraControl = _cameraControl;
22
+ this._stopListenToMessage = undefined;
23
+ this._stopListenToProdConf = undefined;
24
+ this.destroy = () => {
25
+ var _a, _b;
26
+ (_a = this._stopListenToMessage) === null || _a === void 0 ? void 0 : _a.call(this);
27
+ (_b = this._stopListenToProdConf) === null || _b === void 0 ? void 0 : _b.call(this);
28
+ };
29
+ this._send = (data) => this._ioManager.send(STAGE_CAMERA_CONF_MESSAGE_KEY, data);
30
+ this._send(this.makeSendData(initialCameraConf, true));
31
+ this._stopListenToMessage = this.listenForMessage((message) => __awaiter(this, void 0, void 0, function* () {
32
+ if (this._delayId !== undefined) {
33
+ return;
34
+ }
35
+ _cameraControl.notifyAll(message.cameraConf, this);
36
+ }));
37
+ this._stopListenToProdConf = this.listenForCamera((cameraConf) => __awaiter(this, void 0, void 0, function* () {
38
+ window.clearTimeout(this._delayId);
39
+ this._delayId = window.setTimeout(() => {
40
+ this._send(this.makeSendData(cameraConf, false));
41
+ this._delayId = undefined;
42
+ }, THROTTLING_DELAY);
43
+ }));
44
+ }
45
+ makeMessage(cameraConf, initial) {
46
+ return {
47
+ version: STAGE_CAMERA_MESSAGE_VERSION,
48
+ initial,
49
+ cameraConf,
50
+ };
51
+ }
52
+ makeMessageListener(callback) {
53
+ return (message) => __awaiter(this, void 0, void 0, function* () {
54
+ const cameraConfMessage = message;
55
+ const version = cameraConfMessage.version;
56
+ if (version !== STAGE_CAMERA_MESSAGE_VERSION) {
57
+ console.error(`The a message was passed with an unsupported version "${version}". Currently only ${STAGE_CAMERA_MESSAGE_VERSION} is supported.`);
58
+ return;
59
+ }
60
+ yield callback(cameraConfMessage);
61
+ });
62
+ }
63
+ /**
64
+ * Register the callback to listen for Product Configuration messages
65
+ * @returns A function which when called will cancel listening
66
+ */
67
+ listenForMessage(callback) {
68
+ const ioManager = this._ioManager;
69
+ const listener = this.makeMessageListener(callback);
70
+ ioManager.listenForMessage(listener, STAGE_CAMERA_CONF_MESSAGE_KEY);
71
+ return () => {
72
+ ioManager.stopListenForMessage(listener);
73
+ };
74
+ }
75
+ listenForCamera(callback) {
76
+ const cameraControl = this._cameraControl;
77
+ cameraControl.listen(callback, this);
78
+ return () => {
79
+ cameraControl.stopListen(callback);
80
+ };
81
+ }
82
+ }
@@ -0,0 +1,11 @@
1
+ import { CfgOrbitalCameraControlProps } from "../camera/CfgOrbitalCameraControlProps.js";
2
+ import { CfgCameraConfMessage, CfgIOCameraConfConnector } from "./CfgIOCameraConfConnector.js";
3
+ /**
4
+ * Instantiating this will make Stage send camera orientation to the observable state.
5
+ * It will also make Stage listen for incoming updates to the observable state.
6
+
7
+ */
8
+ export declare class CfgObservableStateToCameraConfConnector extends CfgIOCameraConfConnector<CfgCameraConfMessage> {
9
+ protected makeSendData(cameraConf: CfgOrbitalCameraControlProps, initial: boolean): CfgCameraConfMessage;
10
+ }
11
+ //# sourceMappingURL=CfgObservableStateToCameraConfConnector.d.ts.map
@@ -0,0 +1,11 @@
1
+ import { CfgIOCameraConfConnector } from "./CfgIOCameraConfConnector.js";
2
+ /**
3
+ * Instantiating this will make Stage send camera orientation to the observable state.
4
+ * It will also make Stage listen for incoming updates to the observable state.
5
+
6
+ */
7
+ export class CfgObservableStateToCameraConfConnector extends CfgIOCameraConfConnector {
8
+ makeSendData(cameraConf, initial) {
9
+ return this.makeMessage(cameraConf, initial);
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ import { CfgOrbitalCameraControlProps } from "../camera/CfgOrbitalCameraControlProps.js";
2
+ import { CfgCameraConfMessage, CfgIOCameraConfConnector } from "./CfgIOCameraConfConnector.js";
3
+ /**
4
+ * Instantiating this will make Stage send camera orientation changes using the post message-API.
5
+ * It will also make Stage listen for incoming camera orientation update messages.
6
+ * This can be used to communicate in and out of an iframe for example.
7
+ */
8
+ export declare class CfgWindowMessageToCameraConfConnector extends CfgIOCameraConfConnector<CfgCameraConfMessage> {
9
+ protected makeSendData(cameraConf: CfgOrbitalCameraControlProps, initial: boolean): CfgCameraConfMessage;
10
+ }
11
+ //# sourceMappingURL=CfgWindowMessageToCameraConfConnector.d.ts.map
@@ -0,0 +1,11 @@
1
+ import { CfgIOCameraConfConnector } from "./CfgIOCameraConfConnector.js";
2
+ /**
3
+ * Instantiating this will make Stage send camera orientation changes using the post message-API.
4
+ * It will also make Stage listen for incoming camera orientation update messages.
5
+ * This can be used to communicate in and out of an iframe for example.
6
+ */
7
+ export class CfgWindowMessageToCameraConfConnector extends CfgIOCameraConfConnector {
8
+ makeSendData(cameraConf, initial) {
9
+ return this.makeMessage(cameraConf, initial);
10
+ }
11
+ }
@@ -1,5 +1,5 @@
1
1
  import { Matrix } from "@babylonjs/core/Maths/math.vector.js";
2
- import { CfgMaterialMapping, RootNodeSource, Transform as ModelTransform } from "@configura/web-api";
2
+ import { CfgMaterialMapping, DtoTransform as ModelTransform, RootNodeSource } from "@configura/web-api";
3
3
  import { SymNode } from "@configura/web-core/dist/cm/format/cmsym/SymNode.js";
4
4
  import { LengthUnit, Logger } from "@configura/web-utilities";
5
5
  import { CoordinatorWithMeta } from "../animation/coordinator/Coordinator.js";
@@ -1,5 +1,5 @@
1
1
  import { Matrix, Vector3 } from "@babylonjs/core";
2
- import { MeasureParam } from "@configura/web-api";
2
+ import { DtoMeasureParam } from "@configura/web-api";
3
3
  import { CfgMeasureDefinition, CfgMeasurePriority } from "@configura/web-api/dist/CfgMeasure";
4
4
  import { CfgProductNode } from "../../nodes/CfgProductNode.js";
5
5
  import { CfgSymRootNode } from "../../nodes/CfgSymRootNode.js";
@@ -20,13 +20,13 @@ export declare const getAnchorTargetPriorityComparer: (measureDefinitions: CfgMe
20
20
  * It might be possible in the future to anchor to other things than Measures (which are primarily)
21
21
  * used for stretch, but for now we can only support anchoring to the ends of a Measure.
22
22
  * toSp means anchor to start point, else end point.
23
- * The MeasureParam class is used in several different contexts. To make the intent inside Stage
23
+ * The DtoMeasureParam class is used in several different contexts. To make the intent inside Stage
24
24
  * clear CfgAnchorRef exists, which including only what is relevant for when used for anchoring.
25
25
  */
26
26
  export declare class CfgAnchorRef {
27
27
  readonly stretchSymNodeId: string;
28
28
  readonly toSp: boolean;
29
- static make(m: MeasureParam | undefined): CfgAnchorRef | undefined;
29
+ static make(m: DtoMeasureParam | undefined): CfgAnchorRef | undefined;
30
30
  /**
31
31
  * The name stretchSymNodeId might seem confusing. And it is. Turns out CET is implemented so
32
32
  * that it bases its anchoring on symNode Id containing the stretch. Not the measureParamId.
@@ -45,7 +45,7 @@ export const getAnchorTargetPriorityComparer = (measureDefinitions) => (measureP
45
45
  * It might be possible in the future to anchor to other things than Measures (which are primarily)
46
46
  * used for stretch, but for now we can only support anchoring to the ends of a Measure.
47
47
  * toSp means anchor to start point, else end point.
48
- * The MeasureParam class is used in several different contexts. To make the intent inside Stage
48
+ * The DtoMeasureParam class is used in several different contexts. To make the intent inside Stage
49
49
  * clear CfgAnchorRef exists, which including only what is relevant for when used for anchoring.
50
50
  */
51
51
  export class CfgAnchorRef {
@@ -1,5 +1,5 @@
1
1
  import { Matrix, Vector3 } from "@babylonjs/core/Maths/math.vector.js";
2
- import { Transform as ModelTransform } from "@configura/web-api";
2
+ import { DtoTransform as ModelTransform } from "@configura/web-api";
3
3
  import { ATriMeshF } from "@configura/web-core/dist/cm/core3D/ATriMeshF.js";
4
4
  import { SymTransform } from "@configura/web-core/dist/cm/format/cmsym/components/SymTransform.js";
5
5
  import { Point } from "@configura/web-core/dist/cm/geometry/Point.js";
@@ -1,4 +1,4 @@
1
- import { RootNodeSource, Transform as ModelTransform } from "@configura/web-api";
1
+ import { DtoTransform as ModelTransform, RootNodeSource } from "@configura/web-api";
2
2
  import { CfgAnchorRef } from "./anchor/anchor.js";
3
3
  export declare function makeIdentifier(type: "uri" | "file", v: string): string;
4
4
  export declare function identifierIsUri(identifier: string): boolean;
@@ -28,6 +28,9 @@ export declare class SingleProductDefaultCameraView<T extends SingleProductDefau
28
28
  protected notifyCameraListeners(): void;
29
29
  get cameraControlObservable(): Observable<CfgOrbitalCameraControlProps>;
30
30
  protected get contentCenter(): Vector3;
31
+ /**
32
+ * @param force true means force apply camera distance and camera bounds. false means force do not apply.
33
+ */
31
34
  protected handleSizing(force: boolean): void;
32
35
  protected refreshCameraNearFar(): void;
33
36
  protected getNeededFrameRender(time: number): boolean;
@@ -114,6 +114,9 @@ export class SingleProductDefaultCameraView extends SingleProductView {
114
114
  get contentCenter() {
115
115
  return this._camera.target;
116
116
  }
117
+ /**
118
+ * @param force true means force apply camera distance and camera bounds. false means force do not apply.
119
+ */
117
120
  handleSizing(force) {
118
121
  super.handleSizing(force);
119
122
  if (this._viewportSize === undefined) {
@@ -124,7 +127,8 @@ export class SingleProductDefaultCameraView extends SingleProductView {
124
127
  ? new CfgBoundingBox()
125
128
  : currentProductNode.boundingBox;
126
129
  boundingBox.applyMatrix(CET_TO_BABYLON_MATRIX);
127
- this._camera.setContentBoundingBox(boundingBox, force);
130
+ const initialCameraDistanceSetPreventsInitialAutoSizingSet = this.isFirstLoad && this._cameraConf.distance !== undefined;
131
+ this._camera.setContentBoundingBox(boundingBox, initialCameraDistanceSetPreventsInitialAutoSizingSet ? false : force ? true : undefined);
128
132
  if (!boundingBox.isEmpty) {
129
133
  this._lightRig.scale =
130
134
  measureLongestDistanceToCorner(boundingBox, [0, 1, 2]) *
@@ -1,4 +1,5 @@
1
1
  import { EventListener } from "@configura/web-utilities";
2
+ import { CfgOrbitalCameraControlProps } from "../camera/CfgOrbitalCameraControlProps.js";
2
3
  import { CameraConfigurationProps } from "./BaseViewConfiguration.js";
3
4
  import { SingleProductViewConfiguration, SingleProductViewEventMap } from "./SingleProductViewConfiguration.js";
4
5
  /**
@@ -7,17 +8,12 @@ import { SingleProductViewConfiguration, SingleProductViewEventMap } from "./Sin
7
8
  * @param disableSubFloorCam It is common that catalogue models are designed to never be shown from below. This limits camera polar angle.
8
9
  * @param lowestAllowedCameraHeight Relative to the size of the viewed model, the lowest height the camera can reach. Setting this to 0 is the same as disableSubFloorCam. 1 means the camera can not move lower than the height of the model. Any numeric value is allowed.
9
10
  * @param distance Only works if disableAutomaticSizing is set
10
- * @param yaw Horisontal angle for the camera. Range -π/2 to π/2 radians.
11
- * @param pitch Vertical angle for the camera. Range 0 to π/2 radians, measured from the north pole.
11
+ * @param yaw Horisontal angle for the camera. Range to π radians.
12
+ * @param pitch Vertical angle for the camera. Range 0 to π radians, measured from the north pole.
12
13
  * @param autoRotate See babylon-documentation for parameter-documentation
13
14
  */
14
- export declare type SingleProductDefaultCameraDirection = {
15
- distance?: number;
16
- yaw?: number;
17
- pitch?: number;
18
- };
19
15
  export interface SingleProductDefaultCameraViewConfiguration extends SingleProductViewConfiguration {
20
- camera?: SingleProductDefaultCameraDirection & {
16
+ camera?: CfgOrbitalCameraControlProps & {
21
17
  disableZoom?: boolean;
22
18
  disableAutomaticSizing?: boolean;
23
19
  disableSubFloorCam?: boolean;
@@ -1,5 +1,5 @@
1
1
  import { Camera } from "@babylonjs/core/Cameras/camera.js";
2
- import { ApplicationArea, CfgProduct } from "@configura/web-api";
2
+ import { CfgProduct, DtoApplicationArea } from "@configura/web-api";
3
3
  import { EventListener } from "@configura/web-utilities";
4
4
  import { CoordinatorWithMeta } from "../animation/coordinator/Coordinator.js";
5
5
  import { CameraCreator } from "../camera/CameraCreator.js";
@@ -10,7 +10,7 @@ import { CfgProductNode } from "../nodes/CfgProductNode.js";
10
10
  import { SceneCreator } from "../scene/SceneCreator.js";
11
11
  import { BaseView } from "./BaseView.js";
12
12
  import { SingleProductViewConfiguration, SingleProductViewEventMap } from "./SingleProductViewConfiguration.js";
13
- export declare type LoadingOrApplicationAreas = ApplicationArea[] | "loading";
13
+ export declare type LoadingOrApplicationAreas = DtoApplicationArea[] | "loading";
14
14
  export declare type SingleProductViewConstructorOptions<C extends Camera> = {
15
15
  canvas: HTMLCanvasElement;
16
16
  cameraCreator: CameraCreator<C>;
@@ -20,6 +20,7 @@ export declare type SingleProductViewConstructorOptions<C extends Camera> = {
20
20
  dummyMaterialCreator?: DummyMaterialCreator;
21
21
  };
22
22
  export declare class SingleProductView<C extends Camera = Camera, T extends SingleProductViewEventMap = SingleProductViewEventMap> extends BaseView<C, T> {
23
+ private _isFirstLoad;
23
24
  private _currentProductNode;
24
25
  private _scheduledForRemoval;
25
26
  private _viewPhaseObservable;
@@ -31,6 +32,7 @@ export declare class SingleProductView<C extends Camera = Camera, T extends Sing
31
32
  private scheduleForRemoval;
32
33
  setConfiguration(configuration: SingleProductViewConfiguration): void;
33
34
  get currentProductNode(): CfgProductNode | undefined;
35
+ get isFirstLoad(): boolean;
34
36
  addEventListener<K extends keyof T>(event: K, listener: EventListener<T, K>): void;
35
37
  removeEventListener<K extends keyof T>(event: K, listener: EventListener<T, K>): void;
36
38
  protected getNeededFrameRender(time: number): boolean;
@@ -16,6 +16,7 @@ import { SingleProductViewPhase, } from "./SingleProductViewConfiguration.js";
16
16
  export class SingleProductView extends BaseView {
17
17
  constructor(options) {
18
18
  super(options);
19
+ this._isFirstLoad = true;
19
20
  this._scheduledForRemoval = [];
20
21
  this._viewPhaseObservable = new Observable();
21
22
  this._currentPhase = SingleProductViewPhase.Idle;
@@ -100,6 +101,7 @@ export class SingleProductView extends BaseView {
100
101
  this.notifyPhaseChange(SingleProductViewPhase.HandleSizing);
101
102
  this.handleSizing(false);
102
103
  }
104
+ this._isFirstLoad = false;
103
105
  if (doRenderTemporaryMaterials) {
104
106
  this.scheduleRerender();
105
107
  }
@@ -158,6 +160,9 @@ export class SingleProductView extends BaseView {
158
160
  get currentProductNode() {
159
161
  return this._currentProductNode;
160
162
  }
163
+ get isFirstLoad() {
164
+ return this._isFirstLoad;
165
+ }
161
166
  addEventListener(event, listener) {
162
167
  switch (event) {
163
168
  case "viewPhase":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configura/babylon-view",
3
- "version": "1.6.1",
3
+ "version": "2.0.0-alpha.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,16 +16,16 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@babylonjs/core": "4.2.0",
19
- "@configura/web-core": "1.6.1",
20
- "@configura/web-utilities": "1.6.1"
19
+ "@configura/web-core": "2.0.0-alpha.0",
20
+ "@configura/web-utilities": "2.0.0-alpha.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@configura/web-api": "1.6.1",
23
+ "@configura/web-api": "2.0.0-alpha.0",
24
24
  "del-cli": "^3.0.0",
25
25
  "typescript": "4.2"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"
29
29
  },
30
- "gitHead": "bffef8762f32d8629a89837cafc20d34702409a3"
30
+ "gitHead": "b802ecc481c41f8dd8342dc6eaf5010a86f0f85d"
31
31
  }