@babylonjs/inspector 8.29.0-preview → 8.29.1-preview

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.
@@ -1,15 +1,16 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { useMemo, useEffect, useState, useRef, useCallback, forwardRef, createContext, useContext, isValidElement, cloneElement, Children, memo, createElement, Suspense, useReducer, lazy } from 'react';
2
+ import { useMemo, useEffect, useState, useRef, useCallback, forwardRef, createContext, useContext, isValidElement, cloneElement, Children, useLayoutEffect, memo, createElement, Suspense, useReducer, lazy } from 'react';
3
3
  import { Color3, Color4 } from '@babylonjs/core/Maths/math.color.js';
4
4
  import { Vector3, Quaternion, Matrix, Vector2, Vector4, TmpVectors } from '@babylonjs/core/Maths/math.vector.js';
5
5
  import { Observable } from '@babylonjs/core/Misc/observable.js';
6
- import { makeStyles, tokens, Link, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, ToggleButton as ToggleButton$1, Button as Button$1, Body1, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle1, AccordionPanel, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, Divider, TabList, Tooltip, Title3, Tab, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, Switch as Switch$1, PresenceBadge, Spinner, Dialog, DialogTrigger, DialogSurface, DialogBody, DialogTitle, DialogContent, SplitButton, MenuItemRadio, createLightTheme, createDarkTheme, FluentProvider, DialogActions, List as List$1, ListItem, useId, SpinButton as SpinButton$1, Slider, Input, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, Badge, Dropdown as Dropdown$1, Option, Popover, PopoverTrigger, ColorSwatch, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, Textarea as Textarea$1, useComboboxFilter, Combobox, Field } from '@fluentui/react-components';
6
+ import { makeStyles, tokens, Link, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, ToggleButton as ToggleButton$1, Button as Button$1, Body1, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle1, AccordionPanel, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, TabList, Divider, Tooltip, Title3, Tab, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, Switch as Switch$1, PresenceBadge, Spinner, Dialog, DialogTrigger, DialogSurface, DialogBody, DialogTitle, DialogContent, SplitButton, MenuItemRadio, createLightTheme, createDarkTheme, FluentProvider, DialogActions, List as List$1, ListItem, useId, SpinButton as SpinButton$1, Slider, Input, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, Badge, Dropdown as Dropdown$1, Option, Popover, PopoverTrigger, ColorSwatch, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, Textarea as Textarea$1, useComboboxFilter, Combobox, Field } from '@fluentui/react-components';
7
7
  import { SubtractFilled, AddFilled, CopyRegular, PanelLeftExpandRegular, PanelLeftContractRegular, PanelRightExpandRegular, PanelRightContractRegular, DocumentTextRegular, FilterRegular, MoviesAndTvRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, DataBarHorizontalRegular, WrenchRegular, AppsAddInRegular, DismissRegular, WeatherSunnyRegular, WeatherMoonRegular, ErrorCircleRegular, ArrowMoveRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, GlobeRegular, SaveRegular, ArrowUndoRegular, ClearFormattingRegular, DeleteRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, StopFilled, PlayFilled, StackRegular, FilmstripRegular, PauseFilled, LayerRegular, FrameRegular, PlayRegular, AppGenericRegular, PaintBrushRegular, BoxRegular, BranchRegular, CameraRegular, LightbulbRegular, EyeRegular, EyeOffRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, Cone16Filled, Cone16Regular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, WeatherSunnyLowFilled, DeleteFilled } from '@fluentui/react-icons';
8
8
  import { Collapse as Collapse$1 } from '@fluentui/react-motion-components-preview';
9
9
  import '@babylonjs/core/Misc/typeStore.js';
10
10
  import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
11
11
  import { AsyncLock } from '@babylonjs/core/Misc/asyncLock.js';
12
12
  import { Deferred } from '@babylonjs/core/Misc/deferred.js';
13
+ import { useResizeHandle } from '@fluentui-contrib/react-resize-handle';
13
14
  import { VirtualizerScrollView } from '@fluentui-contrib/react-virtualizer';
14
15
  import { FontAsset } from '@babylonjs/addons/msdfText/fontAsset.js';
15
16
  import { TextRenderer } from '@babylonjs/addons/msdfText/textRenderer.js';
@@ -28,6 +29,7 @@ import '@babylonjs/core/Engines/AbstractEngine/abstractEngine.timeQuery.js';
28
29
  import '@babylonjs/core/Engines/Extensions/engine.query.js';
29
30
  import '@babylonjs/core/Engines/WebGPU/Extensions/engine.query.js';
30
31
  import { PerfCollectionStrategy } from '@babylonjs/core/Misc/PerformanceViewer/performanceViewerCollectionStrategies.js';
32
+ import '@babylonjs/core/Misc/PerformanceViewer/performanceViewerSceneExtension.js';
31
33
  import { PressureObserverWrapper } from '@babylonjs/core/Misc/pressureObserverWrapper.js';
32
34
  import { AbstractEngine } from '@babylonjs/core/Engines/abstractEngine.js';
33
35
  import { EngineStore } from '@babylonjs/core/Engines/engineStore.js';
@@ -1276,7 +1278,7 @@ const useStyles$9 = makeStyles({
1276
1278
  display: "flex",
1277
1279
  flexDirection: "row",
1278
1280
  flex: "0 0 auto",
1279
- backgroundColor: tokens.colorNeutralBackground1,
1281
+ backgroundColor: tokens.colorNeutralBackground2,
1280
1282
  },
1281
1283
  bar: {
1282
1284
  display: "flex",
@@ -1284,6 +1286,14 @@ const useStyles$9 = makeStyles({
1284
1286
  height: "32px",
1285
1287
  overflow: "hidden",
1286
1288
  padding: `${tokens.spacingVerticalSNudge} ${tokens.spacingHorizontalSNudge}`,
1289
+ border: `1px solid ${tokens.colorNeutralStroke2}`,
1290
+ backgroundColor: tokens.colorNeutralBackground1,
1291
+ },
1292
+ barTop: {
1293
+ borderTopWidth: 0,
1294
+ },
1295
+ barBottom: {
1296
+ borderBottomWidth: 0,
1287
1297
  },
1288
1298
  barLeft: {
1289
1299
  marginRight: "auto",
@@ -1297,16 +1307,13 @@ const useStyles$9 = makeStyles({
1297
1307
  flexDirection: "row-reverse",
1298
1308
  columnGap: tokens.spacingHorizontalSNudge,
1299
1309
  },
1300
- barDivider: {
1301
- flex: "0 0 auto",
1302
- },
1303
1310
  barItem: {
1304
1311
  display: "flex",
1305
1312
  },
1306
1313
  paneTabListDiv: {
1314
+ backgroundColor: tokens.colorNeutralBackground2,
1307
1315
  flex: "0 0 auto",
1308
1316
  display: "flex",
1309
- columnGap: tokens.spacingHorizontalSNudge,
1310
1317
  },
1311
1318
  paneTabListDivLeft: {
1312
1319
  flexDirection: "row-reverse",
@@ -1389,7 +1396,7 @@ const Toolbar = ({ location, components }) => {
1389
1396
  const classes = useStyles$9();
1390
1397
  const leftComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "left"), [components]);
1391
1398
  const rightComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "right"), [components]);
1392
- return (jsx(Fragment, { children: components.length > 0 && (jsxs("div", { className: classes.bar, children: [jsx("div", { className: classes.barLeft, children: leftComponents.map((entry) => (jsx(ToolbarItem, { location: location, alignment: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) }), jsx("div", { className: classes.barRight, children: rightComponents.map((entry) => (jsx(ToolbarItem, { location: location, alignment: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) })] })) }));
1399
+ 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, { location: location, alignment: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) }), jsx("div", { className: classes.barRight, children: rightComponents.map((entry) => (jsx(ToolbarItem, { location: location, alignment: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) })] })) }));
1393
1400
  };
1394
1401
  // This is a wrapper for a tab in a side pane that simply adds a teaching moment, which is useful for dynamically added items, possibly from extensions.
1395
1402
  const SidePaneTab = ({ alignment, id,
@@ -1403,24 +1410,34 @@ icon: Icon, title, suppressTeachingMoment, }) => {
1403
1410
  // This hook provides a side pane container and the tab list.
1404
1411
  // In "compact" mode, the tab list is integrated into the pane itself.
1405
1412
  // In "full" mode, the returned tab list is later injected into the toolbar.
1406
- function usePane(alignment, defaultWidth, minWidth, paneComponents, toolbarMode, topBarComponents, bottomBarComponents) {
1413
+ function usePane(alignment, defaultWidth, minWidth, topPaneComponents, bottomPaneComponents, toolbarMode, topBarComponents, bottomBarComponents) {
1407
1414
  const classes = useStyles$9();
1408
- const [selectedTab, setSelectedTab] = useState();
1415
+ const [topSelectedTab, setTopSelectedTab] = useState();
1416
+ const [bottomSelectedTab, setBottomSelectedTab] = useState();
1409
1417
  const [collapsed, setCollapsed] = useState(false);
1410
1418
  const onExpandCollapseClick = useCallback(() => {
1411
1419
  setCollapsed((collapsed) => !collapsed);
1412
1420
  }, [collapsed]);
1413
1421
  const widthStorageKey = `Babylon/Settings/${alignment}Pane/Width`;
1422
+ const heightStorageKey = `Babylon/Settings/${alignment}Pane/HeightAdjust`;
1414
1423
  const [width, setWidth] = useState(Number.parseInt(localStorage.getItem(widthStorageKey) ?? "") || Math.max(defaultWidth, minWidth));
1415
1424
  const [resizing, setResizing] = useState(false);
1416
1425
  useEffect(() => {
1417
- if ((selectedTab && !paneComponents.includes(selectedTab)) || (!selectedTab && paneComponents.length > 0)) {
1418
- setSelectedTab(paneComponents[0]);
1426
+ if ((topSelectedTab && !topPaneComponents.includes(topSelectedTab)) || (!topSelectedTab && topPaneComponents.length > 0)) {
1427
+ setTopSelectedTab(topPaneComponents[0]);
1419
1428
  }
1420
- else if (selectedTab && paneComponents.length === 0) {
1421
- setSelectedTab(undefined);
1429
+ else if (topSelectedTab && topPaneComponents.length === 0) {
1430
+ setTopSelectedTab(undefined);
1422
1431
  }
1423
- }, [selectedTab, paneComponents]);
1432
+ }, [topSelectedTab, topPaneComponents]);
1433
+ useEffect(() => {
1434
+ if ((bottomSelectedTab && !bottomPaneComponents.includes(bottomSelectedTab)) || (!bottomSelectedTab && bottomPaneComponents.length > 0)) {
1435
+ setBottomSelectedTab(bottomPaneComponents[0]);
1436
+ }
1437
+ else if (bottomSelectedTab && bottomPaneComponents.length === 0) {
1438
+ setBottomSelectedTab(undefined);
1439
+ }
1440
+ }, [bottomSelectedTab, bottomPaneComponents]);
1424
1441
  const expandCollapseIcon = useMemo(() => {
1425
1442
  if (alignment === "left") {
1426
1443
  return collapsed ? jsx(PanelLeftExpandRegular, {}) : jsx(PanelLeftContractRegular, {});
@@ -1429,6 +1446,7 @@ function usePane(alignment, defaultWidth, minWidth, paneComponents, toolbarMode,
1429
1446
  return collapsed ? jsx(PanelRightExpandRegular, {}) : jsx(PanelRightContractRegular, {});
1430
1447
  }
1431
1448
  }, [collapsed, alignment]);
1449
+ // TODO: Replace this custom resizing logic with useResizeHandle.
1432
1450
  // This function handles resizing the side pane width.
1433
1451
  const onResizerPointerDown = useCallback((event) => {
1434
1452
  const currentTarget = event.currentTarget;
@@ -1457,44 +1475,86 @@ function usePane(alignment, defaultWidth, minWidth, paneComponents, toolbarMode,
1457
1475
  localStorage.setItem(widthStorageKey, finalWidth.toString());
1458
1476
  }, { once: true });
1459
1477
  }, [resizing]);
1478
+ const createPaneTabList = useCallback((paneComponents, toolbarMode, selectedTab, setSelectedTab) => {
1479
+ return (jsx(Fragment, { children: paneComponents.length > 0 && (jsxs("div", { className: `${classes.paneTabListDiv} ${alignment === "left" || toolbarMode === "compact" ? classes.paneTabListDivLeft : classes.paneTabListDivRight}`, children: [paneComponents.length > 1 && (jsx(Fragment, { children: jsx(TabList, { selectedValue: selectedTab?.key ?? "", onTabSelect: (event, data) => {
1480
+ const tab = paneComponents.find((entry) => entry.key === data.value);
1481
+ setSelectedTab(tab);
1482
+ setCollapsed(false);
1483
+ }, children: paneComponents.map((entry) => (jsx(SidePaneTab, { alignment: alignment, id: entry.key, title: entry.title, icon: entry.icon, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) }) })), toolbarMode === "full" && (jsxs(Fragment, { children: [jsx(Divider, { vertical: true, inset: true }), jsx(Tooltip, { content: collapsed ? "Show Side Pane" : "Hide Side Pane", relationship: "label", children: jsx(Button$1, { className: classes.paneCollapseButton, appearance: "subtle", icon: expandCollapseIcon, onClick: onExpandCollapseClick }) })] }))] })) }));
1484
+ }, [alignment, collapsed]);
1460
1485
  // This memos the TabList to make it easy for the JSX to be inserted at the top of the pane (in "compact" mode) or returned to the caller to be used in the toolbar (in "full" mode).
1461
- const paneTabList = useMemo(() => {
1462
- return (jsx(Fragment, { children: paneComponents.length > 0 && (jsxs("div", { className: `${classes.paneTabListDiv} ${alignment === "left" || toolbarMode === "compact" ? classes.paneTabListDivLeft : classes.paneTabListDivRight}`, children: [paneComponents.length > 1 && (jsxs(Fragment, { children: [jsx(Divider, { vertical: true, inset: true }), jsx(TabList, { selectedValue: selectedTab?.key ?? "", onTabSelect: (event, data) => {
1463
- const tab = paneComponents.find((entry) => entry.key === data.value);
1464
- setSelectedTab(tab);
1465
- setCollapsed(false);
1466
- }, children: paneComponents.map((entry) => (jsx(SidePaneTab, { alignment: alignment, id: entry.key, title: entry.title, icon: entry.icon, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) })] })), toolbarMode === "full" && (jsx(Tooltip, { content: collapsed ? "Show Side Pane" : "Hide Side Pane", relationship: "label", children: jsx(Button$1, { className: classes.paneCollapseButton, appearance: "subtle", icon: expandCollapseIcon, onClick: onExpandCollapseClick }) }))] })) }));
1467
- }, [paneComponents, selectedTab, collapsed]);
1486
+ const topPaneTabList = useMemo(() => createPaneTabList(topPaneComponents, toolbarMode, topSelectedTab, setTopSelectedTab), [topPaneComponents, toolbarMode, topSelectedTab]);
1487
+ const bottomPaneTabList = useMemo(() => createPaneTabList(bottomPaneComponents, "compact", bottomSelectedTab, setBottomSelectedTab), [bottomPaneComponents, bottomSelectedTab]);
1488
+ // This manages the CSS variable that controls the height of the bottom pane.
1489
+ const paneHeightAdjustCSSVar = "--pane-height-adjust";
1490
+ const { elementRef: paneVerticalResizeElementRef, handleRef: paneVerticalResizeHandleRef, setValue: setPaneHeightAdjust, } = useResizeHandle({
1491
+ growDirection: "up",
1492
+ relative: true,
1493
+ variableName: paneHeightAdjustCSSVar,
1494
+ variableTarget: "element",
1495
+ onChange: (event, data) => {
1496
+ // Whenever the height is adjusted, store the value.
1497
+ localStorage.setItem(heightStorageKey, data.value.toString());
1498
+ },
1499
+ });
1500
+ // This ensures that when the component is first rendered, the CSS variable is set from storage.
1501
+ useLayoutEffect(() => {
1502
+ const storedPaneHeightAdjust = localStorage.getItem(heightStorageKey);
1503
+ if (storedPaneHeightAdjust) {
1504
+ setPaneHeightAdjust(Number.parseInt(storedPaneHeightAdjust));
1505
+ }
1506
+ });
1468
1507
  // This memoizes the pane itself, which may or may not include the tab list, depending on the toolbar mode.
1469
1508
  const pane = useMemo(() => {
1470
- return (jsx(Fragment, { children: paneComponents.length > 0 && (jsxs("div", { className: `${classes.pane} ${alignment === "left" ? classes.paneLeft : classes.paneRight}`, children: [jsx(Collapse, { orientation: "horizontal", visible: !collapsed, children: jsxs("div", { className: classes.paneContainer, children: [toolbarMode === "compact" && (paneComponents.length > 1 || topBarComponents.length > 0) && (jsxs(Fragment, { children: [jsxs("div", { className: classes.barDiv, children: [paneTabList, jsx(Toolbar, { location: "top", components: topBarComponents })] }), jsx(Divider, { className: classes.barDivider })] })), jsxs("div", { className: classes.paneContent, style: { width: `${width}px` }, children: [selectedTab?.title ? (jsxs(Fragment, { children: [jsx(Title3, { className: classes.paneHeader, children: selectedTab.title }), jsx(Divider, { inset: true, className: classes.headerDivider, appearance: "brand" })] })) : null, selectedTab?.content && jsx(selectedTab.content, {})] }), toolbarMode === "compact" && bottomBarComponents.length > 0 && (jsxs(Fragment, { children: [jsx(Divider, { className: classes.barDivider }), jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarComponents }) })] }))] }) }), jsx("div", { className: `${classes.resizer} ${alignment === "left" ? classes.resizerLeft : classes.resizerRight}`, style: { pointerEvents: `${collapsed ? "none" : "auto"}` }, onPointerDown: onResizerPointerDown })] })) }));
1471
- }, [paneComponents, selectedTab, collapsed, width, resizing]);
1472
- return [paneTabList, pane];
1509
+ return (jsx(Fragment, { children: (topPaneComponents.length > 0 || bottomPaneComponents.length > 0) && (jsxs("div", { className: `${classes.pane} ${alignment === "left" ? classes.paneLeft : classes.paneRight}`, children: [jsx(Collapse, { orientation: "horizontal", visible: !collapsed, children: jsxs("div", { className: classes.paneContainer, style: { width: `${width}px` }, children: [toolbarMode === "compact" && (topPaneComponents.length > 1 || topBarComponents.length > 0) && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [topPaneTabList, jsx(Toolbar, { location: "top", components: topBarComponents })] }) })), jsxs("div", { className: classes.paneContent, children: [topSelectedTab?.title ? (jsxs(Fragment, { children: [jsx(Title3, { className: classes.paneHeader, children: topSelectedTab.title }), jsx(Divider, { inset: true, className: classes.headerDivider, appearance: "brand" })] })) : null, topSelectedTab?.content && jsx(topSelectedTab.content, {})] }), topPaneComponents.length > 0 && bottomPaneComponents.length > 0 && (jsx(Divider, { ref: paneVerticalResizeHandleRef, className: classes.headerDivider, style: { margin: "0", minHeight: tokens.spacingVerticalM, cursor: "ns-resize" } })), bottomPaneComponents.length > 1 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: bottomPaneTabList }) })), jsxs("div", { ref: paneVerticalResizeElementRef, className: classes.paneContent, style: { height: `clamp(200px,calc(45% + var(${paneHeightAdjustCSSVar}, 0px)), 100% - 300px)`, flex: "0 0 auto" }, children: [bottomSelectedTab?.title ? (jsxs(Fragment, { children: [jsx(Title3, { className: classes.paneHeader, children: bottomSelectedTab.title }), jsx(Divider, { inset: true, className: classes.headerDivider, appearance: "brand" })] })) : null, bottomSelectedTab?.content && jsx(bottomSelectedTab.content, {})] }), toolbarMode === "compact" && bottomBarComponents.length > 0 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarComponents }) }) }))] }) }), jsx("div", { className: `${classes.resizer} ${alignment === "left" ? classes.resizerLeft : classes.resizerRight}`, style: { pointerEvents: `${collapsed ? "none" : "auto"}` }, onPointerDown: onResizerPointerDown })] })) }));
1510
+ }, [topPaneComponents, topSelectedTab, bottomPaneComponents, bottomSelectedTab, collapsed, width, resizing]);
1511
+ return [topPaneTabList, pane];
1473
1512
  }
1474
- function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWidth = 350, rightPaneDefaultWidth = 350, rightPaneMinWidth = 350, toolbarMode: toolbarMode = "full", } = {}) {
1513
+ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWidth = 350, rightPaneDefaultWidth = 350, rightPaneMinWidth = 350, toolbarMode = "full", sidePaneMode = "both", } = {}) {
1475
1514
  return {
1476
1515
  friendlyName: "MainView",
1477
1516
  produces: [ShellServiceIdentity, RootComponentServiceIdentity],
1478
1517
  factory: () => {
1479
1518
  const topBarComponentCollection = new ObservableCollection();
1480
1519
  const bottomBarComponentCollection = new ObservableCollection();
1481
- const leftPaneComponentCollection = new ObservableCollection();
1482
- const rightPaneComponentCollection = new ObservableCollection();
1520
+ const topLeftPaneComponentCollection = new ObservableCollection();
1521
+ const topRightPaneComponentCollection = new ObservableCollection();
1522
+ const bottomLeftPaneComponentCollection = new ObservableCollection();
1523
+ const bottomRightPaneComponentCollection = new ObservableCollection();
1483
1524
  const contentComponentCollection = new ObservableCollection();
1484
1525
  const rootComponent = () => {
1485
1526
  const classes = useStyles$9();
1486
- const topBarComponents = useOrderedObservableCollection(topBarComponentCollection);
1487
- const bottomBarComponents = useOrderedObservableCollection(bottomBarComponentCollection);
1488
- const topBarLeftComponents = useMemo(() => topBarComponents.filter((entry) => entry.horizontalLocation === "left"), [topBarComponents]);
1489
- const topBarRightComponents = useMemo(() => topBarComponents.filter((entry) => entry.horizontalLocation === "right"), [topBarComponents]);
1490
- const bottomBarLeftComponents = useMemo(() => bottomBarComponents.filter((entry) => entry.horizontalLocation === "left"), [bottomBarComponents]);
1491
- const bottomBarRightComponents = useMemo(() => bottomBarComponents.filter((entry) => entry.horizontalLocation === "right"), [bottomBarComponents]);
1492
- const leftPaneComponents = useOrderedObservableCollection(leftPaneComponentCollection);
1493
- const rightPaneComponents = useOrderedObservableCollection(rightPaneComponentCollection);
1527
+ const topBarItems = useOrderedObservableCollection(topBarComponentCollection);
1528
+ const bottomBarItems = useOrderedObservableCollection(bottomBarComponentCollection);
1529
+ const topLeftPaneItems = useOrderedObservableCollection(topLeftPaneComponentCollection);
1530
+ const topRightPaneItems = useOrderedObservableCollection(topRightPaneComponentCollection);
1531
+ const bottomLeftPaneItems = useOrderedObservableCollection(bottomLeftPaneComponentCollection);
1532
+ const bottomRightPaneItems = useOrderedObservableCollection(bottomRightPaneComponentCollection);
1533
+ const hasLeftPaneItems = topLeftPaneItems.length > 0 || bottomLeftPaneItems.length > 0;
1534
+ const hasRightPaneItems = topRightPaneItems.length > 0 || bottomRightPaneItems.length > 0;
1535
+ // If we are in compact toolbar mode, we may need to move toolbar items from the left to the right or vice versa,
1536
+ // depending on whether there are any side panes on that side.
1537
+ const coerceToolBarItemHorizontalLocation = (item) => {
1538
+ let location = item.horizontalLocation;
1539
+ // Coercion is only needed in compact toolbar mode since there might not be a left or right pane.
1540
+ if (toolbarMode === "compact") {
1541
+ if (location === "left" && !hasLeftPaneItems) {
1542
+ location = "right";
1543
+ }
1544
+ if (location === "right" && !hasRightPaneItems) {
1545
+ location = "left";
1546
+ }
1547
+ }
1548
+ return location;
1549
+ };
1550
+ const topBarLeftComponents = useMemo(() => topBarItems.filter((entry) => coerceToolBarItemHorizontalLocation(entry) === "left"), [topBarItems]);
1551
+ const topBarRightComponents = useMemo(() => topBarItems.filter((entry) => coerceToolBarItemHorizontalLocation(entry) === "right"), [topBarItems]);
1552
+ const bottomBarLeftComponents = useMemo(() => bottomBarItems.filter((entry) => coerceToolBarItemHorizontalLocation(entry) === "left"), [bottomBarItems]);
1553
+ const bottomBarRightComponents = useMemo(() => bottomBarItems.filter((entry) => coerceToolBarItemHorizontalLocation(entry) === "right"), [bottomBarItems]);
1494
1554
  const contentComponents = useOrderedObservableCollection(contentComponentCollection);
1495
- const [leftPaneTabList, leftPane] = usePane("left", leftPaneDefaultWidth, leftPaneMinWidth, leftPaneComponents, toolbarMode, topBarLeftComponents, bottomBarLeftComponents);
1496
- const [rightPaneTabList, rightPane] = usePane("right", rightPaneDefaultWidth, rightPaneMinWidth, rightPaneComponents, toolbarMode, topBarRightComponents, bottomBarRightComponents);
1497
- return (jsxs("div", { className: classes.mainView, children: [toolbarMode === "full" && (jsxs(Fragment, { children: [jsxs("div", { className: classes.barDiv, children: [leftPaneTabList, jsx(Toolbar, { location: "top", components: topBarComponents }), rightPaneTabList] }), jsx(Divider, { className: classes.barDivider })] })), jsxs("div", { className: classes.verticallyCentralContent, children: [leftPane, jsx("div", { className: classes.centralContent, children: contentComponents.map((entry) => (jsx(entry.component, {}, entry.key))) }), rightPane] }), toolbarMode === "full" && (jsxs(Fragment, { children: [jsx(Divider, { className: classes.barDivider }), jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarComponents }) })] }))] }));
1555
+ const [leftPaneTabList, leftPane] = usePane("left", leftPaneDefaultWidth, leftPaneMinWidth, topLeftPaneItems, bottomLeftPaneItems, toolbarMode, topBarLeftComponents, bottomBarLeftComponents);
1556
+ const [rightPaneTabList, rightPane] = usePane("right", rightPaneDefaultWidth, rightPaneMinWidth, topRightPaneItems, bottomRightPaneItems, toolbarMode, topBarRightComponents, bottomBarRightComponents);
1557
+ return (jsxs("div", { className: classes.mainView, children: [toolbarMode === "full" && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [leftPaneTabList, jsx(Toolbar, { location: "top", components: topBarItems }), rightPaneTabList] }) })), jsxs("div", { className: classes.verticallyCentralContent, children: [leftPane, jsx("div", { className: classes.centralContent, children: contentComponents.map((entry) => (jsx(entry.component, {}, entry.key))) }), rightPane] }), toolbarMode === "full" && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarItems }) }) }))] }));
1498
1558
  };
1499
1559
  rootComponent.displayName = "Shell Service Root";
1500
1560
  return {
@@ -1513,11 +1573,38 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
1513
1573
  if (!entry.content.displayName) {
1514
1574
  entry.content.displayName = `${entry.key} | ${entry.horizontalLocation} pane`;
1515
1575
  }
1516
- if (entry.horizontalLocation === "left") {
1517
- return leftPaneComponentCollection.add(entry);
1576
+ // When we are in "right" side pane mode, we need to coerce all left panes to be right panes.
1577
+ const coerceSidePaneLocation = (sidePane) => {
1578
+ let { horizontalLocation, verticalLocation } = sidePane;
1579
+ if (sidePaneMode === "right") {
1580
+ // All right panes go to right bottom.
1581
+ if (horizontalLocation === "right") {
1582
+ verticalLocation = "bottom";
1583
+ }
1584
+ // All left panes go to right top.
1585
+ if (horizontalLocation === "left") {
1586
+ horizontalLocation = "right";
1587
+ verticalLocation = "top";
1588
+ }
1589
+ }
1590
+ return { horizontalLocation, verticalLocation };
1591
+ };
1592
+ const { horizontalLocation, verticalLocation } = coerceSidePaneLocation(entry);
1593
+ if (horizontalLocation === "left") {
1594
+ if (verticalLocation === "top") {
1595
+ return topLeftPaneComponentCollection.add(entry);
1596
+ }
1597
+ else {
1598
+ return bottomLeftPaneComponentCollection.add(entry);
1599
+ }
1518
1600
  }
1519
1601
  else {
1520
- return rightPaneComponentCollection.add(entry);
1602
+ if (verticalLocation === "top") {
1603
+ return topRightPaneComponentCollection.add(entry);
1604
+ }
1605
+ else {
1606
+ return bottomRightPaneComponentCollection.add(entry);
1607
+ }
1521
1608
  }
1522
1609
  },
1523
1610
  addCentralContent: (entry) => contentComponentCollection.add(entry),
@@ -1543,6 +1630,7 @@ const PropertiesServiceDefinition = {
1543
1630
  title: "Properties",
1544
1631
  icon: DocumentTextRegular,
1545
1632
  horizontalLocation: "right",
1633
+ verticalLocation: "top",
1546
1634
  order: 100,
1547
1635
  suppressTeachingMoment: true,
1548
1636
  content: () => {
@@ -2046,6 +2134,7 @@ const SceneExplorerServiceDefinition = {
2046
2134
  title: "Scene Explorer",
2047
2135
  icon: CubeTreeRegular,
2048
2136
  horizontalLocation: "left",
2137
+ verticalLocation: "top",
2049
2138
  suppressTeachingMoment: true,
2050
2139
  content: () => {
2051
2140
  const sections = useOrderedObservableCollection(sectionsCollection);
@@ -2242,6 +2331,7 @@ const DebugServiceDefinition = {
2242
2331
  title: "Debug",
2243
2332
  icon: BugRegular,
2244
2333
  horizontalLocation: "right",
2334
+ verticalLocation: "top",
2245
2335
  order: 200,
2246
2336
  suppressTeachingMoment: true,
2247
2337
  content: () => {
@@ -2304,6 +2394,7 @@ const SettingsServiceDefinition = {
2304
2394
  title: "Settings",
2305
2395
  icon: SettingsRegular,
2306
2396
  horizontalLocation: "right",
2397
+ verticalLocation: "top",
2307
2398
  order: 500,
2308
2399
  suppressTeachingMoment: true,
2309
2400
  content: () => {
@@ -2574,6 +2665,7 @@ const StatsServiceDefinition = {
2574
2665
  title: "Statistics",
2575
2666
  icon: DataBarHorizontalRegular,
2576
2667
  horizontalLocation: "right",
2668
+ verticalLocation: "top",
2577
2669
  order: 300,
2578
2670
  suppressTeachingMoment: true,
2579
2671
  content: () => {
@@ -2662,6 +2754,7 @@ const ToolsServiceDefinition = {
2662
2754
  title: "Tools",
2663
2755
  icon: WrenchRegular,
2664
2756
  horizontalLocation: "right",
2757
+ verticalLocation: "top",
2665
2758
  order: 400,
2666
2759
  suppressTeachingMoment: true,
2667
2760
  content: () => {
@@ -2727,16 +2820,16 @@ class BuiltInsExtensionFeed {
2727
2820
  }
2728
2821
  async getExtensionModuleAsync(name) {
2729
2822
  if (name === CreationToolsExtensionMetadata.name) {
2730
- return await import('./creationToolsService-CISLGWl-.js');
2823
+ return await import('./creationToolsService-CX79OLiq.js');
2731
2824
  }
2732
2825
  else if (name === ExportToolsExtensionMetadata.name) {
2733
- return await import('./exportService-n5-mIhJj.js');
2826
+ return await import('./exportService-CzzSbQnD.js');
2734
2827
  }
2735
2828
  else if (name === CaptureToolsExtensionMetadata.name) {
2736
- return await import('./captureService-wvKpBv07.js');
2829
+ return await import('./captureService-4uUJw84S.js');
2737
2830
  }
2738
2831
  else if (name === ImportToolsExtensionMetadata.name) {
2739
- return await import('./importService-B-XgHjs9.js');
2832
+ return await import('./importService-BJFsjp8c.js');
2740
2833
  }
2741
2834
  return undefined;
2742
2835
  }
@@ -8124,6 +8217,7 @@ function _ShowInspector(scene, options) {
8124
8217
  isThemeable: options.isThemeable ?? true,
8125
8218
  extensionFeeds: options.isExtensible ? [new BuiltInsExtensionFeed()] : [],
8126
8219
  toolbarMode: "compact",
8220
+ sidePaneMode: options.embedMode ? "right" : "both",
8127
8221
  });
8128
8222
  disposeActions.push(() => modularTool.dispose());
8129
8223
  let disposed = false;
@@ -8401,4 +8495,4 @@ const Pane = (props) => {
8401
8495
  };
8402
8496
 
8403
8497
  export { Checkbox as $, MakePopoverTeachingMoment as A, ButtonLine as B, Collapse as C, DebugServiceIdentity as D, ExtensibleAccordion as E, FileUploadLine as F, GetPropertyDescriptor as G, IsPropertyReadonly as H, InterceptFunction as I, InterceptProperty as J, ConstructorFactory as K, LinkToEntityPropertyLine as L, MakeLazyComponent as M, NumberDropdownPropertyLine as N, SelectionServiceIdentity as O, Pane$1 as P, SelectionServiceDefinition as Q, SettingsContextIdentity as R, ShellServiceIdentity as S, ToolsServiceIdentity as T, IsInspectorVisible as U, ShowInspector as V, HideInspector as W, Inspector as X, AccordionSection as Y, Accordion as Z, Button as _, SceneContextIdentity as a, ColorPickerPopup as a0, InputHexField as a1, InputHsvField as a2, ComboBox as a3, DraggableLine as a4, Dropdown as a5, NumberDropdown as a6, StringDropdown as a7, FactorGradientComponent as a8, Color3GradientComponent as a9, Color4GradientComponent as aa, ColorStepGradientComponent as ab, InfoLabel as ac, List as ad, MessageBar as ae, PositionedPopover as af, SearchBar as ag, SearchBox as ah, SpinButton as ai, CalculatePrecision as aj, Switch as ak, SyncedSliderInput as al, Textarea as am, TextInput as an, ToggleButton as ao, FactorGradientList as ap, Color3GradientList as aq, Color4GradientList as ar, Pane as as, SwitchPropertyLine as b, SyncedSliderPropertyLine as c, PropertiesServiceIdentity as d, SceneExplorerServiceIdentity as e, SettingsServiceIdentity as f, StatsServiceIdentity as g, BoundProperty as h, TeachingMoment as i, useProperty as j, useVector3Property as k, useColor3Property as l, useColor4Property as m, useQuaternionProperty as n, MakePropertyHook as o, useInterceptObservable as p, useEventfulState as q, useObservableCollection as r, useOrderedObservableCollection as s, usePollingObservable as t, useObservableState as u, useResource as v, useAsyncResource as w, useAngleConverters as x, MakeTeachingMoment as y, MakeDialogTeachingMoment as z };
8404
- //# sourceMappingURL=index-Bt4ndVv5.js.map
8498
+ //# sourceMappingURL=index-B29Ify1o.js.map