@babylonjs/inspector 9.2.0 → 9.2.2
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/components/debug/debugPane.d.ts +1 -1
- package/lib/components/properties/postProcesses/postProcessProperties.d.ts +1 -1
- package/lib/components/properties/propertiesPane.d.ts +1 -1
- package/lib/components/properties/textures/texturePreview.d.ts +38 -0
- package/lib/components/scene/sceneExplorer.d.ts +5 -0
- package/lib/components/stats/statsPane.d.ts +1 -1
- package/lib/components/tools/toolsPane.d.ts +1 -1
- package/lib/extensibility/defaultInspectorExtensionFeed.d.ts +1 -1
- package/lib/extensions/quickCreate/quickCreateToolsService.d.ts +2 -2
- package/lib/{extensionsListService-eRZtqcfj.js → extensionsListService-B_R2ChvJ.js} +2 -2
- package/lib/extensionsListService-B_R2ChvJ.js.map +1 -0
- package/lib/hooks/settingsHooks.d.ts +0 -8
- package/lib/{index-FWuITINA.js → index-DB_fpb1t.js} +550 -234
- package/lib/index-DB_fpb1t.js.map +1 -0
- package/lib/index.d.ts +25 -21
- package/lib/index.js +1 -1
- package/lib/inspectable.d.ts +6 -1
- package/lib/inspector.d.ts +1 -1
- package/lib/legacy/inspectableCustomPropertiesService.d.ts +1 -1
- package/lib/misc/textureTools.d.ts +2 -1
- package/lib/{quickCreateToolsService-MzZbVrvr.js → quickCreateToolsService-DaBqYmZw.js} +2 -2
- package/lib/{quickCreateToolsService-MzZbVrvr.js.map → quickCreateToolsService-DaBqYmZw.js.map} +1 -1
- package/lib/{reflectorService-DdPEZLjO.js → reflectorService-5IVRhqd-.js} +2 -2
- package/lib/reflectorService-5IVRhqd-.js.map +1 -0
- package/lib/services/cli/cliConnectionStatus.d.ts +10 -4
- package/lib/services/cli/entityQueryService.d.ts +1 -1
- package/lib/services/cli/inspectableBridgeService.d.ts +5 -1
- package/lib/services/cli/inspectableCommandRegistry.d.ts +1 -1
- package/lib/services/cli/perfTraceCommandService.d.ts +1 -1
- package/lib/services/cli/screenshotCommandService.d.ts +1 -1
- package/lib/services/cli/shaderCommandService.d.ts +1 -1
- package/lib/services/cli/statsCommandService.d.ts +1 -1
- package/lib/services/cliConnectionStatusService.d.ts +2 -2
- package/lib/services/gizmoService.d.ts +1 -1
- package/lib/services/gizmoToolbarService.d.ts +2 -2
- package/lib/services/globalSettings.d.ts +2 -3
- package/lib/services/highlightService.d.ts +3 -3
- package/lib/services/inspectorSettingsService.d.ts +3 -0
- package/lib/services/miniStatsService.d.ts +2 -2
- package/lib/services/panes/debugService.d.ts +3 -3
- package/lib/services/panes/properties/animationGroupPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/animationPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/atmospherePropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/audioPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/cameraPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/commonPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/effectLayerPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/frameGraphPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/lightPropertiesServices.d.ts +1 -1
- package/lib/services/panes/properties/materialPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/metadataPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/nodePropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/particleSystemPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/physicsPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/postProcessPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/propertiesService.d.ts +3 -3
- package/lib/services/panes/properties/renderingPipelinePropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/scenePropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/skeletonPropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/spritePropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/texturePropertiesService.d.ts +1 -1
- package/lib/services/panes/properties/transformPropertiesService.d.ts +1 -1
- package/lib/services/panes/scene/animationGroupExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/atmosphereExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/disposableCommandService.d.ts +1 -1
- package/lib/services/panes/scene/effectLayersExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/frameGraphExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/guiExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/materialExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/nodeExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/particleSystemExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/postProcessExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/renderingPipelinesExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/sceneExplorerService.d.ts +2 -2
- package/lib/services/panes/scene/skeletonExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/soundExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/spriteManagerExplorerService.d.ts +1 -1
- package/lib/services/panes/scene/texturesExplorerService.d.ts +1 -1
- package/lib/services/panes/statsService.d.ts +3 -3
- package/lib/services/panes/tools/captureService.d.ts +1 -1
- package/lib/services/panes/tools/exportService.d.ts +1 -1
- package/lib/services/panes/tools/import/gltfAnimationImportService.d.ts +1 -1
- package/lib/services/panes/tools/import/gltfLoaderOptionsService.d.ts +4 -2
- package/lib/services/panes/tools/import/gltfValidationService.d.ts +1 -1
- package/lib/services/panes/tools/reflectorService.d.ts +1 -1
- package/lib/services/panes/toolsService.d.ts +3 -3
- package/lib/services/pickingService.d.ts +3 -3
- package/lib/services/sceneContext.d.ts +1 -1
- package/lib/services/selectionService.d.ts +4 -4
- package/lib/services/textureEditor/textureEditorService.d.ts +1 -1
- package/lib/services/userFeedbackService.d.ts +2 -2
- package/lib/services/watcherService.d.ts +5 -5
- package/package.json +1 -1
- package/lib/components/errorBoundary.d.ts +0 -31
- package/lib/components/extensibleAccordion.d.ts +0 -67
- package/lib/components/pane.d.ts +0 -4
- package/lib/components/teachingMoment.d.ts +0 -20
- package/lib/components/theme.d.ts +0 -10
- package/lib/components/uxContextProvider.d.ts +0 -2
- package/lib/contexts/extensionManagerContext.d.ts +0 -6
- package/lib/contexts/settingsContext.d.ts +0 -3
- package/lib/extensibility/builtInsExtensionFeed.d.ts +0 -21
- package/lib/extensibility/extensionFeed.d.ts +0 -113
- package/lib/extensibility/extensionManager.d.ts +0 -111
- package/lib/extensionsListService-eRZtqcfj.js.map +0 -1
- package/lib/hooks/observableHooks.d.ts +0 -35
- package/lib/hooks/resourceHooks.d.ts +0 -20
- package/lib/hooks/teachingMomentHooks.d.ts +0 -34
- package/lib/hooks/themeHooks.d.ts +0 -17
- package/lib/hooks/useResizeHandle.d.ts +0 -35
- package/lib/index-FWuITINA.js.map +0 -1
- package/lib/misc/assert.d.ts +0 -5
- package/lib/misc/graphUtils.d.ts +0 -44
- package/lib/misc/observableCollection.d.ts +0 -23
- package/lib/modularTool.d.ts +0 -42
- package/lib/modularity/serviceContainer.d.ts +0 -64
- package/lib/modularity/serviceDefinition.d.ts +0 -64
- package/lib/reflectorService-DdPEZLjO.js.map +0 -1
- package/lib/services/extensionsListService.d.ts +0 -3
- package/lib/services/panes/settingsService.d.ts +0 -25
- package/lib/services/reactContextService.d.ts +0 -18
- package/lib/services/settingsStore.d.ts +0 -55
- package/lib/services/shellService.d.ts +0 -256
- package/lib/services/shellSettingsService.d.ts +0 -3
- package/lib/services/themeSelectorService.d.ts +0 -3
- package/lib/services/themeService.d.ts +0 -60
- package/lib/themes/babylonTheme.d.ts +0 -3
|
@@ -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, useImperativeHandle, cloneElement, createElement, Suspense, memo, Fragment as Fragment$1, lazy } from 'react';
|
|
3
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, Body1Strong, mergeClasses, useId, useToastController, Toast, ToastTitle, FluentProvider, Toaster, Checkbox as Checkbox$1, createLightTheme, createDarkTheme, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, createDOMRenderer, RendererProvider, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, ToolbarRadioButton, MenuGroup, MenuGroupHeader, Switch as Switch$1, 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, useComboboxFilter, Combobox, Subtitle2, 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, PlugConnectedRegular,
|
|
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, WarningRegular, ArrowExpandAllRegular, ArrowCollapseAllRegular, CubeTreeRegular, BugRegular, ArrowUploadRegular, ArrowBidirectionalUpDownFilled, ArrowDownloadRegular, StopRegular, RecordRegular, DataBarHorizontalRegular, WrenchRegular, ArrowClockwiseRegular, WeatherSunnyRegular, WeatherMoonRegular, PlugDisconnectedRegular, PlugConnectedRegular, PlugConnectedCheckmarkRegular, 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, BubbleMultipleRegular, 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';
|
|
@@ -281,7 +281,7 @@ const Button = forwardRef((props, ref) => {
|
|
|
281
281
|
});
|
|
282
282
|
Button.displayName = "Button";
|
|
283
283
|
|
|
284
|
-
const useStyles$
|
|
284
|
+
const useStyles$_ = makeStyles({
|
|
285
285
|
root: {
|
|
286
286
|
display: "flex",
|
|
287
287
|
flexDirection: "column",
|
|
@@ -362,7 +362,7 @@ class ErrorBoundary extends Component {
|
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
364
|
function ErrorFallback({ error, onRetry }) {
|
|
365
|
-
const styles = useStyles$
|
|
365
|
+
const styles = useStyles$_();
|
|
366
366
|
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 })] }));
|
|
367
367
|
}
|
|
368
368
|
|
|
@@ -1277,12 +1277,12 @@ function useAccordionSectionItemState(props) {
|
|
|
1277
1277
|
// Debug: warn if itemId changes (should be stable)
|
|
1278
1278
|
const prevItemIdRef = useRef(itemId);
|
|
1279
1279
|
useEffect(() => {
|
|
1280
|
-
if (prevItemIdRef.current !== itemId) {
|
|
1280
|
+
if (accordionCtx && prevItemIdRef.current !== itemId) {
|
|
1281
1281
|
Logger.Warn(`Accordion: The uniqueId "${itemId}" in section "${sectionCtx?.sectionId}" has changed from "${prevItemIdRef.current}". ` +
|
|
1282
1282
|
`Each item must have a unique, stable ID for pin/hide persistence to work correctly.`);
|
|
1283
1283
|
}
|
|
1284
1284
|
prevItemIdRef.current = itemId;
|
|
1285
|
-
}, [itemId, sectionCtx?.sectionId]);
|
|
1285
|
+
}, [accordionCtx, itemId, sectionCtx?.sectionId]);
|
|
1286
1286
|
// Register item and detect duplicates (skip nested items, as children of other AccordionSectionItem should not participate in pin/hide/search).
|
|
1287
1287
|
useEffect(() => {
|
|
1288
1288
|
if (!accordionCtx || !itemUniqueId || isNested) {
|
|
@@ -1363,7 +1363,7 @@ function useIsSectionEmpty(sectionId) {
|
|
|
1363
1363
|
return hasItems;
|
|
1364
1364
|
}
|
|
1365
1365
|
|
|
1366
|
-
const useStyles$
|
|
1366
|
+
const useStyles$Z = makeStyles({
|
|
1367
1367
|
accordion: {
|
|
1368
1368
|
display: "flex",
|
|
1369
1369
|
flexDirection: "column",
|
|
@@ -1455,7 +1455,7 @@ const useStyles$Y = makeStyles({
|
|
|
1455
1455
|
*/
|
|
1456
1456
|
const AccordionMenuBar = () => {
|
|
1457
1457
|
AccordionMenuBar.displayName = "AccordionMenuBar";
|
|
1458
|
-
const classes = useStyles$
|
|
1458
|
+
const classes = useStyles$Z();
|
|
1459
1459
|
const accordionCtx = useContext(AccordionContext);
|
|
1460
1460
|
if (!accordionCtx) {
|
|
1461
1461
|
return null;
|
|
@@ -1479,7 +1479,7 @@ const AccordionMenuBar = () => {
|
|
|
1479
1479
|
const AccordionSectionBlock = (props) => {
|
|
1480
1480
|
AccordionSectionBlock.displayName = "AccordionSectionBlock";
|
|
1481
1481
|
const { children, sectionId } = props;
|
|
1482
|
-
const classes = useStyles$
|
|
1482
|
+
const classes = useStyles$Z();
|
|
1483
1483
|
const accordionCtx = useContext(AccordionContext);
|
|
1484
1484
|
const { context: sectionContext, isEmpty } = useAccordionSectionBlockContext(props);
|
|
1485
1485
|
if (accordionCtx) {
|
|
@@ -1499,7 +1499,7 @@ const AccordionSectionBlock = (props) => {
|
|
|
1499
1499
|
const AccordionSectionItem = (props) => {
|
|
1500
1500
|
AccordionSectionItem.displayName = "AccordionSectionItem";
|
|
1501
1501
|
const { children, staticItem } = props;
|
|
1502
|
-
const classes = useStyles$
|
|
1502
|
+
const classes = useStyles$Z();
|
|
1503
1503
|
const accordionCtx = useContext(AccordionContext);
|
|
1504
1504
|
const itemState = useAccordionSectionItemState(props);
|
|
1505
1505
|
const [ctrlMode, setCtrlMode] = useState(false);
|
|
@@ -1539,7 +1539,7 @@ const AccordionSectionItem = (props) => {
|
|
|
1539
1539
|
*/
|
|
1540
1540
|
const AccordionPinnedContainer = () => {
|
|
1541
1541
|
AccordionPinnedContainer.displayName = "AccordionPinnedContainer";
|
|
1542
|
-
const classes = useStyles$
|
|
1542
|
+
const classes = useStyles$Z();
|
|
1543
1543
|
const accordionCtx = useContext(AccordionContext);
|
|
1544
1544
|
return (jsx("div", { ref: accordionCtx?.pinnedContainerRef, className: classes.pinnedContainer, children: jsx(MessageBar$1, { className: classes.pinnedContainerEmpty, children: jsx(MessageBarBody, { children: "No pinned items" }) }) }));
|
|
1545
1545
|
};
|
|
@@ -1550,7 +1550,7 @@ const AccordionPinnedContainer = () => {
|
|
|
1550
1550
|
*/
|
|
1551
1551
|
const AccordionSearchBox = () => {
|
|
1552
1552
|
AccordionSearchBox.displayName = "AccordionSearchBox";
|
|
1553
|
-
const classes = useStyles$
|
|
1553
|
+
const classes = useStyles$Z();
|
|
1554
1554
|
const accordionCtx = useContext(AccordionContext);
|
|
1555
1555
|
if (!accordionCtx?.features.search) {
|
|
1556
1556
|
return null;
|
|
@@ -1566,7 +1566,7 @@ const AccordionSearchBox = () => {
|
|
|
1566
1566
|
*/
|
|
1567
1567
|
const AccordionSection = (props) => {
|
|
1568
1568
|
AccordionSection.displayName = "AccordionSection";
|
|
1569
|
-
const classes = useStyles$
|
|
1569
|
+
const classes = useStyles$Z();
|
|
1570
1570
|
return jsx("div", { className: classes.panelDiv, children: props.children });
|
|
1571
1571
|
};
|
|
1572
1572
|
const StringAccordion = Accordion$1;
|
|
@@ -1574,7 +1574,7 @@ const Accordion = forwardRef((props, ref) => {
|
|
|
1574
1574
|
Accordion.displayName = "Accordion";
|
|
1575
1575
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1576
1576
|
const { children, highlightSections, uniqueId, enablePinnedItems, enableHiddenItems, enableSearchItems, ...rest } = props;
|
|
1577
|
-
const classes = useStyles$
|
|
1577
|
+
const classes = useStyles$Z();
|
|
1578
1578
|
const { size } = useContext(ToolContext);
|
|
1579
1579
|
const accordionCtx = useAccordionContext(props);
|
|
1580
1580
|
const hasPinning = accordionCtx?.features.pinning ?? false;
|
|
@@ -1671,7 +1671,7 @@ const Collapse = (props) => {
|
|
|
1671
1671
|
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 }) }));
|
|
1672
1672
|
};
|
|
1673
1673
|
|
|
1674
|
-
const useStyles$
|
|
1674
|
+
const useStyles$Y = makeStyles({
|
|
1675
1675
|
button: {
|
|
1676
1676
|
display: "flex",
|
|
1677
1677
|
alignItems: "center",
|
|
@@ -1689,7 +1689,7 @@ const ToggleButton = (props) => {
|
|
|
1689
1689
|
ToggleButton.displayName = "ToggleButton";
|
|
1690
1690
|
const { value, onChange, title, appearance = "subtle" } = props;
|
|
1691
1691
|
const { size } = useContext(ToolContext);
|
|
1692
|
-
const classes = useStyles$
|
|
1692
|
+
const classes = useStyles$Y();
|
|
1693
1693
|
const [checked, setChecked] = useState(value);
|
|
1694
1694
|
const toggle = useCallback(() => {
|
|
1695
1695
|
setChecked((prevChecked) => {
|
|
@@ -1936,25 +1936,6 @@ function useSettingsStore() {
|
|
|
1936
1936
|
return useContext(SettingsStoreContext);
|
|
1937
1937
|
}
|
|
1938
1938
|
|
|
1939
|
-
// These are all "global" settings that aren't produced/owned by a specific service,
|
|
1940
|
-
// so we just add them by default directly in the SettingsService.
|
|
1941
|
-
const CompactModeSettingDescriptor = {
|
|
1942
|
-
key: "CompactMode",
|
|
1943
|
-
defaultValue: !matchMedia("(pointer: coarse)").matches,
|
|
1944
|
-
};
|
|
1945
|
-
const UseDegreesSettingDescriptor = {
|
|
1946
|
-
key: "UseDegrees",
|
|
1947
|
-
defaultValue: true,
|
|
1948
|
-
};
|
|
1949
|
-
const UseEulerSettingDescriptor = {
|
|
1950
|
-
key: "UseEuler",
|
|
1951
|
-
defaultValue: true,
|
|
1952
|
-
};
|
|
1953
|
-
const DisableCopySettingDescriptor = {
|
|
1954
|
-
key: "DisableCopy",
|
|
1955
|
-
defaultValue: false,
|
|
1956
|
-
};
|
|
1957
|
-
|
|
1958
1939
|
/**
|
|
1959
1940
|
* Hook that reads and writes a setting from the settings store.
|
|
1960
1941
|
* @param descriptor The setting descriptor that identifies the setting and its default value.
|
|
@@ -1990,35 +1971,15 @@ function useSetting(descriptor) {
|
|
|
1990
1971
|
}
|
|
1991
1972
|
return [value, setValue, resetValue];
|
|
1992
1973
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
* Gets functions used to convert to/from display values for angles based on the current settings.
|
|
2003
|
-
* @returns A tuple containing the functions to convert to and from display values.
|
|
2004
|
-
*/
|
|
2005
|
-
function useAngleConverters() {
|
|
2006
|
-
const [useDegrees] = useSetting(UseDegreesSettingDescriptor);
|
|
2007
|
-
const toDisplayValue = useCallback((angle, wrap = false) => {
|
|
2008
|
-
if (wrap) {
|
|
2009
|
-
angle = WrapAngle(angle);
|
|
2010
|
-
}
|
|
2011
|
-
return useDegrees ? angle * RadiansToDegrees : angle;
|
|
2012
|
-
}, [useDegrees]);
|
|
2013
|
-
const fromDisplayValue = useCallback((angle, wrap = false) => {
|
|
2014
|
-
angle = useDegrees ? angle / RadiansToDegrees : angle;
|
|
2015
|
-
if (wrap) {
|
|
2016
|
-
angle = WrapAngle(angle);
|
|
2017
|
-
}
|
|
2018
|
-
return angle;
|
|
2019
|
-
}, [useDegrees]);
|
|
2020
|
-
return [toDisplayValue, fromDisplayValue, useDegrees];
|
|
2021
|
-
}
|
|
1974
|
+
|
|
1975
|
+
const CompactModeSettingDescriptor = {
|
|
1976
|
+
key: "CompactMode",
|
|
1977
|
+
defaultValue: !matchMedia("(pointer: coarse)").matches,
|
|
1978
|
+
};
|
|
1979
|
+
const DisableCopySettingDescriptor = {
|
|
1980
|
+
key: "DisableCopy",
|
|
1981
|
+
defaultValue: false,
|
|
1982
|
+
};
|
|
2022
1983
|
|
|
2023
1984
|
const UXContextProvider = (props) => {
|
|
2024
1985
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
@@ -2037,7 +1998,7 @@ const UXContextProvider = (props) => {
|
|
|
2037
1998
|
function AsReadonlyArray(array) {
|
|
2038
1999
|
return array;
|
|
2039
2000
|
}
|
|
2040
|
-
const useStyles$
|
|
2001
|
+
const useStyles$X = makeStyles({
|
|
2041
2002
|
rootDiv: {
|
|
2042
2003
|
flex: 1,
|
|
2043
2004
|
overflow: "hidden",
|
|
@@ -2052,7 +2013,7 @@ const useStyles$W = makeStyles({
|
|
|
2052
2013
|
* @returns The extensible accordion component.
|
|
2053
2014
|
*/
|
|
2054
2015
|
function ExtensibleAccordion(props) {
|
|
2055
|
-
const classes = useStyles$
|
|
2016
|
+
const classes = useStyles$X();
|
|
2056
2017
|
const { children, sections, sectionContent, context, sectionsRef, ...rest } = props;
|
|
2057
2018
|
const defaultSections = useMemo(() => {
|
|
2058
2019
|
const defaultSections = [];
|
|
@@ -2177,7 +2138,7 @@ function ExtensibleAccordion(props) {
|
|
|
2177
2138
|
})] }) })) }));
|
|
2178
2139
|
}
|
|
2179
2140
|
|
|
2180
|
-
const useStyles$
|
|
2141
|
+
const useStyles$W = makeStyles({
|
|
2181
2142
|
paneRootDiv: {
|
|
2182
2143
|
display: "flex",
|
|
2183
2144
|
flex: 1,
|
|
@@ -2190,7 +2151,7 @@ const useStyles$V = makeStyles({
|
|
|
2190
2151
|
*/
|
|
2191
2152
|
const SidePaneContainer = forwardRef((props, ref) => {
|
|
2192
2153
|
const { className, ...rest } = props;
|
|
2193
|
-
const classes = useStyles$
|
|
2154
|
+
const classes = useStyles$W();
|
|
2194
2155
|
return (jsx("div", { className: mergeClasses(classes.paneRootDiv, className), ref: ref, ...rest, children: props.children }));
|
|
2195
2156
|
});
|
|
2196
2157
|
|
|
@@ -2461,7 +2422,7 @@ function useTheme(invert = false) {
|
|
|
2461
2422
|
}
|
|
2462
2423
|
|
|
2463
2424
|
// Fluent doesn't apply styling to scrollbars by default, so provide our own reasonable default.
|
|
2464
|
-
const useStyles$
|
|
2425
|
+
const useStyles$V = makeStyles({
|
|
2465
2426
|
root: {
|
|
2466
2427
|
scrollbarColor: `${tokens.colorNeutralForeground3} ${tokens.colorTransparentBackground}`,
|
|
2467
2428
|
},
|
|
@@ -2477,11 +2438,11 @@ const Theme = (props) => {
|
|
|
2477
2438
|
// break any UI within the portal. Therefore, default to false.
|
|
2478
2439
|
const { invert = false, applyStylesToPortals = false, className, ...rest } = props;
|
|
2479
2440
|
const theme = useTheme(invert);
|
|
2480
|
-
const classes = useStyles$
|
|
2441
|
+
const classes = useStyles$V();
|
|
2481
2442
|
return (jsx(FluentProvider, { theme: theme, className: mergeClasses(classes.root, className), applyStylesToPortals: applyStylesToPortals, ...rest, children: props.children }));
|
|
2482
2443
|
};
|
|
2483
2444
|
|
|
2484
|
-
const useStyles$
|
|
2445
|
+
const useStyles$U = makeStyles({
|
|
2485
2446
|
extensionTeachingPopover: {
|
|
2486
2447
|
maxWidth: "320px",
|
|
2487
2448
|
},
|
|
@@ -2492,7 +2453,7 @@ const useStyles$T = makeStyles({
|
|
|
2492
2453
|
* @returns The teaching moment popover.
|
|
2493
2454
|
*/
|
|
2494
2455
|
const TeachingMoment = ({ shouldDisplay, positioningRef, onOpenChange, title, description }) => {
|
|
2495
|
-
const classes = useStyles$
|
|
2456
|
+
const classes = useStyles$U();
|
|
2496
2457
|
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 })] }) }));
|
|
2497
2458
|
};
|
|
2498
2459
|
|
|
@@ -2540,6 +2501,47 @@ function usePollingObservable(delay) {
|
|
|
2540
2501
|
return observable;
|
|
2541
2502
|
}
|
|
2542
2503
|
|
|
2504
|
+
// These are all "global" settings that aren't produced/owned by a specific service,
|
|
2505
|
+
// so we just add them by default directly in the SettingsService.
|
|
2506
|
+
const UseDegreesSettingDescriptor = {
|
|
2507
|
+
key: "UseDegrees",
|
|
2508
|
+
defaultValue: true,
|
|
2509
|
+
};
|
|
2510
|
+
const UseEulerSettingDescriptor = {
|
|
2511
|
+
key: "UseEuler",
|
|
2512
|
+
defaultValue: true,
|
|
2513
|
+
};
|
|
2514
|
+
|
|
2515
|
+
const RadiansToDegrees = 180 / Math.PI;
|
|
2516
|
+
function WrapAngle(angle) {
|
|
2517
|
+
angle %= Math.PI * 2;
|
|
2518
|
+
if (angle < 0) {
|
|
2519
|
+
angle += Math.PI * 2;
|
|
2520
|
+
}
|
|
2521
|
+
return angle;
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* Gets functions used to convert to/from display values for angles based on the current settings.
|
|
2525
|
+
* @returns A tuple containing the functions to convert to and from display values.
|
|
2526
|
+
*/
|
|
2527
|
+
function useAngleConverters() {
|
|
2528
|
+
const [useDegrees] = useSetting(UseDegreesSettingDescriptor);
|
|
2529
|
+
const toDisplayValue = useCallback((angle, wrap = false) => {
|
|
2530
|
+
if (wrap) {
|
|
2531
|
+
angle = WrapAngle(angle);
|
|
2532
|
+
}
|
|
2533
|
+
return useDegrees ? angle * RadiansToDegrees : angle;
|
|
2534
|
+
}, [useDegrees]);
|
|
2535
|
+
const fromDisplayValue = useCallback((angle, wrap = false) => {
|
|
2536
|
+
angle = useDegrees ? angle / RadiansToDegrees : angle;
|
|
2537
|
+
if (wrap) {
|
|
2538
|
+
angle = WrapAngle(angle);
|
|
2539
|
+
}
|
|
2540
|
+
return angle;
|
|
2541
|
+
}, [useDegrees]);
|
|
2542
|
+
return [toDisplayValue, fromDisplayValue, useDegrees];
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2543
2545
|
const SequencerLock = new AsyncLock();
|
|
2544
2546
|
/**
|
|
2545
2547
|
* Creates a hook for managing teaching moment state.
|
|
@@ -2676,11 +2678,6 @@ function ConstructorFactory(constructor) {
|
|
|
2676
2678
|
return (...args) => new constructor(...args);
|
|
2677
2679
|
}
|
|
2678
2680
|
|
|
2679
|
-
/**
|
|
2680
|
-
* The unique identity symbol for the scene context service.
|
|
2681
|
-
*/
|
|
2682
|
-
const SceneContextIdentity = Symbol("SceneContext");
|
|
2683
|
-
|
|
2684
2681
|
function ToFeaturesString(options) {
|
|
2685
2682
|
const { defaultWidth, defaultHeight, defaultLeft, defaultTop } = options;
|
|
2686
2683
|
const features = [];
|
|
@@ -2948,7 +2945,7 @@ const RootComponentServiceIdentity = Symbol("RootComponent");
|
|
|
2948
2945
|
* The unique identity symbol for the shell service.
|
|
2949
2946
|
*/
|
|
2950
2947
|
const ShellServiceIdentity = Symbol("ShellService");
|
|
2951
|
-
const useStyles$
|
|
2948
|
+
const useStyles$T = makeStyles({
|
|
2952
2949
|
mainView: {
|
|
2953
2950
|
flex: 1,
|
|
2954
2951
|
display: "flex",
|
|
@@ -3161,14 +3158,14 @@ const DockMenu = (props) => {
|
|
|
3161
3158
|
};
|
|
3162
3159
|
const PaneHeader = (props) => {
|
|
3163
3160
|
const { id, title, dockOptions } = props;
|
|
3164
|
-
const classes = useStyles$
|
|
3161
|
+
const classes = useStyles$T();
|
|
3165
3162
|
return (jsxs("div", { className: classes.paneHeaderDiv, children: [props.icon && (jsx("div", { className: classes.paneHeaderIcon, children: jsx(props.icon, {}) })), jsx(Subtitle2Stronger, { className: mergeClasses(classes.paneHeaderText, !props.icon && classes.paneHeaderTextNoIcon), children: title }), jsx(DockMenu, { sidePaneId: id, dockOptions: dockOptions, children: jsx(Button$1, { className: classes.paneHeaderButton, appearance: "transparent", icon: jsx(MoreHorizontalRegular, {}) }) })] }));
|
|
3166
3163
|
};
|
|
3167
3164
|
// 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.
|
|
3168
3165
|
const ToolbarItem = (props) => {
|
|
3169
3166
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3170
3167
|
const { verticalLocation, horizontalLocation, id, component: Component, displayName } = props;
|
|
3171
|
-
const classes = useStyles$
|
|
3168
|
+
const classes = useStyles$T();
|
|
3172
3169
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Bar/${verticalLocation}/${horizontalLocation}/${displayName ?? id}`), [displayName, id]);
|
|
3173
3170
|
const teachingMoment = useTeachingMoment(props.teachingMoment === false);
|
|
3174
3171
|
const title = typeof props.teachingMoment === "object" ? props.teachingMoment.title : (displayName ?? id);
|
|
@@ -3178,7 +3175,7 @@ const ToolbarItem = (props) => {
|
|
|
3178
3175
|
// TODO: Handle overflow, possibly via https://react.fluentui.dev/?path=/docs/components-overflow--docs with priority.
|
|
3179
3176
|
// This component just renders a toolbar with left aligned toolbar items on the left and right aligned toolbar items on the right.
|
|
3180
3177
|
const Toolbar = ({ location, components }) => {
|
|
3181
|
-
const classes = useStyles$
|
|
3178
|
+
const classes = useStyles$T();
|
|
3182
3179
|
const leftComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "left"), [components]);
|
|
3183
3180
|
const rightComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "right"), [components]);
|
|
3184
3181
|
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))) })] })) }));
|
|
@@ -3188,7 +3185,7 @@ const SidePaneTab = (props) => {
|
|
|
3188
3185
|
const { location, id, isSelected, isFirst, isLast, dockOptions,
|
|
3189
3186
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3190
3187
|
icon: Icon, title, } = props;
|
|
3191
|
-
const classes = useStyles$
|
|
3188
|
+
const classes = useStyles$T();
|
|
3192
3189
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Pane/${location}/${title ?? id}`), [title, id]);
|
|
3193
3190
|
const teachingMoment = useTeachingMoment(props.teachingMoment === false);
|
|
3194
3191
|
const tabClass = mergeClasses(classes.tab, isSelected ? classes.selectedTab : classes.unselectedTab, isFirst ? classes.firstTab : undefined, isLast ? classes.lastTab : undefined);
|
|
@@ -3200,7 +3197,7 @@ const SidePaneTab = (props) => {
|
|
|
3200
3197
|
// In "compact" mode, the tab list is integrated into the pane itself.
|
|
3201
3198
|
// In "full" mode, the returned tab list is later injected into the toolbar.
|
|
3202
3199
|
function usePane(location, defaultWidth, minWidth, sidePanes, onSelectSidePane, dockOperations, toolbarMode, topBarItems, bottomBarItems, initialCollapsed) {
|
|
3203
|
-
const classes = useStyles$
|
|
3200
|
+
const classes = useStyles$T();
|
|
3204
3201
|
const [topSelectedTab, setTopSelectedTab] = useState();
|
|
3205
3202
|
const [bottomSelectedTab, setBottomSelectedTab] = useState();
|
|
3206
3203
|
const [collapsed, setCollapsed] = useState(initialCollapsed);
|
|
@@ -3397,7 +3394,7 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
|
|
|
3397
3394
|
expand: () => onCollapseChanged.notifyObservers({ location: "right", collapsed: false }),
|
|
3398
3395
|
};
|
|
3399
3396
|
const rootComponent = () => {
|
|
3400
|
-
const classes = useStyles$
|
|
3397
|
+
const classes = useStyles$T();
|
|
3401
3398
|
const [sidePaneDockOverrides, setSidePaneDockOverrides] = useSetting(SidePaneDockOverridesSettingDescriptor);
|
|
3402
3399
|
// This function returns a promise that resolves after the dock change takes effect so that
|
|
3403
3400
|
// we can then select the re-docked pane.
|
|
@@ -3617,6 +3614,46 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
|
|
|
3617
3614
|
};
|
|
3618
3615
|
}
|
|
3619
3616
|
|
|
3617
|
+
/**
|
|
3618
|
+
* The unique identity symbol for the settings service.
|
|
3619
|
+
*/
|
|
3620
|
+
const SettingsServiceIdentity = Symbol("SettingsService");
|
|
3621
|
+
const SettingsServiceDefinition = {
|
|
3622
|
+
friendlyName: "Settings",
|
|
3623
|
+
consumes: [ShellServiceIdentity],
|
|
3624
|
+
produces: [SettingsServiceIdentity],
|
|
3625
|
+
factory: (shellService) => {
|
|
3626
|
+
const sectionsCollection = new ObservableCollection();
|
|
3627
|
+
const sectionContentCollection = new ObservableCollection();
|
|
3628
|
+
const registration = shellService.addSidePane({
|
|
3629
|
+
key: "Settings",
|
|
3630
|
+
title: "Settings",
|
|
3631
|
+
icon: SettingsRegular,
|
|
3632
|
+
horizontalLocation: "right",
|
|
3633
|
+
verticalLocation: "top",
|
|
3634
|
+
order: 500,
|
|
3635
|
+
teachingMoment: false,
|
|
3636
|
+
content: () => {
|
|
3637
|
+
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
3638
|
+
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
3639
|
+
return jsx(ExtensibleAccordion, { sections: sections, sectionContent: sectionContent, context: true });
|
|
3640
|
+
},
|
|
3641
|
+
});
|
|
3642
|
+
return {
|
|
3643
|
+
addSection: (section) => sectionsCollection.add(section),
|
|
3644
|
+
addSectionContent: (content) => sectionContentCollection.add(content),
|
|
3645
|
+
dispose: () => {
|
|
3646
|
+
registration.dispose();
|
|
3647
|
+
},
|
|
3648
|
+
};
|
|
3649
|
+
},
|
|
3650
|
+
};
|
|
3651
|
+
|
|
3652
|
+
/**
|
|
3653
|
+
* The unique identity symbol for the scene context service.
|
|
3654
|
+
*/
|
|
3655
|
+
const SceneContextIdentity = Symbol("SceneContext");
|
|
3656
|
+
|
|
3620
3657
|
const useSwitchStyles = makeStyles({
|
|
3621
3658
|
switch: {
|
|
3622
3659
|
marginLeft: "auto",
|
|
@@ -3664,54 +3701,6 @@ const SwitchPropertyLine = (props) => {
|
|
|
3664
3701
|
return (jsx(PropertyLine, { ...props, children: jsx(Switch, { ...switchProps }) }));
|
|
3665
3702
|
};
|
|
3666
3703
|
|
|
3667
|
-
/**
|
|
3668
|
-
* The unique identity symbol for the settings service.
|
|
3669
|
-
*/
|
|
3670
|
-
const SettingsServiceIdentity = Symbol("SettingsService");
|
|
3671
|
-
const SettingsServiceDefinition = {
|
|
3672
|
-
friendlyName: "Settings",
|
|
3673
|
-
consumes: [ShellServiceIdentity, SceneContextIdentity],
|
|
3674
|
-
produces: [SettingsServiceIdentity],
|
|
3675
|
-
factory: (shellService, sceneContext) => {
|
|
3676
|
-
const sectionsCollection = new ObservableCollection();
|
|
3677
|
-
const sectionContentCollection = new ObservableCollection();
|
|
3678
|
-
const registration = shellService.addSidePane({
|
|
3679
|
-
key: "Settings",
|
|
3680
|
-
title: "Settings",
|
|
3681
|
-
icon: SettingsRegular,
|
|
3682
|
-
horizontalLocation: "right",
|
|
3683
|
-
verticalLocation: "top",
|
|
3684
|
-
order: 500,
|
|
3685
|
-
teachingMoment: false,
|
|
3686
|
-
content: () => {
|
|
3687
|
-
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
3688
|
-
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
3689
|
-
const scene = useObservableState(() => sceneContext.currentScene, sceneContext.currentSceneObservable);
|
|
3690
|
-
const [compactMode, setCompactMode] = useSetting(CompactModeSettingDescriptor);
|
|
3691
|
-
const [useDegrees, setUseDegrees] = useSetting(UseDegreesSettingDescriptor);
|
|
3692
|
-
const [useEuler, setUseEuler] = useSetting(UseEulerSettingDescriptor);
|
|
3693
|
-
const [disableCopy, setDisableCopy] = useSetting(DisableCopySettingDescriptor);
|
|
3694
|
-
return (jsx(Fragment, { children: scene && (jsx(ExtensibleAccordion, { sections: sections, sectionContent: sectionContent, context: scene, children: jsxs(AccordionSection, { title: "UI", children: [jsx(SwitchPropertyLine, { label: "Compact Mode", description: "Use a more compact UI with less spacing.", value: compactMode, onChange: (checked) => {
|
|
3695
|
-
setCompactMode(checked);
|
|
3696
|
-
} }), jsx(SwitchPropertyLine, { label: "Use Degrees", description: "Using degrees instead of radians.", value: useDegrees, onChange: (checked) => {
|
|
3697
|
-
setUseDegrees(checked);
|
|
3698
|
-
} }), jsx(SwitchPropertyLine, { label: "Only Show Euler Angles", description: "Only show Euler angles in rotation properties, rather than quaternions.", value: useEuler, onChange: (checked) => {
|
|
3699
|
-
setUseEuler(checked);
|
|
3700
|
-
} }), jsx(SwitchPropertyLine, { label: "Disable Copy Button", description: "Disables the copy to clipboard button on property lines. You can still Ctrl+Click on the label to copy.", value: disableCopy, onChange: (checked) => {
|
|
3701
|
-
setDisableCopy(checked);
|
|
3702
|
-
} })] }) })) }));
|
|
3703
|
-
},
|
|
3704
|
-
});
|
|
3705
|
-
return {
|
|
3706
|
-
addSection: (section) => sectionsCollection.add(section),
|
|
3707
|
-
addSectionContent: (content) => sectionContentCollection.add(content),
|
|
3708
|
-
dispose: () => {
|
|
3709
|
-
registration.dispose();
|
|
3710
|
-
},
|
|
3711
|
-
};
|
|
3712
|
-
},
|
|
3713
|
-
};
|
|
3714
|
-
|
|
3715
3704
|
/**
|
|
3716
3705
|
* The unique identity symbol for the selection service.
|
|
3717
3706
|
*/
|
|
@@ -3792,13 +3781,13 @@ function useImpulse() {
|
|
|
3792
3781
|
return [value, pulse];
|
|
3793
3782
|
}
|
|
3794
3783
|
|
|
3795
|
-
const useStyles$
|
|
3784
|
+
const useStyles$S = makeStyles({
|
|
3796
3785
|
placeholderDiv: {
|
|
3797
3786
|
padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalM}`,
|
|
3798
3787
|
},
|
|
3799
3788
|
});
|
|
3800
3789
|
const PropertiesPane = (props) => {
|
|
3801
|
-
const classes = useStyles$
|
|
3790
|
+
const classes = useStyles$S();
|
|
3802
3791
|
const entity = props.context;
|
|
3803
3792
|
return entity != null ? (jsx(ExtensibleAccordion, { ...props })) : (jsx("div", { className: classes.placeholderDiv, children: jsx(Body1Strong, { italic: true, children: "No entity selected." }) }));
|
|
3804
3793
|
};
|
|
@@ -4238,7 +4227,7 @@ function CoerceEntityArray(entities, sort) {
|
|
|
4238
4227
|
}
|
|
4239
4228
|
return entities;
|
|
4240
4229
|
}
|
|
4241
|
-
const useStyles$
|
|
4230
|
+
const useStyles$R = makeStyles({
|
|
4242
4231
|
rootDiv: {
|
|
4243
4232
|
flex: 1,
|
|
4244
4233
|
overflow: "hidden",
|
|
@@ -4347,14 +4336,14 @@ function MakeInlineCommandElement(command, isPlaceholder) {
|
|
|
4347
4336
|
}
|
|
4348
4337
|
const SceneTreeItem = (props) => {
|
|
4349
4338
|
const { isSelected, select } = props;
|
|
4350
|
-
const classes = useStyles$
|
|
4339
|
+
const classes = useStyles$R();
|
|
4351
4340
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
4352
4341
|
const treeItemLayoutClass = mergeClasses(classes.sceneTreeItemLayout, compactMode ? classes.treeItemLayoutCompact : undefined);
|
|
4353
4342
|
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"));
|
|
4354
4343
|
};
|
|
4355
4344
|
const SectionTreeItem = (props) => {
|
|
4356
4345
|
const { section, isFiltering, commandProviders, expandAll, collapseAll, isDropTarget, ...dropProps } = props;
|
|
4357
|
-
const classes = useStyles$
|
|
4346
|
+
const classes = useStyles$R();
|
|
4358
4347
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
4359
4348
|
// Get the commands that apply to this section.
|
|
4360
4349
|
const commands = useResource(useCallback(() => {
|
|
@@ -4371,7 +4360,7 @@ const SectionTreeItem = (props) => {
|
|
|
4371
4360
|
};
|
|
4372
4361
|
const EntityTreeItem = (props) => {
|
|
4373
4362
|
const { entityItem, isSelected, select, isFiltering, commandProviders, expandAll, collapseAll, isDragging, isDropTarget, ...dragProps } = props;
|
|
4374
|
-
const classes = useStyles$
|
|
4363
|
+
const classes = useStyles$R();
|
|
4375
4364
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
4376
4365
|
const hasChildren = !!entityItem.children?.length;
|
|
4377
4366
|
const displayInfo = useResource(useCallback(() => {
|
|
@@ -4477,7 +4466,7 @@ const EntityTreeItem = (props) => {
|
|
|
4477
4466
|
}, [commands]);
|
|
4478
4467
|
return (jsxs(Menu, { openOnContext: true, checkedValues: checkedContextMenuItems, onCheckedValueChange: onContextMenuCheckedValueChange, children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: jsx(FlatTreeItem, { className: mergeClasses(classes.treeItem, isDragging && classes.treeItemDragging, isDropTarget && classes.treeItemDropTarget), value: GetEntityId$1(entityItem.entity),
|
|
4479
4468
|
// Disable manual expand/collapse when a filter is active.
|
|
4480
|
-
itemType: !isFiltering && hasChildren ? "branch" : "leaf", parentValue: entityItem.parent.type === "section" ? entityItem.parent.sectionName : GetEntityId$1(entityItem.parent.entity), "aria-level": entityItem.depth, "aria-setsize": 1, "aria-posinset": 1, onClick: select, onKeyDown: onKeyDown, style: { [treeItemLevelToken]: entityItem.depth }, ...dragProps, children: jsx(TreeItemLayout, { iconBefore: entityItem.icon ? jsx(entityItem.icon, { entity: entityItem.entity }) : null, className: mergeClasses(hasChildren ? classes.treeItemLayoutBranch : classes.treeItemLayoutLeaf, compactMode ? classes.treeItemLayoutCompact : undefined, isDropTarget && classes.treeItemDropTarget), style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, actions: actions, aside: {
|
|
4469
|
+
itemType: !isFiltering && hasChildren ? "branch" : "leaf", parentValue: entityItem.parent.type === "section" ? entityItem.parent.sectionName : GetEntityId$1(entityItem.parent.entity), "aria-level": entityItem.depth, "aria-setsize": 1, "aria-posinset": 1, onClick: select, onKeyDown: onKeyDown, style: { [treeItemLevelToken]: entityItem.depth }, ...dragProps, children: jsx(TreeItemLayout, { iconBefore: displayInfo.validationError ? (jsx(Tooltip$1, { content: displayInfo.validationError, relationship: "description", children: jsx(WarningRegular, {}) })) : entityItem.icon ? (jsx(entityItem.icon, { entity: entityItem.entity })) : null, className: mergeClasses(hasChildren ? classes.treeItemLayoutBranch : classes.treeItemLayoutLeaf, compactMode ? classes.treeItemLayoutCompact : undefined, isDropTarget && classes.treeItemDropTarget), style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, actions: actions, aside: {
|
|
4481
4470
|
// Match the gap and padding of the actions.
|
|
4482
4471
|
className: classes.treeItemLayoutAside,
|
|
4483
4472
|
children: aside,
|
|
@@ -4487,7 +4476,7 @@ const EntityTreeItem = (props) => {
|
|
|
4487
4476
|
}, children: jsx(Tooltip$1, { content: name, relationship: "description", children: jsx(Body1, { wrap: false, truncate: true, children: name }) }) }) }, GetEntityId$1(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] }) })] }));
|
|
4488
4477
|
};
|
|
4489
4478
|
const SceneExplorer = (props) => {
|
|
4490
|
-
const classes = useStyles$
|
|
4479
|
+
const classes = useStyles$R();
|
|
4491
4480
|
const { sections, entityCommandProviders, sectionCommandProviders, scene, selectedEntity = null } = props;
|
|
4492
4481
|
const [openItems, setOpenItems] = useState(new Set());
|
|
4493
4482
|
const [sceneVersion, setSceneVersion] = useState(0);
|
|
@@ -5037,7 +5026,8 @@ const FrameStepsStats = ({ context: scene }) => {
|
|
|
5037
5026
|
*/
|
|
5038
5027
|
const ButtonLine = (props) => {
|
|
5039
5028
|
ButtonLine.displayName = "ButtonLine";
|
|
5040
|
-
|
|
5029
|
+
const { uniqueId, ...buttonProps } = props;
|
|
5030
|
+
return (jsx(LineContainer, { uniqueId: uniqueId ?? props.label, children: jsx(Button, { ...buttonProps }) }));
|
|
5041
5031
|
};
|
|
5042
5032
|
|
|
5043
5033
|
/**
|
|
@@ -6112,7 +6102,7 @@ class CanvasGraphService {
|
|
|
6112
6102
|
}
|
|
6113
6103
|
}
|
|
6114
6104
|
|
|
6115
|
-
const useStyles$
|
|
6105
|
+
const useStyles$Q = makeStyles({
|
|
6116
6106
|
canvas: {
|
|
6117
6107
|
flexGrow: 1,
|
|
6118
6108
|
width: "100%",
|
|
@@ -6121,7 +6111,7 @@ const useStyles$P = makeStyles({
|
|
|
6121
6111
|
});
|
|
6122
6112
|
const CanvasGraph = (props) => {
|
|
6123
6113
|
const { collector, scene, layoutObservable, returnToPlayheadObservable, onVisibleRangeChangedObservable, initialGraphSize } = props;
|
|
6124
|
-
const classes = useStyles$
|
|
6114
|
+
const classes = useStyles$Q();
|
|
6125
6115
|
const canvasRef = useRef(null);
|
|
6126
6116
|
useEffect(() => {
|
|
6127
6117
|
if (!canvasRef.current) {
|
|
@@ -6198,7 +6188,7 @@ function EvaluateExpression(rawValue) {
|
|
|
6198
6188
|
return NaN;
|
|
6199
6189
|
}
|
|
6200
6190
|
}
|
|
6201
|
-
const useStyles$
|
|
6191
|
+
const useStyles$P = makeStyles({
|
|
6202
6192
|
icon: {
|
|
6203
6193
|
"&:hover": {
|
|
6204
6194
|
color: tokens.colorBrandForeground1,
|
|
@@ -6212,7 +6202,7 @@ const useStyles$O = makeStyles({
|
|
|
6212
6202
|
const SpinButton = forwardRef((props, ref) => {
|
|
6213
6203
|
SpinButton.displayName = "SpinButton2";
|
|
6214
6204
|
const inputClasses = useInputStyles$1();
|
|
6215
|
-
const classes = useStyles$
|
|
6205
|
+
const classes = useStyles$P();
|
|
6216
6206
|
const { size } = useContext(ToolContext);
|
|
6217
6207
|
const { min, max } = props;
|
|
6218
6208
|
const baseStep = props.step ?? 1;
|
|
@@ -6479,7 +6469,7 @@ const Dropdown = (props) => {
|
|
|
6479
6469
|
const NumberDropdown = Dropdown;
|
|
6480
6470
|
const StringDropdown = Dropdown;
|
|
6481
6471
|
|
|
6482
|
-
const useStyles$
|
|
6472
|
+
const useStyles$O = makeStyles({
|
|
6483
6473
|
surface: {
|
|
6484
6474
|
maxWidth: "400px",
|
|
6485
6475
|
},
|
|
@@ -6494,7 +6484,7 @@ const useStyles$N = makeStyles({
|
|
|
6494
6484
|
const Popover = forwardRef((props, ref) => {
|
|
6495
6485
|
const { children, open: controlledOpen, onOpenChange, positioning, surfaceClassName } = props;
|
|
6496
6486
|
const [internalOpen, setInternalOpen] = useState(false);
|
|
6497
|
-
const classes = useStyles$
|
|
6487
|
+
const classes = useStyles$O();
|
|
6498
6488
|
const isControlled = controlledOpen !== undefined;
|
|
6499
6489
|
const popoverOpen = isControlled ? controlledOpen : internalOpen;
|
|
6500
6490
|
const handleOpenChange = (_, data) => {
|
|
@@ -6738,7 +6728,7 @@ const InputAlphaField = (props) => {
|
|
|
6738
6728
|
} }));
|
|
6739
6729
|
};
|
|
6740
6730
|
|
|
6741
|
-
const useStyles$
|
|
6731
|
+
const useStyles$N = makeStyles({
|
|
6742
6732
|
sidebar: {
|
|
6743
6733
|
display: "flex",
|
|
6744
6734
|
flexDirection: "column",
|
|
@@ -6802,7 +6792,7 @@ const useStyles$M = makeStyles({
|
|
|
6802
6792
|
});
|
|
6803
6793
|
const PerformanceSidebar = (props) => {
|
|
6804
6794
|
const { collector, onVisibleRangeChangedObservable } = props;
|
|
6805
|
-
const classes = useStyles$
|
|
6795
|
+
const classes = useStyles$N();
|
|
6806
6796
|
// Map from id to IPerfMetadata information
|
|
6807
6797
|
const [metadataMap, setMetadataMap] = useState();
|
|
6808
6798
|
// Map from category to all the ids belonging to that category
|
|
@@ -6875,7 +6865,7 @@ const PerformanceSidebar = (props) => {
|
|
|
6875
6865
|
})] }, `category-${category || "version"}`))) }));
|
|
6876
6866
|
};
|
|
6877
6867
|
|
|
6878
|
-
const useStyles$
|
|
6868
|
+
const useStyles$M = makeStyles({
|
|
6879
6869
|
container: {
|
|
6880
6870
|
display: "flex",
|
|
6881
6871
|
flexDirection: "row",
|
|
@@ -6904,7 +6894,7 @@ const useStyles$L = makeStyles({
|
|
|
6904
6894
|
});
|
|
6905
6895
|
const PerformanceViewer = (props) => {
|
|
6906
6896
|
const { scene, layoutObservable, returnToLiveObservable, performanceCollector, initialGraphSize } = props;
|
|
6907
|
-
const classes = useStyles$
|
|
6897
|
+
const classes = useStyles$M();
|
|
6908
6898
|
const [onVisibleRangeChangedObservable] = useState(() => new Observable());
|
|
6909
6899
|
const onReturnToPlayheadClick = () => {
|
|
6910
6900
|
returnToLiveObservable.notifyObservers();
|
|
@@ -7071,14 +7061,14 @@ const TextPropertyLine = (props) => {
|
|
|
7071
7061
|
return (jsx(PropertyLine, { ...props, children: jsx(Body1, { title: title, children: value ?? "" }) }));
|
|
7072
7062
|
};
|
|
7073
7063
|
|
|
7074
|
-
const useStyles$
|
|
7064
|
+
const useStyles$L = makeStyles({
|
|
7075
7065
|
pinnedStatsPane: {
|
|
7076
7066
|
flex: "0 1 auto",
|
|
7077
7067
|
paddingBottom: tokens.spacingHorizontalM,
|
|
7078
7068
|
},
|
|
7079
7069
|
});
|
|
7080
7070
|
const StatsPane = (props) => {
|
|
7081
|
-
const classes = useStyles$
|
|
7071
|
+
const classes = useStyles$L();
|
|
7082
7072
|
const scene = props.context;
|
|
7083
7073
|
const engine = scene.getEngine();
|
|
7084
7074
|
const pollingObservable = usePollingObservable(250);
|
|
@@ -7241,7 +7231,7 @@ const ToolsServiceDefinition = {
|
|
|
7241
7231
|
*/
|
|
7242
7232
|
const ReactContextServiceIdentity = Symbol("ReactContextService");
|
|
7243
7233
|
|
|
7244
|
-
const useStyles$
|
|
7234
|
+
const useStyles$K = makeStyles({
|
|
7245
7235
|
dropdown: {
|
|
7246
7236
|
...UniformWidthStyling,
|
|
7247
7237
|
},
|
|
@@ -7253,7 +7243,7 @@ const useStyles$J = makeStyles({
|
|
|
7253
7243
|
*/
|
|
7254
7244
|
const DropdownPropertyLine = forwardRef((props, ref) => {
|
|
7255
7245
|
DropdownPropertyLine.displayName = "DropdownPropertyLine";
|
|
7256
|
-
const classes = useStyles$
|
|
7246
|
+
const classes = useStyles$K();
|
|
7257
7247
|
return (jsx(PropertyLine, { ...props, ref: ref, children: jsx(Dropdown, { ...props, className: classes.dropdown }) }));
|
|
7258
7248
|
});
|
|
7259
7249
|
/**
|
|
@@ -7411,7 +7401,7 @@ const SyncedSliderInput = (props) => {
|
|
|
7411
7401
|
return (jsxs("div", { className: mergeClasses(classes.container, props.className), 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: useCompactSizing ? classes.compactSpinButton : classes.spinButton, inputClassName: useCompactSizing ? classes.compactSpinButtonInput : classes.spinButtonInput, value: value, onChange: handleInputChange, step: props.step, disabled: props.disabled, disableDragButton: true })] })] }));
|
|
7412
7402
|
};
|
|
7413
7403
|
|
|
7414
|
-
const useStyles$
|
|
7404
|
+
const useStyles$J = makeStyles({
|
|
7415
7405
|
uniformWidth: {
|
|
7416
7406
|
...UniformWidthStyling,
|
|
7417
7407
|
},
|
|
@@ -7423,7 +7413,7 @@ const useStyles$I = makeStyles({
|
|
|
7423
7413
|
*/
|
|
7424
7414
|
const SyncedSliderPropertyLine = forwardRef((props, ref) => {
|
|
7425
7415
|
SyncedSliderPropertyLine.displayName = "SyncedSliderPropertyLine";
|
|
7426
|
-
const classes = useStyles$
|
|
7416
|
+
const classes = useStyles$J();
|
|
7427
7417
|
const { label, description, ...sliderProps } = props;
|
|
7428
7418
|
return (jsx(PropertyLine, { ref: ref, ...props, children: jsx(SyncedSliderInput, { ...sliderProps, className: mergeClasses(classes.uniformWidth, props.className) }) }));
|
|
7429
7419
|
});
|
|
@@ -8311,12 +8301,17 @@ class ServiceContainer {
|
|
|
8311
8301
|
}
|
|
8312
8302
|
}
|
|
8313
8303
|
|
|
8304
|
+
/**
|
|
8305
|
+
* The unique identity symbol for the toast service.
|
|
8306
|
+
*/
|
|
8307
|
+
const ToastServiceIdentity = Symbol("ToastService");
|
|
8308
|
+
|
|
8314
8309
|
const ExtensionManagerContext = createContext(undefined);
|
|
8315
8310
|
function useExtensionManager() {
|
|
8316
8311
|
return useContext(ExtensionManagerContext)?.extensionManager;
|
|
8317
8312
|
}
|
|
8318
8313
|
|
|
8319
|
-
const useStyles$
|
|
8314
|
+
const useStyles$I = makeStyles({
|
|
8320
8315
|
themeButton: {
|
|
8321
8316
|
margin: 0,
|
|
8322
8317
|
},
|
|
@@ -8335,7 +8330,7 @@ const ThemeSelectorServiceDefinition = {
|
|
|
8335
8330
|
teachingMoment: false,
|
|
8336
8331
|
order: -300,
|
|
8337
8332
|
component: () => {
|
|
8338
|
-
const classes = useStyles$
|
|
8333
|
+
const classes = useStyles$I();
|
|
8339
8334
|
const { isDarkMode, themeMode, setThemeMode } = useThemeMode();
|
|
8340
8335
|
const onSelectedThemeChange = useCallback((e, data) => {
|
|
8341
8336
|
setThemeMode(data.checkedItems.includes("System") ? "system" : data.checkedItems[0].toLocaleLowerCase());
|
|
@@ -8352,7 +8347,7 @@ const ThemeSelectorServiceDefinition = {
|
|
|
8352
8347
|
},
|
|
8353
8348
|
};
|
|
8354
8349
|
|
|
8355
|
-
const useStyles$
|
|
8350
|
+
const useStyles$H = makeStyles({
|
|
8356
8351
|
app: {
|
|
8357
8352
|
colorScheme: "light dark",
|
|
8358
8353
|
flexGrow: 1,
|
|
@@ -8395,11 +8390,21 @@ function MakeModularTool(options) {
|
|
|
8395
8390
|
settingsStore.writeSetting(ThemeModeSettingDescriptor, themeMode);
|
|
8396
8391
|
}
|
|
8397
8392
|
const modularToolRootComponent = () => {
|
|
8398
|
-
const classes = useStyles$
|
|
8393
|
+
const classes = useStyles$H();
|
|
8399
8394
|
const [extensionManagerContext, setExtensionManagerContext] = useState();
|
|
8400
8395
|
const [requiredExtensions, setRequiredExtensions] = useState();
|
|
8401
8396
|
const [requiredExtensionsDeferred, setRequiredExtensionsDeferred] = useState();
|
|
8402
8397
|
const [extensionInstallError, setExtensionInstallError] = useState();
|
|
8398
|
+
const [toastHandle, setToastHandle] = useState(null);
|
|
8399
|
+
const [toastQueue, setToastQueue] = useState([]);
|
|
8400
|
+
useEffect(() => {
|
|
8401
|
+
if (toastHandle && toastQueue.length > 0) {
|
|
8402
|
+
for (const { message, options } of toastQueue) {
|
|
8403
|
+
toastHandle.showToast(message, options);
|
|
8404
|
+
}
|
|
8405
|
+
setToastQueue([]);
|
|
8406
|
+
}
|
|
8407
|
+
}, [toastHandle, toastQueue]);
|
|
8403
8408
|
const [rootComponentService, setRootComponentService] = useState();
|
|
8404
8409
|
const [contexts, updateContexts] = useReducer((state, action) => {
|
|
8405
8410
|
switch (action.type) {
|
|
@@ -8440,6 +8445,16 @@ function MakeModularTool(options) {
|
|
|
8440
8445
|
},
|
|
8441
8446
|
}),
|
|
8442
8447
|
});
|
|
8448
|
+
// Expose the toast service so non-React code (e.g. Observable callbacks) can show toasts.
|
|
8449
|
+
await serviceContainer.addServiceAsync({
|
|
8450
|
+
friendlyName: "Toast Service",
|
|
8451
|
+
produces: [ToastServiceIdentity],
|
|
8452
|
+
factory: () => ({
|
|
8453
|
+
showToast: (message, options) => {
|
|
8454
|
+
setToastQueue((prev) => [...prev, { message, options }]);
|
|
8455
|
+
},
|
|
8456
|
+
}),
|
|
8457
|
+
});
|
|
8443
8458
|
// Register the shell service (top level toolbar/side pane UI layout).
|
|
8444
8459
|
await serviceContainer.addServiceAsync(MakeShellServiceDefinition(options));
|
|
8445
8460
|
// Register a service that simply consumes the services we need before first render.
|
|
@@ -8462,7 +8477,7 @@ function MakeModularTool(options) {
|
|
|
8462
8477
|
}
|
|
8463
8478
|
// Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
|
|
8464
8479
|
if (extensionFeeds.length > 0) {
|
|
8465
|
-
const { ExtensionListServiceDefinition } = await import('./extensionsListService-
|
|
8480
|
+
const { ExtensionListServiceDefinition } = await import('./extensionsListService-B_R2ChvJ.js');
|
|
8466
8481
|
await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);
|
|
8467
8482
|
}
|
|
8468
8483
|
// Register all external services (that make up a unique tool).
|
|
@@ -8535,7 +8550,7 @@ function MakeModularTool(options) {
|
|
|
8535
8550
|
else {
|
|
8536
8551
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
8537
8552
|
const Content = rootComponentService.rootComponent;
|
|
8538
|
-
return (jsx(ReactContextsWrapper, { contexts: contexts, children: jsx(SettingsStoreContext.Provider, { value: settingsStore, 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, {}) })] }) }) }) }) }));
|
|
8553
|
+
return (jsx(ReactContextsWrapper, { contexts: contexts, children: jsx(SettingsStoreContext.Provider, { value: settingsStore, children: jsx(ExtensionManagerContext.Provider, { value: extensionManagerContext, children: jsx(Theme, { className: classes.app, children: jsxs(ToastProvider, { imperativeRef: setToastHandle, 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, {}) })] }) }) }) }) }));
|
|
8539
8554
|
}
|
|
8540
8555
|
};
|
|
8541
8556
|
// Set the container element to be a flex container so that the tool can be displayed properly.
|
|
@@ -8578,14 +8593,14 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
8578
8593
|
description: "Adds a new panel for easy creation of various Babylon assets. This is a WIP extension...expect changes!",
|
|
8579
8594
|
keywords: ["creation", "tools"],
|
|
8580
8595
|
...BabylonWebResources,
|
|
8581
|
-
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-
|
|
8596
|
+
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-DaBqYmZw.js'),
|
|
8582
8597
|
},
|
|
8583
8598
|
{
|
|
8584
8599
|
name: "Reflector",
|
|
8585
8600
|
description: "Connects to the Reflector Bridge for real-time scene synchronization with the Babylon.js Sandbox.",
|
|
8586
8601
|
keywords: ["reflector", "bridge", "sync", "sandbox", "tools"],
|
|
8587
8602
|
...BabylonWebResources,
|
|
8588
|
-
getExtensionModuleAsync: async () => await import('./reflectorService-
|
|
8603
|
+
getExtensionModuleAsync: async () => await import('./reflectorService-5IVRhqd-.js'),
|
|
8589
8604
|
},
|
|
8590
8605
|
]);
|
|
8591
8606
|
|
|
@@ -8850,25 +8865,34 @@ function MakeInspectableBridgeServiceDefinition(options) {
|
|
|
8850
8865
|
let ws = null;
|
|
8851
8866
|
let reconnectTimer = null;
|
|
8852
8867
|
let disposed = false;
|
|
8868
|
+
let enabled = options.autoStart;
|
|
8853
8869
|
let connected = false;
|
|
8854
8870
|
const onConnectionStatusChanged = new Observable();
|
|
8871
|
+
function notifyStatusChanged() {
|
|
8872
|
+
onConnectionStatusChanged.notifyObservers();
|
|
8873
|
+
}
|
|
8855
8874
|
function setConnected(value) {
|
|
8856
8875
|
if (connected !== value) {
|
|
8857
8876
|
connected = value;
|
|
8858
|
-
|
|
8877
|
+
notifyStatusChanged();
|
|
8859
8878
|
}
|
|
8860
8879
|
}
|
|
8861
8880
|
function sendToBridge(message) {
|
|
8862
8881
|
ws?.send(JSON.stringify(message));
|
|
8863
8882
|
}
|
|
8864
8883
|
function connect() {
|
|
8865
|
-
if (disposed) {
|
|
8884
|
+
if (disposed || !enabled) {
|
|
8866
8885
|
return;
|
|
8867
8886
|
}
|
|
8868
8887
|
try {
|
|
8888
|
+
// NOTE: The browser unconditionally logs a console error for failed WebSocket
|
|
8889
|
+
// connections at the network level. This cannot be suppressed from JavaScript.
|
|
8869
8890
|
ws = new WebSocket(`ws://127.0.0.1:${options.port}`);
|
|
8870
8891
|
}
|
|
8871
8892
|
catch {
|
|
8893
|
+
ws = null;
|
|
8894
|
+
setConnected(false);
|
|
8895
|
+
Logger.Warn(`InspectableBridgeService: Failed to create WebSocket connection on port ${options.port}.`);
|
|
8872
8896
|
scheduleReconnect();
|
|
8873
8897
|
return;
|
|
8874
8898
|
}
|
|
@@ -8894,8 +8918,20 @@ function MakeInspectableBridgeServiceDefinition(options) {
|
|
|
8894
8918
|
// onclose will fire after onerror, which handles reconnection.
|
|
8895
8919
|
};
|
|
8896
8920
|
}
|
|
8921
|
+
function disconnect() {
|
|
8922
|
+
if (reconnectTimer !== null) {
|
|
8923
|
+
clearTimeout(reconnectTimer);
|
|
8924
|
+
reconnectTimer = null;
|
|
8925
|
+
}
|
|
8926
|
+
if (ws) {
|
|
8927
|
+
ws.onclose = null;
|
|
8928
|
+
ws.close();
|
|
8929
|
+
ws = null;
|
|
8930
|
+
}
|
|
8931
|
+
setConnected(false);
|
|
8932
|
+
}
|
|
8897
8933
|
function scheduleReconnect() {
|
|
8898
|
-
if (disposed || reconnectTimer !== null) {
|
|
8934
|
+
if (disposed || !enabled || reconnectTimer !== null) {
|
|
8899
8935
|
return;
|
|
8900
8936
|
}
|
|
8901
8937
|
reconnectTimer = setTimeout(() => {
|
|
@@ -8947,8 +8983,9 @@ function MakeInspectableBridgeServiceDefinition(options) {
|
|
|
8947
8983
|
}
|
|
8948
8984
|
}
|
|
8949
8985
|
}
|
|
8950
|
-
|
|
8951
|
-
|
|
8986
|
+
if (enabled) {
|
|
8987
|
+
connect();
|
|
8988
|
+
}
|
|
8952
8989
|
const registry = {
|
|
8953
8990
|
addCommand(descriptor) {
|
|
8954
8991
|
if (commands.has(descriptor.id)) {
|
|
@@ -8961,24 +8998,31 @@ function MakeInspectableBridgeServiceDefinition(options) {
|
|
|
8961
8998
|
},
|
|
8962
8999
|
};
|
|
8963
9000
|
},
|
|
9001
|
+
get isEnabled() {
|
|
9002
|
+
return enabled;
|
|
9003
|
+
},
|
|
9004
|
+
set isEnabled(value) {
|
|
9005
|
+
if (enabled !== value) {
|
|
9006
|
+
enabled = value;
|
|
9007
|
+
if (enabled) {
|
|
9008
|
+
connect();
|
|
9009
|
+
}
|
|
9010
|
+
else {
|
|
9011
|
+
disconnect();
|
|
9012
|
+
}
|
|
9013
|
+
notifyStatusChanged();
|
|
9014
|
+
}
|
|
9015
|
+
},
|
|
8964
9016
|
get isConnected() {
|
|
8965
9017
|
return connected;
|
|
8966
9018
|
},
|
|
8967
9019
|
onConnectionStatusChanged,
|
|
8968
9020
|
dispose: () => {
|
|
8969
9021
|
disposed = true;
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
reconnectTimer = null;
|
|
8973
|
-
}
|
|
9022
|
+
enabled = false;
|
|
9023
|
+
disconnect();
|
|
8974
9024
|
commands.clear();
|
|
8975
|
-
setConnected(false);
|
|
8976
9025
|
onConnectionStatusChanged.clear();
|
|
8977
|
-
if (ws) {
|
|
8978
|
-
ws.onclose = null;
|
|
8979
|
-
ws.close();
|
|
8980
|
-
ws = null;
|
|
8981
|
-
}
|
|
8982
9026
|
},
|
|
8983
9027
|
};
|
|
8984
9028
|
return registry;
|
|
@@ -9408,6 +9452,7 @@ function _StartInspectable(scene, options) {
|
|
|
9408
9452
|
await serviceContainer.addServicesAsync(sceneContextServiceDefinition, MakeInspectableBridgeServiceDefinition({
|
|
9409
9453
|
port,
|
|
9410
9454
|
name,
|
|
9455
|
+
autoStart: options?.autoStart ?? false,
|
|
9411
9456
|
}), EntityQueryServiceDefinition, ScreenshotCommandServiceDefinition, ShaderCommandServiceDefinition, StatsCommandServiceDefinition, PerfTraceCommandServiceDefinition);
|
|
9412
9457
|
})();
|
|
9413
9458
|
state = {
|
|
@@ -9540,7 +9585,7 @@ const ColorSliders = ({ color, onSliderChange }) => (jsxs(Fragment, { children:
|
|
|
9540
9585
|
const Color3PropertyLine = ColorPropertyLine;
|
|
9541
9586
|
const Color4PropertyLine = ColorPropertyLine;
|
|
9542
9587
|
|
|
9543
|
-
const useStyles$
|
|
9588
|
+
const useStyles$G = makeStyles({
|
|
9544
9589
|
uniformWidth: {
|
|
9545
9590
|
...UniformWidthStyling,
|
|
9546
9591
|
},
|
|
@@ -9552,7 +9597,7 @@ const useStyles$F = makeStyles({
|
|
|
9552
9597
|
*/
|
|
9553
9598
|
const TextInputPropertyLine = (props) => {
|
|
9554
9599
|
TextInputPropertyLine.displayName = "TextInputPropertyLine";
|
|
9555
|
-
const classes = useStyles$
|
|
9600
|
+
const classes = useStyles$G();
|
|
9556
9601
|
return (jsx(PropertyLine, { ...props, children: jsx(TextInput, { ...props, className: mergeClasses(classes.uniformWidth, props.className) }) }));
|
|
9557
9602
|
};
|
|
9558
9603
|
/**
|
|
@@ -9563,7 +9608,7 @@ const TextInputPropertyLine = (props) => {
|
|
|
9563
9608
|
*/
|
|
9564
9609
|
const NumberInputPropertyLine = (props) => {
|
|
9565
9610
|
NumberInputPropertyLine.displayName = "NumberInputPropertyLine";
|
|
9566
|
-
const classes = useStyles$
|
|
9611
|
+
const classes = useStyles$G();
|
|
9567
9612
|
return (jsx(PropertyLine, { ...props, children: jsx(SpinButton, { ...props, className: mergeClasses(classes.uniformWidth, props.className) }) }));
|
|
9568
9613
|
};
|
|
9569
9614
|
|
|
@@ -9694,6 +9739,14 @@ const LegacyInspectableObjectPropertiesServiceDefinition = {
|
|
|
9694
9739
|
},
|
|
9695
9740
|
};
|
|
9696
9741
|
|
|
9742
|
+
const DocUrl = "https://www.npmjs.com/package/@babylonjs/inspector#inspector-cli";
|
|
9743
|
+
const useStyles$F = makeStyles({
|
|
9744
|
+
tooltipContent: {
|
|
9745
|
+
display: "flex",
|
|
9746
|
+
flexDirection: "column",
|
|
9747
|
+
gap: tokens.spacingVerticalXS,
|
|
9748
|
+
},
|
|
9749
|
+
});
|
|
9697
9750
|
const CliConnectionStatusServiceDefinition = {
|
|
9698
9751
|
friendlyName: "CLI Connection Status",
|
|
9699
9752
|
consumes: [ShellServiceIdentity, CliConnectionStatusIdentity],
|
|
@@ -9705,9 +9758,22 @@ const CliConnectionStatusServiceDefinition = {
|
|
|
9705
9758
|
teachingMoment: false,
|
|
9706
9759
|
order: 0 /* DefaultToolbarItemOrder.CliStatus */,
|
|
9707
9760
|
component: () => {
|
|
9761
|
+
const classes = useStyles$F();
|
|
9762
|
+
const isEnabled = useObservableState(() => cliConnectionStatus.isEnabled, cliConnectionStatus.onConnectionStatusChanged);
|
|
9708
9763
|
const isConnected = useObservableState(() => cliConnectionStatus.isConnected, cliConnectionStatus.onConnectionStatusChanged);
|
|
9709
9764
|
const { showToast } = useToast();
|
|
9710
9765
|
const isFirstRender = useRef(true);
|
|
9766
|
+
const [connectingIconToggle, setConnectingIconToggle] = useState(false);
|
|
9767
|
+
const connecting = isEnabled && !isConnected;
|
|
9768
|
+
useEffect(() => {
|
|
9769
|
+
if (!connecting) {
|
|
9770
|
+
return;
|
|
9771
|
+
}
|
|
9772
|
+
const interval = setInterval(() => {
|
|
9773
|
+
setConnectingIconToggle((prev) => !prev);
|
|
9774
|
+
}, 700);
|
|
9775
|
+
return () => clearInterval(interval);
|
|
9776
|
+
}, [connecting]);
|
|
9711
9777
|
useEffect(() => {
|
|
9712
9778
|
if (isFirstRender.current) {
|
|
9713
9779
|
isFirstRender.current = false;
|
|
@@ -9720,8 +9786,25 @@ const CliConnectionStatusServiceDefinition = {
|
|
|
9720
9786
|
showToast("Inspector bridge disconnected.", { intent: "warning" });
|
|
9721
9787
|
}
|
|
9722
9788
|
}, [isConnected, showToast]);
|
|
9723
|
-
|
|
9724
|
-
|
|
9789
|
+
let icon;
|
|
9790
|
+
let statusText;
|
|
9791
|
+
if (!isEnabled) {
|
|
9792
|
+
icon = jsx(PlugDisconnectedRegular, { color: tokens.colorNeutralForeground4 });
|
|
9793
|
+
statusText = "Inspector CLI bridge disabled — click to connect";
|
|
9794
|
+
}
|
|
9795
|
+
else if (!isConnected) {
|
|
9796
|
+
icon = connectingIconToggle ? (jsx(PlugConnectedRegular, { color: tokens.colorPaletteYellowForeground2 })) : (jsx(PlugDisconnectedRegular, { color: tokens.colorPaletteYellowForeground2 }));
|
|
9797
|
+
statusText = "Connecting to Inspector CLI bridge — click to disconnect";
|
|
9798
|
+
}
|
|
9799
|
+
else {
|
|
9800
|
+
icon = jsx(PlugConnectedCheckmarkRegular, { color: tokens.colorPaletteGreenForeground2 });
|
|
9801
|
+
statusText = "Connected to Inspector CLI bridge — click to disconnect";
|
|
9802
|
+
}
|
|
9803
|
+
const tooltipContent = (jsxs("div", { className: classes.tooltipContent, children: [jsx(Body1, { children: statusText }), jsx(Link, { url: DocUrl, value: "Inspector CLI documentation" })] }));
|
|
9804
|
+
// Using raw Fluent Button for custom icon coloring per connection state.
|
|
9805
|
+
return (jsx(Tooltip, { content: tooltipContent, children: jsx(Button$1, { appearance: "subtle", "aria-label": statusText, icon: icon, onClick: () => {
|
|
9806
|
+
cliConnectionStatus.isEnabled = !cliConnectionStatus.isEnabled;
|
|
9807
|
+
} }) }));
|
|
9725
9808
|
},
|
|
9726
9809
|
});
|
|
9727
9810
|
},
|
|
@@ -17050,6 +17133,8 @@ const ParticleSystemEmitterProperties = (props) => {
|
|
|
17050
17133
|
useProperty(emitterVector, "_y");
|
|
17051
17134
|
useProperty(emitterVector, "_z");
|
|
17052
17135
|
const particleEmitterType = useProperty(system, "particleEmitterType");
|
|
17136
|
+
const meshEmitter = particleEmitterType instanceof MeshParticleEmitter ? particleEmitterType : undefined;
|
|
17137
|
+
const useMeshNormalsForDirection = useProperty(meshEmitter, "useMeshNormalsForDirection");
|
|
17053
17138
|
// Derive the current dropdown value from the current instance to stay in sync with external changes.
|
|
17054
17139
|
const derivedEmitterTypeKey = (() => {
|
|
17055
17140
|
if (particleEmitterType instanceof SphereParticleEmitter) {
|
|
@@ -17153,21 +17238,21 @@ const ParticleSystemEmitterProperties = (props) => {
|
|
|
17153
17238
|
break;
|
|
17154
17239
|
}
|
|
17155
17240
|
}
|
|
17156
|
-
} }), particleEmitterType instanceof MeshParticleEmitter && (
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17241
|
+
} }), particleEmitterType instanceof MeshParticleEmitter && (jsxs(Fragment, { children: [scene && scene.meshes.length > 0 ? (jsx(Property, { component: StringDropdownPropertyLine, propertyPath: "source", label: "Source", value: particleEmitterType.mesh ? `mesh:${particleEmitterType.mesh.uniqueId}` : `mesh:${scene.meshes[0].uniqueId}`, options: scene.meshes.map((mesh) => {
|
|
17242
|
+
const uniqueId = mesh.uniqueId;
|
|
17243
|
+
const name = mesh.name ?? "(unnamed)";
|
|
17244
|
+
const label = `${name} (#${uniqueId})`;
|
|
17245
|
+
return {
|
|
17246
|
+
label,
|
|
17247
|
+
value: `mesh:${uniqueId}`,
|
|
17248
|
+
};
|
|
17249
|
+
}), onChange: (value) => {
|
|
17250
|
+
const next = String(value);
|
|
17251
|
+
const uniqueIdText = next.replace("mesh:", "");
|
|
17252
|
+
const uniqueId = Number(uniqueIdText);
|
|
17253
|
+
const mesh = scene.meshes.find((candidate) => candidate.uniqueId === uniqueId) ?? null;
|
|
17254
|
+
particleEmitterType.mesh = mesh;
|
|
17255
|
+
} })) : (jsx(Property, { component: TextPropertyLine, propertyPath: "source", label: "Source", value: "No meshes in scene." })), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use normals for direction", target: particleEmitterType, propertyKey: "useMeshNormalsForDirection" }), !useMeshNormalsForDirection && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Direction1", target: particleEmitterType, propertyKey: "direction1" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Direction2", target: particleEmitterType, propertyKey: "direction2" })] }))] })), particleEmitterType instanceof BoxParticleEmitter && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Direction1", target: particleEmitterType, propertyKey: "direction1" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Direction2", target: particleEmitterType, propertyKey: "direction2" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Min emit box", target: particleEmitterType, propertyKey: "minEmitBox" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Max emit box", target: particleEmitterType, propertyKey: "maxEmitBox" })] })), particleEmitterType instanceof ConeParticleEmitter && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius range", target: particleEmitterType, propertyKey: "radiusRange", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Height range", target: particleEmitterType, propertyKey: "heightRange", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Emit from spawn point only", target: particleEmitterType, propertyKey: "emitFromSpawnPointOnly" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Direction randomizer", target: particleEmitterType, propertyKey: "directionRandomizer", min: 0, max: 1, step: 0.01 })] })), particleEmitterType instanceof SphereParticleEmitter && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius", target: particleEmitterType, propertyKey: "radius", min: 0, step: 0.1 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius range", target: particleEmitterType, propertyKey: "radiusRange", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Direction randomizer", target: particleEmitterType, propertyKey: "directionRandomizer", min: 0, max: 1, step: 0.01 })] })), particleEmitterType instanceof CylinderParticleEmitter && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius", target: particleEmitterType, propertyKey: "radius", min: 0, step: 0.1 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Height", target: particleEmitterType, propertyKey: "height", min: 0, step: 0.1 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius range", target: particleEmitterType, propertyKey: "radiusRange", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Direction randomizer", target: particleEmitterType, propertyKey: "directionRandomizer", min: 0, max: 1, step: 0.01 })] })), particleEmitterType instanceof HemisphericParticleEmitter && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius", target: particleEmitterType, propertyKey: "radius", min: 0, step: 0.1 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius range", target: particleEmitterType, propertyKey: "radiusRange", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Direction randomizer", target: particleEmitterType, propertyKey: "directionRandomizer", min: 0, max: 1, step: 0.01 })] })), particleEmitterType instanceof PointParticleEmitter && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Direction1", target: particleEmitterType, propertyKey: "direction1" }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Direction2", target: particleEmitterType, propertyKey: "direction2" })] }))] })), !scene && jsx(TextPropertyLine, { label: "Emitter", value: "No scene available." })] }));
|
|
17171
17256
|
};
|
|
17172
17257
|
|
|
17173
17258
|
const useStyles$h = makeStyles({
|
|
@@ -18087,7 +18172,7 @@ const PhysicsPropertiesServiceDefinition = {
|
|
|
18087
18172
|
*/
|
|
18088
18173
|
const PostProcessProperties = (props) => {
|
|
18089
18174
|
const { postProcess } = props;
|
|
18090
|
-
return (jsxs(Fragment, { children: [jsx(StringifiedPropertyLine, { label: "Width", description: "The width of the post process", value: postProcess.width, units: "px" }), jsx(StringifiedPropertyLine, { label: "Height", description: "The height of the post process", value: postProcess.height, units: "px" }), jsx(BoundProperty, { component:
|
|
18175
|
+
return (jsxs(Fragment, { children: [jsx(StringifiedPropertyLine, { label: "Width", description: "The width of the post process", value: postProcess.width, units: "px" }), jsx(StringifiedPropertyLine, { label: "Height", description: "The height of the post process", value: postProcess.height, units: "px" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Auto Clear", target: postProcess, propertyKey: "autoClear" }), postProcess.clearColor && jsx(BoundProperty, { component: Color4PropertyLine, label: "Clear Color", target: postProcess, propertyKey: "clearColor" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Pixel Perfect", target: postProcess, propertyKey: "enablePixelPerfectMode" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Fullscreen Viewport", target: postProcess, propertyKey: "forceFullscreenViewport" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Samples", target: postProcess, propertyKey: "samples", min: 1, max: 8, step: 1 })] }));
|
|
18091
18176
|
};
|
|
18092
18177
|
|
|
18093
18178
|
const PostProcessPropertiesServiceDefinition = {
|
|
@@ -18238,7 +18323,7 @@ const IblShadowsRenderPipelineScreenspaceProperties = (props) => {
|
|
|
18238
18323
|
const IblShadowsRenderPipelineDebugProperties = (props) => {
|
|
18239
18324
|
const { pipeline } = props;
|
|
18240
18325
|
const allowDebugPasses = useProperty(pipeline, "allowDebugPasses");
|
|
18241
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Allow Debug Passes", target: pipeline, propertyKey: "allowDebugPasses" }), allowDebugPasses && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "
|
|
18326
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Allow Debug Passes", target: pipeline, propertyKey: "allowDebugPasses" }), allowDebugPasses && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "CDF Debug Enabled", target: pipeline, propertyKey: "cdfDebugEnabled" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Voxel Tracing Debug Enabled", target: pipeline, propertyKey: "voxelTracingDebugEnabled" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Spatial Blur Debug Enabled", target: pipeline, propertyKey: "spatialBlurPassDebugEnabled" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Accumulation Pass Debug Enabled", target: pipeline, propertyKey: "accumulationPassDebugEnabled" })] }))] }));
|
|
18242
18327
|
};
|
|
18243
18328
|
|
|
18244
18329
|
const RenderingPipelinePropertiesServiceDefinition = {
|
|
@@ -18771,12 +18856,42 @@ const SpriteManagerActionsProperties = (props) => {
|
|
|
18771
18856
|
* @param faceOrLayer if the texture has multiple faces, the face index to use for the source. For 2D array textures, this is the layer index.
|
|
18772
18857
|
* @param channels a filter for which of the RGBA channels to return in the result
|
|
18773
18858
|
* @param lod if the texture has multiple LODs, the lod index to use for the source
|
|
18859
|
+
* @param slice if the texture is 3D, the depth slice index to use for the source
|
|
18774
18860
|
* @returns the 8-bit texture data
|
|
18775
18861
|
*/
|
|
18776
|
-
async function ApplyChannelsToTextureDataAsync(texture, width, height, faceOrLayer, channels, lod = 0) {
|
|
18862
|
+
async function ApplyChannelsToTextureDataAsync(texture, width, height, faceOrLayer, channels, lod = 0, slice = 0) {
|
|
18863
|
+
const internalTexture = texture.getInternalTexture();
|
|
18864
|
+
const is3DTexture = texture.is3D || !!internalTexture?.is3D;
|
|
18865
|
+
const textureFormat = internalTexture?.format ?? texture.textureFormat;
|
|
18777
18866
|
// For cube maps, force RTT path to ensure correct face orientation and gamma correction
|
|
18778
18867
|
// For 2D array textures, face is reinterpreted as the layer index for direct pixel readback
|
|
18779
|
-
const data = await GetTextureDataAsync(texture, width, height, faceOrLayer, lod, texture.isCube);
|
|
18868
|
+
const data = await GetTextureDataAsync(texture, width, height, faceOrLayer, lod, texture.isCube || is3DTexture, slice);
|
|
18869
|
+
const forceOpaqueAlpha = is3DTexture || _TextureFormatHasNoAlpha(textureFormat);
|
|
18870
|
+
if (forceOpaqueAlpha) {
|
|
18871
|
+
for (let i = 3; i < width * height * 4; i += 4) {
|
|
18872
|
+
data[i] = 255;
|
|
18873
|
+
}
|
|
18874
|
+
}
|
|
18875
|
+
else if (texture.getScene()?.getEngine().isWebGPU) {
|
|
18876
|
+
let alphaAllZero = true;
|
|
18877
|
+
let hasNonZeroColor = false;
|
|
18878
|
+
for (let i = 0; i < width * height * 4; i += 4) {
|
|
18879
|
+
if (data[i] !== 0 || data[i + 1] !== 0 || data[i + 2] !== 0) {
|
|
18880
|
+
hasNonZeroColor = true;
|
|
18881
|
+
}
|
|
18882
|
+
if (data[i + 3] !== 0) {
|
|
18883
|
+
alphaAllZero = false;
|
|
18884
|
+
break;
|
|
18885
|
+
}
|
|
18886
|
+
}
|
|
18887
|
+
// Some WebGPU RTT readback paths can return zeroed alpha for textures that
|
|
18888
|
+
// are effectively opaque in source data. In that case, force opaque preview.
|
|
18889
|
+
if (alphaAllZero && hasNonZeroColor) {
|
|
18890
|
+
for (let i = 3; i < width * height * 4; i += 4) {
|
|
18891
|
+
data[i] = 255;
|
|
18892
|
+
}
|
|
18893
|
+
}
|
|
18894
|
+
}
|
|
18780
18895
|
if (!channels.R || !channels.G || !channels.B || !channels.A) {
|
|
18781
18896
|
for (let i = 0; i < width * height * 4; i += 4) {
|
|
18782
18897
|
// If alpha is the only channel, just display alpha across all channels
|
|
@@ -18849,6 +18964,40 @@ async function ApplyChannelsToTextureDataAsync(texture, width, height, faceOrLay
|
|
|
18849
18964
|
}
|
|
18850
18965
|
return data;
|
|
18851
18966
|
}
|
|
18967
|
+
function _TextureFormatHasNoAlpha(format) {
|
|
18968
|
+
switch (format) {
|
|
18969
|
+
case Constants.TEXTUREFORMAT_LUMINANCE:
|
|
18970
|
+
case Constants.TEXTUREFORMAT_R:
|
|
18971
|
+
case Constants.TEXTUREFORMAT_R16_UNORM:
|
|
18972
|
+
case Constants.TEXTUREFORMAT_R16_SNORM:
|
|
18973
|
+
case Constants.TEXTUREFORMAT_RG:
|
|
18974
|
+
case Constants.TEXTUREFORMAT_RG16_UNORM:
|
|
18975
|
+
case Constants.TEXTUREFORMAT_RG16_SNORM:
|
|
18976
|
+
case Constants.TEXTUREFORMAT_RGB:
|
|
18977
|
+
case Constants.TEXTUREFORMAT_RGB16_UNORM:
|
|
18978
|
+
case Constants.TEXTUREFORMAT_RGB16_SNORM:
|
|
18979
|
+
case Constants.TEXTUREFORMAT_DEPTH16:
|
|
18980
|
+
case Constants.TEXTUREFORMAT_DEPTH24:
|
|
18981
|
+
case Constants.TEXTUREFORMAT_DEPTH24_STENCIL8:
|
|
18982
|
+
case Constants.TEXTUREFORMAT_DEPTH24UNORM_STENCIL8:
|
|
18983
|
+
case Constants.TEXTUREFORMAT_DEPTH32_FLOAT:
|
|
18984
|
+
case Constants.TEXTUREFORMAT_DEPTH32FLOAT_STENCIL8:
|
|
18985
|
+
case Constants.TEXTUREFORMAT_STENCIL8:
|
|
18986
|
+
case Constants.TEXTUREFORMAT_RED_INTEGER:
|
|
18987
|
+
case Constants.TEXTUREFORMAT_RG_INTEGER:
|
|
18988
|
+
case Constants.TEXTUREFORMAT_RGB_INTEGER:
|
|
18989
|
+
case Constants.TEXTUREFORMAT_COMPRESSED_RGB_S3TC_DXT1:
|
|
18990
|
+
case Constants.TEXTUREFORMAT_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
|
18991
|
+
case Constants.TEXTUREFORMAT_COMPRESSED_RGB_ETC1_WEBGL:
|
|
18992
|
+
case Constants.TEXTUREFORMAT_COMPRESSED_RGB8_ETC2:
|
|
18993
|
+
case Constants.TEXTUREFORMAT_COMPRESSED_SRGB8_ETC2:
|
|
18994
|
+
case Constants.TEXTUREFORMAT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
|
|
18995
|
+
case Constants.TEXTUREFORMAT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
|
|
18996
|
+
return true;
|
|
18997
|
+
default:
|
|
18998
|
+
return false;
|
|
18999
|
+
}
|
|
19000
|
+
}
|
|
18852
19001
|
|
|
18853
19002
|
const useStyles$9 = makeStyles({
|
|
18854
19003
|
root: {
|
|
@@ -18860,6 +19009,10 @@ const useStyles$9 = makeStyles({
|
|
|
18860
19009
|
gap: tokens.spacingHorizontalXS,
|
|
18861
19010
|
padding: 0,
|
|
18862
19011
|
},
|
|
19012
|
+
sliderContainer: {
|
|
19013
|
+
marginTop: tokens.spacingVerticalXS,
|
|
19014
|
+
marginBottom: tokens.spacingVerticalXS,
|
|
19015
|
+
},
|
|
18863
19016
|
controlButton: {
|
|
18864
19017
|
minWidth: "auto",
|
|
18865
19018
|
flex: "1 1 0", // Equal flex grow/shrink with 0 basis
|
|
@@ -18891,15 +19044,28 @@ const TextureChannelStates = {
|
|
|
18891
19044
|
A: { R: false, G: false, B: false, A: true },
|
|
18892
19045
|
ALL: { R: true, G: true, B: true, A: true },
|
|
18893
19046
|
};
|
|
19047
|
+
/**
|
|
19048
|
+
* Displays a 2D preview for a texture, including channels/cube face controls.
|
|
19049
|
+
* @param props The component properties.
|
|
19050
|
+
* @returns The rendered component.
|
|
19051
|
+
*/
|
|
18894
19052
|
const TexturePreview = (props) => {
|
|
18895
19053
|
const { texture, disableToolbar = false, maxWidth = "100%", maxHeight = "384px", offsetX = 0, offsetY = 0, width, height, imperativeRef } = props;
|
|
18896
19054
|
const classes = useStyles$9();
|
|
18897
19055
|
const canvasRef = useRef(null);
|
|
18898
19056
|
const [channels, setChannels] = useState(TextureChannelStates.ALL);
|
|
18899
19057
|
const [face, setFace] = useState(0);
|
|
19058
|
+
const [slice, setSlice] = useState(0);
|
|
19059
|
+
const [lod, setLod] = useState(0);
|
|
18900
19060
|
const [layer, setLayer] = useState(0);
|
|
18901
19061
|
const [canvasStyle, setCanvasStyle] = useState();
|
|
18902
19062
|
const internalTexture = useProperty(texture, "_texture");
|
|
19063
|
+
const is3DTexture = !!internalTexture?.is3D;
|
|
19064
|
+
const baseDepth = Math.max(internalTexture?.depth ?? 1, 1);
|
|
19065
|
+
const lodDepth = Math.max(1, Math.floor(baseDepth / Math.pow(2, lod)));
|
|
19066
|
+
const maxSlice = lodDepth - 1;
|
|
19067
|
+
const lodBaseSize = Math.max(1, Math.min(internalTexture?.width ?? 1, internalTexture?.height ?? 1, is3DTexture ? (internalTexture?.depth ?? 1) : Number.MAX_SAFE_INTEGER));
|
|
19068
|
+
const maxLod = internalTexture?.generateMipMaps ? Math.max(0, Math.floor(Math.log2(lodBaseSize))) : 0;
|
|
18903
19069
|
const showLayerDropdown = texture.is2DArray;
|
|
18904
19070
|
const layerCount = texture.is2DArray && internalTexture ? internalTexture.depth : 0;
|
|
18905
19071
|
useEffect(() => {
|
|
@@ -18916,7 +19082,14 @@ const TexturePreview = (props) => {
|
|
|
18916
19082
|
}
|
|
18917
19083
|
try {
|
|
18918
19084
|
await WhenTextureReadyAsync(texture); // Ensure texture is loaded before grabbing size
|
|
18919
|
-
const
|
|
19085
|
+
const size = texture.getSize();
|
|
19086
|
+
let textureWidth = size.width || internalTexture?.width || 1;
|
|
19087
|
+
let textureHeight = size.height || internalTexture?.height || textureWidth;
|
|
19088
|
+
if (is3DTexture) {
|
|
19089
|
+
const squareSize = Math.max(1, Math.min(textureWidth, textureHeight));
|
|
19090
|
+
textureWidth = squareSize;
|
|
19091
|
+
textureHeight = squareSize;
|
|
19092
|
+
}
|
|
18920
19093
|
// Calculate canvas dimensions
|
|
18921
19094
|
const canvasWidth = width ?? textureWidth;
|
|
18922
19095
|
const canvasHeight = height ?? textureHeight;
|
|
@@ -18926,7 +19099,7 @@ const TexturePreview = (props) => {
|
|
|
18926
19099
|
const imageWidth = `min(${maxWidth}, calc(${maxHeight} * ${aspectRatio}))`;
|
|
18927
19100
|
setCanvasStyle({ width: imageWidth });
|
|
18928
19101
|
// Fetch texture data BEFORE clearing the canvas to avoid flicker
|
|
18929
|
-
const data = await ApplyChannelsToTextureDataAsync(texture, textureWidth, textureHeight, texture.is2DArray ? layer : face, channels);
|
|
19102
|
+
const data = await ApplyChannelsToTextureDataAsync(texture, textureWidth, textureHeight, texture.is2DArray ? layer : face, channels, lod, slice);
|
|
18930
19103
|
// Now set canvas dimensions (this clears the canvas) and draw immediately
|
|
18931
19104
|
canvas.width = canvasWidth;
|
|
18932
19105
|
canvas.height = canvasHeight;
|
|
@@ -18941,7 +19114,19 @@ const TexturePreview = (props) => {
|
|
|
18941
19114
|
catch {
|
|
18942
19115
|
// If we fail, leave the canvas empty
|
|
18943
19116
|
}
|
|
18944
|
-
}, [texture, face, channels, offsetX, offsetY, width, height, internalTexture, layer]);
|
|
19117
|
+
}, [texture, face, channels, lod, slice, offsetX, offsetY, width, height, internalTexture, layer]);
|
|
19118
|
+
useEffect(() => {
|
|
19119
|
+
if (!is3DTexture || slice <= maxSlice) {
|
|
19120
|
+
return;
|
|
19121
|
+
}
|
|
19122
|
+
setSlice(maxSlice);
|
|
19123
|
+
}, [is3DTexture, maxSlice, slice]);
|
|
19124
|
+
useEffect(() => {
|
|
19125
|
+
if (lod <= maxLod) {
|
|
19126
|
+
return;
|
|
19127
|
+
}
|
|
19128
|
+
setLod(maxLod);
|
|
19129
|
+
}, [lod, maxLod]);
|
|
18945
19130
|
useImperativeHandle(imperativeRef, () => ({ refresh: updatePreviewAsync }), [updatePreviewAsync]);
|
|
18946
19131
|
useEffect(() => {
|
|
18947
19132
|
void updatePreviewAsync();
|
|
@@ -18950,7 +19135,7 @@ const TexturePreview = (props) => {
|
|
|
18950
19135
|
useEffect(() => {
|
|
18951
19136
|
void updatePreviewAsync();
|
|
18952
19137
|
}, [isPinned]);
|
|
18953
|
-
return (jsx(LineContainer, { uniqueId: "TexturePreview", children: jsxs("div", { className: classes.root, children: [disableToolbar ? null : texture.isCube ? (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Cube Faces", children: ["+X", "-X", "+Y", "-Y", "+Z", "-Z"].map((label, idx) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: face === idx ? "primary" : "subtle", onClick: () => setFace(idx), children: label }, label))) })) : (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Channels", children: ["R", "G", "B", "A", "ALL"].map((ch) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: channels === TextureChannelStates[ch] ? "primary" : "subtle", onClick: () => setChannels(TextureChannelStates[ch]), children: ch }, ch))) })), jsx("div", { className: classes.previewContainer, children: jsx("canvas", { ref: canvasRef, className: classes.preview, style: canvasStyle }) }), !disableToolbar && showLayerDropdown && layerCount > 0 && (jsx(SyncedSliderPropertyLine, { label: "Layer", value: layer, onChange: setLayer, min: 0, max: layerCount - 1, step: 1 })), texture.isRenderTarget && (jsx(Button$1, { appearance: "outline", onClick: () => {
|
|
19138
|
+
return (jsx(LineContainer, { uniqueId: "TexturePreview", children: jsxs("div", { className: classes.root, children: [disableToolbar ? null : texture.isCube ? (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Cube Faces", children: ["+X", "-X", "+Y", "-Y", "+Z", "-Z"].map((label, idx) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: face === idx ? "primary" : "subtle", onClick: () => setFace(idx), children: label }, label))) })) : (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Channels", children: ["R", "G", "B", "A", "ALL"].map((ch) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: channels === TextureChannelStates[ch] ? "primary" : "subtle", onClick: () => setChannels(TextureChannelStates[ch]), children: ch }, ch))) })), is3DTexture && (jsxs("div", { className: classes.sliderContainer, children: [jsxs(Label, { children: ["Slice: ", slice, " / ", maxSlice] }), jsx(Slider$1, { min: 0, max: maxSlice, step: 1, value: slice, onChange: (_, data) => setSlice(data.value) })] })), maxLod > 0 && (jsxs("div", { className: classes.sliderContainer, children: [jsxs(Label, { children: ["LOD: ", lod] }), jsx(Slider$1, { min: 0, max: maxLod, step: 1, value: lod, onChange: (_, data) => setLod(data.value) })] })), jsx("div", { className: classes.previewContainer, children: jsx("canvas", { ref: canvasRef, className: classes.preview, style: canvasStyle }) }), !disableToolbar && showLayerDropdown && layerCount > 0 && (jsx(SyncedSliderPropertyLine, { label: "Layer", value: layer, onChange: setLayer, min: 0, max: layerCount - 1, step: 1 })), texture.isRenderTarget && (jsx(Button$1, { appearance: "outline", onClick: () => {
|
|
18954
19139
|
void updatePreviewAsync();
|
|
18955
19140
|
}, children: "Refresh" }))] }) }));
|
|
18956
19141
|
};
|
|
@@ -21543,6 +21728,9 @@ const MaterialExplorerServiceDefinition = {
|
|
|
21543
21728
|
function IsCameraFrameGraphTask(task) {
|
|
21544
21729
|
return task.camera instanceof Camera;
|
|
21545
21730
|
}
|
|
21731
|
+
function IsNodesSectionType(node) {
|
|
21732
|
+
return node instanceof TransformNode || node instanceof Camera || node instanceof Light;
|
|
21733
|
+
}
|
|
21546
21734
|
const NodeExplorerServiceDefinition = {
|
|
21547
21735
|
friendlyName: "Node Explorer",
|
|
21548
21736
|
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity, GizmoServiceIdentity, WatcherServiceIdentity],
|
|
@@ -21552,21 +21740,36 @@ const NodeExplorerServiceDefinition = {
|
|
|
21552
21740
|
return undefined;
|
|
21553
21741
|
}
|
|
21554
21742
|
const nodeMovedObservable = new Observable();
|
|
21743
|
+
// Set of all nodes known to be in the scene, rebuilt each time getRootEntities
|
|
21744
|
+
// is called. Used by getEntityDisplayInfo to detect orphaned ancestor nodes.
|
|
21745
|
+
const knownSceneNodes = new Set();
|
|
21555
21746
|
const sectionRegistration = sceneExplorerService.addSection({
|
|
21556
21747
|
displayName: "Nodes",
|
|
21557
21748
|
order: 100 /* DefaultSectionsOrder.Nodes */,
|
|
21558
21749
|
getRootEntities: () => {
|
|
21559
|
-
const rootNodes =
|
|
21560
|
-
|
|
21561
|
-
//
|
|
21562
|
-
//
|
|
21750
|
+
const rootNodes = new Set(scene.rootNodes);
|
|
21751
|
+
knownSceneNodes.clear();
|
|
21752
|
+
// Ensure all nodes in the scene are reachable in the explorer, even if their
|
|
21753
|
+
// parent was removed from the scene or is not a type shown in the Nodes section.
|
|
21563
21754
|
for (const node of [...scene.meshes, ...scene.transformNodes, ...scene.cameras, ...scene.lights]) {
|
|
21564
|
-
|
|
21565
|
-
|
|
21566
|
-
|
|
21567
|
-
|
|
21568
|
-
|
|
21569
|
-
|
|
21755
|
+
knownSceneNodes.add(node);
|
|
21756
|
+
if (!node.parent) {
|
|
21757
|
+
continue;
|
|
21758
|
+
}
|
|
21759
|
+
if (!IsNodesSectionType(node.parent)) {
|
|
21760
|
+
// Parent is not a type shown in the Nodes section (e.g. a Bone).
|
|
21761
|
+
// Treat this node as a root so it still appears in the explorer.
|
|
21762
|
+
rootNodes.add(node);
|
|
21763
|
+
}
|
|
21764
|
+
else {
|
|
21765
|
+
// Walk up through Nodes-section-type parents to find the topmost ancestor.
|
|
21766
|
+
// If that ancestor was removed from the scene (not in rootNodes), add it
|
|
21767
|
+
// so the entire subtree remains visible in the explorer.
|
|
21768
|
+
let ancestor = node.parent;
|
|
21769
|
+
while (ancestor.parent && IsNodesSectionType(ancestor.parent)) {
|
|
21770
|
+
ancestor = ancestor.parent;
|
|
21771
|
+
}
|
|
21772
|
+
rootNodes.add(ancestor);
|
|
21570
21773
|
}
|
|
21571
21774
|
}
|
|
21572
21775
|
// Lights within a clustered light container are not included in Scene.lights or Scene.rootNodes.
|
|
@@ -21574,23 +21777,32 @@ const NodeExplorerServiceDefinition = {
|
|
|
21574
21777
|
for (const light of scene.lights) {
|
|
21575
21778
|
if (light instanceof ClusteredLightContainer) {
|
|
21576
21779
|
for (const childLight of light.lights) {
|
|
21577
|
-
|
|
21578
|
-
|
|
21780
|
+
knownSceneNodes.add(childLight);
|
|
21781
|
+
if (!childLight.parent) {
|
|
21782
|
+
rootNodes.add(childLight);
|
|
21579
21783
|
}
|
|
21580
21784
|
}
|
|
21581
21785
|
}
|
|
21582
21786
|
}
|
|
21583
|
-
return rootNodes;
|
|
21787
|
+
return [...rootNodes];
|
|
21584
21788
|
},
|
|
21585
21789
|
getEntityChildren: (node) => node.getChildren(),
|
|
21586
21790
|
getEntityDisplayInfo: (node) => {
|
|
21587
21791
|
const onChangeObservable = new Observable();
|
|
21588
21792
|
const nameHookToken = watcherService.watchProperty(node, "name", () => onChangeObservable.notifyObservers());
|
|
21589
21793
|
const parentHookToken = watcherService.watchProperty(node, "parent", () => nodeMovedObservable.notifyObservers(node));
|
|
21794
|
+
// A node is "not in the scene" if it is a Nodes-section type but is not
|
|
21795
|
+
// a known scene node. This handles nodes that were removed from the scene
|
|
21796
|
+
// but still appear because a descendant is in the scene. Nodes from the
|
|
21797
|
+
// !IsNodesSectionType(parent) branch are unaffected because they always
|
|
21798
|
+
// come from the scene's tracking lists. Clustered light children are also
|
|
21799
|
+
// unaffected because they are added to knownSceneNodes explicitly.
|
|
21800
|
+
const validationError = IsNodesSectionType(node) && !knownSceneNodes.has(node) ? "This entity is not in the scene but is shown because a descendant is still in the scene." : undefined;
|
|
21590
21801
|
return {
|
|
21591
21802
|
get name() {
|
|
21592
21803
|
return node.name || `Unnamed ${node.getClassName()}`;
|
|
21593
21804
|
},
|
|
21805
|
+
validationError,
|
|
21594
21806
|
onChange: onChangeObservable,
|
|
21595
21807
|
dispose: () => {
|
|
21596
21808
|
nameHookToken.dispose();
|
|
@@ -22608,23 +22820,68 @@ const CoordinateSystemModeOptions = [
|
|
|
22608
22820
|
{ label: "Right Handed", value: GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED },
|
|
22609
22821
|
];
|
|
22610
22822
|
const GLTFLoaderOptionsTool = ({ loaderOptions }) => {
|
|
22611
|
-
|
|
22823
|
+
const resetLoaderOptions = useCallback(() => {
|
|
22824
|
+
for (const key of Object.keys(loaderOptions)) {
|
|
22825
|
+
loaderOptions[key] = null;
|
|
22826
|
+
}
|
|
22827
|
+
}, [loaderOptions]);
|
|
22828
|
+
return (jsx(PropertyLine, { label: "Loader Options", expandByDefault: false, expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Always Compute Bounding Box", target: loaderOptions, propertyKey: "alwaysComputeBoundingBox", nullable: true, defaultValue: LoaderOptionDefaults.alwaysComputeBoundingBox }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Always Compute Skeleton Root Node", target: loaderOptions, propertyKey: "alwaysComputeSkeletonRootNode", nullable: true, defaultValue: LoaderOptionDefaults.alwaysComputeSkeletonRootNode }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Animation Start Mode", options: AnimationStartModeOptions, target: loaderOptions, propertyKey: "animationStartMode", nullable: true, defaultValue: LoaderOptionDefaults.animationStartMode }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Capture Performance Counters", target: loaderOptions, propertyKey: "capturePerformanceCounters", nullable: true, defaultValue: LoaderOptionDefaults.capturePerformanceCounters }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Compile Materials", target: loaderOptions, propertyKey: "compileMaterials", nullable: true, defaultValue: LoaderOptionDefaults.compileMaterials }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Compile Shadow Generators", target: loaderOptions, propertyKey: "compileShadowGenerators", nullable: true, defaultValue: LoaderOptionDefaults.compileShadowGenerators }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Coordinate System", options: CoordinateSystemModeOptions, target: loaderOptions, propertyKey: "coordinateSystemMode", nullable: true, defaultValue: LoaderOptionDefaults.coordinateSystemMode }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Create Instances", target: loaderOptions, propertyKey: "createInstances", nullable: true, defaultValue: LoaderOptionDefaults.createInstances }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Don't Use Transmission Helper", target: loaderOptions, propertyKey: "dontUseTransmissionHelper", nullable: true, defaultValue: LoaderOptionDefaults.dontUseTransmissionHelper }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Enable Logging", target: loaderOptions, propertyKey: "loggingEnabled", nullable: true, defaultValue: LoaderOptionDefaults.loggingEnabled }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Load All Materials", target: loaderOptions, propertyKey: "loadAllMaterials", nullable: true, defaultValue: LoaderOptionDefaults.loadAllMaterials }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Load Morph Targets", target: loaderOptions, propertyKey: "loadMorphTargets", nullable: true, defaultValue: LoaderOptionDefaults.loadMorphTargets }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Load Node Animations", target: loaderOptions, propertyKey: "loadNodeAnimations", nullable: true, defaultValue: LoaderOptionDefaults.loadNodeAnimations }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Load Only Materials", target: loaderOptions, propertyKey: "loadOnlyMaterials", nullable: true, defaultValue: LoaderOptionDefaults.loadOnlyMaterials }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Load Skins", target: loaderOptions, propertyKey: "loadSkins", nullable: true, defaultValue: LoaderOptionDefaults.loadSkins }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Skip Materials", target: loaderOptions, propertyKey: "skipMaterials", nullable: true, defaultValue: LoaderOptionDefaults.skipMaterials }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Target FPS", target: loaderOptions, propertyKey: "targetFps", min: 1, max: 120, step: 1, nullable: true, defaultValue: LoaderOptionDefaults.targetFps }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Transparency As Coverage", target: loaderOptions, propertyKey: "transparencyAsCoverage", nullable: true, defaultValue: LoaderOptionDefaults.transparencyAsCoverage }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Clip Plane", target: loaderOptions, propertyKey: "useClipPlane", nullable: true, defaultValue: LoaderOptionDefaults.useClipPlane }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use glTF Texture Names", target: loaderOptions, propertyKey: "useGltfTextureNames", nullable: true, defaultValue: LoaderOptionDefaults.useGltfTextureNames }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use OpenPBR", target: loaderOptions, propertyKey: "useOpenPBR", nullable: true, defaultValue: LoaderOptionDefaults.useOpenPBR }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Range Requests", target: loaderOptions, propertyKey: "useRangeRequests", nullable: true, defaultValue: LoaderOptionDefaults.useRangeRequests }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use sRGB Buffers", target: loaderOptions, propertyKey: "useSRGBBuffers", nullable: true, defaultValue: LoaderOptionDefaults.useSRGBBuffers }), jsx(ButtonLine, { label: "Reset to Defaults", icon: ArrowResetRegular, onClick: resetLoaderOptions })] }) }));
|
|
22612
22829
|
};
|
|
22613
22830
|
const GLTFExtensionOptionsTool = ({ extensionOptions }) => {
|
|
22614
|
-
|
|
22615
|
-
|
|
22616
|
-
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22831
|
+
const resetExtensionOptions = useCallback(() => {
|
|
22832
|
+
for (const options of Object.values(extensionOptions)) {
|
|
22833
|
+
for (const key of Object.keys(options)) {
|
|
22834
|
+
options[key] = null;
|
|
22835
|
+
}
|
|
22836
|
+
}
|
|
22837
|
+
}, [extensionOptions]);
|
|
22838
|
+
return (jsx(PropertyLine, { label: "Extension Options", expandByDefault: false, expandedContent: jsxs(Fragment, { children: [Object.entries(extensionOptions)
|
|
22839
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
22840
|
+
.map(([extensionName, options]) => {
|
|
22841
|
+
return (jsx(BoundProperty, { component: SwitchPropertyLine, label: extensionName, target: options, propertyKey: "enabled", nullable: true, defaultValue: true, expandedContent: (extensionName === "MSFT_lod" && (jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Maximum LODs", target: extensionOptions[extensionName], propertyKey: "maxLODsToLoad", min: 1, max: 10, step: 1, nullable: true, defaultValue: ExtensionOptionDefaults.MSFT_lod.maxLODsToLoad }, extensionName + "_maxLODsToLoad"))) ||
|
|
22842
|
+
undefined }, extensionName));
|
|
22843
|
+
}), jsx(ButtonLine, { label: "Reset to Defaults", icon: ArrowResetRegular, onClick: resetExtensionOptions })] }) }));
|
|
22620
22844
|
};
|
|
22621
22845
|
|
|
22846
|
+
const LoaderOptionsSetting = {
|
|
22847
|
+
key: "glTFLoaderOptions",
|
|
22848
|
+
defaultValue: {},
|
|
22849
|
+
};
|
|
22850
|
+
const ExtensionOptionsSetting = {
|
|
22851
|
+
key: "glTFExtensionOptions",
|
|
22852
|
+
defaultValue: {},
|
|
22853
|
+
};
|
|
22854
|
+
function CreatePersistingProxy(target, settingsStore, descriptor) {
|
|
22855
|
+
return new Proxy(target, {
|
|
22856
|
+
set(obj, prop, value) {
|
|
22857
|
+
const result = Reflect.set(obj, prop, value);
|
|
22858
|
+
settingsStore.writeSetting(descriptor, { ...obj });
|
|
22859
|
+
return result;
|
|
22860
|
+
},
|
|
22861
|
+
});
|
|
22862
|
+
}
|
|
22863
|
+
function HasNonNullValues(obj) {
|
|
22864
|
+
return Object.values(obj).some((v) => v !== null);
|
|
22865
|
+
}
|
|
22866
|
+
const OverridesWarning = (props) => {
|
|
22867
|
+
const { loaderOptions, extensionOptions } = props;
|
|
22868
|
+
useSetting(LoaderOptionsSetting);
|
|
22869
|
+
useSetting(ExtensionOptionsSetting);
|
|
22870
|
+
const hasLoaderOverrides = HasNonNullValues(loaderOptions);
|
|
22871
|
+
const hasExtensionOverrides = Object.values(extensionOptions).some((opts) => HasNonNullValues(opts));
|
|
22872
|
+
return (jsx(Collapse, { visible: hasLoaderOverrides || hasExtensionOverrides, children: jsx(MessageBar, { intent: "warning", message: "Loader option overrides are enabled and will persist across refreshes until disabled or reset." }) }));
|
|
22873
|
+
};
|
|
22622
22874
|
const GLTFLoaderOptionsServiceDefinition = {
|
|
22623
22875
|
friendlyName: "GLTF Loader Options",
|
|
22624
|
-
consumes: [ToolsServiceIdentity],
|
|
22625
|
-
factory: (toolsService) => {
|
|
22876
|
+
consumes: [ToolsServiceIdentity, SettingsStoreIdentity, ToastServiceIdentity],
|
|
22877
|
+
factory: (toolsService, settingsStore, toastService) => {
|
|
22626
22878
|
// Current loader options with nullable properties (null means "don't override the options coming in with load calls")
|
|
22627
|
-
|
|
22879
|
+
let currentLoaderOptions = Object.fromEntries(Object.keys(LoaderOptionDefaults).map((key) => [key, null]));
|
|
22880
|
+
// Hydrate loader options from persisted settings
|
|
22881
|
+
const persistedLoaderOptions = settingsStore.readSetting(LoaderOptionsSetting);
|
|
22882
|
+
Object.assign(currentLoaderOptions, persistedLoaderOptions);
|
|
22883
|
+
// Wrap in a proxy so property writes from the UI are automatically persisted
|
|
22884
|
+
currentLoaderOptions = CreatePersistingProxy(currentLoaderOptions, settingsStore, LoaderOptionsSetting);
|
|
22628
22885
|
// Build extension options dynamically from the registered extensions.
|
|
22629
22886
|
// Every extension gets an 'enabled' toggle; extensions in ExtensionOptionDefaults also get their extra properties.
|
|
22630
22887
|
const currentExtensionOptions = {};
|
|
@@ -22633,22 +22890,50 @@ const GLTFLoaderOptionsServiceDefinition = {
|
|
|
22633
22890
|
const extraNulls = defaults ? Object.fromEntries(Object.keys(defaults).map((key) => [key, null])) : {};
|
|
22634
22891
|
currentExtensionOptions[extName] = { enabled: null, ...extraNulls };
|
|
22635
22892
|
}
|
|
22893
|
+
// Hydrate extension options from persisted settings, only for extensions that are still registered
|
|
22894
|
+
const persistedExtensionOptions = settingsStore.readSetting(ExtensionOptionsSetting);
|
|
22895
|
+
for (const [extName, persistedOptions] of Object.entries(persistedExtensionOptions)) {
|
|
22896
|
+
if (currentExtensionOptions[extName] && persistedOptions) {
|
|
22897
|
+
Object.assign(currentExtensionOptions[extName], persistedOptions);
|
|
22898
|
+
}
|
|
22899
|
+
}
|
|
22900
|
+
// Wrap each extension's options object in a proxy that persists the full extension options map on write
|
|
22901
|
+
for (const extName of Object.keys(currentExtensionOptions)) {
|
|
22902
|
+
currentExtensionOptions[extName] = new Proxy(currentExtensionOptions[extName], {
|
|
22903
|
+
set(obj, prop, value) {
|
|
22904
|
+
const result = Reflect.set(obj, prop, value);
|
|
22905
|
+
settingsStore.writeSetting(ExtensionOptionsSetting, { ...currentExtensionOptions });
|
|
22906
|
+
return result;
|
|
22907
|
+
},
|
|
22908
|
+
});
|
|
22909
|
+
}
|
|
22636
22910
|
// Subscribe to plugin activation
|
|
22637
22911
|
const pluginObserver = SceneLoader.OnPluginActivatedObservable.add((plugin) => {
|
|
22638
22912
|
if (plugin.name === "gltf") {
|
|
22639
22913
|
const loader = plugin;
|
|
22640
22914
|
// Apply loader settings (filter out null values to not override options coming in with load calls)
|
|
22641
22915
|
const nonNullLoaderOptions = Object.fromEntries(Object.entries(currentLoaderOptions).filter(([_, v]) => v !== null));
|
|
22916
|
+
const hasLoaderOverrides = Object.keys(nonNullLoaderOptions).length > 0;
|
|
22642
22917
|
Object.assign(loader, nonNullLoaderOptions);
|
|
22918
|
+
let hasExtensionOverrides = false;
|
|
22643
22919
|
// Subscribe to extension loading
|
|
22644
22920
|
loader.onExtensionLoadedObservable.add((extension) => {
|
|
22645
22921
|
const extensionOptions = currentExtensionOptions[extension.name];
|
|
22646
22922
|
if (extensionOptions) {
|
|
22647
22923
|
// Apply extension settings (filter out null values to not override options coming in with load calls)
|
|
22648
22924
|
const nonNullExtOptions = Object.fromEntries(Object.entries(extensionOptions).filter(([_, v]) => v !== null));
|
|
22925
|
+
if (Object.keys(nonNullExtOptions).length > 0) {
|
|
22926
|
+
hasExtensionOverrides = true;
|
|
22927
|
+
}
|
|
22649
22928
|
Object.assign(extension, nonNullExtOptions);
|
|
22650
22929
|
}
|
|
22651
22930
|
});
|
|
22931
|
+
// Show a toast after all extensions have loaded if any overrides were applied
|
|
22932
|
+
loader.onCompleteObservable.addOnce(() => {
|
|
22933
|
+
if (hasLoaderOverrides || hasExtensionOverrides) {
|
|
22934
|
+
toastService.showToast("Applied glTF loader option overrides");
|
|
22935
|
+
}
|
|
22936
|
+
});
|
|
22652
22937
|
}
|
|
22653
22938
|
});
|
|
22654
22939
|
const loaderToolsRegistration = toolsService.addSectionContent({
|
|
@@ -22656,7 +22941,7 @@ const GLTFLoaderOptionsServiceDefinition = {
|
|
|
22656
22941
|
section: "GLTF Loader",
|
|
22657
22942
|
order: 50,
|
|
22658
22943
|
component: () => {
|
|
22659
|
-
return (jsxs(Fragment, { children: [jsx(MessageBar, { intent: "info", message: "Reload the file for changes to take effect" }), jsx(GLTFLoaderOptionsTool, { loaderOptions: currentLoaderOptions }), jsx(GLTFExtensionOptionsTool, { extensionOptions: currentExtensionOptions })] }));
|
|
22944
|
+
return (jsxs(Fragment, { children: [jsx(MessageBar, { intent: "info", message: "Reload the file for changes to take effect" }), jsx(OverridesWarning, { loaderOptions: currentLoaderOptions, extensionOptions: currentExtensionOptions }), jsx(GLTFLoaderOptionsTool, { loaderOptions: currentLoaderOptions }), jsx(GLTFExtensionOptionsTool, { extensionOptions: currentExtensionOptions })] }));
|
|
22660
22945
|
},
|
|
22661
22946
|
});
|
|
22662
22947
|
return {
|
|
@@ -22861,6 +23146,37 @@ const ShellSettingsServiceDefinition = {
|
|
|
22861
23146
|
},
|
|
22862
23147
|
};
|
|
22863
23148
|
|
|
23149
|
+
const InspectorSettingsServiceDefinition = {
|
|
23150
|
+
friendlyName: "Inspector Settings",
|
|
23151
|
+
consumes: [SettingsServiceIdentity],
|
|
23152
|
+
factory: (settingsService) => {
|
|
23153
|
+
const settingRegistration = settingsService.addSectionContent({
|
|
23154
|
+
key: "Inspector Settings",
|
|
23155
|
+
section: "UI",
|
|
23156
|
+
component: () => {
|
|
23157
|
+
const [compactMode, setCompactMode] = useSetting(CompactModeSettingDescriptor);
|
|
23158
|
+
const [useDegrees, setUseDegrees] = useSetting(UseDegreesSettingDescriptor);
|
|
23159
|
+
const [useEuler, setUseEuler] = useSetting(UseEulerSettingDescriptor);
|
|
23160
|
+
const [disableCopy, setDisableCopy] = useSetting(DisableCopySettingDescriptor);
|
|
23161
|
+
return (jsxs(Fragment, { children: [jsx(SwitchPropertyLine, { label: "Compact Mode", description: "Use a more compact UI with less spacing.", value: compactMode, onChange: (checked) => {
|
|
23162
|
+
setCompactMode(checked);
|
|
23163
|
+
} }), jsx(SwitchPropertyLine, { label: "Use Degrees", description: "Using degrees instead of radians.", value: useDegrees, onChange: (checked) => {
|
|
23164
|
+
setUseDegrees(checked);
|
|
23165
|
+
} }), jsx(SwitchPropertyLine, { label: "Only Show Euler Angles", description: "Only show Euler angles in rotation properties, rather than quaternions.", value: useEuler, onChange: (checked) => {
|
|
23166
|
+
setUseEuler(checked);
|
|
23167
|
+
} }), jsx(SwitchPropertyLine, { label: "Disable Copy Button", description: "Disables the copy to clipboard button on property lines. You can still Ctrl+Click on the label to copy.", value: disableCopy, onChange: (checked) => {
|
|
23168
|
+
setDisableCopy(checked);
|
|
23169
|
+
} })] }));
|
|
23170
|
+
},
|
|
23171
|
+
});
|
|
23172
|
+
return {
|
|
23173
|
+
dispose: () => {
|
|
23174
|
+
settingRegistration.dispose();
|
|
23175
|
+
},
|
|
23176
|
+
};
|
|
23177
|
+
},
|
|
23178
|
+
};
|
|
23179
|
+
|
|
22864
23180
|
const UserFeedbackServiceDefinition = {
|
|
22865
23181
|
friendlyName: "User Feedback",
|
|
22866
23182
|
consumes: [ShellServiceIdentity],
|
|
@@ -23065,7 +23381,7 @@ function ShowInspector(scene, options = {}) {
|
|
|
23065
23381
|
// Tools pane tab and related services.
|
|
23066
23382
|
ToolsServiceDefinition, ExportServiceDefinition, GLTFAnimationImportServiceDefinition, GLTFLoaderOptionsServiceDefinition, GLTFValidationServiceDefinition, CaptureToolsDefinition,
|
|
23067
23383
|
// Settings pane tab and related services.
|
|
23068
|
-
SettingsServiceDefinition, WatcherSettingsServiceDefinition, ShellSettingsServiceDefinition,
|
|
23384
|
+
SettingsServiceDefinition, InspectorSettingsServiceDefinition, WatcherSettingsServiceDefinition, ShellSettingsServiceDefinition,
|
|
23069
23385
|
// Adds a button to refresh all properties manually (when watcher is in "manual" mode).
|
|
23070
23386
|
WatcherRefreshToolbarServiceDefinition,
|
|
23071
23387
|
// 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.).
|
|
@@ -23922,5 +24238,5 @@ const TextAreaPropertyLine = (props) => {
|
|
|
23922
24238
|
// Attach Inspector v2 to Scene.debugLayer as a side effect for back compat.
|
|
23923
24239
|
AttachDebugLayer();
|
|
23924
24240
|
|
|
23925
|
-
export { GizmoServiceIdentity as $, Accordion as A, Button as B, CheckboxPropertyLine as C, ColorPickerPopup as D, ColorStepGradientComponent as E, ComboBox as F, ComboBoxPropertyLine as G, ConstructorFactory as H, ConvertOptions as I, DebugServiceIdentity as J, DetachDebugLayer as K, Link as L, MessageBar as M, NumberInputPropertyLine as N, DraggableLine as O, Popover as P, Dropdown as Q, EntitySelector as R, ShellServiceIdentity as S, TextInputPropertyLine as T, ErrorBoundary as U, Vector3PropertyLine as V, ExtensibleAccordion as W, FactorGradientComponent as X, FactorGradientList as Y, FileUploadLine as Z, GetPropertyDescriptor as _, useToast as a,
|
|
23926
|
-
//# sourceMappingURL=index-
|
|
24241
|
+
export { GizmoServiceIdentity as $, Accordion as A, Button as B, CheckboxPropertyLine as C, ColorPickerPopup as D, ColorStepGradientComponent as E, ComboBox as F, ComboBoxPropertyLine as G, ConstructorFactory as H, ConvertOptions as I, DebugServiceIdentity as J, DetachDebugLayer as K, Link as L, MessageBar as M, NumberInputPropertyLine as N, DraggableLine as O, Popover as P, Dropdown as Q, EntitySelector as R, ShellServiceIdentity as S, TextInputPropertyLine as T, ErrorBoundary as U, Vector3PropertyLine as V, ExtensibleAccordion as W, FactorGradientComponent as X, FactorGradientList as Y, FileUploadLine as Z, GetPropertyDescriptor as _, useToast as a, ToastProvider as a$, HexPropertyLine as a0, InfoLabel as a1, InputHexField as a2, InputHsvField as a3, InspectableCommandRegistryIdentity as a4, Inspector as a5, InterceptFunction as a6, InterceptProperty as a7, IsPropertyReadonly as a8, LineContainer as a9, SelectionServiceDefinition as aA, SettingsServiceIdentity as aB, SettingsStore as aC, SettingsStoreIdentity as aD, ShowInspector as aE, SidePaneContainer as aF, SkeletonSelector as aG, Slider as aH, SpinButton as aI, StartInspectable as aJ, StatsServiceIdentity as aK, StringDropdown as aL, StringDropdownPropertyLine as aM, StringifiedPropertyLine as aN, Switch as aO, SwitchPropertyLine as aP, SyncedSliderInput as aQ, SyncedSliderPropertyLine as aR, TeachingMoment as aS, TextAreaPropertyLine as aT, TextInput as aU, TextPropertyLine as aV, Textarea as aW, TextureSelector as aX, TextureUpload as aY, Theme as aZ, ThemeServiceIdentity as a_, LinkPropertyLine as aa, LinkToEntityPropertyLine as ab, List as ac, MakeDialogTeachingMoment as ad, MakeLazyComponent as ae, MakeModularTool as af, MakePopoverTeachingMoment as ag, MakePropertyHook as ah, MakeTeachingMoment as ai, MaterialSelector as aj, NodeSelector as ak, NumberDropdown as al, NumberDropdownPropertyLine as am, ObservableCollection as an, Pane as ao, PlaceholderPropertyLine as ap, PositionedPopover as aq, PropertiesServiceIdentity as ar, Property as as, PropertyContext as at, PropertyLine as au, QuaternionPropertyLine as av, RotationVectorPropertyLine as aw, SceneExplorerServiceIdentity as ax, SearchBar as ay, SearchBox as az, useInterceptObservable as b, ToggleButton as b0, Tooltip as b1, UploadButton as b2, Vector2PropertyLine as b3, Vector4PropertyLine as b4, WatcherServiceIdentity as b5, useAngleConverters as b6, useAsyncResource as b7, useColor3Property as b8, useColor4Property as b9, useEventListener as ba, useEventfulState as bb, useKeyListener as bc, useKeyState as bd, useObservableCollection as be, useOrderedObservableCollection as bf, usePollingObservable as bg, usePropertyChangedNotifier as bh, useQuaternionProperty as bi, useResource as bj, useTheme as bk, useThemeMode as bl, useVector3Property as bm, LinkToEntity as c, SpinButtonPropertyLine as d, useProperty as e, SceneContextIdentity as f, SelectionServiceIdentity as g, useObservableState as h, AccordionSection as i, ButtonLine as j, ToolsServiceIdentity as k, AccordionSectionItem as l, AttachDebugLayer as m, BooleanBadgePropertyLine as n, BoundProperty as o, BuiltInsExtensionFeed as p, Checkbox as q, ChildWindow as r, Collapse as s, Color3GradientComponent as t, useExtensionManager as u, Color3GradientList as v, Color3PropertyLine as w, Color4GradientComponent as x, Color4GradientList as y, Color4PropertyLine as z };
|
|
24242
|
+
//# sourceMappingURL=index-DB_fpb1t.js.map
|