@needle-tools/engine 4.10.0 → 4.10.1-next.ffb3f90
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/CHANGELOG.md +5 -0
- package/components.needle.json +1 -1
- package/dist/{needle-engine.bundle-BSq-d_16.min.js → needle-engine.bundle-Bn8PNDsX.min.js} +117 -117
- package/dist/{needle-engine.bundle-C2kVfQq6.umd.cjs → needle-engine.bundle-Cya6w82Z.umd.cjs} +113 -113
- package/dist/{needle-engine.bundle-CIuhf7-t.js → needle-engine.bundle-rOOXObYF.js} +4602 -4569
- package/dist/needle-engine.js +2 -2
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_context.js +7 -7
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.loading.d.ts +1 -0
- package/lib/engine/webcomponents/needle-engine.loading.js +5 -13
- package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +1 -1
- package/lib/engine-components/Camera.js +1 -1
- package/lib/engine-components/CharacterController.d.ts +2 -2
- package/lib/engine-components/CharacterController.js +2 -2
- package/lib/engine-components/OrbitControls.d.ts +1 -1
- package/lib/engine-components/OrbitControls.js +1 -1
- package/lib/engine-components/SceneSwitcher.d.ts +1 -1
- package/lib/engine-components/SceneSwitcher.js +1 -1
- package/lib/engine-components/timeline/TimelineModels.d.ts +35 -2
- package/lib/engine-components/timeline/TimelineModels.js +6 -0
- package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
- package/lib/engine-components/web/ViewBox.d.ts +24 -11
- package/lib/engine-components/web/ViewBox.js +154 -62
- package/lib/engine-components/web/ViewBox.js.map +1 -1
- package/lib/engine-components/webxr/WebARSessionRoot.js +1 -0
- package/lib/engine-components/webxr/WebARSessionRoot.js.map +1 -1
- package/package.json +2 -2
- package/src/engine/engine_context.ts +8 -8
- package/src/engine/webcomponents/needle-engine.loading.ts +5 -13
- package/src/engine-components/Camera.ts +1 -1
- package/src/engine-components/CharacterController.ts +2 -2
- package/src/engine-components/OrbitControls.ts +1 -1
- package/src/engine-components/SceneSwitcher.ts +1 -1
- package/src/engine-components/timeline/TimelineModels.ts +35 -3
- package/src/engine-components/web/ViewBox.ts +164 -57
- package/src/engine-components/webxr/WebARSessionRoot.ts +1 -0
|
@@ -36,7 +36,7 @@ const debugscreenpointtoray = getParam("debugscreenpointtoray");
|
|
|
36
36
|
* Supports both perspective and orthographic cameras with various rendering options.
|
|
37
37
|
* Internally, this component uses {@link PerspectiveCamera} and {@link OrthographicCamera} three.js objects.
|
|
38
38
|
*
|
|
39
|
-
* @category Camera
|
|
39
|
+
* @category Camera
|
|
40
40
|
* @group Components
|
|
41
41
|
*/
|
|
42
42
|
export class Camera extends Behaviour implements ICamera {
|
|
@@ -14,7 +14,7 @@ import { Rigidbody } from "./RigidBody.js";
|
|
|
14
14
|
const debug = getParam("debugcharactercontroller");
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* @category Camera
|
|
17
|
+
* @category Camera
|
|
18
18
|
* @group Components
|
|
19
19
|
*/
|
|
20
20
|
export class CharacterController extends Behaviour {
|
|
@@ -107,7 +107,7 @@ export class CharacterController extends Behaviour {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* @category Camera
|
|
110
|
+
* @category Camera
|
|
111
111
|
* @category Interactivity
|
|
112
112
|
* @group Components
|
|
113
113
|
*/
|
|
@@ -63,7 +63,7 @@ declare module 'three/examples/jsm/controls/OrbitControls.js' {
|
|
|
63
63
|
/** The OrbitControls component is used to control a camera using the [OrbitControls from three.js](https://threejs.org/docs/#examples/en/controls/OrbitControls) library.
|
|
64
64
|
* The three OrbitControls object can be accessed via the `controls` property.
|
|
65
65
|
* The object being controlled by the OrbitControls (usually the camera) can be accessed via the `controllerObject` property.
|
|
66
|
-
* @category Camera
|
|
66
|
+
* @category Camera
|
|
67
67
|
* @group Components
|
|
68
68
|
*/
|
|
69
69
|
export class OrbitControls extends Behaviour implements ICameraController {
|
|
@@ -80,7 +80,7 @@ export interface ISceneEventListener {
|
|
|
80
80
|
* Available scenes are defined in the `scenes` array.
|
|
81
81
|
* Loaded scenes will be added to the SceneSwitcher's GameObject as a child and removed when another scene is loaded by the same SceneSwitcher.
|
|
82
82
|
* Live Examples
|
|
83
|
-
* - [Multi Scenes Sample](https://engine.needle.tools/samples/multi-
|
|
83
|
+
* - [Multi Scenes Sample](https://engine.needle.tools/samples/multi-scene-example) (source code available)
|
|
84
84
|
* - [Needle Website](https://needle.tools)
|
|
85
85
|
* - [Songs Of Cultures](https://app.songsofcultures.com)
|
|
86
86
|
*
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { AnimationClip, Object3D, Quaternion, Vector3 } from "three";
|
|
2
|
-
import { Behavior } from "three-mesh-ui";
|
|
3
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @category Animation and Sequencing
|
|
5
|
+
*/
|
|
4
6
|
export declare type TimelineAssetModel = {
|
|
5
7
|
name: string;
|
|
6
8
|
tracks: TrackModel[];
|
|
7
9
|
}
|
|
8
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @category Animation and Sequencing
|
|
13
|
+
*/
|
|
9
14
|
export enum TrackType {
|
|
10
15
|
Activation = "ActivationTrack",
|
|
11
16
|
Animation = "AnimationTrack",
|
|
@@ -15,6 +20,9 @@ export enum TrackType {
|
|
|
15
20
|
Signal = "SignalTrack",
|
|
16
21
|
}
|
|
17
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @category Animation and Sequencing
|
|
25
|
+
*/
|
|
18
26
|
export enum ClipExtrapolation {
|
|
19
27
|
None = 0,
|
|
20
28
|
Hold = 1,
|
|
@@ -23,6 +31,9 @@ export enum ClipExtrapolation {
|
|
|
23
31
|
Continue = 4
|
|
24
32
|
};
|
|
25
33
|
|
|
34
|
+
/**
|
|
35
|
+
* @category Animation and Sequencing
|
|
36
|
+
*/
|
|
26
37
|
export declare type TrackModel = {
|
|
27
38
|
name: string;
|
|
28
39
|
type: TrackType;
|
|
@@ -37,11 +48,17 @@ export declare type TrackModel = {
|
|
|
37
48
|
declare type Vec3 = { x: number, y: number, z: number };
|
|
38
49
|
declare type Quat = { x: number, y: number, z: number, w: number };
|
|
39
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @category Animation and Sequencing
|
|
53
|
+
*/
|
|
40
54
|
export declare type TrackOffset = {
|
|
41
55
|
position: Vec3 | Vector3;
|
|
42
56
|
rotation: Quat | Quaternion;
|
|
43
57
|
}
|
|
44
58
|
|
|
59
|
+
/**
|
|
60
|
+
* @category Animation and Sequencing
|
|
61
|
+
*/
|
|
45
62
|
export declare type ClipModel = {
|
|
46
63
|
start: number;
|
|
47
64
|
end: number;
|
|
@@ -56,6 +73,9 @@ export declare type ClipModel = {
|
|
|
56
73
|
reversed?: boolean;
|
|
57
74
|
}
|
|
58
75
|
|
|
76
|
+
/**
|
|
77
|
+
* @category Animation and Sequencing
|
|
78
|
+
*/
|
|
59
79
|
export declare type AnimationClipModel = {
|
|
60
80
|
clip: string | number | AnimationClip;
|
|
61
81
|
loop: boolean;
|
|
@@ -65,12 +85,18 @@ export declare type AnimationClipModel = {
|
|
|
65
85
|
rotation?: Quat | Quaternion;
|
|
66
86
|
}
|
|
67
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @category Animation and Sequencing
|
|
90
|
+
*/
|
|
68
91
|
export declare type AudioClipModel = {
|
|
69
92
|
clip: string;
|
|
70
93
|
loop: boolean;
|
|
71
94
|
volume: number;
|
|
72
95
|
}
|
|
73
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @category Animation and Sequencing
|
|
99
|
+
*/
|
|
74
100
|
export declare type ControlClipModel = {
|
|
75
101
|
sourceObject: string | Object3D;
|
|
76
102
|
controlActivation: boolean;
|
|
@@ -81,11 +107,16 @@ export enum MarkerType {
|
|
|
81
107
|
Signal = "SignalEmitter",
|
|
82
108
|
}
|
|
83
109
|
|
|
84
|
-
|
|
110
|
+
/**
|
|
111
|
+
* @category Animation and Sequencing
|
|
112
|
+
*/export declare class MarkerModel {
|
|
85
113
|
type: MarkerType;
|
|
86
114
|
time: number;
|
|
87
115
|
}
|
|
88
116
|
|
|
117
|
+
/**
|
|
118
|
+
* @category Animation and Sequencing
|
|
119
|
+
*/
|
|
89
120
|
export declare class SignalMarkerModel extends MarkerModel {
|
|
90
121
|
retroActive: boolean;
|
|
91
122
|
emitOnce: boolean;
|
|
@@ -101,5 +132,6 @@ export declare class SignalMarkerModel extends MarkerModel {
|
|
|
101
132
|
* ```
|
|
102
133
|
*
|
|
103
134
|
* @link [Example Project using ScrollMarker](https://scrollytelling-bike-z23hmxb2gnu5a.needle.run/)
|
|
104
|
-
|
|
135
|
+
* @category Animation and Sequencing
|
|
136
|
+
*/
|
|
105
137
|
export type ScrollMarkerModel = MarkerModel & { name: string };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Camera, PerspectiveCamera, Quaternion, Scene, Vector2, Vector3 } from "three";
|
|
1
|
+
import { Camera, Matrix4, PerspectiveCamera, Quaternion, Scene, Vector2, Vector3 } from "three";
|
|
2
2
|
|
|
3
3
|
import { isDevEnvironment } from "../../engine/debug/debug.js";
|
|
4
|
+
import type { Context } from "../../engine/engine_context.js";
|
|
4
5
|
import { Gizmos } from "../../engine/engine_gizmos.js";
|
|
6
|
+
import { Mathf } from "../../engine/engine_math.js";
|
|
5
7
|
import { serializable } from "../../engine/engine_serialization_decorator.js";
|
|
6
|
-
import { getTempVector } from "../../engine/engine_three_utils.js";
|
|
8
|
+
import { getTempQuaternion, getTempVector } from "../../engine/engine_three_utils.js";
|
|
7
9
|
import { registerType } from "../../engine/engine_typestore.js";
|
|
8
10
|
import { getParam } from "../../engine/engine_utils.js";
|
|
9
11
|
import { RGBAColor } from "../../engine/js-extensions/RGBAColor.js";
|
|
@@ -11,7 +13,8 @@ import { Behaviour } from "../Component.js";
|
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
const debugParam = getParam("debugviewbox");
|
|
14
|
-
const disabledGizmoColor = new RGBAColor(.5, .5, .5, .
|
|
16
|
+
const disabledGizmoColor = new RGBAColor(.5, .5, .5, .3);
|
|
17
|
+
const enabledGizmoColor = new RGBAColor(.5, .5, 0, 1);
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* This component can be used to automatically fit a certain box area into the camera view - no matter your screen size or aspect ratio.
|
|
@@ -28,23 +31,39 @@ const disabledGizmoColor = new RGBAColor(.5, .5, .5, .5);
|
|
|
28
31
|
viewBox.scale.set(0, 0, 0);
|
|
29
32
|
viewBox.addComponent(ViewBox, { debug: true });
|
|
30
33
|
scene.add(viewBox);
|
|
34
|
+
* ```
|
|
31
35
|
|
|
32
|
-
* @category
|
|
36
|
+
* @category Camera
|
|
33
37
|
* @group Components
|
|
34
38
|
* @component
|
|
35
|
-
* ```
|
|
36
39
|
*/
|
|
37
40
|
@registerType
|
|
38
41
|
export class ViewBox extends Behaviour {
|
|
39
42
|
|
|
43
|
+
/** All known viewbox instances */
|
|
40
44
|
static readonly instances: ViewBox[] = [];
|
|
41
45
|
|
|
46
|
+
/**
|
|
47
|
+
* The currently active viewbox (the last one that was set active). If you have multiple viewboxes in your scene, only the active one will be used.
|
|
48
|
+
* Note that the last viewbox may be inactive if its component is disabled or disabled in the hierarchy.
|
|
49
|
+
* @returns The active viewbox or null if none is active
|
|
50
|
+
*/
|
|
51
|
+
static get activeInstance(): ViewBox | null {
|
|
52
|
+
if (ViewBox.instances.length === 0) return null;
|
|
53
|
+
return ViewBox.instances[ViewBox.instances.length - 1];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A runner instance is used per context to update the viewbox
|
|
58
|
+
*/
|
|
59
|
+
private static readonly runners: WeakMap<Context, Runner> = new WeakMap();
|
|
60
|
+
|
|
42
61
|
/**
|
|
43
62
|
* The reference field of view is used to calculate the box size. This should usually be the same as your camera's fov.
|
|
44
|
-
* @default
|
|
63
|
+
* @default -1 (meaning it will use the camera fov on the first frame)
|
|
45
64
|
*/
|
|
46
65
|
@serializable()
|
|
47
|
-
referenceFieldOfView: number
|
|
66
|
+
referenceFieldOfView: number = -1;
|
|
48
67
|
|
|
49
68
|
/**
|
|
50
69
|
* Enable debug logs and rendering for this component instance
|
|
@@ -52,23 +71,47 @@ export class ViewBox extends Behaviour {
|
|
|
52
71
|
@serializable()
|
|
53
72
|
debug: boolean = false;
|
|
54
73
|
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Set this ViewBox as the active one (if you have multiple in your scene). The last active one will be used.
|
|
77
|
+
* @returns self for chaining
|
|
78
|
+
*/
|
|
79
|
+
setActive(): this {
|
|
80
|
+
this.enabled = true;
|
|
81
|
+
const idx = ViewBox.instances.indexOf(this);
|
|
82
|
+
if (idx !== -1) ViewBox.instances.splice(idx, 1);
|
|
83
|
+
ViewBox.instances.push(this);
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @internal */
|
|
55
88
|
onEnable(): void {
|
|
56
89
|
if (debugParam || this.debug || isDevEnvironment()) console.debug("[ViewBox] Using camera fov:", this.referenceFieldOfView);
|
|
57
90
|
// register instance
|
|
58
91
|
ViewBox.instances.push(this);
|
|
92
|
+
|
|
93
|
+
this.removeUpdateCallback();
|
|
94
|
+
this.context.pre_render_callbacks.push(this.internalUpdate);
|
|
59
95
|
}
|
|
60
96
|
|
|
97
|
+
/** @internal */
|
|
61
98
|
onDisable(): void {
|
|
62
99
|
if (debugParam || this.debug) console.debug("[ViewBox] Disabled");
|
|
63
100
|
// unregister instance
|
|
64
101
|
const idx = ViewBox.instances.indexOf(this);
|
|
65
102
|
if (idx !== -1) ViewBox.instances.splice(idx, 1);
|
|
66
|
-
this.
|
|
103
|
+
this.removeUpdateCallback();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private removeUpdateCallback() {
|
|
107
|
+
// remove prerender callback
|
|
108
|
+
const cbIdx = this.context.pre_render_callbacks.indexOf(this.internalUpdate);
|
|
109
|
+
if (cbIdx !== -1) this.context.pre_render_callbacks.splice(cbIdx, 1);
|
|
67
110
|
}
|
|
68
111
|
|
|
69
|
-
|
|
112
|
+
private internalUpdate = () => {
|
|
70
113
|
if (this.context.isInXR) return;
|
|
71
|
-
if (this.destroyed) return;
|
|
114
|
+
if (this.destroyed || !this.activeAndEnabled) return;
|
|
72
115
|
const isActive = ViewBox.instances[ViewBox.instances.length - 1] === this;
|
|
73
116
|
if (!isActive) {
|
|
74
117
|
if (debugParam || this.debug) {
|
|
@@ -76,40 +119,85 @@ export class ViewBox extends Behaviour {
|
|
|
76
119
|
}
|
|
77
120
|
return;
|
|
78
121
|
}
|
|
79
|
-
if (debugParam || this.debug) Gizmos.DrawWireBox(this.gameObject.worldPosition, this.gameObject.worldScale,
|
|
122
|
+
if (debugParam || this.debug) Gizmos.DrawWireBox(this.gameObject.worldPosition, this.gameObject.worldScale, enabledGizmoColor, 0, true, this.gameObject.worldQuaternion);
|
|
123
|
+
|
|
80
124
|
|
|
81
125
|
// calculate box size to fit the camera frustrum size at the current position (just scale)
|
|
82
126
|
const camera = this.context.mainCamera;
|
|
83
127
|
if (!camera) return;
|
|
84
128
|
if (!(camera instanceof PerspectiveCamera)) {
|
|
85
129
|
// TODO: support orthographic camera
|
|
130
|
+
if (!this["__warnedOrthographic"]) {
|
|
131
|
+
console.warn("[ViewBox] Only perspective cameras are supported.");
|
|
132
|
+
this["__warnedOrthographic"] = true;
|
|
133
|
+
}
|
|
86
134
|
return;
|
|
87
135
|
}
|
|
88
136
|
|
|
89
|
-
if (this.referenceFieldOfView === undefined) {
|
|
137
|
+
if (this.referenceFieldOfView === undefined || this.referenceFieldOfView === -1) {
|
|
90
138
|
this.referenceFieldOfView = camera.fov;
|
|
139
|
+
console.debug("[ViewBox] No referenceFieldOfView set, using camera fov:", this.referenceFieldOfView);
|
|
91
140
|
}
|
|
92
|
-
|
|
93
141
|
if (this.referenceFieldOfView === undefined || this.referenceFieldOfView <= 0) {
|
|
94
142
|
if (debugParam || this.debug) console.warn("[ViewBox] No valid referenceFieldOfView set, cannot adjust box size:", this.referenceFieldOfView);
|
|
95
143
|
return;
|
|
96
144
|
}
|
|
97
145
|
|
|
98
|
-
|
|
99
|
-
|
|
146
|
+
let runner = ViewBox.runners.get(this.context);
|
|
147
|
+
if (!runner) {
|
|
148
|
+
runner = new Runner();
|
|
149
|
+
ViewBox.runners.set(this.context, runner);
|
|
150
|
+
}
|
|
151
|
+
runner.update(this);
|
|
152
|
+
|
|
153
|
+
// BACKLOG: some code for box scale of an object (different component)
|
|
154
|
+
// this.gameObject.worldScale = getTempVector(width, height, worldscale.z);
|
|
155
|
+
// this.gameObject.scale.multiplyScalar(.98)
|
|
156
|
+
// const minscale = Math.min(width, height);
|
|
157
|
+
// console.log(width, height);
|
|
158
|
+
// this.gameObject.worldScale = getTempVector(scale, scale, scale);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
const projectionMatrixCopy: Matrix4 = new Matrix4();
|
|
167
|
+
const projectionMatrixInverseCopy: Matrix4 = new Matrix4();
|
|
168
|
+
|
|
169
|
+
class Runner {
|
|
170
|
+
|
|
171
|
+
private lastActiveViewBox: ViewBox | null = null;
|
|
172
|
+
private lastViewBoxChangeTime: number = -1;
|
|
173
|
+
private currentX: number = 0;
|
|
174
|
+
private currentY: number = 0;
|
|
175
|
+
private currentZoom: number = 1;
|
|
176
|
+
|
|
177
|
+
update(viewBox: ViewBox) {
|
|
178
|
+
|
|
179
|
+
const context = viewBox.context;
|
|
180
|
+
const camera = viewBox.context.mainCamera;
|
|
181
|
+
if (!(camera instanceof PerspectiveCamera)) return;
|
|
182
|
+
|
|
183
|
+
if (this.lastActiveViewBox !== viewBox) {
|
|
184
|
+
if (this.lastActiveViewBox === null)
|
|
185
|
+
this.lastViewBoxChangeTime = -100; // long ago
|
|
186
|
+
else
|
|
187
|
+
this.lastViewBoxChangeTime = context.time.time;
|
|
188
|
+
this.lastActiveViewBox = viewBox;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const domWidth = context.domWidth;
|
|
192
|
+
const domHeight = context.domHeight;
|
|
100
193
|
|
|
101
|
-
let rectPosX = 0;
|
|
102
|
-
let rectPosY = 0;
|
|
103
194
|
let rectWidth = domWidth;
|
|
104
195
|
let rectHeight = domHeight;
|
|
105
196
|
let diffWidth = 1;
|
|
106
197
|
let diffHeight = 1;
|
|
107
198
|
// use focus rect if available
|
|
108
|
-
const focusRectSize =
|
|
199
|
+
const focusRectSize = context.focusRectSize;
|
|
109
200
|
if (focusRectSize) {
|
|
110
|
-
// console.log(focusRectSize)
|
|
111
|
-
rectPosX = focusRectSize.x;
|
|
112
|
-
rectPosY = focusRectSize.y;
|
|
113
201
|
rectWidth = focusRectSize.width;
|
|
114
202
|
rectHeight = focusRectSize.height;
|
|
115
203
|
diffWidth = domWidth / rectWidth;
|
|
@@ -117,22 +205,28 @@ export class ViewBox extends Behaviour {
|
|
|
117
205
|
}
|
|
118
206
|
|
|
119
207
|
|
|
208
|
+
// Copy the projection matrix and restore values so we can reset it later
|
|
209
|
+
projectionMatrixCopy.copy(camera.projectionMatrix);
|
|
210
|
+
projectionMatrixInverseCopy.copy(camera.projectionMatrixInverse);
|
|
120
211
|
const view = camera.view;
|
|
121
212
|
const zoom = camera.zoom;
|
|
122
213
|
const aspect = camera.aspect;
|
|
123
214
|
const fov = camera.fov;
|
|
215
|
+
// Set values to default so we can calculate the box size correctly
|
|
124
216
|
camera.view = null;
|
|
125
217
|
camera.zoom = 1;
|
|
126
|
-
camera.fov =
|
|
218
|
+
camera.fov = viewBox.referenceFieldOfView;
|
|
127
219
|
camera.updateProjectionMatrix();
|
|
128
220
|
|
|
129
221
|
|
|
130
|
-
const boxPosition =
|
|
131
|
-
const boxScale =
|
|
222
|
+
const boxPosition = viewBox.gameObject.worldPosition;
|
|
223
|
+
const boxScale = viewBox.gameObject.worldScale;
|
|
132
224
|
|
|
133
225
|
const cameraPosition = camera.worldPosition;
|
|
134
226
|
const distance = cameraPosition.distanceTo(boxPosition);
|
|
135
227
|
|
|
228
|
+
const timeSinceViewBoxChanged = context.time.time - this.lastViewBoxChangeTime;
|
|
229
|
+
const interpolationDelta = timeSinceViewBoxChanged < 1 ? (context.time.deltaTime / .1) : 1;
|
|
136
230
|
|
|
137
231
|
// #region camera fixes
|
|
138
232
|
// If the camera is inside the box, move it out
|
|
@@ -140,13 +234,13 @@ export class ViewBox extends Behaviour {
|
|
|
140
234
|
const direction = getTempVector(cameraPosition).sub(boxPosition);
|
|
141
235
|
if (distance < boxSizeMax) {
|
|
142
236
|
// move camera out of bounds
|
|
143
|
-
if (
|
|
237
|
+
if (viewBox.debug || debugParam) console.warn("[ViewBox] Moving camera out of bounds", distance, "<", boxSizeMax);
|
|
144
238
|
const positionDirection = getTempVector(direction);
|
|
145
239
|
positionDirection.y *= .00000001; // stay on horizontal plane mostly
|
|
146
240
|
positionDirection.normalize();
|
|
147
|
-
const lengthToMove = (boxSizeMax - distance);
|
|
241
|
+
const lengthToMove = (boxSizeMax - distance);
|
|
148
242
|
const newPosition = cameraPosition.add(positionDirection.multiplyScalar(lengthToMove));
|
|
149
|
-
camera.worldPosition = newPosition.lerp(cameraPosition, 1 -
|
|
243
|
+
camera.worldPosition = newPosition.lerp(cameraPosition, 1 - context.time.deltaTime);
|
|
150
244
|
}
|
|
151
245
|
|
|
152
246
|
// Ensure the camera looks at the ViewBox
|
|
@@ -160,18 +254,26 @@ export class ViewBox extends Behaviour {
|
|
|
160
254
|
// camera.worldQuaternion = rotation;
|
|
161
255
|
// camera.updateMatrixWorld();
|
|
162
256
|
// }
|
|
163
|
-
const boxPositionInCameraSpace = getTempVector(boxPosition);
|
|
164
|
-
|
|
165
|
-
camera
|
|
166
|
-
camera.
|
|
257
|
+
// const boxPositionInCameraSpace = getTempVector(boxPosition);
|
|
258
|
+
|
|
259
|
+
// Ensure the camera looks at the box position
|
|
260
|
+
// camera.worldToLocal(boxPositionInCameraSpace);
|
|
261
|
+
// if (interpolationDelta < 1) {
|
|
262
|
+
// const startRotation = interpolationDelta < 1 ? getTempQuaternion(camera.quaternion) : null;
|
|
263
|
+
// camera.lookAt(boxPosition);
|
|
264
|
+
// if (startRotation !== null) {
|
|
265
|
+
// camera.quaternion.slerpQuaternions(startRotation, camera.quaternion, interpolationDelta);
|
|
266
|
+
// }
|
|
267
|
+
// camera.updateMatrixWorld();
|
|
268
|
+
// }
|
|
167
269
|
|
|
168
270
|
|
|
169
271
|
// #region calculate fit
|
|
170
|
-
const vFOV =
|
|
272
|
+
const vFOV = viewBox.referenceFieldOfView * Math.PI / 180; // convert vertical fov to radians
|
|
171
273
|
const height = 2 * Math.tan(vFOV / 2) * distance; // visible height
|
|
172
274
|
const width = height * camera.aspect; // visible width
|
|
173
275
|
|
|
174
|
-
const projectedBox = this.projectBoxIntoCamera(camera, 1);
|
|
276
|
+
const projectedBox = this.projectBoxIntoCamera(viewBox, camera, 1);
|
|
175
277
|
// return
|
|
176
278
|
const boxWidth = (projectedBox.maxX - projectedBox.minX);
|
|
177
279
|
const boxHeight = (projectedBox.maxY - projectedBox.minY);
|
|
@@ -182,32 +284,38 @@ export class ViewBox extends Behaviour {
|
|
|
182
284
|
width / diffWidth,
|
|
183
285
|
height / diffHeight
|
|
184
286
|
);
|
|
287
|
+
const rectZoom = scale / (height * .5);
|
|
185
288
|
// console.log({ scale, width, height, boxWidth: boxWidth * camera.aspect, boxHeight, diffWidth, diffHeight, aspect: camera.aspect, distance })
|
|
186
289
|
// this.context.focusRectSettings.zoom = 1.39;
|
|
187
290
|
// if (!this.context.focusRect) this.context.setCameraFocusRect(this.context.domElement);
|
|
188
291
|
// return
|
|
189
292
|
const vec = getTempVector(boxPosition);
|
|
190
293
|
vec.project(camera);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
294
|
+
|
|
295
|
+
if (interpolationDelta < 1) {
|
|
296
|
+
this.currentX = Mathf.lerp(this.currentX, vec.x, interpolationDelta);
|
|
297
|
+
this.currentY = Mathf.lerp(this.currentY, vec.y, interpolationDelta);
|
|
298
|
+
this.currentZoom = Mathf.lerp(this.currentZoom, rectZoom, interpolationDelta);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
this.currentX = vec.x;
|
|
302
|
+
this.currentY = vec.y;
|
|
303
|
+
this.currentZoom = rectZoom;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Apply new values
|
|
307
|
+
context.focusRectSettings.offsetX = this.currentX;
|
|
308
|
+
context.focusRectSettings.offsetY = this.currentY;
|
|
309
|
+
context.focusRectSettings.zoom = this.currentZoom;
|
|
310
|
+
if (!context.focusRect) context.setCameraFocusRect(context.domElement); // if we don't have a focus rect yet, set it to the dom element
|
|
196
311
|
|
|
197
312
|
// Reset values
|
|
198
313
|
camera.view = view;
|
|
199
314
|
camera.zoom = zoom;
|
|
200
315
|
camera.aspect = aspect;
|
|
201
316
|
camera.fov = fov;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// BACKLOG: some code for box scale of an object (different component)
|
|
206
|
-
// this.gameObject.worldScale = getTempVector(width, height, worldscale.z);
|
|
207
|
-
// this.gameObject.scale.multiplyScalar(.98)
|
|
208
|
-
// const minscale = Math.min(width, height);
|
|
209
|
-
// console.log(width, height);
|
|
210
|
-
// this.gameObject.worldScale = getTempVector(scale, scale, scale);
|
|
317
|
+
camera.projectionMatrix.copy(projectionMatrixCopy);
|
|
318
|
+
camera.projectionMatrixInverse.copy(projectionMatrixInverseCopy);
|
|
211
319
|
}
|
|
212
320
|
|
|
213
321
|
|
|
@@ -222,7 +330,7 @@ export class ViewBox extends Behaviour {
|
|
|
222
330
|
|
|
223
331
|
|
|
224
332
|
|
|
225
|
-
private projectBoxIntoCamera(camera: Camera, _factor: number) {
|
|
333
|
+
private projectBoxIntoCamera(comp: ViewBox, camera: Camera, _factor: number) {
|
|
226
334
|
const factor = .5 * _factor;
|
|
227
335
|
|
|
228
336
|
const corners = [
|
|
@@ -241,7 +349,7 @@ export class ViewBox extends Behaviour {
|
|
|
241
349
|
let maxY = Number.NEGATIVE_INFINITY;
|
|
242
350
|
for (let i = 0; i < corners.length; i++) {
|
|
243
351
|
const c = corners[i];
|
|
244
|
-
c.applyMatrix4(
|
|
352
|
+
c.applyMatrix4(comp.gameObject.matrixWorld);
|
|
245
353
|
c.project(camera);
|
|
246
354
|
if (c.x < minX) minX = c.x;
|
|
247
355
|
if (c.x > maxX) maxX = c.x;
|
|
@@ -253,15 +361,15 @@ export class ViewBox extends Behaviour {
|
|
|
253
361
|
if (!this._projectedBoxElement) {
|
|
254
362
|
this._projectedBoxElement = document.createElement("div");
|
|
255
363
|
}
|
|
256
|
-
if (this._projectedBoxElement.parentElement !==
|
|
257
|
-
|
|
364
|
+
if (this._projectedBoxElement.parentElement !== comp.context.domElement)
|
|
365
|
+
comp.context.domElement.appendChild(this._projectedBoxElement);
|
|
258
366
|
this._projectedBoxElement.style.position = "fixed";
|
|
259
367
|
// dotted but with larger gaps
|
|
260
368
|
this._projectedBoxElement.style.outline = "2px dashed rgba(255,0,0,.5)";
|
|
261
|
-
this._projectedBoxElement.style.left = ((minX * .5 + .5) *
|
|
262
|
-
this._projectedBoxElement.style.top = ((-maxY * .5 + .5) *
|
|
263
|
-
this._projectedBoxElement.style.width = ((maxX - minX) * .5 *
|
|
264
|
-
this._projectedBoxElement.style.height = ((maxY - minY) * .5 *
|
|
369
|
+
this._projectedBoxElement.style.left = ((minX * .5 + .5) * comp.context.domWidth) + "px";
|
|
370
|
+
this._projectedBoxElement.style.top = ((-maxY * .5 + .5) * comp.context.domHeight) + "px";
|
|
371
|
+
this._projectedBoxElement.style.width = ((maxX - minX) * .5 * comp.context.domWidth) + "px";
|
|
372
|
+
this._projectedBoxElement.style.height = ((maxY - minY) * .5 * comp.context.domHeight) + "px";
|
|
265
373
|
this._projectedBoxElement.style.pointerEvents = "none";
|
|
266
374
|
this._projectedBoxElement.style.zIndex = "1000";
|
|
267
375
|
}
|
|
@@ -274,5 +382,4 @@ export class ViewBox extends Behaviour {
|
|
|
274
382
|
|
|
275
383
|
|
|
276
384
|
|
|
277
|
-
|
|
278
|
-
}
|
|
385
|
+
}
|