@babylonjs/inspector 9.26.0 → 9.26.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/browser-CANgtOiM.js.map +1 -1
- package/lib/components/properties/boundProperty.d.ts +27 -0
- package/lib/components/properties/metadataProperties.d.ts +5 -1
- package/lib/contexts/propertyContext.d.ts +1 -1
- package/lib/{extensionsListService-DVpZa3gV.js → extensionsListService-GhHoWP21.js} +4 -4
- package/lib/{extensionsListService-DVpZa3gV.js.map → extensionsListService-GhHoWP21.js.map} +1 -1
- package/lib/gif-5DieAkSF.js.map +1 -1
- package/lib/{index-C5ggNiyY.js → index-DHNtmMzT.js} +282 -91
- package/lib/index-DHNtmMzT.js.map +1 -0
- package/lib/index.js +4 -4
- package/lib/lite/components/properties/cameraProperties.d.ts +11 -0
- package/lib/lite/components/properties/lightProperties.d.ts +33 -0
- package/lib/lite/components/properties/sceneNodeProperties.d.ts +8 -0
- package/lib/lite/{extensionsListService-xgITNk9y.js → extensionsListService-D1JivcAu.js} +2 -4
- package/lib/lite/{extensionsListService-xgITNk9y.js.map → extensionsListService-D1JivcAu.js.map} +1 -1
- package/lib/lite/{index-DmQN3QdU.js → index-D8vFySa7.js} +1616 -213
- package/lib/lite/index-D8vFySa7.js.map +1 -0
- package/lib/lite/index.js +2 -4
- package/lib/lite/index.js.map +1 -1
- package/lib/lite/renderingLayerUtils.d.ts +12 -0
- package/lib/lite/sceneEntityUtils.d.ts +19 -0
- package/lib/lite/services/panes/properties/cameraPropertiesService.d.ts +3 -0
- package/lib/lite/services/panes/properties/lightPropertiesService.d.ts +3 -0
- package/lib/lite/services/panes/properties/sceneNodePropertiesService.d.ts +3 -0
- package/lib/lite/services/panes/properties/shadowGeneratorPropertiesService.d.ts +4 -0
- package/lib/lite/services/panes/properties/spriteLayerPropertiesService.d.ts +4 -0
- package/lib/lite/services/panes/scene/cameraExplorerService.d.ts +7 -0
- package/lib/lite/services/panes/scene/lightExplorerService.d.ts +6 -0
- package/lib/lite/services/panes/scene/meshExplorerService.d.ts +4 -1
- package/lib/lite/services/panes/scene/renderingLayerExplorerService.d.ts +24 -0
- package/lib/lite/services/panes/scene/sceneSelectionUtils.d.ts +3 -0
- package/lib/lite/services/panes/scene/shadowGeneratorExplorerService.d.ts +6 -0
- package/lib/lite/services/panes/scene/spriteLayerExplorerService.d.ts +1 -0
- package/lib/lite/services/panes/scene/textLayerExplorerService.d.ts +1 -3
- package/lib/{quickCreateToolsService-0rVa_CjZ.js → quickCreateToolsService-COtk9VE9.js} +5 -5
- package/lib/{quickCreateToolsService-0rVa_CjZ.js.map → quickCreateToolsService-COtk9VE9.js.map} +1 -1
- package/lib/{reflectorService-pyDncbYA.js → reflectorService-fcsir8s0.js} +5 -5
- package/lib/{reflectorService-pyDncbYA.js.map → reflectorService-fcsir8s0.js.map} +1 -1
- package/package.json +1 -1
- package/lib/index-C5ggNiyY.js.map +0 -1
- package/lib/lite/index-DmQN3QdU.js.map +0 -1
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { Observable } from '@babylonjs/core/Misc/observable.js';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { createContext, forwardRef, useContext, useState, useCallback, Component, useEffect, useMemo, useReducer, useRef, Children, isValidElement, useLayoutEffect, useImperativeHandle, cloneElement, createElement, Suspense, lazy } from 'react';
|
|
4
|
-
import { tokens, makeStyles, Tooltip as Tooltip$1, Button as Button$1, Spinner, useFluent, Accordion as Accordion$1, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, MessageBar as MessageBar$1, MessageBarBody, AccordionItem, SearchBox as SearchBox$1, Portal, mergeClasses, createLightTheme, createDarkTheme, createDOMRenderer, FluentProvider, RendererProvider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, useId, useToastController, Toast, ToastTitle, Toaster, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, ToolbarRadioButton, MenuGroup, MenuGroupHeader, Link as Link$1, Caption1, Body1, ToggleButton as ToggleButton$1, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, Switch as Switch$1, Dropdown as Dropdown$1, Option, useMergedRefs, Input, Slider as Slider$1, MenuItemRadio, Dialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, List as List$1, ListItem, useComboboxFilter, Combobox, MessageBarTitle, Popover as Popover$1, PopoverTrigger, PopoverSurface, Field, Textarea as Textarea$1, PresenceBadge, treeItemLevelToken, typographyStyles, FlatTree, FlatTreeItem, MenuDivider, TreeItemLayout, MenuItemCheckbox } from '@fluentui/react-components';
|
|
5
|
-
import { ErrorCircleRegular, EyeFilled, EyeOffRegular, CheckmarkFilled, EditRegular, FilterRegular, PinFilled, PinRegular, ArrowCircleUpRegular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, SettingsRegular, ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, CopyRegular, DocumentTextRegular, ArrowBidirectionalUpDownFilled, ArrowClockwiseRegular, WeatherSunnyRegular, WeatherMoonRegular, InfoRegular, WarningRegular, CheckmarkCircleRegular, DeleteFilled, LinkDismissRegular, LinkEditRegular, AddRegular, DeleteRegular, ArrowUploadRegular, createFluentIcon, TextSortAscendingRegular, GlobeRegular, ArrowExpandAllRegular, ArrowCollapseAllRegular, ChevronRightRegular, CubeTreeRegular, EngineRegular, WindowRegular, TextFieldRegular, PersonSquareRegular, TextTRegular, ImageRegular } from '@fluentui/react-icons';
|
|
4
|
+
import { tokens, makeStyles, Tooltip as Tooltip$1, Button as Button$1, Spinner, useFluent, Accordion as Accordion$1, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, MessageBar as MessageBar$1, MessageBarBody, AccordionItem, SearchBox as SearchBox$1, Portal, mergeClasses, createLightTheme, createDarkTheme, createDOMRenderer, FluentProvider, RendererProvider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, useId, useToastController, Toast, ToastTitle, Toaster, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, ToolbarRadioButton, MenuGroup, MenuGroupHeader, Link as Link$1, Caption1, Body1, ToggleButton as ToggleButton$1, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, Switch as Switch$1, Dropdown as Dropdown$1, Option, useMergedRefs, Input, Slider as Slider$1, MenuItemRadio, Dialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, List as List$1, ListItem, useComboboxFilter, Combobox, MessageBarTitle, Popover as Popover$1, PopoverTrigger, PopoverSurface, Field, Textarea as Textarea$1, PresenceBadge, treeItemLevelToken, typographyStyles, FlatTree, FlatTreeItem, MenuDivider, TreeItemLayout, MenuItemCheckbox, ColorPicker, ColorArea, ColorSlider, AlphaSlider, ColorSwatch } from '@fluentui/react-components';
|
|
5
|
+
import { ErrorCircleRegular, EyeFilled, EyeOffRegular, CheckmarkFilled, EditRegular, FilterRegular, PinFilled, PinRegular, ArrowCircleUpRegular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, SettingsRegular, ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, CopyRegular, DocumentTextRegular, ArrowBidirectionalUpDownFilled, ArrowClockwiseRegular, WeatherSunnyRegular, WeatherMoonRegular, InfoRegular, WarningRegular, CheckmarkCircleRegular, DeleteFilled, LinkDismissRegular, LinkEditRegular, AddRegular, DeleteRegular, ArrowUploadRegular, createFluentIcon, TextSortAscendingRegular, GlobeRegular, ArrowExpandAllRegular, ArrowCollapseAllRegular, ChevronRightRegular, CubeTreeRegular, EngineRegular, WindowRegular, TextFieldRegular, PersonSquareRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, CameraRegular, LightbulbRegular, EyeRegular, MyLocationRegular, LayerDiagonalPersonRegular, TextTRegular, ImageRegular } from '@fluentui/react-icons';
|
|
6
6
|
import { DataStorage } from '@babylonjs/core/Misc/dataStorage.js';
|
|
7
|
-
import { Logger } from '@babylonjs/core/Misc/logger.js';
|
|
8
7
|
import { AsyncLock } from '@babylonjs/core/Misc/asyncLock.js';
|
|
9
8
|
import { Deferred } from '@babylonjs/core/Misc/deferred.js';
|
|
10
9
|
import { useResizeHandle } from '@fluentui-contrib/react-resize-handle';
|
|
11
10
|
import { Collapse as Collapse$1, Fade } from '@fluentui/react-motion-components-preview';
|
|
12
|
-
import {
|
|
13
|
-
import { Clamp } from '@babylonjs/core/Maths/math.scalar.functions.js';
|
|
11
|
+
import { Logger } from '@babylonjs/core/Misc/logger.js';
|
|
14
12
|
import { createRoot } from 'react-dom/client';
|
|
15
|
-
import { getRenderingContexts, getRenderingContextKind, getMaterialFamily, getMaterialTextures, resizeEngine } from '@babylonjs/lite';
|
|
13
|
+
import { getRenderingContexts, getRenderingContextKind, quatToEulerXYZ, eulerToQuat, getMaterialFamily, setSubtreeVisible, spriteBlendOpaque, spriteBlendOneOne, spriteBlendMultiply, spriteBlendAdditive, spriteBlendPremultiplied, spriteBlendAlpha, removeFromScene, getMaterialTextures, setParent, resizeEngine } from '@babylonjs/lite';
|
|
16
14
|
import { VirtualizerScrollView } from '@fluentui-contrib/react-virtualizer';
|
|
17
15
|
import { UniqueIdGenerator } from '@babylonjs/core/Misc/uniqueIdGenerator.js';
|
|
18
16
|
import { Color3, Color4 } from '@babylonjs/core/Maths/math.color.js';
|
|
@@ -263,7 +261,7 @@ const Button = forwardRef((props, ref) => {
|
|
|
263
261
|
});
|
|
264
262
|
Button.displayName = "Button";
|
|
265
263
|
|
|
266
|
-
const useStyles$
|
|
264
|
+
const useStyles$n = makeStyles({
|
|
267
265
|
root: {
|
|
268
266
|
display: "flex",
|
|
269
267
|
flexDirection: "column",
|
|
@@ -347,7 +345,7 @@ class ErrorBoundary extends Component {
|
|
|
347
345
|
}
|
|
348
346
|
}
|
|
349
347
|
function ErrorFallback({ error, onRetry }) {
|
|
350
|
-
const styles = useStyles$
|
|
348
|
+
const styles = useStyles$n();
|
|
351
349
|
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 })] }));
|
|
352
350
|
}
|
|
353
351
|
|
|
@@ -416,9 +414,32 @@ function useKeyState(key, options) {
|
|
|
416
414
|
// Storage Helpers
|
|
417
415
|
// ============================================================================
|
|
418
416
|
const STORAGE_KEY_ROOT = "Babylon/Accordion";
|
|
417
|
+
const InMemoryStorage = new Map();
|
|
418
|
+
// eslint-disable-next-line no-console
|
|
419
|
+
const Warn = (message) => globalThis.console?.warn?.(message);
|
|
420
|
+
const ReadStoredString = (key) => {
|
|
421
|
+
try {
|
|
422
|
+
return globalThis.localStorage?.getItem(key) ?? InMemoryStorage.get(key) ?? "";
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
return InMemoryStorage.get(key) ?? "";
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
const WriteStoredString = (key, value) => {
|
|
429
|
+
try {
|
|
430
|
+
if (globalThis.localStorage) {
|
|
431
|
+
globalThis.localStorage.setItem(key, value);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// Fall through to in-memory persistence when localStorage is unavailable.
|
|
437
|
+
}
|
|
438
|
+
InMemoryStorage.set(key, value);
|
|
439
|
+
};
|
|
419
440
|
const ReadFromStorage = (path, initial) => {
|
|
420
441
|
try {
|
|
421
|
-
const stored =
|
|
442
|
+
const stored = ReadStoredString(`${STORAGE_KEY_ROOT}/${path}`);
|
|
422
443
|
return stored ? JSON.parse(stored) : initial;
|
|
423
444
|
}
|
|
424
445
|
catch {
|
|
@@ -426,7 +447,7 @@ const ReadFromStorage = (path, initial) => {
|
|
|
426
447
|
}
|
|
427
448
|
};
|
|
428
449
|
const WriteToStorage = (path, data) => {
|
|
429
|
-
|
|
450
|
+
WriteStoredString(`${STORAGE_KEY_ROOT}/${path}`, JSON.stringify(data));
|
|
430
451
|
};
|
|
431
452
|
// ============================================================================
|
|
432
453
|
// Reducer
|
|
@@ -584,7 +605,7 @@ function useAccordionSectionItemState(props) {
|
|
|
584
605
|
const prevItemIdRef = useRef(itemId);
|
|
585
606
|
useEffect(() => {
|
|
586
607
|
if (accordionCtx && prevItemIdRef.current !== itemId) {
|
|
587
|
-
|
|
608
|
+
Warn(`Accordion: The uniqueId "${itemId}" in section "${sectionCtx?.sectionId}" has changed from "${prevItemIdRef.current}". ` +
|
|
588
609
|
`Each item must have a unique, stable ID for pin/hide persistence to work correctly.`);
|
|
589
610
|
}
|
|
590
611
|
prevItemIdRef.current = itemId;
|
|
@@ -596,7 +617,7 @@ function useAccordionSectionItemState(props) {
|
|
|
596
617
|
}
|
|
597
618
|
const { registeredItemIds } = accordionCtx;
|
|
598
619
|
if (registeredItemIds.has(itemUniqueId)) {
|
|
599
|
-
|
|
620
|
+
Warn(`Accordion: Duplicate uniqueId "${itemId}" detected in section "${sectionCtx?.sectionId}". ` +
|
|
600
621
|
`Each item must have a unique ID within its section for pin/hide persistence to work correctly.`);
|
|
601
622
|
}
|
|
602
623
|
registeredItemIds.set(itemUniqueId, itemLabel ?? itemId);
|
|
@@ -669,7 +690,7 @@ function useIsSectionEmpty(sectionId) {
|
|
|
669
690
|
return hasItems;
|
|
670
691
|
}
|
|
671
692
|
|
|
672
|
-
const useStyles$
|
|
693
|
+
const useStyles$m = makeStyles({
|
|
673
694
|
accordion: {
|
|
674
695
|
display: "flex",
|
|
675
696
|
flexDirection: "column",
|
|
@@ -761,7 +782,7 @@ const useStyles$k = makeStyles({
|
|
|
761
782
|
*/
|
|
762
783
|
const AccordionMenuBar = () => {
|
|
763
784
|
AccordionMenuBar.displayName = "AccordionMenuBar";
|
|
764
|
-
const classes = useStyles$
|
|
785
|
+
const classes = useStyles$m();
|
|
765
786
|
const accordionCtx = useContext(AccordionContext);
|
|
766
787
|
if (!accordionCtx) {
|
|
767
788
|
return null;
|
|
@@ -785,7 +806,7 @@ const AccordionMenuBar = () => {
|
|
|
785
806
|
const AccordionSectionBlock = (props) => {
|
|
786
807
|
AccordionSectionBlock.displayName = "AccordionSectionBlock";
|
|
787
808
|
const { children, sectionId } = props;
|
|
788
|
-
const classes = useStyles$
|
|
809
|
+
const classes = useStyles$m();
|
|
789
810
|
const accordionCtx = useContext(AccordionContext);
|
|
790
811
|
const { context: sectionContext, isEmpty } = useAccordionSectionBlockContext(props);
|
|
791
812
|
if (accordionCtx) {
|
|
@@ -805,7 +826,7 @@ const AccordionSectionBlock = (props) => {
|
|
|
805
826
|
const AccordionSectionItem = (props) => {
|
|
806
827
|
AccordionSectionItem.displayName = "AccordionSectionItem";
|
|
807
828
|
const { children, staticItem } = props;
|
|
808
|
-
const classes = useStyles$
|
|
829
|
+
const classes = useStyles$m();
|
|
809
830
|
const accordionCtx = useContext(AccordionContext);
|
|
810
831
|
const itemState = useAccordionSectionItemState(props);
|
|
811
832
|
const [ctrlMode, setCtrlMode] = useState(false);
|
|
@@ -845,7 +866,7 @@ const AccordionSectionItem = (props) => {
|
|
|
845
866
|
*/
|
|
846
867
|
const AccordionPinnedContainer = () => {
|
|
847
868
|
AccordionPinnedContainer.displayName = "AccordionPinnedContainer";
|
|
848
|
-
const classes = useStyles$
|
|
869
|
+
const classes = useStyles$m();
|
|
849
870
|
const accordionCtx = useContext(AccordionContext);
|
|
850
871
|
return (jsx("div", { ref: accordionCtx?.pinnedContainerRef, className: classes.pinnedContainer, children: jsx(MessageBar$1, { className: classes.pinnedContainerEmpty, children: jsx(MessageBarBody, { children: "No pinned items" }) }) }));
|
|
851
872
|
};
|
|
@@ -856,7 +877,7 @@ const AccordionPinnedContainer = () => {
|
|
|
856
877
|
*/
|
|
857
878
|
const AccordionSearchBox = () => {
|
|
858
879
|
AccordionSearchBox.displayName = "AccordionSearchBox";
|
|
859
|
-
const classes = useStyles$
|
|
880
|
+
const classes = useStyles$m();
|
|
860
881
|
const accordionCtx = useContext(AccordionContext);
|
|
861
882
|
if (!accordionCtx?.features.search) {
|
|
862
883
|
return null;
|
|
@@ -872,7 +893,7 @@ const AccordionSearchBox = () => {
|
|
|
872
893
|
*/
|
|
873
894
|
const AccordionSection = (props) => {
|
|
874
895
|
AccordionSection.displayName = "AccordionSection";
|
|
875
|
-
const classes = useStyles$
|
|
896
|
+
const classes = useStyles$m();
|
|
876
897
|
return jsx("div", { className: classes.panelDiv, children: props.children });
|
|
877
898
|
};
|
|
878
899
|
const StringAccordion = Accordion$1;
|
|
@@ -880,7 +901,7 @@ const Accordion = forwardRef((props, ref) => {
|
|
|
880
901
|
Accordion.displayName = "Accordion";
|
|
881
902
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
882
903
|
const { children, highlightSections, uniqueId, enablePinnedItems, enableHiddenItems, enableSearchItems, ...rest } = props;
|
|
883
|
-
const classes = useStyles$
|
|
904
|
+
const classes = useStyles$m();
|
|
884
905
|
const { size } = useContext(ToolContext);
|
|
885
906
|
const accordionCtx = useAccordionContext(props);
|
|
886
907
|
const hasPinning = accordionCtx?.features.pinning ?? false;
|
|
@@ -1106,7 +1127,7 @@ const UXContextProvider = (props) => {
|
|
|
1106
1127
|
function AsReadonlyArray(array) {
|
|
1107
1128
|
return array;
|
|
1108
1129
|
}
|
|
1109
|
-
const useStyles$
|
|
1130
|
+
const useStyles$l = makeStyles({
|
|
1110
1131
|
rootDiv: {
|
|
1111
1132
|
flex: 1,
|
|
1112
1133
|
overflow: "hidden",
|
|
@@ -1121,7 +1142,7 @@ const useStyles$j = makeStyles({
|
|
|
1121
1142
|
* @returns The extensible accordion component.
|
|
1122
1143
|
*/
|
|
1123
1144
|
function ExtensibleAccordion(props) {
|
|
1124
|
-
const classes = useStyles$
|
|
1145
|
+
const classes = useStyles$l();
|
|
1125
1146
|
const { children, sections, sectionContent, context, sectionsRef, ...rest } = props;
|
|
1126
1147
|
const defaultSections = useMemo(() => {
|
|
1127
1148
|
const defaultSections = [];
|
|
@@ -1246,7 +1267,7 @@ function ExtensibleAccordion(props) {
|
|
|
1246
1267
|
})] }) })) }));
|
|
1247
1268
|
}
|
|
1248
1269
|
|
|
1249
|
-
const useStyles$
|
|
1270
|
+
const useStyles$k = makeStyles({
|
|
1250
1271
|
paneRootDiv: {
|
|
1251
1272
|
display: "flex",
|
|
1252
1273
|
flex: 1,
|
|
@@ -1259,7 +1280,7 @@ const useStyles$i = makeStyles({
|
|
|
1259
1280
|
*/
|
|
1260
1281
|
const SidePaneContainer = forwardRef((props, ref) => {
|
|
1261
1282
|
const { className, ...rest } = props;
|
|
1262
|
-
const classes = useStyles$
|
|
1283
|
+
const classes = useStyles$k();
|
|
1263
1284
|
return (jsx("div", { className: mergeClasses(classes.paneRootDiv, className), ref: ref, ...rest, children: props.children }));
|
|
1264
1285
|
});
|
|
1265
1286
|
|
|
@@ -1530,7 +1551,7 @@ function useTheme(invert = false) {
|
|
|
1530
1551
|
}
|
|
1531
1552
|
|
|
1532
1553
|
// Fluent doesn't apply styling to scrollbars by default, so provide our own reasonable default.
|
|
1533
|
-
const useStyles$
|
|
1554
|
+
const useStyles$j = makeStyles({
|
|
1534
1555
|
root: {
|
|
1535
1556
|
scrollbarColor: `${tokens.colorNeutralForeground3} ${tokens.colorTransparentBackground}`,
|
|
1536
1557
|
},
|
|
@@ -1551,7 +1572,7 @@ const Theme = (props) => {
|
|
|
1551
1572
|
// break any UI within the portal. Therefore, default to false.
|
|
1552
1573
|
const { invert = false, applyStylesToPortals = false, className, targetDocument: explicitTargetDocument, ...rest } = props;
|
|
1553
1574
|
const theme = useTheme(invert);
|
|
1554
|
-
const classes = useStyles$
|
|
1575
|
+
const classes = useStyles$j();
|
|
1555
1576
|
// Resolve the target document from the explicit prop or fall back to the ambient Fluent context.
|
|
1556
1577
|
// This makes nested <Theme> components automatically inherit cross-window targeting from a
|
|
1557
1578
|
// top-level <Theme targetDocument={popupDocument}> wrapper.
|
|
@@ -1573,7 +1594,7 @@ const Theme = (props) => {
|
|
|
1573
1594
|
return fluent;
|
|
1574
1595
|
};
|
|
1575
1596
|
|
|
1576
|
-
const useStyles$
|
|
1597
|
+
const useStyles$i = makeStyles({
|
|
1577
1598
|
extensionTeachingPopover: {
|
|
1578
1599
|
maxWidth: "320px",
|
|
1579
1600
|
},
|
|
@@ -1584,7 +1605,7 @@ const useStyles$g = makeStyles({
|
|
|
1584
1605
|
* @returns The teaching moment popover.
|
|
1585
1606
|
*/
|
|
1586
1607
|
const TeachingMoment = ({ shouldDisplay, positioningRef, onOpenChange, title, description }) => {
|
|
1587
|
-
const classes = useStyles$
|
|
1608
|
+
const classes = useStyles$i();
|
|
1588
1609
|
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 })] }) }));
|
|
1589
1610
|
};
|
|
1590
1611
|
|
|
@@ -1953,6 +1974,10 @@ const UseDegreesSettingDescriptor = {
|
|
|
1953
1974
|
key: "UseDegrees",
|
|
1954
1975
|
defaultValue: true,
|
|
1955
1976
|
};
|
|
1977
|
+
const UseEulerSettingDescriptor = {
|
|
1978
|
+
key: "UseEuler",
|
|
1979
|
+
defaultValue: true,
|
|
1980
|
+
};
|
|
1956
1981
|
|
|
1957
1982
|
const RadiansToDegrees = 180 / Math.PI;
|
|
1958
1983
|
function WrapAngle(angle) {
|
|
@@ -2416,7 +2441,7 @@ const RootComponentServiceIdentity = Symbol("RootComponent");
|
|
|
2416
2441
|
* The unique identity symbol for the shell service.
|
|
2417
2442
|
*/
|
|
2418
2443
|
const ShellServiceIdentity = Symbol("ShellService");
|
|
2419
|
-
const useStyles$
|
|
2444
|
+
const useStyles$h = makeStyles({
|
|
2420
2445
|
mainView: {
|
|
2421
2446
|
flex: 1,
|
|
2422
2447
|
display: "flex",
|
|
@@ -2638,14 +2663,14 @@ const DockMenu = (props) => {
|
|
|
2638
2663
|
};
|
|
2639
2664
|
const PaneHeader = (props) => {
|
|
2640
2665
|
const { id, title, dockOptions } = props;
|
|
2641
|
-
const classes = useStyles$
|
|
2666
|
+
const classes = useStyles$h();
|
|
2642
2667
|
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, {}) }) })] }));
|
|
2643
2668
|
};
|
|
2644
2669
|
// 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.
|
|
2645
2670
|
const ToolbarItem = (props) => {
|
|
2646
2671
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
2647
2672
|
const { verticalLocation, horizontalLocation, id, component: Component, displayName } = props;
|
|
2648
|
-
const classes = useStyles$
|
|
2673
|
+
const classes = useStyles$h();
|
|
2649
2674
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Bar/${verticalLocation}/${horizontalLocation}/${displayName ?? id}`), [displayName, id]);
|
|
2650
2675
|
const teachingMoment = useTeachingMoment(props.teachingMoment === false);
|
|
2651
2676
|
const title = typeof props.teachingMoment === "object" ? props.teachingMoment.title : (displayName ?? id);
|
|
@@ -2655,7 +2680,7 @@ const ToolbarItem = (props) => {
|
|
|
2655
2680
|
// TODO: Handle overflow, possibly via https://react.fluentui.dev/?path=/docs/components-overflow--docs with priority.
|
|
2656
2681
|
// This component just renders a toolbar with left aligned toolbar items on the left and right aligned toolbar items on the right.
|
|
2657
2682
|
const Toolbar = ({ location, components }) => {
|
|
2658
|
-
const classes = useStyles$
|
|
2683
|
+
const classes = useStyles$h();
|
|
2659
2684
|
const leftComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "left"), [components]);
|
|
2660
2685
|
const rightComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "right"), [components]);
|
|
2661
2686
|
return (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))) })] }));
|
|
@@ -2665,7 +2690,7 @@ const SidePaneTab = (props) => {
|
|
|
2665
2690
|
const { location, id, isSelected, isFirst, isLast, dockOptions,
|
|
2666
2691
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
2667
2692
|
icon: Icon, title, } = props;
|
|
2668
|
-
const classes = useStyles$
|
|
2693
|
+
const classes = useStyles$h();
|
|
2669
2694
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Pane/${location}/${title ?? id}`), [title, id]);
|
|
2670
2695
|
const teachingMoment = useTeachingMoment(props.teachingMoment === false);
|
|
2671
2696
|
const tabClass = mergeClasses(classes.tab, isSelected ? classes.selectedTab : classes.unselectedTab, isFirst ? classes.firstTab : undefined, isLast ? classes.lastTab : undefined);
|
|
@@ -2677,7 +2702,7 @@ const SidePaneTab = (props) => {
|
|
|
2677
2702
|
// In "compact" mode, the tab list is integrated into the pane itself.
|
|
2678
2703
|
// In "full" mode, the returned tab list is later injected into the toolbar.
|
|
2679
2704
|
function usePane(location, defaultWidth, minWidth, sidePanes, onSelectSidePane, dockOperations, toolbarMode, topBarItems, bottomBarItems, initialCollapsed) {
|
|
2680
|
-
const classes = useStyles$
|
|
2705
|
+
const classes = useStyles$h();
|
|
2681
2706
|
const [topSelectedTab, setTopSelectedTab] = useState();
|
|
2682
2707
|
const [bottomSelectedTab, setBottomSelectedTab] = useState();
|
|
2683
2708
|
const [collapsed, setCollapsed] = useState(initialCollapsed);
|
|
@@ -2919,7 +2944,7 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
|
|
|
2919
2944
|
expand: () => onCollapseChanged.notifyObservers({ location: "right", collapsed: false }),
|
|
2920
2945
|
};
|
|
2921
2946
|
const rootComponent = () => {
|
|
2922
|
-
const classes = useStyles$
|
|
2947
|
+
const classes = useStyles$h();
|
|
2923
2948
|
const [sidePaneDockOverrides, setSidePaneDockOverrides] = useSetting(SidePaneDockOverridesSettingDescriptor);
|
|
2924
2949
|
// This function returns a promise that resolves after the dock change takes effect so that
|
|
2925
2950
|
// we can then select the re-docked pane.
|
|
@@ -3202,7 +3227,11 @@ function copyCommandToClipboard(strCommand) {
|
|
|
3202
3227
|
// babylonNamespace is either "" (ES6) or "BABYLON."
|
|
3203
3228
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3204
3229
|
function getClassNameWithNamespace(obj) {
|
|
3205
|
-
|
|
3230
|
+
if ((typeof obj !== "object" && typeof obj !== "function") || obj === null) {
|
|
3231
|
+
return { className: "Unknown", babylonNamespace: "" };
|
|
3232
|
+
}
|
|
3233
|
+
const candidate = obj;
|
|
3234
|
+
let className = candidate.getClassName?.() ?? candidate.constructor?.name ?? "Unknown";
|
|
3206
3235
|
if (className.includes("BABYLON.")) {
|
|
3207
3236
|
className = className.split("BABYLON.")[1];
|
|
3208
3237
|
}
|
|
@@ -3217,7 +3246,7 @@ const Link = forwardRef((props, ref) => {
|
|
|
3217
3246
|
});
|
|
3218
3247
|
Link.displayName = "Link";
|
|
3219
3248
|
|
|
3220
|
-
const useStyles$
|
|
3249
|
+
const useStyles$g = makeStyles({
|
|
3221
3250
|
button: {
|
|
3222
3251
|
display: "flex",
|
|
3223
3252
|
alignItems: "center",
|
|
@@ -3235,7 +3264,7 @@ const ToggleButton = (props) => {
|
|
|
3235
3264
|
ToggleButton.displayName = "ToggleButton";
|
|
3236
3265
|
const { value, onChange, title, appearance = "subtle", ariaLabel } = props;
|
|
3237
3266
|
const { size } = useContext(ToolContext);
|
|
3238
|
-
const classes = useStyles$
|
|
3267
|
+
const classes = useStyles$g();
|
|
3239
3268
|
const [checked, setChecked] = useState(value);
|
|
3240
3269
|
const toggle = useCallback(() => {
|
|
3241
3270
|
setChecked((prevChecked) => {
|
|
@@ -3558,13 +3587,13 @@ function useImpulse() {
|
|
|
3558
3587
|
return [value, pulse];
|
|
3559
3588
|
}
|
|
3560
3589
|
|
|
3561
|
-
const useStyles$
|
|
3590
|
+
const useStyles$f = makeStyles({
|
|
3562
3591
|
placeholderDiv: {
|
|
3563
3592
|
padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalM}`,
|
|
3564
3593
|
},
|
|
3565
3594
|
});
|
|
3566
3595
|
const PropertiesPane = (props) => {
|
|
3567
|
-
const classes = useStyles$
|
|
3596
|
+
const classes = useStyles$f();
|
|
3568
3597
|
const entity = props.context;
|
|
3569
3598
|
return entity != null ? (jsx(ExtensibleAccordion, { ...props })) : (jsx("div", { className: classes.placeholderDiv, children: jsx(Body1Strong, { italic: true, children: "No entity selected." }) }));
|
|
3570
3599
|
};
|
|
@@ -3694,7 +3723,7 @@ const Dropdown = (props) => {
|
|
|
3694
3723
|
const NumberDropdown = Dropdown;
|
|
3695
3724
|
const StringDropdown = Dropdown;
|
|
3696
3725
|
|
|
3697
|
-
const useStyles$
|
|
3726
|
+
const useStyles$e = makeStyles({
|
|
3698
3727
|
dropdown: {
|
|
3699
3728
|
...UniformWidthStyling,
|
|
3700
3729
|
},
|
|
@@ -3706,7 +3735,7 @@ const useStyles$c = makeStyles({
|
|
|
3706
3735
|
*/
|
|
3707
3736
|
const DropdownPropertyLine = forwardRef((props, ref) => {
|
|
3708
3737
|
DropdownPropertyLine.displayName = "DropdownPropertyLine";
|
|
3709
|
-
const classes = useStyles$
|
|
3738
|
+
const classes = useStyles$e();
|
|
3710
3739
|
return (jsx(PropertyLine, { ...props, ref: ref, children: jsx(Dropdown, { ...props, className: classes.dropdown }) }));
|
|
3711
3740
|
});
|
|
3712
3741
|
/**
|
|
@@ -3753,7 +3782,7 @@ function EvaluateExpression(rawValue) {
|
|
|
3753
3782
|
return NaN;
|
|
3754
3783
|
}
|
|
3755
3784
|
}
|
|
3756
|
-
const useStyles$
|
|
3785
|
+
const useStyles$d = makeStyles({
|
|
3757
3786
|
icon: {
|
|
3758
3787
|
"&:hover": {
|
|
3759
3788
|
color: tokens.colorBrandForeground1,
|
|
@@ -3767,7 +3796,7 @@ const useStyles$b = makeStyles({
|
|
|
3767
3796
|
const SpinButton = forwardRef((props, ref) => {
|
|
3768
3797
|
SpinButton.displayName = "SpinButton2";
|
|
3769
3798
|
const inputClasses = useInputStyles$1();
|
|
3770
|
-
const classes = useStyles$
|
|
3799
|
+
const classes = useStyles$d();
|
|
3771
3800
|
const { size } = useContext(ToolContext);
|
|
3772
3801
|
const { min, max } = props;
|
|
3773
3802
|
const baseStep = props.step ?? 1;
|
|
@@ -3815,7 +3844,7 @@ const SpinButton = forwardRef((props, ref) => {
|
|
|
3815
3844
|
return !invalid;
|
|
3816
3845
|
}, [min, max, props.validator, props.forceInt]);
|
|
3817
3846
|
// Constrain a value to the valid range by clamping to [min, max].
|
|
3818
|
-
const constrainValue = useCallback((v) =>
|
|
3847
|
+
const constrainValue = useCallback((v) => Math.min(max ?? Infinity, Math.max(min ?? -Infinity, v)), [min, max]);
|
|
3819
3848
|
const tryCommitValue = useCallback((currVal) => {
|
|
3820
3849
|
if (validateValue(currVal) && currVal !== lastCommittedValue.current) {
|
|
3821
3850
|
lastCommittedValue.current = currVal;
|
|
@@ -4083,7 +4112,7 @@ const SyncedSliderInput = (props) => {
|
|
|
4083
4112
|
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 })] })] }));
|
|
4084
4113
|
};
|
|
4085
4114
|
|
|
4086
|
-
const useStyles$
|
|
4115
|
+
const useStyles$c = makeStyles({
|
|
4087
4116
|
uniformWidth: {
|
|
4088
4117
|
...UniformWidthStyling,
|
|
4089
4118
|
},
|
|
@@ -4095,7 +4124,7 @@ const useStyles$a = makeStyles({
|
|
|
4095
4124
|
*/
|
|
4096
4125
|
const SyncedSliderPropertyLine = forwardRef((props, ref) => {
|
|
4097
4126
|
SyncedSliderPropertyLine.displayName = "SyncedSliderPropertyLine";
|
|
4098
|
-
const classes = useStyles$
|
|
4127
|
+
const classes = useStyles$c();
|
|
4099
4128
|
const { label, description, ...sliderProps } = props;
|
|
4100
4129
|
return (jsx(PropertyLine, { ref: ref, ...props, children: jsx(SyncedSliderInput, { ...sliderProps, className: mergeClasses(classes.uniformWidth, props.className) }) }));
|
|
4101
4130
|
});
|
|
@@ -4896,7 +4925,7 @@ function useExtensionManager() {
|
|
|
4896
4925
|
return useContext(ExtensionManagerContext)?.extensionManager;
|
|
4897
4926
|
}
|
|
4898
4927
|
|
|
4899
|
-
const useStyles$
|
|
4928
|
+
const useStyles$b = makeStyles({
|
|
4900
4929
|
themeButton: {
|
|
4901
4930
|
margin: 0,
|
|
4902
4931
|
},
|
|
@@ -4915,7 +4944,7 @@ const ThemeSelectorServiceDefinition = {
|
|
|
4915
4944
|
teachingMoment: false,
|
|
4916
4945
|
order: -300,
|
|
4917
4946
|
component: () => {
|
|
4918
|
-
const classes = useStyles$
|
|
4947
|
+
const classes = useStyles$b();
|
|
4919
4948
|
const { isDarkMode, themeMode, setThemeMode } = useThemeMode();
|
|
4920
4949
|
const onSelectedThemeChange = useCallback((e, data) => {
|
|
4921
4950
|
setThemeMode(data.checkedItems.includes("System") ? "system" : data.checkedItems[0].toLocaleLowerCase());
|
|
@@ -4932,7 +4961,7 @@ const ThemeSelectorServiceDefinition = {
|
|
|
4932
4961
|
},
|
|
4933
4962
|
};
|
|
4934
4963
|
|
|
4935
|
-
const useStyles$
|
|
4964
|
+
const useStyles$a = makeStyles({
|
|
4936
4965
|
app: {
|
|
4937
4966
|
colorScheme: "light dark",
|
|
4938
4967
|
flexGrow: 1,
|
|
@@ -4996,7 +5025,7 @@ function MakeModularTool(options) {
|
|
|
4996
5025
|
// This deferred resolves once the React effect cleanup (which disposes the ServiceContainer) is complete.
|
|
4997
5026
|
const disposeDeferred = new Deferred();
|
|
4998
5027
|
const modularToolRootComponent = () => {
|
|
4999
|
-
const classes = useStyles$
|
|
5028
|
+
const classes = useStyles$a();
|
|
5000
5029
|
const [requiredExtensions, setRequiredExtensions] = useState();
|
|
5001
5030
|
const [requiredExtensionsDeferred, setRequiredExtensionsDeferred] = useState();
|
|
5002
5031
|
const [extensionInstallError, setExtensionInstallError] = useState();
|
|
@@ -5108,7 +5137,7 @@ function MakeModularTool(options) {
|
|
|
5108
5137
|
}
|
|
5109
5138
|
// Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
|
|
5110
5139
|
if (extensionFeeds.length > 0) {
|
|
5111
|
-
const { ExtensionListServiceDefinition } = await import('./extensionsListService-
|
|
5140
|
+
const { ExtensionListServiceDefinition } = await import('./extensionsListService-D1JivcAu.js');
|
|
5112
5141
|
serviceContainer.addService(ExtensionListServiceDefinition);
|
|
5113
5142
|
}
|
|
5114
5143
|
// Register all external services (that make up a unique tool).
|
|
@@ -5508,7 +5537,7 @@ const Checkbox = (props) => {
|
|
|
5508
5537
|
return jsx(Checkbox$1, { checked: checked, onChange: onChange, indicator: { className: classes.indicator } });
|
|
5509
5538
|
};
|
|
5510
5539
|
|
|
5511
|
-
const useStyles$
|
|
5540
|
+
const useStyles$9 = makeStyles({
|
|
5512
5541
|
root: {
|
|
5513
5542
|
display: "grid",
|
|
5514
5543
|
gridTemplateRows: "repeat(1fr)",
|
|
@@ -5538,7 +5567,7 @@ const useStyles$7 = makeStyles({
|
|
|
5538
5567
|
const ComboBox = forwardRef((props, ref) => {
|
|
5539
5568
|
ComboBox.displayName = "ComboBox";
|
|
5540
5569
|
const comboId = useId();
|
|
5541
|
-
const styles = useStyles$
|
|
5570
|
+
const styles = useStyles$9();
|
|
5542
5571
|
const { size } = useContext(ToolContext);
|
|
5543
5572
|
// Find the label for the current value
|
|
5544
5573
|
const getLabel = (value) => props.options.find((opt) => opt.value === value)?.label ?? "";
|
|
@@ -5615,7 +5644,7 @@ const DraggableLine = (props) => {
|
|
|
5615
5644
|
}, children: [props.label, props.onDelete && jsx(DeleteFilled, { className: classes.icon, onClick: props.onDelete })] }));
|
|
5616
5645
|
};
|
|
5617
5646
|
|
|
5618
|
-
const useStyles$
|
|
5647
|
+
const useStyles$8 = makeStyles({
|
|
5619
5648
|
linkDiv: {
|
|
5620
5649
|
display: "flex",
|
|
5621
5650
|
flexDirection: "row",
|
|
@@ -5640,7 +5669,7 @@ const useStyles$6 = makeStyles({
|
|
|
5640
5669
|
function EntitySelector(props) {
|
|
5641
5670
|
const { value, onLink, getEntities, getName, filter, defaultValue } = props;
|
|
5642
5671
|
const onChange = props.onChange;
|
|
5643
|
-
const classes = useStyles$
|
|
5672
|
+
const classes = useStyles$8();
|
|
5644
5673
|
const comboBoxRef = useRef(null);
|
|
5645
5674
|
// Build options with uniqueId as key
|
|
5646
5675
|
const options = useMemo(() => {
|
|
@@ -5767,7 +5796,7 @@ const MessageBar = (props) => {
|
|
|
5767
5796
|
return (jsx(AccordionSectionItem, { uniqueId: title ?? message, staticItem: staticItem ?? true, children: jsx("div", { className: classes.container, children: jsx(MessageBar$1, { intent: intent, layout: "multiline", children: jsxs(MessageBarBody, { children: [title && jsx(MessageBarTitle, { children: title }), message, docLink && (jsxs(Fragment, { children: [" - ", jsx(Link, { url: docLink, value: "Learn More" })] }))] }) }) }) }));
|
|
5768
5797
|
};
|
|
5769
5798
|
|
|
5770
|
-
const useStyles$
|
|
5799
|
+
const useStyles$7 = makeStyles({
|
|
5771
5800
|
surface: {
|
|
5772
5801
|
maxWidth: "400px",
|
|
5773
5802
|
},
|
|
@@ -5782,7 +5811,7 @@ const useStyles$5 = makeStyles({
|
|
|
5782
5811
|
const Popover = forwardRef((props, ref) => {
|
|
5783
5812
|
const { children, open: controlledOpen, onOpenChange, positioning, surfaceClassName } = props;
|
|
5784
5813
|
const [internalOpen, setInternalOpen] = useState(false);
|
|
5785
|
-
const classes = useStyles$
|
|
5814
|
+
const classes = useStyles$7();
|
|
5786
5815
|
const isControlled = controlledOpen !== undefined;
|
|
5787
5816
|
const popoverOpen = isControlled ? controlledOpen : internalOpen;
|
|
5788
5817
|
const handleOpenChange = (_, data) => {
|
|
@@ -5828,14 +5857,14 @@ const PositionedPopover = (props) => {
|
|
|
5828
5857
|
} }) }), jsx(PopoverSurface, { children: props.children })] }));
|
|
5829
5858
|
};
|
|
5830
5859
|
|
|
5831
|
-
const useStyles$
|
|
5860
|
+
const useStyles$6 = makeStyles({
|
|
5832
5861
|
search: {
|
|
5833
5862
|
minWidth: "50px",
|
|
5834
5863
|
},
|
|
5835
5864
|
});
|
|
5836
5865
|
const SearchBar = forwardRef((props, ref) => {
|
|
5837
5866
|
SearchBar.displayName = "SearchBar";
|
|
5838
|
-
const classes = useStyles$
|
|
5867
|
+
const classes = useStyles$6();
|
|
5839
5868
|
const onChange = (_, data) => {
|
|
5840
5869
|
props.onChange(data.value);
|
|
5841
5870
|
};
|
|
@@ -6051,7 +6080,7 @@ const FileUploadLine = ({ onClick, label, accept, ...buttonProps }) => {
|
|
|
6051
6080
|
return (jsx(LineContainer, { uniqueId: `${label}_upload`, label: label, children: jsx(UploadButton, { onUpload: onClick, accept: accept, label: label, ...buttonProps }) }));
|
|
6052
6081
|
};
|
|
6053
6082
|
|
|
6054
|
-
const useStyles$
|
|
6083
|
+
const useStyles$5 = makeStyles({
|
|
6055
6084
|
rootDiv: {
|
|
6056
6085
|
flex: 1,
|
|
6057
6086
|
overflow: "hidden",
|
|
@@ -6071,7 +6100,7 @@ const useStyles$3 = makeStyles({
|
|
|
6071
6100
|
},
|
|
6072
6101
|
});
|
|
6073
6102
|
const Pane = (props) => {
|
|
6074
|
-
const classes = useStyles$
|
|
6103
|
+
const classes = useStyles$5();
|
|
6075
6104
|
return (jsxs("div", { className: classes.rootDiv, children: [jsxs("div", { className: classes.header, children: [props.icon ? (jsx(props.icon, { className: classes.icon })) : (jsx("img", { className: classes.icon, id: "logo", src: "https://www.babylonjs.com/Assets/logo-babylonjs-social-twitter.png" })), jsx(Body1Strong, { id: "title", children: props.title })] }), props.children] }));
|
|
6076
6105
|
};
|
|
6077
6106
|
|
|
@@ -6155,7 +6184,7 @@ const HexPropertyLine = (props) => {
|
|
|
6155
6184
|
return (jsx(PropertyLine, { ...props, children: jsx(TextInput, { ...props, validator: MaskValidatorFn, value: hexVal, onChange: onStrValChange, validateOnlyOnBlur: true }) }));
|
|
6156
6185
|
};
|
|
6157
6186
|
|
|
6158
|
-
const useStyles$
|
|
6187
|
+
const useStyles$4 = makeStyles({
|
|
6159
6188
|
uniformWidth: {
|
|
6160
6189
|
...UniformWidthStyling,
|
|
6161
6190
|
},
|
|
@@ -6167,7 +6196,7 @@ const useStyles$2 = makeStyles({
|
|
|
6167
6196
|
*/
|
|
6168
6197
|
const TextInputPropertyLine = (props) => {
|
|
6169
6198
|
TextInputPropertyLine.displayName = "TextInputPropertyLine";
|
|
6170
|
-
const classes = useStyles$
|
|
6199
|
+
const classes = useStyles$4();
|
|
6171
6200
|
return (jsx(PropertyLine, { ...props, children: jsx(TextInput, { ...props, className: mergeClasses(classes.uniformWidth, props.className) }) }));
|
|
6172
6201
|
};
|
|
6173
6202
|
/**
|
|
@@ -6178,7 +6207,7 @@ const TextInputPropertyLine = (props) => {
|
|
|
6178
6207
|
*/
|
|
6179
6208
|
const NumberInputPropertyLine = (props) => {
|
|
6180
6209
|
NumberInputPropertyLine.displayName = "NumberInputPropertyLine";
|
|
6181
|
-
const classes = useStyles$
|
|
6210
|
+
const classes = useStyles$4();
|
|
6182
6211
|
return (jsx(PropertyLine, { ...props, children: jsx(SpinButton, { ...props, className: mergeClasses(classes.uniformWidth, props.className) }) }));
|
|
6183
6212
|
};
|
|
6184
6213
|
|
|
@@ -6192,14 +6221,14 @@ const LinkPropertyLine = (props) => {
|
|
|
6192
6221
|
return (jsx(PropertyLine, { ...props, children: jsx(Link, { ...props }) }));
|
|
6193
6222
|
};
|
|
6194
6223
|
|
|
6195
|
-
const useStyles$
|
|
6224
|
+
const useStyles$3 = makeStyles({
|
|
6196
6225
|
uniformWidth: {
|
|
6197
6226
|
...UniformWidthStyling,
|
|
6198
6227
|
},
|
|
6199
6228
|
});
|
|
6200
6229
|
const SpinButtonPropertyLine = (props) => {
|
|
6201
6230
|
SpinButtonPropertyLine.displayName = "SpinButtonPropertyLine";
|
|
6202
|
-
const classes = useStyles$
|
|
6231
|
+
const classes = useStyles$3();
|
|
6203
6232
|
return (jsx(PropertyLine, { ...props, children: jsx(SpinButton, { ...props, className: mergeClasses(classes.uniformWidth, props.className) }) }));
|
|
6204
6233
|
};
|
|
6205
6234
|
|
|
@@ -6838,7 +6867,7 @@ function useExplorerDragDrop(options) {
|
|
|
6838
6867
|
};
|
|
6839
6868
|
}
|
|
6840
6869
|
|
|
6841
|
-
const useStyles = makeStyles({
|
|
6870
|
+
const useStyles$2 = makeStyles({
|
|
6842
6871
|
rootDiv: {
|
|
6843
6872
|
flex: 1,
|
|
6844
6873
|
overflow: "hidden",
|
|
@@ -6978,7 +7007,7 @@ function useBranchIconInteraction(enabled) {
|
|
|
6978
7007
|
}
|
|
6979
7008
|
const ExplorerTreeItemLayout = (props) => {
|
|
6980
7009
|
const { isBranch, isOpen, icon, showChevron, select, ...layoutProps } = props;
|
|
6981
|
-
const classes = useStyles();
|
|
7010
|
+
const classes = useStyles$2();
|
|
6982
7011
|
const { dir } = useFluent();
|
|
6983
7012
|
const hasIcon = !!icon;
|
|
6984
7013
|
const chevron = (jsx("div", { className: mergeClasses(classes.leadingChevron, isOpen ? classes.leadingChevronOpen : dir === "rtl" && classes.leadingChevronClosedRtl), children: jsx(ChevronRightRegular, {}) }));
|
|
@@ -7114,7 +7143,7 @@ function useNodeDisplayInfo(node) {
|
|
|
7114
7143
|
}
|
|
7115
7144
|
const RootTreeItem = (props) => {
|
|
7116
7145
|
const { node, isSelected, isOpen, select, isFiltering, expandAll, collapseAll } = props;
|
|
7117
|
-
const classes = useStyles();
|
|
7146
|
+
const classes = useStyles$2();
|
|
7118
7147
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
7119
7148
|
const treeItemLayoutClass = mergeClasses(classes.rootTreeItemLayout, compactMode ? classes.treeItemLayoutCompact : undefined);
|
|
7120
7149
|
const displayInfo = useNodeDisplayInfo(node);
|
|
@@ -7141,7 +7170,7 @@ const RootTreeItem = (props) => {
|
|
|
7141
7170
|
};
|
|
7142
7171
|
const GroupTreeItem = (props) => {
|
|
7143
7172
|
const { node, isFiltering, commandProviders, expandAll, collapseAll, isSelected, isOpen, select, isDropTarget, ...dropProps } = props;
|
|
7144
|
-
const classes = useStyles();
|
|
7173
|
+
const classes = useStyles$2();
|
|
7145
7174
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
7146
7175
|
const displayInfo = useNodeDisplayInfo(node);
|
|
7147
7176
|
const name = useObservableState(() => displayInfo.name, displayInfo.onChange);
|
|
@@ -7165,7 +7194,7 @@ const GroupTreeItem = (props) => {
|
|
|
7165
7194
|
};
|
|
7166
7195
|
const ItemTreeItem = (props) => {
|
|
7167
7196
|
const { node, entity, isSelected, select, isFiltering, commandProviders, expandAll, collapseAll, isDragging, isDropTarget, isOpen, ...dragProps } = props;
|
|
7168
|
-
const classes = useStyles();
|
|
7197
|
+
const classes = useStyles$2();
|
|
7169
7198
|
const [compactMode] = useSetting(CompactModeSettingDescriptor);
|
|
7170
7199
|
const hasChildren = node.children.length > 0;
|
|
7171
7200
|
const isBranch = !isFiltering && hasChildren;
|
|
@@ -7287,7 +7316,7 @@ const ItemTreeItem = (props) => {
|
|
|
7287
7316
|
* @returns The explorer tree component.
|
|
7288
7317
|
*/
|
|
7289
7318
|
const Explorer = (props) => {
|
|
7290
|
-
const classes = useStyles();
|
|
7319
|
+
const classes = useStyles$2();
|
|
7291
7320
|
const { getNodes, itemCommandProviders, groupCommandProviders, selectedEntity = null, ariaLabel = "Scene Explorer Tree" } = props;
|
|
7292
7321
|
const [treeVersion, setTreeVersion] = useState(0);
|
|
7293
7322
|
const tree = useMemo(() => BuildExplorerTree(getNodes()), [getNodes, treeVersion]);
|
|
@@ -7944,11 +7973,11 @@ function GenerateCopyString(value) {
|
|
|
7944
7973
|
}
|
|
7945
7974
|
// Color3, Color4 — HEX is a direct 0-1→0-255 conversion of the stored values (property-space)
|
|
7946
7975
|
if (className === "Color3") {
|
|
7947
|
-
const hexString = ColorToHex(obj.r, obj.g, obj.b, 1);
|
|
7976
|
+
const hexString = ColorToHex$1(obj.r, obj.g, obj.b, 1);
|
|
7948
7977
|
return `new ${babylonNamespace}Color3(${obj.r}, ${obj.g}, ${obj.b}) // (HEX: ${hexString})`;
|
|
7949
7978
|
}
|
|
7950
7979
|
if (className === "Color4") {
|
|
7951
|
-
const hexString = ColorToHex(obj.r, obj.g, obj.b, obj.a);
|
|
7980
|
+
const hexString = ColorToHex$1(obj.r, obj.g, obj.b, obj.a);
|
|
7952
7981
|
return `new ${babylonNamespace}Color4(${obj.r}, ${obj.g}, ${obj.b}, ${obj.a}) // (HEX: ${hexString})`;
|
|
7953
7982
|
}
|
|
7954
7983
|
// Matrix - output as array
|
|
@@ -7981,7 +8010,7 @@ function GenerateCopyString(value) {
|
|
|
7981
8010
|
* @param a - Alpha component (0-1)
|
|
7982
8011
|
* @returns Hex string in format #RRGGBBAA
|
|
7983
8012
|
*/
|
|
7984
|
-
function ColorToHex(r, g, b, a) {
|
|
8013
|
+
function ColorToHex$1(r, g, b, a) {
|
|
7985
8014
|
const toByte = (c) => Math.round(Math.min(255, Math.max(0, c * 255)));
|
|
7986
8015
|
const rHex = toByte(r).toString(16).padStart(2, "0").toUpperCase();
|
|
7987
8016
|
const gHex = toByte(g).toString(16).padStart(2, "0").toUpperCase();
|
|
@@ -8080,6 +8109,45 @@ function ComputedProperty(props) {
|
|
|
8080
8109
|
const value = useWatchedValue(target, getValue);
|
|
8081
8110
|
return jsx(Component, { ...{ ...rest, value } });
|
|
8082
8111
|
}
|
|
8112
|
+
/**
|
|
8113
|
+
* Renders an editable property-line component for a value derived from a target.
|
|
8114
|
+
*
|
|
8115
|
+
* This is useful for method-backed values, readonly object references, or values whose UI
|
|
8116
|
+
* representation differs from their stored representation. The getter follows the Preferred
|
|
8117
|
+
* Watch Mode, while the setter owns the runtime-specific write-back.
|
|
8118
|
+
* @param props The target, derived getter, write-back function, and property-line component props.
|
|
8119
|
+
* @returns The editable derived property-line component.
|
|
8120
|
+
*/
|
|
8121
|
+
function DerivedProperty(props) {
|
|
8122
|
+
const {
|
|
8123
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
8124
|
+
component: Component, target, getValue, setValue, propertyPath, getPropertyOwner, propertyKey, ...rest } = props;
|
|
8125
|
+
const value = useWatchedValue(target, getValue);
|
|
8126
|
+
const notifyPropertyChanged = usePropertyChangedNotifier();
|
|
8127
|
+
const getStoredProperty = () => {
|
|
8128
|
+
if (!getPropertyOwner || propertyKey === undefined) {
|
|
8129
|
+
return undefined;
|
|
8130
|
+
}
|
|
8131
|
+
const propertyTarget = getPropertyOwner(target);
|
|
8132
|
+
return {
|
|
8133
|
+
propertyTarget,
|
|
8134
|
+
value: Reflect.get(propertyTarget, propertyKey),
|
|
8135
|
+
};
|
|
8136
|
+
};
|
|
8137
|
+
return (jsx(Component, { ...{
|
|
8138
|
+
...(propertyPath ? { onCopy: () => GetOnCopyString(getStoredProperty()?.value, propertyPath) } : {}),
|
|
8139
|
+
...rest,
|
|
8140
|
+
value,
|
|
8141
|
+
onChange: (changedValue) => {
|
|
8142
|
+
const oldStoredProperty = getStoredProperty();
|
|
8143
|
+
setValue(target, changedValue);
|
|
8144
|
+
const newStoredProperty = getStoredProperty();
|
|
8145
|
+
if (newStoredProperty && oldStoredProperty && propertyKey !== undefined) {
|
|
8146
|
+
notifyPropertyChanged(newStoredProperty.propertyTarget, propertyKey, oldStoredProperty.value, newStoredProperty.value);
|
|
8147
|
+
}
|
|
8148
|
+
},
|
|
8149
|
+
} }));
|
|
8150
|
+
}
|
|
8083
8151
|
function GetOnCopyString(value, propertyPath) {
|
|
8084
8152
|
const valueStr = GenerateCopyString(value);
|
|
8085
8153
|
return `globalThis.debugNode.${propertyPath} = ${valueStr};`;
|
|
@@ -8158,85 +8226,713 @@ const EnginePropertiesServiceDefinition = {
|
|
|
8158
8226
|
},
|
|
8159
8227
|
};
|
|
8160
8228
|
|
|
8161
|
-
function
|
|
8162
|
-
return
|
|
8229
|
+
function GetSceneContexts(engine) {
|
|
8230
|
+
return engine.surfaces.flatMap((surface) => getRenderingContexts(surface).filter((context) => getRenderingContextKind(context) === "scene"));
|
|
8163
8231
|
}
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8232
|
+
function IsSceneNode(entity) {
|
|
8233
|
+
return (typeof entity === "object" &&
|
|
8234
|
+
entity !== null &&
|
|
8235
|
+
"name" in entity &&
|
|
8236
|
+
"children" in entity &&
|
|
8237
|
+
"position" in entity &&
|
|
8238
|
+
"rotationQuaternion" in entity &&
|
|
8239
|
+
"scaling" in entity &&
|
|
8240
|
+
"parent" in entity);
|
|
8241
|
+
}
|
|
8242
|
+
function IsMesh(entity) {
|
|
8243
|
+
return IsSceneNode(entity) && "material" in entity && "receiveShadows" in entity;
|
|
8244
|
+
}
|
|
8245
|
+
function IsCamera(entity) {
|
|
8246
|
+
return typeof entity === "object" && entity !== null && "fov" in entity && "nearPlane" in entity && "farPlane" in entity && "children" in entity && "worldMatrix" in entity;
|
|
8247
|
+
}
|
|
8248
|
+
function IsArcRotateCamera(entity) {
|
|
8249
|
+
return IsCamera(entity) && "alpha" in entity && "beta" in entity && "radius" in entity && "target" in entity;
|
|
8250
|
+
}
|
|
8251
|
+
function IsFreeCamera(entity) {
|
|
8252
|
+
return IsCamera(entity) && "position" in entity && "target" in entity && "speed" in entity;
|
|
8253
|
+
}
|
|
8254
|
+
function IsLight(entity) {
|
|
8255
|
+
return typeof entity === "object" && entity !== null && "lightType" in entity && "children" in entity && "parent" in entity && "worldMatrix" in entity;
|
|
8256
|
+
}
|
|
8257
|
+
function IsDirectionalLight(entity) {
|
|
8258
|
+
return IsLight(entity) && entity.lightType === "directional";
|
|
8259
|
+
}
|
|
8260
|
+
function IsPointLight(entity) {
|
|
8261
|
+
return IsLight(entity) && entity.lightType === "point";
|
|
8262
|
+
}
|
|
8263
|
+
function IsSpotLight(entity) {
|
|
8264
|
+
return IsLight(entity) && entity.lightType === "spot";
|
|
8265
|
+
}
|
|
8266
|
+
function IsHemisphericLight(entity) {
|
|
8267
|
+
return IsLight(entity) && entity.lightType === "hemispheric";
|
|
8268
|
+
}
|
|
8269
|
+
function GetSceneNodes(scene) {
|
|
8270
|
+
const nodes = new Set();
|
|
8271
|
+
const addNode = (node) => {
|
|
8272
|
+
if (nodes.has(node)) {
|
|
8273
|
+
return;
|
|
8274
|
+
}
|
|
8275
|
+
nodes.add(node);
|
|
8276
|
+
for (const child of node.children) {
|
|
8277
|
+
addNode(child);
|
|
8278
|
+
}
|
|
8279
|
+
};
|
|
8280
|
+
for (const mesh of scene.meshes) {
|
|
8281
|
+
let root = mesh;
|
|
8282
|
+
while (IsSceneNode(root.parent)) {
|
|
8283
|
+
root = root.parent;
|
|
8284
|
+
}
|
|
8285
|
+
addNode(root);
|
|
8286
|
+
}
|
|
8287
|
+
return [...nodes];
|
|
8288
|
+
}
|
|
8289
|
+
function GetSceneNodeRoots(scene) {
|
|
8290
|
+
const nodes = GetSceneNodes(scene);
|
|
8291
|
+
const nodeSet = new Set(nodes);
|
|
8292
|
+
return nodes.filter((node) => !IsSceneNode(node.parent) || !nodeSet.has(node.parent));
|
|
8293
|
+
}
|
|
8294
|
+
function IsSceneNodeDescendantOf(node, ancestor) {
|
|
8295
|
+
let parent = node.parent;
|
|
8296
|
+
while (typeof parent === "object" && parent !== null) {
|
|
8297
|
+
if (parent === ancestor) {
|
|
8298
|
+
return true;
|
|
8299
|
+
}
|
|
8300
|
+
if (!IsSceneNode(parent)) {
|
|
8301
|
+
return false;
|
|
8302
|
+
}
|
|
8303
|
+
parent = parent.parent;
|
|
8304
|
+
}
|
|
8305
|
+
return false;
|
|
8306
|
+
}
|
|
8307
|
+
function SetVector3Value(target, value) {
|
|
8308
|
+
const x = "x" in value ? value.x : value[0];
|
|
8309
|
+
const y = "x" in value ? value.y : value[1];
|
|
8310
|
+
const z = "x" in value ? value.z : value[2];
|
|
8311
|
+
const observableTarget = target;
|
|
8312
|
+
if (typeof observableTarget.set === "function") {
|
|
8313
|
+
observableTarget.set(x, y, z);
|
|
8314
|
+
}
|
|
8315
|
+
else {
|
|
8316
|
+
target.x = x;
|
|
8317
|
+
target.y = y;
|
|
8318
|
+
target.z = z;
|
|
8319
|
+
}
|
|
8320
|
+
}
|
|
8321
|
+
function SetQuaternionValue(target, value) {
|
|
8322
|
+
const x = "x" in value ? value.x : value[0];
|
|
8323
|
+
const y = "x" in value ? value.y : value[1];
|
|
8324
|
+
const z = "x" in value ? value.z : value[2];
|
|
8325
|
+
const w = "x" in value ? value.w : value[3];
|
|
8326
|
+
const observableTarget = target;
|
|
8327
|
+
if (typeof observableTarget.set === "function") {
|
|
8328
|
+
observableTarget.set(x, y, z, w);
|
|
8329
|
+
}
|
|
8330
|
+
else {
|
|
8331
|
+
target.x = x;
|
|
8332
|
+
target.y = y;
|
|
8333
|
+
target.z = z;
|
|
8334
|
+
target.w = w;
|
|
8335
|
+
}
|
|
8336
|
+
}
|
|
8337
|
+
function GetLightDisplayName(light, index) {
|
|
8338
|
+
const typeName = `${light.lightType.charAt(0).toUpperCase()}${light.lightType.slice(1)}`;
|
|
8339
|
+
return `${typeName} Light ${index + 1}`;
|
|
8340
|
+
}
|
|
8341
|
+
function GetShadowGeneratorDisplayName(scene, shadowGenerator) {
|
|
8342
|
+
const lightIndex = scene.lights.findIndex((light) => light.shadowGenerator === shadowGenerator);
|
|
8343
|
+
return lightIndex === -1 ? `Shadow Generator ${scene.shadowGenerators.indexOf(shadowGenerator) + 1}` : `${GetLightDisplayName(scene.lights[lightIndex], lightIndex)} Shadows`;
|
|
8344
|
+
}
|
|
8345
|
+
|
|
8346
|
+
/**
|
|
8347
|
+
* Runtime-neutral controlled editor for two-, three-, and four-component numeric values.
|
|
8348
|
+
* @param props The value, change callback, component adapter, and property-line presentation.
|
|
8349
|
+
* @returns The tensor property line.
|
|
8350
|
+
*/
|
|
8351
|
+
const ControlledTensorPropertyLine = (props) => {
|
|
8352
|
+
const { adapter, min, max, unit, step, precision, valueConverter } = props;
|
|
8353
|
+
const converted = (value) => (valueConverter ? valueConverter.from(value) : value);
|
|
8354
|
+
const formatted = (value) => converted(value).toFixed(precision ?? (step !== undefined ? Math.max(0, CalculatePrecision(step)) : 2));
|
|
8355
|
+
const [value, setValue] = useState(props.value);
|
|
8356
|
+
useEffect(() => {
|
|
8357
|
+
setValue(props.value);
|
|
8358
|
+
}, [props.value, props.expandedContent]);
|
|
8359
|
+
const onComponentChange = (componentValue, component) => {
|
|
8360
|
+
const storedValue = valueConverter ? valueConverter.to(componentValue) : componentValue;
|
|
8361
|
+
const newValue = adapter.withComponent(value, component, storedValue);
|
|
8362
|
+
setValue(newValue);
|
|
8363
|
+
props.onChange(newValue);
|
|
8364
|
+
};
|
|
8365
|
+
const summary = adapter.components.map((component) => formatted(adapter.getComponent(props.value, component))).join(", ");
|
|
8366
|
+
return (jsx(PropertyLine, { ...props, expandedContent: jsxs(Fragment, { children: [props.expandedContent, jsx(TensorSliders, { value: value, adapter: adapter, min: min, max: max, unit: unit, step: step, precision: precision, converted: converted, onChange: onComponentChange })] }), children: jsx(Body1, { children: `[${summary}]` }) }));
|
|
8167
8367
|
};
|
|
8168
|
-
const
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8368
|
+
const TensorSliders = (props) => {
|
|
8369
|
+
const { value, adapter, min, max, unit, step, precision, converted, onChange } = props;
|
|
8370
|
+
return (jsx(Fragment, { children: adapter.components.map((component) => (jsx(NumberInputPropertyLine, { label: component.toUpperCase(), value: converted(adapter.getComponent(value, component)), min: min, max: max, onChange: (componentValue) => onChange(componentValue, component), unit: unit, step: step, precision: precision }, component))) }));
|
|
8371
|
+
};
|
|
8372
|
+
const RadiansToDegreesConverter = {
|
|
8373
|
+
from: (value) => (value * 180) / Math.PI,
|
|
8374
|
+
to: (value) => (value * Math.PI) / 180,
|
|
8375
|
+
};
|
|
8376
|
+
/**
|
|
8377
|
+
* Runtime-neutral controlled quaternion editor with optional Euler presentation.
|
|
8378
|
+
* @param props The quaternion value, runtime conversion adapter, and display options.
|
|
8379
|
+
* @returns The quaternion or Euler property line.
|
|
8380
|
+
*/
|
|
8381
|
+
const ControlledQuaternionPropertyLine = (props) => {
|
|
8382
|
+
const { adapter, useEuler, useDegrees, ...rest } = props;
|
|
8383
|
+
const [quaternion, setQuaternion] = useState(props.value);
|
|
8384
|
+
useEffect(() => {
|
|
8385
|
+
setQuaternion(props.value);
|
|
8386
|
+
}, [props.value]);
|
|
8387
|
+
const onQuaternionChange = (value) => {
|
|
8388
|
+
setQuaternion(value);
|
|
8389
|
+
props.onChange(value);
|
|
8390
|
+
};
|
|
8391
|
+
if (useEuler) {
|
|
8392
|
+
const quaternionSummary = adapter.quaternion.components.map((component) => adapter.quaternion.getComponent(quaternion, component).toFixed(4)).join(", ");
|
|
8393
|
+
return (jsx(ControlledTensorPropertyLine, { ...rest, nullable: false, ignoreNullable: false, value: adapter.toEuler(quaternion), adapter: adapter.euler, valueConverter: useDegrees ? RadiansToDegreesConverter : undefined, onChange: (value) => onQuaternionChange(adapter.fromEuler(value, quaternion)), unit: useDegrees ? "°" : "rad", step: useDegrees ? 1 : 0.01, precision: useDegrees ? 1 : 2, expandedContent: jsx(TextPropertyLine, { label: "Quaternion", value: `[${quaternionSummary}]` }) }));
|
|
8394
|
+
}
|
|
8395
|
+
return (jsx(ControlledTensorPropertyLine, { ...rest, nullable: false, value: quaternion, adapter: adapter.quaternion, onChange: onQuaternionChange, unit: useDegrees ? "°" : "rad", step: useDegrees ? 1 : 0.01, precision: useDegrees ? 1 : 2 }));
|
|
8181
8396
|
};
|
|
8182
8397
|
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextInputPropertyLine, label: "Name", target: mesh, propertyKey: "name" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Receive Shadows", target: mesh, propertyKey: "receiveShadows" })] }));
|
|
8398
|
+
const ComponentIndices = {
|
|
8399
|
+
x: 0,
|
|
8400
|
+
y: 1,
|
|
8401
|
+
z: 2,
|
|
8402
|
+
w: 3,
|
|
8189
8403
|
};
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8404
|
+
function IsNumberTuple(value) {
|
|
8405
|
+
return Array.isArray(value);
|
|
8406
|
+
}
|
|
8407
|
+
function GetComponent(value, component) {
|
|
8408
|
+
if (IsNumberTuple(value)) {
|
|
8409
|
+
return value[ComponentIndices[component]];
|
|
8410
|
+
}
|
|
8411
|
+
switch (component) {
|
|
8412
|
+
case "x":
|
|
8413
|
+
return value.x;
|
|
8414
|
+
case "y":
|
|
8415
|
+
return value.y;
|
|
8416
|
+
case "z":
|
|
8417
|
+
return "z" in value ? value.z : 0;
|
|
8418
|
+
case "w":
|
|
8419
|
+
return "w" in value ? value.w : 0;
|
|
8420
|
+
}
|
|
8421
|
+
}
|
|
8422
|
+
const Vector3Adapter = {
|
|
8423
|
+
components: ["x", "y", "z"],
|
|
8424
|
+
getComponent: GetComponent,
|
|
8425
|
+
withComponent: (value, component, componentValue) => IsNumberTuple(value)
|
|
8426
|
+
? [component === "x" ? componentValue : value[0], component === "y" ? componentValue : value[1], component === "z" ? componentValue : value[2]]
|
|
8427
|
+
: { ...value, [component]: componentValue },
|
|
8428
|
+
};
|
|
8429
|
+
const QuaternionTensorAdapter = {
|
|
8430
|
+
components: ["x", "y", "z", "w"],
|
|
8431
|
+
getComponent: GetComponent,
|
|
8432
|
+
withComponent: (value, component, componentValue) => IsNumberTuple(value)
|
|
8433
|
+
? [
|
|
8434
|
+
component === "x" ? componentValue : value[0],
|
|
8435
|
+
component === "y" ? componentValue : value[1],
|
|
8436
|
+
component === "z" ? componentValue : value[2],
|
|
8437
|
+
component === "w" ? componentValue : value[3],
|
|
8438
|
+
]
|
|
8439
|
+
: { ...value, [component]: componentValue },
|
|
8440
|
+
};
|
|
8441
|
+
/**
|
|
8442
|
+
* Converts a Lite Euler value to a quaternion while preserving tuple versus structural representation.
|
|
8443
|
+
* @param value The Euler value in radians.
|
|
8444
|
+
* @param source The source quaternion whose representation should be preserved.
|
|
8445
|
+
* @returns The converted quaternion.
|
|
8446
|
+
*/
|
|
8447
|
+
function CreateQuaternionFromEuler(value, source) {
|
|
8448
|
+
const [x, y, z] = "x" in value ? [value.x, value.y, value.z] : value;
|
|
8449
|
+
const quaternion = eulerToQuat(x, y, z);
|
|
8450
|
+
return "x" in source ? { x: quaternion[0], y: quaternion[1], z: quaternion[2], w: quaternion[3] } : quaternion;
|
|
8451
|
+
}
|
|
8452
|
+
const QuaternionAdapter = {
|
|
8453
|
+
quaternion: QuaternionTensorAdapter,
|
|
8454
|
+
euler: Vector3Adapter,
|
|
8455
|
+
fromEuler: CreateQuaternionFromEuler,
|
|
8456
|
+
toEuler: (value) => {
|
|
8457
|
+
const [x, y, z, w] = "x" in value ? [value.x, value.y, value.z, value.w] : value;
|
|
8458
|
+
return quatToEulerXYZ(x, y, z, w);
|
|
8459
|
+
},
|
|
8203
8460
|
};
|
|
8461
|
+
const Vector3PropertyLine = (props) => jsx(ControlledTensorPropertyLine, { ...props, adapter: Vector3Adapter });
|
|
8462
|
+
const QuaternionPropertyLine = (props) => jsx(ControlledQuaternionPropertyLine, { ...props, adapter: QuaternionAdapter });
|
|
8204
8463
|
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
const GetAnimationGroupCount = (scene) => scene.animationGroups.length;
|
|
8208
|
-
const GetShadowGeneratorCount = (scene) => scene.shadowGenerators.length;
|
|
8209
|
-
const GetTextLayerCount = (renderer) => renderer.layers.length;
|
|
8210
|
-
const GetSpriteLayerCount = (renderer) => renderer.layers.length;
|
|
8211
|
-
function IsRegisteredRenderingContext(engine, entity) {
|
|
8212
|
-
return typeof entity === "object" && entity !== null && engine.surfaces.some((surface) => getRenderingContexts(surface).includes(entity));
|
|
8464
|
+
function GetPosition$2(camera) {
|
|
8465
|
+
return [camera.position.x, camera.position.y, camera.position.z];
|
|
8213
8466
|
}
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8467
|
+
function GetTarget(camera) {
|
|
8468
|
+
return [camera.target.x, camera.target.y, camera.target.z];
|
|
8469
|
+
}
|
|
8470
|
+
function SetFreeCameraPosition(camera, value) {
|
|
8471
|
+
SetVector3Value(camera.position, value);
|
|
8472
|
+
}
|
|
8473
|
+
function SetCameraTarget(camera, value) {
|
|
8474
|
+
SetVector3Value(camera.target, value);
|
|
8475
|
+
}
|
|
8476
|
+
const CameraGeneralProperties = (props) => {
|
|
8477
|
+
const { camera } = props;
|
|
8478
|
+
const [toDisplayAngle, fromDisplayAngle, useDegrees] = useAngleConverters();
|
|
8479
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextInputPropertyLine, label: "Name", target: camera, propertyKey: "name", ignoreNullable: true, defaultValue: "" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Near Plane", target: camera, propertyKey: "nearPlane" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Far Plane", target: camera, propertyKey: "farPlane" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "FOV", target: camera, propertyKey: "fov", min: toDisplayAngle(0.1), max: toDisplayAngle(Math.PI), step: toDisplayAngle(0.01), unit: useDegrees ? "°" : "rad", convertTo: toDisplayAngle, convertFrom: fromDisplayAngle })] }));
|
|
8217
8480
|
};
|
|
8218
|
-
const
|
|
8219
|
-
const {
|
|
8220
|
-
return jsx(
|
|
8481
|
+
const FreeCameraTransformProperties = (props) => {
|
|
8482
|
+
const { camera } = props;
|
|
8483
|
+
return (jsxs(Fragment, { children: [jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Position", target: camera, getValue: GetPosition$2, setValue: SetFreeCameraPosition }), jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Target", target: camera, getValue: GetTarget, setValue: SetCameraTarget }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Speed", target: camera, propertyKey: "speed" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Inertia", target: camera, propertyKey: "inertia", min: 0, max: 1 })] }));
|
|
8221
8484
|
};
|
|
8222
|
-
const
|
|
8223
|
-
const {
|
|
8224
|
-
|
|
8485
|
+
const ArcRotateCameraTransformProperties = (props) => {
|
|
8486
|
+
const { camera } = props;
|
|
8487
|
+
const [toDisplayAngle, fromDisplayAngle, useDegrees] = useAngleConverters();
|
|
8488
|
+
return (jsxs(Fragment, { children: [jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Target", target: camera, getValue: GetTarget, setValue: SetCameraTarget }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Alpha", target: camera, propertyKey: "alpha", unit: useDegrees ? "°" : "rad", convertTo: toDisplayAngle, convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Beta", target: camera, propertyKey: "beta", unit: useDegrees ? "°" : "rad", convertTo: toDisplayAngle, convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius", target: camera, propertyKey: "radius", min: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Inertia", target: camera, propertyKey: "inertia", min: 0, max: 1 })] }));
|
|
8225
8489
|
};
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
const
|
|
8232
|
-
key: "Babylon Lite
|
|
8233
|
-
predicate:
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8490
|
+
|
|
8491
|
+
const CameraPropertiesServiceDefinition = {
|
|
8492
|
+
friendlyName: "Babylon Lite Camera Properties",
|
|
8493
|
+
consumes: [PropertiesServiceIdentity],
|
|
8494
|
+
factory: (propertiesService) => {
|
|
8495
|
+
const cameraRegistration = propertiesService.addSectionContent({
|
|
8496
|
+
key: "Babylon Lite Camera Properties",
|
|
8497
|
+
predicate: IsCamera,
|
|
8498
|
+
content: [
|
|
8499
|
+
{
|
|
8500
|
+
section: "General",
|
|
8501
|
+
component: ({ context }) => jsx(CameraGeneralProperties, { camera: context }),
|
|
8502
|
+
},
|
|
8503
|
+
],
|
|
8504
|
+
});
|
|
8505
|
+
const freeCameraRegistration = propertiesService.addSectionContent({
|
|
8506
|
+
key: "Babylon Lite Free Camera Properties",
|
|
8507
|
+
predicate: IsFreeCamera,
|
|
8508
|
+
content: [
|
|
8509
|
+
{
|
|
8510
|
+
section: "Transform",
|
|
8511
|
+
component: ({ context }) => jsx(FreeCameraTransformProperties, { camera: context }),
|
|
8512
|
+
},
|
|
8513
|
+
],
|
|
8514
|
+
});
|
|
8515
|
+
const arcRotateCameraRegistration = propertiesService.addSectionContent({
|
|
8516
|
+
key: "Babylon Lite Arc Rotate Camera Properties",
|
|
8517
|
+
predicate: IsArcRotateCamera,
|
|
8518
|
+
content: [
|
|
8519
|
+
{
|
|
8520
|
+
section: "Transform",
|
|
8521
|
+
component: ({ context }) => jsx(ArcRotateCameraTransformProperties, { camera: context }),
|
|
8522
|
+
},
|
|
8523
|
+
],
|
|
8524
|
+
});
|
|
8525
|
+
return {
|
|
8526
|
+
dispose: () => {
|
|
8527
|
+
arcRotateCameraRegistration.dispose();
|
|
8528
|
+
freeCameraRegistration.dispose();
|
|
8529
|
+
cameraRegistration.dispose();
|
|
8530
|
+
},
|
|
8531
|
+
};
|
|
8532
|
+
},
|
|
8533
|
+
};
|
|
8534
|
+
|
|
8535
|
+
/**
|
|
8536
|
+
* Runtime-neutral controlled color editor with RGB or RGBA sliders and an injected picker.
|
|
8537
|
+
* @param props The controlled color, runtime adapter, and property-line presentation.
|
|
8538
|
+
* @returns The color property line.
|
|
8539
|
+
*/
|
|
8540
|
+
const ControlledColorPropertyLine = (props) => {
|
|
8541
|
+
const { adapter, value, onChange, propertyLineRef } = props;
|
|
8542
|
+
const [currentValue, setCurrentValue] = useState(value);
|
|
8543
|
+
useEffect(() => {
|
|
8544
|
+
setCurrentValue(value);
|
|
8545
|
+
}, [value]);
|
|
8546
|
+
const handleChange = (newValue) => {
|
|
8547
|
+
setCurrentValue(newValue);
|
|
8548
|
+
onChange(newValue);
|
|
8549
|
+
};
|
|
8550
|
+
const onSliderChange = (componentValue, component) => {
|
|
8551
|
+
const color = adapter.getColor(currentValue);
|
|
8552
|
+
handleChange(adapter.createColor({
|
|
8553
|
+
...color,
|
|
8554
|
+
[component]: component === "a" ? componentValue : componentValue / 255,
|
|
8555
|
+
}, currentValue));
|
|
8556
|
+
};
|
|
8557
|
+
const color = adapter.getColor(currentValue);
|
|
8558
|
+
return (jsx(PropertyLine, { ref: propertyLineRef, ...props, expandedContent: jsx(ColorSliders, { color: color, onSliderChange: onSliderChange }), children: createElement(adapter.picker, {
|
|
8559
|
+
value: currentValue,
|
|
8560
|
+
onChange: handleChange,
|
|
8561
|
+
isLinearMode: props.isLinearMode,
|
|
8562
|
+
disabled: props.disabled,
|
|
8563
|
+
className: props.className,
|
|
8564
|
+
style: props.style,
|
|
8565
|
+
title: props.title,
|
|
8566
|
+
}) }));
|
|
8567
|
+
};
|
|
8568
|
+
const ColorSliders = (props) => {
|
|
8569
|
+
const { color, onSliderChange } = props;
|
|
8570
|
+
return (jsxs(Fragment, { children: [jsx(SyncedSliderPropertyLine, { label: "R", value: color.r * 255, min: 0, max: 255, onChange: (value) => onSliderChange(value, "r") }), jsx(SyncedSliderPropertyLine, { label: "G", value: color.g * 255, min: 0, max: 255, onChange: (value) => onSliderChange(value, "g") }), jsx(SyncedSliderPropertyLine, { label: "B", value: color.b * 255, min: 0, max: 255, onChange: (value) => onSliderChange(value, "b") }), color.a === undefined ? undefined : (jsx(SyncedSliderPropertyLine, { label: "A", value: color.a, min: 0, max: 1, step: 0.01, onChange: (value) => onSliderChange(value, "a") }))] }));
|
|
8571
|
+
};
|
|
8572
|
+
|
|
8573
|
+
const useStyles$1 = makeStyles({
|
|
8574
|
+
picker: {
|
|
8575
|
+
width: "350px",
|
|
8576
|
+
height: "350px",
|
|
8577
|
+
},
|
|
8578
|
+
trigger: {
|
|
8579
|
+
display: "flex",
|
|
8580
|
+
alignItems: "center",
|
|
8581
|
+
},
|
|
8582
|
+
});
|
|
8583
|
+
function LinearChannelToGamma(value) {
|
|
8584
|
+
return value <= 0.0031308 ? value * 12.92 : 1.055 * value ** (1 / 2.4) - 0.055;
|
|
8585
|
+
}
|
|
8586
|
+
function GammaChannelToLinear(value) {
|
|
8587
|
+
return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
|
8588
|
+
}
|
|
8589
|
+
function ConvertColorSpace(color, convertChannel) {
|
|
8590
|
+
return {
|
|
8591
|
+
r: convertChannel(color.r),
|
|
8592
|
+
g: convertChannel(color.g),
|
|
8593
|
+
b: convertChannel(color.b),
|
|
8594
|
+
...("a" in color ? { a: color.a } : {}),
|
|
8595
|
+
};
|
|
8596
|
+
}
|
|
8597
|
+
function RgbToHsv(color) {
|
|
8598
|
+
const max = Math.max(color.r, color.g, color.b);
|
|
8599
|
+
const min = Math.min(color.r, color.g, color.b);
|
|
8600
|
+
const delta = max - min;
|
|
8601
|
+
let hue = 0;
|
|
8602
|
+
if (delta !== 0) {
|
|
8603
|
+
if (max === color.r) {
|
|
8604
|
+
hue = 60 * (((color.g - color.b) / delta) % 6);
|
|
8605
|
+
}
|
|
8606
|
+
else if (max === color.g) {
|
|
8607
|
+
hue = 60 * ((color.b - color.r) / delta + 2);
|
|
8608
|
+
}
|
|
8609
|
+
else {
|
|
8610
|
+
hue = 60 * ((color.r - color.g) / delta + 4);
|
|
8611
|
+
}
|
|
8612
|
+
}
|
|
8613
|
+
return {
|
|
8614
|
+
h: hue < 0 ? hue + 360 : hue,
|
|
8615
|
+
s: max === 0 ? 0 : delta / max,
|
|
8616
|
+
v: max,
|
|
8617
|
+
...("a" in color ? { a: color.a } : {}),
|
|
8618
|
+
};
|
|
8619
|
+
}
|
|
8620
|
+
function HsvToRgb(hue, saturation, value, alpha) {
|
|
8621
|
+
const chroma = value * saturation;
|
|
8622
|
+
const hueSector = hue / 60;
|
|
8623
|
+
const intermediate = chroma * (1 - Math.abs((hueSector % 2) - 1));
|
|
8624
|
+
const offset = value - chroma;
|
|
8625
|
+
let red = 0;
|
|
8626
|
+
let green = 0;
|
|
8627
|
+
let blue = 0;
|
|
8628
|
+
if (hueSector < 1) {
|
|
8629
|
+
red = chroma;
|
|
8630
|
+
green = intermediate;
|
|
8631
|
+
}
|
|
8632
|
+
else if (hueSector < 2) {
|
|
8633
|
+
red = intermediate;
|
|
8634
|
+
green = chroma;
|
|
8635
|
+
}
|
|
8636
|
+
else if (hueSector < 3) {
|
|
8637
|
+
green = chroma;
|
|
8638
|
+
blue = intermediate;
|
|
8639
|
+
}
|
|
8640
|
+
else if (hueSector < 4) {
|
|
8641
|
+
green = intermediate;
|
|
8642
|
+
blue = chroma;
|
|
8643
|
+
}
|
|
8644
|
+
else if (hueSector < 5) {
|
|
8645
|
+
red = intermediate;
|
|
8646
|
+
blue = chroma;
|
|
8647
|
+
}
|
|
8648
|
+
else {
|
|
8649
|
+
red = chroma;
|
|
8650
|
+
blue = intermediate;
|
|
8651
|
+
}
|
|
8652
|
+
return {
|
|
8653
|
+
r: red + offset,
|
|
8654
|
+
g: green + offset,
|
|
8655
|
+
b: blue + offset,
|
|
8656
|
+
...(alpha !== undefined ? { a: alpha } : {}),
|
|
8657
|
+
};
|
|
8658
|
+
}
|
|
8659
|
+
function ColorToHex(color) {
|
|
8660
|
+
const channelToHex = (value) => Math.round(Math.min(1, Math.max(0, value)) * 255)
|
|
8661
|
+
.toString(16)
|
|
8662
|
+
.padStart(2, "0");
|
|
8663
|
+
return `#${channelToHex(color.r)}${channelToHex(color.g)}${channelToHex(color.b)}${color.a === undefined ? "" : channelToHex(color.a)}`;
|
|
8664
|
+
}
|
|
8665
|
+
/**
|
|
8666
|
+
* Runtime-neutral color picker for structural RGB and RGBA values.
|
|
8667
|
+
* @param props The controlled value, adapter, color-space mode, and change callback.
|
|
8668
|
+
* @returns A color swatch that opens the Fluent color picker.
|
|
8669
|
+
*/
|
|
8670
|
+
const StructuralColorPickerPopup = (props) => {
|
|
8671
|
+
const { value, onChange, adapter, isLinearMode, ...rest } = props;
|
|
8672
|
+
const classes = useStyles$1();
|
|
8673
|
+
const { size } = useContext(ToolContext);
|
|
8674
|
+
const [currentValue, setCurrentValue] = useState(value);
|
|
8675
|
+
useEffect(() => {
|
|
8676
|
+
setCurrentValue(value);
|
|
8677
|
+
}, [value]);
|
|
8678
|
+
const storedColor = adapter.getColor(currentValue);
|
|
8679
|
+
const gammaColor = useMemo(() => (isLinearMode ? ConvertColorSpace(storedColor, LinearChannelToGamma) : storedColor), [storedColor, isLinearMode]);
|
|
8680
|
+
const hexColor = ColorToHex(gammaColor);
|
|
8681
|
+
const handleColorPickerChange = (_event, data) => {
|
|
8682
|
+
const changedGammaColor = HsvToRgb(data.color.h, data.color.s, data.color.v, storedColor.a === undefined ? undefined : (data.color.a ?? storedColor.a));
|
|
8683
|
+
const changedStoredColor = isLinearMode ? ConvertColorSpace(changedGammaColor, GammaChannelToLinear) : changedGammaColor;
|
|
8684
|
+
const changedValue = adapter.createColor(changedStoredColor, currentValue);
|
|
8685
|
+
setCurrentValue(changedValue);
|
|
8686
|
+
onChange(changedValue);
|
|
8687
|
+
};
|
|
8688
|
+
return (jsx(Popover, { trigger: jsx(ColorSwatch, { ...rest, className: classes.trigger, borderColor: tokens.colorNeutralShadowKeyDarker, size: size === "small" ? "extra-small" : "small", shape: "rounded", color: hexColor, value: hexColor.slice(1) }), children: jsxs(ColorPicker, { className: classes.picker, color: RgbToHsv(gammaColor), onColorChange: handleColorPickerChange, children: [jsx(ColorArea, { inputX: { "aria-label": "Saturation" }, inputY: { "aria-label": "Brightness" } }), jsx(ColorSlider, { "aria-label": "Hue" }), storedColor.a !== undefined ? jsx(AlphaSlider, { "aria-label": "Alpha" }) : undefined] }) }));
|
|
8689
|
+
};
|
|
8690
|
+
|
|
8691
|
+
function IsColor4Value(value) {
|
|
8692
|
+
return "r" in value ? "a" in value : value.length === 4;
|
|
8693
|
+
}
|
|
8694
|
+
function GetStructuralColor(value) {
|
|
8695
|
+
if (!("r" in value)) {
|
|
8696
|
+
return {
|
|
8697
|
+
r: value[0],
|
|
8698
|
+
g: value[1],
|
|
8699
|
+
b: value[2],
|
|
8700
|
+
...(value.length === 4 ? { a: value[3] } : {}),
|
|
8701
|
+
};
|
|
8702
|
+
}
|
|
8703
|
+
return value;
|
|
8704
|
+
}
|
|
8705
|
+
function CreateColor3Value(color, source) {
|
|
8706
|
+
if (!("r" in source)) {
|
|
8707
|
+
return [color.r, color.g, color.b];
|
|
8708
|
+
}
|
|
8709
|
+
return {
|
|
8710
|
+
r: color.r,
|
|
8711
|
+
g: color.g,
|
|
8712
|
+
b: color.b,
|
|
8713
|
+
};
|
|
8714
|
+
}
|
|
8715
|
+
function CreateColor4Value(color, source) {
|
|
8716
|
+
if (!("r" in source)) {
|
|
8717
|
+
return [color.r, color.g, color.b, color.a ?? source[3]];
|
|
8718
|
+
}
|
|
8719
|
+
return {
|
|
8720
|
+
r: color.r,
|
|
8721
|
+
g: color.g,
|
|
8722
|
+
b: color.b,
|
|
8723
|
+
a: color.a ?? source.a,
|
|
8724
|
+
};
|
|
8725
|
+
}
|
|
8726
|
+
const Picker = (props) => (jsx(StructuralColorPickerPopup, { ...props, adapter: {
|
|
8727
|
+
getColor: GetStructuralColor,
|
|
8728
|
+
createColor: (color, source) => (IsColor4Value(source) ? CreateColor4Value(color, source) : CreateColor3Value(color, source)),
|
|
8729
|
+
} }));
|
|
8730
|
+
const Adapter = {
|
|
8731
|
+
picker: Picker,
|
|
8732
|
+
getColor: GetStructuralColor,
|
|
8733
|
+
createColor: (color, source) => (IsColor4Value(source) ? CreateColor4Value(color, source) : CreateColor3Value(color, source)),
|
|
8734
|
+
};
|
|
8735
|
+
const Color3PropertyLine = (props) => (jsx(ControlledColorPropertyLine, { ...props, adapter: Adapter }));
|
|
8736
|
+
|
|
8737
|
+
function GetVector3(value) {
|
|
8738
|
+
return [value.x, value.y, value.z];
|
|
8739
|
+
}
|
|
8740
|
+
/**
|
|
8741
|
+
* Updates a plain Babylon Lite light property and marks its GPU light data dirty through a public observable transform.
|
|
8742
|
+
* @param light The light to update.
|
|
8743
|
+
* @param propertyKey The property to update.
|
|
8744
|
+
* @param value The new property value.
|
|
8745
|
+
*/
|
|
8746
|
+
function SetLightProperty(light, propertyKey, value) {
|
|
8747
|
+
light[propertyKey] = value;
|
|
8748
|
+
const dirtyVector = "direction" in light ? light.direction : light.position;
|
|
8749
|
+
dirtyVector.set(dirtyVector.x, dirtyVector.y, dirtyVector.z);
|
|
8750
|
+
}
|
|
8751
|
+
function GetDiffuse(light) {
|
|
8752
|
+
return light.diffuse;
|
|
8753
|
+
}
|
|
8754
|
+
function ToColorTuple(value) {
|
|
8755
|
+
return "r" in value ? [value.r, value.g, value.b] : [value[0], value[1], value[2]];
|
|
8756
|
+
}
|
|
8757
|
+
function SetDiffuse(light, value) {
|
|
8758
|
+
SetLightProperty(light, "diffuse", ToColorTuple(value));
|
|
8759
|
+
}
|
|
8760
|
+
function GetSpecular(light) {
|
|
8761
|
+
return light.specular;
|
|
8762
|
+
}
|
|
8763
|
+
function SetSpecular(light, value) {
|
|
8764
|
+
SetLightProperty(light, "specular", ToColorTuple(value));
|
|
8765
|
+
}
|
|
8766
|
+
function GetIntensity(light) {
|
|
8767
|
+
return light.intensity;
|
|
8768
|
+
}
|
|
8769
|
+
function SetIntensity(light, value) {
|
|
8770
|
+
SetLightProperty(light, "intensity", value);
|
|
8771
|
+
}
|
|
8772
|
+
function GetRange(light) {
|
|
8773
|
+
return light.range;
|
|
8774
|
+
}
|
|
8775
|
+
function SetRange(light, value) {
|
|
8776
|
+
SetLightProperty(light, "range", value);
|
|
8777
|
+
}
|
|
8778
|
+
function GetExponent(light) {
|
|
8779
|
+
return light.exponent;
|
|
8780
|
+
}
|
|
8781
|
+
function SetExponent(light, value) {
|
|
8782
|
+
SetLightProperty(light, "exponent", value);
|
|
8783
|
+
}
|
|
8784
|
+
function GetDiffuseColor(light) {
|
|
8785
|
+
return light.diffuseColor;
|
|
8786
|
+
}
|
|
8787
|
+
function SetDiffuseColor(light, value) {
|
|
8788
|
+
SetLightProperty(light, "diffuseColor", ToColorTuple(value));
|
|
8789
|
+
}
|
|
8790
|
+
function GetSpecularColor(light) {
|
|
8791
|
+
return light.specularColor;
|
|
8792
|
+
}
|
|
8793
|
+
function SetSpecularColor(light, value) {
|
|
8794
|
+
SetLightProperty(light, "specularColor", ToColorTuple(value));
|
|
8795
|
+
}
|
|
8796
|
+
function GetGroundColor(light) {
|
|
8797
|
+
return light.groundColor;
|
|
8798
|
+
}
|
|
8799
|
+
function SetGroundColor(light, value) {
|
|
8800
|
+
SetLightProperty(light, "groundColor", ToColorTuple(value));
|
|
8801
|
+
}
|
|
8802
|
+
const LightGeneralProperties = (props) => {
|
|
8803
|
+
const { light } = props;
|
|
8804
|
+
return jsx(TextPropertyLine, { label: "Type", value: light.lightType });
|
|
8805
|
+
};
|
|
8806
|
+
const DirectionalLightSetupProperties = (props) => {
|
|
8807
|
+
const { light } = props;
|
|
8808
|
+
return (jsxs(Fragment, { children: [jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Position", target: light.position, getValue: GetVector3, setValue: SetVector3Value }), jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Direction", target: light.direction, getValue: GetVector3, setValue: SetVector3Value }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Diffuse", target: light, getValue: GetDiffuse, setValue: SetDiffuse, isLinearMode: true }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Specular", target: light, getValue: GetSpecular, setValue: SetSpecular, isLinearMode: true }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Intensity", target: light, getValue: GetIntensity, setValue: SetIntensity })] }));
|
|
8809
|
+
};
|
|
8810
|
+
const PointLightSetupProperties = (props) => {
|
|
8811
|
+
const { light } = props;
|
|
8812
|
+
return (jsxs(Fragment, { children: [jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Position", target: light.position, getValue: GetVector3, setValue: SetVector3Value }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Diffuse", target: light, getValue: GetDiffuse, setValue: SetDiffuse, isLinearMode: true }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Specular", target: light, getValue: GetSpecular, setValue: SetSpecular, isLinearMode: true }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Intensity", target: light, getValue: GetIntensity, setValue: SetIntensity }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Range", target: light, getValue: GetRange, setValue: SetRange })] }));
|
|
8813
|
+
};
|
|
8814
|
+
const SpotLightSetupProperties = (props) => {
|
|
8815
|
+
const { light } = props;
|
|
8816
|
+
return (jsxs(Fragment, { children: [jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Position", target: light.position, getValue: GetVector3, setValue: SetVector3Value }), jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Direction", target: light.direction, getValue: GetVector3, setValue: SetVector3Value }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Diffuse", target: light, getValue: GetDiffuse, setValue: SetDiffuse, isLinearMode: true }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Specular", target: light, getValue: GetSpecular, setValue: SetSpecular, isLinearMode: true }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Intensity", target: light, getValue: GetIntensity, setValue: SetIntensity }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Range", target: light, getValue: GetRange, setValue: SetRange }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Angle", target: light, propertyKey: "angle", unit: "rad", min: 0, max: Math.PI }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Exponent", target: light, getValue: GetExponent, setValue: SetExponent, min: 0 })] }));
|
|
8817
|
+
};
|
|
8818
|
+
const HemisphericLightSetupProperties = (props) => {
|
|
8819
|
+
const { light } = props;
|
|
8820
|
+
return (jsxs(Fragment, { children: [jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Direction", target: light.direction, getValue: GetVector3, setValue: SetVector3Value }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Diffuse", target: light, getValue: GetDiffuseColor, setValue: SetDiffuseColor, isLinearMode: true }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Specular", target: light, getValue: GetSpecularColor, setValue: SetSpecularColor, isLinearMode: true }), jsx(DerivedProperty, { component: Color3PropertyLine, label: "Ground", target: light, getValue: GetGroundColor, setValue: SetGroundColor, isLinearMode: true }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Intensity", target: light, getValue: GetIntensity, setValue: SetIntensity })] }));
|
|
8821
|
+
};
|
|
8822
|
+
|
|
8823
|
+
const LightPropertiesServiceDefinition = {
|
|
8824
|
+
friendlyName: "Babylon Lite Light Properties",
|
|
8825
|
+
consumes: [PropertiesServiceIdentity],
|
|
8826
|
+
factory: (propertiesService) => {
|
|
8827
|
+
const registrations = [
|
|
8828
|
+
propertiesService.addSectionContent({
|
|
8829
|
+
key: "Babylon Lite Light Properties",
|
|
8830
|
+
predicate: IsLight,
|
|
8831
|
+
content: [{ section: "General", component: ({ context }) => jsx(LightGeneralProperties, { light: context }) }],
|
|
8832
|
+
}),
|
|
8833
|
+
propertiesService.addSectionContent({
|
|
8834
|
+
key: "Babylon Lite Directional Light Properties",
|
|
8835
|
+
predicate: IsDirectionalLight,
|
|
8836
|
+
content: [{ section: "Setup", component: ({ context }) => jsx(DirectionalLightSetupProperties, { light: context }) }],
|
|
8837
|
+
}),
|
|
8838
|
+
propertiesService.addSectionContent({
|
|
8839
|
+
key: "Babylon Lite Point Light Properties",
|
|
8840
|
+
predicate: IsPointLight,
|
|
8841
|
+
content: [{ section: "Setup", component: ({ context }) => jsx(PointLightSetupProperties, { light: context }) }],
|
|
8842
|
+
}),
|
|
8843
|
+
propertiesService.addSectionContent({
|
|
8844
|
+
key: "Babylon Lite Spot Light Properties",
|
|
8845
|
+
predicate: IsSpotLight,
|
|
8846
|
+
content: [{ section: "Setup", component: ({ context }) => jsx(SpotLightSetupProperties, { light: context }) }],
|
|
8847
|
+
}),
|
|
8848
|
+
propertiesService.addSectionContent({
|
|
8849
|
+
key: "Babylon Lite Hemispheric Light Properties",
|
|
8850
|
+
predicate: IsHemisphericLight,
|
|
8851
|
+
content: [{ section: "Setup", component: ({ context }) => jsx(HemisphericLightSetupProperties, { light: context }) }],
|
|
8852
|
+
}),
|
|
8853
|
+
];
|
|
8854
|
+
return {
|
|
8855
|
+
dispose: () => registrations.forEach((registration) => registration.dispose()),
|
|
8856
|
+
};
|
|
8857
|
+
},
|
|
8858
|
+
};
|
|
8859
|
+
|
|
8860
|
+
function IsMaterial(entity) {
|
|
8861
|
+
return typeof entity === "object" && entity !== null && getMaterialFamily(entity) !== undefined;
|
|
8862
|
+
}
|
|
8863
|
+
const MaterialProperties = (props) => {
|
|
8864
|
+
const { material } = props;
|
|
8865
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextInputPropertyLine, label: "Name", target: material, propertyKey: "name", ignoreNullable: true, defaultValue: "" }), jsx(TextPropertyLine, { label: "Family", value: getMaterialFamily(material) ?? "Unknown" })] }));
|
|
8866
|
+
};
|
|
8867
|
+
const MaterialPropertiesServiceDefinition = {
|
|
8868
|
+
friendlyName: "Babylon Lite Material Properties",
|
|
8869
|
+
consumes: [PropertiesServiceIdentity],
|
|
8870
|
+
factory: (propertiesService) => propertiesService.addSectionContent({
|
|
8871
|
+
key: "Babylon Lite Material Properties",
|
|
8872
|
+
predicate: IsMaterial,
|
|
8873
|
+
content: [
|
|
8874
|
+
{
|
|
8875
|
+
section: "General",
|
|
8876
|
+
component: ({ context }) => jsx(MaterialProperties, { material: context }),
|
|
8877
|
+
},
|
|
8878
|
+
],
|
|
8879
|
+
}),
|
|
8880
|
+
};
|
|
8881
|
+
|
|
8882
|
+
const MeshGeneralProperties = (props) => {
|
|
8883
|
+
const { mesh } = props;
|
|
8884
|
+
return jsx(BoundProperty, { component: SwitchPropertyLine, label: "Receive Shadows", target: mesh, propertyKey: "receiveShadows" });
|
|
8885
|
+
};
|
|
8886
|
+
const MeshPropertiesServiceDefinition = {
|
|
8887
|
+
friendlyName: "Babylon Lite Mesh Properties",
|
|
8888
|
+
consumes: [PropertiesServiceIdentity],
|
|
8889
|
+
factory: (propertiesService) => propertiesService.addSectionContent({
|
|
8890
|
+
key: "Babylon Lite Mesh Properties",
|
|
8891
|
+
predicate: IsMesh,
|
|
8892
|
+
content: [
|
|
8893
|
+
{
|
|
8894
|
+
section: "Rendering",
|
|
8895
|
+
component: ({ context }) => jsx(MeshGeneralProperties, { mesh: context }),
|
|
8896
|
+
},
|
|
8897
|
+
],
|
|
8898
|
+
}),
|
|
8899
|
+
};
|
|
8900
|
+
|
|
8901
|
+
const GetMeshCount = (scene) => scene.meshes.length;
|
|
8902
|
+
const GetLightCount = (scene) => scene.lights.length;
|
|
8903
|
+
const GetAnimationGroupCount = (scene) => scene.animationGroups.length;
|
|
8904
|
+
const GetShadowGeneratorCount = (scene) => scene.shadowGenerators.length;
|
|
8905
|
+
const GetTextLayerCount = (renderer) => renderer.layers.length;
|
|
8906
|
+
const GetSpriteLayerCount = (renderer) => renderer.layers.length;
|
|
8907
|
+
function IsRegisteredRenderingContext(engine, entity) {
|
|
8908
|
+
return typeof entity === "object" && entity !== null && engine.surfaces.some((surface) => getRenderingContexts(surface).includes(entity));
|
|
8909
|
+
}
|
|
8910
|
+
const SceneProperties = (props) => {
|
|
8911
|
+
const { scene } = props;
|
|
8912
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextInputPropertyLine, label: "Name", target: scene, propertyKey: "name", ignoreNullable: true, defaultValue: "" }), jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Mesh Count", target: scene, getValue: GetMeshCount }), jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Light Count", target: scene, getValue: GetLightCount }), jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Animation Group Count", target: scene, getValue: GetAnimationGroupCount }), jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Shadow Generator Count", target: scene, getValue: GetShadowGeneratorCount }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Fixed Delta (ms)", target: scene, propertyKey: "fixedDeltaMs", min: 0, step: 1 })] }));
|
|
8913
|
+
};
|
|
8914
|
+
const TextRendererProperties = (props) => {
|
|
8915
|
+
const { renderer } = props;
|
|
8916
|
+
return jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Layer Count", target: renderer, getValue: GetTextLayerCount });
|
|
8917
|
+
};
|
|
8918
|
+
const SpriteRendererProperties = (props) => {
|
|
8919
|
+
const { renderer } = props;
|
|
8920
|
+
return jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Layer Count", target: renderer, getValue: GetSpriteLayerCount });
|
|
8921
|
+
};
|
|
8922
|
+
const RenderingContextPropertiesServiceDefinition = {
|
|
8923
|
+
friendlyName: "Babylon Lite Rendering Context Properties",
|
|
8924
|
+
consumes: [PropertiesServiceIdentity, EngineContextIdentity],
|
|
8925
|
+
factory: (propertiesService, engineContext) => {
|
|
8926
|
+
const engine = engineContext.engine;
|
|
8927
|
+
const sceneRegistration = propertiesService.addSectionContent({
|
|
8928
|
+
key: "Babylon Lite Scene Properties",
|
|
8929
|
+
predicate: (entity) => {
|
|
8930
|
+
if (!IsRegisteredRenderingContext(engine, entity)) {
|
|
8931
|
+
return false;
|
|
8932
|
+
}
|
|
8933
|
+
return getRenderingContextKind(entity) === "scene";
|
|
8934
|
+
},
|
|
8935
|
+
content: [
|
|
8240
8936
|
{
|
|
8241
8937
|
section: "General",
|
|
8242
8938
|
component: ({ context }) => jsx(SceneProperties, { scene: context }),
|
|
@@ -8261,21 +8957,442 @@ const RenderingContextPropertiesServiceDefinition = {
|
|
|
8261
8957
|
section: "General",
|
|
8262
8958
|
component: ({ context }) => jsx(SpriteRendererProperties, { renderer: context }),
|
|
8263
8959
|
},
|
|
8264
|
-
],
|
|
8265
|
-
});
|
|
8266
|
-
return {
|
|
8267
|
-
dispose: () => {
|
|
8268
|
-
sceneRegistration.dispose();
|
|
8269
|
-
textRendererRegistration.dispose();
|
|
8270
|
-
spriteRendererRegistration.dispose();
|
|
8960
|
+
],
|
|
8961
|
+
});
|
|
8962
|
+
return {
|
|
8963
|
+
dispose: () => {
|
|
8964
|
+
sceneRegistration.dispose();
|
|
8965
|
+
textRendererRegistration.dispose();
|
|
8966
|
+
spriteRendererRegistration.dispose();
|
|
8967
|
+
},
|
|
8968
|
+
};
|
|
8969
|
+
},
|
|
8970
|
+
};
|
|
8971
|
+
|
|
8972
|
+
const PrettyJSONIndent = 2;
|
|
8973
|
+
function IsParsable(metadata) {
|
|
8974
|
+
try {
|
|
8975
|
+
const parsed = JSON.parse(metadata);
|
|
8976
|
+
return !!parsed && !IsString(parsed);
|
|
8977
|
+
}
|
|
8978
|
+
catch {
|
|
8979
|
+
return false;
|
|
8980
|
+
}
|
|
8981
|
+
}
|
|
8982
|
+
/**
|
|
8983
|
+
* Checks if the input is a string.
|
|
8984
|
+
* @param input - any input to check
|
|
8985
|
+
* @returns boolean - true if the input is a string, false otherwise
|
|
8986
|
+
*/
|
|
8987
|
+
function IsString(input) {
|
|
8988
|
+
return typeof input === "string" || input instanceof String;
|
|
8989
|
+
}
|
|
8990
|
+
/**
|
|
8991
|
+
* Checks recursively for functions on an object and returns `false` if any are found.
|
|
8992
|
+
* @param o any object, string or number
|
|
8993
|
+
* @returns boolean
|
|
8994
|
+
*/
|
|
8995
|
+
function ObjectCanSafelyStringify(o) {
|
|
8996
|
+
if (typeof o === "function") {
|
|
8997
|
+
return false;
|
|
8998
|
+
}
|
|
8999
|
+
if (o === null || o === true || o === false || typeof o === "number" || IsString(o)) {
|
|
9000
|
+
return true;
|
|
9001
|
+
}
|
|
9002
|
+
if (typeof o === "object") {
|
|
9003
|
+
if (Object.values(o).length === 0) {
|
|
9004
|
+
return true;
|
|
9005
|
+
}
|
|
9006
|
+
return Object.values(o).every((value) => ObjectCanSafelyStringify(value));
|
|
9007
|
+
}
|
|
9008
|
+
if (Array.isArray(o)) {
|
|
9009
|
+
return o.every((value) => ObjectCanSafelyStringify(value));
|
|
9010
|
+
}
|
|
9011
|
+
return false;
|
|
9012
|
+
}
|
|
9013
|
+
function GetMetadataEntityType(metadata) {
|
|
9014
|
+
if (metadata == null) {
|
|
9015
|
+
return "null";
|
|
9016
|
+
}
|
|
9017
|
+
else if (IsString(metadata)) {
|
|
9018
|
+
return "string";
|
|
9019
|
+
}
|
|
9020
|
+
else if (!ObjectCanSafelyStringify(metadata)) {
|
|
9021
|
+
return "object";
|
|
9022
|
+
}
|
|
9023
|
+
else {
|
|
9024
|
+
return "JSON";
|
|
9025
|
+
}
|
|
9026
|
+
}
|
|
9027
|
+
function HasGltfExtras(metadata) {
|
|
9028
|
+
return IsParsable(metadata) && !!JSON.parse(metadata).gltf;
|
|
9029
|
+
}
|
|
9030
|
+
function StringifyMetadata(metadata, format) {
|
|
9031
|
+
if (IsString(metadata)) {
|
|
9032
|
+
return metadata;
|
|
9033
|
+
}
|
|
9034
|
+
if (metadata) {
|
|
9035
|
+
// Try JSON.stringify even for objects with functions — it safely omits
|
|
9036
|
+
// function-valued and undefined properties. Only fall back to String()
|
|
9037
|
+
// for cases that actually throw (e.g. circular references).
|
|
9038
|
+
try {
|
|
9039
|
+
return JSON.stringify(metadata, undefined, format ? PrettyJSONIndent : undefined);
|
|
9040
|
+
}
|
|
9041
|
+
catch {
|
|
9042
|
+
return String(metadata);
|
|
9043
|
+
}
|
|
9044
|
+
}
|
|
9045
|
+
return null;
|
|
9046
|
+
}
|
|
9047
|
+
function Restringify(value, format) {
|
|
9048
|
+
return IsParsable(value) ? JSON.stringify(JSON.parse(value), undefined, format ? PrettyJSONIndent : undefined) : value;
|
|
9049
|
+
}
|
|
9050
|
+
function PopulateGLTFExtras(metadata) {
|
|
9051
|
+
if (!metadata) {
|
|
9052
|
+
metadata = "{}";
|
|
9053
|
+
}
|
|
9054
|
+
if (!IsParsable(metadata)) {
|
|
9055
|
+
return metadata;
|
|
9056
|
+
}
|
|
9057
|
+
try {
|
|
9058
|
+
const parsedJson = JSON.parse(metadata);
|
|
9059
|
+
if (parsedJson) {
|
|
9060
|
+
if (Reflect.has(parsedJson, "gltf")) {
|
|
9061
|
+
if (!Reflect.has(parsedJson.gltf, "extras")) {
|
|
9062
|
+
parsedJson.gltf.extras = {};
|
|
9063
|
+
}
|
|
9064
|
+
}
|
|
9065
|
+
else {
|
|
9066
|
+
parsedJson.gltf = { extras: {} };
|
|
9067
|
+
}
|
|
9068
|
+
}
|
|
9069
|
+
return JSON.stringify(parsedJson);
|
|
9070
|
+
}
|
|
9071
|
+
catch {
|
|
9072
|
+
return metadata;
|
|
9073
|
+
}
|
|
9074
|
+
}
|
|
9075
|
+
function SaveMetadata(entity, metadata) {
|
|
9076
|
+
if (IsParsable(metadata)) {
|
|
9077
|
+
entity.metadata = JSON.parse(metadata);
|
|
9078
|
+
}
|
|
9079
|
+
else {
|
|
9080
|
+
entity.metadata = metadata;
|
|
9081
|
+
}
|
|
9082
|
+
}
|
|
9083
|
+
const useStyles = makeStyles({
|
|
9084
|
+
mainDiv: {
|
|
9085
|
+
display: "flex",
|
|
9086
|
+
flexDirection: "column",
|
|
9087
|
+
gap: tokens.spacingVerticalXS,
|
|
9088
|
+
},
|
|
9089
|
+
buttonDiv: {
|
|
9090
|
+
display: "grid",
|
|
9091
|
+
gridAutoFlow: "column",
|
|
9092
|
+
gridTemplateColumns: "1fr auto auto auto",
|
|
9093
|
+
gap: tokens.spacingHorizontalXS,
|
|
9094
|
+
},
|
|
9095
|
+
});
|
|
9096
|
+
/**
|
|
9097
|
+
* Component to display metadata properties of an entity.
|
|
9098
|
+
* @param props - The properties for the component.
|
|
9099
|
+
* @returns A React component that displays metadata properties.
|
|
9100
|
+
*/
|
|
9101
|
+
const MetadataProperties = (props) => {
|
|
9102
|
+
const { entity } = props;
|
|
9103
|
+
const classes = useStyles();
|
|
9104
|
+
const { size } = useContext(ToolContext);
|
|
9105
|
+
const metadata = useProperty(entity, "metadata");
|
|
9106
|
+
const stringifiedMetadata = useMemo(() => StringifyMetadata(metadata, false) ?? "", [metadata]);
|
|
9107
|
+
const metadataType = useMemo(() => GetMetadataEntityType(metadata), [metadata]);
|
|
9108
|
+
const canPreventObjectCorruption = metadataType === "object";
|
|
9109
|
+
const [preventObjectCorruption, setPreventObjectCorruption] = useState(false);
|
|
9110
|
+
const isReadonly = canPreventObjectCorruption && preventObjectCorruption;
|
|
9111
|
+
const [editedMetadata, setEditedMetadata] = useState(stringifiedMetadata);
|
|
9112
|
+
useEffect(() => {
|
|
9113
|
+
setEditedMetadata(stringifiedMetadata);
|
|
9114
|
+
}, [stringifiedMetadata]);
|
|
9115
|
+
const isEditedMetadataJSON = useMemo(() => IsParsable(editedMetadata), [editedMetadata]);
|
|
9116
|
+
const unformattedEditedMetadata = useMemo(() => Restringify(editedMetadata, false), [editedMetadata]);
|
|
9117
|
+
return (jsxs(Fragment, { children: [jsx(TextPropertyLine, { label: "Property Type", value: metadataType }), jsx(Collapse, { visible: canPreventObjectCorruption, children: jsx(SwitchPropertyLine, { label: "Prevent Object Corruption", value: isReadonly, onChange: setPreventObjectCorruption }) }), jsx(LineContainer, { uniqueId: "MetadataTextarea", children: jsx(Textarea, { disabled: isReadonly, value: editedMetadata, onChange: setEditedMetadata }) }), jsx(ButtonLine, { label: "Populate glTF extras", disabled: !!editedMetadata && (!IsParsable(editedMetadata) || HasGltfExtras(editedMetadata)), onClick: () => {
|
|
9118
|
+
const isFormatted = Restringify(editedMetadata, true) === editedMetadata;
|
|
9119
|
+
let withGLTFExtras = PopulateGLTFExtras(editedMetadata);
|
|
9120
|
+
if (isFormatted) {
|
|
9121
|
+
withGLTFExtras = Restringify(withGLTFExtras, true);
|
|
9122
|
+
}
|
|
9123
|
+
setEditedMetadata(withGLTFExtras);
|
|
9124
|
+
} }), jsx(LineContainer, { uniqueId: "MetadataButtonDiv", children: jsxs("div", { className: classes.buttonDiv, children: [jsx(Button$1, { size: size, icon: jsx(SaveRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => SaveMetadata(entity, editedMetadata), children: jsx(Body1, { children: "Save" }) }), jsx(Tooltip$1, { content: "Undo Changes", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(ArrowUndoRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => setEditedMetadata(stringifiedMetadata) }) }), jsx(Tooltip$1, { content: "Format (Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesRegular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, true)) }) }), jsx(Tooltip$1, { content: "Clear Formatting (Undo Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesDismiss16Regular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, false)) }) })] }) })] }));
|
|
9125
|
+
};
|
|
9126
|
+
|
|
9127
|
+
function GetPosition$1(node) {
|
|
9128
|
+
return [node.position.x, node.position.y, node.position.z];
|
|
9129
|
+
}
|
|
9130
|
+
function GetRotation(node) {
|
|
9131
|
+
return [node.rotationQuaternion.x, node.rotationQuaternion.y, node.rotationQuaternion.z, node.rotationQuaternion.w];
|
|
9132
|
+
}
|
|
9133
|
+
function GetScaling(node) {
|
|
9134
|
+
return [node.scaling.x, node.scaling.y, node.scaling.z];
|
|
9135
|
+
}
|
|
9136
|
+
function GetVisibility(node) {
|
|
9137
|
+
return node.visible !== false;
|
|
9138
|
+
}
|
|
9139
|
+
function SetVisibility(node, visible) {
|
|
9140
|
+
setSubtreeVisible(node, visible);
|
|
9141
|
+
}
|
|
9142
|
+
function SetPosition(node, value) {
|
|
9143
|
+
SetVector3Value(node.position, value);
|
|
9144
|
+
}
|
|
9145
|
+
function SetRotation(node, value) {
|
|
9146
|
+
SetQuaternionValue(node.rotationQuaternion, value);
|
|
9147
|
+
}
|
|
9148
|
+
function SetScaling(node, value) {
|
|
9149
|
+
SetVector3Value(node.scaling, value);
|
|
9150
|
+
}
|
|
9151
|
+
const SceneNodeGeneralProperties = (props) => {
|
|
9152
|
+
const { node } = props;
|
|
9153
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextInputPropertyLine, label: "Name", target: node, propertyKey: "name" }), jsx(DerivedProperty, { component: SwitchPropertyLine, label: "Visible", target: node, getValue: GetVisibility, setValue: SetVisibility })] }));
|
|
9154
|
+
};
|
|
9155
|
+
const SceneNodeTransformProperties = (props) => {
|
|
9156
|
+
const { node } = props;
|
|
9157
|
+
const [useDegrees] = useSetting(UseDegreesSettingDescriptor);
|
|
9158
|
+
const [useEuler] = useSetting(UseEulerSettingDescriptor);
|
|
9159
|
+
return (jsxs(Fragment, { children: [jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Position", target: node, getValue: GetPosition$1, setValue: SetPosition }), jsx(DerivedProperty, { component: QuaternionPropertyLine, label: "Rotation", target: node, getValue: GetRotation, setValue: SetRotation, useDegrees: useDegrees, useEuler: useEuler }), jsx(DerivedProperty, { component: Vector3PropertyLine, label: "Scaling", target: node, getValue: GetScaling, setValue: SetScaling, step: 0.1 })] }));
|
|
9160
|
+
};
|
|
9161
|
+
|
|
9162
|
+
const SceneNodePropertiesServiceDefinition = {
|
|
9163
|
+
friendlyName: "Babylon Lite Scene Node Properties",
|
|
9164
|
+
consumes: [PropertiesServiceIdentity],
|
|
9165
|
+
factory: (propertiesService) => propertiesService.addSectionContent({
|
|
9166
|
+
key: "Babylon Lite Scene Node Properties",
|
|
9167
|
+
predicate: IsSceneNode,
|
|
9168
|
+
content: [
|
|
9169
|
+
{
|
|
9170
|
+
section: "General",
|
|
9171
|
+
component: ({ context }) => jsx(SceneNodeGeneralProperties, { node: context }),
|
|
9172
|
+
},
|
|
9173
|
+
{
|
|
9174
|
+
section: "Transform",
|
|
9175
|
+
component: ({ context }) => jsx(SceneNodeTransformProperties, { node: context }),
|
|
9176
|
+
},
|
|
9177
|
+
{
|
|
9178
|
+
section: "Metadata",
|
|
9179
|
+
component: ({ context }) => jsx(MetadataProperties, { entity: context }),
|
|
9180
|
+
},
|
|
9181
|
+
],
|
|
9182
|
+
}),
|
|
9183
|
+
};
|
|
9184
|
+
|
|
9185
|
+
/**
|
|
9186
|
+
* Returns whether a rendering context is a scene context.
|
|
9187
|
+
* @param context The rendering context to test.
|
|
9188
|
+
* @returns Whether the context is a scene context.
|
|
9189
|
+
*/
|
|
9190
|
+
function IsSceneContext(context) {
|
|
9191
|
+
return getRenderingContextKind(context) === "scene";
|
|
9192
|
+
}
|
|
9193
|
+
/**
|
|
9194
|
+
* Creates an Explorer section containing the supplied scene entities.
|
|
9195
|
+
* @param id The stable section identifier.
|
|
9196
|
+
* @param displayName The section's display name.
|
|
9197
|
+
* @param entities The entities displayed by the section.
|
|
9198
|
+
* @param getEntityDisplayInfo Gets the display information for an entity.
|
|
9199
|
+
* @param entityIcon The optional icon component for the entities.
|
|
9200
|
+
* @returns The Explorer node description for the section.
|
|
9201
|
+
*/
|
|
9202
|
+
function CreateSceneExplorerSectionNode(id, displayName, entities, getEntityDisplayInfo, entityIcon) {
|
|
9203
|
+
return {
|
|
9204
|
+
id,
|
|
9205
|
+
kind: "group",
|
|
9206
|
+
getDisplayInfo: () => ({ name: displayName }),
|
|
9207
|
+
getChildren: () => entities.map((entity, index) => ({
|
|
9208
|
+
id: GetEntityId(entity).toString(),
|
|
9209
|
+
kind: "item",
|
|
9210
|
+
entity,
|
|
9211
|
+
icon: entityIcon,
|
|
9212
|
+
getDisplayInfo: () => getEntityDisplayInfo(entity, index),
|
|
9213
|
+
})),
|
|
9214
|
+
};
|
|
9215
|
+
}
|
|
9216
|
+
|
|
9217
|
+
function GetScenes(engineContext) {
|
|
9218
|
+
return engineContext.engine.surfaces.flatMap((surface) => getRenderingContexts(surface).filter(IsSceneContext));
|
|
9219
|
+
}
|
|
9220
|
+
const ShadowGeneratorPropertiesServiceDefinition = {
|
|
9221
|
+
friendlyName: "Babylon Lite Shadow Generator Properties",
|
|
9222
|
+
consumes: [PropertiesServiceIdentity, EngineContextIdentity],
|
|
9223
|
+
factory: (propertiesService, engineContext) => propertiesService.addSectionContent({
|
|
9224
|
+
key: "Babylon Lite Shadow Generator Properties",
|
|
9225
|
+
predicate: (entity) => typeof entity === "object" && entity !== null && GetScenes(engineContext).some((scene) => scene.shadowGenerators.includes(entity)),
|
|
9226
|
+
content: [
|
|
9227
|
+
{
|
|
9228
|
+
section: "General",
|
|
9229
|
+
component: ({ context }) => {
|
|
9230
|
+
const scene = GetScenes(engineContext).find((candidate) => candidate.shadowGenerators.includes(context));
|
|
9231
|
+
return jsx(TextPropertyLine, { label: "Identity", value: scene ? GetShadowGeneratorDisplayName(scene, context) : "Shadow Generator" });
|
|
9232
|
+
},
|
|
8271
9233
|
},
|
|
8272
|
-
|
|
8273
|
-
},
|
|
9234
|
+
],
|
|
9235
|
+
}),
|
|
9236
|
+
};
|
|
9237
|
+
|
|
9238
|
+
const LayerOrderMarkers = new WeakMap();
|
|
9239
|
+
function GetLayerOrderMarker(layer) {
|
|
9240
|
+
const existing = LayerOrderMarkers.get(layer);
|
|
9241
|
+
if (existing?.order === layer.order) {
|
|
9242
|
+
return existing.marker;
|
|
9243
|
+
}
|
|
9244
|
+
const marker = {};
|
|
9245
|
+
LayerOrderMarkers.set(layer, { order: layer.order, marker });
|
|
9246
|
+
return marker;
|
|
9247
|
+
}
|
|
9248
|
+
function GetOrderedRenderingLayers(layers) {
|
|
9249
|
+
return layers
|
|
9250
|
+
.map((layer, index) => ({ layer, index }))
|
|
9251
|
+
.sort((left, right) => left.layer.order - right.layer.order || left.index - right.index)
|
|
9252
|
+
.map(({ layer }) => layer);
|
|
9253
|
+
}
|
|
9254
|
+
function GetRenderingLayerSnapshot(layers) {
|
|
9255
|
+
return layers.flatMap((layer) => [layer, GetLayerOrderMarker(layer)]);
|
|
9256
|
+
}
|
|
9257
|
+
function GetRenderingLayerOwners(engine, contextKind, layer) {
|
|
9258
|
+
return engine.surfaces.flatMap((surface) => getRenderingContexts(surface).filter((context) => getRenderingContextKind(context) === contextKind && context.layers.includes(layer)));
|
|
9259
|
+
}
|
|
9260
|
+
function GetRenderingLayerDisplayName(engine, contextKind, layer, layerTypeName) {
|
|
9261
|
+
const owners = GetRenderingLayerOwners(engine, contextKind, layer);
|
|
9262
|
+
const index = owners.length === 1 ? GetOrderedRenderingLayers(owners[0].layers).indexOf(layer) : -1;
|
|
9263
|
+
return index === -1 ? layerTypeName : `${layerTypeName} ${index + 1}`;
|
|
9264
|
+
}
|
|
9265
|
+
|
|
9266
|
+
const SpriteLayerDisplayNameGetters = new WeakMap();
|
|
9267
|
+
function GetSpriteLayerDisplayNameGetter(engine) {
|
|
9268
|
+
let getter = SpriteLayerDisplayNameGetters.get(engine);
|
|
9269
|
+
if (!getter) {
|
|
9270
|
+
getter = (layer) => GetRenderingLayerDisplayName(engine, "sprite-renderer", layer, "Sprite Layer");
|
|
9271
|
+
SpriteLayerDisplayNameGetters.set(engine, getter);
|
|
9272
|
+
}
|
|
9273
|
+
return getter;
|
|
9274
|
+
}
|
|
9275
|
+
function GetSpriteCount(layer) {
|
|
9276
|
+
return layer.count;
|
|
9277
|
+
}
|
|
9278
|
+
function GetViewPositionX(layer) {
|
|
9279
|
+
return layer.view.positionPx[0];
|
|
9280
|
+
}
|
|
9281
|
+
function SetViewPositionX(layer, value) {
|
|
9282
|
+
layer.view.positionPx[0] = value;
|
|
9283
|
+
}
|
|
9284
|
+
function GetViewPositionY(layer) {
|
|
9285
|
+
return layer.view.positionPx[1];
|
|
9286
|
+
}
|
|
9287
|
+
function SetViewPositionY(layer, value) {
|
|
9288
|
+
layer.view.positionPx[1] = value;
|
|
9289
|
+
}
|
|
9290
|
+
function GetViewPosition(layer) {
|
|
9291
|
+
return layer.view.positionPx;
|
|
9292
|
+
}
|
|
9293
|
+
function GetViewZoom(layer) {
|
|
9294
|
+
return layer.view.zoom;
|
|
9295
|
+
}
|
|
9296
|
+
function SetViewZoom(layer, value) {
|
|
9297
|
+
layer.view.zoom = value;
|
|
9298
|
+
}
|
|
9299
|
+
function IsNonZero(value) {
|
|
9300
|
+
return value !== 0;
|
|
9301
|
+
}
|
|
9302
|
+
function GetView(layer) {
|
|
9303
|
+
return layer.view;
|
|
9304
|
+
}
|
|
9305
|
+
function GetViewRotation(layer) {
|
|
9306
|
+
return layer.view.rotation;
|
|
9307
|
+
}
|
|
9308
|
+
function SetViewRotation(layer, value) {
|
|
9309
|
+
layer.view.rotation = value;
|
|
9310
|
+
}
|
|
9311
|
+
function GetPivotX(layer) {
|
|
9312
|
+
return layer.pivot[0];
|
|
9313
|
+
}
|
|
9314
|
+
function SetPivotX(layer, value) {
|
|
9315
|
+
layer.pivot[0] = value;
|
|
9316
|
+
}
|
|
9317
|
+
function GetPivotY(layer) {
|
|
9318
|
+
return layer.pivot[1];
|
|
9319
|
+
}
|
|
9320
|
+
function SetPivotY(layer, value) {
|
|
9321
|
+
layer.pivot[1] = value;
|
|
9322
|
+
}
|
|
9323
|
+
function GetPivot(layer) {
|
|
9324
|
+
return layer.pivot;
|
|
9325
|
+
}
|
|
9326
|
+
function GetSpriteBlendModeName(blendMode) {
|
|
9327
|
+
switch (blendMode) {
|
|
9328
|
+
case spriteBlendAlpha:
|
|
9329
|
+
return "Alpha";
|
|
9330
|
+
case spriteBlendPremultiplied:
|
|
9331
|
+
return "Premultiplied";
|
|
9332
|
+
case spriteBlendAdditive:
|
|
9333
|
+
return "Additive";
|
|
9334
|
+
case spriteBlendMultiply:
|
|
9335
|
+
return "Multiply";
|
|
9336
|
+
case spriteBlendOneOne:
|
|
9337
|
+
return "One-One";
|
|
9338
|
+
case spriteBlendOpaque:
|
|
9339
|
+
return "Opaque";
|
|
9340
|
+
default:
|
|
9341
|
+
return "Unsupported descriptor";
|
|
9342
|
+
}
|
|
9343
|
+
}
|
|
9344
|
+
function IsRegisteredSpriteLayer(engine, entity) {
|
|
9345
|
+
if (typeof entity !== "object" || entity === null) {
|
|
9346
|
+
return false;
|
|
9347
|
+
}
|
|
9348
|
+
return engine.surfaces.some((surface) => getRenderingContexts(surface).some((context) => getRenderingContextKind(context) === "sprite-renderer" && context.layers.includes(entity)));
|
|
9349
|
+
}
|
|
9350
|
+
const SpriteLayerProperties = (props) => {
|
|
9351
|
+
const { engine, layer } = props;
|
|
9352
|
+
return (jsxs(Fragment, { children: [jsx(ComputedProperty, { component: TextPropertyLine, label: "Name", target: layer, getValue: GetSpriteLayerDisplayNameGetter(engine) }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Visible", target: layer, propertyKey: "visible" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Order", target: layer, propertyKey: "order" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Opacity", target: layer, propertyKey: "opacity", min: 0, max: 1, step: 0.01 }), jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Sprite Count", target: layer, getValue: GetSpriteCount }), jsx(TextPropertyLine, { label: "Depth Mode", value: layer.depth }), jsx(TextPropertyLine, { label: "Blend Mode", value: GetSpriteBlendModeName(layer.blendMode) }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "View Position X", target: layer, getValue: GetViewPositionX, setValue: SetViewPositionX, propertyPath: "view.positionPx[0]", getPropertyOwner: GetViewPosition, propertyKey: 0, step: 1, unit: "px" }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "View Position Y", target: layer, getValue: GetViewPositionY, setValue: SetViewPositionY, propertyPath: "view.positionPx[1]", getPropertyOwner: GetViewPosition, propertyKey: 1, step: 1, unit: "px" }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "View Zoom", target: layer, getValue: GetViewZoom, setValue: SetViewZoom, propertyPath: "view.zoom", getPropertyOwner: GetView, propertyKey: "zoom", validator: IsNonZero, step: 0.1 }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "View Rotation", target: layer, getValue: GetViewRotation, setValue: SetViewRotation, propertyPath: "view.rotation", getPropertyOwner: GetView, propertyKey: "rotation", step: 0.01, unit: "rad" }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Pivot X", target: layer, getValue: GetPivotX, setValue: SetPivotX, propertyPath: "pivot[0]", getPropertyOwner: GetPivot, propertyKey: 0, min: 0, max: 1, step: 0.01 }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Pivot Y", target: layer, getValue: GetPivotY, setValue: SetPivotY, propertyPath: "pivot[1]", getPropertyOwner: GetPivot, propertyKey: 1, min: 0, max: 1, step: 0.01 }), jsx(TextPropertyLine, { label: "Default Depth", value: "Not applicable to renderer-owned layers." }), jsx(TextPropertyLine, { label: "Atlas Frames", value: layer.atlas.frames.length.toString() }), jsx(TextPropertyLine, { label: "Atlas Size", value: `${layer.atlas.textureSizePx[0]} x ${layer.atlas.textureSizePx[1]} px` }), jsx(TextPropertyLine, { label: "Premultiplied Alpha", value: layer.atlas.premultipliedAlpha ? "True" : "False" })] }));
|
|
9353
|
+
};
|
|
9354
|
+
const SpriteLayerPropertiesServiceDefinition = {
|
|
9355
|
+
friendlyName: "Babylon Lite Sprite Layer Properties",
|
|
9356
|
+
consumes: [PropertiesServiceIdentity, EngineContextIdentity],
|
|
9357
|
+
factory: (propertiesService, engineContext) => propertiesService.addSectionContent({
|
|
9358
|
+
key: "Babylon Lite Sprite Layer Properties",
|
|
9359
|
+
predicate: (entity) => IsRegisteredSpriteLayer(engineContext.engine, entity),
|
|
9360
|
+
content: [
|
|
9361
|
+
{
|
|
9362
|
+
section: "General",
|
|
9363
|
+
component: ({ context }) => jsx(SpriteLayerProperties, { engine: engineContext.engine, layer: context }),
|
|
9364
|
+
},
|
|
9365
|
+
],
|
|
9366
|
+
}),
|
|
8274
9367
|
};
|
|
8275
9368
|
|
|
9369
|
+
const TextLayerDisplayNameGetters = new WeakMap();
|
|
9370
|
+
function GetTextLayerDisplayNameGetter(engine) {
|
|
9371
|
+
let getter = TextLayerDisplayNameGetters.get(engine);
|
|
9372
|
+
if (!getter) {
|
|
9373
|
+
getter = (layer) => GetRenderingLayerDisplayName(engine, "text-renderer", layer, "Text Layer");
|
|
9374
|
+
TextLayerDisplayNameGetters.set(engine, getter);
|
|
9375
|
+
}
|
|
9376
|
+
return getter;
|
|
9377
|
+
}
|
|
8276
9378
|
function GetRunCount(layer) {
|
|
8277
9379
|
return layer.data.runs.length;
|
|
8278
9380
|
}
|
|
9381
|
+
function GetPositionX(layer) {
|
|
9382
|
+
return layer.positionPx.x;
|
|
9383
|
+
}
|
|
9384
|
+
function SetPositionX(layer, value) {
|
|
9385
|
+
layer.positionPx.x = value;
|
|
9386
|
+
}
|
|
9387
|
+
function GetPositionY(layer) {
|
|
9388
|
+
return layer.positionPx.y;
|
|
9389
|
+
}
|
|
9390
|
+
function SetPositionY(layer, value) {
|
|
9391
|
+
layer.positionPx.y = value;
|
|
9392
|
+
}
|
|
9393
|
+
function GetPosition(layer) {
|
|
9394
|
+
return layer.positionPx;
|
|
9395
|
+
}
|
|
8279
9396
|
function GetGlyphCount(layer) {
|
|
8280
9397
|
return layer.data.runs.reduce((count, run) => count + run.glyphs.length, 0);
|
|
8281
9398
|
}
|
|
@@ -8286,8 +9403,8 @@ function IsRegisteredTextLayer(engine, entity) {
|
|
|
8286
9403
|
return engine.surfaces.some((surface) => getRenderingContexts(surface).some((context) => getRenderingContextKind(context) === "text-renderer" && context.layers.includes(entity)));
|
|
8287
9404
|
}
|
|
8288
9405
|
const TextLayerProperties = (props) => {
|
|
8289
|
-
const { layer } = props;
|
|
8290
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Visible", target: layer, propertyKey: "visible" }), jsx(
|
|
9406
|
+
const { engine, layer } = props;
|
|
9407
|
+
return (jsxs(Fragment, { children: [jsx(ComputedProperty, { component: TextPropertyLine, label: "Name", target: layer, getValue: GetTextLayerDisplayNameGetter(engine) }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Visible", target: layer, propertyKey: "visible" }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Position X", target: layer, getValue: GetPositionX, setValue: SetPositionX, propertyPath: "positionPx.x", getPropertyOwner: GetPosition, propertyKey: "x", step: 1, unit: "px" }), jsx(DerivedProperty, { component: NumberInputPropertyLine, label: "Position Y", target: layer, getValue: GetPositionY, setValue: SetPositionY, propertyPath: "positionPx.y", getPropertyOwner: GetPosition, propertyKey: "y", step: 1, unit: "px" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Rotation", target: layer, propertyKey: "rotationRad", step: 0.01, unit: "rad" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Scale", target: layer, propertyKey: "scale", step: 0.1 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Order", target: layer, propertyKey: "order" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Opacity", target: layer, propertyKey: "opacity", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Coverage Gamma", target: layer, propertyKey: "coverageGamma", step: 0.1 }), jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Run Count", target: layer, getValue: GetRunCount }), jsx(ComputedProperty, { component: StringifiedPropertyLine, label: "Glyph Count", target: layer, getValue: GetGlyphCount })] }));
|
|
8291
9408
|
};
|
|
8292
9409
|
const TextLayerPropertiesServiceDefinition = {
|
|
8293
9410
|
friendlyName: "Babylon Lite Text Layer Properties",
|
|
@@ -8298,7 +9415,7 @@ const TextLayerPropertiesServiceDefinition = {
|
|
|
8298
9415
|
content: [
|
|
8299
9416
|
{
|
|
8300
9417
|
section: "General",
|
|
8301
|
-
component: ({ context }) => jsx(TextLayerProperties, { layer: context }),
|
|
9418
|
+
component: ({ context }) => jsx(TextLayerProperties, { engine: engineContext.engine, layer: context }),
|
|
8302
9419
|
},
|
|
8303
9420
|
],
|
|
8304
9421
|
}),
|
|
@@ -8330,6 +9447,100 @@ const TexturePropertiesServiceDefinition = {
|
|
|
8330
9447
|
}),
|
|
8331
9448
|
};
|
|
8332
9449
|
|
|
9450
|
+
function ClearRemovedSelection(selectionService, engineContext, selectionWasRemoved) {
|
|
9451
|
+
const selectedEntity = selectionService.selectedEntity;
|
|
9452
|
+
if (selectionWasRemoved &&
|
|
9453
|
+
!GetSceneContexts(engineContext.engine).some((scene) => GetSceneNodeRoots(scene).some((root) => root === selectedEntity || (IsSceneNode(selectedEntity) && IsSceneNodeDescendantOf(selectedEntity, root))))) {
|
|
9454
|
+
selectionService.selectedEntity = null;
|
|
9455
|
+
}
|
|
9456
|
+
}
|
|
9457
|
+
|
|
9458
|
+
const CameraIcon = () => jsx(CameraRegular, { color: tokens.colorPaletteGreenForeground2 });
|
|
9459
|
+
const CameraExplorerServiceDefinition = {
|
|
9460
|
+
friendlyName: "Babylon Lite Camera Explorer",
|
|
9461
|
+
consumes: [EngineExplorerServiceIdentity, ExplorerServiceIdentity, WatcherServiceIdentity, SelectionServiceIdentity, EngineContextIdentity],
|
|
9462
|
+
factory: (engineExplorerService, explorerService, watcherService, selectionService, engineContext) => {
|
|
9463
|
+
const providerRegistration = engineExplorerService.addRenderingContextNodeProvider({
|
|
9464
|
+
order: 10,
|
|
9465
|
+
predicate: IsSceneContext,
|
|
9466
|
+
getNodes: (scene) => {
|
|
9467
|
+
return [
|
|
9468
|
+
CreateSceneExplorerSectionNode("cameras", "Cameras", scene.camera ? [scene.camera] : [], (camera) => CreateWatchedNameDisplayInfo(watcherService, camera, () => camera.name || "Camera"), CameraIcon),
|
|
9469
|
+
];
|
|
9470
|
+
},
|
|
9471
|
+
getSnapshot: (scene) => (scene.camera ? [scene.camera] : []),
|
|
9472
|
+
});
|
|
9473
|
+
const removeRegistration = explorerService.addItemCommand({
|
|
9474
|
+
predicate: (entity) => IsCamera(entity) && GetSceneContexts(engineContext.engine).filter((scene) => scene.camera === entity).length === 1,
|
|
9475
|
+
order: 10000,
|
|
9476
|
+
getCommand: (camera) => ({
|
|
9477
|
+
type: "action",
|
|
9478
|
+
mode: "contextMenu",
|
|
9479
|
+
displayName: "Remove from Scene",
|
|
9480
|
+
icon: DeleteRegular,
|
|
9481
|
+
hotKey: { keyCode: "Delete" },
|
|
9482
|
+
execute: () => {
|
|
9483
|
+
const owningScenes = GetSceneContexts(engineContext.engine).filter((candidate) => candidate.camera === camera);
|
|
9484
|
+
if (owningScenes.length === 1) {
|
|
9485
|
+
const selectedEntity = selectionService.selectedEntity;
|
|
9486
|
+
const selectionWasRemoved = selectedEntity === camera || (IsSceneNode(selectedEntity) && IsSceneNodeDescendantOf(selectedEntity, camera));
|
|
9487
|
+
removeFromScene(owningScenes[0], camera);
|
|
9488
|
+
ClearRemovedSelection(selectionService, engineContext, selectionWasRemoved);
|
|
9489
|
+
}
|
|
9490
|
+
},
|
|
9491
|
+
}),
|
|
9492
|
+
});
|
|
9493
|
+
return {
|
|
9494
|
+
dispose: () => {
|
|
9495
|
+
removeRegistration.dispose();
|
|
9496
|
+
providerRegistration.dispose();
|
|
9497
|
+
},
|
|
9498
|
+
};
|
|
9499
|
+
},
|
|
9500
|
+
};
|
|
9501
|
+
|
|
9502
|
+
const LightIcon = () => jsx(LightbulbRegular, { color: tokens.colorPaletteYellowForeground2 });
|
|
9503
|
+
const LightExplorerServiceDefinition = {
|
|
9504
|
+
friendlyName: "Babylon Lite Light Explorer",
|
|
9505
|
+
consumes: [EngineExplorerServiceIdentity, ExplorerServiceIdentity, SelectionServiceIdentity, EngineContextIdentity],
|
|
9506
|
+
factory: (engineExplorerService, explorerService, selectionService, engineContext) => {
|
|
9507
|
+
const providerRegistration = engineExplorerService.addRenderingContextNodeProvider({
|
|
9508
|
+
order: 20,
|
|
9509
|
+
predicate: IsSceneContext,
|
|
9510
|
+
getNodes: (scene) => {
|
|
9511
|
+
return [CreateSceneExplorerSectionNode("lights", "Lights", scene.lights, (light, index) => ({ name: GetLightDisplayName(light, index) }), LightIcon)];
|
|
9512
|
+
},
|
|
9513
|
+
getSnapshot: (scene) => scene.lights,
|
|
9514
|
+
});
|
|
9515
|
+
const removeRegistration = explorerService.addItemCommand({
|
|
9516
|
+
predicate: (entity) => IsLight(entity) && GetSceneContexts(engineContext.engine).filter((scene) => scene.lights.includes(entity)).length === 1,
|
|
9517
|
+
order: 10000,
|
|
9518
|
+
getCommand: (light) => ({
|
|
9519
|
+
type: "action",
|
|
9520
|
+
mode: "contextMenu",
|
|
9521
|
+
displayName: "Remove from Scene",
|
|
9522
|
+
icon: DeleteRegular,
|
|
9523
|
+
hotKey: { keyCode: "Delete" },
|
|
9524
|
+
execute: () => {
|
|
9525
|
+
const owningScenes = GetSceneContexts(engineContext.engine).filter((candidate) => candidate.lights.includes(light));
|
|
9526
|
+
if (owningScenes.length === 1) {
|
|
9527
|
+
const selectedEntity = selectionService.selectedEntity;
|
|
9528
|
+
const selectionWasRemoved = selectedEntity === light || selectedEntity === light.shadowGenerator || (IsSceneNode(selectedEntity) && IsSceneNodeDescendantOf(selectedEntity, light));
|
|
9529
|
+
removeFromScene(owningScenes[0], light);
|
|
9530
|
+
ClearRemovedSelection(selectionService, engineContext, selectionWasRemoved);
|
|
9531
|
+
}
|
|
9532
|
+
},
|
|
9533
|
+
}),
|
|
9534
|
+
});
|
|
9535
|
+
return {
|
|
9536
|
+
dispose: () => {
|
|
9537
|
+
removeRegistration.dispose();
|
|
9538
|
+
providerRegistration.dispose();
|
|
9539
|
+
},
|
|
9540
|
+
};
|
|
9541
|
+
},
|
|
9542
|
+
};
|
|
9543
|
+
|
|
8333
9544
|
const MeshIcon = createFluentIcon("Mesh", "1em", '<g transform="scale(1.25)"><path d="M14.03,3.54l-5.11-2.07c-.61-.25-1.27-.25-1.88,0L1.93,3.54c-.57.23-.94.78-.94,1.39v6.15c0,.61.37,1.16.94,1.39l5.11,2.07c.3.12.62.18.94.18s.64-.06.94-.18l5.12-2.07c.57-.23.94-.78.94-1.39v-6.15c0-.61-.37-1.16-.94-1.39ZM13.97,7.71l-2.11.86v-2.71l2.11-.86v2.71ZM1.99,5l2.11.86v2.71l-2.11-.86v-2.71ZM11.35,4.98l-2.04-.83,1.78-.72,2.04.83-1.78.72ZM10.02,5.52l-2.04.83-2.04-.83,2.04-.83,2.04.83ZM4.6,4.98l-1.78-.72,2.04-.83,1.78.72-2.04.83ZM5.1,6.26l2.38.96v2.71l-2.38-.96v-2.71ZM8.48,7.22l2.38-.96v2.71l-2.38.96v-2.71ZM7.41,2.39c.18-.07.37-.11.56-.11s.38.04.56.11l1.22.49-1.78.72-1.79-.72,1.22-.49ZM1.99,11.07v-2.29l2.11.86v2.62l-1.8-.73c-.19-.08-.31-.26-.31-.46ZM5.1,12.67v-2.62l2.38.96v2.61s-.04,0-.06-.01l-2.31-.94ZM8.54,13.61s-.04,0-.06.01v-2.61l2.38-.96v2.62l-2.31.94ZM13.66,11.54l-1.8.73v-2.62l2.11-.86v2.29c0,.2-.12.39-.31.46Z"/></g>');
|
|
8334
9545
|
createFluentIcon("Translate", "1em", '<g transform="scale(0.833)"><path d="M20.16,12.98l-2.75-2.75c-.29-.29-.77-.29-1.06,0-.29.29-.29.77,0,1.06l1.47,1.47h-6.69v-6.69l1.47,1.47c.29.29.77.29,1.06,0,.29-.29.29-.77,0-1.06l-2.75-2.75c-.14-.14-.33-.22-.53-.22s-.39.08-.53.22l-2.75,2.75c-.29.29-.29.77,0,1.06.29.29.77.29,1.06,0l1.47-1.47v7.13l-3.52,3.52v-2.08c0-.41-.34-.75-.75-.75s-.75.34-.75.75v3.89c0,.2.08.39.22.53.14.14.33.22.53.22h3.89c.41,0,.75-.34.75-.75s-.34-.75-.75-.75h-2.08s3.52-3.52,3.52-3.52h7.13l-1.47,1.47c-.29.29-.29.77,0,1.06s.77.29,1.06,0l2.75-2.75c.14-.14.22-.33.22-.53s-.08-.39-.22-.53Z" /></g>');
|
|
8335
9546
|
const MaterialIcon = createFluentIcon("Material", "1em", '<g transform="scale(1.25)"><path d="M14.74,6.3c-.09-.36-.38-.64-.75-.72-.04-.09-.08-.18-.12-.27.1-.15.16-.32.16-.51,0-.18-.05-.34-.13-.48-1.23-1.97-3.41-3.28-5.9-3.28C4.16,1.04,1.04,4.16,1.04,7.99c0,.39.23.72.57.88.02.12.03.25.06.37-.18.18-.3.42-.3.7,0,.11.02.21.06.31.94,2.74,3.53,4.71,6.58,4.71,3.84,0,6.96-3.12,6.96-6.96,0-.59-.08-1.16-.22-1.7ZM2.07,8.58c-.02-.19-.03-.39-.03-.58,0-3.29,2.67-5.96,5.96-5.96,2.23,0,4.17,1.23,5.2,3.05.05.18-.07.45-.3.75-.57-.73-1.45-1.21-2.45-1.21-1.72,0-3.12,1.4-3.12,3.11,0,.33.07.65.16.95-3.05.82-5.17.52-5.42-.11ZM12.56,7.75c0,1.17-.95,2.11-2.11,2.11s-2.12-.95-2.12-2.11.95-2.11,2.12-2.11,2.11.95,2.11,2.11ZM8,13.96c-2.6,0-4.81-1.68-5.62-4.01.5.16,1.11.24,1.79.24,1.15,0,2.49-.22,3.79-.59.57.76,1.47,1.26,2.49,1.26,1.72,0,3.11-1.4,3.11-3.11,0-.34-.07-.65-.17-.96.13-.13.24-.26.34-.39.14.51.22,1.04.22,1.6,0,3.29-2.67,5.96-5.96,5.96Z"/></g>');
|
|
@@ -8339,38 +9550,6 @@ createFluentIcon("BreakTangent", "20", '<g transform="scale(0.5)"><path d="M27.1
|
|
|
8339
9550
|
createFluentIcon("UnifyTangent", "20", '<g transform="scale(0.5)"><path d="M27.94,18.28a1.49,1.49,0,0,0-1.41,1h-5l-1.62-1.63-1.62,1.63h-5a1.5,1.5,0,1,0,0,1h5l1.62,1.62,1.62-1.62h5a1.5,1.5,0,1,0,1.41-2Z"/></g>');
|
|
8340
9551
|
createFluentIcon("StepTangent", "20", '<g transform="scale(0.5)"><path d="M29,16.71a1.5,1.5,0,1,0-2,1.41v5.67H11v1H28V18.12A1.51,1.51,0,0,0,29,16.71Z"/></g>');
|
|
8341
9552
|
|
|
8342
|
-
/**
|
|
8343
|
-
* Returns whether a rendering context is a scene context.
|
|
8344
|
-
* @param context The rendering context to test.
|
|
8345
|
-
* @returns Whether the context is a scene context.
|
|
8346
|
-
*/
|
|
8347
|
-
function IsSceneContext(context) {
|
|
8348
|
-
return getRenderingContextKind(context) === "scene";
|
|
8349
|
-
}
|
|
8350
|
-
/**
|
|
8351
|
-
* Creates an Explorer section containing the supplied scene entities.
|
|
8352
|
-
* @param id The stable section identifier.
|
|
8353
|
-
* @param displayName The section's display name.
|
|
8354
|
-
* @param entities The entities displayed by the section.
|
|
8355
|
-
* @param getEntityDisplayInfo Gets the display information for an entity.
|
|
8356
|
-
* @param entityIcon The optional icon component for the entities.
|
|
8357
|
-
* @returns The Explorer node description for the section.
|
|
8358
|
-
*/
|
|
8359
|
-
function CreateSceneExplorerSectionNode(id, displayName, entities, getEntityDisplayInfo, entityIcon) {
|
|
8360
|
-
return {
|
|
8361
|
-
id,
|
|
8362
|
-
kind: "group",
|
|
8363
|
-
getDisplayInfo: () => ({ name: displayName }),
|
|
8364
|
-
getChildren: () => entities.map((entity, index) => ({
|
|
8365
|
-
id: GetEntityId(entity).toString(),
|
|
8366
|
-
kind: "item",
|
|
8367
|
-
entity,
|
|
8368
|
-
icon: entityIcon,
|
|
8369
|
-
getDisplayInfo: () => getEntityDisplayInfo(entity, index),
|
|
8370
|
-
})),
|
|
8371
|
-
};
|
|
8372
|
-
}
|
|
8373
|
-
|
|
8374
9553
|
/**
|
|
8375
9554
|
* Gets the unique materials referenced by a scene's meshes.
|
|
8376
9555
|
* @param scene The scene to inspect.
|
|
@@ -8405,35 +9584,250 @@ const MaterialExplorerServiceDefinition = {
|
|
|
8405
9584
|
}),
|
|
8406
9585
|
};
|
|
8407
9586
|
|
|
9587
|
+
const NodeTopologyMarkers = new WeakMap();
|
|
9588
|
+
function GetNodeTopologyMarker(node) {
|
|
9589
|
+
const parent = IsSceneNode(node.parent) ? node.parent : null;
|
|
9590
|
+
const existing = NodeTopologyMarkers.get(node);
|
|
9591
|
+
if (existing?.parent === parent) {
|
|
9592
|
+
return existing.marker;
|
|
9593
|
+
}
|
|
9594
|
+
const marker = {};
|
|
9595
|
+
NodeTopologyMarkers.set(node, { parent, marker });
|
|
9596
|
+
return marker;
|
|
9597
|
+
}
|
|
9598
|
+
function CreateNodeDescription(node, watcherService) {
|
|
9599
|
+
return {
|
|
9600
|
+
id: GetEntityId(node).toString(),
|
|
9601
|
+
kind: "item",
|
|
9602
|
+
entity: node,
|
|
9603
|
+
icon: () => (IsMesh(node) ? jsx(MeshIcon, { color: tokens.colorPaletteBlueForeground2 }) : jsx(MyLocationRegular, { color: tokens.colorPaletteBlueForeground2 })),
|
|
9604
|
+
getDisplayInfo: () => CreateWatchedNameDisplayInfo(watcherService, node, () => node.name || (IsMesh(node) ? "Unnamed Mesh" : "Unnamed Transform Node")),
|
|
9605
|
+
getChildren: () => node.children.filter(IsSceneNode).map((child) => CreateNodeDescription(child, watcherService)),
|
|
9606
|
+
};
|
|
9607
|
+
}
|
|
9608
|
+
function IsNodeInScene(scene, node) {
|
|
9609
|
+
return GetSceneNodeRoots(scene).some((root) => root === node || IsSceneNodeDescendantOf(node, root));
|
|
9610
|
+
}
|
|
8408
9611
|
const MeshExplorerServiceDefinition = {
|
|
8409
|
-
friendlyName: "Babylon Lite
|
|
8410
|
-
consumes: [EngineExplorerServiceIdentity, WatcherServiceIdentity],
|
|
8411
|
-
factory: (engineExplorerService, watcherService) =>
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
9612
|
+
friendlyName: "Babylon Lite Scene Node Explorer",
|
|
9613
|
+
consumes: [EngineExplorerServiceIdentity, ExplorerServiceIdentity, WatcherServiceIdentity, SelectionServiceIdentity, EngineContextIdentity],
|
|
9614
|
+
factory: (engineExplorerService, explorerService, watcherService, selectionService, engineContext) => {
|
|
9615
|
+
const providerRegistration = engineExplorerService.addRenderingContextNodeProvider({
|
|
9616
|
+
order: 0,
|
|
9617
|
+
predicate: IsSceneContext,
|
|
9618
|
+
getNodes: (scene) => {
|
|
9619
|
+
return [
|
|
9620
|
+
{
|
|
9621
|
+
id: "nodes",
|
|
9622
|
+
kind: "group",
|
|
9623
|
+
getDisplayInfo: () => ({ name: "Nodes" }),
|
|
9624
|
+
getChildren: () => GetSceneNodeRoots(scene).map((node) => CreateNodeDescription(node, watcherService)),
|
|
9625
|
+
dragDropConfig: {
|
|
9626
|
+
canDrag: (entity) => IsSceneNode(entity) && IsNodeInScene(scene, entity),
|
|
9627
|
+
canDrop: (draggedEntity, targetEntity) => IsSceneNode(draggedEntity) &&
|
|
9628
|
+
IsNodeInScene(scene, draggedEntity) &&
|
|
9629
|
+
(targetEntity === null ||
|
|
9630
|
+
(IsSceneNode(targetEntity) &&
|
|
9631
|
+
IsNodeInScene(scene, targetEntity) &&
|
|
9632
|
+
draggedEntity !== targetEntity &&
|
|
9633
|
+
!IsSceneNodeDescendantOf(targetEntity, draggedEntity))) &&
|
|
9634
|
+
draggedEntity.parent !== targetEntity,
|
|
9635
|
+
onDrop: (draggedEntity, targetEntity) => {
|
|
9636
|
+
if (IsSceneNode(draggedEntity) && (targetEntity === null || IsSceneNode(targetEntity))) {
|
|
9637
|
+
setParent(draggedEntity, targetEntity);
|
|
9638
|
+
}
|
|
9639
|
+
},
|
|
9640
|
+
},
|
|
9641
|
+
},
|
|
9642
|
+
];
|
|
9643
|
+
},
|
|
9644
|
+
getSnapshot: (scene) => GetSceneNodeRoots(scene)
|
|
9645
|
+
.flatMap((root) => [root, ...GetNodeDescendants(root)])
|
|
9646
|
+
.flatMap((node) => [node, GetNodeTopologyMarker(node)]),
|
|
9647
|
+
});
|
|
9648
|
+
const visibilityRegistration = explorerService.addItemCommand({
|
|
9649
|
+
predicate: (entity) => IsSceneNode(entity) && GetOwningScenes(engineContext, entity).length > 0,
|
|
9650
|
+
order: 1100,
|
|
9651
|
+
getCommand: (node) => {
|
|
9652
|
+
const onChange = new Observable();
|
|
9653
|
+
const visibilityWatcher = watcherService.watchValue(() => node.visible !== false, () => onChange.notifyObservers());
|
|
9654
|
+
return {
|
|
9655
|
+
type: "toggle",
|
|
9656
|
+
mode: "contextMenu",
|
|
9657
|
+
get displayName() {
|
|
9658
|
+
return node.visible === false ? "Show Node" : "Hide Node";
|
|
9659
|
+
},
|
|
9660
|
+
icon: () => (node.visible === false ? jsx(EyeOffRegular, {}) : jsx(EyeRegular, {})),
|
|
9661
|
+
get isEnabled() {
|
|
9662
|
+
return node.visible !== false;
|
|
9663
|
+
},
|
|
9664
|
+
set isEnabled(visible) {
|
|
9665
|
+
setSubtreeVisible(node, visible);
|
|
9666
|
+
},
|
|
9667
|
+
onChange,
|
|
9668
|
+
dispose: () => {
|
|
9669
|
+
visibilityWatcher.dispose();
|
|
9670
|
+
onChange.clear();
|
|
9671
|
+
},
|
|
9672
|
+
};
|
|
9673
|
+
},
|
|
9674
|
+
});
|
|
9675
|
+
const removeRegistration = explorerService.addItemCommand({
|
|
9676
|
+
predicate: (entity) => IsSceneNode(entity) && GetOwningScenes(engineContext, entity).length === 1,
|
|
9677
|
+
order: 10000,
|
|
9678
|
+
getCommand: (node) => ({
|
|
9679
|
+
type: "action",
|
|
9680
|
+
mode: "contextMenu",
|
|
9681
|
+
displayName: "Remove from Scene",
|
|
9682
|
+
icon: DeleteRegular,
|
|
9683
|
+
hotKey: { keyCode: "Delete" },
|
|
9684
|
+
execute: () => {
|
|
9685
|
+
const owningScenes = GetOwningScenes(engineContext, node);
|
|
9686
|
+
const [scene] = owningScenes;
|
|
9687
|
+
if (scene && owningScenes.length === 1) {
|
|
9688
|
+
const selectedEntity = selectionService.selectedEntity;
|
|
9689
|
+
const selectionWasRemoved = selectedEntity === node || (IsSceneNode(selectedEntity) && IsSceneNodeDescendantOf(selectedEntity, node));
|
|
9690
|
+
if (node.parent) {
|
|
9691
|
+
setParent(node, null);
|
|
9692
|
+
}
|
|
9693
|
+
removeFromScene(scene, node);
|
|
9694
|
+
ClearRemovedSelection(selectionService, engineContext, selectionWasRemoved);
|
|
9695
|
+
}
|
|
9696
|
+
},
|
|
9697
|
+
}),
|
|
9698
|
+
});
|
|
9699
|
+
return {
|
|
9700
|
+
dispose: () => {
|
|
9701
|
+
removeRegistration.dispose();
|
|
9702
|
+
visibilityRegistration.dispose();
|
|
9703
|
+
providerRegistration.dispose();
|
|
9704
|
+
},
|
|
9705
|
+
};
|
|
9706
|
+
},
|
|
9707
|
+
};
|
|
9708
|
+
function GetNodeDescendants(node) {
|
|
9709
|
+
return node.children.filter(IsSceneNode).flatMap((child) => [child, ...GetNodeDescendants(child)]);
|
|
9710
|
+
}
|
|
9711
|
+
function GetOwningScenes(engineContext, node) {
|
|
9712
|
+
return GetSceneContexts(engineContext.engine).filter((scene) => GetSceneNodeRoots(scene).some((root) => root === node || IsSceneNodeDescendantOf(node, root)));
|
|
9713
|
+
}
|
|
9714
|
+
|
|
9715
|
+
const ShadowGeneratorIcon = () => jsx(WeatherMoonRegular, { color: tokens.colorPaletteYellowForeground2 });
|
|
9716
|
+
const ShadowGeneratorExplorerServiceDefinition = {
|
|
9717
|
+
friendlyName: "Babylon Lite Shadow Generator Explorer",
|
|
9718
|
+
consumes: [EngineExplorerServiceIdentity, ExplorerServiceIdentity, SelectionServiceIdentity, EngineContextIdentity],
|
|
9719
|
+
factory: (engineExplorerService, explorerService, selectionService, engineContext) => {
|
|
9720
|
+
const providerRegistration = engineExplorerService.addRenderingContextNodeProvider({
|
|
9721
|
+
order: 30,
|
|
9722
|
+
predicate: IsSceneContext,
|
|
9723
|
+
getNodes: (scene) => {
|
|
9724
|
+
return [
|
|
9725
|
+
CreateSceneExplorerSectionNode("shadow-generators", "Shadow Generators", scene.shadowGenerators, (shadowGenerator) => ({ name: GetShadowGeneratorDisplayName(scene, shadowGenerator) }), ShadowGeneratorIcon),
|
|
9726
|
+
];
|
|
9727
|
+
},
|
|
9728
|
+
getSnapshot: (scene) => scene.shadowGenerators,
|
|
9729
|
+
});
|
|
9730
|
+
const removeRegistration = explorerService.addItemCommand({
|
|
9731
|
+
predicate: (entity) => typeof entity === "object" &&
|
|
9732
|
+
entity !== null &&
|
|
9733
|
+
GetSceneContexts(engineContext.engine).filter((scene) => scene.shadowGenerators.some((shadowGenerator) => shadowGenerator === entity)).length === 1,
|
|
9734
|
+
order: 10000,
|
|
9735
|
+
getCommand: (shadowGenerator) => ({
|
|
9736
|
+
type: "action",
|
|
9737
|
+
mode: "contextMenu",
|
|
9738
|
+
displayName: "Remove from Scene",
|
|
9739
|
+
icon: DeleteRegular,
|
|
9740
|
+
hotKey: { keyCode: "Delete" },
|
|
9741
|
+
execute: () => {
|
|
9742
|
+
const owningScenes = GetSceneContexts(engineContext.engine).filter((candidate) => candidate.shadowGenerators.includes(shadowGenerator));
|
|
9743
|
+
if (owningScenes.length === 1) {
|
|
9744
|
+
if (selectionService.selectedEntity === shadowGenerator) {
|
|
9745
|
+
selectionService.selectedEntity = null;
|
|
9746
|
+
}
|
|
9747
|
+
removeFromScene(owningScenes[0], shadowGenerator);
|
|
9748
|
+
}
|
|
9749
|
+
},
|
|
9750
|
+
}),
|
|
9751
|
+
});
|
|
9752
|
+
return {
|
|
9753
|
+
dispose: () => {
|
|
9754
|
+
removeRegistration.dispose();
|
|
9755
|
+
providerRegistration.dispose();
|
|
9756
|
+
},
|
|
9757
|
+
};
|
|
9758
|
+
},
|
|
8419
9759
|
};
|
|
8420
9760
|
|
|
9761
|
+
function CreateRenderingLayerExplorerServiceDefinition(options) {
|
|
9762
|
+
const { friendlyName, contextKind, layerTypeName, icon } = options;
|
|
9763
|
+
return {
|
|
9764
|
+
friendlyName,
|
|
9765
|
+
consumes: [EngineExplorerServiceIdentity, ExplorerServiceIdentity, WatcherServiceIdentity, EngineContextIdentity],
|
|
9766
|
+
factory: (engineExplorerService, explorerService, watcherService, engineContext) => {
|
|
9767
|
+
const getOwners = (layer) => GetRenderingLayerOwners(engineContext.engine, contextKind, layer);
|
|
9768
|
+
const providerRegistration = engineExplorerService.addRenderingContextNodeProvider({
|
|
9769
|
+
predicate: (context) => getRenderingContextKind(context) === contextKind,
|
|
9770
|
+
getNodes: (context) => GetOrderedRenderingLayers(context.layers).map((layer, index) => ({
|
|
9771
|
+
id: `${contextKind}-layer-${GetEntityId(layer)}`,
|
|
9772
|
+
kind: "item",
|
|
9773
|
+
entity: layer,
|
|
9774
|
+
icon,
|
|
9775
|
+
getDisplayInfo: () => ({ name: `${layerTypeName} ${index + 1}` }),
|
|
9776
|
+
})),
|
|
9777
|
+
getSnapshot: (context) => GetRenderingLayerSnapshot(context.layers),
|
|
9778
|
+
});
|
|
9779
|
+
const visibilityRegistration = explorerService.addItemCommand({
|
|
9780
|
+
predicate: (entity) => typeof entity === "object" && entity !== null && getOwners(entity).length > 0,
|
|
9781
|
+
order: 1100,
|
|
9782
|
+
getCommand: (layer) => {
|
|
9783
|
+
const onChange = new Observable();
|
|
9784
|
+
const visibilityWatcher = watcherService.watchProperty(layer, "visible", () => onChange.notifyObservers());
|
|
9785
|
+
return {
|
|
9786
|
+
type: "toggle",
|
|
9787
|
+
mode: "contextMenu",
|
|
9788
|
+
get displayName() {
|
|
9789
|
+
return layer.visible ? `Hide ${layerTypeName}` : `Show ${layerTypeName}`;
|
|
9790
|
+
},
|
|
9791
|
+
icon: () => (layer.visible ? jsx(EyeRegular, {}) : jsx(EyeOffRegular, {})),
|
|
9792
|
+
get isEnabled() {
|
|
9793
|
+
return layer.visible;
|
|
9794
|
+
},
|
|
9795
|
+
set isEnabled(visible) {
|
|
9796
|
+
layer.visible = visible;
|
|
9797
|
+
},
|
|
9798
|
+
onChange,
|
|
9799
|
+
dispose: () => {
|
|
9800
|
+
visibilityWatcher.dispose();
|
|
9801
|
+
onChange.clear();
|
|
9802
|
+
},
|
|
9803
|
+
};
|
|
9804
|
+
},
|
|
9805
|
+
});
|
|
9806
|
+
return {
|
|
9807
|
+
dispose: () => {
|
|
9808
|
+
visibilityRegistration.dispose();
|
|
9809
|
+
providerRegistration.dispose();
|
|
9810
|
+
},
|
|
9811
|
+
};
|
|
9812
|
+
},
|
|
9813
|
+
};
|
|
9814
|
+
}
|
|
9815
|
+
|
|
9816
|
+
const SpriteLayerIcon = () => jsx(LayerDiagonalPersonRegular, { color: tokens.colorPalettePeachForeground2 });
|
|
9817
|
+
const SpriteLayerExplorerServiceDefinition = CreateRenderingLayerExplorerServiceDefinition({
|
|
9818
|
+
friendlyName: "Babylon Lite Sprite Layer Explorer",
|
|
9819
|
+
contextKind: "sprite-renderer",
|
|
9820
|
+
layerTypeName: "Sprite Layer",
|
|
9821
|
+
icon: SpriteLayerIcon,
|
|
9822
|
+
});
|
|
9823
|
+
|
|
8421
9824
|
const TextLayerIcon = () => jsx(TextTRegular, {});
|
|
8422
|
-
const TextLayerExplorerServiceDefinition = {
|
|
9825
|
+
const TextLayerExplorerServiceDefinition = CreateRenderingLayerExplorerServiceDefinition({
|
|
8423
9826
|
friendlyName: "Babylon Lite Text Layer Explorer",
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
id: `text-layer-${GetEntityId(layer)}`,
|
|
8429
|
-
kind: "item",
|
|
8430
|
-
entity: layer,
|
|
8431
|
-
icon: TextLayerIcon,
|
|
8432
|
-
getDisplayInfo: () => ({ name: `Layer ${index + 1}` }),
|
|
8433
|
-
})),
|
|
8434
|
-
getSnapshot: (renderer) => renderer.layers,
|
|
8435
|
-
}),
|
|
8436
|
-
};
|
|
9827
|
+
contextKind: "text-renderer",
|
|
9828
|
+
layerTypeName: "Text Layer",
|
|
9829
|
+
icon: TextLayerIcon,
|
|
9830
|
+
});
|
|
8437
9831
|
|
|
8438
9832
|
function GetTextureDisplayName(texture, index) {
|
|
8439
9833
|
return `Texture ${index + 1} (${texture.width} x ${texture.height})`;
|
|
@@ -8489,16 +9883,25 @@ function ShowInspector(engine, options = {}) {
|
|
|
8489
9883
|
watcherServiceDefinition,
|
|
8490
9884
|
EngineExplorerServiceDefinition,
|
|
8491
9885
|
MeshExplorerServiceDefinition,
|
|
9886
|
+
CameraExplorerServiceDefinition,
|
|
9887
|
+
LightExplorerServiceDefinition,
|
|
9888
|
+
ShadowGeneratorExplorerServiceDefinition,
|
|
8492
9889
|
MaterialExplorerServiceDefinition,
|
|
8493
9890
|
TextureExplorerServiceDefinition,
|
|
8494
9891
|
TextLayerExplorerServiceDefinition,
|
|
9892
|
+
SpriteLayerExplorerServiceDefinition,
|
|
8495
9893
|
PropertiesServiceDefinition,
|
|
8496
9894
|
EnginePropertiesServiceDefinition,
|
|
8497
9895
|
RenderingContextPropertiesServiceDefinition,
|
|
9896
|
+
SceneNodePropertiesServiceDefinition,
|
|
8498
9897
|
MeshPropertiesServiceDefinition,
|
|
9898
|
+
CameraPropertiesServiceDefinition,
|
|
9899
|
+
LightPropertiesServiceDefinition,
|
|
9900
|
+
ShadowGeneratorPropertiesServiceDefinition,
|
|
8499
9901
|
MaterialPropertiesServiceDefinition,
|
|
8500
9902
|
TexturePropertiesServiceDefinition,
|
|
8501
9903
|
TextLayerPropertiesServiceDefinition,
|
|
9904
|
+
SpriteLayerPropertiesServiceDefinition,
|
|
8502
9905
|
SettingsServiceDefinition,
|
|
8503
9906
|
watcherSettingsServiceDefinition,
|
|
8504
9907
|
ShellSettingsServiceDefinition,
|
|
@@ -8515,4 +9918,4 @@ function ShowInspector(engine, options = {}) {
|
|
|
8515
9918
|
}
|
|
8516
9919
|
|
|
8517
9920
|
export { PropertyLine as $, Accordion as A, BooleanBadgePropertyLine as B, Checkbox as C, DraggableLine as D, EngineContextIdentity as E, FileUploadLine as F, GetPropertyDescriptor as G, HexPropertyLine as H, InfoLabel as I, MakeModularBridge as J, MakeModularTool as K, Link as L, MakeDialogTeachingMoment as M, MakePopoverTeachingMoment as N, MakeTeachingMoment as O, MessageBar as P, NumberDropdown as Q, NumberDropdownPropertyLine as R, ShellServiceIdentity as S, NumberInputPropertyLine as T, ObservableCollection as U, Pane as V, PlaceholderPropertyLine as W, Popover as X, PositionedPopover as Y, PropertiesServiceIdentity as Z, PropertyContext as _, AccordionSection as a, SearchBar as a0, SearchBox as a1, SelectionServiceDefinition as a2, SelectionServiceIdentity as a3, SettingsServiceIdentity as a4, SettingsStore as a5, SettingsStoreIdentity as a6, ShowInspector as a7, SidePaneContainer as a8, Slider as a9, useInterceptObservable as aA, useKeyListener as aB, useKeyState as aC, useObservableCollection as aD, useObservableState as aE, useOrderedObservableCollection as aF, usePollingObservable as aG, usePropertyChangedNotifier as aH, useResource as aI, useTheme as aJ, useThemeMode as aK, useToast as aL, SpinButton as aa, SpinButtonPropertyLine as ab, StringDropdown as ac, StringDropdownPropertyLine as ad, StringifiedPropertyLine as ae, Switch as af, SwitchPropertyLine as ag, SyncedSliderInput as ah, SyncedSliderPropertyLine as ai, TeachingMoment as aj, TextAreaPropertyLine as ak, TextInput as al, TextInputPropertyLine as am, TextPropertyLine as an, Textarea as ao, Theme as ap, ThemeServiceIdentity as aq, ToastProvider as ar, ToggleButton as as, Tooltip as at, UploadButton as au, WatcherServiceIdentity as av, useAngleConverters as aw, useAsyncResource as ax, useEventListener as ay, useEventfulState as az, AccordionSectionItem as b, BridgeCommandRegistryIdentity as c, BuiltInsExtensionFeed as d, Button as e, ButtonLine as f, CheckboxPropertyLine as g, ChildWindow as h, Collapse as i, ComboBox as j, ComboBoxPropertyLine as k, ConstructorFactory as l, Dropdown as m, EngineExplorerServiceIdentity as n, EntitySelector as o, ErrorBoundary as p, ExplorerServiceIdentity as q, ExtensibleAccordion as r, InterceptFunction as s, InterceptProperty as t, useExtensionManager as u, IsPropertyReadonly as v, LineContainer as w, LinkPropertyLine as x, List as y, MakeLazyComponent as z };
|
|
8518
|
-
//# sourceMappingURL=index-
|
|
9921
|
+
//# sourceMappingURL=index-D8vFySa7.js.map
|