@babylonjs/inspector 8.52.0 → 8.52.1
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/{extensionsListService-qU9tqfBg.js → extensionsListService-Duej2zkq.js} +12 -11
- package/lib/extensionsListService-Duej2zkq.js.map +1 -0
- package/lib/{index-Cmd13UXt.js → index-BvYg0Psk.js} +878 -642
- package/lib/index-BvYg0Psk.js.map +1 -0
- package/lib/index.d.ts +40 -11
- package/lib/index.js +3 -3
- package/lib/{quickCreateToolsService-C9jZpIAl.js → quickCreateToolsService-DHfs_EZ6.js} +4 -4
- package/lib/{quickCreateToolsService-C9jZpIAl.js.map → quickCreateToolsService-DHfs_EZ6.js.map} +1 -1
- package/lib/{reflectorService-DGy36OAK.js → reflectorService-DEPuGTAZ.js} +4 -4
- package/lib/{reflectorService-DGy36OAK.js.map → reflectorService-DEPuGTAZ.js.map} +1 -1
- package/package.json +1 -1
- package/lib/extensionsListService-qU9tqfBg.js.map +0 -1
- package/lib/index-Cmd13UXt.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { createContext, forwardRef, useContext, useState, useCallback, Component, useMemo, useEffect, useRef, useReducer, Children, isValidElement, useLayoutEffect, cloneElement, useImperativeHandle, createElement, Suspense, memo, Fragment as Fragment$1, lazy } from 'react';
|
|
3
|
-
import { tokens, makeStyles, Tooltip as Tooltip$1, Button as Button$1, Spinner, Link as Link$1, Caption1, Body1, useFluent, Accordion as Accordion$1, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, MessageBar as MessageBar$1, MessageBarBody, AccordionItem, SearchBox as SearchBox$1, Portal, ToggleButton as ToggleButton$1, InfoLabel as InfoLabel$1, mergeClasses, Body1Strong, useId, useToastController, Toast, ToastTitle, FluentProvider, Toaster, Checkbox as Checkbox$1, createLightTheme, createDarkTheme, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, Switch as Switch$1, createDOMRenderer, RendererProvider, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, ToolbarRadioButton, MenuGroup, MenuGroupHeader, treeItemLevelToken, FlatTree, FlatTreeItem, TreeItemLayout, MenuDivider, MenuItemCheckbox,
|
|
4
|
-
import { ErrorCircleRegular, EyeFilled, EyeOffRegular, CheckmarkFilled, EditRegular, FilterRegular, PinFilled, PinRegular, ArrowCircleUpRegular, ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, CopyRegular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, SettingsRegular, DocumentTextRegular, createFluentIcon, TextSortAscendingRegular, GlobeRegular, ArrowExpandAllRegular, ArrowCollapseAllRegular, CubeTreeRegular, BugRegular, ArrowUploadRegular, ArrowDownloadRegular, StopRegular, RecordRegular, DataBarHorizontalRegular, WrenchRegular, WeatherSunnyRegular, WeatherMoonRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, CameraRegular, AddRegular, DeleteRegular, FullScreenMaximizeRegular, ChevronDownRegular, ChevronRightRegular, CircleSmallFilled, SaveRegular, PreviousRegular, ArrowPreviousRegular, TriangleLeftRegular, RecordStopRegular, PlayRegular, ArrowNextRegular, NextRegular, PauseRegular, LinkDismissRegular, LinkEditRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, EyeRegular, CloudArrowUpRegular, CloudArrowDownRegular, EyeOffFilled, ArrowMoveFilled, StopFilled, PlayFilled, LockOpenRegular, LockClosedRegular, ResizeRegular, ChevronUpRegular, ArrowResetRegular, CircleHalfFillRegular, EyedropperRegular, PaintBucketRegular, InkStrokeRegular, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, AppGenericRegular, RectangleLandscapeRegular, BorderOutsideRegular, BorderNoneRegular, MyLocationRegular, LightbulbRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, SoundWaveCircleRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, BranchRegular, DeleteFilled } from '@fluentui/react-icons';
|
|
3
|
+
import { tokens, makeStyles, Tooltip as Tooltip$1, Button as Button$1, Spinner, Link as Link$1, Caption1, Body1, useFluent, Accordion as Accordion$1, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, MessageBar as MessageBar$1, MessageBarBody, AccordionItem, SearchBox as SearchBox$1, Portal, ToggleButton as ToggleButton$1, InfoLabel as InfoLabel$1, mergeClasses, Body1Strong, useId, useToastController, Toast, ToastTitle, FluentProvider, Toaster, Checkbox as Checkbox$1, createLightTheme, createDarkTheme, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, Switch as Switch$1, createDOMRenderer, RendererProvider, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, ToolbarRadioButton, MenuGroup, MenuGroupHeader, treeItemLevelToken, FlatTree, FlatTreeItem, TreeItemLayout, MenuDivider, MenuItemCheckbox, useMergedRefs, Input, Dropdown as Dropdown$1, Option, Popover as Popover$1, PopoverTrigger, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, ColorSwatch, PresenceBadge, Slider as Slider$1, MenuItemRadio, Dialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, List as List$1, ListItem, Badge, Label, MessageBarTitle, Subtitle2, useComboboxFilter, Combobox, Textarea as Textarea$1, ToolbarButton, ToolbarDivider, Field } from '@fluentui/react-components';
|
|
4
|
+
import { ErrorCircleRegular, EyeFilled, EyeOffRegular, CheckmarkFilled, EditRegular, FilterRegular, PinFilled, PinRegular, ArrowCircleUpRegular, ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, CopyRegular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, SettingsRegular, DocumentTextRegular, createFluentIcon, TextSortAscendingRegular, GlobeRegular, ArrowExpandAllRegular, ArrowCollapseAllRegular, CubeTreeRegular, BugRegular, ArrowUploadRegular, ArrowBidirectionalUpDownFilled, ArrowDownloadRegular, StopRegular, RecordRegular, DataBarHorizontalRegular, WrenchRegular, ArrowClockwiseRegular, WeatherSunnyRegular, WeatherMoonRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, CameraRegular, AddRegular, DeleteRegular, FullScreenMaximizeRegular, ChevronDownRegular, ChevronRightRegular, CircleSmallFilled, SaveRegular, PreviousRegular, ArrowPreviousRegular, TriangleLeftRegular, RecordStopRegular, PlayRegular, ArrowNextRegular, NextRegular, PauseRegular, LinkDismissRegular, LinkEditRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, EyeRegular, CloudArrowUpRegular, CloudArrowDownRegular, EyeOffFilled, ArrowMoveFilled, StopFilled, PlayFilled, LockOpenRegular, LockClosedRegular, ResizeRegular, ChevronUpRegular, ArrowResetRegular, CircleHalfFillRegular, EyedropperRegular, PaintBucketRegular, InkStrokeRegular, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, AppGenericRegular, RectangleLandscapeRegular, BorderOutsideRegular, BorderNoneRegular, MyLocationRegular, LightbulbRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, SoundWaveCircleRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, BranchRegular, DeleteFilled } from '@fluentui/react-icons';
|
|
5
5
|
import { Color3, Color4 } from '@babylonjs/core/Maths/math.color.js';
|
|
6
6
|
import { Vector3, Quaternion, Matrix, Vector2, Vector4, TmpVectors } from '@babylonjs/core/Maths/math.vector.js';
|
|
7
7
|
import { Observable } from '@babylonjs/core/Misc/observable.js';
|
|
@@ -45,6 +45,8 @@ import { Light } from '@babylonjs/core/Lights/light.js';
|
|
|
45
45
|
import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh.js';
|
|
46
46
|
import { Node as Node$1 } from '@babylonjs/core/node.js';
|
|
47
47
|
import { createRoot } from 'react-dom/client';
|
|
48
|
+
import { SelectionOutlineLayer } from '@babylonjs/core/Layers/selectionOutlineLayer.js';
|
|
49
|
+
import { GaussianSplattingMesh } from '@babylonjs/core/Meshes/GaussianSplatting/gaussianSplattingMesh.js';
|
|
48
50
|
import { AnimationGroup, TargetedAnimation } from '@babylonjs/core/Animations/animationGroup.js';
|
|
49
51
|
import { Animation } from '@babylonjs/core/Animations/animation.js';
|
|
50
52
|
import { AnimationPropertiesOverride } from '@babylonjs/core/Animations/animationPropertiesOverride.js';
|
|
@@ -80,7 +82,6 @@ import { NodeMaterialBlockConnectionPointTypes } from '@babylonjs/core/Materials
|
|
|
80
82
|
import { FactorGradient, Color3Gradient, ColorGradient } from '@babylonjs/core/Misc/gradients.js';
|
|
81
83
|
import { ReadFile } from '@babylonjs/core/Misc/fileTools.js';
|
|
82
84
|
import { CubeTexture } from '@babylonjs/core/Materials/Textures/cubeTexture.js';
|
|
83
|
-
import { GaussianSplattingMesh } from '@babylonjs/core/Meshes/GaussianSplatting/gaussianSplattingMesh.js';
|
|
84
85
|
import { Mesh } from '@babylonjs/core/Meshes/mesh.js';
|
|
85
86
|
import { SkeletonViewer } from '@babylonjs/core/Debug/skeletonViewer.js';
|
|
86
87
|
import { VertexBuffer } from '@babylonjs/core/Meshes/buffer.js';
|
|
@@ -144,7 +145,6 @@ import { ImportAnimationsAsync, SceneLoader } from '@babylonjs/core/Loading/scen
|
|
|
144
145
|
import { FilesInput } from '@babylonjs/core/Misc/filesInput.js';
|
|
145
146
|
import { GLTFLoaderAnimationStartMode, GLTFLoaderCoordinateSystemMode, GLTFLoaderDefaultOptions } from '@babylonjs/loaders/glTF/glTFFileLoader.js';
|
|
146
147
|
import { GLTFValidation } from '@babylonjs/loaders/glTF/glTFValidation.js';
|
|
147
|
-
import { SelectionOutlineLayer } from '@babylonjs/core/Layers/selectionOutlineLayer.js';
|
|
148
148
|
import { EngineStore } from '@babylonjs/core/Engines/engineStore.js';
|
|
149
149
|
import { DebugLayer } from '@babylonjs/core/Debug/debugLayer.js';
|
|
150
150
|
import { Lazy } from '@babylonjs/core/Misc/lazy.js';
|
|
@@ -276,7 +276,7 @@ const Button = forwardRef((props, ref) => {
|
|
|
276
276
|
});
|
|
277
277
|
Button.displayName = "Button";
|
|
278
278
|
|
|
279
|
-
const useStyles$
|
|
279
|
+
const useStyles$U = makeStyles({
|
|
280
280
|
root: {
|
|
281
281
|
display: "flex",
|
|
282
282
|
flexDirection: "column",
|
|
@@ -357,7 +357,7 @@ class ErrorBoundary extends Component {
|
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
function ErrorFallback({ error, onRetry }) {
|
|
360
|
-
const styles = useStyles$
|
|
360
|
+
const styles = useStyles$U();
|
|
361
361
|
return (jsxs("div", { className: styles.root, children: [jsx(ErrorCircleRegular, { className: styles.icon }), jsx("div", { className: styles.title, children: "Something went wrong" }), jsx("div", { className: styles.message, children: "An error occurred in this component. You can try again or continue using other parts of the tool." }), jsx(Button, { label: "Try Again", appearance: "primary", onClick: onRetry }), error && jsx("div", { className: styles.details, children: error.message })] }));
|
|
362
362
|
}
|
|
363
363
|
|
|
@@ -369,82 +369,6 @@ function usePropertyChangedNotifier() {
|
|
|
369
369
|
}, [propertyContext]);
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
const InterceptorHooksMaps$1 = new WeakMap();
|
|
373
|
-
/** @internal */
|
|
374
|
-
function InterceptFunction(target, propertyKey, hooks) {
|
|
375
|
-
if (!hooks.afterCall) {
|
|
376
|
-
throw new Error("At least one hook must be provided.");
|
|
377
|
-
}
|
|
378
|
-
const originalFunction = Reflect.get(target, propertyKey, target);
|
|
379
|
-
if (typeof originalFunction !== "function") {
|
|
380
|
-
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is not a function.`);
|
|
381
|
-
}
|
|
382
|
-
// Make sure the property is configurable and writable, otherwise it is immutable and cannot be intercepted.
|
|
383
|
-
const propertyDescriptor = Reflect.getOwnPropertyDescriptor(target, propertyKey);
|
|
384
|
-
if (propertyDescriptor) {
|
|
385
|
-
if (!propertyDescriptor.configurable) {
|
|
386
|
-
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is not configurable.`);
|
|
387
|
-
}
|
|
388
|
-
if (propertyDescriptor.writable === false || (propertyDescriptor.writable === undefined && !propertyDescriptor.set)) {
|
|
389
|
-
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is readonly.`);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
// Get or create the hooks map for the target object.
|
|
393
|
-
let hooksMap = InterceptorHooksMaps$1.get(target);
|
|
394
|
-
if (!hooksMap) {
|
|
395
|
-
InterceptorHooksMaps$1.set(target, (hooksMap = new Map()));
|
|
396
|
-
}
|
|
397
|
-
// Get or create the hooks array for the property key.
|
|
398
|
-
let hooksForKey = hooksMap.get(propertyKey);
|
|
399
|
-
if (!hooksForKey) {
|
|
400
|
-
hooksMap.set(propertyKey, (hooksForKey = []));
|
|
401
|
-
if (
|
|
402
|
-
// Replace the function with a new one that calls the hooks in addition to the original function.
|
|
403
|
-
!Reflect.set(target, propertyKey, (...args) => {
|
|
404
|
-
const result = Reflect.apply(originalFunction, target, args);
|
|
405
|
-
for (const { afterCall } of hooksForKey) {
|
|
406
|
-
afterCall?.(...args);
|
|
407
|
-
}
|
|
408
|
-
return result;
|
|
409
|
-
})) {
|
|
410
|
-
throw new Error(`Failed to define new function "${propertyKey.toString()}" on object "${target}".`);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
hooksForKey.push(hooks);
|
|
414
|
-
let isDisposed = false;
|
|
415
|
-
return {
|
|
416
|
-
dispose: () => {
|
|
417
|
-
if (!isDisposed) {
|
|
418
|
-
// Remove the hooks from the hooks array for the property key.
|
|
419
|
-
hooksForKey.splice(hooksForKey.indexOf(hooks), 1);
|
|
420
|
-
// If there are no more hooks for the property key, remove the property from the hooks map.
|
|
421
|
-
if (hooksForKey.length === 0) {
|
|
422
|
-
hooksMap.delete(propertyKey);
|
|
423
|
-
// If there are no more hooks for the target object, remove the hooks map from the WeakMap.
|
|
424
|
-
if (hooksMap.size === 0) {
|
|
425
|
-
InterceptorHooksMaps$1.delete(target);
|
|
426
|
-
}
|
|
427
|
-
if (propertyDescriptor) {
|
|
428
|
-
// If we have a property descriptor, it means the property was defined directly on the target object,
|
|
429
|
-
// in which case we replaced it and the original property descriptor needs to be restored.
|
|
430
|
-
if (!Reflect.defineProperty(target, propertyKey, propertyDescriptor)) {
|
|
431
|
-
throw new Error(`Failed to restore original function "${propertyKey.toString()}" on object "${target}".`);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
else {
|
|
435
|
-
// Otherwise, the property was inherited through the prototype chain, and so we can simply delete it from
|
|
436
|
-
// the target object to allow it to fall back to the prototype chain as it did originally.
|
|
437
|
-
if (!Reflect.deleteProperty(target, propertyKey)) {
|
|
438
|
-
throw new Error(`Failed to delete transient function "${propertyKey.toString()}" on object "${target}".`);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
isDisposed = true;
|
|
443
|
-
}
|
|
444
|
-
},
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
|
|
448
372
|
/**
|
|
449
373
|
* Gets the property descriptor for a property on an object, including inherited properties.
|
|
450
374
|
* @param target The object containing the property.
|
|
@@ -474,7 +398,7 @@ function IsPropertyReadonly(propertyDescriptor) {
|
|
|
474
398
|
// If the property is not writable, it is readonly.
|
|
475
399
|
return propertyDescriptor.writable === false || (propertyDescriptor.writable === undefined && !propertyDescriptor.set);
|
|
476
400
|
}
|
|
477
|
-
const InterceptorHooksMaps = new WeakMap();
|
|
401
|
+
const InterceptorHooksMaps$1 = new WeakMap();
|
|
478
402
|
/** @internal */
|
|
479
403
|
function InterceptProperty(target, propertyKey, hooks) {
|
|
480
404
|
// Find the property descriptor and note the owning object (might be inherited through the prototype chain).
|
|
@@ -505,9 +429,9 @@ function InterceptProperty(target, propertyKey, hooks) {
|
|
|
505
429
|
}
|
|
506
430
|
}
|
|
507
431
|
// Get or create the hooks map for the target object.
|
|
508
|
-
let hooksMap = InterceptorHooksMaps.get(target);
|
|
432
|
+
let hooksMap = InterceptorHooksMaps$1.get(target);
|
|
509
433
|
if (!hooksMap) {
|
|
510
|
-
InterceptorHooksMaps.set(target, (hooksMap = new Map()));
|
|
434
|
+
InterceptorHooksMaps$1.set(target, (hooksMap = new Map()));
|
|
511
435
|
}
|
|
512
436
|
// Get or create the hooks array for the property key.
|
|
513
437
|
let hooksForKey = hooksMap.get(propertyKey);
|
|
@@ -547,7 +471,7 @@ function InterceptProperty(target, propertyKey, hooks) {
|
|
|
547
471
|
hooksMap.delete(propertyKey);
|
|
548
472
|
// If there are no more hooks for the target object, remove the hooks map from the WeakMap.
|
|
549
473
|
if (hooksMap.size === 0) {
|
|
550
|
-
InterceptorHooksMaps.delete(target);
|
|
474
|
+
InterceptorHooksMaps$1.delete(target);
|
|
551
475
|
}
|
|
552
476
|
const shouldRestorePropertyDescriptor =
|
|
553
477
|
// If the property is owned by the target object, then we may have replaced an original property descriptor that needs to be restore.
|
|
@@ -573,6 +497,95 @@ function InterceptProperty(target, propertyKey, hooks) {
|
|
|
573
497
|
};
|
|
574
498
|
}
|
|
575
499
|
|
|
500
|
+
const DefaultWatcher = {
|
|
501
|
+
watchProperty(target, propertyKey, onChanged) {
|
|
502
|
+
return InterceptProperty(target, propertyKey, {
|
|
503
|
+
afterSet: (value) => onChanged(value),
|
|
504
|
+
});
|
|
505
|
+
},
|
|
506
|
+
refresh: () => { },
|
|
507
|
+
};
|
|
508
|
+
const WatcherContext = createContext(DefaultWatcher);
|
|
509
|
+
function useWatcher() {
|
|
510
|
+
return useContext(WatcherContext);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const InterceptorHooksMaps = new WeakMap();
|
|
514
|
+
/** @internal */
|
|
515
|
+
function InterceptFunction(target, propertyKey, hooks) {
|
|
516
|
+
if (!hooks.afterCall) {
|
|
517
|
+
throw new Error("At least one hook must be provided.");
|
|
518
|
+
}
|
|
519
|
+
const originalFunction = Reflect.get(target, propertyKey, target);
|
|
520
|
+
if (typeof originalFunction !== "function") {
|
|
521
|
+
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is not a function.`);
|
|
522
|
+
}
|
|
523
|
+
// Make sure the property is configurable and writable, otherwise it is immutable and cannot be intercepted.
|
|
524
|
+
const propertyDescriptor = Reflect.getOwnPropertyDescriptor(target, propertyKey);
|
|
525
|
+
if (propertyDescriptor) {
|
|
526
|
+
if (!propertyDescriptor.configurable) {
|
|
527
|
+
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is not configurable.`);
|
|
528
|
+
}
|
|
529
|
+
if (propertyDescriptor.writable === false || (propertyDescriptor.writable === undefined && !propertyDescriptor.set)) {
|
|
530
|
+
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is readonly.`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
// Get or create the hooks map for the target object.
|
|
534
|
+
let hooksMap = InterceptorHooksMaps.get(target);
|
|
535
|
+
if (!hooksMap) {
|
|
536
|
+
InterceptorHooksMaps.set(target, (hooksMap = new Map()));
|
|
537
|
+
}
|
|
538
|
+
// Get or create the hooks array for the property key.
|
|
539
|
+
let hooksForKey = hooksMap.get(propertyKey);
|
|
540
|
+
if (!hooksForKey) {
|
|
541
|
+
hooksMap.set(propertyKey, (hooksForKey = []));
|
|
542
|
+
if (
|
|
543
|
+
// Replace the function with a new one that calls the hooks in addition to the original function.
|
|
544
|
+
!Reflect.set(target, propertyKey, (...args) => {
|
|
545
|
+
const result = Reflect.apply(originalFunction, target, args);
|
|
546
|
+
for (const { afterCall } of hooksForKey) {
|
|
547
|
+
afterCall?.(...args);
|
|
548
|
+
}
|
|
549
|
+
return result;
|
|
550
|
+
})) {
|
|
551
|
+
throw new Error(`Failed to define new function "${propertyKey.toString()}" on object "${target}".`);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
hooksForKey.push(hooks);
|
|
555
|
+
let isDisposed = false;
|
|
556
|
+
return {
|
|
557
|
+
dispose: () => {
|
|
558
|
+
if (!isDisposed) {
|
|
559
|
+
// Remove the hooks from the hooks array for the property key.
|
|
560
|
+
hooksForKey.splice(hooksForKey.indexOf(hooks), 1);
|
|
561
|
+
// If there are no more hooks for the property key, remove the property from the hooks map.
|
|
562
|
+
if (hooksForKey.length === 0) {
|
|
563
|
+
hooksMap.delete(propertyKey);
|
|
564
|
+
// If there are no more hooks for the target object, remove the hooks map from the WeakMap.
|
|
565
|
+
if (hooksMap.size === 0) {
|
|
566
|
+
InterceptorHooksMaps.delete(target);
|
|
567
|
+
}
|
|
568
|
+
if (propertyDescriptor) {
|
|
569
|
+
// If we have a property descriptor, it means the property was defined directly on the target object,
|
|
570
|
+
// in which case we replaced it and the original property descriptor needs to be restored.
|
|
571
|
+
if (!Reflect.defineProperty(target, propertyKey, propertyDescriptor)) {
|
|
572
|
+
throw new Error(`Failed to restore original function "${propertyKey.toString()}" on object "${target}".`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
// Otherwise, the property was inherited through the prototype chain, and so we can simply delete it from
|
|
577
|
+
// the target object to allow it to fall back to the prototype chain as it did originally.
|
|
578
|
+
if (!Reflect.deleteProperty(target, propertyKey)) {
|
|
579
|
+
throw new Error(`Failed to delete transient function "${propertyKey.toString()}" on object "${target}".`);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
isDisposed = true;
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
|
|
576
589
|
/**
|
|
577
590
|
* Provides an observable that fires when a specified function/property is called/set.
|
|
578
591
|
* @param type The type of the interceptor, either "function" or "property".
|
|
@@ -583,6 +596,7 @@ function InterceptProperty(target, propertyKey, hooks) {
|
|
|
583
596
|
function useInterceptObservable(type, target, propertyKey) {
|
|
584
597
|
// Create a cached observable. It effectively has the lifetime of the component that uses this hook.
|
|
585
598
|
const observable = useMemo(() => new Observable(), []);
|
|
599
|
+
const watcher = useWatcher();
|
|
586
600
|
// Whenever the type, target, or property key changes, we need to set up a new interceptor.
|
|
587
601
|
useEffect(() => {
|
|
588
602
|
let interceptToken = null;
|
|
@@ -595,11 +609,7 @@ function useInterceptObservable(type, target, propertyKey) {
|
|
|
595
609
|
});
|
|
596
610
|
}
|
|
597
611
|
else if (type === "property") {
|
|
598
|
-
interceptToken =
|
|
599
|
-
afterSet: () => {
|
|
600
|
-
observable.notifyObservers();
|
|
601
|
-
},
|
|
602
|
-
});
|
|
612
|
+
interceptToken = watcher.watchProperty(target, propertyKey, () => observable.notifyObservers());
|
|
603
613
|
}
|
|
604
614
|
else {
|
|
605
615
|
throw new Error(`Unknown interceptor type: ${type}`);
|
|
@@ -1068,14 +1078,20 @@ function useKeyState(key, options) {
|
|
|
1068
1078
|
useKeyListener({
|
|
1069
1079
|
onKeyDown: useCallback((e) => {
|
|
1070
1080
|
if (e.key === key) {
|
|
1081
|
+
if (options?.preventDefault) {
|
|
1082
|
+
e.preventDefault();
|
|
1083
|
+
}
|
|
1071
1084
|
setIsPressed(true);
|
|
1072
1085
|
}
|
|
1073
|
-
}, [key]),
|
|
1086
|
+
}, [key, options?.preventDefault]),
|
|
1074
1087
|
onKeyUp: useCallback((e) => {
|
|
1075
1088
|
if (e.key === key) {
|
|
1089
|
+
if (options?.preventDefault) {
|
|
1090
|
+
e.preventDefault();
|
|
1091
|
+
}
|
|
1076
1092
|
setIsPressed(false);
|
|
1077
1093
|
}
|
|
1078
|
-
}, [key]),
|
|
1094
|
+
}, [key, options?.preventDefault]),
|
|
1079
1095
|
}, options);
|
|
1080
1096
|
useEventListener("window", "blur", useCallback(() => setIsPressed(false), []), options); // Reset state on window blur to avoid stuck keys
|
|
1081
1097
|
return isPressed;
|
|
@@ -1338,7 +1354,7 @@ function useIsSectionEmpty(sectionId) {
|
|
|
1338
1354
|
return hasItems;
|
|
1339
1355
|
}
|
|
1340
1356
|
|
|
1341
|
-
const useStyles$
|
|
1357
|
+
const useStyles$T = makeStyles({
|
|
1342
1358
|
accordion: {
|
|
1343
1359
|
display: "flex",
|
|
1344
1360
|
flexDirection: "column",
|
|
@@ -1425,7 +1441,7 @@ const useStyles$S = makeStyles({
|
|
|
1425
1441
|
*/
|
|
1426
1442
|
const AccordionMenuBar = () => {
|
|
1427
1443
|
AccordionMenuBar.displayName = "AccordionMenuBar";
|
|
1428
|
-
const classes = useStyles$
|
|
1444
|
+
const classes = useStyles$T();
|
|
1429
1445
|
const accordionCtx = useContext(AccordionContext);
|
|
1430
1446
|
if (!accordionCtx) {
|
|
1431
1447
|
return null;
|
|
@@ -1468,7 +1484,7 @@ const AccordionSectionBlock = (props) => {
|
|
|
1468
1484
|
const AccordionSectionItem = (props) => {
|
|
1469
1485
|
AccordionSectionItem.displayName = "AccordionSectionItem";
|
|
1470
1486
|
const { children, staticItem } = props;
|
|
1471
|
-
const classes = useStyles$
|
|
1487
|
+
const classes = useStyles$T();
|
|
1472
1488
|
const accordionCtx = useContext(AccordionContext);
|
|
1473
1489
|
const itemState = useAccordionSectionItemState(props);
|
|
1474
1490
|
const [ctrlMode, setCtrlMode] = useState(false);
|
|
@@ -1508,7 +1524,7 @@ const AccordionSectionItem = (props) => {
|
|
|
1508
1524
|
*/
|
|
1509
1525
|
const AccordionPinnedContainer = () => {
|
|
1510
1526
|
AccordionPinnedContainer.displayName = "AccordionPinnedContainer";
|
|
1511
|
-
const classes = useStyles$
|
|
1527
|
+
const classes = useStyles$T();
|
|
1512
1528
|
const accordionCtx = useContext(AccordionContext);
|
|
1513
1529
|
return (jsx("div", { ref: accordionCtx?.pinnedContainerRef, className: classes.pinnedContainer, children: jsx(MessageBar$1, { className: classes.pinnedContainerEmpty, children: jsx(MessageBarBody, { children: "No pinned items" }) }) }));
|
|
1514
1530
|
};
|
|
@@ -1519,7 +1535,7 @@ const AccordionPinnedContainer = () => {
|
|
|
1519
1535
|
*/
|
|
1520
1536
|
const AccordionSearchBox = () => {
|
|
1521
1537
|
AccordionSearchBox.displayName = "AccordionSearchBox";
|
|
1522
|
-
const classes = useStyles$
|
|
1538
|
+
const classes = useStyles$T();
|
|
1523
1539
|
const accordionCtx = useContext(AccordionContext);
|
|
1524
1540
|
if (!accordionCtx?.features.search) {
|
|
1525
1541
|
return null;
|
|
@@ -1535,14 +1551,14 @@ const AccordionSearchBox = () => {
|
|
|
1535
1551
|
*/
|
|
1536
1552
|
const AccordionSection = (props) => {
|
|
1537
1553
|
AccordionSection.displayName = "AccordionSection";
|
|
1538
|
-
const classes = useStyles$
|
|
1554
|
+
const classes = useStyles$T();
|
|
1539
1555
|
return jsx("div", { className: classes.panelDiv, children: props.children });
|
|
1540
1556
|
};
|
|
1541
1557
|
const StringAccordion = Accordion$1;
|
|
1542
1558
|
const Accordion = forwardRef((props, ref) => {
|
|
1543
1559
|
Accordion.displayName = "Accordion";
|
|
1544
1560
|
const { children, highlightSections, ...rest } = props;
|
|
1545
|
-
const classes = useStyles$
|
|
1561
|
+
const classes = useStyles$T();
|
|
1546
1562
|
const { size } = useContext(ToolContext);
|
|
1547
1563
|
const accordionCtx = useAccordionContext(props);
|
|
1548
1564
|
const hasPinning = accordionCtx?.features.pinning ?? false;
|
|
@@ -1639,7 +1655,7 @@ const Collapse = (props) => {
|
|
|
1639
1655
|
return (jsx(Collapse$1, { visible: props.visible, orientation: props.orientation, unmountOnExit: true, children: jsx("div", { className: `${classes.collapseContent} ${props.orientation === "horizontal" ? classes.horizontal : classes.vertical}`, children: props.children }) }));
|
|
1640
1656
|
};
|
|
1641
1657
|
|
|
1642
|
-
const useStyles$
|
|
1658
|
+
const useStyles$S = makeStyles({
|
|
1643
1659
|
button: {
|
|
1644
1660
|
display: "flex",
|
|
1645
1661
|
alignItems: "center",
|
|
@@ -1657,7 +1673,7 @@ const ToggleButton = (props) => {
|
|
|
1657
1673
|
ToggleButton.displayName = "ToggleButton";
|
|
1658
1674
|
const { value, onChange, title, appearance = "subtle" } = props;
|
|
1659
1675
|
const { size } = useContext(ToolContext);
|
|
1660
|
-
const classes = useStyles$
|
|
1676
|
+
const classes = useStyles$S();
|
|
1661
1677
|
const [checked, setChecked] = useState(value);
|
|
1662
1678
|
const toggle = useCallback(() => {
|
|
1663
1679
|
setChecked((prevChecked) => {
|
|
@@ -1908,11 +1924,11 @@ const CompactModeSettingDescriptor = {
|
|
|
1908
1924
|
};
|
|
1909
1925
|
const UseDegreesSettingDescriptor = {
|
|
1910
1926
|
key: "UseDegrees",
|
|
1911
|
-
defaultValue:
|
|
1927
|
+
defaultValue: true,
|
|
1912
1928
|
};
|
|
1913
1929
|
const UseEulerSettingDescriptor = {
|
|
1914
1930
|
key: "UseEuler",
|
|
1915
|
-
defaultValue:
|
|
1931
|
+
defaultValue: true,
|
|
1916
1932
|
};
|
|
1917
1933
|
const DisableCopySettingDescriptor = {
|
|
1918
1934
|
key: "DisableCopy",
|
|
@@ -1996,7 +2012,7 @@ const UXContextProvider = (props) => {
|
|
|
1996
2012
|
function AsReadonlyArray(array) {
|
|
1997
2013
|
return array;
|
|
1998
2014
|
}
|
|
1999
|
-
const useStyles$
|
|
2015
|
+
const useStyles$R = makeStyles({
|
|
2000
2016
|
rootDiv: {
|
|
2001
2017
|
flex: 1,
|
|
2002
2018
|
overflow: "hidden",
|
|
@@ -2005,7 +2021,7 @@ const useStyles$Q = makeStyles({
|
|
|
2005
2021
|
},
|
|
2006
2022
|
});
|
|
2007
2023
|
function ExtensibleAccordion(props) {
|
|
2008
|
-
const classes = useStyles$
|
|
2024
|
+
const classes = useStyles$R();
|
|
2009
2025
|
const { children, sections, sectionContent, context, sectionsRef, ...rest } = props;
|
|
2010
2026
|
const defaultSections = useMemo(() => {
|
|
2011
2027
|
const defaultSections = [];
|
|
@@ -2130,7 +2146,7 @@ function ExtensibleAccordion(props) {
|
|
|
2130
2146
|
})] }) })) }));
|
|
2131
2147
|
}
|
|
2132
2148
|
|
|
2133
|
-
const useStyles$
|
|
2149
|
+
const useStyles$Q = makeStyles({
|
|
2134
2150
|
paneRootDiv: {
|
|
2135
2151
|
display: "flex",
|
|
2136
2152
|
flex: 1,
|
|
@@ -2143,7 +2159,7 @@ const useStyles$P = makeStyles({
|
|
|
2143
2159
|
*/
|
|
2144
2160
|
const SidePaneContainer = forwardRef((props, ref) => {
|
|
2145
2161
|
const { className, ...rest } = props;
|
|
2146
|
-
const classes = useStyles$
|
|
2162
|
+
const classes = useStyles$Q();
|
|
2147
2163
|
return (jsx("div", { className: mergeClasses(classes.paneRootDiv, className), ref: ref, ...rest, children: props.children }));
|
|
2148
2164
|
});
|
|
2149
2165
|
|
|
@@ -2393,7 +2409,7 @@ const Theme = (props) => {
|
|
|
2393
2409
|
return (jsx(FluentProvider, { theme: theme, applyStylesToPortals: applyStylesToPortals, ...rest, children: props.children }));
|
|
2394
2410
|
};
|
|
2395
2411
|
|
|
2396
|
-
const useStyles$
|
|
2412
|
+
const useStyles$P = makeStyles({
|
|
2397
2413
|
extensionTeachingPopover: {
|
|
2398
2414
|
maxWidth: "320px",
|
|
2399
2415
|
},
|
|
@@ -2404,7 +2420,7 @@ const useStyles$O = makeStyles({
|
|
|
2404
2420
|
* @returns The teaching moment popover.
|
|
2405
2421
|
*/
|
|
2406
2422
|
const TeachingMoment = ({ shouldDisplay, positioningRef, onOpenChange, title, description }) => {
|
|
2407
|
-
const classes = useStyles$
|
|
2423
|
+
const classes = useStyles$P();
|
|
2408
2424
|
return (jsx(TeachingPopover, { appearance: "brand", open: shouldDisplay, positioning: { positioningRef }, onOpenChange: onOpenChange, children: jsxs(TeachingPopoverSurface, { className: classes.extensionTeachingPopover, children: [jsx(TeachingPopoverHeader, { children: title }), jsx(TeachingPopoverBody, { children: description })] }) }));
|
|
2409
2425
|
};
|
|
2410
2426
|
|
|
@@ -2588,13 +2604,13 @@ function ConstructorFactory(constructor) {
|
|
|
2588
2604
|
return (...args) => new constructor(...args);
|
|
2589
2605
|
}
|
|
2590
2606
|
|
|
2591
|
-
const useStyles$
|
|
2607
|
+
const useStyles$O = makeStyles({
|
|
2592
2608
|
placeholderDiv: {
|
|
2593
2609
|
padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalM}`,
|
|
2594
2610
|
},
|
|
2595
2611
|
});
|
|
2596
2612
|
const PropertiesPane = (props) => {
|
|
2597
|
-
const classes = useStyles$
|
|
2613
|
+
const classes = useStyles$O();
|
|
2598
2614
|
const entity = props.context;
|
|
2599
2615
|
return entity != null ? (jsx(ExtensibleAccordion, { ...props })) : (jsx("div", { className: classes.placeholderDiv, children: jsx(Body1Strong, { italic: true, children: "No entity selected." }) }));
|
|
2600
2616
|
};
|
|
@@ -2896,7 +2912,7 @@ const RightSidePaneHeightAdjustSettingDescriptor = {
|
|
|
2896
2912
|
};
|
|
2897
2913
|
const RootComponentServiceIdentity = Symbol("RootComponent");
|
|
2898
2914
|
const ShellServiceIdentity = Symbol("ShellService");
|
|
2899
|
-
const useStyles$
|
|
2915
|
+
const useStyles$N = makeStyles({
|
|
2900
2916
|
mainView: {
|
|
2901
2917
|
flex: 1,
|
|
2902
2918
|
display: "flex",
|
|
@@ -3099,34 +3115,38 @@ const DockMenu = (props) => {
|
|
|
3099
3115
|
};
|
|
3100
3116
|
const PaneHeader = (props) => {
|
|
3101
3117
|
const { id, title, dockOptions } = props;
|
|
3102
|
-
const classes = useStyles$
|
|
3118
|
+
const classes = useStyles$N();
|
|
3103
3119
|
return (jsxs("div", { className: classes.paneHeaderDiv, children: [jsx(Subtitle2Stronger, { className: classes.paneHeaderText, children: title }), jsx(DockMenu, { sidePaneId: id, dockOptions: dockOptions, children: jsx(Button$1, { className: classes.paneHeaderButton, appearance: "transparent", icon: jsx(MoreHorizontalRegular, {}) }) })] }));
|
|
3104
3120
|
};
|
|
3105
3121
|
// This is a wrapper for an item in a toolbar that simply adds a teaching moment, which is useful for dynamically added items, possibly from extensions.
|
|
3106
|
-
const ToolbarItem = (
|
|
3107
|
-
|
|
3122
|
+
const ToolbarItem = (props) => {
|
|
3123
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3124
|
+
const { verticalLocation, horizontalLocation, id, component: Component, displayName } = props;
|
|
3125
|
+
const classes = useStyles$N();
|
|
3108
3126
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Bar/${verticalLocation}/${horizontalLocation}/${displayName ?? id}`), [displayName, id]);
|
|
3109
|
-
const teachingMoment = useTeachingMoment(
|
|
3110
|
-
|
|
3127
|
+
const teachingMoment = useTeachingMoment(props.teachingMoment === false);
|
|
3128
|
+
const title = typeof props.teachingMoment === "object" ? props.teachingMoment.title : (displayName ?? id);
|
|
3129
|
+
const description = typeof props.teachingMoment === "object" ? props.teachingMoment.description : `The "${displayName ?? id}" extension can be accessed here.`;
|
|
3130
|
+
return (jsxs(Fragment, { children: [jsx(TeachingMoment, { ...teachingMoment, shouldDisplay: teachingMoment.shouldDisplay, title: title, description: description }), jsx("div", { className: classes.barItem, ref: teachingMoment.targetRef, children: jsx(Component, {}) })] }));
|
|
3111
3131
|
};
|
|
3112
3132
|
// TODO: Handle overflow, possibly via https://react.fluentui.dev/?path=/docs/components-overflow--docs with priority.
|
|
3113
3133
|
// This component just renders a toolbar with left aligned toolbar items on the left and right aligned toolbar items on the right.
|
|
3114
3134
|
const Toolbar = ({ location, components }) => {
|
|
3115
|
-
const classes = useStyles$
|
|
3135
|
+
const classes = useStyles$N();
|
|
3116
3136
|
const leftComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "left"), [components]);
|
|
3117
3137
|
const rightComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "right"), [components]);
|
|
3118
|
-
return (jsx(Fragment, { children: components.length > 0 && (jsxs("div", { className: `${classes.bar} ${location === "top" ? classes.barTop : classes.barBottom}`, children: [jsx("div", { className: classes.barLeft, children: leftComponents.map((entry) => (jsx(ToolbarItem, { verticalLocation: location, horizontalLocation: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName,
|
|
3138
|
+
return (jsx(Fragment, { children: components.length > 0 && (jsxs("div", { className: `${classes.bar} ${location === "top" ? classes.barTop : classes.barBottom}`, children: [jsx("div", { className: classes.barLeft, children: leftComponents.map((entry) => (jsx(ToolbarItem, { verticalLocation: location, horizontalLocation: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, teachingMoment: entry.teachingMoment }, entry.key))) }), jsx("div", { className: classes.barRight, children: rightComponents.map((entry) => (jsx(ToolbarItem, { verticalLocation: location, horizontalLocation: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, teachingMoment: entry.teachingMoment }, entry.key))) })] })) }));
|
|
3119
3139
|
};
|
|
3120
3140
|
// This is a wrapper for a tab in a side pane that simply adds a teaching moment, which is useful for dynamically added items, possibly from extensions.
|
|
3121
3141
|
const SidePaneTab = (props) => {
|
|
3122
3142
|
const { location, id, isSelected, isFirst, isLast, dockOptions,
|
|
3123
3143
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3124
|
-
icon: Icon, title,
|
|
3125
|
-
const classes = useStyles$
|
|
3144
|
+
icon: Icon, title, } = props;
|
|
3145
|
+
const classes = useStyles$N();
|
|
3126
3146
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Pane/${location}/${title ?? id}`), [title, id]);
|
|
3127
|
-
const teachingMoment = useTeachingMoment(
|
|
3147
|
+
const teachingMoment = useTeachingMoment(props.teachingMoment === false);
|
|
3128
3148
|
const tabClass = mergeClasses(classes.tab, isSelected ? classes.selectedTab : classes.unselectedTab, isFirst ? classes.firstTab : undefined, isLast ? classes.lastTab : undefined);
|
|
3129
|
-
return (jsxs(Fragment, { children: [jsx(TeachingMoment, { ...teachingMoment, shouldDisplay: teachingMoment.shouldDisplay
|
|
3149
|
+
return (jsxs(Fragment, { children: [jsx(TeachingMoment, { ...teachingMoment, shouldDisplay: teachingMoment.shouldDisplay, title: typeof props.teachingMoment === "object" ? props.teachingMoment.title : (title ?? "Extension"), description: typeof props.teachingMoment === "object" ? props.teachingMoment.description : `The "${title ?? id}" extension can be accessed here.` }), jsx("div", { className: tabClass, children: jsx(DockMenu, { openOnContext: true, sidePaneId: id, dockOptions: dockOptions, children: jsx(Tooltip, { content: title ?? id, children: jsx(ToolbarRadioButton, { ref: teachingMoment.targetRef, appearance: "transparent", className: classes.tabRadioButton, name: "selectedTab", value: id, icon: {
|
|
3130
3150
|
children: jsx(Icon, {}),
|
|
3131
3151
|
} }) }) }) })] }));
|
|
3132
3152
|
};
|
|
@@ -3134,7 +3154,7 @@ const SidePaneTab = (props) => {
|
|
|
3134
3154
|
// In "compact" mode, the tab list is integrated into the pane itself.
|
|
3135
3155
|
// In "full" mode, the returned tab list is later injected into the toolbar.
|
|
3136
3156
|
function usePane(location, defaultWidth, minWidth, sidePanes, onSelectSidePane, dockOperations, toolbarMode, topBarItems, bottomBarItems, initialCollapsed) {
|
|
3137
|
-
const classes = useStyles$
|
|
3157
|
+
const classes = useStyles$N();
|
|
3138
3158
|
const [topSelectedTab, setTopSelectedTab] = useState();
|
|
3139
3159
|
const [bottomSelectedTab, setBottomSelectedTab] = useState();
|
|
3140
3160
|
const [collapsed, setCollapsed] = useState(initialCollapsed);
|
|
@@ -3236,7 +3256,7 @@ function usePane(location, defaultWidth, minWidth, sidePanes, onSelectSidePane,
|
|
|
3236
3256
|
setCollapsed(false);
|
|
3237
3257
|
}, children: paneComponents.map((entry, index) => {
|
|
3238
3258
|
const isSelected = selectedTab?.key === entry.key;
|
|
3239
|
-
return (jsx(SidePaneTab, { location: location, id: entry.key, title: entry.title, icon: entry.icon,
|
|
3259
|
+
return (jsx(SidePaneTab, { location: location, id: entry.key, title: entry.title, icon: entry.icon, teachingMoment: entry.teachingMoment, isSelected: isSelected && !collapsed, isFirst: index === 0, isLast: index === paneComponents.length - 1, dockOptions: dockOptions }, entry.key));
|
|
3240
3260
|
}) }) })), toolbarMode === "full" && (jsx(Collapse, { visible: !isChildWindowOpen, orientation: "horizontal", children: expandCollapseButton }))] })) }));
|
|
3241
3261
|
}, [location, collapsed, isChildWindowOpen, expandCollapseButton]);
|
|
3242
3262
|
// This memos the TabList to make it easy for the JSX to be inserted at the top of the pane (in "compact" mode) or returned to the caller to be used in the toolbar (in "full" mode).
|
|
@@ -3331,7 +3351,7 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
|
|
|
3331
3351
|
expand: () => onCollapseChanged.notifyObservers({ location: "right", collapsed: false }),
|
|
3332
3352
|
};
|
|
3333
3353
|
const rootComponent = () => {
|
|
3334
|
-
const classes = useStyles$
|
|
3354
|
+
const classes = useStyles$N();
|
|
3335
3355
|
const [sidePaneDockOverrides, setSidePaneDockOverrides] = useSetting(SidePaneDockOverridesSettingDescriptor);
|
|
3336
3356
|
// This function returns a promise that resolves after the dock change takes effect so that
|
|
3337
3357
|
// we can then select the re-docked pane.
|
|
@@ -3566,7 +3586,7 @@ const SettingsServiceDefinition = {
|
|
|
3566
3586
|
horizontalLocation: "right",
|
|
3567
3587
|
verticalLocation: "top",
|
|
3568
3588
|
order: 500,
|
|
3569
|
-
|
|
3589
|
+
teachingMoment: false,
|
|
3570
3590
|
content: () => {
|
|
3571
3591
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
3572
3592
|
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
@@ -3672,7 +3692,7 @@ const PropertiesServiceDefinition = {
|
|
|
3672
3692
|
horizontalLocation: "right",
|
|
3673
3693
|
verticalLocation: "top",
|
|
3674
3694
|
order: 100,
|
|
3675
|
-
|
|
3695
|
+
teachingMoment: false,
|
|
3676
3696
|
keepMounted: true,
|
|
3677
3697
|
content: () => {
|
|
3678
3698
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
@@ -4076,7 +4096,7 @@ function CoerceEntityArray(entities, sort) {
|
|
|
4076
4096
|
}
|
|
4077
4097
|
return entities;
|
|
4078
4098
|
}
|
|
4079
|
-
const useStyles$
|
|
4099
|
+
const useStyles$M = makeStyles({
|
|
4080
4100
|
rootDiv: {
|
|
4081
4101
|
flex: 1,
|
|
4082
4102
|
overflow: "hidden",
|
|
@@ -4184,14 +4204,14 @@ function MakeInlineCommandElement(command, isPlaceholder) {
|
|
|
4184
4204
|
}
|
|
4185
4205
|
const SceneTreeItem = (props) => {
|
|
4186
4206
|
const { isSelected, select } = props;
|
|
4187
|
-
const classes = useStyles$
|
|
4207
|
+
const classes = useStyles$M();
|
|
4188
4208
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
4189
4209
|
const treeItemLayoutClass = mergeClasses(classes.sceneTreeItemLayout, compactMode ? classes.treeItemLayoutCompact : undefined);
|
|
4190
4210
|
return (jsx(FlatTreeItem, { className: classes.treeItem, value: "scene", itemType: "leaf", parentValue: undefined, "aria-level": 1, "aria-setsize": 1, "aria-posinset": 1, onClick: select, children: jsx(TreeItemLayout, { iconBefore: jsx(GlobeRegular, {}), className: treeItemLayoutClass, style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, children: jsx(Body1Strong, { wrap: false, truncate: true, children: "Scene" }) }) }, "scene"));
|
|
4191
4211
|
};
|
|
4192
4212
|
const SectionTreeItem = (props) => {
|
|
4193
4213
|
const { section, isFiltering, commandProviders, expandAll, collapseAll, isDropTarget, ...dropProps } = props;
|
|
4194
|
-
const classes = useStyles$
|
|
4214
|
+
const classes = useStyles$M();
|
|
4195
4215
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
4196
4216
|
// Get the commands that apply to this section.
|
|
4197
4217
|
const commands = useResource(useCallback(() => {
|
|
@@ -4208,7 +4228,7 @@ const SectionTreeItem = (props) => {
|
|
|
4208
4228
|
};
|
|
4209
4229
|
const EntityTreeItem = (props) => {
|
|
4210
4230
|
const { entityItem, isSelected, select, isFiltering, commandProviders, expandAll, collapseAll, isDragging, isDropTarget, ...dragProps } = props;
|
|
4211
|
-
const classes = useStyles$
|
|
4231
|
+
const classes = useStyles$M();
|
|
4212
4232
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
4213
4233
|
const hasChildren = !!entityItem.children?.length;
|
|
4214
4234
|
const displayInfo = useResource(useCallback(() => {
|
|
@@ -4324,7 +4344,7 @@ const EntityTreeItem = (props) => {
|
|
|
4324
4344
|
}, children: jsx(Body1, { wrap: false, truncate: true, children: name }) }) }, GetEntityId(entityItem.entity)) }), jsx(MenuPopover, { hidden: !hasChildren && contextMenuCommands.length === 0, children: jsxs(MenuList, { children: [hasChildren && (jsxs(Fragment, { children: [jsx(MenuItem, { icon: jsx(ArrowExpandAllRegular, {}), onClick: expandAll, children: jsx(Body1, { children: "Expand All" }) }), jsx(MenuItem, { icon: jsx(ArrowCollapseAllRegular, {}), onClick: collapseAll, children: jsx(Body1, { children: "Collapse All" }) })] })), hasChildren && contextMenuCommands.length > 0 && jsx(MenuDivider, {}), contextMenuItems] }) })] }));
|
|
4325
4345
|
};
|
|
4326
4346
|
const SceneExplorer = (props) => {
|
|
4327
|
-
const classes = useStyles$
|
|
4347
|
+
const classes = useStyles$M();
|
|
4328
4348
|
const { sections, entityCommandProviders, sectionCommandProviders, scene, selectedEntity = null } = props;
|
|
4329
4349
|
const [openItems, setOpenItems] = useState(new Set());
|
|
4330
4350
|
const [sceneVersion, setSceneVersion] = useState(0);
|
|
@@ -4617,7 +4637,7 @@ const SceneExplorerServiceDefinition = {
|
|
|
4617
4637
|
icon: CubeTreeRegular,
|
|
4618
4638
|
horizontalLocation: "left",
|
|
4619
4639
|
verticalLocation: "top",
|
|
4620
|
-
|
|
4640
|
+
teachingMoment: false,
|
|
4621
4641
|
keepMounted: true,
|
|
4622
4642
|
content: () => {
|
|
4623
4643
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
@@ -4778,7 +4798,7 @@ const DebugServiceDefinition = {
|
|
|
4778
4798
|
horizontalLocation: "right",
|
|
4779
4799
|
verticalLocation: "top",
|
|
4780
4800
|
order: 200,
|
|
4781
|
-
|
|
4801
|
+
teachingMoment: false,
|
|
4782
4802
|
content: () => {
|
|
4783
4803
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
4784
4804
|
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
@@ -5947,7 +5967,7 @@ class CanvasGraphService {
|
|
|
5947
5967
|
}
|
|
5948
5968
|
}
|
|
5949
5969
|
|
|
5950
|
-
const useStyles$
|
|
5970
|
+
const useStyles$L = makeStyles({
|
|
5951
5971
|
canvas: {
|
|
5952
5972
|
flexGrow: 1,
|
|
5953
5973
|
width: "100%",
|
|
@@ -5956,7 +5976,7 @@ const useStyles$K = makeStyles({
|
|
|
5956
5976
|
});
|
|
5957
5977
|
const CanvasGraph = (props) => {
|
|
5958
5978
|
const { collector, scene, layoutObservable, returnToPlayheadObservable, onVisibleRangeChangedObservable, initialGraphSize } = props;
|
|
5959
|
-
const classes = useStyles$
|
|
5979
|
+
const classes = useStyles$L();
|
|
5960
5980
|
const canvasRef = useRef(null);
|
|
5961
5981
|
useEffect(() => {
|
|
5962
5982
|
if (!canvasRef.current) {
|
|
@@ -6010,135 +6030,208 @@ const CanvasGraph = (props) => {
|
|
|
6010
6030
|
return jsx("canvas", { className: classes.canvas, ref: canvasRef });
|
|
6011
6031
|
};
|
|
6012
6032
|
|
|
6013
|
-
function CoerceStepValue(step,
|
|
6014
|
-
// When the
|
|
6015
|
-
if (
|
|
6033
|
+
function CoerceStepValue(step, isFineKeyPressed, isCourseKeyPressed) {
|
|
6034
|
+
// When the fine key is pressed, decrease step by a factor of 10.
|
|
6035
|
+
if (isFineKeyPressed) {
|
|
6016
6036
|
return step * 0.1;
|
|
6017
6037
|
}
|
|
6018
|
-
// When the
|
|
6019
|
-
if (
|
|
6038
|
+
// When the course key is pressed, increase step by a factor of 10.
|
|
6039
|
+
if (isCourseKeyPressed) {
|
|
6020
6040
|
return step * 10;
|
|
6021
6041
|
}
|
|
6022
6042
|
return step;
|
|
6023
6043
|
}
|
|
6044
|
+
// Allow arbitrary expressions, primarily for math operations (e.g. 10*60 for 10 minutes in seconds).
|
|
6045
|
+
// Use Function constructor to safely evaluate the expression without allowing access to scope.
|
|
6046
|
+
// If the expression is invalid, fallback to NaN which will be caught by validateValue and prevent committing.
|
|
6047
|
+
function EvaluateExpression(rawValue) {
|
|
6048
|
+
const val = rawValue.trim();
|
|
6049
|
+
try {
|
|
6050
|
+
return Number(Function(`"use strict";return (${val})`)());
|
|
6051
|
+
}
|
|
6052
|
+
catch {
|
|
6053
|
+
return NaN;
|
|
6054
|
+
}
|
|
6055
|
+
}
|
|
6056
|
+
const useStyles$K = makeStyles({
|
|
6057
|
+
icon: {
|
|
6058
|
+
"&:hover": {
|
|
6059
|
+
color: tokens.colorBrandForeground1,
|
|
6060
|
+
},
|
|
6061
|
+
},
|
|
6062
|
+
});
|
|
6063
|
+
/**
|
|
6064
|
+
* A numeric input with a vertical drag-to-scrub icon (ArrowsBidirectionalRegular rotated 90°).
|
|
6065
|
+
* Click-and-drag up/down on the icon to increment/decrement the value.
|
|
6066
|
+
*/
|
|
6024
6067
|
const SpinButton = forwardRef((props, ref) => {
|
|
6025
|
-
SpinButton.displayName = "
|
|
6026
|
-
const
|
|
6068
|
+
SpinButton.displayName = "SpinButton2";
|
|
6069
|
+
const inputClasses = useInputStyles$1();
|
|
6070
|
+
const classes = useStyles$K();
|
|
6027
6071
|
const { size } = useContext(ToolContext);
|
|
6028
6072
|
const { min, max } = props;
|
|
6029
|
-
const
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
const
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
const
|
|
6036
|
-
const
|
|
6037
|
-
// step and forceInt are not mutually exclusive since there could be cases where you want to forceInt but have spinButton jump >1 int per spin
|
|
6038
|
-
const step = CoerceStepValue(props.step ?? 1, isUnfocusedAltKeyPressed || isFocusedAltKeyPressed, isUnfocusedShiftKeyPressed || isFocusedShiftKeyPressed);
|
|
6073
|
+
const baseStep = props.step ?? 1;
|
|
6074
|
+
// Local ref for the input element so we can blur it programmatically (e.g. when a drag starts while editing).
|
|
6075
|
+
const inputRef = useRef(null);
|
|
6076
|
+
const mergedRef = useMergedRefs(ref, inputRef);
|
|
6077
|
+
// Modifier keys for step coercion.
|
|
6078
|
+
const isAltKeyPressed = useKeyState("Alt", { preventDefault: true });
|
|
6079
|
+
const isShiftKeyPressed = useKeyState("Shift");
|
|
6080
|
+
const step = CoerceStepValue(baseStep, isAltKeyPressed, isShiftKeyPressed);
|
|
6039
6081
|
const stepPrecision = Math.max(0, CalculatePrecision(step));
|
|
6040
|
-
const
|
|
6041
|
-
|
|
6042
|
-
const
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
const
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6082
|
+
const [value, setValue] = useState(props.value ?? 0);
|
|
6083
|
+
const lastCommittedValue = useRef(props.value);
|
|
6084
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
6085
|
+
const scrubStartYRef = useRef(0);
|
|
6086
|
+
const scrubStartValueRef = useRef(0);
|
|
6087
|
+
const lastPointerYRef = useRef(0);
|
|
6088
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
6089
|
+
// Editing state: when the user is typing, we show their raw text rather than the formatted value.
|
|
6090
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
6091
|
+
const [editText, setEditText] = useState("");
|
|
6092
|
+
const valuePrecision = Math.max(0, CalculatePrecision(value));
|
|
6093
|
+
// Display precision: controls how many decimals are shown in the formatted displayValue. Cap at 4 to avoid wild numbers.
|
|
6094
|
+
// If a fixed precision prop is provided, use it instead.
|
|
6095
|
+
const displayPrecision = props.precision ?? Math.min(4, Math.max(stepPrecision, valuePrecision));
|
|
6096
|
+
// Format a number for display: toFixed, then trim trailing zeros and period unless a fixed precision is specified.
|
|
6097
|
+
const formatValue = useCallback((v) => {
|
|
6098
|
+
const fixed = v.toFixed(displayPrecision);
|
|
6099
|
+
if (props.precision !== undefined) {
|
|
6100
|
+
return fixed;
|
|
6101
|
+
}
|
|
6102
|
+
return fixed.replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
|
|
6103
|
+
}, [displayPrecision, props.precision]);
|
|
6104
|
+
useEffect(() => {
|
|
6105
|
+
if (!isDragging && props.value !== lastCommittedValue.current) {
|
|
6106
|
+
lastCommittedValue.current = props.value;
|
|
6107
|
+
setValue(props.value ?? 0);
|
|
6050
6108
|
}
|
|
6051
|
-
}, [props.value]);
|
|
6052
|
-
const validateValue = (numericValue) => {
|
|
6109
|
+
}, [props.value, isDragging]);
|
|
6110
|
+
const validateValue = useCallback((numericValue) => {
|
|
6053
6111
|
const outOfBounds = (min !== undefined && numericValue < min) || (max !== undefined && numericValue > max);
|
|
6054
6112
|
const failsValidator = props.validator && !props.validator(numericValue);
|
|
6055
6113
|
const failsIntCheck = props.forceInt ? !Number.isInteger(numericValue) : false;
|
|
6056
6114
|
const invalid = !!outOfBounds || !!failsValidator || isNaN(numericValue) || !!failsIntCheck;
|
|
6057
6115
|
return !invalid;
|
|
6058
|
-
};
|
|
6059
|
-
|
|
6060
|
-
|
|
6116
|
+
}, [min, max, props.validator, props.forceInt]);
|
|
6117
|
+
// Constrain a value to the valid range by clamping to [min, max].
|
|
6118
|
+
const constrainValue = useCallback((v) => Clamp(v, min ?? -Infinity, max ?? Infinity), [min, max]);
|
|
6119
|
+
const tryCommitValue = useCallback((currVal) => {
|
|
6061
6120
|
if (validateValue(currVal) && currVal !== lastCommittedValue.current) {
|
|
6062
6121
|
lastCommittedValue.current = currVal;
|
|
6063
6122
|
props.onChange(currVal);
|
|
6064
6123
|
}
|
|
6065
|
-
};
|
|
6066
|
-
const
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
const regex = new RegExp("\\s*" + props.unit + "$");
|
|
6079
|
-
const match = val.match(regex);
|
|
6080
|
-
if (match) {
|
|
6081
|
-
return val.slice(0, -match[0].length);
|
|
6082
|
-
}
|
|
6083
|
-
return val;
|
|
6084
|
-
};
|
|
6085
|
-
// Allow arbitrary expressions, primarily for math operations (e.g. 10*60 for 10 minutes in seconds).
|
|
6086
|
-
// Use Function constructor to safely evaluate the expression without allowing access to scope.
|
|
6087
|
-
// If the expression is invalid, fallback to NaN which will be caught by validateValue and prevent committing.
|
|
6088
|
-
const evaluateExpression = (rawValue) => {
|
|
6089
|
-
const val = stripUnit(rawValue).trim();
|
|
6090
|
-
try {
|
|
6091
|
-
return Number(Function(`"use strict";return (${val})`)());
|
|
6092
|
-
}
|
|
6093
|
-
catch {
|
|
6094
|
-
return NaN;
|
|
6124
|
+
}, [validateValue, props.onChange]);
|
|
6125
|
+
const handleInputChange = useCallback((_, data) => {
|
|
6126
|
+
// Just update the raw text — no evaluation or commit until Enter/blur.
|
|
6127
|
+
setEditText(data.value);
|
|
6128
|
+
}, []);
|
|
6129
|
+
// Evaluate the current edit text and commit the value. Returns the clamped value if valid, or undefined.
|
|
6130
|
+
const commitEditText = useCallback((text) => {
|
|
6131
|
+
const numericValue = EvaluateExpression(text);
|
|
6132
|
+
if (!isNaN(numericValue) && validateValue(numericValue)) {
|
|
6133
|
+
const constrained = constrainValue(numericValue);
|
|
6134
|
+
setValue(constrained);
|
|
6135
|
+
tryCommitValue(constrained);
|
|
6136
|
+
return constrained;
|
|
6095
6137
|
}
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6138
|
+
return undefined;
|
|
6139
|
+
}, [validateValue, constrainValue, tryCommitValue]);
|
|
6140
|
+
const handleIconPointerDown = useCallback((e) => {
|
|
6141
|
+
e.preventDefault();
|
|
6142
|
+
e.stopPropagation();
|
|
6143
|
+
// If the input was being edited, commit the current text and blur the input
|
|
6144
|
+
// so the focus state stays consistent after the drag ends.
|
|
6145
|
+
let startValue = value;
|
|
6146
|
+
if (isEditing) {
|
|
6147
|
+
const committed = commitEditText(editText);
|
|
6148
|
+
if (committed !== undefined) {
|
|
6149
|
+
startValue = committed;
|
|
6150
|
+
}
|
|
6151
|
+
setIsEditing(false);
|
|
6152
|
+
}
|
|
6153
|
+
// Blur the active element to ensure we can observe document level modifier keys.
|
|
6154
|
+
inputRef.current?.ownerDocument.activeElement?.blur?.();
|
|
6155
|
+
setIsDragging(true);
|
|
6156
|
+
scrubStartYRef.current = e.clientY;
|
|
6157
|
+
scrubStartValueRef.current = startValue;
|
|
6158
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
6159
|
+
}, [value, isEditing, editText, commitEditText]);
|
|
6160
|
+
// When the step size changes during a drag (e.g. Shift/Alt pressed or released), reset the scrub reference point
|
|
6161
|
+
// to the current value and pointer position so only future movement uses the new step.
|
|
6162
|
+
useEffect(() => {
|
|
6163
|
+
if (isDragging) {
|
|
6164
|
+
scrubStartValueRef.current = value;
|
|
6165
|
+
scrubStartYRef.current = lastPointerYRef.current;
|
|
6100
6166
|
}
|
|
6101
|
-
|
|
6102
|
-
|
|
6167
|
+
}, [step]);
|
|
6168
|
+
const handleIconPointerMove = useCallback((e) => {
|
|
6169
|
+
if (!isDragging) {
|
|
6170
|
+
return;
|
|
6103
6171
|
}
|
|
6104
|
-
|
|
6105
|
-
//
|
|
6172
|
+
lastPointerYRef.current = e.clientY;
|
|
6173
|
+
// Dragging up (negative dy) should increment, dragging down should decrement.
|
|
6174
|
+
// Scale delta by step but round to display precision (not step) for smooth fine-grained control.
|
|
6175
|
+
const dy = scrubStartYRef.current - e.clientY;
|
|
6176
|
+
// 5 is just a number that "feels right" for the drag sensitivity — it determines how far the user needs to drag to change the value by 1 step.
|
|
6177
|
+
const delta = (dy * step) / 5;
|
|
6178
|
+
const raw = scrubStartValueRef.current + delta;
|
|
6179
|
+
const precisionFactor = Math.pow(10, displayPrecision);
|
|
6180
|
+
const rounded = Math.round(raw * precisionFactor) / precisionFactor;
|
|
6181
|
+
const constrained = constrainValue(rounded);
|
|
6182
|
+
setValue(constrained);
|
|
6183
|
+
tryCommitValue(constrained);
|
|
6184
|
+
}, [isDragging, step, displayPrecision, constrainValue, tryCommitValue]);
|
|
6185
|
+
const handleIconPointerUp = useCallback((e) => {
|
|
6186
|
+
setIsDragging(false);
|
|
6187
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
6188
|
+
}, []);
|
|
6189
|
+
const handleKeyDown = useCallback((event) => {
|
|
6190
|
+
// Commit on Enter and blur the input if the value is valid.
|
|
6106
6191
|
if (event.key === "Enter") {
|
|
6107
|
-
const
|
|
6108
|
-
if (
|
|
6109
|
-
|
|
6110
|
-
tryCommitValue(currVal);
|
|
6192
|
+
const committed = commitEditText(event.currentTarget.value);
|
|
6193
|
+
if (committed !== undefined) {
|
|
6194
|
+
inputRef.current?.blur();
|
|
6111
6195
|
}
|
|
6112
6196
|
}
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
setIsFocusedShiftKeyPressed(false);
|
|
6197
|
+
if (event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
6198
|
+
event.preventDefault();
|
|
6199
|
+
const direction = event.key === "ArrowUp" ? 1 : -1;
|
|
6200
|
+
const newValue = constrainValue(Math.round((value + direction * step) / step) * step);
|
|
6201
|
+
setValue(newValue);
|
|
6202
|
+
tryCommitValue(newValue);
|
|
6203
|
+
// Update edit text to reflect the new value so the user sees the change
|
|
6204
|
+
setEditText(formatValue(newValue));
|
|
6122
6205
|
}
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6206
|
+
HandleKeyDown(event);
|
|
6207
|
+
}, [value, step, constrainValue, tryCommitValue, commitEditText, formatValue]);
|
|
6208
|
+
const id = useId("spin-button2");
|
|
6209
|
+
// Real-time validation: when editing, validate the expression; otherwise validate the committed value.
|
|
6210
|
+
// (validateValue already handles NaN, so no separate isNaN check needed.)
|
|
6211
|
+
const isInputInvalid = !validateValue(isEditing ? EvaluateExpression(editText) : value);
|
|
6212
|
+
const mergedClassName = mergeClasses(inputClasses.input, isInputInvalid ? inputClasses.invalid : "", props.className);
|
|
6213
|
+
const inputSlotClassName = mergeClasses(inputClasses.inputSlot, props.inputClassName);
|
|
6214
|
+
const formattedValue = formatValue(value);
|
|
6215
|
+
const handleFocus = useCallback(() => {
|
|
6216
|
+
setIsEditing(true);
|
|
6217
|
+
setEditText(formattedValue);
|
|
6218
|
+
}, [formattedValue]);
|
|
6219
|
+
const handleBlur = useCallback((event) => {
|
|
6220
|
+
// Skip blur handling if a drag just started (icon pointerDown already committed).
|
|
6221
|
+
if (isDragging) {
|
|
6126
6222
|
return;
|
|
6127
6223
|
}
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
};
|
|
6140
|
-
const spinButton = (jsx(SpinButton$1, { ref: ref, ...props, appearance: "outline", input: inputSlot, step: step, id: id, size: size, precision: fluentPrecision, displayValue: `${value.toFixed(displayPrecision)}${props.unit ? " " + props.unit : ""}`, value: value, onChange: handleChange, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, onBlur: HandleOnBlur, className: mergedClassName }));
|
|
6141
|
-
return props.infoLabel ? (jsxs("div", { className: classes.container, children: [jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), spinButton] })) : (spinButton);
|
|
6224
|
+
commitEditText(event.target.value);
|
|
6225
|
+
setIsEditing(false);
|
|
6226
|
+
HandleOnBlur(event);
|
|
6227
|
+
}, [commitEditText, isDragging]);
|
|
6228
|
+
const contentBefore = !props.disableDragButton && (isHovered || isDragging) && !isInputInvalid ? (jsx(ArrowBidirectionalUpDownFilled, { className: classes.icon, style: { cursor: isDragging ? "ns-resize" : "pointer" }, onPointerDown: handleIconPointerDown, onPointerMove: handleIconPointerMove, onPointerUp: handleIconPointerUp })) : undefined;
|
|
6229
|
+
const input = (jsx("div", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => {
|
|
6230
|
+
if (!isDragging) {
|
|
6231
|
+
setIsHovered(false);
|
|
6232
|
+
}
|
|
6233
|
+
}, children: jsx(Input, { ref: mergedRef, id: id, appearance: "outline", size: size, className: mergedClassName, input: { className: inputSlotClassName }, value: isEditing ? editText : formattedValue, onChange: handleInputChange, onFocus: handleFocus, onKeyDown: handleKeyDown, onBlur: handleBlur, contentBefore: contentBefore, contentAfter: props.unit }) }));
|
|
6234
|
+
return props.infoLabel ? (jsxs("div", { className: inputClasses.container, children: [jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), input] })) : (input);
|
|
6142
6235
|
});
|
|
6143
6236
|
|
|
6144
6237
|
const TextInput = (props) => {
|
|
@@ -6820,7 +6913,7 @@ const StatsServiceDefinition = {
|
|
|
6820
6913
|
horizontalLocation: "right",
|
|
6821
6914
|
verticalLocation: "top",
|
|
6822
6915
|
order: 300,
|
|
6823
|
-
|
|
6916
|
+
teachingMoment: false,
|
|
6824
6917
|
content: () => {
|
|
6825
6918
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
6826
6919
|
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
@@ -6909,7 +7002,7 @@ const ToolsServiceDefinition = {
|
|
|
6909
7002
|
horizontalLocation: "right",
|
|
6910
7003
|
verticalLocation: "top",
|
|
6911
7004
|
order: 400,
|
|
6912
|
-
|
|
7005
|
+
teachingMoment: false,
|
|
6913
7006
|
content: () => {
|
|
6914
7007
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
6915
7008
|
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
@@ -6927,12 +7020,337 @@ const ToolsServiceDefinition = {
|
|
|
6927
7020
|
},
|
|
6928
7021
|
};
|
|
6929
7022
|
|
|
7023
|
+
const useStyles$F = makeStyles({
|
|
7024
|
+
dropdown: {
|
|
7025
|
+
...UniformWidthStyling,
|
|
7026
|
+
},
|
|
7027
|
+
});
|
|
7028
|
+
/**
|
|
7029
|
+
* Wraps a dropdown in a property line
|
|
7030
|
+
* @param props - PropertyLineProps and DropdownProps
|
|
7031
|
+
* @returns property-line wrapped dropdown
|
|
7032
|
+
*/
|
|
7033
|
+
const DropdownPropertyLine = forwardRef((props, ref) => {
|
|
7034
|
+
DropdownPropertyLine.displayName = "DropdownPropertyLine";
|
|
7035
|
+
const classes = useStyles$F();
|
|
7036
|
+
return (jsx(PropertyLine, { ...props, ref: ref, children: jsx(Dropdown, { ...props, className: classes.dropdown }) }));
|
|
7037
|
+
});
|
|
7038
|
+
/**
|
|
7039
|
+
* Dropdown component for number values.
|
|
7040
|
+
*/
|
|
7041
|
+
const NumberDropdownPropertyLine = DropdownPropertyLine;
|
|
7042
|
+
/**
|
|
7043
|
+
* Dropdown component for string values
|
|
7044
|
+
*/
|
|
7045
|
+
const StringDropdownPropertyLine = DropdownPropertyLine;
|
|
7046
|
+
|
|
7047
|
+
/**
|
|
7048
|
+
* A slider primitive that wraps the Fluent UI Slider with step scaling, drag tracking, and optional notify-on-release behavior.
|
|
7049
|
+
* Follows the same pattern as other primitives (e.g. Switch) — no wrapper divs, just the Fluent component with logic.
|
|
7050
|
+
* @param props
|
|
7051
|
+
* @returns Slider component
|
|
7052
|
+
*/
|
|
7053
|
+
const Slider = (props) => {
|
|
7054
|
+
Slider.displayName = "Slider";
|
|
7055
|
+
const { size } = useContext(ToolContext);
|
|
7056
|
+
const [value, setValue] = useState(props.value ?? 0);
|
|
7057
|
+
const pendingValueRef = useRef(undefined);
|
|
7058
|
+
const isDraggingRef = useRef(false);
|
|
7059
|
+
// NOTE: The Fluent slider will add tick marks if the step prop is anything other than undefined.
|
|
7060
|
+
// To avoid this, we scale the min/max based on the step so we can always make step undefined.
|
|
7061
|
+
// The actual step size in the Fluent slider is 1 when it is set to undefined.
|
|
7062
|
+
const min = props.min ?? 0;
|
|
7063
|
+
const max = props.max ?? 100;
|
|
7064
|
+
const step = props.step ?? 1;
|
|
7065
|
+
useEffect(() => {
|
|
7066
|
+
!isDraggingRef.current && setValue(props.value ?? 0); // Update local state when props.value changes as long as user is not actively dragging
|
|
7067
|
+
}, [props.value]);
|
|
7068
|
+
const handleSliderChange = (_, data) => {
|
|
7069
|
+
const newValue = data.value * step;
|
|
7070
|
+
setValue(newValue);
|
|
7071
|
+
if (props.notifyOnlyOnRelease) {
|
|
7072
|
+
// Store the value but don't notify parent yet
|
|
7073
|
+
pendingValueRef.current = newValue;
|
|
7074
|
+
}
|
|
7075
|
+
else {
|
|
7076
|
+
// Notify parent as slider changes
|
|
7077
|
+
props.onChange(newValue);
|
|
7078
|
+
}
|
|
7079
|
+
};
|
|
7080
|
+
const handleSliderPointerDown = () => {
|
|
7081
|
+
isDraggingRef.current = true;
|
|
7082
|
+
};
|
|
7083
|
+
const handleSliderPointerUp = () => {
|
|
7084
|
+
if (props.notifyOnlyOnRelease && isDraggingRef.current && pendingValueRef.current !== undefined) {
|
|
7085
|
+
props.onChange(pendingValueRef.current);
|
|
7086
|
+
pendingValueRef.current = undefined;
|
|
7087
|
+
}
|
|
7088
|
+
isDraggingRef.current = false;
|
|
7089
|
+
};
|
|
7090
|
+
return (jsx(Slider$1, { className: props.className, size: size, min: min / step, max: max / step, step: undefined, value: value / step, disabled: props.disabled, onChange: handleSliderChange, onPointerDown: () => {
|
|
7091
|
+
handleSliderPointerDown();
|
|
7092
|
+
props.onPointerDown?.();
|
|
7093
|
+
}, onPointerUp: () => {
|
|
7094
|
+
handleSliderPointerUp();
|
|
7095
|
+
props.onPointerUp?.();
|
|
7096
|
+
} }));
|
|
7097
|
+
};
|
|
7098
|
+
|
|
7099
|
+
const useSyncedSliderStyles = makeStyles({
|
|
7100
|
+
container: { display: "flex", minWidth: 0 },
|
|
7101
|
+
syncedSlider: {
|
|
7102
|
+
flex: "1 1 0",
|
|
7103
|
+
flexDirection: "row",
|
|
7104
|
+
display: "flex",
|
|
7105
|
+
alignItems: "center",
|
|
7106
|
+
minWidth: 0,
|
|
7107
|
+
},
|
|
7108
|
+
slider: {
|
|
7109
|
+
flex: "1 1 auto",
|
|
7110
|
+
minWidth: "75px",
|
|
7111
|
+
maxWidth: "75px",
|
|
7112
|
+
},
|
|
7113
|
+
compactSlider: {
|
|
7114
|
+
flex: "1 1 auto",
|
|
7115
|
+
minWidth: "50px", // Allow shrinking for compact mode
|
|
7116
|
+
maxWidth: "75px",
|
|
7117
|
+
},
|
|
7118
|
+
growSlider: {
|
|
7119
|
+
flex: "1 1 auto",
|
|
7120
|
+
minWidth: "50px",
|
|
7121
|
+
// No maxWidth - slider grows to fill available space
|
|
7122
|
+
},
|
|
7123
|
+
compactSpinButton: {
|
|
7124
|
+
width: "65px",
|
|
7125
|
+
minWidth: "65px",
|
|
7126
|
+
maxWidth: "65px",
|
|
7127
|
+
},
|
|
7128
|
+
compactSpinButtonInput: {
|
|
7129
|
+
minWidth: "0",
|
|
7130
|
+
},
|
|
7131
|
+
});
|
|
7132
|
+
/**
|
|
7133
|
+
* Component which synchronizes a slider and an input field, allowing the user to change the value using either control
|
|
7134
|
+
* @param props
|
|
7135
|
+
* @returns SyncedSlider component
|
|
7136
|
+
*/
|
|
7137
|
+
const SyncedSliderInput = (props) => {
|
|
7138
|
+
SyncedSliderInput.displayName = "SyncedSliderInput";
|
|
7139
|
+
const { infoLabel, ...passthroughProps } = props;
|
|
7140
|
+
const classes = useSyncedSliderStyles();
|
|
7141
|
+
const [value, setValue] = useState(props.value ?? 0);
|
|
7142
|
+
const pendingValueRef = useRef(undefined);
|
|
7143
|
+
const isDraggingRef = useRef(false);
|
|
7144
|
+
useEffect(() => {
|
|
7145
|
+
!isDraggingRef.current && setValue(props.value ?? 0); // Update local state when props.value changes as long as user is not actively dragging
|
|
7146
|
+
}, [props.value]);
|
|
7147
|
+
const handleSliderChange = (newValue) => {
|
|
7148
|
+
setValue(newValue);
|
|
7149
|
+
if (props.notifyOnlyOnRelease) {
|
|
7150
|
+
// Store the value but don't notify parent yet
|
|
7151
|
+
pendingValueRef.current = newValue;
|
|
7152
|
+
}
|
|
7153
|
+
else {
|
|
7154
|
+
// Notify parent as slider changes
|
|
7155
|
+
props.onChange(newValue);
|
|
7156
|
+
}
|
|
7157
|
+
};
|
|
7158
|
+
const handleSliderPointerDown = () => {
|
|
7159
|
+
isDraggingRef.current = true;
|
|
7160
|
+
};
|
|
7161
|
+
const handleSliderPointerUp = () => {
|
|
7162
|
+
if (props.notifyOnlyOnRelease && isDraggingRef.current && pendingValueRef.current !== undefined) {
|
|
7163
|
+
props.onChange(pendingValueRef.current);
|
|
7164
|
+
pendingValueRef.current = undefined;
|
|
7165
|
+
}
|
|
7166
|
+
isDraggingRef.current = false;
|
|
7167
|
+
};
|
|
7168
|
+
const handleInputChange = (value) => {
|
|
7169
|
+
setValue(value);
|
|
7170
|
+
props.onChange(value); // Input always updates immediately
|
|
7171
|
+
};
|
|
7172
|
+
const hasSlider = props.min !== undefined && props.max !== undefined;
|
|
7173
|
+
// Determine Slider className based on props
|
|
7174
|
+
const getSliderClassName = () => {
|
|
7175
|
+
if (props.growSlider) {
|
|
7176
|
+
return classes.growSlider;
|
|
7177
|
+
}
|
|
7178
|
+
if (props.compact) {
|
|
7179
|
+
return classes.compactSlider;
|
|
7180
|
+
}
|
|
7181
|
+
return classes.slider;
|
|
7182
|
+
};
|
|
7183
|
+
return (jsxs("div", { className: classes.container, children: [infoLabel && jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [hasSlider && (jsx(Slider, { className: getSliderClassName(), value: value, onChange: handleSliderChange, min: props.min, max: props.max, step: props.step, disabled: props.disabled, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), jsx(SpinButton, { ...passthroughProps, className: hasSlider || props.compact ? classes.compactSpinButton : undefined, inputClassName: hasSlider || props.compact ? classes.compactSpinButtonInput : undefined, value: value, onChange: handleInputChange, step: props.step, disableDragButton: true })] })] }));
|
|
7184
|
+
};
|
|
7185
|
+
|
|
7186
|
+
/**
|
|
7187
|
+
* Renders a simple wrapper around the SyncedSliderInput
|
|
7188
|
+
* @param props
|
|
7189
|
+
* @returns
|
|
7190
|
+
*/
|
|
7191
|
+
const SyncedSliderPropertyLine = forwardRef((props, ref) => {
|
|
7192
|
+
SyncedSliderPropertyLine.displayName = "SyncedSliderPropertyLine";
|
|
7193
|
+
const { label, description, ...sliderProps } = props;
|
|
7194
|
+
return (jsx(PropertyLine, { ref: ref, ...props, children: jsx(SyncedSliderInput, { ...sliderProps }) }));
|
|
7195
|
+
});
|
|
7196
|
+
|
|
7197
|
+
const WatcherSettingDescriptor = {
|
|
7198
|
+
key: "WatcherSettings",
|
|
7199
|
+
defaultValue: {
|
|
7200
|
+
mode: "intercept",
|
|
7201
|
+
},
|
|
7202
|
+
};
|
|
7203
|
+
const WatcherServiceIdentity = Symbol("WatcherService");
|
|
7204
|
+
const WatcherServiceDefinition = {
|
|
7205
|
+
friendlyName: "Watcher Service",
|
|
7206
|
+
produces: [WatcherServiceIdentity],
|
|
7207
|
+
consumes: [SettingsStoreIdentity],
|
|
7208
|
+
factory: (settingsStore) => {
|
|
7209
|
+
let refreshObservable = null;
|
|
7210
|
+
let pollingHandle = null;
|
|
7211
|
+
const applySettings = () => {
|
|
7212
|
+
const settings = settingsStore.readSetting(WatcherSettingDescriptor);
|
|
7213
|
+
if (pollingHandle !== null) {
|
|
7214
|
+
clearInterval(pollingHandle);
|
|
7215
|
+
pollingHandle = null;
|
|
7216
|
+
}
|
|
7217
|
+
if (settings.mode === "intercept") {
|
|
7218
|
+
if (refreshObservable) {
|
|
7219
|
+
refreshObservable.clear();
|
|
7220
|
+
refreshObservable = null;
|
|
7221
|
+
}
|
|
7222
|
+
}
|
|
7223
|
+
else {
|
|
7224
|
+
const pollingObservable = refreshObservable ?? (refreshObservable = new Observable());
|
|
7225
|
+
if (settings.mode === "polling") {
|
|
7226
|
+
pollingHandle = window.setInterval(() => {
|
|
7227
|
+
pollingObservable.notifyObservers();
|
|
7228
|
+
}, settings.interval);
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
};
|
|
7232
|
+
const settingsStoreObserver = settingsStore.onChanged.add((key) => {
|
|
7233
|
+
if (key === WatcherSettingDescriptor.key) {
|
|
7234
|
+
applySettings();
|
|
7235
|
+
}
|
|
7236
|
+
});
|
|
7237
|
+
applySettings();
|
|
7238
|
+
return {
|
|
7239
|
+
watchProperty(target, propertyKey, onChanged) {
|
|
7240
|
+
if (refreshObservable) {
|
|
7241
|
+
let previousValue = target[propertyKey];
|
|
7242
|
+
const observer = refreshObservable.add(() => {
|
|
7243
|
+
const currentValue = target[propertyKey];
|
|
7244
|
+
if (!Object.is(previousValue, currentValue)) {
|
|
7245
|
+
previousValue = currentValue;
|
|
7246
|
+
onChanged(currentValue);
|
|
7247
|
+
}
|
|
7248
|
+
});
|
|
7249
|
+
return {
|
|
7250
|
+
dispose: () => observer.remove(),
|
|
7251
|
+
};
|
|
7252
|
+
}
|
|
7253
|
+
else {
|
|
7254
|
+
return InterceptProperty(target, propertyKey, {
|
|
7255
|
+
afterSet: (value) => onChanged(value),
|
|
7256
|
+
});
|
|
7257
|
+
}
|
|
7258
|
+
},
|
|
7259
|
+
refresh: () => {
|
|
7260
|
+
refreshObservable?.notifyObservers();
|
|
7261
|
+
},
|
|
7262
|
+
dispose: () => {
|
|
7263
|
+
if (pollingHandle !== null) {
|
|
7264
|
+
clearInterval(pollingHandle);
|
|
7265
|
+
pollingHandle = null;
|
|
7266
|
+
}
|
|
7267
|
+
refreshObservable?.clear();
|
|
7268
|
+
refreshObservable = null;
|
|
7269
|
+
settingsStoreObserver.remove();
|
|
7270
|
+
},
|
|
7271
|
+
};
|
|
7272
|
+
},
|
|
7273
|
+
};
|
|
7274
|
+
const WatchModes = [
|
|
7275
|
+
{ label: "Interception", value: "intercept" },
|
|
7276
|
+
{ label: "Polling", value: "polling" },
|
|
7277
|
+
{ label: "Manual", value: "manual" },
|
|
7278
|
+
];
|
|
7279
|
+
const WatcherSettingsServiceDefinition = {
|
|
7280
|
+
friendlyName: "Watcher Settings Service",
|
|
7281
|
+
consumes: [SettingsServiceIdentity],
|
|
7282
|
+
factory: (settingsService) => {
|
|
7283
|
+
const settingsRegistration = settingsService.addSectionContent({
|
|
7284
|
+
key: "watcherSettings",
|
|
7285
|
+
section: "UI",
|
|
7286
|
+
component: () => {
|
|
7287
|
+
const [watcherSettings, setWatcherSettings] = useSetting(WatcherSettingDescriptor);
|
|
7288
|
+
return (jsxs(Fragment, { children: [jsx(DropdownPropertyLine, { label: "Property Watch Mode", description: `Specifies how Inspector watches entity properties for changes. "Interception" sees changes instantly, but for complex scenes can impact performance. "Polling" has less performance impact on complex scenes, but changes are only detected at the specified interval. "Manual" requires the "Refresh" button in the toolbar to be pressed.`, options: WatchModes, value: watcherSettings.mode, onChange: (value) => setWatcherSettings((prev) => {
|
|
7289
|
+
return { interval: 250, ...prev, mode: value };
|
|
7290
|
+
}) }), jsx(Collapse, { visible: watcherSettings.mode === "polling", children: jsx(SyncedSliderPropertyLine, { label: "Polling Interval", description: "A smaller polling interval will detect changes faster but may impact performance more.", min: 30, max: 1000, step: 10, unit: "ms", value: watcherSettings.mode === "polling" ? watcherSettings.interval : NaN, onChange: (value) => setWatcherSettings((prev) => {
|
|
7291
|
+
return { ...prev, interval: value };
|
|
7292
|
+
}) }) })] }));
|
|
7293
|
+
},
|
|
7294
|
+
});
|
|
7295
|
+
return {
|
|
7296
|
+
dispose: () => {
|
|
7297
|
+
settingsRegistration.dispose();
|
|
7298
|
+
},
|
|
7299
|
+
};
|
|
7300
|
+
},
|
|
7301
|
+
};
|
|
7302
|
+
const WatcherRefreshToolbarServiceDefinition = {
|
|
7303
|
+
friendlyName: "Watcher Refresh Toolbar Service",
|
|
7304
|
+
consumes: [WatcherServiceIdentity, SettingsStoreIdentity, ShellServiceIdentity],
|
|
7305
|
+
factory: (watcherService, settingsStore, shellService) => {
|
|
7306
|
+
let toolbarItemRegistration = null;
|
|
7307
|
+
const updateToolbar = () => {
|
|
7308
|
+
const settings = settingsStore.readSetting(WatcherSettingDescriptor);
|
|
7309
|
+
if (settings.mode === "manual") {
|
|
7310
|
+
if (!toolbarItemRegistration) {
|
|
7311
|
+
toolbarItemRegistration = shellService.addToolbarItem({
|
|
7312
|
+
key: "Watcher Refresh",
|
|
7313
|
+
displayName: "Refresh Properties",
|
|
7314
|
+
verticalLocation: "bottom",
|
|
7315
|
+
horizontalLocation: "right",
|
|
7316
|
+
order: 200 /* DefaultToolbarItemOrder.RefreshProperties */,
|
|
7317
|
+
teachingMoment: {
|
|
7318
|
+
title: "Refresh Properties",
|
|
7319
|
+
description: "Press this button to manually refresh all UI bound to scene state. This is only available when Property Watch Mode is set to Manual in the settings pane.",
|
|
7320
|
+
},
|
|
7321
|
+
component: () => {
|
|
7322
|
+
return (jsx(Button, { appearance: "subtle", icon: ArrowClockwiseRegular, title: "Update all UI (e.g. Scene Explorer, Properties, etc.) bound to properties of entities (Meshes, Materials, etc.)", onClick: () => watcherService.refresh() }));
|
|
7323
|
+
},
|
|
7324
|
+
});
|
|
7325
|
+
}
|
|
7326
|
+
}
|
|
7327
|
+
else {
|
|
7328
|
+
toolbarItemRegistration?.dispose();
|
|
7329
|
+
toolbarItemRegistration = null;
|
|
7330
|
+
}
|
|
7331
|
+
};
|
|
7332
|
+
updateToolbar();
|
|
7333
|
+
const settingsStoreObserver = settingsStore.onChanged.add((key) => {
|
|
7334
|
+
if (key === WatcherSettingDescriptor.key) {
|
|
7335
|
+
updateToolbar();
|
|
7336
|
+
}
|
|
7337
|
+
});
|
|
7338
|
+
return {
|
|
7339
|
+
dispose: () => {
|
|
7340
|
+
toolbarItemRegistration?.dispose();
|
|
7341
|
+
toolbarItemRegistration = null;
|
|
7342
|
+
settingsStoreObserver.remove();
|
|
7343
|
+
},
|
|
7344
|
+
};
|
|
7345
|
+
},
|
|
7346
|
+
};
|
|
7347
|
+
|
|
6930
7348
|
const GizmoServiceIdentity = Symbol("GizmoService");
|
|
6931
7349
|
const GizmoServiceDefinition = {
|
|
6932
7350
|
friendlyName: "Gizmo Service",
|
|
6933
7351
|
produces: [GizmoServiceIdentity],
|
|
6934
|
-
consumes: [SceneContextIdentity, SelectionServiceIdentity],
|
|
6935
|
-
factory: (sceneContext, selectionService) => {
|
|
7352
|
+
consumes: [SceneContextIdentity, SelectionServiceIdentity, WatcherServiceIdentity],
|
|
7353
|
+
factory: (sceneContext, selectionService, watcherService) => {
|
|
6936
7354
|
// Ref-counted utility layers, shared across consumers.
|
|
6937
7355
|
const utilityLayers = new WeakMap();
|
|
6938
7356
|
const getUtilityLayer = (scene, layer = "default") => {
|
|
@@ -7031,13 +7449,11 @@ const GizmoServiceDefinition = {
|
|
|
7031
7449
|
currentKeepDepthUtilityLayerRef = null;
|
|
7032
7450
|
};
|
|
7033
7451
|
gm.coordinatesMode = coordinatesModeState;
|
|
7034
|
-
coordinatesModeInterceptToken =
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
}
|
|
7040
|
-
},
|
|
7452
|
+
coordinatesModeInterceptToken = watcherService.watchProperty(gm, "coordinatesMode", (value) => {
|
|
7453
|
+
if (value !== coordinatesModeState) {
|
|
7454
|
+
coordinatesModeState = value;
|
|
7455
|
+
coordinatesModeObservable.notifyObservers();
|
|
7456
|
+
}
|
|
7041
7457
|
});
|
|
7042
7458
|
currentGizmoManager = gm;
|
|
7043
7459
|
}
|
|
@@ -7210,7 +7626,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
7210
7626
|
keywords: ["creation", "tools"],
|
|
7211
7627
|
...BabylonWebResources,
|
|
7212
7628
|
author: { name: "Babylon.js", forumUserName: "" },
|
|
7213
|
-
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-
|
|
7629
|
+
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-DHfs_EZ6.js'),
|
|
7214
7630
|
},
|
|
7215
7631
|
{
|
|
7216
7632
|
name: "Reflector",
|
|
@@ -7218,116 +7634,10 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
7218
7634
|
keywords: ["reflector", "bridge", "sync", "sandbox", "tools"],
|
|
7219
7635
|
...BabylonWebResources,
|
|
7220
7636
|
author: { name: "Babylon.js", forumUserName: "" },
|
|
7221
|
-
getExtensionModuleAsync: async () => await import('./reflectorService-
|
|
7637
|
+
getExtensionModuleAsync: async () => await import('./reflectorService-DEPuGTAZ.js'),
|
|
7222
7638
|
},
|
|
7223
7639
|
]);
|
|
7224
7640
|
|
|
7225
|
-
const useSyncedSliderStyles = makeStyles({
|
|
7226
|
-
container: { display: "flex", minWidth: 0 },
|
|
7227
|
-
syncedSlider: {
|
|
7228
|
-
flex: "1 1 0",
|
|
7229
|
-
flexDirection: "row",
|
|
7230
|
-
display: "flex",
|
|
7231
|
-
alignItems: "center",
|
|
7232
|
-
minWidth: 0,
|
|
7233
|
-
},
|
|
7234
|
-
slider: {
|
|
7235
|
-
flex: "1 1 auto",
|
|
7236
|
-
minWidth: "75px",
|
|
7237
|
-
maxWidth: "75px",
|
|
7238
|
-
},
|
|
7239
|
-
compactSlider: {
|
|
7240
|
-
flex: "1 1 auto",
|
|
7241
|
-
minWidth: "50px", // Allow shrinking for compact mode
|
|
7242
|
-
maxWidth: "75px",
|
|
7243
|
-
},
|
|
7244
|
-
growSlider: {
|
|
7245
|
-
flex: "1 1 auto",
|
|
7246
|
-
minWidth: "50px",
|
|
7247
|
-
// No maxWidth - slider grows to fill available space
|
|
7248
|
-
},
|
|
7249
|
-
compactSpinButton: {
|
|
7250
|
-
width: "65px",
|
|
7251
|
-
minWidth: "65px",
|
|
7252
|
-
maxWidth: "65px",
|
|
7253
|
-
},
|
|
7254
|
-
compactSpinButtonInput: {
|
|
7255
|
-
minWidth: "0",
|
|
7256
|
-
},
|
|
7257
|
-
});
|
|
7258
|
-
/**
|
|
7259
|
-
* Component which synchronizes a slider and an input field, allowing the user to change the value using either control
|
|
7260
|
-
* @param props
|
|
7261
|
-
* @returns SyncedSlider component
|
|
7262
|
-
*/
|
|
7263
|
-
const SyncedSliderInput = (props) => {
|
|
7264
|
-
SyncedSliderInput.displayName = "SyncedSliderInput";
|
|
7265
|
-
const { infoLabel, ...passthroughProps } = props;
|
|
7266
|
-
const classes = useSyncedSliderStyles();
|
|
7267
|
-
const { size } = useContext(ToolContext);
|
|
7268
|
-
const [value, setValue] = useState(props.value ?? 0);
|
|
7269
|
-
const pendingValueRef = useRef(undefined);
|
|
7270
|
-
const isDraggingRef = useRef(false);
|
|
7271
|
-
// NOTE: The Fluent slider will add tick marks if the step prop is anything other than undefined.
|
|
7272
|
-
// To avoid this, we scale the min/max based on the step so we can always make step undefined.
|
|
7273
|
-
// The actual step size in the Fluent slider is 1 when it is ste to undefined.
|
|
7274
|
-
const min = props.min ?? 0;
|
|
7275
|
-
const max = props.max ?? 100;
|
|
7276
|
-
const step = props.step ?? 1;
|
|
7277
|
-
useEffect(() => {
|
|
7278
|
-
!isDraggingRef.current && setValue(props.value ?? 0); // Update local state when props.value changes as long as user is not actively dragging
|
|
7279
|
-
}, [props.value]);
|
|
7280
|
-
const handleSliderChange = (_, data) => {
|
|
7281
|
-
const newValue = data.value * step;
|
|
7282
|
-
setValue(newValue);
|
|
7283
|
-
if (props.notifyOnlyOnRelease) {
|
|
7284
|
-
// Store the value but don't notify parent yet
|
|
7285
|
-
pendingValueRef.current = newValue;
|
|
7286
|
-
}
|
|
7287
|
-
else {
|
|
7288
|
-
// Notify parent as slider changes
|
|
7289
|
-
props.onChange(newValue);
|
|
7290
|
-
}
|
|
7291
|
-
};
|
|
7292
|
-
const handleSliderPointerDown = () => {
|
|
7293
|
-
isDraggingRef.current = true;
|
|
7294
|
-
};
|
|
7295
|
-
const handleSliderPointerUp = () => {
|
|
7296
|
-
if (props.notifyOnlyOnRelease && isDraggingRef.current && pendingValueRef.current !== undefined) {
|
|
7297
|
-
props.onChange(pendingValueRef.current);
|
|
7298
|
-
pendingValueRef.current = undefined;
|
|
7299
|
-
}
|
|
7300
|
-
isDraggingRef.current = false;
|
|
7301
|
-
};
|
|
7302
|
-
const handleInputChange = (value) => {
|
|
7303
|
-
setValue(value);
|
|
7304
|
-
props.onChange(value); // Input always updates immediately
|
|
7305
|
-
};
|
|
7306
|
-
const hasSlider = props.min !== undefined && props.max !== undefined;
|
|
7307
|
-
// Determine Slider className based on props
|
|
7308
|
-
const getSliderClassName = () => {
|
|
7309
|
-
if (props.growSlider) {
|
|
7310
|
-
return classes.growSlider;
|
|
7311
|
-
}
|
|
7312
|
-
if (props.compact) {
|
|
7313
|
-
return classes.compactSlider;
|
|
7314
|
-
}
|
|
7315
|
-
return classes.slider;
|
|
7316
|
-
};
|
|
7317
|
-
return (jsxs("div", { className: classes.container, children: [infoLabel && jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [hasSlider && (jsx(Slider, { ...passthroughProps, className: getSliderClassName(), size: size, min: min / step, max: max / step, step: undefined, value: value / step, onChange: handleSliderChange, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), jsx(SpinButton, { ...passthroughProps, className: hasSlider || props.compact ? classes.compactSpinButton : undefined, inputClassName: hasSlider || props.compact ? classes.compactSpinButtonInput : undefined, value: value, onChange: handleInputChange, step: props.step })] })] }));
|
|
7318
|
-
};
|
|
7319
|
-
|
|
7320
|
-
/**
|
|
7321
|
-
* Renders a simple wrapper around the SyncedSliderInput
|
|
7322
|
-
* @param props
|
|
7323
|
-
* @returns
|
|
7324
|
-
*/
|
|
7325
|
-
const SyncedSliderPropertyLine = forwardRef((props, ref) => {
|
|
7326
|
-
SyncedSliderPropertyLine.displayName = "SyncedSliderPropertyLine";
|
|
7327
|
-
const { label, description, ...sliderProps } = props;
|
|
7328
|
-
return (jsx(PropertyLine, { ref: ref, ...props, children: jsx(SyncedSliderInput, { ...sliderProps }) }));
|
|
7329
|
-
});
|
|
7330
|
-
|
|
7331
7641
|
/**
|
|
7332
7642
|
* Reusable component which renders a color property line containing a label, colorPicker popout, and expandable RGBA values
|
|
7333
7643
|
* The expandable RGBA values are synced sliders that allow the user to modify the color's RGBA values directly
|
|
@@ -7362,30 +7672,6 @@ const ColorSliders = ({ color, onSliderChange }) => (jsxs(Fragment, { children:
|
|
|
7362
7672
|
const Color3PropertyLine = ColorPropertyLine;
|
|
7363
7673
|
const Color4PropertyLine = ColorPropertyLine;
|
|
7364
7674
|
|
|
7365
|
-
const useStyles$F = makeStyles({
|
|
7366
|
-
dropdown: {
|
|
7367
|
-
...UniformWidthStyling,
|
|
7368
|
-
},
|
|
7369
|
-
});
|
|
7370
|
-
/**
|
|
7371
|
-
* Wraps a dropdown in a property line
|
|
7372
|
-
* @param props - PropertyLineProps and DropdownProps
|
|
7373
|
-
* @returns property-line wrapped dropdown
|
|
7374
|
-
*/
|
|
7375
|
-
const DropdownPropertyLine = forwardRef((props, ref) => {
|
|
7376
|
-
DropdownPropertyLine.displayName = "DropdownPropertyLine";
|
|
7377
|
-
const classes = useStyles$F();
|
|
7378
|
-
return (jsx(PropertyLine, { ...props, ref: ref, children: jsx(Dropdown, { ...props, className: classes.dropdown }) }));
|
|
7379
|
-
});
|
|
7380
|
-
/**
|
|
7381
|
-
* Dropdown component for number values.
|
|
7382
|
-
*/
|
|
7383
|
-
const NumberDropdownPropertyLine = DropdownPropertyLine;
|
|
7384
|
-
/**
|
|
7385
|
-
* Dropdown component for string values
|
|
7386
|
-
*/
|
|
7387
|
-
const StringDropdownPropertyLine = DropdownPropertyLine;
|
|
7388
|
-
|
|
7389
7675
|
/**
|
|
7390
7676
|
* Wraps a text input in a property line
|
|
7391
7677
|
* @param props - PropertyLineProps and InputProps
|
|
@@ -7430,21 +7716,21 @@ const TensorPropertyLine = (props) => {
|
|
|
7430
7716
|
useEffect(() => {
|
|
7431
7717
|
setVector(props.value);
|
|
7432
7718
|
}, [props.value, props.expandedContent]);
|
|
7433
|
-
return (jsx(PropertyLine, { ...props, expandedContent: vector ? jsx(VectorSliders, { vector: vector, min: min, max: max, unit: props.unit, step: props.step, converted: converted, onChange: onChange }) : undefined, children: jsx(Body1, { children: `[${formatted(props.value.x)}, ${formatted(props.value.y)}${HasZ(props.value) ? `, ${formatted(props.value.z)}` : ""}${HasW(props.value) ? `, ${formatted(props.value.w)}` : ""}]` }) }));
|
|
7719
|
+
return (jsx(PropertyLine, { ...props, expandedContent: jsxs(Fragment, { children: [props.expandedContent, vector ? (jsx(VectorSliders, { vector: vector, min: min, max: max, unit: props.unit, step: props.step, precision: props.precision, converted: converted, onChange: onChange })) : undefined] }), children: jsx(Body1, { children: `[${formatted(props.value.x)}, ${formatted(props.value.y)}${HasZ(props.value) ? `, ${formatted(props.value.z)}` : ""}${HasW(props.value) ? `, ${formatted(props.value.w)}` : ""}]` }) }));
|
|
7434
7720
|
};
|
|
7435
|
-
const VectorSliders = ({ vector, min, max, unit, step, converted, onChange }) => (jsxs(Fragment, { children: [jsx(
|
|
7721
|
+
const VectorSliders = ({ vector, min, max, unit, step, precision, converted, onChange }) => (jsxs(Fragment, { children: [jsx(NumberInputPropertyLine, { label: "X", value: converted(vector.x), min: min, max: max, onChange: (val) => onChange(val, "x"), unit: unit, step: step, precision: precision }), jsx(NumberInputPropertyLine, { label: "Y", value: converted(vector.y), min: min, max: max, onChange: (val) => onChange(val, "y"), unit: unit, step: step, precision: precision }), HasZ(vector) && (jsx(NumberInputPropertyLine, { label: "Z", value: converted(vector.z), min: min, max: max, onChange: (val) => onChange(val, "z"), unit: unit, step: step, precision: precision })), HasW(vector) && (jsx(NumberInputPropertyLine, { label: "W", value: converted(vector.w), min: min, max: max, onChange: (val) => onChange(val, "w"), unit: unit, step: step, precision: precision }))] }));
|
|
7436
7722
|
const ToDegreesConverter = { from: Tools.ToDegrees, to: Tools.ToRadians };
|
|
7437
7723
|
const RotationVectorPropertyLine = (props) => {
|
|
7438
7724
|
RotationVectorPropertyLine.displayName = "RotationVectorPropertyLine";
|
|
7439
|
-
const
|
|
7440
|
-
const
|
|
7441
|
-
return (jsx(Vector3PropertyLine, { ...props, unit: props.useDegrees ? "
|
|
7725
|
+
const step = props.useDegrees ? 1 : 0.01;
|
|
7726
|
+
const precision = props.useDegrees ? 1 : 2;
|
|
7727
|
+
return (jsx(Vector3PropertyLine, { ...props, unit: props.useDegrees ? "°" : "rad", valueConverter: props.useDegrees ? ToDegreesConverter : undefined, step: step, precision: precision }));
|
|
7442
7728
|
};
|
|
7443
7729
|
const QuaternionPropertyLineInternal = TensorPropertyLine;
|
|
7444
7730
|
const QuaternionPropertyLine = (props) => {
|
|
7445
7731
|
QuaternionPropertyLine.displayName = "QuaternionPropertyLine";
|
|
7446
|
-
const
|
|
7447
|
-
const
|
|
7732
|
+
const step = props.useDegrees ? 1 : 0.01;
|
|
7733
|
+
const precision = props.useDegrees ? 1 : 2;
|
|
7448
7734
|
const [quat, setQuat] = useState(props.value);
|
|
7449
7735
|
useEffect(() => {
|
|
7450
7736
|
setQuat(props.value);
|
|
@@ -7459,7 +7745,7 @@ const QuaternionPropertyLine = (props) => {
|
|
|
7459
7745
|
const quat = Quaternion.FromEulerAngles(val.x, val.y, val.z);
|
|
7460
7746
|
onQuatChange(quat);
|
|
7461
7747
|
};
|
|
7462
|
-
return useEuler ? (jsx(Vector3PropertyLine, { ...restProps, nullable: false, ignoreNullable: false, value: quat.toEulerAngles(), valueConverter: ToDegreesConverter,
|
|
7748
|
+
return useEuler ? (jsx(Vector3PropertyLine, { ...restProps, nullable: false, ignoreNullable: false, value: quat.toEulerAngles(), valueConverter: ToDegreesConverter, onChange: onEulerChange, unit: props.useDegrees ? "°" : "rad", step: step, precision: precision, expandedContent: jsx(TextPropertyLine, { label: "Quaternion", value: `[${quat.x.toFixed(4)}, ${quat.y.toFixed(4)}, ${quat.z.toFixed(4)}, ${quat.w.toFixed(4)}]` }) })) : (jsx(QuaternionPropertyLineInternal, { ...props, nullable: false, value: quat, onChange: onQuatChange, unit: props.useDegrees ? "°" : "rad", step: step, precision: precision }));
|
|
7463
7749
|
};
|
|
7464
7750
|
const Vector2PropertyLine = TensorPropertyLine;
|
|
7465
7751
|
const Vector3PropertyLine = TensorPropertyLine;
|
|
@@ -7974,7 +8260,7 @@ const ThemeSelectorServiceDefinition = {
|
|
|
7974
8260
|
key: "ThemeSelector",
|
|
7975
8261
|
horizontalLocation: "right",
|
|
7976
8262
|
verticalLocation: "top",
|
|
7977
|
-
|
|
8263
|
+
teachingMoment: false,
|
|
7978
8264
|
order: -300,
|
|
7979
8265
|
component: () => {
|
|
7980
8266
|
const classes = useStyles$E();
|
|
@@ -8039,7 +8325,7 @@ function MakeModularTool(options) {
|
|
|
8039
8325
|
const [requiredExtensions, setRequiredExtensions] = useState();
|
|
8040
8326
|
const [requiredExtensionsDeferred, setRequiredExtensionsDeferred] = useState();
|
|
8041
8327
|
const [extensionInstallError, setExtensionInstallError] = useState();
|
|
8042
|
-
const [
|
|
8328
|
+
const [bootstrapServices, setBootstrapServices] = useState();
|
|
8043
8329
|
// This is the main async initialization.
|
|
8044
8330
|
useEffect(() => {
|
|
8045
8331
|
const initializeExtensionManagerAsync = async () => {
|
|
@@ -8050,17 +8336,22 @@ function MakeModularTool(options) {
|
|
|
8050
8336
|
produces: [SettingsStoreIdentity],
|
|
8051
8337
|
factory: () => settingsStore,
|
|
8052
8338
|
});
|
|
8339
|
+
// Register watcher service early since many other services will rely on it.
|
|
8340
|
+
// TODO: Really this should be in the Inspector layer, but we would need a way
|
|
8341
|
+
// to setup the WatcherContext.Provider before the root component is rendered
|
|
8342
|
+
// for that to work, since components will use the WatcherContext.
|
|
8343
|
+
await serviceContainer.addServiceAsync(WatcherServiceDefinition);
|
|
8053
8344
|
// Register the shell service (top level toolbar/side pane UI layout).
|
|
8054
8345
|
await serviceContainer.addServiceAsync(MakeShellServiceDefinition(options));
|
|
8055
|
-
// Register a service that simply consumes the
|
|
8346
|
+
// Register a service that simply consumes the services we need before first render.
|
|
8056
8347
|
await serviceContainer.addServiceAsync({
|
|
8057
|
-
friendlyName: "
|
|
8058
|
-
consumes: [RootComponentServiceIdentity],
|
|
8059
|
-
factory: (rootComponentService) => {
|
|
8348
|
+
friendlyName: "Service Bootstrapper",
|
|
8349
|
+
consumes: [RootComponentServiceIdentity, WatcherServiceIdentity],
|
|
8350
|
+
factory: (rootComponentService, watcherService) => {
|
|
8060
8351
|
// Use function syntax for the state setter since the root component may be a function component.
|
|
8061
|
-
|
|
8352
|
+
setBootstrapServices({ rootComponentService, watcherService });
|
|
8062
8353
|
return {
|
|
8063
|
-
dispose: () =>
|
|
8354
|
+
dispose: () => setBootstrapServices(undefined),
|
|
8064
8355
|
};
|
|
8065
8356
|
},
|
|
8066
8357
|
});
|
|
@@ -8072,7 +8363,7 @@ function MakeModularTool(options) {
|
|
|
8072
8363
|
}
|
|
8073
8364
|
// Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
|
|
8074
8365
|
if (extensionFeeds.length > 0) {
|
|
8075
|
-
const { ExtensionListServiceDefinition } = await import('./extensionsListService-
|
|
8366
|
+
const { ExtensionListServiceDefinition } = await import('./extensionsListService-Duej2zkq.js');
|
|
8076
8367
|
await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);
|
|
8077
8368
|
}
|
|
8078
8369
|
// Register all external services (that make up a unique tool).
|
|
@@ -8139,12 +8430,17 @@ function MakeModularTool(options) {
|
|
|
8139
8430
|
setExtensionInstallError(undefined);
|
|
8140
8431
|
}, [setExtensionInstallError]);
|
|
8141
8432
|
// Show a spinner until a main view has been set.
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8433
|
+
if (!bootstrapServices) {
|
|
8434
|
+
return (jsx(SettingsStoreContext.Provider, { value: settingsStore, children: jsx(Theme, { className: classes.app, children: jsx(Spinner, { className: classes.spinner }) }) }));
|
|
8435
|
+
}
|
|
8436
|
+
else {
|
|
8437
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
8438
|
+
const Content = bootstrapServices.rootComponentService.rootComponent;
|
|
8439
|
+
return (
|
|
8440
|
+
// Expose the settings store as a React context so that UI components can read/write
|
|
8441
|
+
// settings without the ISettingsService needing to be explicitly passed around.
|
|
8442
|
+
jsx(SettingsStoreContext.Provider, { value: settingsStore, children: jsx(WatcherContext.Provider, { value: bootstrapServices.watcherService, children: jsx(ExtensionManagerContext.Provider, { value: extensionManagerContext, children: jsx(Theme, { className: classes.app, children: jsxs(ToastProvider, { children: [jsx(Dialog, { open: !!requiredExtensions, modalType: "alert", children: jsx(DialogSurface, { children: jsxs(DialogBody, { children: [jsx(DialogTitle, { children: "Required Extensions" }), jsxs(DialogContent, { children: ["Opening this URL requires the following extensions to be installed and enabled:", jsx("ul", { children: requiredExtensions?.map((name) => jsx("li", { children: name }, name)) })] }), jsxs(DialogActions, { children: [jsx(Button$1, { appearance: "primary", onClick: onAcceptRequiredExtensions, children: "Install & Enable" }), jsx(Button$1, { appearance: "secondary", onClick: onRejectRequiredExtensions, children: "No Thanks" })] })] }) }) }), jsx(Dialog, { open: !!extensionInstallError, modalType: "alert", children: jsx(DialogSurface, { children: jsxs(DialogBody, { children: [jsx(DialogTitle, { children: jsxs("div", { className: classes.extensionErrorTitleDiv, children: ["Extension Install Error", jsx(ErrorCircleRegular, { className: classes.extensionErrorIcon })] }) }), jsx(DialogContent, { children: jsxs(List$1, { children: [jsx(ListItem, { children: jsx(Body1, { children: `Extension "${extensionInstallError?.extension.name}" failed to install and was removed.` }) }), jsx(ListItem, { children: jsx(Body1, { children: `${extensionInstallError?.error}` }) })] }) }), jsx(DialogActions, { children: jsx(Button$1, { appearance: "primary", onClick: onAcknowledgedExtensionInstallError, children: "Close" }) })] }) }) }), jsx(Suspense, { fallback: jsx(Spinner, { className: classes.spinner }), children: jsx(Content, {}) })] }) }) }) }) }));
|
|
8443
|
+
}
|
|
8148
8444
|
};
|
|
8149
8445
|
// Set the container element to be a flex container so that the tool can be displayed properly.
|
|
8150
8446
|
const originalContainerElementDisplay = containerElement.style.display;
|
|
@@ -8223,12 +8519,103 @@ const GizmoToolbarServiceDefinition = {
|
|
|
8223
8519
|
key: "Gizmo Toolbar",
|
|
8224
8520
|
verticalLocation: "top",
|
|
8225
8521
|
horizontalLocation: "left",
|
|
8226
|
-
|
|
8522
|
+
teachingMoment: false,
|
|
8227
8523
|
component: () => jsx(GizmoToolbar, { gizmoService: gizmoService, sceneContext: sceneContext }),
|
|
8228
8524
|
});
|
|
8229
8525
|
},
|
|
8230
8526
|
};
|
|
8231
8527
|
|
|
8528
|
+
const HighlightSelectedEntitySettingDescriptor = {
|
|
8529
|
+
key: "HighlightSelectedEntity",
|
|
8530
|
+
defaultValue: true,
|
|
8531
|
+
};
|
|
8532
|
+
const HighlightServiceDefinition = {
|
|
8533
|
+
friendlyName: "Highlight Service",
|
|
8534
|
+
consumes: [SelectionServiceIdentity, SceneContextIdentity, SettingsStoreIdentity, ThemeServiceIdentity, GizmoServiceIdentity],
|
|
8535
|
+
factory: (selectionService, sceneContext, settingsStore, themeService, gizmoService) => {
|
|
8536
|
+
let outlineLayer = null;
|
|
8537
|
+
let utilityLayer = null;
|
|
8538
|
+
let currentScene = null;
|
|
8539
|
+
let activeCameraObserver = null;
|
|
8540
|
+
function disposeOutlineLayer() {
|
|
8541
|
+
outlineLayer?.dispose();
|
|
8542
|
+
outlineLayer = null;
|
|
8543
|
+
utilityLayer?.dispose();
|
|
8544
|
+
utilityLayer = null;
|
|
8545
|
+
currentScene = null;
|
|
8546
|
+
}
|
|
8547
|
+
function getOrCreateOutlineLayer(scene) {
|
|
8548
|
+
if (!outlineLayer || currentScene !== scene) {
|
|
8549
|
+
disposeOutlineLayer();
|
|
8550
|
+
utilityLayer = gizmoService.getUtilityLayer(scene);
|
|
8551
|
+
outlineLayer = new SelectionOutlineLayer("InspectorSelectionOutline", utilityLayer.value.utilityLayerScene);
|
|
8552
|
+
updateColor(outlineLayer);
|
|
8553
|
+
currentScene = scene;
|
|
8554
|
+
}
|
|
8555
|
+
return outlineLayer;
|
|
8556
|
+
}
|
|
8557
|
+
function updateColor(outlineLayer) {
|
|
8558
|
+
outlineLayer.outlineColor = Color3.FromHexString(themeService.theme.colorBrandForeground1);
|
|
8559
|
+
}
|
|
8560
|
+
function updateHighlight() {
|
|
8561
|
+
const scene = sceneContext.currentScene;
|
|
8562
|
+
const entity = selectionService.selectedEntity instanceof AbstractMesh && !(selectionService.selectedEntity instanceof GaussianSplattingMesh)
|
|
8563
|
+
? selectionService.selectedEntity
|
|
8564
|
+
: null;
|
|
8565
|
+
if (!entity || !settingsStore.readSetting(HighlightSelectedEntitySettingDescriptor) || !scene || !scene.activeCamera) {
|
|
8566
|
+
disposeOutlineLayer();
|
|
8567
|
+
return;
|
|
8568
|
+
}
|
|
8569
|
+
const layer = getOrCreateOutlineLayer(scene);
|
|
8570
|
+
layer.clearSelection();
|
|
8571
|
+
layer.addSelection(entity);
|
|
8572
|
+
}
|
|
8573
|
+
function watchActiveCamera(scene) {
|
|
8574
|
+
activeCameraObserver?.remove();
|
|
8575
|
+
activeCameraObserver = null;
|
|
8576
|
+
if (scene) {
|
|
8577
|
+
activeCameraObserver = scene.onActiveCameraChanged.add(updateHighlight);
|
|
8578
|
+
}
|
|
8579
|
+
}
|
|
8580
|
+
// React to theme changes.
|
|
8581
|
+
const themeObserver = themeService.onChanged.add(() => {
|
|
8582
|
+
if (outlineLayer) {
|
|
8583
|
+
updateColor(outlineLayer);
|
|
8584
|
+
}
|
|
8585
|
+
});
|
|
8586
|
+
// React to selection changes.
|
|
8587
|
+
const selectionObserver = selectionService.onSelectedEntityChanged.add(updateHighlight);
|
|
8588
|
+
// React to scene changes.
|
|
8589
|
+
const sceneObserver = sceneContext.currentSceneObservable.add(() => {
|
|
8590
|
+
// Dispose the old layer when the scene changes.
|
|
8591
|
+
disposeOutlineLayer();
|
|
8592
|
+
watchActiveCamera(sceneContext.currentScene);
|
|
8593
|
+
updateHighlight();
|
|
8594
|
+
});
|
|
8595
|
+
// React to setting changes.
|
|
8596
|
+
const settingObserver = settingsStore.onChanged.add((setting) => {
|
|
8597
|
+
if (setting === HighlightSelectedEntitySettingDescriptor.key) {
|
|
8598
|
+
updateHighlight();
|
|
8599
|
+
}
|
|
8600
|
+
});
|
|
8601
|
+
// Watch active camera on the initial scene.
|
|
8602
|
+
watchActiveCamera(sceneContext.currentScene);
|
|
8603
|
+
// Initial update.
|
|
8604
|
+
updateHighlight();
|
|
8605
|
+
return {
|
|
8606
|
+
dispose: () => {
|
|
8607
|
+
themeObserver.remove();
|
|
8608
|
+
selectionObserver.remove();
|
|
8609
|
+
sceneObserver.remove();
|
|
8610
|
+
settingObserver.remove();
|
|
8611
|
+
activeCameraObserver?.remove();
|
|
8612
|
+
activeCameraObserver = null;
|
|
8613
|
+
disposeOutlineLayer();
|
|
8614
|
+
},
|
|
8615
|
+
};
|
|
8616
|
+
},
|
|
8617
|
+
};
|
|
8618
|
+
|
|
8232
8619
|
const useStyles$B = makeStyles({
|
|
8233
8620
|
badge: {
|
|
8234
8621
|
margin: tokens.spacingHorizontalXXS,
|
|
@@ -8243,7 +8630,8 @@ const MiniStatsServiceDefinition = {
|
|
|
8243
8630
|
key: "Mini Stats",
|
|
8244
8631
|
verticalLocation: "bottom",
|
|
8245
8632
|
horizontalLocation: "right",
|
|
8246
|
-
|
|
8633
|
+
order: 300 /* DefaultToolbarItemOrder.FrameRate */,
|
|
8634
|
+
teachingMoment: false,
|
|
8247
8635
|
component: () => {
|
|
8248
8636
|
const classes = useStyles$B();
|
|
8249
8637
|
const scene = useObservableState(useCallback(() => sceneContext.currentScene, [sceneContext.currentScene]), sceneContext.currentSceneObservable);
|
|
@@ -12429,7 +12817,7 @@ const SoundCommandProperties = (props) => {
|
|
|
12429
12817
|
else {
|
|
12430
12818
|
sound.play();
|
|
12431
12819
|
}
|
|
12432
|
-
} }), jsx(Property, { component:
|
|
12820
|
+
} }), jsx(Property, { component: NumberInputPropertyLine, label: "Volume", functionPath: "setVolume", value: volume, min: 0, step: 0.1, onChange: (value) => {
|
|
12433
12821
|
sound.setVolume(value);
|
|
12434
12822
|
} }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Loop", target: sound, propertyKey: "loop" })] }));
|
|
12435
12823
|
};
|
|
@@ -12469,7 +12857,7 @@ const ArcRotateCameraTransformProperties = (props) => {
|
|
|
12469
12857
|
const upperBetaLimit = useProperty(camera, "upperBetaLimit") ?? Math.PI;
|
|
12470
12858
|
const lowerRadiusLimit = useProperty(camera, "lowerRadiusLimit");
|
|
12471
12859
|
const upperRadiusLimit = useProperty(camera, "upperRadiusLimit");
|
|
12472
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component:
|
|
12860
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Alpha", description: `Horizontal angle in ${useDegrees ? "degrees" : "radians"}`, target: camera, propertyKey: "alpha", min: toDisplayAngle(lowerAlphaLimit), max: toDisplayAngle(upperAlphaLimit), step: toDisplayAngle(0.01), unit: useDegrees ? "°" : "rad", convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Beta", description: `Vertical angle in ${useDegrees ? "degrees" : "radians"}`, target: camera, propertyKey: "beta", min: toDisplayAngle(lowerBetaLimit), max: toDisplayAngle(upperBetaLimit), step: toDisplayAngle(0.01), unit: useDegrees ? "°" : "rad", convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius", description: "Distance from the target point.", target: camera, propertyKey: "radius", min: lowerRadiusLimit ?? undefined, max: upperRadiusLimit ?? undefined, step: 0.01 })] }));
|
|
12473
12861
|
};
|
|
12474
12862
|
const ArcRotateCameraControlProperties = (props) => {
|
|
12475
12863
|
const { camera } = props;
|
|
@@ -12481,8 +12869,19 @@ const ArcRotateCameraCollisionProperties = (props) => {
|
|
|
12481
12869
|
};
|
|
12482
12870
|
const ArcRotateCameraLimitsProperties = (props) => {
|
|
12483
12871
|
const { camera } = props;
|
|
12872
|
+
const [toDisplayAngle, fromDisplayAngle, useDegrees] = useAngleConverters();
|
|
12873
|
+
const minAlphaLimit = 0;
|
|
12874
|
+
const maxAlphaLimit = Math.PI * 2;
|
|
12875
|
+
const minBetaLimit = -Math.PI;
|
|
12876
|
+
const maxBetaLimit = Math.PI;
|
|
12877
|
+
const lowerAlphaLimit = useProperty(camera, "lowerAlphaLimit") ?? minAlphaLimit;
|
|
12878
|
+
const upperAlphaLimit = useProperty(camera, "upperAlphaLimit") ?? maxAlphaLimit;
|
|
12879
|
+
const lowerBetaLimit = useProperty(camera, "lowerBetaLimit") ?? minBetaLimit;
|
|
12880
|
+
const upperBetaLimit = useProperty(camera, "upperBetaLimit") ?? maxBetaLimit;
|
|
12881
|
+
const lowerRadiusLimit = useProperty(camera, "lowerRadiusLimit");
|
|
12882
|
+
const upperRadiusLimit = useProperty(camera, "upperRadiusLimit");
|
|
12484
12883
|
// TODO-Iv2: Update defaultValues
|
|
12485
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Alpha Limit", target: camera, propertyKey: "lowerAlphaLimit", nullable: true, defaultValue:
|
|
12884
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Alpha Limit", target: camera, propertyKey: "lowerAlphaLimit", nullable: true, defaultValue: toDisplayAngle(minAlphaLimit), min: toDisplayAngle(minAlphaLimit), max: toDisplayAngle(upperAlphaLimit), unit: useDegrees ? "°" : "rad", convertTo: (value) => (value === null ? value : toDisplayAngle(value, true)), convertFrom: (value) => (value === null ? value : fromDisplayAngle(value)) }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Upper Alpha Limit", target: camera, propertyKey: "upperAlphaLimit", nullable: true, defaultValue: toDisplayAngle(maxAlphaLimit), min: toDisplayAngle(lowerAlphaLimit), max: toDisplayAngle(maxAlphaLimit), unit: useDegrees ? "°" : "rad", convertTo: (value) => (value === null ? value : toDisplayAngle(value, true)), convertFrom: (value) => (value === null ? value : fromDisplayAngle(value)) }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Beta Limit", target: camera, propertyKey: "lowerBetaLimit", nullable: true, defaultValue: toDisplayAngle(minBetaLimit), min: toDisplayAngle(minBetaLimit), max: toDisplayAngle(upperBetaLimit), unit: useDegrees ? "°" : "rad", convertTo: (value) => (value === null ? value : toDisplayAngle(value, true)), convertFrom: (value) => (value === null ? value : fromDisplayAngle(value)) }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Upper Beta Limit", target: camera, propertyKey: "upperBetaLimit", nullable: true, defaultValue: toDisplayAngle(maxBetaLimit), min: toDisplayAngle(lowerBetaLimit), max: toDisplayAngle(maxBetaLimit), unit: useDegrees ? "°" : "rad", convertTo: (value) => (value === null ? value : toDisplayAngle(value, true)), convertFrom: (value) => (value === null ? value : fromDisplayAngle(value)) }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Radius Limit", target: camera, propertyKey: "lowerRadiusLimit", nullable: true, defaultValue: 0, min: 0, max: upperRadiusLimit ?? undefined }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Upper Radius Limit", target: camera, propertyKey: "upperRadiusLimit", nullable: true, defaultValue: 100, min: lowerRadiusLimit ?? undefined }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Target Y Limit", target: camera, propertyKey: "lowerTargetYLimit" })] }));
|
|
12486
12885
|
};
|
|
12487
12886
|
const ArcRotateCameraBehaviorsProperties = (props) => {
|
|
12488
12887
|
const { camera } = props;
|
|
@@ -12499,7 +12898,7 @@ const GeospatialCameraTransformProperties = (props) => {
|
|
|
12499
12898
|
const pitchMax = limits?.pitchMax ?? Math.PI / 2;
|
|
12500
12899
|
const radiusMin = limits?.radiusMin ?? 0;
|
|
12501
12900
|
const radiusMax = limits?.radiusMax ?? Infinity;
|
|
12502
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component:
|
|
12901
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Yaw", description: `Horizontal rotation in ${useDegrees ? "degrees" : "radians"} (0 = north)`, target: camera, propertyKey: "yaw", min: toDisplayAngle(yawMin), max: toDisplayAngle(yawMax), step: toDisplayAngle(0.01), unit: useDegrees ? "°" : "rad", convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Pitch", description: `Vertical angle in ${useDegrees ? "degrees" : "radians"} (0 = looking down, π/2 = horizon)`, target: camera, propertyKey: "pitch", min: toDisplayAngle(pitchMin), max: toDisplayAngle(pitchMax), step: toDisplayAngle(0.01), unit: useDegrees ? "°" : "rad", convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), radiusMax !== Infinity ? (jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Radius", description: "Distance from the center point.", target: camera, propertyKey: "radius", min: radiusMin, max: radiusMax, step: 0.01 })) : (jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius", description: "Distance from the center point.", target: camera, propertyKey: "radius", min: 0, step: 0.01 })), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Center", description: "The point on the globe the camera orbits around.", target: camera, propertyKey: "center" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Position", description: "The camera's position.", target: camera, propertyKey: "position" })] }));
|
|
12503
12902
|
};
|
|
12504
12903
|
const GeospatialCameraCollisionProperties = (props) => {
|
|
12505
12904
|
const { camera } = props;
|
|
@@ -12576,7 +12975,7 @@ const CameraGeneralProperties = (props) => {
|
|
|
12576
12975
|
const { camera } = props;
|
|
12577
12976
|
const [toDisplayAngle, fromDisplayAngle, useDegrees] = useAngleConverters();
|
|
12578
12977
|
const mode = useProperty(camera, "mode");
|
|
12579
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Near Plane", description: "Anything closer than this will not be drawn.", target: camera, propertyKey: "minZ" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Far Plane", description: "Anything further than this will not be drawn.", target: camera, propertyKey: "maxZ" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Inertia", target: camera, propertyKey: "inertia", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: HexPropertyLine, label: "Layer Mask", target: camera, propertyKey: "layerMask" }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Mode", options: CameraModes, target: camera, propertyKey: "mode" }), jsx(Collapse, { visible: mode === Camera.PERSPECTIVE_CAMERA, children: jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "FOV", description: `Field of view in ${useDegrees ? "degrees" : "radians"}`, target: camera, propertyKey: "fov", min: toDisplayAngle(0.1), max: toDisplayAngle(Math.PI), step: toDisplayAngle(0.01), convertTo: toDisplayAngle, convertFrom: fromDisplayAngle }) }), jsx(Collapse, { visible: mode === Camera.ORTHOGRAPHIC_CAMERA, children: jsxs("div", { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Left", target: camera, step: 0.1, propertyKey: "orthoLeft", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Right", target: camera, step: 0.1, propertyKey: "orthoRight", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Top", target: camera, step: 0.1, propertyKey: "orthoTop", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Bottom", target: camera, step: 0.1, propertyKey: "orthoBottom", nullable: true, defaultValue: 0 })] }) })] }));
|
|
12978
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Near Plane", description: "Anything closer than this will not be drawn.", target: camera, propertyKey: "minZ" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Far Plane", description: "Anything further than this will not be drawn.", target: camera, propertyKey: "maxZ" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Inertia", target: camera, propertyKey: "inertia", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: HexPropertyLine, label: "Layer Mask", target: camera, propertyKey: "layerMask" }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Mode", options: CameraModes, target: camera, propertyKey: "mode" }), jsx(Collapse, { visible: mode === Camera.PERSPECTIVE_CAMERA, children: jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "FOV", description: `Field of view in ${useDegrees ? "degrees" : "radians"}`, target: camera, propertyKey: "fov", min: toDisplayAngle(0.1), max: toDisplayAngle(Math.PI), step: toDisplayAngle(0.01), unit: useDegrees ? "°" : "rad", convertTo: toDisplayAngle, convertFrom: fromDisplayAngle }) }), jsx(Collapse, { visible: mode === Camera.ORTHOGRAPHIC_CAMERA, children: jsxs("div", { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Left", target: camera, step: 0.1, propertyKey: "orthoLeft", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Right", target: camera, step: 0.1, propertyKey: "orthoRight", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Top", target: camera, step: 0.1, propertyKey: "orthoTop", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Bottom", target: camera, step: 0.1, propertyKey: "orthoBottom", nullable: true, defaultValue: 0 })] }) })] }));
|
|
12580
12979
|
};
|
|
12581
12980
|
|
|
12582
12981
|
const FollowCameraTransformProperties = (props) => {
|
|
@@ -13295,7 +13694,7 @@ const Gradient = (props) => {
|
|
|
13295
13694
|
// Only use compact mode when there are numeric values (spinbuttons) taking up space
|
|
13296
13695
|
const hasNumericValues = !(gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4) ||
|
|
13297
13696
|
(gradient.value2 !== undefined && !(gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4));
|
|
13298
|
-
return (jsxs("div", { id: "gradientContainer", className: classes.container, children: [jsx("div", { className: gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4 ? classes.colorWrapper : classes.valueWrapper, children: gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4 ? (jsx(ColorPickerPopup, { value: gradient.value1, onChange: (color) => gradientChange({ ...gradient, value1: color }) })) : (jsx(SyncedSliderInput, { step: 0.01, value: gradient.value1, onChange: (val) => gradientChange({ ...gradient, value1: val }), compact: true })) }), gradient.value2 !== undefined && (jsx("div", { className: gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4 ? classes.colorWrapper : classes.valueWrapper, children: gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4 ? (jsx(ColorPickerPopup, { value: gradient.value2, onChange: (color) => gradientChange({ ...gradient, value2: color }) })) : (jsx(SyncedSliderInput, { step: 0.01, value: gradient.value2, onChange: (val) => gradientChange({ ...gradient, value2: val }), compact: true })) })), jsx("div", { className: classes.stepSliderWrapper, children: jsx(SyncedSliderInput, { notifyOnlyOnRelease: true, min: 0, max: 1, step: 0.01, value: gradient.step, onChange: (val) => gradientChange({ ...gradient, step: val }), compact: hasNumericValues, growSlider: !hasNumericValues }) })] }));
|
|
13697
|
+
return (jsxs("div", { id: "gradientContainer", className: classes.container, children: [jsx("div", { className: gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4 ? classes.colorWrapper : classes.valueWrapper, children: gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4 ? (jsx(ColorPickerPopup, { value: gradient.value1, onChange: (color) => gradientChange({ ...gradient, value1: color }) })) : (jsx(SyncedSliderInput, { step: 0.01, precision: 2, value: gradient.value1, onChange: (val) => gradientChange({ ...gradient, value1: val }), compact: true })) }), gradient.value2 !== undefined && (jsx("div", { className: gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4 ? classes.colorWrapper : classes.valueWrapper, children: gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4 ? (jsx(ColorPickerPopup, { value: gradient.value2, onChange: (color) => gradientChange({ ...gradient, value2: color }) })) : (jsx(SyncedSliderInput, { step: 0.01, precision: 2, value: gradient.value2, onChange: (val) => gradientChange({ ...gradient, value2: val }), compact: true })) })), jsx("div", { className: classes.stepSliderWrapper, children: jsx(SyncedSliderInput, { notifyOnlyOnRelease: true, min: 0, max: 1, step: 0.01, precision: 2, value: gradient.step, onChange: (val) => gradientChange({ ...gradient, step: val }), compact: hasNumericValues, growSlider: !hasNumericValues }) })] }));
|
|
13299
13698
|
};
|
|
13300
13699
|
const FactorGradientCast = Gradient;
|
|
13301
13700
|
const Color3GradientCast = Gradient;
|
|
@@ -14166,7 +14565,7 @@ const PBRBaseMaterialDebugProperties = (props) => {
|
|
|
14166
14565
|
const SkyMaterialProperties = (props) => {
|
|
14167
14566
|
const { material } = props;
|
|
14168
14567
|
const [toDisplayAngle, fromDisplayAngle, useDegrees] = useAngleConverters();
|
|
14169
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component:
|
|
14568
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Azimuth", description: `Azimuth angle in ${useDegrees ? "degrees" : "radians"}`, target: material, propertyKey: "azimuth", step: toDisplayAngle(0.001), unit: useDegrees ? "°" : "rad", convertTo: toDisplayAngle, convertFrom: fromDisplayAngle, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Inclination", description: `Inclination angle in ${useDegrees ? "degrees" : "radians"}`, target: material, propertyKey: "inclination", min: toDisplayAngle(0), max: toDisplayAngle(Math.PI / 2), step: toDisplayAngle(0.001), unit: useDegrees ? "°" : "rad", convertTo: toDisplayAngle, convertFrom: fromDisplayAngle, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Turbidity", description: "Atmospheric turbidity.", target: material, propertyKey: "turbidity", min: 0, max: 100, step: 0.1, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Luminance", description: "Brightness of the sky (0 to 1).", target: material, propertyKey: "luminance", min: 0, max: 1, step: 0.001, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Rayleigh", description: "Rayleigh scattering coefficient (0 to 4).", target: material, propertyKey: "rayleigh", min: 0, max: 4, step: 0.001, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Mie Directional G", description: "Mie directional scattering (0 to 1).", target: material, propertyKey: "mieDirectionalG", min: 0, max: 1, step: 0.001, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Mie Coefficient", description: "Mie scattering coefficient (0 to 1).", target: material, propertyKey: "mieCoefficient", min: 0, max: 1, step: 0.001, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Distance", description: "Distance to the sky dome (0 to 1000 units).", target: material, propertyKey: "distance", min: 0, max: 1000, step: 0.1, docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Sun Pos", description: "Enable custom sun position.", target: material, propertyKey: "useSunPosition", docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Sun Position", description: "Custom sun position (Vector3).", target: material, propertyKey: "sunPosition", docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#configuring-the-sky-material" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Camera Offset", description: "Offset for the camera (Vector3).", target: material, propertyKey: "cameraOffset", docLink: "https://doc.babylonjs.com/toolsAndResources/assetLibraries/materialsLibrary/skyMat/#keeping-the-horizon-relative-to-the-camera-elevation" })] }));
|
|
14170
14569
|
};
|
|
14171
14570
|
|
|
14172
14571
|
const StandardMaterialGeneralProperties = (props) => {
|
|
@@ -17336,7 +17735,7 @@ const SpriteGeneralProperties = (props) => {
|
|
|
17336
17735
|
const SpriteTransformProperties = (props) => {
|
|
17337
17736
|
const { sprite } = props;
|
|
17338
17737
|
const [toDisplayAngle, fromDisplayAngle, useDegrees] = useAngleConverters();
|
|
17339
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Position", target: sprite, propertyKey: "position" }), jsx(BoundProperty, { component:
|
|
17738
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Position", target: sprite, propertyKey: "position" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Angle", description: `Rotation angle of the sprite in ${useDegrees ? "degrees" : "radians"}`, step: toDisplayAngle(0.01), unit: useDegrees ? "°" : "rad", target: sprite, propertyKey: "angle", convertTo: toDisplayAngle, convertFrom: fromDisplayAngle }, "Angle"), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Width", description: "Width of the sprite (in world space units)", target: sprite, propertyKey: "width" }, "Width"), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Height", description: "Height of the sprite (in world space units)", target: sprite, propertyKey: "height" }, "Height")] }));
|
|
17340
17739
|
};
|
|
17341
17740
|
const SpriteAnimationProperties = (props) => {
|
|
17342
17741
|
const { sprite } = props;
|
|
@@ -18930,7 +19329,7 @@ const Contrast = {
|
|
|
18930
19329
|
const handleExposureChange = (_, data) => {
|
|
18931
19330
|
setExposure(data.value);
|
|
18932
19331
|
};
|
|
18933
|
-
return (jsxs("div", { className: classes.settingsContainer, children: [jsxs("div", { className: classes.sliderRow, children: [jsxs(Label, { children: ["Contrast: ", contrast] }), jsx(Slider, { min: -100, max: 100, value: contrast, onChange: handleContrastChange })] }), jsxs("div", { className: classes.sliderRow, children: [jsxs(Label, { children: ["Exposure: ", exposure] }), jsx(Slider, { min: -100, max: 100, value: exposure, onChange: handleExposureChange })] })] }));
|
|
19332
|
+
return (jsxs("div", { className: classes.settingsContainer, children: [jsxs("div", { className: classes.sliderRow, children: [jsxs(Label, { children: ["Contrast: ", contrast] }), jsx(Slider$1, { min: -100, max: 100, value: contrast, onChange: handleContrastChange })] }), jsxs("div", { className: classes.sliderRow, children: [jsxs(Label, { children: ["Exposure: ", exposure] }), jsx(Slider$1, { min: -100, max: 100, value: exposure, onChange: handleExposureChange })] })] }));
|
|
18934
19333
|
},
|
|
18935
19334
|
};
|
|
18936
19335
|
},
|
|
@@ -19152,7 +19551,7 @@ const Paintbrush = {
|
|
|
19152
19551
|
const handleWidthChange = (_, data) => {
|
|
19153
19552
|
setWidth(data.value);
|
|
19154
19553
|
};
|
|
19155
|
-
return (jsx("div", { className: classes.settingsContainer, children: jsxs("div", { className: classes.sliderRow, children: [jsxs(Label, { children: ["Size: ", width] }), jsx(Slider, { min: 1, max: 100, value: width, onChange: handleWidthChange })] }) }));
|
|
19554
|
+
return (jsx("div", { className: classes.settingsContainer, children: jsxs("div", { className: classes.sliderRow, children: [jsxs(Label, { children: ["Size: ", width] }), jsx(Slider$1, { min: 1, max: 100, value: width, onChange: handleWidthChange })] }) }));
|
|
19156
19555
|
},
|
|
19157
19556
|
};
|
|
19158
19557
|
},
|
|
@@ -19397,7 +19796,7 @@ const TransformProperties = (props) => {
|
|
|
19397
19796
|
const quatRotation = useQuaternionProperty(transform, "rotationQuaternion");
|
|
19398
19797
|
const [useDegrees] = useSetting(UseDegreesSettingDescriptor);
|
|
19399
19798
|
const [useEuler] = useSetting(UseEulerSettingDescriptor);
|
|
19400
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Position", target: transform, propertyKey: "position" }), quatRotation ? (jsx(Property, { component: QuaternionPropertyLine, label: "Rotation
|
|
19799
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Position", target: transform, propertyKey: "position" }), quatRotation ? (jsx(Property, { component: QuaternionPropertyLine, label: "Rotation", propertyPath: "rotationQuaternion", value: quatRotation, onChange: (val) => (transform.rotationQuaternion = val), useDegrees: useDegrees, useEuler: useEuler })) : (jsx(BoundProperty, { component: RotationVectorPropertyLine, label: "Rotation", target: transform, propertyKey: "rotation", useDegrees: useDegrees })), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Scaling", target: transform, propertyKey: "scaling", step: 0.1 })] }));
|
|
19401
19800
|
};
|
|
19402
19801
|
|
|
19403
19802
|
const TransformPropertiesServiceDefinition = {
|
|
@@ -19425,8 +19824,8 @@ const TransformPropertiesServiceDefinition = {
|
|
|
19425
19824
|
|
|
19426
19825
|
const AnimationGroupExplorerServiceDefinition = {
|
|
19427
19826
|
friendlyName: "Animation Group Explorer",
|
|
19428
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
19429
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
19827
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
19828
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
19430
19829
|
const scene = sceneContext.currentScene;
|
|
19431
19830
|
if (!scene) {
|
|
19432
19831
|
return undefined;
|
|
@@ -19439,11 +19838,7 @@ const AnimationGroupExplorerServiceDefinition = {
|
|
|
19439
19838
|
getEntityDisplayInfo: (entity) => {
|
|
19440
19839
|
const namedEntity = entity instanceof AnimationGroup ? entity : entity.animation;
|
|
19441
19840
|
const onChangeObservable = new Observable();
|
|
19442
|
-
const nameHookToken =
|
|
19443
|
-
afterSet: () => {
|
|
19444
|
-
onChangeObservable.notifyObservers();
|
|
19445
|
-
},
|
|
19446
|
-
});
|
|
19841
|
+
const nameHookToken = watcherService.watchProperty(namedEntity, "name", () => onChangeObservable.notifyObservers());
|
|
19447
19842
|
return {
|
|
19448
19843
|
get name() {
|
|
19449
19844
|
return namedEntity.name;
|
|
@@ -19509,8 +19904,8 @@ const AnimationGroupExplorerServiceDefinition = {
|
|
|
19509
19904
|
|
|
19510
19905
|
const AtmosphereExplorerServiceDefinition = {
|
|
19511
19906
|
friendlyName: "Atmosphere Explorer",
|
|
19512
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
19513
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
19907
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
19908
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
19514
19909
|
const scene = sceneContext.currentScene;
|
|
19515
19910
|
if (!scene) {
|
|
19516
19911
|
return undefined;
|
|
@@ -19521,11 +19916,7 @@ const AtmosphereExplorerServiceDefinition = {
|
|
|
19521
19916
|
getRootEntities: () => (scene.getExternalData("atmosphere") ? [scene.getExternalData("atmosphere")] : []),
|
|
19522
19917
|
getEntityDisplayInfo: (atmosphere) => {
|
|
19523
19918
|
const onChangeObservable = new Observable();
|
|
19524
|
-
const nameHookToken =
|
|
19525
|
-
afterSet: () => {
|
|
19526
|
-
onChangeObservable.notifyObservers();
|
|
19527
|
-
},
|
|
19528
|
-
});
|
|
19919
|
+
const nameHookToken = watcherService.watchProperty(atmosphere, "name", () => onChangeObservable.notifyObservers());
|
|
19529
19920
|
return {
|
|
19530
19921
|
get name() {
|
|
19531
19922
|
return atmosphere.name;
|
|
@@ -19584,8 +19975,8 @@ const DisposableCommandServiceDefinition = {
|
|
|
19584
19975
|
|
|
19585
19976
|
const EffectLayerExplorerServiceDefinition = {
|
|
19586
19977
|
friendlyName: "Effect Layer Explorer",
|
|
19587
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
19588
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
19978
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
19979
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
19589
19980
|
const scene = sceneContext.currentScene;
|
|
19590
19981
|
if (!scene) {
|
|
19591
19982
|
return undefined;
|
|
@@ -19596,11 +19987,7 @@ const EffectLayerExplorerServiceDefinition = {
|
|
|
19596
19987
|
getRootEntities: () => scene.effectLayers,
|
|
19597
19988
|
getEntityDisplayInfo: (effectLayer) => {
|
|
19598
19989
|
const onChangeObservable = new Observable();
|
|
19599
|
-
const nameHookToken =
|
|
19600
|
-
afterSet: () => {
|
|
19601
|
-
onChangeObservable.notifyObservers();
|
|
19602
|
-
},
|
|
19603
|
-
});
|
|
19990
|
+
const nameHookToken = watcherService.watchProperty(effectLayer, "name", () => onChangeObservable.notifyObservers());
|
|
19604
19991
|
return {
|
|
19605
19992
|
get name() {
|
|
19606
19993
|
return effectLayer.name;
|
|
@@ -19626,8 +20013,8 @@ const EffectLayerExplorerServiceDefinition = {
|
|
|
19626
20013
|
|
|
19627
20014
|
const FrameGraphExplorerServiceDefinition = {
|
|
19628
20015
|
friendlyName: "Frame Graph Explorer",
|
|
19629
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
19630
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20016
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20017
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
19631
20018
|
const scene = sceneContext.currentScene;
|
|
19632
20019
|
if (!scene) {
|
|
19633
20020
|
return undefined;
|
|
@@ -19638,11 +20025,7 @@ const FrameGraphExplorerServiceDefinition = {
|
|
|
19638
20025
|
getRootEntities: () => scene.frameGraphs,
|
|
19639
20026
|
getEntityDisplayInfo: (frameGraph) => {
|
|
19640
20027
|
const onChangeObservable = new Observable();
|
|
19641
|
-
const nameHookToken =
|
|
19642
|
-
afterSet: () => {
|
|
19643
|
-
onChangeObservable.notifyObservers();
|
|
19644
|
-
},
|
|
19645
|
-
});
|
|
20028
|
+
const nameHookToken = watcherService.watchProperty(frameGraph, "name", () => onChangeObservable.notifyObservers());
|
|
19646
20029
|
return {
|
|
19647
20030
|
get name() {
|
|
19648
20031
|
return frameGraph.name;
|
|
@@ -19663,9 +20046,7 @@ const FrameGraphExplorerServiceDefinition = {
|
|
|
19663
20046
|
order: 900 /* DefaultCommandsOrder.FrameGraphPlay */,
|
|
19664
20047
|
getCommand: (frameGraph) => {
|
|
19665
20048
|
const onChangeObservable = new Observable();
|
|
19666
|
-
const frameGraphHook =
|
|
19667
|
-
afterSet: () => onChangeObservable.notifyObservers(),
|
|
19668
|
-
});
|
|
20049
|
+
const frameGraphHook = watcherService.watchProperty(scene, "frameGraph", () => onChangeObservable.notifyObservers());
|
|
19669
20050
|
return {
|
|
19670
20051
|
type: "toggle",
|
|
19671
20052
|
displayName: "Make Active",
|
|
@@ -19728,8 +20109,8 @@ function IsControl(entity) {
|
|
|
19728
20109
|
}
|
|
19729
20110
|
const GuiExplorerServiceDefinition = {
|
|
19730
20111
|
friendlyName: "GUI Explorer",
|
|
19731
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
19732
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20112
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20113
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
19733
20114
|
const scene = sceneContext.currentScene;
|
|
19734
20115
|
if (!scene) {
|
|
19735
20116
|
return undefined;
|
|
@@ -19755,10 +20136,8 @@ const GuiExplorerServiceDefinition = {
|
|
|
19755
20136
|
const disposeActions = [];
|
|
19756
20137
|
const onChangeObservable = new Observable();
|
|
19757
20138
|
disposeActions.push(() => onChangeObservable.clear());
|
|
19758
|
-
const nameHookToken =
|
|
19759
|
-
|
|
19760
|
-
onChangeObservable.notifyObservers();
|
|
19761
|
-
},
|
|
20139
|
+
const nameHookToken = watcherService.watchProperty(entity, "name", () => {
|
|
20140
|
+
onChangeObservable.notifyObservers();
|
|
19762
20141
|
});
|
|
19763
20142
|
disposeActions.push(() => nameHookToken.dispose());
|
|
19764
20143
|
if (!IsAdvancedDynamicTexture(entity) && IsContainer(entity)) {
|
|
@@ -19815,9 +20194,7 @@ const GuiExplorerServiceDefinition = {
|
|
|
19815
20194
|
order: 1000 /* DefaultCommandsOrder.GuiHighlight */,
|
|
19816
20195
|
getCommand: (control) => {
|
|
19817
20196
|
const onChangeObservable = new Observable();
|
|
19818
|
-
const showBoundingBoxHook =
|
|
19819
|
-
afterSet: () => onChangeObservable.notifyObservers(),
|
|
19820
|
-
});
|
|
20197
|
+
const showBoundingBoxHook = watcherService.watchProperty(control, "isHighlighted", () => onChangeObservable.notifyObservers());
|
|
19821
20198
|
return {
|
|
19822
20199
|
type: "toggle",
|
|
19823
20200
|
get displayName() {
|
|
@@ -19873,8 +20250,8 @@ const GuiExplorerServiceDefinition = {
|
|
|
19873
20250
|
|
|
19874
20251
|
const MaterialExplorerServiceDefinition = {
|
|
19875
20252
|
friendlyName: "Material Explorer",
|
|
19876
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
19877
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20253
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20254
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
19878
20255
|
const scene = sceneContext.currentScene;
|
|
19879
20256
|
if (!scene) {
|
|
19880
20257
|
return undefined;
|
|
@@ -19885,11 +20262,7 @@ const MaterialExplorerServiceDefinition = {
|
|
|
19885
20262
|
getRootEntities: () => [...scene.materials, ...scene.multiMaterials],
|
|
19886
20263
|
getEntityDisplayInfo: (material) => {
|
|
19887
20264
|
const onChangeObservable = new Observable();
|
|
19888
|
-
const nameHookToken =
|
|
19889
|
-
afterSet: () => {
|
|
19890
|
-
onChangeObservable.notifyObservers();
|
|
19891
|
-
},
|
|
19892
|
-
});
|
|
20265
|
+
const nameHookToken = watcherService.watchProperty(material, "name", () => onChangeObservable.notifyObservers());
|
|
19893
20266
|
return {
|
|
19894
20267
|
get name() {
|
|
19895
20268
|
return material.name;
|
|
@@ -19929,8 +20302,8 @@ const MaterialExplorerServiceDefinition = {
|
|
|
19929
20302
|
|
|
19930
20303
|
const NodeExplorerServiceDefinition = {
|
|
19931
20304
|
friendlyName: "Node Explorer",
|
|
19932
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, GizmoServiceIdentity],
|
|
19933
|
-
factory: (sceneExplorerService, sceneContext, gizmoService) => {
|
|
20305
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, GizmoServiceIdentity, WatcherServiceIdentity],
|
|
20306
|
+
factory: (sceneExplorerService, sceneContext, gizmoService, watcherService) => {
|
|
19934
20307
|
const scene = sceneContext.currentScene;
|
|
19935
20308
|
if (!scene) {
|
|
19936
20309
|
return undefined;
|
|
@@ -19969,14 +20342,8 @@ const NodeExplorerServiceDefinition = {
|
|
|
19969
20342
|
getEntityChildren: (node) => node.getChildren(),
|
|
19970
20343
|
getEntityDisplayInfo: (node) => {
|
|
19971
20344
|
const onChangeObservable = new Observable();
|
|
19972
|
-
const nameHookToken =
|
|
19973
|
-
|
|
19974
|
-
});
|
|
19975
|
-
const parentHookToken = InterceptProperty(node, "parent", {
|
|
19976
|
-
afterSet: () => {
|
|
19977
|
-
nodeMovedObservable.notifyObservers(node);
|
|
19978
|
-
},
|
|
19979
|
-
});
|
|
20345
|
+
const nameHookToken = watcherService.watchProperty(node, "name", () => onChangeObservable.notifyObservers());
|
|
20346
|
+
const parentHookToken = watcherService.watchProperty(node, "parent", () => nodeMovedObservable.notifyObservers(node));
|
|
19980
20347
|
return {
|
|
19981
20348
|
get name() {
|
|
19982
20349
|
return node.name;
|
|
@@ -20039,9 +20406,7 @@ const NodeExplorerServiceDefinition = {
|
|
|
20039
20406
|
order: 1000 /* DefaultCommandsOrder.MeshBoundingBox */,
|
|
20040
20407
|
getCommand: (mesh) => {
|
|
20041
20408
|
const onChangeObservable = new Observable();
|
|
20042
|
-
const showBoundingBoxHook =
|
|
20043
|
-
afterSet: () => onChangeObservable.notifyObservers(),
|
|
20044
|
-
});
|
|
20409
|
+
const showBoundingBoxHook = watcherService.watchProperty(mesh, "showBoundingBox", () => onChangeObservable.notifyObservers());
|
|
20045
20410
|
return {
|
|
20046
20411
|
type: "toggle",
|
|
20047
20412
|
get displayName() {
|
|
@@ -20067,9 +20432,7 @@ const NodeExplorerServiceDefinition = {
|
|
|
20067
20432
|
order: 1100 /* DefaultCommandsOrder.MeshVisibility */,
|
|
20068
20433
|
getCommand: (mesh) => {
|
|
20069
20434
|
const onChangeObservable = new Observable();
|
|
20070
|
-
const isVisibleHook =
|
|
20071
|
-
afterSet: () => onChangeObservable.notifyObservers(),
|
|
20072
|
-
});
|
|
20435
|
+
const isVisibleHook = watcherService.watchProperty(mesh, "isVisible", () => onChangeObservable.notifyObservers());
|
|
20073
20436
|
return {
|
|
20074
20437
|
type: "toggle",
|
|
20075
20438
|
get displayName() {
|
|
@@ -20221,8 +20584,8 @@ const NodeExplorerServiceDefinition = {
|
|
|
20221
20584
|
|
|
20222
20585
|
const ParticleSystemExplorerServiceDefinition = {
|
|
20223
20586
|
friendlyName: "Particle System Explorer",
|
|
20224
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
20225
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20587
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20588
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
20226
20589
|
const scene = sceneContext.currentScene;
|
|
20227
20590
|
if (!scene) {
|
|
20228
20591
|
return undefined;
|
|
@@ -20233,11 +20596,7 @@ const ParticleSystemExplorerServiceDefinition = {
|
|
|
20233
20596
|
getRootEntities: () => scene.particleSystems,
|
|
20234
20597
|
getEntityDisplayInfo: (particleSystem) => {
|
|
20235
20598
|
const onChangeObservable = new Observable();
|
|
20236
|
-
const nameHookToken =
|
|
20237
|
-
afterSet: () => {
|
|
20238
|
-
onChangeObservable.notifyObservers();
|
|
20239
|
-
},
|
|
20240
|
-
});
|
|
20599
|
+
const nameHookToken = watcherService.watchProperty(particleSystem, "name", () => onChangeObservable.notifyObservers());
|
|
20241
20600
|
return {
|
|
20242
20601
|
get name() {
|
|
20243
20602
|
return particleSystem.name;
|
|
@@ -20277,8 +20636,8 @@ const ParticleSystemExplorerServiceDefinition = {
|
|
|
20277
20636
|
|
|
20278
20637
|
const PostProcessExplorerServiceDefinition = {
|
|
20279
20638
|
friendlyName: "Post Process Explorer",
|
|
20280
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
20281
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20639
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20640
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
20282
20641
|
const scene = sceneContext.currentScene;
|
|
20283
20642
|
if (!scene) {
|
|
20284
20643
|
return undefined;
|
|
@@ -20289,11 +20648,7 @@ const PostProcessExplorerServiceDefinition = {
|
|
|
20289
20648
|
getRootEntities: () => scene.postProcesses,
|
|
20290
20649
|
getEntityDisplayInfo: (postProcess) => {
|
|
20291
20650
|
const onChangeObservable = new Observable();
|
|
20292
|
-
const nameHookToken =
|
|
20293
|
-
afterSet: () => {
|
|
20294
|
-
onChangeObservable.notifyObservers();
|
|
20295
|
-
},
|
|
20296
|
-
});
|
|
20651
|
+
const nameHookToken = watcherService.watchProperty(postProcess, "name", () => onChangeObservable.notifyObservers());
|
|
20297
20652
|
return {
|
|
20298
20653
|
get name() {
|
|
20299
20654
|
return postProcess.name;
|
|
@@ -20351,8 +20706,8 @@ const RenderingPipelineExplorerServiceDefinition = {
|
|
|
20351
20706
|
|
|
20352
20707
|
const SkeletonExplorerServiceDefinition = {
|
|
20353
20708
|
friendlyName: "Skeleton Explorer",
|
|
20354
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
20355
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20709
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20710
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
20356
20711
|
const scene = sceneContext.currentScene;
|
|
20357
20712
|
if (!scene) {
|
|
20358
20713
|
return undefined;
|
|
@@ -20365,16 +20720,8 @@ const SkeletonExplorerServiceDefinition = {
|
|
|
20365
20720
|
getEntityChildren: (skeletonOrBone) => skeletonOrBone.getChildren(),
|
|
20366
20721
|
getEntityDisplayInfo: (skeletonOrBone) => {
|
|
20367
20722
|
const onChangeObservable = new Observable();
|
|
20368
|
-
const nameHookToken =
|
|
20369
|
-
|
|
20370
|
-
});
|
|
20371
|
-
const parentHookToken = skeletonOrBone instanceof Skeleton
|
|
20372
|
-
? null
|
|
20373
|
-
: InterceptProperty(skeletonOrBone, "parent", {
|
|
20374
|
-
afterSet: () => {
|
|
20375
|
-
boneMovedObservable.notifyObservers(skeletonOrBone);
|
|
20376
|
-
},
|
|
20377
|
-
});
|
|
20723
|
+
const nameHookToken = watcherService.watchProperty(skeletonOrBone, "name", () => onChangeObservable.notifyObservers());
|
|
20724
|
+
const parentHookToken = skeletonOrBone instanceof Skeleton ? null : watcherService.watchProperty(skeletonOrBone, "parent", () => boneMovedObservable.notifyObservers(skeletonOrBone));
|
|
20378
20725
|
return {
|
|
20379
20726
|
get name() {
|
|
20380
20727
|
return skeletonOrBone.name;
|
|
@@ -20402,8 +20749,8 @@ const SkeletonExplorerServiceDefinition = {
|
|
|
20402
20749
|
|
|
20403
20750
|
const SoundExplorerServiceDefinition = {
|
|
20404
20751
|
friendlyName: "Sound Explorer",
|
|
20405
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
20406
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20752
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20753
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
20407
20754
|
const scene = sceneContext.currentScene;
|
|
20408
20755
|
if (!scene) {
|
|
20409
20756
|
return undefined;
|
|
@@ -20429,25 +20776,14 @@ const SoundExplorerServiceDefinition = {
|
|
|
20429
20776
|
// If _mainSoundTrack is already defined, set up hooks immediately.
|
|
20430
20777
|
hookMainSoundTrack(scene.mainSoundTrack);
|
|
20431
20778
|
// Watch for _mainSoundTrack being set (it is lazily created by the mainSoundTrack getter in audioSceneComponent.ts).
|
|
20432
|
-
const mainSoundTrackHook =
|
|
20433
|
-
afterSet: () => hookMainSoundTrack(scene._mainSoundTrack),
|
|
20434
|
-
});
|
|
20779
|
+
const mainSoundTrackHook = watcherService.watchProperty(scene, "_mainSoundTrack", () => hookMainSoundTrack(scene._mainSoundTrack));
|
|
20435
20780
|
const sectionRegistration = sceneExplorerService.addSection({
|
|
20436
20781
|
displayName: "Sounds",
|
|
20437
20782
|
order: 1400 /* DefaultSectionsOrder.Sounds */,
|
|
20438
20783
|
getRootEntities: () => scene.mainSoundTrack?.soundCollection ?? [],
|
|
20439
20784
|
getEntityDisplayInfo: (sound) => {
|
|
20440
20785
|
const onChangeObservable = new Observable();
|
|
20441
|
-
const
|
|
20442
|
-
afterSet: () => {
|
|
20443
|
-
onChangeObservable.notifyObservers();
|
|
20444
|
-
},
|
|
20445
|
-
});
|
|
20446
|
-
const nameHookToken = InterceptProperty(sound, "name", {
|
|
20447
|
-
afterSet: () => {
|
|
20448
|
-
onChangeObservable.notifyObservers();
|
|
20449
|
-
},
|
|
20450
|
-
});
|
|
20786
|
+
const nameHookToken = watcherService.watchProperty(sound, "name", () => onChangeObservable.notifyObservers());
|
|
20451
20787
|
return {
|
|
20452
20788
|
get name() {
|
|
20453
20789
|
return sound.name;
|
|
@@ -20455,7 +20791,6 @@ const SoundExplorerServiceDefinition = {
|
|
|
20455
20791
|
onChange: onChangeObservable,
|
|
20456
20792
|
dispose: () => {
|
|
20457
20793
|
nameHookToken.dispose();
|
|
20458
|
-
displayNameHookToken.dispose();
|
|
20459
20794
|
onChangeObservable.clear();
|
|
20460
20795
|
},
|
|
20461
20796
|
};
|
|
@@ -20479,8 +20814,8 @@ const SoundExplorerServiceDefinition = {
|
|
|
20479
20814
|
|
|
20480
20815
|
const SpriteManagerExplorerServiceDefinition = {
|
|
20481
20816
|
friendlyName: "Sprite Manager Explorer",
|
|
20482
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
20483
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20817
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20818
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
20484
20819
|
const scene = sceneContext.currentScene;
|
|
20485
20820
|
if (!scene) {
|
|
20486
20821
|
return undefined;
|
|
@@ -20492,9 +20827,7 @@ const SpriteManagerExplorerServiceDefinition = {
|
|
|
20492
20827
|
getEntityChildren: (spriteEntity) => (spriteEntity instanceof Sprite ? [] : spriteEntity.sprites),
|
|
20493
20828
|
getEntityDisplayInfo: (spriteEntity) => {
|
|
20494
20829
|
const onChangeObservable = new Observable();
|
|
20495
|
-
const nameHookToken =
|
|
20496
|
-
afterSet: () => onChangeObservable.notifyObservers(),
|
|
20497
|
-
});
|
|
20830
|
+
const nameHookToken = watcherService.watchProperty(spriteEntity, "name", () => onChangeObservable.notifyObservers());
|
|
20498
20831
|
return {
|
|
20499
20832
|
get name() {
|
|
20500
20833
|
return spriteEntity.name;
|
|
@@ -20552,8 +20885,8 @@ const SpriteManagerExplorerServiceDefinition = {
|
|
|
20552
20885
|
|
|
20553
20886
|
const TextureExplorerServiceDefinition = {
|
|
20554
20887
|
friendlyName: "Texture Explorer",
|
|
20555
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
20556
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
20888
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, WatcherServiceIdentity],
|
|
20889
|
+
factory: (sceneExplorerService, sceneContext, watcherService) => {
|
|
20557
20890
|
const scene = sceneContext.currentScene;
|
|
20558
20891
|
if (!scene) {
|
|
20559
20892
|
return undefined;
|
|
@@ -20564,16 +20897,8 @@ const TextureExplorerServiceDefinition = {
|
|
|
20564
20897
|
getRootEntities: () => scene.textures.filter((texture) => texture.getClassName() !== "AdvancedDynamicTexture"),
|
|
20565
20898
|
getEntityDisplayInfo: (texture) => {
|
|
20566
20899
|
const onChangeObservable = new Observable();
|
|
20567
|
-
const displayNameHookToken =
|
|
20568
|
-
|
|
20569
|
-
onChangeObservable.notifyObservers();
|
|
20570
|
-
},
|
|
20571
|
-
});
|
|
20572
|
-
const nameHookToken = InterceptProperty(texture, "name", {
|
|
20573
|
-
afterSet: () => {
|
|
20574
|
-
onChangeObservable.notifyObservers();
|
|
20575
|
-
},
|
|
20576
|
-
});
|
|
20900
|
+
const displayNameHookToken = watcherService.watchProperty(texture, "displayName", () => onChangeObservable.notifyObservers());
|
|
20901
|
+
const nameHookToken = watcherService.watchProperty(texture, "name", () => onChangeObservable.notifyObservers());
|
|
20577
20902
|
return {
|
|
20578
20903
|
get name() {
|
|
20579
20904
|
return texture.displayName || texture.name || `${texture.getClassName() || "Unnamed Texture"} (${texture.uniqueId})`;
|
|
@@ -21123,97 +21448,6 @@ const GLTFValidationServiceDefinition = {
|
|
|
21123
21448
|
},
|
|
21124
21449
|
};
|
|
21125
21450
|
|
|
21126
|
-
const HighlightSelectedEntitySettingDescriptor = {
|
|
21127
|
-
key: "HighlightSelectedEntity",
|
|
21128
|
-
defaultValue: true,
|
|
21129
|
-
};
|
|
21130
|
-
const HighlightServiceDefinition = {
|
|
21131
|
-
friendlyName: "Highlight Service",
|
|
21132
|
-
consumes: [SelectionServiceIdentity, SceneContextIdentity, SettingsStoreIdentity, ThemeServiceIdentity, GizmoServiceIdentity],
|
|
21133
|
-
factory: (selectionService, sceneContext, settingsStore, themeService, gizmoService) => {
|
|
21134
|
-
let outlineLayer = null;
|
|
21135
|
-
let utilityLayer = null;
|
|
21136
|
-
let currentScene = null;
|
|
21137
|
-
let activeCameraObserver = null;
|
|
21138
|
-
function disposeOutlineLayer() {
|
|
21139
|
-
outlineLayer?.dispose();
|
|
21140
|
-
outlineLayer = null;
|
|
21141
|
-
utilityLayer?.dispose();
|
|
21142
|
-
utilityLayer = null;
|
|
21143
|
-
currentScene = null;
|
|
21144
|
-
}
|
|
21145
|
-
function getOrCreateOutlineLayer(scene) {
|
|
21146
|
-
if (!outlineLayer || currentScene !== scene) {
|
|
21147
|
-
disposeOutlineLayer();
|
|
21148
|
-
utilityLayer = gizmoService.getUtilityLayer(scene);
|
|
21149
|
-
outlineLayer = new SelectionOutlineLayer("InspectorSelectionOutline", utilityLayer.value.utilityLayerScene);
|
|
21150
|
-
updateColor(outlineLayer);
|
|
21151
|
-
currentScene = scene;
|
|
21152
|
-
}
|
|
21153
|
-
return outlineLayer;
|
|
21154
|
-
}
|
|
21155
|
-
function updateColor(outlineLayer) {
|
|
21156
|
-
outlineLayer.outlineColor = Color3.FromHexString(themeService.theme.colorBrandForeground1);
|
|
21157
|
-
}
|
|
21158
|
-
function updateHighlight() {
|
|
21159
|
-
const scene = sceneContext.currentScene;
|
|
21160
|
-
const entity = selectionService.selectedEntity instanceof AbstractMesh && !(selectionService.selectedEntity instanceof GaussianSplattingMesh)
|
|
21161
|
-
? selectionService.selectedEntity
|
|
21162
|
-
: null;
|
|
21163
|
-
if (!entity || !settingsStore.readSetting(HighlightSelectedEntitySettingDescriptor) || !scene || !scene.activeCamera) {
|
|
21164
|
-
disposeOutlineLayer();
|
|
21165
|
-
return;
|
|
21166
|
-
}
|
|
21167
|
-
const layer = getOrCreateOutlineLayer(scene);
|
|
21168
|
-
layer.clearSelection();
|
|
21169
|
-
layer.addSelection(entity);
|
|
21170
|
-
}
|
|
21171
|
-
function watchActiveCamera(scene) {
|
|
21172
|
-
activeCameraObserver?.remove();
|
|
21173
|
-
activeCameraObserver = null;
|
|
21174
|
-
if (scene) {
|
|
21175
|
-
activeCameraObserver = scene.onActiveCameraChanged.add(updateHighlight);
|
|
21176
|
-
}
|
|
21177
|
-
}
|
|
21178
|
-
// React to theme changes.
|
|
21179
|
-
const themeObserver = themeService.onChanged.add(() => {
|
|
21180
|
-
if (outlineLayer) {
|
|
21181
|
-
updateColor(outlineLayer);
|
|
21182
|
-
}
|
|
21183
|
-
});
|
|
21184
|
-
// React to selection changes.
|
|
21185
|
-
const selectionObserver = selectionService.onSelectedEntityChanged.add(updateHighlight);
|
|
21186
|
-
// React to scene changes.
|
|
21187
|
-
const sceneObserver = sceneContext.currentSceneObservable.add(() => {
|
|
21188
|
-
// Dispose the old layer when the scene changes.
|
|
21189
|
-
disposeOutlineLayer();
|
|
21190
|
-
watchActiveCamera(sceneContext.currentScene);
|
|
21191
|
-
updateHighlight();
|
|
21192
|
-
});
|
|
21193
|
-
// React to setting changes.
|
|
21194
|
-
const settingObserver = settingsStore.onChanged.add((setting) => {
|
|
21195
|
-
if (setting === HighlightSelectedEntitySettingDescriptor.key) {
|
|
21196
|
-
updateHighlight();
|
|
21197
|
-
}
|
|
21198
|
-
});
|
|
21199
|
-
// Watch active camera on the initial scene.
|
|
21200
|
-
watchActiveCamera(sceneContext.currentScene);
|
|
21201
|
-
// Initial update.
|
|
21202
|
-
updateHighlight();
|
|
21203
|
-
return {
|
|
21204
|
-
dispose: () => {
|
|
21205
|
-
themeObserver.remove();
|
|
21206
|
-
selectionObserver.remove();
|
|
21207
|
-
sceneObserver.remove();
|
|
21208
|
-
settingObserver.remove();
|
|
21209
|
-
activeCameraObserver?.remove();
|
|
21210
|
-
activeCameraObserver = null;
|
|
21211
|
-
disposeOutlineLayer();
|
|
21212
|
-
},
|
|
21213
|
-
};
|
|
21214
|
-
},
|
|
21215
|
-
};
|
|
21216
|
-
|
|
21217
21451
|
const PickingToolbar = (props) => {
|
|
21218
21452
|
const { scene, selectEntity, gizmoService, ignoreBackfaces, highlightSelectedEntity, onHighlightSelectedEntityChange } = props;
|
|
21219
21453
|
const meshDataCache = useMemo(() => new WeakMap(), [scene]);
|
|
@@ -21322,7 +21556,7 @@ const PickingServiceDefinition = {
|
|
|
21322
21556
|
key: "Picking Service",
|
|
21323
21557
|
verticalLocation: "top",
|
|
21324
21558
|
horizontalLocation: "left",
|
|
21325
|
-
|
|
21559
|
+
teachingMoment: false,
|
|
21326
21560
|
component: () => {
|
|
21327
21561
|
const scene = useObservableState(() => sceneContext.currentScene, sceneContext.currentSceneObservable);
|
|
21328
21562
|
const selectEntity = useCallback((entity) => (selectionService.selectedEntity = entity), []);
|
|
@@ -21378,7 +21612,11 @@ const UserFeedbackServiceDefinition = {
|
|
|
21378
21612
|
key: "User Feedback",
|
|
21379
21613
|
verticalLocation: "bottom",
|
|
21380
21614
|
horizontalLocation: "right",
|
|
21381
|
-
|
|
21615
|
+
order: 100 /* DefaultToolbarItemOrder.Feedback */,
|
|
21616
|
+
teachingMoment: {
|
|
21617
|
+
title: "Feedback",
|
|
21618
|
+
description: "Press this button to give feedback on Inspector v2 and help us prioritize new features and improvements!",
|
|
21619
|
+
},
|
|
21382
21620
|
component: () => {
|
|
21383
21621
|
return (jsx(Tooltip, { content: "Give Feedback on Inspector v2", children: jsx(Button, { appearance: "subtle", icon: PersonFeedbackRegular, onClick: () => window.open("https://forum.babylonjs.com/t/introducing-inspector-v2/60937", "_blank") }) }));
|
|
21384
21622
|
},
|
|
@@ -21569,7 +21807,9 @@ function ShowInspector(scene, options = {}) {
|
|
|
21569
21807
|
// Tools pane tab and related services.
|
|
21570
21808
|
ToolsServiceDefinition, ExportServiceDefinition, GLTFAnimationImportServiceDefinition, GLTFLoaderOptionsServiceDefinition, GLTFValidationServiceDefinition, CaptureToolsDefinition,
|
|
21571
21809
|
// Settings pane tab and related services.
|
|
21572
|
-
SettingsServiceDefinition, ShellSettingsServiceDefinition,
|
|
21810
|
+
SettingsServiceDefinition, WatcherSettingsServiceDefinition, ShellSettingsServiceDefinition,
|
|
21811
|
+
// Adds a button to refresh all properties manually (when watcher is in "manual" mode).
|
|
21812
|
+
WatcherRefreshToolbarServiceDefinition,
|
|
21573
21813
|
// Tracks entity selection state (e.g. which Mesh or Material or other entity is currently selected in scene explorer and bound to the properties pane, etc.).
|
|
21574
21814
|
SelectionServiceDefinition,
|
|
21575
21815
|
// Gizmos for manipulating objects in the scene.
|
|
@@ -21803,19 +22043,15 @@ function ConvertOptions(v1Options) {
|
|
|
21803
22043
|
const { additionalNodes } = v1Options;
|
|
21804
22044
|
const additionalNodesServiceDefinition = {
|
|
21805
22045
|
friendlyName: "Additional Nodes (Backward Compatibility)",
|
|
21806
|
-
consumes: [SceneExplorerServiceIdentity],
|
|
21807
|
-
factory: (sceneExplorerService) => {
|
|
22046
|
+
consumes: [SceneExplorerServiceIdentity, WatcherServiceIdentity],
|
|
22047
|
+
factory: (sceneExplorerService, watcherService) => {
|
|
21808
22048
|
const sceneExplorerSectionRegistrations = additionalNodes.map((node) => sceneExplorerService.addSection({
|
|
21809
22049
|
displayName: node.name,
|
|
21810
22050
|
order: Number.MAX_SAFE_INTEGER,
|
|
21811
22051
|
getRootEntities: () => node.getContent(),
|
|
21812
22052
|
getEntityDisplayInfo: (entity) => {
|
|
21813
22053
|
const onChangeObservable = new Observable();
|
|
21814
|
-
const nameHookToken =
|
|
21815
|
-
afterSet: () => {
|
|
21816
|
-
onChangeObservable.notifyObservers();
|
|
21817
|
-
},
|
|
21818
|
-
});
|
|
22054
|
+
const nameHookToken = watcherService.watchProperty(entity, "name", () => onChangeObservable.notifyObservers());
|
|
21819
22055
|
return {
|
|
21820
22056
|
get name() {
|
|
21821
22057
|
return entity.name;
|
|
@@ -22406,5 +22642,5 @@ const TextAreaPropertyLine = (props) => {
|
|
|
22406
22642
|
// Attach Inspector v2 to Scene.debugLayer as a side effect for back compat.
|
|
22407
22643
|
AttachDebugLayer();
|
|
22408
22644
|
|
|
22409
|
-
export {
|
|
22410
|
-
//# sourceMappingURL=index-
|
|
22645
|
+
export { useObservableCollection as $, Accordion as A, Button as B, CheckboxPropertyLine as C, DebugServiceIdentity as D, ErrorBoundary as E, ExtensibleAccordion as F, GizmoServiceIdentity as G, Theme as H, Inspector as I, TeachingMoment as J, PropertyContext as K, LinkToEntity as L, MessageBar as M, NumberInputPropertyLine as N, usePropertyChangedNotifier as O, Popover as P, BuiltInsExtensionFeed as Q, useVector3Property as R, SpinButtonPropertyLine as S, TextInputPropertyLine as T, useColor3Property as U, Vector3PropertyLine as V, useColor4Property as W, useQuaternionProperty as X, MakePropertyHook as Y, useInterceptObservable as Z, useEventfulState as _, useProperty as a, Pane as a$, useOrderedObservableCollection as a0, usePollingObservable as a1, useResource as a2, useAsyncResource as a3, useSetting as a4, useAngleConverters as a5, MakeTeachingMoment as a6, MakeDialogTeachingMoment as a7, MakePopoverTeachingMoment as a8, useThemeMode as a9, Color3GradientComponent as aA, Color4GradientComponent as aB, ColorStepGradientComponent as aC, InfoLabel as aD, MakeLazyComponent as aE, List as aF, MaterialSelector as aG, NodeSelector as aH, PositionedPopover as aI, SearchBar as aJ, SearchBox as aK, SkeletonSelector as aL, SpinButton as aM, Switch as aN, SyncedSliderInput as aO, Textarea as aP, TextInput as aQ, TextureSelector as aR, ToastProvider as aS, ToggleButton as aT, Tooltip as aU, UploadButton as aV, ChildWindow as aW, FileUploadLine as aX, FactorGradientList as aY, Color3GradientList as aZ, Color4GradientList as a_, useTheme as aa, InterceptFunction as ab, GetPropertyDescriptor as ac, IsPropertyReadonly as ad, InterceptProperty as ae, ObservableCollection as af, ConstructorFactory as ag, SelectionServiceDefinition as ah, SettingsStore as ai, ShowInspector as aj, useKeyListener as ak, useKeyState as al, useEventListener as am, AccordionSectionItem as an, Checkbox as ao, Collapse as ap, ColorPickerPopup as aq, InputHexField as ar, InputHsvField as as, ComboBox as at, DraggableLine as au, Dropdown as av, NumberDropdown as aw, StringDropdown as ax, EntitySelector as ay, FactorGradientComponent as az, ShellServiceIdentity as b, TextureUpload as b0, BooleanBadgePropertyLine as b1, Color3PropertyLine as b2, Color4PropertyLine as b3, ComboBoxPropertyLine as b4, HexPropertyLine as b5, LinkPropertyLine as b6, PropertyLine as b7, LineContainer as b8, PlaceholderPropertyLine as b9, StringifiedPropertyLine as ba, SwitchPropertyLine as bb, SyncedSliderPropertyLine as bc, TextAreaPropertyLine as bd, TextPropertyLine as be, RotationVectorPropertyLine as bf, QuaternionPropertyLine as bg, Vector2PropertyLine as bh, Vector4PropertyLine as bi, SceneContextIdentity as c, SelectionServiceIdentity as d, useObservableState as e, AccordionSection as f, ButtonLine as g, ToolsServiceIdentity as h, useExtensionManager as i, Link as j, SidePaneContainer as k, PropertiesServiceIdentity as l, SceneExplorerServiceIdentity as m, SettingsServiceIdentity as n, StatsServiceIdentity as o, ThemeServiceIdentity as p, SettingsStoreIdentity as q, ConvertOptions as r, AttachDebugLayer as s, DetachDebugLayer as t, useToast as u, NumberDropdownPropertyLine as v, StringDropdownPropertyLine as w, BoundProperty as x, Property as y, LinkToEntityPropertyLine as z };
|
|
22646
|
+
//# sourceMappingURL=index-BvYg0Psk.js.map
|