architwin 1.12.5 → 1.13.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/CORE_FEATURES.md +35 -0
- package/lib/architwin.d.ts +96 -5
- package/lib/architwin.js +1 -1
- package/lib/atwinui/components/toolbar/collapse.d.ts +18 -0
- package/lib/atwinui/components/toolbar/collapse.js +62 -0
- package/lib/atwinui/components/toolbar/i18n.js +52 -2
- package/lib/atwinui/components/toolbar/index.js +11 -1
- package/lib/atwinui/components/toolbar/menuBar.d.ts +1 -0
- package/lib/atwinui/components/toolbar/menuBar.js +11 -0
- package/lib/atwinui/components/toolbar/pipeFormPane.d.ts +31 -0
- package/lib/atwinui/components/toolbar/pipeFormPane.js +545 -0
- package/lib/atwinui/components/toolbar/pipeListPane.d.ts +19 -0
- package/lib/atwinui/components/toolbar/pipeListPane.js +388 -0
- package/lib/atwinui/components/toolbar/spaceUserListPane.d.ts +3 -0
- package/lib/atwinui/components/toolbar/spaceUserListPane.js +95 -0
- package/lib/atwinui/components/toolbar/tagIotForm.d.ts +20 -0
- package/lib/atwinui/components/toolbar/tagIotForm.js +391 -0
- package/lib/atwinui/components/toolbar/tagIotFormPane.d.ts +62 -0
- package/lib/atwinui/components/toolbar/tagIotFormPane.js +606 -0
- package/lib/atwinui/components/toolbar/usersPane.d.ts +14 -0
- package/lib/atwinui/components/toolbar/usersPane.js +273 -0
- package/lib/atwinui/components/toolbar/viewingRemoteSpace.d.ts +7 -0
- package/lib/atwinui/components/toolbar/viewingRemoteSpace.js +77 -0
- package/lib/atwinui/events.d.ts +4 -1
- package/lib/atwinui/events.js +76 -13
- package/lib/atwinui/helpers.d.ts +15 -0
- package/lib/atwinui/helpers.js +49 -0
- package/lib/atwinui/index.js +2 -0
- package/lib/loaders/curosrMarkerLoader.d.ts +25 -0
- package/lib/loaders/curosrMarkerLoader.js +86 -0
- package/lib/loaders/index.d.ts +2 -1
- package/lib/loaders/index.js +2 -1
- package/lib/loaders/pathLoader.d.ts +99 -0
- package/lib/loaders/pathLoader.js +451 -0
- package/lib/types.d.ts +79 -1
- package/lib/types.js +34 -0
- package/package.json +1 -1
- package/static/atwinui.css +263 -0
- package/static/utility.css +81 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { _mpConfig } from "../architwin";
|
|
2
|
+
// Default asset path (overridden if bundlePath is present in config)
|
|
3
|
+
let _staticAssetPath = '../';
|
|
4
|
+
class CursorMarkerLoader {
|
|
5
|
+
constructor(mpConfig) {
|
|
6
|
+
// === Inputs ===
|
|
7
|
+
this.inputs = {
|
|
8
|
+
pointerIntersection: null,
|
|
9
|
+
markerTexture: null,
|
|
10
|
+
visible: true,
|
|
11
|
+
offset: 0.05,
|
|
12
|
+
scale: 1 // Marker scale multiplier
|
|
13
|
+
};
|
|
14
|
+
// === Initialization ===
|
|
15
|
+
this.onInit = () => {
|
|
16
|
+
console.log('🛠️ CursorMarkerLoader on init', this.inputs.pointerIntersection);
|
|
17
|
+
const THREE = this.context.three;
|
|
18
|
+
if (!this.inputs.pointerIntersection)
|
|
19
|
+
return;
|
|
20
|
+
// Extract position and surface normal from intersection data
|
|
21
|
+
const { position: coord, normal: _normal } = this.inputs.pointerIntersection;
|
|
22
|
+
// Normalize the surface normal
|
|
23
|
+
const normal = new THREE.Vector3(_normal.x, _normal.y, _normal.z).normalize();
|
|
24
|
+
// === Generate rotation quaternion to align marker with surface ===
|
|
25
|
+
// Build a tangent-bitangent-normal (TBN) basis from surface normal
|
|
26
|
+
const up = new THREE.Vector3(0, 0, 1);
|
|
27
|
+
const tangent = new THREE.Vector3().crossVectors(new THREE.Vector3(1, 0, 0), normal).normalize();
|
|
28
|
+
const bitangent = new THREE.Vector3().crossVectors(normal, tangent).normalize();
|
|
29
|
+
const matrix = new THREE.Matrix4().makeBasis(tangent, bitangent, normal);
|
|
30
|
+
// Create quaternion from basis matrix and align Z-up to normal
|
|
31
|
+
const quaternion = new THREE.Quaternion().setFromRotationMatrix(matrix);
|
|
32
|
+
quaternion.setFromUnitVectors(up, normal);
|
|
33
|
+
// Convert to Euler angles for use with Three.js transforms
|
|
34
|
+
const euler = new THREE.Euler().setFromQuaternion(quaternion);
|
|
35
|
+
// Apply offset to position to move slightly off the surface
|
|
36
|
+
const adjustedPosition = new THREE.Vector3(coord.x + normal.x * this.inputs.offset, coord.y + normal.y * this.inputs.offset, coord.z + normal.z * this.inputs.offset);
|
|
37
|
+
// Marker texture fallback
|
|
38
|
+
const markerUrl = this.inputs.markerTexture || `${_staticAssetPath}static/objective.png`;
|
|
39
|
+
// === Load texture and build the marker plane ===
|
|
40
|
+
const loader = new THREE.TextureLoader();
|
|
41
|
+
loader.load(markerUrl, (texture) => {
|
|
42
|
+
this.texture = texture;
|
|
43
|
+
// Define geometry and material for the flat marker plane
|
|
44
|
+
this.geometry = new THREE.PlaneGeometry(0.1, 0.1);
|
|
45
|
+
this.material = new THREE.MeshBasicMaterial({
|
|
46
|
+
map: texture,
|
|
47
|
+
transparent: false,
|
|
48
|
+
opacity: 1,
|
|
49
|
+
side: THREE.DoubleSide,
|
|
50
|
+
});
|
|
51
|
+
// Create the mesh
|
|
52
|
+
this.mesh = new THREE.Mesh(this.geometry, this.material);
|
|
53
|
+
this.mesh.position.copy(adjustedPosition);
|
|
54
|
+
this.mesh.rotation.set(euler.x, euler.y, euler.z);
|
|
55
|
+
this.mesh.name = 'cursorMarker';
|
|
56
|
+
this.mesh.visible = this.inputs.visible;
|
|
57
|
+
// Register output so it can be used as a collider/interactable object
|
|
58
|
+
this.outputs.objectRoot = this.mesh;
|
|
59
|
+
this.outputs.collider = this.mesh;
|
|
60
|
+
console.log('🛠️ CursorMarkerLoader on loader.load', texture);
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
// === Triggered when inputs change ===
|
|
64
|
+
this.onInputsUpdated = () => {
|
|
65
|
+
console.log('🛠️ CursorMarkerLoader inputupdated');
|
|
66
|
+
this.onInit();
|
|
67
|
+
};
|
|
68
|
+
// === Cleanup for memory management ===
|
|
69
|
+
this.onDestroy = () => {
|
|
70
|
+
var _a, _b, _c;
|
|
71
|
+
console.log('🛠️ CursorMarkerLoader destroy');
|
|
72
|
+
(_a = this.geometry) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
73
|
+
(_b = this.material) === null || _b === void 0 ? void 0 : _b.dispose();
|
|
74
|
+
(_c = this.texture) === null || _c === void 0 ? void 0 : _c.dispose();
|
|
75
|
+
};
|
|
76
|
+
console.log('🛠️ CursorMarkerLoader constructor called');
|
|
77
|
+
this.outputs = {};
|
|
78
|
+
// Override static asset path if deployed via CDN
|
|
79
|
+
if ('bundlePath' in mpConfig) {
|
|
80
|
+
_staticAssetPath = 'https://cdn.jsdelivr.net/npm/architwin@latest/';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// === Factory and Component Type ===
|
|
85
|
+
export const cursorMarkerType = 'mp.cursorMarker';
|
|
86
|
+
export const cursorMarkerFactory = () => new CursorMarkerLoader(_mpConfig);
|
package/lib/loaders/index.d.ts
CHANGED
|
@@ -9,4 +9,5 @@ import { sweepPuckType, puckBackgroundFactory } from "./sweepPuckLoader";
|
|
|
9
9
|
import { viewpointType, viewpointFactory } from "./viewpointLoader";
|
|
10
10
|
import { tubeLineType, tubeLineFactory, verticeType, verticeFactory, bufferGeometryType, bufferGeometry } from "./polydrawerLoader";
|
|
11
11
|
import { fbxType, fbxFactory } from "./fbxLoader";
|
|
12
|
-
|
|
12
|
+
import { pathPointType, pathPointFactory, pathLineType, pathLineFactory } from "./pathLoader";
|
|
13
|
+
export { planeType, planeFactory, planeTypeImage, planeTypeVideo, planeTypePdf, setHudState, planeImageFactory, planeVideoFactory, planePdfFactory, gltfType, gltfFactory, boxType, boxFactory, textType, textFactory, css3DType, css3DFactory, hudType, hudFactory, sweepPuckType, puckBackgroundFactory, viewpointType, viewpointFactory, tubeLineType, tubeLineFactory, verticeType, verticeFactory, bufferGeometryType, bufferGeometry, fbxType, fbxFactory, pathPointType, pathPointFactory, pathLineType, pathLineFactory };
|
package/lib/loaders/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { sweepPuckType, puckBackgroundFactory } from "./sweepPuckLoader";
|
|
|
9
9
|
import { viewpointType, viewpointFactory } from "./viewpointLoader";
|
|
10
10
|
import { tubeLineType, tubeLineFactory, verticeType, verticeFactory, bufferGeometryType, bufferGeometry } from "./polydrawerLoader";
|
|
11
11
|
import { fbxType, fbxFactory } from "./fbxLoader";
|
|
12
|
+
import { pathPointType, pathPointFactory, pathLineType, pathLineFactory } from "./pathLoader";
|
|
12
13
|
export {
|
|
13
14
|
// planeType,planeFactory,
|
|
14
|
-
planeType, planeFactory, planeTypeImage, planeTypeVideo, planeTypePdf, setHudState, planeImageFactory, planeVideoFactory, planePdfFactory, gltfType, gltfFactory, boxType, boxFactory, textType, textFactory, css3DType, css3DFactory, hudType, hudFactory, sweepPuckType, puckBackgroundFactory, viewpointType, viewpointFactory, tubeLineType, tubeLineFactory, verticeType, verticeFactory, bufferGeometryType, bufferGeometry, fbxType, fbxFactory };
|
|
15
|
+
planeType, planeFactory, planeTypeImage, planeTypeVideo, planeTypePdf, setHudState, planeImageFactory, planeVideoFactory, planePdfFactory, gltfType, gltfFactory, boxType, boxFactory, textType, textFactory, css3DType, css3DFactory, hudType, hudFactory, sweepPuckType, puckBackgroundFactory, viewpointType, viewpointFactory, tubeLineType, tubeLineFactory, verticeType, verticeFactory, bufferGeometryType, bufferGeometry, fbxType, fbxFactory, pathPointType, pathPointFactory, pathLineType, pathLineFactory };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { MpSdk } from "../../bundle/sdk";
|
|
2
|
+
import { Pane } from 'tweakpane';
|
|
3
|
+
export declare class PathLine {
|
|
4
|
+
mpSdk: MpSdk;
|
|
5
|
+
mesh: THREE.Mesh;
|
|
6
|
+
material: THREE.Material;
|
|
7
|
+
geometry: THREE.BufferGeometry;
|
|
8
|
+
texture: THREE.CanvasTexture;
|
|
9
|
+
tubeGeometry: THREE.TubeGeometry;
|
|
10
|
+
time: number;
|
|
11
|
+
closed: boolean;
|
|
12
|
+
panel: Pane;
|
|
13
|
+
billboard: string;
|
|
14
|
+
hovered: boolean;
|
|
15
|
+
length: number;
|
|
16
|
+
groupedMesh: THREE.Group;
|
|
17
|
+
constructor(mpSdk: MpSdk);
|
|
18
|
+
inputs: {
|
|
19
|
+
name: string;
|
|
20
|
+
label: string;
|
|
21
|
+
description: string;
|
|
22
|
+
node: any;
|
|
23
|
+
tubes: any;
|
|
24
|
+
path: any;
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
active: boolean;
|
|
27
|
+
editMode: boolean;
|
|
28
|
+
direction: number;
|
|
29
|
+
curveType: string;
|
|
30
|
+
opacity: number;
|
|
31
|
+
tubularSegments: number;
|
|
32
|
+
radialSegments: number;
|
|
33
|
+
fillColor: string;
|
|
34
|
+
textColor: string;
|
|
35
|
+
text: string;
|
|
36
|
+
font: string;
|
|
37
|
+
radius: number;
|
|
38
|
+
scrollSpeed: number;
|
|
39
|
+
collider: boolean;
|
|
40
|
+
visible: boolean;
|
|
41
|
+
pathOptions: any;
|
|
42
|
+
};
|
|
43
|
+
outputs: Record<string, unknown> & MpSdk.Scene.PredefinedOutputs;
|
|
44
|
+
context: MpSdk.Scene.IComponentContext;
|
|
45
|
+
emits: {
|
|
46
|
+
active: boolean;
|
|
47
|
+
destroyed: boolean;
|
|
48
|
+
};
|
|
49
|
+
events: {
|
|
50
|
+
'INTERACTION.CLICK': boolean;
|
|
51
|
+
'INTERACTION.HOVER': boolean;
|
|
52
|
+
};
|
|
53
|
+
onInit: () => void;
|
|
54
|
+
onInputsUpdated: (prevInputs: any) => void;
|
|
55
|
+
renderPathLine: () => void;
|
|
56
|
+
setBillboard: (value: any) => void;
|
|
57
|
+
onEvent(eventType: any, data: any): void;
|
|
58
|
+
onTick(tickDelta: any): void;
|
|
59
|
+
renderGUI: () => void;
|
|
60
|
+
onDestroy(): void;
|
|
61
|
+
}
|
|
62
|
+
export declare const pathLineType = "pathLine";
|
|
63
|
+
export declare const pathLineFactory: (mpSdk: MpSdk) => () => PathLine;
|
|
64
|
+
export declare class PathPoint {
|
|
65
|
+
mpSdk: MpSdk;
|
|
66
|
+
mesh: THREE.Mesh;
|
|
67
|
+
material: THREE.Material;
|
|
68
|
+
geometry: THREE.BufferGeometry;
|
|
69
|
+
texture: THREE.CanvasTexture;
|
|
70
|
+
pointerSub: MpSdk.ISubscription;
|
|
71
|
+
pointerIntersection: MpSdk.Pointer.Intersection;
|
|
72
|
+
constructor(mpSdk: MpSdk);
|
|
73
|
+
inputs: {
|
|
74
|
+
index: any;
|
|
75
|
+
radius: number;
|
|
76
|
+
position: any;
|
|
77
|
+
fillColor: string;
|
|
78
|
+
hoverColor: string;
|
|
79
|
+
ringVisibility: boolean;
|
|
80
|
+
};
|
|
81
|
+
outputs: Record<string, unknown> & MpSdk.Scene.PredefinedOutputs;
|
|
82
|
+
context: MpSdk.Scene.IComponentContext;
|
|
83
|
+
emits: {
|
|
84
|
+
active: boolean;
|
|
85
|
+
changed: boolean;
|
|
86
|
+
};
|
|
87
|
+
events: {
|
|
88
|
+
'INTERACTION.DRAG': boolean;
|
|
89
|
+
'INTERACTION.DRAG_BEGIN': boolean;
|
|
90
|
+
'INTERACTION.DRAG_END': boolean;
|
|
91
|
+
'INTERACTION.HOVER': boolean;
|
|
92
|
+
};
|
|
93
|
+
onInputsUpdated: (prevInputs: any) => void;
|
|
94
|
+
onEvent(eventType: any, data: any): void;
|
|
95
|
+
onInit: () => void;
|
|
96
|
+
renderVertice: (hovered?: boolean) => void;
|
|
97
|
+
}
|
|
98
|
+
export declare const pathPointType = "pathPoint";
|
|
99
|
+
export declare const pathPointFactory: (mpSdk: any) => () => PathPoint;
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
import { Pane } from 'tweakpane';
|
|
2
|
+
import { dispatchSpaceEvent } from "../architwin";
|
|
3
|
+
import { SPACE_EVENTS } from "../types";
|
|
4
|
+
export class PathLine {
|
|
5
|
+
constructor(mpSdk) {
|
|
6
|
+
this.time = 0;
|
|
7
|
+
this.closed = false;
|
|
8
|
+
this.billboard = undefined;
|
|
9
|
+
this.hovered = false;
|
|
10
|
+
this.length = 0;
|
|
11
|
+
this.inputs = {
|
|
12
|
+
name: '',
|
|
13
|
+
label: 'Path Line',
|
|
14
|
+
description: '',
|
|
15
|
+
node: null,
|
|
16
|
+
tubes: null,
|
|
17
|
+
path: null,
|
|
18
|
+
enabled: true,
|
|
19
|
+
active: false,
|
|
20
|
+
editMode: false,
|
|
21
|
+
direction: -1,
|
|
22
|
+
curveType: 'catmullrom',
|
|
23
|
+
opacity: 0.3,
|
|
24
|
+
tubularSegments: 100,
|
|
25
|
+
radialSegments: 20,
|
|
26
|
+
fillColor: 'none',
|
|
27
|
+
textColor: 'rgb(255,255,255)',
|
|
28
|
+
text: '➡︎',
|
|
29
|
+
font: '48px sans-serif',
|
|
30
|
+
radius: 0.05,
|
|
31
|
+
scrollSpeed: 1.35,
|
|
32
|
+
collider: true,
|
|
33
|
+
visible: true,
|
|
34
|
+
pathOptions: null
|
|
35
|
+
};
|
|
36
|
+
//@ts-expect-error
|
|
37
|
+
this.outputs = {
|
|
38
|
+
length: 0,
|
|
39
|
+
gui: {},
|
|
40
|
+
};
|
|
41
|
+
this.emits = {
|
|
42
|
+
active: true,
|
|
43
|
+
destroyed: true,
|
|
44
|
+
};
|
|
45
|
+
this.events = {
|
|
46
|
+
'INTERACTION.CLICK': true,
|
|
47
|
+
'INTERACTION.HOVER': false,
|
|
48
|
+
};
|
|
49
|
+
this.onInit = () => {
|
|
50
|
+
const THREE = this.context.three;
|
|
51
|
+
this.groupedMesh = new THREE.Group();
|
|
52
|
+
if (this.inputs.active) {
|
|
53
|
+
//this.renderGUI();
|
|
54
|
+
}
|
|
55
|
+
if (this.inputs.path.length > 1) {
|
|
56
|
+
this.renderPathLine();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
this.onInputsUpdated = (prevInputs) => {
|
|
60
|
+
if (this.inputs !== prevInputs) {
|
|
61
|
+
const THREE = this.context.three;
|
|
62
|
+
this.groupedMesh = new THREE.Group();
|
|
63
|
+
if (!this.inputs.active && this.panel) {
|
|
64
|
+
this.panel.dispose();
|
|
65
|
+
//@ts-expect-error
|
|
66
|
+
this.panel = false;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (!this.panel || this.inputs.label !== prevInputs.label) {
|
|
70
|
+
//console.log('Rendering GUI...');
|
|
71
|
+
// this.renderGUI();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (this.inputs.pathOptions) {
|
|
75
|
+
const excludedKeys = ['id', 'pathOptions'];
|
|
76
|
+
for (let key in this.inputs) {
|
|
77
|
+
if (!excludedKeys.includes(key)) {
|
|
78
|
+
if (this.inputs.pathOptions[key]) {
|
|
79
|
+
this.inputs[key] = this.inputs.pathOptions[key];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (this.inputs.path.length > 1) {
|
|
85
|
+
this.renderPathLine();
|
|
86
|
+
console.log("paths ", this.inputs.path);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
this.renderPathLine = () => {
|
|
91
|
+
const THREE = this.context.three;
|
|
92
|
+
// Find Length
|
|
93
|
+
let sections = this.inputs.path.length - 1;
|
|
94
|
+
this.length = 0;
|
|
95
|
+
for (let i = 0; i < sections; i++) {
|
|
96
|
+
const start = new THREE.Vector3(this.inputs.path[i].x, this.inputs.path[i].y, this.inputs.path[i].z);
|
|
97
|
+
const end = new THREE.Vector3(this.inputs.path[i + 1].x, this.inputs.path[i + 1].y, this.inputs.path[i + 1].z);
|
|
98
|
+
this.length += start.distanceTo(end);
|
|
99
|
+
}
|
|
100
|
+
const ctx = document.createElement('canvas').getContext('2d');
|
|
101
|
+
if (!ctx) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
ctx.canvas.width = 64;
|
|
105
|
+
ctx.canvas.height = 64;
|
|
106
|
+
if (this.inputs.fillColor == 'none') {
|
|
107
|
+
ctx.clearRect(0, 0, 64, 64);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// background
|
|
111
|
+
let fillColorRGBA = this.inputs.fillColor.replace(/rgb/i, 'rgba');
|
|
112
|
+
fillColorRGBA = fillColorRGBA.replace(/\)/i, ',' + (this.hovered ? 0.9 : this.inputs.opacity) + ')');
|
|
113
|
+
ctx.fillStyle = fillColorRGBA;
|
|
114
|
+
ctx.fillRect(0, 0, 64, 64);
|
|
115
|
+
}
|
|
116
|
+
// render out text measurement in the rendered line
|
|
117
|
+
ctx.translate(32, 32);
|
|
118
|
+
ctx.fillStyle = this.inputs.textColor;
|
|
119
|
+
ctx.textAlign = 'center';
|
|
120
|
+
ctx.textBaseline = 'middle';
|
|
121
|
+
ctx.font = this.inputs.font;
|
|
122
|
+
ctx.fillText(this.inputs.text, 0, 0);
|
|
123
|
+
this.texture = new THREE.CanvasTexture(ctx.canvas);
|
|
124
|
+
this.texture.wrapS = THREE.RepeatWrapping;
|
|
125
|
+
this.texture.wrapT = THREE.RepeatWrapping;
|
|
126
|
+
this.texture.repeat.set(this.length, 3);
|
|
127
|
+
this.material = new THREE.MeshBasicMaterial({
|
|
128
|
+
map: this.texture,
|
|
129
|
+
side: THREE.DoubleSide,
|
|
130
|
+
depthWrite: false,
|
|
131
|
+
depthTest: true,
|
|
132
|
+
transparent: true,
|
|
133
|
+
//@ts-expect-error
|
|
134
|
+
flatShading: true,
|
|
135
|
+
emissive: 0x072534,
|
|
136
|
+
});
|
|
137
|
+
if (this.inputs.path !== null) {
|
|
138
|
+
this.tubeGeometry && this.tubeGeometry.dispose();
|
|
139
|
+
this.tubeGeometry = new THREE.TubeGeometry(new THREE.CatmullRomCurve3(this.inputs.path, false,
|
|
140
|
+
//@ts-expect-error
|
|
141
|
+
this.inputs.curveType, this.inputs.curveType == 'catmullrom' ? 0.25 : 0), this.inputs.tubularSegments, // tubularSegments
|
|
142
|
+
this.inputs.radius, this.inputs.radialSegments, // radialSegments
|
|
143
|
+
this.closed // closed
|
|
144
|
+
);
|
|
145
|
+
this.mesh = new THREE.Mesh(this.tubeGeometry, this.material);
|
|
146
|
+
}
|
|
147
|
+
this.mesh.name = this.inputs.name;
|
|
148
|
+
this.outputs.length = this.length;
|
|
149
|
+
this.groupedMesh.add(this.mesh);
|
|
150
|
+
this.mesh.visible = this.inputs.visible;
|
|
151
|
+
if (this.inputs.enabled) {
|
|
152
|
+
this.outputs.objectRoot = this.mesh;
|
|
153
|
+
this.outputs.collider = this.inputs.collider ? this.mesh : null;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
this.outputs.objectRoot = null;
|
|
157
|
+
this.outputs.collider = null;
|
|
158
|
+
}
|
|
159
|
+
if (this.panel) {
|
|
160
|
+
this.panel.refresh();
|
|
161
|
+
}
|
|
162
|
+
dispatchSpaceEvent(SPACE_EVENTS.PATH_UPDATED, {
|
|
163
|
+
path: this.inputs.path,
|
|
164
|
+
textColor: this.inputs.textColor
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
this.setBillboard = (value) => {
|
|
168
|
+
this.billboard = value;
|
|
169
|
+
};
|
|
170
|
+
//This is just a temp gui I need for debugging and experimentation purposes. Will be commented out once I am done
|
|
171
|
+
this.renderGUI = () => {
|
|
172
|
+
if (this.panel) {
|
|
173
|
+
this.panel.dispose();
|
|
174
|
+
}
|
|
175
|
+
this.panel = new Pane({
|
|
176
|
+
//width: 260,
|
|
177
|
+
title: 'Scrolling Tube Creator',
|
|
178
|
+
container: document.getElementById('objgui'),
|
|
179
|
+
});
|
|
180
|
+
const tab = this.panel.addTab({
|
|
181
|
+
pages: [{ title: 'Edit' }, { title: 'All Drawings' }],
|
|
182
|
+
});
|
|
183
|
+
const folder1 = tab.pages[0].addFolder({ title: 'Inputs' });
|
|
184
|
+
folder1.addBinding(this.inputs, 'name');
|
|
185
|
+
folder1.addBinding(this.inputs, 'label');
|
|
186
|
+
folder1.addBinding(this.inputs, 'description', {
|
|
187
|
+
readonly: false,
|
|
188
|
+
multiline: true,
|
|
189
|
+
rows: 5,
|
|
190
|
+
});
|
|
191
|
+
folder1.addBinding(this.inputs, 'text', {
|
|
192
|
+
options: { ' ': ' ', '➡︎': '➡︎', '✳': '✳', '☠': '☠' },
|
|
193
|
+
});
|
|
194
|
+
folder1.addBinding(this.inputs, 'textColor');
|
|
195
|
+
folder1.addBinding(this.inputs, 'fillColor');
|
|
196
|
+
folder1.addBinding(this.inputs, 'direction', {
|
|
197
|
+
options: { 'Left to Right': -1, 'Right to Left': 1 },
|
|
198
|
+
});
|
|
199
|
+
folder1.addBinding(this.outputs, 'length', {
|
|
200
|
+
readonly: true,
|
|
201
|
+
});
|
|
202
|
+
// If the node was passed as an input, we can run node.destroy();
|
|
203
|
+
if (this.inputs.node) {
|
|
204
|
+
const remove = folder1.addButton({ title: 'Remove', label: 'Remove' });
|
|
205
|
+
remove.on('click', () => {
|
|
206
|
+
//@ts-expect-error
|
|
207
|
+
this.notify('destroyed');
|
|
208
|
+
this.panel.dispose();
|
|
209
|
+
//@ts-expect-error
|
|
210
|
+
this.panel = false;
|
|
211
|
+
this.inputs.active = false;
|
|
212
|
+
this.inputs.node.stop();
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const folder2 = tab.pages[0].addFolder({
|
|
216
|
+
title: 'Advanced',
|
|
217
|
+
expanded: true,
|
|
218
|
+
});
|
|
219
|
+
folder2.addBinding(this.inputs, 'enabled');
|
|
220
|
+
folder2.addBinding(this.inputs, 'opacity', { min: 0, max: 1, step: 0.05 });
|
|
221
|
+
folder2.addBinding(this.inputs, 'radius', {
|
|
222
|
+
min: 0.01,
|
|
223
|
+
max: 1,
|
|
224
|
+
step: 0.01,
|
|
225
|
+
});
|
|
226
|
+
folder2.addBinding(this.inputs, 'scrollSpeed', {
|
|
227
|
+
min: 0,
|
|
228
|
+
max: 5,
|
|
229
|
+
step: 0.05,
|
|
230
|
+
});
|
|
231
|
+
folder2.addBinding(this.inputs, 'tubularSegments', {
|
|
232
|
+
min: 1,
|
|
233
|
+
max: 100,
|
|
234
|
+
step: 1,
|
|
235
|
+
});
|
|
236
|
+
folder2.addBinding(this.inputs, 'radialSegments', {
|
|
237
|
+
min: 1,
|
|
238
|
+
max: 20,
|
|
239
|
+
step: 1,
|
|
240
|
+
});
|
|
241
|
+
folder2.addBinding(this.inputs, 'collider');
|
|
242
|
+
if (this.inputs.tubes !== null) {
|
|
243
|
+
const nodeIterator = this.inputs.tubes.nodeIterator();
|
|
244
|
+
let nodes = nodeIterator.next();
|
|
245
|
+
while (!nodes.done) {
|
|
246
|
+
const componentIterator = nodes.value.componentIterator();
|
|
247
|
+
let component = componentIterator.next();
|
|
248
|
+
nodes = nodeIterator.next();
|
|
249
|
+
const button = tab.pages[1].addButton({
|
|
250
|
+
title: component.value.inputs.label,
|
|
251
|
+
label: '=',
|
|
252
|
+
});
|
|
253
|
+
button.on('click', (data) => {
|
|
254
|
+
// This needs to be reviewed
|
|
255
|
+
if (!component.value.inputs.active) {
|
|
256
|
+
//@ts-expect-error
|
|
257
|
+
this.notify('active', { component: component.value });
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
this.mpSdk = mpSdk;
|
|
264
|
+
}
|
|
265
|
+
onEvent(eventType, data) {
|
|
266
|
+
if (eventType === 'INTERACTION.CLICK') {
|
|
267
|
+
//@ts-expect-error
|
|
268
|
+
this.notify('active', { component: this });
|
|
269
|
+
// Show a Tag Billboard with the info of this tube
|
|
270
|
+
if (!this.billboard) {
|
|
271
|
+
// Allow access to these variables within then callbacks.
|
|
272
|
+
var mpSdk = this.mpSdk;
|
|
273
|
+
mpSdk.Tag.toggleNavControls(false);
|
|
274
|
+
mpSdk.Tag.add({
|
|
275
|
+
label: this.inputs.label,
|
|
276
|
+
description: this.inputs.description +
|
|
277
|
+
' - ' +
|
|
278
|
+
Math.round(this.length * 1000) / 1000 +
|
|
279
|
+
'm',
|
|
280
|
+
anchorPosition: {
|
|
281
|
+
x: data.point.x,
|
|
282
|
+
y: data.point.y,
|
|
283
|
+
z: data.point.z,
|
|
284
|
+
},
|
|
285
|
+
stemVector: {
|
|
286
|
+
x: 0,
|
|
287
|
+
y: 0,
|
|
288
|
+
z: 0,
|
|
289
|
+
},
|
|
290
|
+
}).then((tags) => {
|
|
291
|
+
this.setBillboard(tags[0]);
|
|
292
|
+
mpSdk.Tag.allowAction(tags[0], {
|
|
293
|
+
opening: true,
|
|
294
|
+
navigating: true,
|
|
295
|
+
});
|
|
296
|
+
mpSdk.Tag.editOpacity(tags[0], 0);
|
|
297
|
+
mpSdk.Tag.open(tags[0]).then(() => {
|
|
298
|
+
let tagDestroyer = mpSdk.Tag.openTags.subscribe((newState) => {
|
|
299
|
+
if (newState.selected.size == 0) {
|
|
300
|
+
let thisTag = newState.selected;
|
|
301
|
+
//@ts-expect-error
|
|
302
|
+
if (thisTag != tags[0]) {
|
|
303
|
+
mpSdk.Tag.remove(tags[0]);
|
|
304
|
+
tagDestroyer.cancel();
|
|
305
|
+
this.setBillboard(false);
|
|
306
|
+
mpSdk.Tag.toggleNavControls(true);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
onTick(tickDelta) {
|
|
316
|
+
if (this.inputs.scrollSpeed > 0) {
|
|
317
|
+
this.time += tickDelta;
|
|
318
|
+
if (this.texture) {
|
|
319
|
+
this.texture.offset.x =
|
|
320
|
+
(this.inputs.direction *
|
|
321
|
+
((this.inputs.scrollSpeed * this.time) / 1000)) %
|
|
322
|
+
1;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
onDestroy() {
|
|
327
|
+
this.texture.dispose();
|
|
328
|
+
if (this.panel) {
|
|
329
|
+
this.panel.dispose();
|
|
330
|
+
//@ts-expect-error
|
|
331
|
+
this.panel = false;
|
|
332
|
+
}
|
|
333
|
+
if (this.billboard) {
|
|
334
|
+
this.mpSdk.Tag.remove(this.billboard);
|
|
335
|
+
console.log('Nav Controls On');
|
|
336
|
+
this.mpSdk.Tag.toggleNavControls(true);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
export const pathLineType = 'pathLine';
|
|
341
|
+
export const pathLineFactory = function (mpSdk) {
|
|
342
|
+
return function () {
|
|
343
|
+
return new PathLine(mpSdk);
|
|
344
|
+
};
|
|
345
|
+
};
|
|
346
|
+
export class PathPoint {
|
|
347
|
+
constructor(mpSdk) {
|
|
348
|
+
this.inputs = {
|
|
349
|
+
index: null,
|
|
350
|
+
radius: 0.05,
|
|
351
|
+
position: null,
|
|
352
|
+
fillColor: 'rgb(11,57,72)',
|
|
353
|
+
hoverColor: 'rgb(255,0,0)',
|
|
354
|
+
ringVisibility: false
|
|
355
|
+
};
|
|
356
|
+
this.emits = {
|
|
357
|
+
active: true,
|
|
358
|
+
changed: true,
|
|
359
|
+
};
|
|
360
|
+
this.events = {
|
|
361
|
+
'INTERACTION.DRAG': true,
|
|
362
|
+
'INTERACTION.DRAG_BEGIN': true,
|
|
363
|
+
'INTERACTION.DRAG_END': true,
|
|
364
|
+
'INTERACTION.HOVER': true,
|
|
365
|
+
};
|
|
366
|
+
this.onInputsUpdated = (prevInputs) => {
|
|
367
|
+
this.renderVertice(false);
|
|
368
|
+
};
|
|
369
|
+
this.onInit = () => {
|
|
370
|
+
this.renderVertice();
|
|
371
|
+
};
|
|
372
|
+
this.renderVertice = (hovered = false) => {
|
|
373
|
+
const THREE = this.context.three;
|
|
374
|
+
const group = new THREE.Group();
|
|
375
|
+
//This is just a visual marker so that the user can see the points they have already marked
|
|
376
|
+
this.geometry = new THREE.SphereGeometry(this.inputs.radius, 16, 16);
|
|
377
|
+
this.material = new THREE.MeshBasicMaterial({
|
|
378
|
+
color: (hovered ? this.inputs.hoverColor : this.inputs.fillColor),
|
|
379
|
+
transparent: true,
|
|
380
|
+
opacity: 0.6,
|
|
381
|
+
});
|
|
382
|
+
this.mesh = new THREE.Mesh(this.geometry, this.material);
|
|
383
|
+
this.mesh.position.set(this.inputs.position.x, this.inputs.position.y, this.inputs.position.z);
|
|
384
|
+
this.outputs.objectRoot = this.mesh;
|
|
385
|
+
this.outputs.collider = this.mesh;
|
|
386
|
+
};
|
|
387
|
+
this.mpSdk = mpSdk;
|
|
388
|
+
}
|
|
389
|
+
onEvent(eventType, data) {
|
|
390
|
+
var _a;
|
|
391
|
+
if (eventType === 'INTERACTION.DRAG') {
|
|
392
|
+
//this.pointerIntersection.object === 'intersectedobject.model'
|
|
393
|
+
//this.pointerIntersection.object
|
|
394
|
+
console.log("group this.pointerIntersection ", this.pointerIntersection);
|
|
395
|
+
if (this.pointerIntersection.object === 'intersectedobject.model') {
|
|
396
|
+
let e = Object.assign({}, this.pointerIntersection.position);
|
|
397
|
+
this.mesh.position.set(e.x, e.y, e.z);
|
|
398
|
+
//this.mesh.children[0].position.set(e.x, e.y, e.z)
|
|
399
|
+
//@ts-expect-error
|
|
400
|
+
this.notify('changed', {
|
|
401
|
+
index: this.inputs.index,
|
|
402
|
+
position: this.mesh.position,
|
|
403
|
+
collider: null,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (eventType === 'INTERACTION.DRAG_BEGIN') {
|
|
408
|
+
this.mpSdk.Pointer.setVisible(false);
|
|
409
|
+
//@ts-expect-error
|
|
410
|
+
this.mesh.material.opacity = 0.5;
|
|
411
|
+
//this.mesh.children[0].material.opacity = 0.5
|
|
412
|
+
// will make it smaller later. Setting this to 0.5 to make it easier to see in the space
|
|
413
|
+
this.mesh.scale.set(0.5, 0.5, 0.5);
|
|
414
|
+
if (this.pointerSub == null) {
|
|
415
|
+
this.pointerSub = this.mpSdk.Pointer.intersection.subscribe((data) => {
|
|
416
|
+
this.pointerIntersection = data;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
//@ts-expect-error
|
|
420
|
+
this.notify('changed', {
|
|
421
|
+
index: this.inputs.index,
|
|
422
|
+
position: this.mesh.position,
|
|
423
|
+
collider: false,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
if (eventType === 'INTERACTION.DRAG_END') {
|
|
427
|
+
//@ts-expect-error
|
|
428
|
+
this.mesh.material.opacity = 1;
|
|
429
|
+
this.mesh.scale.set(1, 1, 1);
|
|
430
|
+
this.mpSdk.Pointer.setVisible(true);
|
|
431
|
+
(_a = this.pointerSub) === null || _a === void 0 ? void 0 : _a.cancel();
|
|
432
|
+
//renderPolygonFromPath()
|
|
433
|
+
//@ts-expect-error
|
|
434
|
+
this.notify('changed', {
|
|
435
|
+
index: this.inputs.index,
|
|
436
|
+
position: this.mesh.position,
|
|
437
|
+
collider: false,
|
|
438
|
+
});
|
|
439
|
+
dispatchSpaceEvent(SPACE_EVENTS.VERTEX_DRAG_END, {
|
|
440
|
+
index: this.inputs.index,
|
|
441
|
+
position: this.mesh.position
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
export const pathPointType = 'pathPoint';
|
|
447
|
+
export const pathPointFactory = function (mpSdk) {
|
|
448
|
+
return function () {
|
|
449
|
+
return new PathPoint(mpSdk);
|
|
450
|
+
};
|
|
451
|
+
};
|