architwin 1.12.4 → 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.
Files changed (44) hide show
  1. package/CORE_FEATURES.md +35 -0
  2. package/ONBOARDING.md +115 -0
  3. package/lib/architwin.d.ts +98 -6
  4. package/lib/architwin.js +1 -1
  5. package/lib/atwinui/components/toolbar/collapse.d.ts +18 -0
  6. package/lib/atwinui/components/toolbar/collapse.js +62 -0
  7. package/lib/atwinui/components/toolbar/i18n.js +52 -2
  8. package/lib/atwinui/components/toolbar/index.js +11 -1
  9. package/lib/atwinui/components/toolbar/menuBar.d.ts +1 -0
  10. package/lib/atwinui/components/toolbar/menuBar.js +11 -0
  11. package/lib/atwinui/components/toolbar/pipeFormPane.d.ts +31 -0
  12. package/lib/atwinui/components/toolbar/pipeFormPane.js +545 -0
  13. package/lib/atwinui/components/toolbar/pipeListPane.d.ts +19 -0
  14. package/lib/atwinui/components/toolbar/pipeListPane.js +388 -0
  15. package/lib/atwinui/components/toolbar/spaceUserListPane.d.ts +3 -0
  16. package/lib/atwinui/components/toolbar/spaceUserListPane.js +95 -0
  17. package/lib/atwinui/components/toolbar/tagIotForm.d.ts +20 -0
  18. package/lib/atwinui/components/toolbar/tagIotForm.js +391 -0
  19. package/lib/atwinui/components/toolbar/tagIotFormPane.d.ts +62 -0
  20. package/lib/atwinui/components/toolbar/tagIotFormPane.js +606 -0
  21. package/lib/atwinui/components/toolbar/tagMessagingPane.d.ts +4 -0
  22. package/lib/atwinui/components/toolbar/tagMessagingPane.js +117 -10
  23. package/lib/atwinui/components/toolbar/usersPane.d.ts +14 -0
  24. package/lib/atwinui/components/toolbar/usersPane.js +273 -0
  25. package/lib/atwinui/components/toolbar/viewingRemoteSpace.d.ts +7 -0
  26. package/lib/atwinui/components/toolbar/viewingRemoteSpace.js +77 -0
  27. package/lib/atwinui/events.d.ts +4 -1
  28. package/lib/atwinui/events.js +106 -26
  29. package/lib/atwinui/helpers.d.ts +15 -0
  30. package/lib/atwinui/helpers.js +49 -0
  31. package/lib/atwinui/index.js +2 -0
  32. package/lib/loaders/curosrMarkerLoader.d.ts +25 -0
  33. package/lib/loaders/curosrMarkerLoader.js +86 -0
  34. package/lib/loaders/index.d.ts +2 -1
  35. package/lib/loaders/index.js +2 -1
  36. package/lib/loaders/pathLoader.d.ts +99 -0
  37. package/lib/loaders/pathLoader.js +451 -0
  38. package/lib/tag.d.ts +1 -1
  39. package/lib/tag.js +2 -0
  40. package/lib/types.d.ts +80 -1
  41. package/lib/types.js +35 -0
  42. package/package.json +1 -1
  43. package/static/atwinui.css +267 -0
  44. package/static/utility.css +81 -1
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { actionBar, renderObjectCards, renderLibraryCards, renderTags, renderTagRow, getTagFormData, addClickEventToTagRow, setActiveCard, setActiveMenu, removeObjectCard, clearActiveMenu, setTagCategoriesOption, toggleDropdown, tagFormMode, selectedTag, renderRecepientOptions, renderTagMessages, createTagMessage, setTagLink, setTagMessagingDetails, renderCategoryDropdownOptions, clearTagFormDropdown, clearActiveActionBtn, clearActiveCard, toggleActionBarButtons, selectedCategoryFilterId, selectedSubCategoryFilterId, filterTagList, toggleModal, setModalAction, } from "./components/toolbar";
11
- import { getTargetPosition, addMediaScreen, _3DXObjects, selectedObject, setTransformControls, copyObject, revertTransform, clearSelectedObject, removeTransformControls, getLibrary, getMpTags, renderTag, captureSpaceScreenshot, moveTag, subscribeSpaceEvent, setModelVisibility, disposeModel, disposeTag, _tags, _tagCategories, dispatchSpaceEvent, editTagLabel, editTagDescription, setTagMessageRecepients, setTagMessages, setSelectedTagUuid, renderMeetingSidebar, setTagIcon, setObjectTransformation, getSelectedObject, _atwin, isCdnMapDataAvailable, captureScreenshotAndCameraDetails, _mpConfig, cancelModelPlacement, _modelDetails, actionHistory, get3DXObjects, transformHistory, goToModel, themeManager, _partitionNodes, setSpacePartitionNodes, getSpaceId, setFloorBaseHeight, toggleWallVisibility, getChildrenOfModel, toggleFloorVisibility, renderPolygon, getCurrentPolygon, getFloorBaseHeight, setSelectedObject, redoDrawAction, undoDrawAction, setWallBaseHeight, clearWallBaseHeight, clearFloorBaseHeight, isToolbarFeatureEnabled, captureCurrentView, getCurrentFloor, } from "../architwin";
11
+ import { getTargetPosition, addMediaScreen, _3DXObjects, selectedObject, setTransformControls, copyObject, revertTransform, clearSelectedObject, removeTransformControls, getLibrary, getMpTags, renderTag, captureSpaceScreenshot, moveTag, subscribeSpaceEvent, setModelVisibility, disposeModel, disposeTag, _tags, _tagCategories, dispatchSpaceEvent, editTagLabel, editTagDescription, setTagMessageRecepients, setTagMessages, setSelectedTagUuid, renderMeetingSidebar, setTagIcon, setObjectTransformation, getSelectedObject, _atwin, isCdnMapDataAvailable, captureScreenshotAndCameraDetails, _mpConfig, cancelModelPlacement, _modelDetails, actionHistory, get3DXObjects, transformHistory, goToModel, themeManager, _partitionNodes, setSpacePartitionNodes, getSpaceId, setFloorBaseHeight, toggleWallVisibility, getChildrenOfModel, toggleFloorVisibility, renderPolygon, getCurrentPolygon, getFloorBaseHeight, setSelectedObject, redoDrawAction, undoDrawAction, setWallBaseHeight, clearWallBaseHeight, clearFloorBaseHeight, isToolbarFeatureEnabled, captureCurrentView, getCurrentFloor, setPipeCategories, setPipes, detachTagMedia, getTagDataCollection } from "../architwin";
12
12
  import { Notyf } from 'notyf';
13
13
  import 'notyf/notyf.min.css';
14
14
  import { SPACE_EVENTS, COORDINATE_SYSTEM, UNITS, DEGREE, MAP_OPTIONS } from "../types";
@@ -29,8 +29,15 @@ import { actionSettingsSelectOption, getTempCoordinateSystem, getTempMeasurement
29
29
  import { getBasepointCalibrateBpCoordinateValues, getBasepointCalibrateMpCoordinateValues, initBsepointCalibratePane, toggleBasepointCalibratePane } from "./components/toolbar/basepointCalibratePane";
30
30
  import { toggleGeneralMapOptions, initGeneralSelectedMap, getSelectedMapOption } from './components/toolbar/generalSettingsMenuPane';
31
31
  import { searchTagList, setSearchTagTerm, searchClearfield, getSearchTagTerm } from './components/toolbar/tagListPane';
32
+ import { PipeList } from "./components/toolbar/pipeListPane";
33
+ import { PipeForm } from "./components/toolbar/pipeFormPane";
34
+ // import { EditPipeForm, initPipeFormPane, pipeFormData, setPipeFormMode } from "./components/toolbar/pipeFormPane";
35
+ // import { initPipeData } from "./components/toolbar/addPipePane";
36
+ import { unsendComment, timedoutComment, getTheseTagMessages } from './components/toolbar/tagMessagingPane';
37
+ const pipeList = new PipeList();
38
+ const pipeForm = new PipeForm();
32
39
  let activeToolbarItem, activeActionItem, activePane, activeActionPane, cancelTagPlacementPrompt, cancelModelPlacementPrompt;
33
- let notyf = new Notyf({ position: { x: 'left', y: 'bottom' }, duration: 4500, types: [
40
+ export let notyf = new Notyf({ position: { x: 'left', y: 'bottom' }, duration: 4500, types: [
34
41
  {
35
42
  type: 'info',
36
43
  background: 'blue',
@@ -49,6 +56,7 @@ let _currentPaneId;
49
56
  let isPlacingTag = false;
50
57
  let isCustomMapControlsVisible = false;
51
58
  let isNotyfExecuted = false; // flag for notification
59
+ let pipeColor = "";
52
60
  function batchAddEventListenerByClassName(className, callback) {
53
61
  if (className) {
54
62
  const elements = document.querySelectorAll(`.${className}`);
@@ -255,6 +263,15 @@ function toggleDisplayPane(targetId) {
255
263
  initGeneralSelectedMap();
256
264
  handleCloseActiveMinimap();
257
265
  }
266
+ if (paneId === 'at-pipe-list-pane') {
267
+ log.info("Pipe Pane");
268
+ //setup pipe list pane initialization
269
+ pipeList.init();
270
+ }
271
+ if (paneId === 'at-pipe-form-pane') {
272
+ log.info("Pipe Pane");
273
+ }
274
+ console.log("paneId", paneId);
258
275
  return;
259
276
  }
260
277
  else {
@@ -263,7 +280,7 @@ function toggleDisplayPane(targetId) {
263
280
  return;
264
281
  }
265
282
  }
266
- log.error('Could not get value of target-pane attribute');
283
+ log.error('Could not get value of target-pane attribute', targetId);
267
284
  return;
268
285
  });
269
286
  }
@@ -340,8 +357,44 @@ function setupIndividualEventListeners() {
340
357
  handleCloseCustomMinimap();
341
358
  handleCustomMapControls();
342
359
  handleCloseActiveMinimap();
360
+ handlePipeForm();
361
+ handlePipeList();
362
+ }
363
+ //================ OBJECT EVENT HANDLERS ===============//s
364
+ // handle pipe undo drawing
365
+ function handleUndoPipeDrawing() {
366
+ }
367
+ // handle pipe redo drawing
368
+ function handleRedoDrawing() {
369
+ }
370
+ function handlePipeCategory(payload) {
371
+ return __awaiter(this, void 0, void 0, function* () {
372
+ console.log("HANDLE CATEGORY =>", payload);
373
+ // set categories latest value
374
+ yield setPipeCategories(payload);
375
+ });
376
+ }
377
+ function handlePipe(payload) {
378
+ return __awaiter(this, void 0, void 0, function* () {
379
+ console.log("HANDLE PIPE =>", payload);
380
+ // set pipes latest value
381
+ yield setPipes(payload);
382
+ });
383
+ }
384
+ //handler pipe form events
385
+ function handlePipeForm() {
386
+ // setup events from pipe form
387
+ pipeForm.save();
388
+ pipeForm.cancel();
389
+ pipeForm.draw();
390
+ pipeForm.undo();
391
+ pipeForm.redo();
392
+ }
393
+ //handle pipe list event
394
+ function handlePipeList() {
395
+ // setup event from pipe list
396
+ pipeList.add();
343
397
  }
344
- //================ OBJECT EVENT HANDLERS ===============//
345
398
  function handleTranslateObject() {
346
399
  const translateObjectbtn = document.getElementById('at-translate-action-btn');
347
400
  translateObjectbtn.addEventListener('click', () => {
@@ -381,7 +434,7 @@ function handleCopyObject() {
381
434
  function onCopyModel() {
382
435
  return __awaiter(this, void 0, void 0, function* () {
383
436
  //Clear transform controls otherwise the original object will move to the duplicated object position making it look
384
- //like the original disappeared
437
+ //like the original disappeare
385
438
  const selectedObj = getSelectedObject().object;
386
439
  log.info("copyModel selectedObj ", selectedObj);
387
440
  const objectCards = document.getElementById('at-object-cards');
@@ -863,11 +916,13 @@ function handleSaveTag() {
863
916
  const index = _tags.findIndex(tag => tag.id == selectedTag.id);
864
917
  //Check if object contains a url embed and if the url does not match the existing url in media url
865
918
  //perform a validation of the new url embed
866
- if (tagFormPayload && tagFormPayload.tagEmbed && _tags[index].media_url !== tagFormPayload.tagEmbed) {
867
- if ((yield isValidUrl(tagFormPayload.tagEmbed)) === false) {
868
- notyf.error(`${i18n.t('InvalidURL')}`);
869
- saveTagBtn.classList.remove('at_disabled');
870
- return;
919
+ if (tagFormPayload && tagFormPayload.tagEmbed != '') { // this condition is added when Embed URL is removed by user and is Empty #15842
920
+ if (tagFormPayload && tagFormPayload.tagEmbed && _tags[index].media_url !== tagFormPayload.tagEmbed) {
921
+ if ((yield isValidUrl(tagFormPayload.tagEmbed)) === false) {
922
+ notyf.error(`${i18n.t('InvalidURL')}`);
923
+ saveTagBtn.classList.remove('at_disabled');
924
+ return;
925
+ }
871
926
  }
872
927
  }
873
928
  if (_tagCategories) {
@@ -915,15 +970,26 @@ function handleSaveTag() {
915
970
  }
916
971
  _tags[index].category_uuid = tagFormPayload.tagSubcategoryId;
917
972
  _tags[index].json_data.color = targetCategory.json_data.color.rgb;
918
- if (tagFormPayload.tagEmbed !== _tags[index].media_url) {
919
- const tagData = {
920
- id: _tags[index].json_data.id,
921
- attachments: []
922
- };
923
- const mediaAttachment = [tagFormPayload.tagEmbed];
924
- yield attachTagMedia({ sdk: _atwin, tag: tagData, attachments: mediaAttachment });
973
+ if (tagFormPayload.tagEmbed && tagFormPayload.tagEmbed != '') { // this condition is added when Embed URL is removed by user and is Empty #15842
974
+ if (tagFormPayload.tagEmbed !== _tags[index].media_url) {
975
+ const tagData = {
976
+ id: _tags[index].json_data.id,
977
+ attachments: []
978
+ };
979
+ const mediaAttachment = [tagFormPayload.tagEmbed];
980
+ const attachments = yield attachTagMedia({ sdk: _atwin, tag: tagData, attachments: mediaAttachment });
981
+ }
982
+ _tags[index].media_url = tagFormPayload.tagEmbed;
983
+ }
984
+ else {
985
+ _tags[index].media_url = undefined;
986
+ const tagDataCollection = getTagDataCollection();
987
+ _tags[index].json_data.attachments = tagDataCollection[_tags[index].json_data.id] ? tagDataCollection[_tags[index].json_data.id].attachments : _tags[index].json_data.attachments;
988
+ if (_tags[index].json_data.attachments) {
989
+ yield detachTagMedia({ tagId: _tags[index].json_data.id, attachmentIds: _tags[index].json_data.attachments });
990
+ _tags[index].json_data.attachments = [];
991
+ }
925
992
  }
926
- _tags[index].media_url = tagFormPayload.tagEmbed;
927
993
  // Add tag icon data
928
994
  _tags[index].tag_icon_name = thisTagIconName;
929
995
  _tags[index].tag_icon_url = thisTagIconURL;
@@ -1263,6 +1329,9 @@ function setupSpaceEventSubscriptions() {
1263
1329
  subscribeSpaceEvent(SPACE_EVENTS.DRAW_HISTORY, handleDrawHistory);
1264
1330
  subscribeSpaceEvent(SPACE_EVENTS.FLOOR_IMAGE_UPLOADED, handleCustomMapFloorImageUploaded);
1265
1331
  subscribeSpaceEvent(SPACE_EVENTS.FLOOR_IMAGE_UPLOAD_FAILED, handleCustomMapFloorUploadFailed);
1332
+ // subscribeSpaceEvent(SPACE_EVENTS.DRAW_PIPE, handleDrawPipe)
1333
+ subscribeSpaceEvent(SPACE_EVENTS.PIPE_CATEGORY_ON_CHANGE, handlePipeCategory);
1334
+ subscribeSpaceEvent(SPACE_EVENTS.PIPE_ON_CHANGE, handlePipe);
1266
1335
  }
1267
1336
  function handleDragEnd(payload) {
1268
1337
  console.log("handleDragEnd payload", payload);
@@ -1308,7 +1377,7 @@ function handleDragEnd(payload) {
1308
1377
  showCurrentCoordinateValue();
1309
1378
  const transformValues = {
1310
1379
  object_position: payload.object_position,
1311
- object_rotation: payload.object_rotation,
1380
+ object_rotation: payload.object_rotationƒ,
1312
1381
  object_scale: payload.object_scale,
1313
1382
  };
1314
1383
  setCurrentTransformationValues(transformValues);
@@ -1333,13 +1402,21 @@ function handleDrawHistory(payload) {
1333
1402
  const redoBtn = document.getElementById('at-draw-redo-btn');
1334
1403
  redoBtn.classList.remove('at_disabled');
1335
1404
  }
1405
+ console.log("undoCount", undoCount);
1406
+ console.log("redoCount", redoCount);
1336
1407
  }
1337
- function handleVertexPlace() {
1338
- const undoBtn = document.getElementById('at-draw-undo-btn');
1339
- undoBtn.classList.remove('at_disabled');
1340
- setCurrentPartitionData();
1341
- const redoBtn = document.getElementById('at-draw-redo-btn');
1342
- redoBtn.classList.add('at_disabled');
1408
+ function handleVertexPlace(payload) {
1409
+ console.log("handleVertexPlace ==>", payload);
1410
+ if (isToolbarFeatureEnabled('roomCreation')) {
1411
+ const undoBtn = document.getElementById('at-draw-undo-btn');
1412
+ undoBtn.classList.remove('at_disabled');
1413
+ setCurrentPartitionData();
1414
+ const redoBtn = document.getElementById('at-draw-redo-btn');
1415
+ redoBtn.classList.add('at_disabled');
1416
+ }
1417
+ if (isToolbarFeatureEnabled('pipe')) {
1418
+ pipeForm.setPipeVertices(payload.path);
1419
+ }
1343
1420
  }
1344
1421
  function handleMouseClickObject(object) {
1345
1422
  var _a, _b, _c;
@@ -1412,6 +1489,9 @@ function handleRetrieveTagMessage(payload) {
1412
1489
  renderRecepientOptions();
1413
1490
  renderTagMessages();
1414
1491
  setTagMessagingDetails(payload.tagUuid);
1492
+ unsendComment(payload);
1493
+ getTheseTagMessages(payload.tagMessages);
1494
+ timedoutComment(payload.tagMessages);
1415
1495
  }
1416
1496
  function handleSetModelsView() {
1417
1497
  const modelsCardViewBtn = document.getElementById('at-models-card-view-btn');
@@ -2972,7 +3052,7 @@ function handleCloseActiveMinimap() {
2972
3052
  }
2973
3053
  export {
2974
3054
  //state
2975
- activeToolbarItem, activeActionItem, cancelModelPlacementPrompt, isCustomMapControlsVisible,
3055
+ activeToolbarItem, activeActionItem, cancelModelPlacementPrompt, isCustomMapControlsVisible, pipeColor,
2976
3056
  //methods
2977
3057
  batchAddEventListenerById, batchAddEventListenerByClassName, batchAddEventListenerByClassNames, batchAddEventListenerByDataAttribute, setActiveToolbarItem, toggleDisplayPane, toggleActionBar, setupIndividualEventListeners, setupSpaceEventSubscriptions, handleModelVisibility, handleDeleteModel, handleShowMinimap, handleScrollToView, handleRenderMeetingUI, handleShowCustomMinimap,
2978
3058
  // partition
@@ -0,0 +1,15 @@
1
+ export declare function waitForChange<T>(getter: () => T, options?: {
2
+ interval?: number;
3
+ timeout?: number;
4
+ }): Promise<T>;
5
+ export declare function waitForChange<T1, T2>(getter1: () => T1, getter2: () => T2, options?: {
6
+ interval?: number;
7
+ timeout?: number;
8
+ }): Promise<[T1, T2]>;
9
+ /**
10
+ * Binds an input element's value to a target object's property using input and mutation observers.
11
+ * @param input The input HTML element to observe
12
+ * @param getTarget A function returning the target object (like _selectedPipeCategory)
13
+ * @param key The key of the target object to update
14
+ */
15
+ export declare function observeInputToUpdate(input: HTMLInputElement, getTarget: () => Record<string, any> | undefined, key: string): void;
@@ -0,0 +1,49 @@
1
+ export function waitForChange(...args) {
2
+ const maybeOptions = args[args.length - 1];
3
+ const options = typeof maybeOptions === 'object' && ('interval' in maybeOptions || 'timeout' in maybeOptions)
4
+ ? maybeOptions
5
+ : {};
6
+ const getters = (maybeOptions === options ? args.slice(0, -1) : args);
7
+ const { interval = 100, timeout = 5000 } = options;
8
+ const initial = getters.map(fn => fn());
9
+ const start = Date.now();
10
+ return new Promise((resolve, reject) => {
11
+ const check = () => {
12
+ const current = getters.map(fn => fn());
13
+ const hasChanged = current.some((val, i) => val !== initial[i] && val != null);
14
+ if (hasChanged) {
15
+ resolve(getters.length === 1 ? current[0] : current);
16
+ }
17
+ else if (Date.now() - start >= timeout) {
18
+ reject(new Error('Timeout: Values did not change'));
19
+ }
20
+ else {
21
+ setTimeout(check, interval);
22
+ }
23
+ };
24
+ check();
25
+ });
26
+ }
27
+ /**
28
+ * Binds an input element's value to a target object's property using input and mutation observers.
29
+ * @param input The input HTML element to observe
30
+ * @param getTarget A function returning the target object (like _selectedPipeCategory)
31
+ * @param key The key of the target object to update
32
+ */
33
+ export function observeInputToUpdate(input, getTarget, key) {
34
+ if (!input)
35
+ return;
36
+ const update = () => {
37
+ const target = getTarget();
38
+ if (target) {
39
+ target[key] = input.value;
40
+ }
41
+ };
42
+ const observer = new MutationObserver(update);
43
+ observer.observe(input, {
44
+ attributes: true,
45
+ attributeFilter: ['value'],
46
+ });
47
+ input.addEventListener('input', update);
48
+ console.log("observer ==>", input);
49
+ }
@@ -37,6 +37,8 @@ const sidebarPaneBtnIds = [
37
37
  'at-cancel-theme-btn',
38
38
  'at-save-customization-btn',
39
39
  'at-draw-room-btn',
40
+ // 'at-cancel-pipe-btn',
41
+ // 'at-save-pipe-btn'
40
42
  ];
41
43
  //'at-cancel-add-object-form-btn',
42
44
  function initToolbarUI(payload) {
@@ -0,0 +1,25 @@
1
+ import { MpSdk } from "../../bundle/sdk";
2
+ import * as THREE from "three";
3
+ import { IMPConfig } from "../types";
4
+ declare class CursorMarkerLoader {
5
+ inputs: {
6
+ pointerIntersection: MpSdk.Pointer.Intersection;
7
+ markerTexture: string;
8
+ visible: boolean;
9
+ offset: number;
10
+ scale: number;
11
+ };
12
+ outputs: Record<string, unknown> & MpSdk.Scene.PredefinedOutputs;
13
+ context: MpSdk.Scene.IComponentContext;
14
+ mesh: THREE.Mesh;
15
+ material: THREE.Material;
16
+ geometry: THREE.PlaneGeometry;
17
+ texture: THREE.Texture;
18
+ constructor(mpConfig: IMPConfig);
19
+ onInit: () => void;
20
+ onInputsUpdated: () => void;
21
+ onDestroy: () => void;
22
+ }
23
+ export declare const cursorMarkerType = "mp.cursorMarker";
24
+ export declare const cursorMarkerFactory: () => CursorMarkerLoader;
25
+ export {};
@@ -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);
@@ -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
- 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 };
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 };
@@ -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;