@vived/app 2.19.1 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Entities/KeyboardInput.js +0 -2
- package/lib/Entities/MouseInput.js +0 -5
- package/lib/Entities/SceneRoot.d.ts +69 -0
- package/lib/Entities/SceneRoot.js +77 -0
- package/lib/Entities/TransformNode.d.ts +78 -0
- package/lib/Entities/TransformNode.js +217 -0
- package/lib/Entities/WorkPlane.d.ts +49 -0
- package/lib/Entities/WorkPlane.js +122 -0
- package/lib/Entities/index.d.ts +3 -0
- package/lib/Entities/index.js +3 -0
- package/lib/PresentationManagers/FocusCameraPosRotPM.d.ts +13 -0
- package/lib/PresentationManagers/FocusCameraPosRotPM.js +28 -0
- package/lib/PresentationManagers/TransformNodePM.d.ts +14 -0
- package/lib/PresentationManagers/TransformNodePM.js +23 -0
- package/lib/PresentationManagers/index.d.ts +2 -0
- package/lib/PresentationManagers/index.js +2 -0
- package/lib/UseCases/SceneRoot/SerializeSceneRoot.d.ts +18 -0
- package/lib/UseCases/SceneRoot/SerializeSceneRoot.js +48 -0
- package/lib/UseCases/SceneRoot/index.d.ts +1 -0
- package/lib/UseCases/SceneRoot/index.js +13 -0
- package/lib/UseCases/index.d.ts +1 -0
- package/lib/UseCases/index.js +1 -0
- package/lib/ValueObjects/Angle.d.ts +18 -0
- package/lib/ValueObjects/Angle.js +26 -2
- package/lib/ValueObjects/Color.d.ts +46 -0
- package/lib/ValueObjects/Color.js +46 -0
- package/lib/ValueObjects/Matrix.d.ts +120 -0
- package/lib/ValueObjects/Matrix.js +423 -0
- package/lib/ValueObjects/Quaternion.d.ts +94 -0
- package/lib/ValueObjects/Quaternion.js +243 -0
- package/lib/ValueObjects/Vector2.d.ts +82 -0
- package/lib/ValueObjects/Vector2.js +82 -0
- package/lib/ValueObjects/Vector3.d.ts +107 -0
- package/lib/ValueObjects/Vector3.js +116 -0
- package/lib/ValueObjects/index.d.ts +2 -0
- package/lib/ValueObjects/index.js +2 -0
- package/package.json +1 -1
|
@@ -23,7 +23,6 @@ class KeyboardInputImp {
|
|
|
23
23
|
this._eventElement = undefined;
|
|
24
24
|
};
|
|
25
25
|
this.submitKeyDown = (e) => {
|
|
26
|
-
e.preventDefault();
|
|
27
26
|
this.controllers.forEach((c) => {
|
|
28
27
|
if (c.onKeyDown) {
|
|
29
28
|
c.onKeyDown(e);
|
|
@@ -31,7 +30,6 @@ class KeyboardInputImp {
|
|
|
31
30
|
});
|
|
32
31
|
};
|
|
33
32
|
this.submitKeyUp = (e) => {
|
|
34
|
-
e.preventDefault();
|
|
35
33
|
this.controllers.forEach((c) => {
|
|
36
34
|
if (c.onKeyUp) {
|
|
37
35
|
c.onKeyUp(e);
|
|
@@ -42,7 +42,6 @@ class MouseInputImp {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
this.onMouseDown = (e) => {
|
|
45
|
-
e.preventDefault();
|
|
46
45
|
const inputEvt = this.makeMouseInputEvent(e);
|
|
47
46
|
this.controllers.forEach((c) => {
|
|
48
47
|
if (c.onDown) {
|
|
@@ -53,7 +52,6 @@ class MouseInputImp {
|
|
|
53
52
|
this.pressEvent = e;
|
|
54
53
|
};
|
|
55
54
|
this.onMouseUp = (e) => {
|
|
56
|
-
e.preventDefault();
|
|
57
55
|
const inputEvt = this.makeMouseInputEvent(e);
|
|
58
56
|
this.controllers.forEach((c) => {
|
|
59
57
|
if (c.onUp) {
|
|
@@ -76,7 +74,6 @@ class MouseInputImp {
|
|
|
76
74
|
this.pressEvent = undefined;
|
|
77
75
|
};
|
|
78
76
|
this.onMouseMove = (e) => {
|
|
79
|
-
e.preventDefault();
|
|
80
77
|
const inputEvt = this.makeMouseInputEvent(e);
|
|
81
78
|
this.controllers.forEach((c) => {
|
|
82
79
|
if (c.onMove) {
|
|
@@ -93,7 +90,6 @@ class MouseInputImp {
|
|
|
93
90
|
}
|
|
94
91
|
};
|
|
95
92
|
this.onMouseOut = (e) => {
|
|
96
|
-
e.preventDefault();
|
|
97
93
|
if (!this.isPressed)
|
|
98
94
|
return;
|
|
99
95
|
const inputEvt = this.makeMouseInputEvent(e);
|
|
@@ -106,7 +102,6 @@ class MouseInputImp {
|
|
|
106
102
|
this.isPressed = false;
|
|
107
103
|
};
|
|
108
104
|
this.onWheel = (e) => {
|
|
109
|
-
e.preventDefault();
|
|
110
105
|
const inputEvt = this.makeMouseInputEvent(e);
|
|
111
106
|
this.controllers.forEach((c) => {
|
|
112
107
|
if (c.onWheel) {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Quaternion, Vector3 } from "../ValueObjects";
|
|
2
|
+
import { EaseFn, TransformNode } from "./TransformNode";
|
|
3
|
+
export declare type OnSceneRootChange = () => void;
|
|
4
|
+
export interface DefaultSceneRootData {
|
|
5
|
+
position: [number, number, number];
|
|
6
|
+
rotation: [number, number, number, number];
|
|
7
|
+
scale: number;
|
|
8
|
+
id: string;
|
|
9
|
+
minScale: number;
|
|
10
|
+
maxScale: number;
|
|
11
|
+
}
|
|
12
|
+
export interface SceneRoot {
|
|
13
|
+
/**
|
|
14
|
+
* The default position of the scene root in local coordinates
|
|
15
|
+
*/
|
|
16
|
+
defaultPosition: Vector3;
|
|
17
|
+
/**
|
|
18
|
+
* The default rotation of the scene root in local coordinates
|
|
19
|
+
*/
|
|
20
|
+
defaultRoation: Quaternion;
|
|
21
|
+
/**
|
|
22
|
+
* The default scale of the scene root in local coordinates
|
|
23
|
+
*/
|
|
24
|
+
defaultScale: Vector3;
|
|
25
|
+
/**
|
|
26
|
+
* The minimum scale allowed for the scene root
|
|
27
|
+
*/
|
|
28
|
+
minScale: number;
|
|
29
|
+
/**
|
|
30
|
+
* The maximum scale allowed for the scene root
|
|
31
|
+
*/
|
|
32
|
+
maxScale: number;
|
|
33
|
+
/**
|
|
34
|
+
* The identifier for the scene root
|
|
35
|
+
*/
|
|
36
|
+
id: string;
|
|
37
|
+
/**
|
|
38
|
+
* Transform node for the scene root
|
|
39
|
+
*/
|
|
40
|
+
transform: TransformNode;
|
|
41
|
+
/**
|
|
42
|
+
* Applies the default data to this entity. This will not trigger a notification
|
|
43
|
+
*/
|
|
44
|
+
applyDefaultData: (data: DefaultSceneRootData) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Smoothly moves the transform so that the point is a the world origin
|
|
47
|
+
* @param point The point to center on in world coordinates
|
|
48
|
+
* @param durationMS The duration of the transition in milliseconds
|
|
49
|
+
* @param easeFn The easing funciton
|
|
50
|
+
* @param onCompleted An optional callback function when the ease is completed
|
|
51
|
+
*/
|
|
52
|
+
centerOnPoint: (point: Vector3, durationMS: number, easeFn: EaseFn, onCompleted?: () => void) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Smoothly moves the transform so that it is back in the default pose
|
|
55
|
+
* @param durationMS The duration of the transition in milliseconds
|
|
56
|
+
* @param easeFn The easing funciton
|
|
57
|
+
* @param onCompleted An optional callback function when the ease is completed
|
|
58
|
+
*/
|
|
59
|
+
lerpToDefault: (durationMS: number, easeFn: EaseFn, onCompleted?: () => void) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Bumps the scale of the root by a specific amount. Note this will enforce the min and max limits
|
|
62
|
+
* @param amount The world amount to bump the scale by. It will be applied uniformly
|
|
63
|
+
* @param worldPoint The world position about which to apply the scaling
|
|
64
|
+
*/
|
|
65
|
+
bumpScaleAboutPoint: (amount: number, worldPoint: Vector3) => void;
|
|
66
|
+
addObserver: (observer: OnSceneRootChange) => void;
|
|
67
|
+
removeObserver: (observer: OnSceneRootChange) => void;
|
|
68
|
+
}
|
|
69
|
+
export declare function makeSceneRoot(): SceneRoot;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeSceneRoot = void 0;
|
|
4
|
+
const ValueObjects_1 = require("../ValueObjects");
|
|
5
|
+
const ObserverList_1 = require("./ObserverList");
|
|
6
|
+
const TransformNode_1 = require("./TransformNode");
|
|
7
|
+
function makeSceneRoot() {
|
|
8
|
+
return new SceneRootImp();
|
|
9
|
+
}
|
|
10
|
+
exports.makeSceneRoot = makeSceneRoot;
|
|
11
|
+
class SceneRootImp {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.observers = new ObserverList_1.ObserverList();
|
|
14
|
+
this._defaultPosition = ValueObjects_1.Vector3.Zero();
|
|
15
|
+
this._defaultRoation = ValueObjects_1.Quaternion.Identity();
|
|
16
|
+
this._defaultScale = ValueObjects_1.Vector3.One();
|
|
17
|
+
this._minScale = 0.01;
|
|
18
|
+
this._maxScale = 10;
|
|
19
|
+
this._id = "scene_root";
|
|
20
|
+
this.applyDefaultData = (data) => {
|
|
21
|
+
this._defaultPosition = ValueObjects_1.Vector3.FromArray(data.position);
|
|
22
|
+
this._defaultRoation = ValueObjects_1.Quaternion.FromArray(data.rotation);
|
|
23
|
+
this._defaultScale = new ValueObjects_1.Vector3(data.scale, data.scale, data.scale);
|
|
24
|
+
this._maxScale = data.maxScale;
|
|
25
|
+
this._minScale = data.minScale;
|
|
26
|
+
this._id = data.id;
|
|
27
|
+
};
|
|
28
|
+
this.centerOnPoint = (point, durationMS, easeFn, onCompleted) => {
|
|
29
|
+
const finalPosition = ValueObjects_1.Vector3.Subtract(this.transform.worldPosition, point);
|
|
30
|
+
this.transform.lerp(durationMS, easeFn, finalPosition, undefined, undefined, onCompleted);
|
|
31
|
+
};
|
|
32
|
+
this.bumpScaleAboutPoint = (amount, worldPoint) => {
|
|
33
|
+
const localPickOffset = this.transform.worldPointToLocal(worldPoint);
|
|
34
|
+
const currentScale = this.transform.worldScale.x;
|
|
35
|
+
let newScale = currentScale + amount;
|
|
36
|
+
if (newScale < this.minScale) {
|
|
37
|
+
newScale = this.minScale;
|
|
38
|
+
}
|
|
39
|
+
else if (newScale > this.maxScale) {
|
|
40
|
+
newScale = this.maxScale;
|
|
41
|
+
}
|
|
42
|
+
this.transform.worldScale = new ValueObjects_1.Vector3(newScale, newScale, newScale);
|
|
43
|
+
const worldPickOffset = this.transform.localPointToWorld(localPickOffset);
|
|
44
|
+
const bump = ValueObjects_1.Vector3.Subtract(worldPoint, worldPickOffset);
|
|
45
|
+
this.transform.worldPosition = ValueObjects_1.Vector3.Add(bump, this.transform.worldPosition);
|
|
46
|
+
};
|
|
47
|
+
this.lerpToDefault = (durationMS, easeFn, onCompleted) => {
|
|
48
|
+
this.transform.lerp(durationMS, easeFn, this.defaultPosition, this.defaultRoation, this.defaultScale, onCompleted);
|
|
49
|
+
};
|
|
50
|
+
this.addObserver = (observer) => {
|
|
51
|
+
this.observers.add(observer);
|
|
52
|
+
};
|
|
53
|
+
this.removeObserver = (observer) => {
|
|
54
|
+
this.observers.remove(observer);
|
|
55
|
+
};
|
|
56
|
+
this.transform = TransformNode_1.makeTransformNode();
|
|
57
|
+
this.transform.addObserver(this.observers.notify);
|
|
58
|
+
}
|
|
59
|
+
get defaultPosition() {
|
|
60
|
+
return this._defaultPosition;
|
|
61
|
+
}
|
|
62
|
+
get defaultRoation() {
|
|
63
|
+
return this._defaultRoation;
|
|
64
|
+
}
|
|
65
|
+
get defaultScale() {
|
|
66
|
+
return this._defaultScale;
|
|
67
|
+
}
|
|
68
|
+
get minScale() {
|
|
69
|
+
return this._minScale;
|
|
70
|
+
}
|
|
71
|
+
get maxScale() {
|
|
72
|
+
return this._maxScale;
|
|
73
|
+
}
|
|
74
|
+
get id() {
|
|
75
|
+
return this._id;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Matrix, Quaternion, Vector3 } from "../ValueObjects";
|
|
2
|
+
export declare type OnTransformNodeChange = () => void;
|
|
3
|
+
export declare type EaseFn = (p: number) => number;
|
|
4
|
+
export interface TransformNode {
|
|
5
|
+
/**
|
|
6
|
+
* Local position of the transform
|
|
7
|
+
*/
|
|
8
|
+
localPosition: Vector3;
|
|
9
|
+
/**
|
|
10
|
+
* The world position of the transform
|
|
11
|
+
*/
|
|
12
|
+
worldPosition: Vector3;
|
|
13
|
+
/**
|
|
14
|
+
* Local roation of the transform
|
|
15
|
+
*/
|
|
16
|
+
localRotation: Quaternion;
|
|
17
|
+
/**
|
|
18
|
+
* World roation of the transform
|
|
19
|
+
*/
|
|
20
|
+
worldRotation: Quaternion;
|
|
21
|
+
/**
|
|
22
|
+
* Local scale of the transform
|
|
23
|
+
*/
|
|
24
|
+
localScale: Vector3;
|
|
25
|
+
/**
|
|
26
|
+
* World scale of the transform
|
|
27
|
+
*/
|
|
28
|
+
worldScale: Vector3;
|
|
29
|
+
/**
|
|
30
|
+
* Local transformation matrix
|
|
31
|
+
*/
|
|
32
|
+
localMatrix: Matrix;
|
|
33
|
+
/**
|
|
34
|
+
* The global transformation matrix
|
|
35
|
+
*/
|
|
36
|
+
worldMatrix: Matrix;
|
|
37
|
+
/**
|
|
38
|
+
* The transform's parent. Optional
|
|
39
|
+
*/
|
|
40
|
+
parent?: TransformNode;
|
|
41
|
+
/**
|
|
42
|
+
* Transforms a point from local to world space coordinates
|
|
43
|
+
* @param point point to transform in local coordinates
|
|
44
|
+
*/
|
|
45
|
+
localPointToWorld: (point: Vector3) => Vector3;
|
|
46
|
+
/**
|
|
47
|
+
* Transforms a point from world to local space coordinates
|
|
48
|
+
* @param point point to transform in world coordinates
|
|
49
|
+
*/
|
|
50
|
+
worldPointToLocal: (point: Vector3) => Vector3;
|
|
51
|
+
/**
|
|
52
|
+
* Transforms a local direction vector to world coordinates.
|
|
53
|
+
* @param direction direction to transform in local coordinates
|
|
54
|
+
*/
|
|
55
|
+
localDirectionToWorld: (direction: Vector3) => Vector3;
|
|
56
|
+
/**
|
|
57
|
+
* Transforms a world direction vector to local coordinates
|
|
58
|
+
* @param direction direction to transform in world coordinates
|
|
59
|
+
*/
|
|
60
|
+
worldDirectionToLocal: (direction: Vector3) => Vector3;
|
|
61
|
+
/**
|
|
62
|
+
* Lerps this transform node
|
|
63
|
+
* @param duration Lerp duration in MS
|
|
64
|
+
* @param ease Lerp ease function
|
|
65
|
+
* @param desiredPosition: Desired position. Optional.
|
|
66
|
+
* @param desiredRotation: Desired rotation. Optional.
|
|
67
|
+
* @param desiredScale: Desired scale. Optional.
|
|
68
|
+
* @param onCompletedCallback: Optional function to call when the lerp has completed
|
|
69
|
+
*/
|
|
70
|
+
lerp: (duration: number, ease: EaseFn, desiredPosition?: Vector3, desiredRotation?: Quaternion, desiredScale?: Vector3, onCompletedCallback?: () => void) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Cancels any currently running lerp
|
|
73
|
+
*/
|
|
74
|
+
cancelLerp: () => void;
|
|
75
|
+
addObserver: (observer: OnTransformNodeChange) => void;
|
|
76
|
+
removeObserver: (observer: OnTransformNodeChange) => void;
|
|
77
|
+
}
|
|
78
|
+
export declare function makeTransformNode(): TransformNode;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeTransformNode = void 0;
|
|
4
|
+
const ValueObjects_1 = require("../ValueObjects");
|
|
5
|
+
const ObserverList_1 = require("./ObserverList");
|
|
6
|
+
function makeTransformNode() {
|
|
7
|
+
return new TransformNodeImp();
|
|
8
|
+
}
|
|
9
|
+
exports.makeTransformNode = makeTransformNode;
|
|
10
|
+
class TransformNodeImp {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.observers = new ObserverList_1.ObserverList();
|
|
13
|
+
this._transformationMatrix = ValueObjects_1.Matrix.Identity();
|
|
14
|
+
this.localPointToWorld = (point) => {
|
|
15
|
+
return ValueObjects_1.Vector3.Transform(point, this.worldMatrix);
|
|
16
|
+
};
|
|
17
|
+
this.worldPointToLocal = (point) => {
|
|
18
|
+
const worldInverse = ValueObjects_1.Matrix.Invert(this.worldMatrix);
|
|
19
|
+
return ValueObjects_1.Vector3.Transform(point, worldInverse);
|
|
20
|
+
};
|
|
21
|
+
this.localDirectionToWorld = (point) => {
|
|
22
|
+
const rotationMatrix = ValueObjects_1.Quaternion.ToRotationMatrix(this.worldRotation);
|
|
23
|
+
return ValueObjects_1.Vector3.Transform(point, rotationMatrix).unit;
|
|
24
|
+
};
|
|
25
|
+
this.worldDirectionToLocal = (point) => {
|
|
26
|
+
const worldInverse = ValueObjects_1.Matrix.Invert(this.worldMatrix);
|
|
27
|
+
const rotationMatrix = ValueObjects_1.Quaternion.ToRotationMatrix(worldInverse.rotation);
|
|
28
|
+
return ValueObjects_1.Vector3.Transform(point, rotationMatrix).unit;
|
|
29
|
+
};
|
|
30
|
+
this.chrono = 0;
|
|
31
|
+
this.lerpDuration = 1;
|
|
32
|
+
this.lerpEase = (p) => p;
|
|
33
|
+
this.tickInterval = 10;
|
|
34
|
+
this.lerp = (duration, ease, desiredPosition, desiredRotation, desiredScale, onCompletedCallback) => {
|
|
35
|
+
this.cancelLerp();
|
|
36
|
+
this.chrono = 0;
|
|
37
|
+
this.lerpDuration = duration;
|
|
38
|
+
this.lerpEase = ease;
|
|
39
|
+
if (duration <= 0) {
|
|
40
|
+
this.localMatrix = ValueObjects_1.Matrix.Compose(desiredScale !== null && desiredScale !== void 0 ? desiredScale : this.localScale, desiredRotation !== null && desiredRotation !== void 0 ? desiredRotation : this.localRotation, desiredPosition !== null && desiredPosition !== void 0 ? desiredPosition : this.localPosition);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (desiredPosition) {
|
|
44
|
+
this.lerpPos = [this.localPosition, desiredPosition];
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.lerpPos = undefined;
|
|
48
|
+
}
|
|
49
|
+
if (desiredRotation) {
|
|
50
|
+
this.lerpQuat = [this.localRotation, desiredRotation];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this.lerpQuat = undefined;
|
|
54
|
+
}
|
|
55
|
+
if (desiredScale) {
|
|
56
|
+
this.lerpScale = [this.localScale, desiredScale];
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.lerpScale = undefined;
|
|
60
|
+
}
|
|
61
|
+
this.onLerpCompletedCallback = onCompletedCallback;
|
|
62
|
+
this.interval = setInterval(() => {
|
|
63
|
+
this.tickLerp();
|
|
64
|
+
}, this.tickInterval);
|
|
65
|
+
};
|
|
66
|
+
this.tickLerp = () => {
|
|
67
|
+
this.chrono = this.chrono + this.tickInterval;
|
|
68
|
+
let nomralizedTime = this.chrono / this.lerpDuration;
|
|
69
|
+
if (nomralizedTime > 1) {
|
|
70
|
+
nomralizedTime = 1;
|
|
71
|
+
}
|
|
72
|
+
const percent = this.lerpEase(nomralizedTime);
|
|
73
|
+
let pos = this.localPosition;
|
|
74
|
+
if (this.lerpPos) {
|
|
75
|
+
pos = ValueObjects_1.Vector3.Lerp(this.lerpPos[0], this.lerpPos[1], percent);
|
|
76
|
+
}
|
|
77
|
+
let rotation = this.localRotation;
|
|
78
|
+
if (this.lerpQuat) {
|
|
79
|
+
rotation = ValueObjects_1.Quaternion.Slerp(this.lerpQuat[0], this.lerpQuat[1], percent);
|
|
80
|
+
}
|
|
81
|
+
let scale = this.localScale;
|
|
82
|
+
if (this.lerpScale) {
|
|
83
|
+
scale = ValueObjects_1.Vector3.Lerp(this.lerpScale[0], this.lerpScale[1], percent);
|
|
84
|
+
}
|
|
85
|
+
this._transformationMatrix = ValueObjects_1.Matrix.Compose(scale, rotation, pos);
|
|
86
|
+
this.observers.notify();
|
|
87
|
+
if (nomralizedTime >= 1 && this.interval) {
|
|
88
|
+
if (this.onLerpCompletedCallback) {
|
|
89
|
+
this.onLerpCompletedCallback();
|
|
90
|
+
}
|
|
91
|
+
clearInterval(this.interval);
|
|
92
|
+
this.interval = undefined;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
this.cancelLerp = () => {
|
|
96
|
+
if (this.interval) {
|
|
97
|
+
clearInterval(this.interval);
|
|
98
|
+
this.interval = undefined;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
this.addObserver = (observer) => {
|
|
102
|
+
this.observers.add(observer);
|
|
103
|
+
};
|
|
104
|
+
this.removeObserver = (observer) => {
|
|
105
|
+
this.observers.remove(observer);
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
get localMatrix() {
|
|
109
|
+
return this._transformationMatrix;
|
|
110
|
+
}
|
|
111
|
+
set localMatrix(val) {
|
|
112
|
+
if (ValueObjects_1.Matrix.Close(this._transformationMatrix, val))
|
|
113
|
+
return;
|
|
114
|
+
this.cancelLerp();
|
|
115
|
+
this._transformationMatrix = val;
|
|
116
|
+
this.observers.notify();
|
|
117
|
+
}
|
|
118
|
+
get worldMatrix() {
|
|
119
|
+
if (!this._parent) {
|
|
120
|
+
return this._transformationMatrix;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return ValueObjects_1.Matrix.Multiply(this._parent.worldMatrix, this._transformationMatrix);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
get localPosition() {
|
|
127
|
+
return this._transformationMatrix.translation;
|
|
128
|
+
}
|
|
129
|
+
set localPosition(val) {
|
|
130
|
+
const currentPos = this._transformationMatrix.translation;
|
|
131
|
+
if (ValueObjects_1.Vector3.Close(val, currentPos, 0.00001))
|
|
132
|
+
return;
|
|
133
|
+
this.cancelLerp();
|
|
134
|
+
this._transformationMatrix = ValueObjects_1.Matrix.SetMatrixTranslation(this._transformationMatrix, val);
|
|
135
|
+
this.observers.notify();
|
|
136
|
+
}
|
|
137
|
+
get worldPosition() {
|
|
138
|
+
return this.worldMatrix.translation;
|
|
139
|
+
}
|
|
140
|
+
set worldPosition(val) {
|
|
141
|
+
if (!this._parent) {
|
|
142
|
+
this.localPosition = val;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
const local = this._parent.worldPointToLocal(val);
|
|
146
|
+
this.localPosition = local;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
get localRotation() {
|
|
150
|
+
return this._transformationMatrix.rotation;
|
|
151
|
+
}
|
|
152
|
+
set localRotation(val) {
|
|
153
|
+
const currentRot = this._transformationMatrix.rotation;
|
|
154
|
+
if (ValueObjects_1.Quaternion.Close(val, currentRot))
|
|
155
|
+
return;
|
|
156
|
+
this.cancelLerp();
|
|
157
|
+
this._transformationMatrix = ValueObjects_1.Matrix.SetMatrixRotation(this._transformationMatrix, val);
|
|
158
|
+
this.observers.notify();
|
|
159
|
+
}
|
|
160
|
+
get worldRotation() {
|
|
161
|
+
return this.worldMatrix.rotation;
|
|
162
|
+
}
|
|
163
|
+
set worldRotation(val) {
|
|
164
|
+
if (!this._parent) {
|
|
165
|
+
this.localRotation = val;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const parentRotation = this._parent.worldRotation;
|
|
169
|
+
const parentRotationInverse = ValueObjects_1.Quaternion.Inverse(parentRotation);
|
|
170
|
+
this.localRotation = ValueObjects_1.Quaternion.Multiply(parentRotationInverse, val);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
get localScale() {
|
|
174
|
+
return this._transformationMatrix.scale;
|
|
175
|
+
}
|
|
176
|
+
set localScale(val) {
|
|
177
|
+
const currentScale = this._transformationMatrix.scale;
|
|
178
|
+
if (ValueObjects_1.Vector3.Close(val, currentScale, 0.00001))
|
|
179
|
+
return;
|
|
180
|
+
this.cancelLerp();
|
|
181
|
+
this._transformationMatrix = ValueObjects_1.Matrix.SetMatrixScale(this._transformationMatrix, val);
|
|
182
|
+
this.observers.notify();
|
|
183
|
+
}
|
|
184
|
+
get worldScale() {
|
|
185
|
+
return this.worldMatrix.scale;
|
|
186
|
+
}
|
|
187
|
+
set worldScale(val) {
|
|
188
|
+
if (!this._parent) {
|
|
189
|
+
this.localScale = val;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const parentScale = this._parent.worldScale;
|
|
193
|
+
const x = val.x / parentScale.x;
|
|
194
|
+
const y = val.y / parentScale.y;
|
|
195
|
+
const z = val.z / parentScale.z;
|
|
196
|
+
this.localScale = new ValueObjects_1.Vector3(x, y, z);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
get parent() {
|
|
200
|
+
return this._parent;
|
|
201
|
+
}
|
|
202
|
+
set parent(val) {
|
|
203
|
+
if (this._parent === val)
|
|
204
|
+
return;
|
|
205
|
+
const wMatrix = this.worldMatrix;
|
|
206
|
+
this._parent = val;
|
|
207
|
+
if (this._parent) {
|
|
208
|
+
const parentMatrix = this._parent.worldMatrix;
|
|
209
|
+
const parentMatrixInverse = ValueObjects_1.Matrix.Invert(parentMatrix);
|
|
210
|
+
this.localMatrix = ValueObjects_1.Matrix.Multiply(parentMatrixInverse, wMatrix);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
this.localMatrix = wMatrix;
|
|
214
|
+
}
|
|
215
|
+
this.observers.notify();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ParametricLine, Vector2 } from "../ValueObjects";
|
|
2
|
+
import { TransformNode } from "./TransformNode";
|
|
3
|
+
export declare type OnWorkPlaneChange = () => void;
|
|
4
|
+
export declare enum WorkPlaneUnits {
|
|
5
|
+
INCHES = 0,
|
|
6
|
+
METERS = 1,
|
|
7
|
+
FEET = 2
|
|
8
|
+
}
|
|
9
|
+
export declare enum WorkplaneShape {
|
|
10
|
+
RECTANGE = 0,
|
|
11
|
+
CIRCLE = 1,
|
|
12
|
+
UNKNOWN = 2
|
|
13
|
+
}
|
|
14
|
+
export interface WorkPlane {
|
|
15
|
+
transform: TransformNode;
|
|
16
|
+
id: string;
|
|
17
|
+
units: WorkPlaneUnits;
|
|
18
|
+
/**
|
|
19
|
+
* The conversion rate from world units (meters) to workspace units
|
|
20
|
+
*/
|
|
21
|
+
conversionFactor: number;
|
|
22
|
+
workplaneShape: WorkplaneShape;
|
|
23
|
+
showWorkPlane: boolean;
|
|
24
|
+
workPlaneRadius?: number;
|
|
25
|
+
workPlaneSize?: Vector2;
|
|
26
|
+
/**
|
|
27
|
+
* Sets the radius of the work plane. Call this if your workplane is a circle and it will limits the picks accordingly
|
|
28
|
+
* Note this will not notify observers of a change so this should be set
|
|
29
|
+
* when the app starts.
|
|
30
|
+
* @param radius The radius of the work plane in work plane units
|
|
31
|
+
*/
|
|
32
|
+
setWorkplaneSize: (size: Vector2) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Sets the radius of the work plane. Call this if your workplane is a circle and it will limits the picks accordingly
|
|
35
|
+
* Note this will not notify observers of a change so this should be set
|
|
36
|
+
* when the app starts.
|
|
37
|
+
* @param radius The radius of the work plane in work plane units
|
|
38
|
+
*/
|
|
39
|
+
setWorkplaneRadius: (radius: number) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Tries to intersect a world ray with the work plane. If the work plane size or radius has been set
|
|
42
|
+
* it will limit the intersection appropriately, otherwise it will use an infinate plane.
|
|
43
|
+
* @param ray A ray in world coordinates
|
|
44
|
+
* @param unconstrained Optional. If set to true it will not limit the pick to the workplane size or radius. Instead it will pick on an infinate plane in the X-Z plane of the work plane. Defaults to false.
|
|
45
|
+
* @returns Where that ray intersects the work plane in work plane units. If the ray does not intersect, it returns undefined
|
|
46
|
+
*/
|
|
47
|
+
pickOnWorkplane: (ray: ParametricLine, unconstrained?: boolean) => Vector2 | undefined;
|
|
48
|
+
}
|
|
49
|
+
export declare function makeWorkPlane(): WorkPlane;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeWorkPlane = exports.WorkplaneShape = exports.WorkPlaneUnits = void 0;
|
|
4
|
+
const ValueObjects_1 = require("../ValueObjects");
|
|
5
|
+
const TransformNode_1 = require("./TransformNode");
|
|
6
|
+
var WorkPlaneUnits;
|
|
7
|
+
(function (WorkPlaneUnits) {
|
|
8
|
+
WorkPlaneUnits[WorkPlaneUnits["INCHES"] = 0] = "INCHES";
|
|
9
|
+
WorkPlaneUnits[WorkPlaneUnits["METERS"] = 1] = "METERS";
|
|
10
|
+
WorkPlaneUnits[WorkPlaneUnits["FEET"] = 2] = "FEET";
|
|
11
|
+
})(WorkPlaneUnits = exports.WorkPlaneUnits || (exports.WorkPlaneUnits = {}));
|
|
12
|
+
var WorkplaneShape;
|
|
13
|
+
(function (WorkplaneShape) {
|
|
14
|
+
WorkplaneShape[WorkplaneShape["RECTANGE"] = 0] = "RECTANGE";
|
|
15
|
+
WorkplaneShape[WorkplaneShape["CIRCLE"] = 1] = "CIRCLE";
|
|
16
|
+
WorkplaneShape[WorkplaneShape["UNKNOWN"] = 2] = "UNKNOWN";
|
|
17
|
+
})(WorkplaneShape = exports.WorkplaneShape || (exports.WorkplaneShape = {}));
|
|
18
|
+
function makeWorkPlane() {
|
|
19
|
+
return new WorkPlaneImp();
|
|
20
|
+
}
|
|
21
|
+
exports.makeWorkPlane = makeWorkPlane;
|
|
22
|
+
class WorkPlaneImp {
|
|
23
|
+
constructor() {
|
|
24
|
+
this._workPlaneHalfSize = ValueObjects_1.Vector2.One();
|
|
25
|
+
this.showWorkPlane = true;
|
|
26
|
+
this.transform = TransformNode_1.makeTransformNode();
|
|
27
|
+
this.id = "workplane";
|
|
28
|
+
this._units = WorkPlaneUnits.METERS;
|
|
29
|
+
this._workplaneShape = WorkplaneShape.UNKNOWN;
|
|
30
|
+
this.setWorkplaneSize = (size) => {
|
|
31
|
+
this._workPlaneSize = size;
|
|
32
|
+
this._workPlaneHalfSize = new ValueObjects_1.Vector2(0.5 * size.x, 0.5 * size.y);
|
|
33
|
+
this._workplaneShape = WorkplaneShape.RECTANGE;
|
|
34
|
+
};
|
|
35
|
+
this.setWorkplaneRadius = (radius) => {
|
|
36
|
+
this._workPlaneRadius = radius;
|
|
37
|
+
this._workplaneShape = WorkplaneShape.CIRCLE;
|
|
38
|
+
};
|
|
39
|
+
this.pickOnWorkplane = (ray, unconstrained = false) => {
|
|
40
|
+
const worldPos = this.transform.worldPosition;
|
|
41
|
+
const worldUp = this.transform.localDirectionToWorld(ValueObjects_1.Vector3.Up());
|
|
42
|
+
const pickPlane = ValueObjects_1.ParametricPlane.FromPointNormal(worldPos, worldUp);
|
|
43
|
+
const worldPick = pickPlane.intersectLine(ray);
|
|
44
|
+
if (worldPick === undefined) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const localPick = this.transform.worldPointToLocal(worldPick);
|
|
48
|
+
const workPlanePick = new ValueObjects_1.Vector2(localPick.x, localPick.z);
|
|
49
|
+
if (unconstrained) {
|
|
50
|
+
return workPlanePick;
|
|
51
|
+
}
|
|
52
|
+
if (this._workplaneShape === WorkplaneShape.CIRCLE) {
|
|
53
|
+
return this.constrainToRadius(workPlanePick);
|
|
54
|
+
}
|
|
55
|
+
else if (this._workplaneShape === WorkplaneShape.RECTANGE) {
|
|
56
|
+
return this.constrainToSize(workPlanePick);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return workPlanePick;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
get workPlaneRadius() {
|
|
64
|
+
return this._workPlaneRadius;
|
|
65
|
+
}
|
|
66
|
+
get workPlaneSize() {
|
|
67
|
+
return this._workPlaneSize;
|
|
68
|
+
}
|
|
69
|
+
get units() {
|
|
70
|
+
return this._units;
|
|
71
|
+
}
|
|
72
|
+
set units(val) {
|
|
73
|
+
if (val === this._units)
|
|
74
|
+
return;
|
|
75
|
+
this._units = val;
|
|
76
|
+
const scale = 1 / this.conversionFactor;
|
|
77
|
+
this.transform.localScale = new ValueObjects_1.Vector3(scale, scale, scale);
|
|
78
|
+
}
|
|
79
|
+
get workplaneShape() {
|
|
80
|
+
return this._workplaneShape;
|
|
81
|
+
}
|
|
82
|
+
get conversionFactor() {
|
|
83
|
+
switch (this.units) {
|
|
84
|
+
case WorkPlaneUnits.FEET:
|
|
85
|
+
return 3.28084;
|
|
86
|
+
case WorkPlaneUnits.INCHES:
|
|
87
|
+
return 39.3701;
|
|
88
|
+
case WorkPlaneUnits.METERS:
|
|
89
|
+
return 1;
|
|
90
|
+
default:
|
|
91
|
+
console.warn("[WorkPlane] Unknown units " + this.units);
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
constrainToRadius(workPlanePick) {
|
|
96
|
+
if (!this.workPlaneRadius)
|
|
97
|
+
return workPlanePick;
|
|
98
|
+
const pickRadius = workPlanePick.magnitued;
|
|
99
|
+
if (pickRadius <= this.workPlaneRadius) {
|
|
100
|
+
return workPlanePick;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
constrainToSize(workPlanePick) {
|
|
107
|
+
if (!this._workPlaneHalfSize)
|
|
108
|
+
return workPlanePick;
|
|
109
|
+
const x = workPlanePick.x;
|
|
110
|
+
const maxX = this._workPlaneHalfSize.x;
|
|
111
|
+
const minX = -this._workPlaneHalfSize.x;
|
|
112
|
+
const y = workPlanePick.y;
|
|
113
|
+
const maxY = this._workPlaneHalfSize.y;
|
|
114
|
+
const minY = -this._workPlaneHalfSize.y;
|
|
115
|
+
if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
|
|
116
|
+
return workPlanePick;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/lib/Entities/index.d.ts
CHANGED
|
@@ -10,8 +10,11 @@ export * from "./MemoizedVector3";
|
|
|
10
10
|
export * from "./ObserverList";
|
|
11
11
|
export * from "./FocusCamera";
|
|
12
12
|
export * from "./StateMachine";
|
|
13
|
+
export * from "./TransformNode";
|
|
13
14
|
export * from "./UndoRedo";
|
|
14
15
|
export * from "./MouseInput";
|
|
15
16
|
export * from "./TouchInput";
|
|
16
17
|
export * from "./QuestionChallengeAnswer";
|
|
17
18
|
export * from "./QuestionChallenge";
|
|
19
|
+
export * from "./SceneRoot";
|
|
20
|
+
export * from "./WorkPlane";
|