@babylonjs/inspector 8.32.0-preview → 8.32.1-preview

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -3,9 +3,9 @@ import { useMemo, useEffect, useState, useRef, useCallback, forwardRef, createCo
3
3
  import { Color3, Color4 } from '@babylonjs/core/Maths/math.color.js';
4
4
  import { Vector3, Quaternion, Matrix, Vector2, Vector4, TmpVectors } from '@babylonjs/core/Maths/math.vector.js';
5
5
  import { Observable } from '@babylonjs/core/Misc/observable.js';
6
- import { makeStyles, ToggleButton as ToggleButton$1, Button as Button$1, tokens, Link, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, Body1, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, mergeClasses, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, createLightTheme, createDarkTheme, FluentProvider, Toolbar as Toolbar$1, Tooltip, ToolbarRadioButton, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, treeItemLevelToken, Switch as Switch$1, PresenceBadge, Spinner, Dialog, DialogTrigger, DialogSurface, DialogBody, DialogTitle, TabList, Tab, DialogContent, SplitButton, MenuItemRadio, DialogActions, List as List$1, ListItem, Badge, useId, Input, SpinButton as SpinButton$1, Slider, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, Dropdown as Dropdown$1, Option, Popover, PopoverTrigger, ColorSwatch, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, Textarea as Textarea$1, ToolbarButton, useComboboxFilter, Combobox, Field } from '@fluentui/react-components';
6
+ import { makeStyles, ToggleButton as ToggleButton$1, Button as Button$1, tokens, Link, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, mergeClasses, Body1, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, createLightTheme, createDarkTheme, FluentProvider, Toolbar as Toolbar$1, Tooltip, ToolbarRadioButton, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, treeItemLevelToken, Switch as Switch$1, PresenceBadge, Spinner, Dialog, DialogTrigger, DialogSurface, DialogBody, DialogTitle, TabList, Tab, DialogContent, SplitButton, MenuItemRadio, DialogActions, List as List$1, ListItem, Badge, useId, Input, SpinButton as SpinButton$1, Slider, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, Dropdown as Dropdown$1, Option, Popover, PopoverTrigger, ColorSwatch, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, Textarea as Textarea$1, ToolbarButton, useComboboxFilter, Combobox, Field } from '@fluentui/react-components';
7
7
  export { Link } from '@fluentui/react-components';
8
- import { ChevronCircleRight20Regular, ChevronCircleDown20Regular, CopyRegular, PanelLeftExpandRegular, PanelLeftContractRegular, PanelRightExpandRegular, PanelRightContractRegular, DocumentTextRegular, createFluentIcon, FilterRegular, GlobeRegular, ArrowExpandAllRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, DataBarHorizontalRegular, WrenchRegular, AppsAddInRegular, DismissRegular, WeatherSunnyRegular, WeatherMoonRegular, ErrorCircleRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, DeleteRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, StopFilled, PlayFilled, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, PlayRegular, AppGenericRegular, MyLocationRegular, CameraRegular, LightbulbRegular, BorderOutsideRegular, BorderNoneRegular, EyeRegular, EyeOffRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, DeleteFilled } from '@fluentui/react-icons';
8
+ import { ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, Copy20Regular, PanelLeftExpandRegular, PanelLeftContractRegular, PanelRightExpandRegular, PanelRightContractRegular, DocumentTextRegular, createFluentIcon, FilterRegular, GlobeRegular, ArrowExpandAllRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, DataBarHorizontalRegular, WrenchRegular, AppsAddInRegular, DismissRegular, WeatherSunnyRegular, WeatherMoonRegular, ErrorCircleRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, CopyRegular, DeleteRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, StopFilled, PlayFilled, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, PlayRegular, AppGenericRegular, MyLocationRegular, CameraRegular, LightbulbRegular, BorderOutsideRegular, BorderNoneRegular, EyeRegular, EyeOffRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, DeleteFilled } from '@fluentui/react-icons';
9
9
  import { Collapse as Collapse$1 } from '@fluentui/react-motion-components-preview';
10
10
  import '@babylonjs/core/Misc/typeStore.js';
11
11
  import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
@@ -635,7 +635,7 @@ function copyCommandToClipboard(strCommand) {
635
635
  element.remove();
636
636
  }
637
637
 
638
- const ToolContext = createContext({ useFluent: false, disableCopy: false, toolName: "" });
638
+ const ToolContext = createContext({ useFluent: false, disableCopy: false, toolName: "", size: undefined });
639
639
 
640
640
  /**
641
641
  * Toggles between two states using a button with icons.
@@ -647,6 +647,7 @@ const ToolContext = createContext({ useFluent: false, disableCopy: false, toolNa
647
647
  const ToggleButton = (props) => {
648
648
  ToggleButton.displayName = "ToggleButton";
649
649
  const { value, onChange, title, appearance = "subtle" } = props;
650
+ const { size } = useContext(ToolContext);
650
651
  const [checked, setChecked] = useState(value);
651
652
  const toggle = useCallback(() => {
652
653
  setChecked((prev) => {
@@ -658,23 +659,27 @@ const ToggleButton = (props) => {
658
659
  useEffect(() => {
659
660
  setChecked(props.value);
660
661
  }, [props.value]);
661
- return (jsx(ToggleButton$1, { title: title, icon: checked ? jsx(props.checkedIcon, {}) : props.uncheckedIcon ? jsx(props.uncheckedIcon, {}) : jsx(props.checkedIcon, {}), appearance: appearance, checked: checked, onClick: toggle }));
662
+ return (jsx(ToggleButton$1, { title: title, size: size, icon: checked ? jsx(props.checkedIcon, {}) : props.uncheckedIcon ? jsx(props.uncheckedIcon, {}) : jsx(props.checkedIcon, {}), appearance: appearance, checked: checked, onClick: toggle }));
662
663
  };
663
664
 
664
665
  const Button = (props) => {
665
666
  Button.displayName = "Button";
667
+ const { size } = useContext(ToolContext);
666
668
  // eslint-disable-next-line @typescript-eslint/naming-convention
667
669
  const { icon: Icon, label, ...buttonProps } = props;
668
- return (jsx(Button$1, { iconPosition: "after", ...buttonProps, icon: Icon && jsx(Icon, {}), children: label && props.label }));
670
+ return (jsx(Button$1, { iconPosition: "after", ...buttonProps, size: size, icon: Icon && jsx(Icon, {}), children: label && props.label }));
669
671
  };
670
672
 
671
673
  const CustomTokens = {
672
674
  inputWidth: "150px",
673
- lineHeight: "36px",
675
+ lineHeight: tokens.lineHeightHero700, // 36px
676
+ lineHeightSmall: tokens.lineHeightBase500, // 28px
677
+ dividerGap: tokens.fontSizeBase100, // "10px",
678
+ dividerGapSmall: tokens.borderRadiusMedium, // 4px",
674
679
  labelMinWidth: "50px",
675
680
  sliderMinWidth: "30px",
676
681
  sliderMaxWidth: "80px",
677
- rightAlignOffset: "-8px",
682
+ rightAlignOffset: `-${tokens.borderRadiusXLarge}`, // -8px
678
683
  };
679
684
  const UniformWidthStyling = { width: CustomTokens.inputWidth, boxSizing: "border-box" };
680
685
  const useInputStyles$1 = makeStyles({
@@ -686,7 +691,6 @@ const useInputStyles$1 = makeStyles({
686
691
  display: "flex",
687
692
  flexDirection: "column",
688
693
  justifyContent: "center", // align items vertically
689
- gap: "4px",
690
694
  },
691
695
  });
692
696
  function HandleOnBlur(event) {
@@ -731,21 +735,11 @@ function CalculatePrecision(value) {
731
735
  return 0;
732
736
  }
733
737
  const HEX_REGEX = RegExp(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/);
734
- function ColorHexValidatorFn(val) {
738
+ function ValidateColorHex(val) {
735
739
  return val != "" && HEX_REGEX.test(val);
736
740
  }
737
741
 
738
742
  const usePropertyLineStyles = makeStyles({
739
- container: {
740
- width: "100%",
741
- display: "flex",
742
- flexDirection: "column", // Stack line + expanded content
743
- minHeight: CustomTokens.lineHeight,
744
- boxSizing: "border-box",
745
- justifyContent: "center",
746
- paddingTop: tokens.spacingVerticalXXS,
747
- paddingBottom: tokens.spacingVerticalXXS,
748
- },
749
743
  baseLine: {
750
744
  display: "flex",
751
745
  alignItems: "center",
@@ -793,11 +787,11 @@ const usePropertyLineStyles = makeStyles({
793
787
  */
794
788
  const PropertyLine = forwardRef((props, ref) => {
795
789
  PropertyLine.displayName = "PropertyLine";
790
+ const { disableCopy, size } = useContext(ToolContext);
796
791
  const classes = usePropertyLineStyles();
797
792
  const { label, onCopy, expandedContent, children, nullable, ignoreNullable } = props;
798
793
  const [expanded, setExpanded] = useState("expandByDefault" in props ? props.expandByDefault : false);
799
794
  const cachedVal = useRef(nullable ? props.value : null);
800
- const { disableCopy } = useContext(ToolContext);
801
795
  const description = props.docLink ? jsx(Link, { href: props.docLink, children: props.description ?? "Docs" }) : props.description;
802
796
  // Process children to handle nullable state -- creating component in disabled state with default value in lieu of null value
803
797
  const processedChildren = (nullable || ignoreNullable) && isValidElement(children)
@@ -808,7 +802,7 @@ const PropertyLine = forwardRef((props, ref) => {
808
802
  defaultValue: undefined, // Don't pass defaultValue to children as there is no guarantee how this will be used and we can't mix controlled + uncontrolled state
809
803
  })
810
804
  : children;
811
- return (jsxs(LineContainer, { ref: ref, children: [jsxs("div", { className: classes.baseLine, children: [jsx(InfoLabel$1, { className: classes.infoLabel, label: { className: classes.labelSlot }, info: description ? jsx("div", { className: classes.infoPopup, children: description }) : undefined, title: label, children: jsx(Body1Strong, { className: classes.labelText, children: label }) }), jsxs("div", { className: classes.rightContent, children: [expandedContent && (jsx(ToggleButton, { title: "Expand/Collapse property", appearance: "transparent", checkedIcon: ChevronCircleDown20Regular, uncheckedIcon: ChevronCircleRight20Regular, value: expanded === true, onChange: setExpanded })), nullable && !ignoreNullable && (
805
+ return (jsxs(LineContainer, { ref: ref, children: [jsxs("div", { className: classes.baseLine, children: [jsx(InfoLabel$1, { size: size, className: classes.infoLabel, label: { className: classes.labelSlot }, info: description ? jsx("div", { className: classes.infoPopup, children: description }) : undefined, title: label, children: jsx(Body1Strong, { className: classes.labelText, children: label }) }), jsxs("div", { className: classes.rightContent, children: [expandedContent && (jsx(ToggleButton, { title: "Expand/Collapse property", appearance: "transparent", checkedIcon: size === "small" ? ChevronCircleDown16Regular : ChevronCircleDown20Regular, uncheckedIcon: size === "small" ? ChevronCircleRight16Regular : ChevronCircleRight20Regular, value: expanded === true, onChange: setExpanded })), nullable && !ignoreNullable && (
812
806
  // If this is a nullableProperty and ignoreNullable was not sent, display a checkbox used to toggle null ('checked' means 'non null')
813
807
  jsx(Checkbox$1, { checked: !(props.value == null), onChange: (_, data) => {
814
808
  if (data.checked) {
@@ -820,11 +814,27 @@ const PropertyLine = forwardRef((props, ref) => {
820
814
  cachedVal.current = props.value;
821
815
  props.onChange(null);
822
816
  }
823
- }, title: "Toggle null state" })), processedChildren, onCopy && !disableCopy && (jsx(Button, { className: classes.copy, title: "Copy to clipboard", appearance: "transparent", icon: CopyRegular, onClick: () => copyCommandToClipboard(onCopy()) }))] })] }), expandedContent && (jsx(Collapse, { visible: !!expanded, children: jsx("div", { className: classes.expandedContentDiv, children: expandedContent }) }))] }));
817
+ }, title: "Toggle null state" })), processedChildren, onCopy && !disableCopy && (jsx(Button, { className: classes.copy, title: "Copy to clipboard", appearance: "transparent", icon: size === "small" ? Copy16Regular : Copy20Regular, onClick: () => copyCommandToClipboard(onCopy()) }))] })] }), expandedContent && (jsx(Collapse, { visible: !!expanded, children: jsx("div", { className: classes.expandedContentDiv, children: expandedContent }) }))] }));
818
+ });
819
+ const useLineStyles = makeStyles({
820
+ container: {
821
+ width: "100%",
822
+ display: "flex",
823
+ flexDirection: "column", // Stack line + expanded content
824
+ minHeight: CustomTokens.lineHeight,
825
+ boxSizing: "border-box",
826
+ justifyContent: "center",
827
+ paddingTop: tokens.spacingVerticalXXS,
828
+ paddingBottom: tokens.spacingVerticalXXS,
829
+ },
830
+ containerSmall: {
831
+ minHeight: CustomTokens.lineHeightSmall,
832
+ },
824
833
  });
825
834
  const LineContainer = forwardRef((props, ref) => {
826
- const classes = usePropertyLineStyles();
827
- return (jsx("div", { ref: ref, className: classes.container, ...props, children: props.children }));
835
+ const { size } = useContext(ToolContext);
836
+ const classes = useLineStyles();
837
+ return (jsx("div", { ref: ref, className: mergeClasses(classes.container, size == "small" ? classes.containerSmall : undefined), ...props, children: props.children }));
828
838
  });
829
839
  const PlaceholderPropertyLine = (props) => {
830
840
  return (jsx(PropertyLine, { ...props, children: jsx(Body1, { children: props.value }) }));
@@ -865,8 +875,12 @@ const useStyles$i = makeStyles({
865
875
  height: "100%",
866
876
  },
867
877
  divider: {
868
- paddingTop: "10px",
869
- paddingBottom: "10px",
878
+ paddingTop: CustomTokens.dividerGap,
879
+ paddingBottom: CustomTokens.dividerGap,
880
+ },
881
+ dividerSmall: {
882
+ paddingTop: CustomTokens.dividerGapSmall,
883
+ paddingBottom: CustomTokens.dividerGapSmall,
870
884
  },
871
885
  panelDiv: {
872
886
  display: "flex",
@@ -882,6 +896,7 @@ const AccordionSection = (props) => {
882
896
  const Accordion = (props) => {
883
897
  Accordion.displayName = "Accordion";
884
898
  const classes = useStyles$i();
899
+ const { size } = useContext(ToolContext);
885
900
  const { children, ...rest } = props;
886
901
  const validChildren = useMemo(() => {
887
902
  return (Children.map(children, (child) => {
@@ -923,10 +938,69 @@ const Accordion = (props) => {
923
938
  }
924
939
  }, []);
925
940
  return (jsx(Accordion$1, { className: classes.accordion, collapsible: true, multiple: true, onToggle: onToggle, openItems: openItems, ...rest, children: validChildren.map((child, index) => {
926
- return (jsxs(AccordionItem, { value: child.title, children: [jsx(AccordionHeader, { children: jsx(Subtitle2Stronger, { children: child.title }) }), jsx(AccordionPanel, { children: jsx("div", { className: classes.panelDiv, children: child.content }) }), index < validChildren.length - 1 && jsx(Divider, { inset: true, className: classes.divider })] }, child.content.key));
941
+ return (jsxs(AccordionItem, { value: child.title, children: [jsx(AccordionHeader, { size: size, children: jsx(Subtitle2Stronger, { children: child.title }) }), jsx(AccordionPanel, { children: jsx("div", { className: classes.panelDiv, children: child.content }) }), index < validChildren.length - 1 && jsx(Divider, { inset: true, className: size === "small" ? classes.dividerSmall : classes.divider })] }, child.content.key));
927
942
  }) }));
928
943
  };
929
944
 
945
+ const CompactModeStorageKey = "Babylon/Settings/IsCompactMode";
946
+ function useSetting(storageKey, defaultValue) {
947
+ const [value, setValue, resetValue] = useLocalStorage(storageKey, defaultValue);
948
+ if (!localStorage.getItem(storageKey)) {
949
+ localStorage.setItem(storageKey, JSON.stringify(value));
950
+ }
951
+ return [value, setValue, resetValue];
952
+ }
953
+ /**
954
+ * Gets the compact mode setting.
955
+ * @returns A tuple containing the current compact mode value, a function to update it, and a function to reset it.
956
+ */
957
+ function useCompactMode() {
958
+ return useSetting(CompactModeStorageKey, !matchMedia("(pointer: coarse)").matches);
959
+ }
960
+ const RadiansToDegrees = 180 / Math.PI;
961
+ function WrapAngle(angle) {
962
+ angle %= Math.PI * 2;
963
+ if (angle < 0) {
964
+ angle += Math.PI * 2;
965
+ }
966
+ return angle;
967
+ }
968
+ /**
969
+ * Gets functions used to convert to/from display values for angles based on the current settings.
970
+ * @param settings The settings context to use for determining if angles should be displayed in degrees or radians.
971
+ * @returns A tuple containing the functions to convert to and from display values.
972
+ */
973
+ function useAngleConverters(settings) {
974
+ const useDegrees = useObservableState(() => settings.useDegrees, settings.settingsChangedObservable);
975
+ const toDisplayValue = useCallback((angle, wrap = false) => {
976
+ if (wrap) {
977
+ angle = WrapAngle(angle);
978
+ }
979
+ return useDegrees ? angle * RadiansToDegrees : angle;
980
+ }, [useDegrees]);
981
+ const fromDisplayValue = useCallback((angle, wrap = false) => {
982
+ angle = useDegrees ? angle / RadiansToDegrees : angle;
983
+ if (wrap) {
984
+ angle = WrapAngle(angle);
985
+ }
986
+ return angle;
987
+ }, [useDegrees]);
988
+ return [toDisplayValue, fromDisplayValue, useDegrees];
989
+ }
990
+
991
+ const CompactModeContextProvider = (props) => {
992
+ const [compactMode] = useCompactMode();
993
+ const toolsContext = useMemo(() => {
994
+ return {
995
+ toolName: "",
996
+ size: compactMode ? "small" : "medium",
997
+ disableCopy: false,
998
+ useFluent: true,
999
+ };
1000
+ }, [compactMode]);
1001
+ return jsx(ToolContext.Provider, { value: toolsContext, children: props.children });
1002
+ };
1003
+
930
1004
  function AsReadonlyArray(array) {
931
1005
  return array;
932
1006
  }
@@ -1023,9 +1097,9 @@ function ExtensibleAccordion(props) {
1023
1097
  })
1024
1098
  .filter((section) => section !== null);
1025
1099
  }, [mergedSections, mergedSectionContent, context]);
1026
- return (jsx("div", { className: classes.rootDiv, children: visibleSections.length > -1 && (jsxs(Accordion, { children: [...visibleSections.map((section) => {
1027
- return (jsx(AccordionSection, { title: section.identity, collapseByDefault: section.collapseByDefault, children: section.components }, section.identity));
1028
- })] })) }));
1100
+ return (jsx("div", { className: classes.rootDiv, children: visibleSections.length > -1 && (jsx(CompactModeContextProvider, { children: jsxs(Accordion, { children: [...visibleSections.map((section) => {
1101
+ return (jsx(AccordionSection, { title: section.identity, collapseByDefault: section.collapseByDefault, children: section.components }, section.identity));
1102
+ })] }) })) }));
1029
1103
  }
1030
1104
 
1031
1105
  const useStyles$g = makeStyles({
@@ -1176,37 +1250,6 @@ function useAsyncResource(factory) {
1176
1250
  return resource;
1177
1251
  }
1178
1252
 
1179
- const RadiansToDegrees = 180 / Math.PI;
1180
- function WrapAngle(angle) {
1181
- angle %= Math.PI * 2;
1182
- if (angle < 0) {
1183
- angle += Math.PI * 2;
1184
- }
1185
- return angle;
1186
- }
1187
- /**
1188
- * Gets functions used to convert to/from display values for angles based on the current settings.
1189
- * @param settings The settings context to use for determining if angles should be displayed in degrees or radians.
1190
- * @returns A tuple containing the functions to convert to and from display values.
1191
- */
1192
- function useAngleConverters(settings) {
1193
- const useDegrees = useObservableState(() => settings.useDegrees, settings.settingsChangedObservable);
1194
- const toDisplayValue = useCallback((angle, wrap = false) => {
1195
- if (wrap) {
1196
- angle = WrapAngle(angle);
1197
- }
1198
- return useDegrees ? angle * RadiansToDegrees : angle;
1199
- }, [useDegrees]);
1200
- const fromDisplayValue = useCallback((angle, wrap = false) => {
1201
- angle = useDegrees ? angle / RadiansToDegrees : angle;
1202
- if (wrap) {
1203
- angle = WrapAngle(angle);
1204
- }
1205
- return angle;
1206
- }, [useDegrees]);
1207
- return [toDisplayValue, fromDisplayValue, useDegrees];
1208
- }
1209
-
1210
1253
  const SequencerLock = new AsyncLock();
1211
1254
  /**
1212
1255
  * Creates a hook for managing teaching moment state.
@@ -2098,6 +2141,10 @@ const useStyles$c = makeStyles({
2098
2141
  overflow: "hidden",
2099
2142
  textOverflow: "ellipsis",
2100
2143
  },
2144
+ treeItemLayoutCompact: {
2145
+ minHeight: CustomTokens.lineHeightSmall,
2146
+ maxHeight: CustomTokens.lineHeightSmall,
2147
+ },
2101
2148
  });
2102
2149
  const ActionCommand = (props) => {
2103
2150
  const { command } = props;
@@ -2134,17 +2181,22 @@ function MakeCommandElement(command, isPlaceholder) {
2134
2181
  const SceneTreeItem = (props) => {
2135
2182
  const { isSelected, select } = props;
2136
2183
  const classes = useStyles$c();
2137
- return (jsx(FlatTreeItem, { value: "scene", itemType: "leaf", parentValue: undefined, "aria-level": 1, "aria-setsize": 1, "aria-posinset": 1, onClick: select, children: jsx(TreeItemLayout, { iconBefore: jsx(GlobeRegular, {}), className: classes.sceneTreeItemLayout, style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, children: jsx(Body1Strong, { wrap: false, truncate: true, children: "Scene" }) }) }, "scene"));
2184
+ const [compactMode] = useCompactMode();
2185
+ const treeItemLayoutClass = mergeClasses(classes.sceneTreeItemLayout, compactMode ? classes.treeItemLayoutCompact : undefined);
2186
+ return (jsx(FlatTreeItem, { value: "scene", itemType: "leaf", parentValue: undefined, "aria-level": 1, "aria-setsize": 1, "aria-posinset": 1, onClick: select, children: jsx(TreeItemLayout, { iconBefore: jsx(GlobeRegular, {}), className: treeItemLayoutClass, style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, children: jsx(Body1Strong, { wrap: false, truncate: true, children: "Scene" }) }) }, "scene"));
2138
2187
  };
2139
2188
  const SectionTreeItem = (props) => {
2140
2189
  const { section, isFiltering, expandAll, collapseAll } = props;
2190
+ const classes = useStyles$c();
2191
+ const [compactMode] = useCompactMode();
2141
2192
  return (jsxs(Menu, { openOnContext: true, children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: jsx(FlatTreeItem, { value: section.sectionName,
2142
2193
  // Disable manual expand/collapse when a filter is active.
2143
- itemType: !isFiltering && section.children.length > 0 ? "branch" : "leaf", parentValue: undefined, "aria-level": 1, "aria-setsize": 1, "aria-posinset": 1, children: jsx(TreeItemLayout, { children: jsx(Body1Strong, { wrap: false, truncate: true, children: section.sectionName.substring(0, 100) }) }) }, section.sectionName) }), jsx(MenuPopover, { hidden: !section.children.length, children: jsxs(MenuList, { children: [jsx(MenuItem, { onClick: expandAll, children: jsx(Body1, { children: "Expand All" }) }), jsx(MenuItem, { onClick: collapseAll, children: jsx(Body1, { children: "Collapse All" }) })] }) })] }));
2194
+ itemType: !isFiltering && section.children.length > 0 ? "branch" : "leaf", parentValue: undefined, "aria-level": 1, "aria-setsize": 1, "aria-posinset": 1, children: jsx(TreeItemLayout, { className: compactMode ? classes.treeItemLayoutCompact : undefined, children: jsx(Body1Strong, { wrap: false, truncate: true, children: section.sectionName.substring(0, 100) }) }) }, section.sectionName) }), jsx(MenuPopover, { hidden: !section.children.length, children: jsxs(MenuList, { children: [jsx(MenuItem, { onClick: expandAll, children: jsx(Body1, { children: "Expand All" }) }), jsx(MenuItem, { onClick: collapseAll, children: jsx(Body1, { children: "Collapse All" }) })] }) })] }));
2144
2195
  };
2145
2196
  const EntityTreeItem = (props) => {
2146
2197
  const { entityItem, isSelected, select, isFiltering, commandProviders, expandAll, collapseAll } = props;
2147
2198
  const classes = useStyles$c();
2199
+ const [compactMode] = useCompactMode();
2148
2200
  const hasChildren = !!entityItem.children?.length;
2149
2201
  const displayInfo = useResource(useCallback(() => {
2150
2202
  const displayInfo = entityItem.getDisplayInfo();
@@ -2223,7 +2275,7 @@ const EntityTreeItem = (props) => {
2223
2275
  }, [commands]);
2224
2276
  return (jsxs(Menu, { openOnContext: true, children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: jsx(FlatTreeItem, { value: entityItem.entity.uniqueId,
2225
2277
  // Disable manual expand/collapse when a filter is active.
2226
- itemType: !isFiltering && hasChildren ? "branch" : "leaf", parentValue: entityItem.parent.type === "section" ? entityItem.parent.sectionName : entityItem.entity.uniqueId, "aria-level": entityItem.depth, "aria-setsize": 1, "aria-posinset": 1, onClick: select, style: { [treeItemLevelToken]: entityItem.depth }, children: jsx(TreeItemLayout, { iconBefore: entityItem.icon ? jsx(entityItem.icon, { entity: entityItem.entity }) : null, style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, actions: actions, aside: {
2278
+ itemType: !isFiltering && hasChildren ? "branch" : "leaf", parentValue: entityItem.parent.type === "section" ? entityItem.parent.sectionName : entityItem.entity.uniqueId, "aria-level": entityItem.depth, "aria-setsize": 1, "aria-posinset": 1, onClick: select, style: { [treeItemLevelToken]: entityItem.depth }, children: jsx(TreeItemLayout, { iconBefore: entityItem.icon ? jsx(entityItem.icon, { entity: entityItem.entity }) : null, className: compactMode ? classes.treeItemLayoutCompact : undefined, style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, actions: actions, aside: {
2227
2279
  // Match the gap and padding of the actions.
2228
2280
  className: classes.treeItemLayoutAside,
2229
2281
  children: aside,
@@ -2513,6 +2565,10 @@ const useSwitchStyles = makeStyles({
2513
2565
  switch: {
2514
2566
  marginLeft: "auto",
2515
2567
  },
2568
+ switchSmall: {
2569
+ transform: `scale(.85)`, // workaround since we cannot resize fluent switch
2570
+ transformOrigin: "right",
2571
+ },
2516
2572
  indicator: {
2517
2573
  margin: 0, // Remove the default right margin so the switch aligns well on the right side inside panels like the properties pane.
2518
2574
  },
@@ -2524,6 +2580,7 @@ const useSwitchStyles = makeStyles({
2524
2580
  */
2525
2581
  const Switch = (props) => {
2526
2582
  Switch.displayName = "Switch";
2583
+ const { size } = useContext(ToolContext);
2527
2584
  const classes = useSwitchStyles();
2528
2585
  const [checked, setChecked] = useState(() => props.value ?? false);
2529
2586
  useEffect(() => {
@@ -2535,7 +2592,7 @@ const Switch = (props) => {
2535
2592
  props.onChange && props.onChange(event.target.checked);
2536
2593
  setChecked(event.target.checked);
2537
2594
  };
2538
- return jsx(Switch$1, { className: classes.switch, indicator: { className: classes.indicator }, checked: checked, disabled: props.disabled, onChange: onChange });
2595
+ return (jsx(Switch$1, { className: mergeClasses(classes.switch, size === "small" && classes.switchSmall), indicator: { className: classes.indicator }, checked: checked, disabled: props.disabled, onChange: onChange }));
2539
2596
  };
2540
2597
 
2541
2598
  /**
@@ -2770,7 +2827,10 @@ const SettingsServiceDefinition = {
2770
2827
  const sections = useOrderedObservableCollection(sectionsCollection);
2771
2828
  const sectionContent = useObservableCollection(sectionContentCollection);
2772
2829
  const scene = useObservableState(() => sceneContext.currentScene, sceneContext.currentSceneObservable);
2773
- return (jsx(Fragment, { children: scene && (jsx(ExtensibleAccordion, { sections: sections, sectionContent: sectionContent, context: scene, children: jsxs(AccordionSection, { title: "UI", children: [jsx(SwitchPropertyLine, { label: "Use Degrees", description: "Using degrees instead of radians.", value: settings.useDegrees, onChange: (checked) => {
2830
+ const [compactMode, setCompactMode] = useCompactMode();
2831
+ return (jsx(Fragment, { children: scene && (jsx(ExtensibleAccordion, { sections: sections, sectionContent: sectionContent, context: scene, children: jsxs(AccordionSection, { title: "UI", children: [jsx(SwitchPropertyLine, { label: "Compact Mode", description: "Use a more compact UI with less spacing.", value: compactMode, onChange: (checked) => {
2832
+ setCompactMode(checked);
2833
+ } }), jsx(SwitchPropertyLine, { label: "Use Degrees", description: "Using degrees instead of radians.", value: settings.useDegrees, onChange: (checked) => {
2774
2834
  settings.useDegrees = checked;
2775
2835
  } }), jsx(SwitchPropertyLine, { label: "Ignore Backfaces for Picking", description: "Ignore backfaces when picking.", value: settings.ignoreBackfacesForPicking, onChange: (checked) => {
2776
2836
  settings.ignoreBackfacesForPicking = checked;
@@ -4166,6 +4226,7 @@ const TextInput = (props) => {
4166
4226
  const classes = useInputStyles$1();
4167
4227
  const [value, setValue] = useState(props.value);
4168
4228
  const lastCommittedValue = useRef(props.value);
4229
+ const { size } = useContext(ToolContext);
4169
4230
  useEffect(() => {
4170
4231
  if (props.value !== lastCommittedValue.current) {
4171
4232
  setValue(props.value); // Update local state when props.value changes
@@ -4195,12 +4256,13 @@ const TextInput = (props) => {
4195
4256
  };
4196
4257
  const mergedClassName = mergeClasses(classes.input, !validateValue(value) ? classes.invalid : "", props.className);
4197
4258
  const id = useId("input-button");
4198
- return (jsxs("div", { className: classes.container, children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(Input, { ...props, input: { className: classes.inputSlot }, id: id, size: "medium", value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: HandleOnBlur, className: mergedClassName })] }));
4259
+ return (jsxs("div", { className: classes.container, children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(Input, { ...props, input: { className: classes.inputSlot }, id: id, size: size, value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: HandleOnBlur, className: mergedClassName })] }));
4199
4260
  };
4200
4261
 
4201
4262
  const SpinButton = (props) => {
4202
4263
  SpinButton.displayName = "SpinButton";
4203
4264
  const classes = useInputStyles$1();
4265
+ const { size } = useContext(ToolContext);
4204
4266
  const { min, max } = props;
4205
4267
  const [value, setValue] = useState(props.value);
4206
4268
  const lastCommittedValue = useRef(props.value);
@@ -4244,7 +4306,7 @@ const SpinButton = (props) => {
4244
4306
  };
4245
4307
  const id = useId("spin-button");
4246
4308
  const mergedClassName = mergeClasses(classes.input, !validateValue(value) ? classes.invalid : "", props.className);
4247
- return (jsxs("div", { className: classes.container, children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(SpinButton$1, { ...props, input: { className: classes.inputSlot }, step: step, id: id, size: "medium", precision: precision, displayValue: `${value.toFixed(precision)}${props.unit ? " " + props.unit : ""}`, value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: HandleOnBlur, className: mergedClassName })] }));
4309
+ return (jsxs("div", { className: classes.container, children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(SpinButton$1, { ...props, input: { className: classes.inputSlot }, step: step, id: id, size: size, precision: precision, displayValue: `${value.toFixed(precision)}${props.unit ? " " + props.unit : ""}`, value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: HandleOnBlur, className: mergedClassName })] }));
4248
4310
  };
4249
4311
 
4250
4312
  /**
@@ -4289,6 +4351,7 @@ const SyncedSliderInput = (props) => {
4289
4351
  SyncedSliderInput.displayName = "SyncedSliderInput";
4290
4352
  const { infoLabel, ...passthroughProps } = props;
4291
4353
  const classes = useSyncedSliderStyles();
4354
+ const { size } = useContext(ToolContext);
4292
4355
  const [value, setValue] = useState(props.value);
4293
4356
  const pendingValueRef = useRef(undefined);
4294
4357
  const isDraggingRef = useRef(false);
@@ -4327,7 +4390,7 @@ const SyncedSliderInput = (props) => {
4327
4390
  setValue(value);
4328
4391
  props.onChange(value); // Input always updates immediately
4329
4392
  };
4330
- return (jsxs("div", { className: classes.container, children: [infoLabel && jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [props.min !== undefined && props.max !== undefined && (jsx(Slider, { ...passthroughProps, className: classes.slider, min: min / step, max: max / step, step: undefined, value: value / step, onChange: handleSliderChange, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), jsx(SpinButton, { ...passthroughProps, value: value, onChange: handleInputChange, step: props.step })] })] }));
4393
+ return (jsxs("div", { className: classes.container, children: [infoLabel && jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [props.min !== undefined && props.max !== undefined && (jsx(Slider, { ...passthroughProps, className: classes.slider, size: size, min: min / step, max: max / step, step: undefined, value: value / step, onChange: handleSliderChange, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), jsx(SpinButton, { ...passthroughProps, value: value, onChange: handleInputChange, step: props.step })] })] }));
4331
4394
  };
4332
4395
 
4333
4396
  /**
@@ -4539,7 +4602,7 @@ const TensorPropertyLine = (props) => {
4539
4602
  useEffect(() => {
4540
4603
  setVector(props.value);
4541
4604
  }, [props.value, props.expandedContent]);
4542
- return (jsx(PropertyLine, { ...props, onCopy: () => `new ${props.value.constructor.name}(${vector.x},${vector.y} ${HasZ(vector) ? `,${vector.z}` : ""}${HasW(vector) ? `,${vector.w}` : ""})`, expandedContent: jsxs(Fragment, { children: [jsx(SyncedSliderPropertyLine, { label: "X", value: converted(vector.x), min: min, max: max, onChange: (val) => onChange(val, "x"), unit: props.unit, step: props.step }), jsx(SyncedSliderPropertyLine, { label: "Y", value: converted(vector.y), min: min, max: max, onChange: (val) => onChange(val, "y"), unit: props.unit, step: props.step }), HasZ(vector) && (jsx(SyncedSliderPropertyLine, { label: "Z", value: converted(vector.z), min: min, max: max, onChange: (val) => onChange(val, "z"), unit: props.unit, step: props.step })), HasW(vector) && (jsx(SyncedSliderPropertyLine, { label: "W", value: converted(vector.w), min: min, max: max, onChange: (val) => onChange(val, "w"), unit: props.unit, step: props.step }))] }), children: jsx(Body1, { children: `[${formatted(props.value.x)}, ${formatted(props.value.y)}${HasZ(props.value) ? `, ${formatted(props.value.z)}` : ""}${HasW(props.value) ? `, ${formatted(props.value.w)}` : ""}]` }) }));
4605
+ return (jsx(PropertyLine, { ...props, onCopy: () => `new ${props.value.getClassName()}(${vector.x},${vector.y}${HasZ(vector) ? `,${vector.z}` : ""}${HasW(vector) ? `,${vector.w}` : ""})`, expandedContent: jsxs(Fragment, { children: [jsx(SyncedSliderPropertyLine, { label: "X", value: converted(vector.x), min: min, max: max, onChange: (val) => onChange(val, "x"), unit: props.unit, step: props.step }), jsx(SyncedSliderPropertyLine, { label: "Y", value: converted(vector.y), min: min, max: max, onChange: (val) => onChange(val, "y"), unit: props.unit, step: props.step }), HasZ(vector) && (jsx(SyncedSliderPropertyLine, { label: "Z", value: converted(vector.z), min: min, max: max, onChange: (val) => onChange(val, "z"), unit: props.unit, step: props.step })), HasW(vector) && (jsx(SyncedSliderPropertyLine, { label: "W", value: converted(vector.w), min: min, max: max, onChange: (val) => onChange(val, "w"), unit: props.unit, step: props.step }))] }), children: jsx(Body1, { children: `[${formatted(props.value.x)}, ${formatted(props.value.y)}${HasZ(props.value) ? `, ${formatted(props.value.z)}` : ""}${HasW(props.value) ? `, ${formatted(props.value.w)}` : ""}]` }) }));
4543
4606
  };
4544
4607
  const ToDegreesConverter = { from: Tools.ToDegrees, to: Tools.ToRadians };
4545
4608
  const RotationVectorPropertyLine = (props) => {
@@ -4580,7 +4643,6 @@ const useDropdownStyles = makeStyles({
4580
4643
  display: "flex",
4581
4644
  flexDirection: "column",
4582
4645
  justifyContent: "center", // align items vertically
4583
- gap: "4px",
4584
4646
  },
4585
4647
  dropdownText: { textAlign: "end", textOverflow: "ellipsis", whiteSpace: "nowrap", overflowX: "hidden" },
4586
4648
  });
@@ -4595,13 +4657,14 @@ const Dropdown = (props) => {
4595
4657
  const classes = useDropdownStyles();
4596
4658
  const { options, value } = props;
4597
4659
  const [defaultVal, setDefaultVal] = useState(props.value);
4660
+ const { size } = useContext(ToolContext);
4598
4661
  useEffect(() => {
4599
4662
  setDefaultVal(value);
4600
4663
  }, [props.value]);
4601
4664
  const id = useId("dropdown");
4602
4665
  const mergedClassName = mergeClasses(classes.container, props.className);
4603
4666
  const optionLabel = options.find((o) => o.value === defaultVal)?.label;
4604
- return (jsxs("div", { className: mergedClassName, children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(Dropdown$1, { id: id, disabled: props.disabled, size: "medium", className: classes.dropdown, button: jsx("span", { className: classes.dropdownText, children: optionLabel }), onOptionSelect: (evt, data) => {
4667
+ return (jsxs("div", { className: mergedClassName, children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(Dropdown$1, { id: id, disabled: props.disabled, size: size, className: classes.dropdown, button: jsx("span", { className: classes.dropdownText, children: optionLabel }), onOptionSelect: (evt, data) => {
4605
4668
  const value = typeof props.value === "number" ? Number(data.optionValue) : data.optionValue;
4606
4669
  if (value !== undefined) {
4607
4670
  setDefaultVal(value);
@@ -4666,6 +4729,7 @@ const ColorPickerPopup = (props) => {
4666
4729
  const [popoverOpen, setPopoverOpen] = useState(false);
4667
4730
  const [isLinear, setIsLinear] = useState(props.isLinearMode ?? false);
4668
4731
  const [isFloat, setFloat] = useState(false);
4732
+ const { size } = useContext(ToolContext);
4669
4733
  useEffect(() => {
4670
4734
  setColor(props.value); // Ensures the trigger color updates when props.value changes
4671
4735
  }, [props.value]);
@@ -4684,7 +4748,7 @@ const ColorPickerPopup = (props) => {
4684
4748
  align: "start",
4685
4749
  overflowBoundary: document.body,
4686
4750
  autoSize: true,
4687
- }, open: popoverOpen, trapFocus: true, onOpenChange: (_, data) => setPopoverOpen(data.open), children: [jsx(PopoverTrigger, { disableButtonEnhancement: true, children: jsx(ColorSwatch, { borderColor: tokens.colorNeutralShadowKeyDarker, size: "small", shape: "rounded", color: color.toHexString(), value: color.toHexString().slice(1) }) }), jsx(PopoverSurface, { children: jsxs("div", { className: classes.container, children: [jsxs(ColorPicker, { className: classes.colorPicker, color: rgbaToHsv(color), onColorChange: handleColorPickerChange, children: [jsx(ColorArea, { inputX: { "aria-label": "Saturation" }, inputY: { "aria-label": "Brightness" } }), jsx(ColorSlider, { "aria-label": "Hue" }), color instanceof Color4 && jsx(AlphaSlider, { "aria-label": "Alpha" })] }), jsxs("div", { className: classes.row, children: [jsx("div", { className: classes.previewColor, style: { backgroundColor: color.toHexString() } }), jsx(NumberDropdown, { className: classes.inputField, infoLabel: {
4751
+ }, open: popoverOpen, trapFocus: true, onOpenChange: (_, data) => setPopoverOpen(data.open), children: [jsx(PopoverTrigger, { disableButtonEnhancement: true, children: jsx(ColorSwatch, { borderColor: tokens.colorNeutralShadowKeyDarker, size: size === "small" ? "extra-small" : "small", shape: "rounded", color: color.toHexString(), value: color.toHexString().slice(1) }) }), jsx(PopoverSurface, { children: jsxs("div", { className: classes.container, children: [jsxs(ColorPicker, { className: classes.colorPicker, color: rgbaToHsv(color), onColorChange: handleColorPickerChange, children: [jsx(ColorArea, { inputX: { "aria-label": "Saturation" }, inputY: { "aria-label": "Brightness" } }), jsx(ColorSlider, { "aria-label": "Hue" }), color instanceof Color4 && jsx(AlphaSlider, { "aria-label": "Alpha" })] }), jsxs("div", { className: classes.row, children: [jsx("div", { className: classes.previewColor, style: { backgroundColor: color.toHexString() } }), jsx(NumberDropdown, { className: classes.inputField, infoLabel: {
4688
4752
  label: "Color Space",
4689
4753
  info: jsx(Body1, { children: "Today this is not mutable as the color space is determined by the entity. Soon we will allow swapping" }),
4690
4754
  }, options: [
@@ -4709,7 +4773,7 @@ const ColorPickerPopup = (props) => {
4709
4773
  const InputHexField = (props) => {
4710
4774
  const classes = useColorPickerStyles();
4711
4775
  const { title, value, onChange, linearHex, isLinearMode } = props;
4712
- return (jsx(TextInput, { disabled: linearHex ? !isLinearMode : false, className: classes.inputField, value: linearHex ? value.toLinearSpace().toHexString() : value.toHexString(), validator: ColorHexValidatorFn, onChange: (val) => (linearHex ? onChange(Color3.FromHexString(val).toGammaSpace()) : onChange(Color3.FromHexString(val))), infoLabel: title
4776
+ return (jsx(TextInput, { disabled: linearHex ? !isLinearMode : false, className: classes.inputField, value: linearHex ? value.toLinearSpace().toHexString() : value.toHexString(), validator: ValidateColorHex, onChange: (val) => (linearHex ? onChange(Color3.FromHexString(val).toGammaSpace()) : onChange(Color3.FromHexString(val))), infoLabel: title
4713
4777
  ? {
4714
4778
  label: title,
4715
4779
  // If not representing a linearHex, no info is needed.
@@ -5495,7 +5559,9 @@ const StencilOperationOptions = [
5495
5559
  const MaterialGeneralProperties = (props) => {
5496
5560
  const { material } = props;
5497
5561
  const pointsCloud = useProperty(material, "pointsCloud");
5498
- return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Backface Culling", docLink: "https://doc.babylonjs.com/features/featuresDeepDive/materials/using/materials_introduction#back-face-culling", target: material, propertyKey: "backFaceCulling" }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Orientation", description: "The front face side. Overrides mesh's orientation.", options: OrientationOptions, target: material, propertyKey: "sideOrientation", nullable: true, defaultValue: material.getScene().useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Disable Color Write", target: material, propertyKey: "disableColorWrite" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Disable Depth Write", target: material, propertyKey: "disableDepthWrite" }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Depth Function", options: DepthFunctionOptions, target: material, propertyKey: "depthFunction" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Need Depth Pre-pass", docLink: "https://doc.babylonjs.com/features/featuresDeepDive/materials/advanced/transparent_rendering/#depth-pre-pass-meshes", target: material, propertyKey: "needDepthPrePass" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Z-offset Factor", target: material, propertyKey: "zOffset", min: -10, max: 10, step: 0.1 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Z-offset Units", target: material, propertyKey: "zOffsetUnits", min: -10, max: 10, step: 0.1 }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Wireframe", target: material, propertyKey: "wireframe" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Point Cloud", target: material, propertyKey: "pointsCloud" }), pointsCloud && jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Point Size", target: material, propertyKey: "pointSize", min: 0, max: 100, step: 0.1 })] }));
5562
+ const faceCulling = useProperty(material, "backFaceCulling");
5563
+ const isWebGPU = material.getScene().getEngine().isWebGPU;
5564
+ return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Face Culling", docLink: "https://doc.babylonjs.com/features/featuresDeepDive/materials/using/materials_introduction#back-face-culling", target: material, propertyKey: "backFaceCulling" }), faceCulling && (jsx(BoundProperty, { component: SwitchPropertyLine, label: "Culls back faces", description: "Culls back faces. If false, front faces are culled.", target: material, propertyKey: "cullBackFaces" })), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Orientation", description: "The front face side. Overrides mesh's orientation.", options: OrientationOptions, target: material, propertyKey: "sideOrientation", nullable: true, defaultValue: material.getScene().useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Disable Color Write", target: material, propertyKey: "disableColorWrite" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Disable Depth Write", target: material, propertyKey: "disableDepthWrite" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Force Depth Write", target: material, propertyKey: "forceDepthWrite" }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Depth Function", options: DepthFunctionOptions, target: material, propertyKey: "depthFunction" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Need Depth Pre-pass", docLink: "https://doc.babylonjs.com/features/featuresDeepDive/materials/advanced/transparent_rendering/#depth-pre-pass-meshes", target: material, propertyKey: "needDepthPrePass" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Z-offset Factor", target: material, propertyKey: "zOffset", min: -10, max: 10, step: 0.1 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Z-offset Units", target: material, propertyKey: "zOffsetUnits", min: -10, max: 10, step: 0.1 }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Wireframe", target: material, propertyKey: "wireframe" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Point Cloud", target: material, propertyKey: "pointsCloud" }), pointsCloud && jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Point Size", target: material, propertyKey: "pointSize", min: 0, max: 100, step: 0.1 }), isWebGPU && jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use vertex pulling", target: material, propertyKey: "useVertexPulling" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Support fog", target: material, propertyKey: "fogEnabled", description: "Indicates whether the material supports fog (however, fog must be enabled at the scene level to be effective)." }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use logarithmic depth", target: material, propertyKey: "useLogarithmicDepth", docLink: "https://doc.babylonjs.com/features/featuresDeepDive/materials/advanced/logarithmicDepthBuffer" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Set vertex output invariant", target: material, propertyKey: "setVertexOutputInvariant", description: "Setting this property to true will force the shader compiler to disable some optimization to make sure the vertex output is always calculated the same way across different compilation units." })] }));
5499
5565
  };
5500
5566
  const MaterialTransparencyProperties = (props) => {
5501
5567
  const { material } = props;
@@ -5913,6 +5979,7 @@ const useStyles$4 = makeStyles({
5913
5979
  const MetadataProperties = (props) => {
5914
5980
  const { entity } = props;
5915
5981
  const classes = useStyles$4();
5982
+ const { size } = useContext(ToolContext);
5916
5983
  const metadata = useProperty(entity, "metadata");
5917
5984
  const stringifiedMetadata = useMemo(() => StringifyMetadata(metadata) ?? "", [metadata]);
5918
5985
  const metadataType = useMemo(() => GetMetadataEntityType(metadata), [metadata]);
@@ -5929,7 +5996,7 @@ const MetadataProperties = (props) => {
5929
5996
  withGLTFExtras = Restringify(withGLTFExtras, true);
5930
5997
  }
5931
5998
  setEditedMetadata(withGLTFExtras);
5932
- } }), jsx(LineContainer, { children: jsxs("div", { className: classes.buttonDiv, children: [jsx(Button$1, { icon: jsx(SaveRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => SaveMetadata(entity, editedMetadata), children: jsx(Body1, { children: "Save" }) }), jsx(Tooltip, { content: "Undo Changes", relationship: "label", children: jsx(Button$1, { icon: jsx(ArrowUndoRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => setEditedMetadata(stringifiedMetadata) }) }), jsx(Tooltip, { content: "Format (Pretty Print)", relationship: "label", children: jsx(Button$1, { icon: jsx(BracesRegular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, true)) }) }), jsx(Tooltip, { content: "Clear Formatting (Undo Pretty Print)", relationship: "label", children: jsx(Button$1, { icon: jsx(BracesDismiss16Regular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, false)) }) })] }) })] }));
5999
+ } }), jsx(LineContainer, { 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, { content: "Undo Changes", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(ArrowUndoRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => setEditedMetadata(stringifiedMetadata) }) }), jsx(Tooltip, { content: "Format (Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesRegular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, true)) }) }), jsx(Tooltip, { content: "Clear Formatting (Undo Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesDismiss16Regular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, false)) }) })] }) })] }));
5933
6000
  };
5934
6001
 
5935
6002
  function IsMetadataContainer(entity) {
@@ -6787,6 +6854,11 @@ const PhysicsPropertiesServiceDefinition = {
6787
6854
  },
6788
6855
  };
6789
6856
 
6857
+ const useCheckboxStyles = makeStyles({
6858
+ indicator: {
6859
+ margin: 0,
6860
+ },
6861
+ });
6790
6862
  /**
6791
6863
  * This is a primitive fluent checkbox that can both read and write checked state
6792
6864
  * @param props
@@ -6795,6 +6867,7 @@ const PhysicsPropertiesServiceDefinition = {
6795
6867
  const Checkbox = (props) => {
6796
6868
  Checkbox.displayName = "Checkbox";
6797
6869
  const [checked, setChecked] = useState(() => props.value ?? false);
6870
+ const classes = useCheckboxStyles();
6798
6871
  useEffect(() => {
6799
6872
  if (props.value != undefined) {
6800
6873
  setChecked(props.value); // Update local state when props.checked changes
@@ -6804,7 +6877,7 @@ const Checkbox = (props) => {
6804
6877
  props.onChange(ev.target.checked);
6805
6878
  setChecked(ev.target.checked);
6806
6879
  };
6807
- return jsx(Checkbox$1, { checked: checked, onChange: onChange, disabled: props.disabled });
6880
+ return jsx(Checkbox$1, { checked: checked, onChange: onChange, indicator: { className: classes.indicator } });
6808
6881
  };
6809
6882
 
6810
6883
  /**
@@ -7382,6 +7455,7 @@ const TexturePreview = (props) => {
7382
7455
  const [channels, setChannels] = useState(TextureChannelStates.ALL);
7383
7456
  const [face, setFace] = useState(0);
7384
7457
  const internalTexture = useProperty(texture, "_texture");
7458
+ const { size } = useContext(ToolContext);
7385
7459
  const updatePreviewCanvasSize = useCallback((previewCanvas) => {
7386
7460
  // This logic was brought over from inspectorv1 and can likely be refactored/simplified
7387
7461
  const size = texture.getSize();
@@ -7425,7 +7499,7 @@ const TexturePreview = (props) => {
7425
7499
  useEffect(() => {
7426
7500
  void updatePreviewAsync();
7427
7501
  }, [texture, width, height, face, channels, internalTexture]);
7428
- return (jsxs("div", { className: classes.root, children: [texture.isCube ? (jsx(Toolbar$1, { className: classes.controls, "aria-label": "Cube Faces", children: ["+X", "-X", "+Y", "-Y", "+Z", "-Z"].map((label, idx) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: face === idx ? "primary" : "subtle", onClick: () => setFace(idx), children: label }, label))) })) : (jsx(Toolbar$1, { className: classes.controls, "aria-label": "Channels", children: ["R", "G", "B", "A", "ALL"].map((ch) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: channels === TextureChannelStates[ch] ? "primary" : "subtle", onClick: () => setChannels(TextureChannelStates[ch]), children: ch }, ch))) })), jsx("canvas", { ref: canvasRef, className: classes.preview }), texture.isRenderTarget && (jsx(Button$1, { appearance: "outline", onClick: () => {
7502
+ return (jsxs("div", { className: classes.root, children: [texture.isCube ? (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Cube Faces", children: ["+X", "-X", "+Y", "-Y", "+Z", "-Z"].map((label, idx) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: face === idx ? "primary" : "subtle", onClick: () => setFace(idx), children: label }, label))) })) : (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Channels", children: ["R", "G", "B", "A", "ALL"].map((ch) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: channels === TextureChannelStates[ch] ? "primary" : "subtle", onClick: () => setChannels(TextureChannelStates[ch]), children: ch }, ch))) })), jsx("canvas", { ref: canvasRef, className: classes.preview }), texture.isRenderTarget && (jsx(Button$1, { appearance: "outline", onClick: () => {
7429
7503
  void updatePreviewAsync();
7430
7504
  }, children: "Refresh" }))] }));
7431
7505
  };
@@ -7574,7 +7648,8 @@ const BaseTextureCharacteristicProperties = (props) => {
7574
7648
  const useSRGBBuffer = useProperty(internalTexture, "_useSRGBBuffer");
7575
7649
  const displayFormat = FindTextureFormat(format === -1 ? Constants.TEXTUREFORMAT_RGBA : format);
7576
7650
  const displayType = FindTextureType(type === -1 ? Constants.TEXTURETYPE_UNSIGNED_BYTE : type);
7577
- return (jsxs(Fragment, { children: [texture.is2DArray && jsx(TextPropertyLine, { label: "Layers", value: depth?.toString() ?? "?" }), texture.is3D && jsx(TextPropertyLine, { label: "Depth", value: depth?.toString() ?? "?" }), jsx(TextPropertyLine, { label: "Format", value: displayFormat?.label ?? "unknown" }), !displayFormat?.hideType && !displayFormat?.compressed && jsx(TextPropertyLine, { label: "Type", value: displayType?.label ?? "unknown" }), !!displayFormat?.normalizable && !displayFormat?.compressed && displayType?.normalizable != undefined && (jsx(BooleanBadgePropertyLine, { label: "Normalized", value: displayType.normalizable })), jsx(BooleanBadgePropertyLine, { label: "Compressed", value: displayFormat?.compressed ?? false }), jsx(BooleanBadgePropertyLine, { label: "sRGB Buffers", value: useSRGBBuffer ?? false }), jsx(BoundProperty, { component: BooleanBadgePropertyLine, label: "Gamma Space", target: texture, propertyKey: "gammaSpace" }), jsx(BoundProperty, { component: BooleanBadgePropertyLine, label: "Has Alpha", target: texture, propertyKey: "hasAlpha" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Alpha from RGB", target: texture, propertyKey: "getAlphaFromRGB" }), jsx(BooleanBadgePropertyLine, { label: "3D", value: texture.is3D }), jsx(BooleanBadgePropertyLine, { label: "2D Array", value: texture.is2DArray }), jsx(BooleanBadgePropertyLine, { label: "Cube", value: texture.isCube }), jsx(BooleanBadgePropertyLine, { label: "Render Target", value: texture.isRenderTarget }), jsx(BooleanBadgePropertyLine, { label: "Mipmaps", value: !texture.noMipmap }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "UV Set", target: texture, propertyKey: "coordinatesIndex", min: 0, max: 3, step: 1 }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Mode", target: texture, propertyKey: "coordinatesMode", options: CoordinatesMode }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Level", target: texture, propertyKey: "level", min: 0, max: 2, step: 0.01 })] }));
7651
+ const maxAnisotropy = texture.getScene()?.getEngine().getCaps().maxAnisotropy ?? 1;
7652
+ return (jsxs(Fragment, { children: [texture.is2DArray && jsx(TextPropertyLine, { label: "Layers", value: depth?.toString() ?? "?" }), texture.is3D && jsx(TextPropertyLine, { label: "Depth", value: depth?.toString() ?? "?" }), jsx(TextPropertyLine, { label: "Format", value: displayFormat?.label ?? "unknown" }), !displayFormat?.hideType && !displayFormat?.compressed && jsx(TextPropertyLine, { label: "Type", value: displayType?.label ?? "unknown" }), !!displayFormat?.normalizable && !displayFormat?.compressed && displayType?.normalizable != undefined && (jsx(BooleanBadgePropertyLine, { label: "Normalized", value: displayType.normalizable })), jsx(BooleanBadgePropertyLine, { label: "Compressed", value: displayFormat?.compressed ?? false }), jsx(BooleanBadgePropertyLine, { label: "sRGB Buffers", value: useSRGBBuffer ?? false }), jsx(BoundProperty, { component: BooleanBadgePropertyLine, label: "Gamma Space", target: texture, propertyKey: "gammaSpace" }), jsx(BoundProperty, { component: BooleanBadgePropertyLine, label: "Has Alpha", target: texture, propertyKey: "hasAlpha" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Alpha from RGB", target: texture, propertyKey: "getAlphaFromRGB" }), jsx(BooleanBadgePropertyLine, { label: "3D", value: texture.is3D }), jsx(BooleanBadgePropertyLine, { label: "2D Array", value: texture.is2DArray }), jsx(BooleanBadgePropertyLine, { label: "Cube", value: texture.isCube }), jsx(BooleanBadgePropertyLine, { label: "Render Target", value: texture.isRenderTarget }), jsx(BooleanBadgePropertyLine, { label: "Mipmaps", value: !texture.noMipmap }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "UV Set", target: texture, propertyKey: "coordinatesIndex", min: 0, max: 3, step: 1 }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Mode", target: texture, propertyKey: "coordinatesMode", options: CoordinatesMode }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Level", target: texture, propertyKey: "level", min: 0, max: 2, step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Anisotropy", target: texture, propertyKey: "anisotropicFilteringLevel", min: 1, max: maxAnisotropy, step: 1 })] }));
7578
7653
  };
7579
7654
  const BaseTextureTransformProperties = (props) => {
7580
7655
  const { texture } = props;
@@ -9208,5 +9283,5 @@ const TextAreaPropertyLine = (props) => {
9208
9283
  return (jsx(PropertyLine, { ...props, children: jsx(Textarea, { ...props }) }));
9209
9284
  };
9210
9285
 
9211
- export { Accordion, AccordionSection, BooleanBadgePropertyLine, BoundProperty, BuiltInsExtensionFeed, Button, ButtonLine, Checkbox, CheckboxPropertyLine, Collapse, Color3GradientComponent, Color3GradientList, Color3PropertyLine, Color4GradientComponent, Color4GradientList, Color4PropertyLine, ColorPickerPopup, ColorStepGradientComponent, ComboBox, ConstructorFactory, DebugServiceIdentity, DraggableLine, Dropdown, ExtensibleAccordion, FactorGradientComponent, FactorGradientList, FileUploadLine, GetPropertyDescriptor, HexPropertyLine, HideInspector, InfoLabel, InputHexField, InputHsvField, Inspector, InterceptFunction, InterceptProperty, IsInspectorVisible, IsPropertyReadonly, LineContainer, LinkPropertyLine, LinkToEntityPropertyLine, List, MakeDialogTeachingMoment, MakeLazyComponent, MakePopoverTeachingMoment, MakePropertyHook, MakeTeachingMoment, MessageBar, NumberDropdown, NumberDropdownPropertyLine, NumberInputPropertyLine, ObservableCollection, Pane, PlaceholderPropertyLine, PositionedPopover, PropertiesServiceIdentity, PropertyLine, QuaternionPropertyLine, RotationVectorPropertyLine, SceneContextIdentity, SceneExplorerServiceIdentity, SearchBar, SearchBox, SelectionServiceDefinition, SelectionServiceIdentity, SettingsContextIdentity, SettingsServiceIdentity, ShellServiceIdentity, ShowInspector, SidePaneContainer, SpinButton, SpinButtonPropertyLine, StatsServiceIdentity, StringDropdown, StringDropdownPropertyLine, StringifiedPropertyLine, Switch, SwitchPropertyLine, SyncedSliderInput, SyncedSliderPropertyLine, TeachingMoment, TextAreaPropertyLine, TextInput, TextInputPropertyLine, TextPropertyLine, Textarea, ToggleButton, ToolsServiceIdentity, Vector2PropertyLine, Vector3PropertyLine, Vector4PropertyLine, useAngleConverters, useAsyncResource, useColor3Property, useColor4Property, useEventfulState, useInterceptObservable, useObservableCollection, useObservableState, useOrderedObservableCollection, usePollingObservable, useProperty, useQuaternionProperty, useResource, useVector3Property };
9286
+ export { Accordion, AccordionSection, BooleanBadgePropertyLine, BoundProperty, BuiltInsExtensionFeed, Button, ButtonLine, Checkbox, CheckboxPropertyLine, Collapse, Color3GradientComponent, Color3GradientList, Color3PropertyLine, Color4GradientComponent, Color4GradientList, Color4PropertyLine, ColorPickerPopup, ColorStepGradientComponent, ComboBox, ConstructorFactory, DebugServiceIdentity, DraggableLine, Dropdown, ExtensibleAccordion, FactorGradientComponent, FactorGradientList, FileUploadLine, GetPropertyDescriptor, HexPropertyLine, HideInspector, InfoLabel, InputHexField, InputHsvField, Inspector, InterceptFunction, InterceptProperty, IsInspectorVisible, IsPropertyReadonly, LineContainer, LinkPropertyLine, LinkToEntityPropertyLine, List, MakeDialogTeachingMoment, MakeLazyComponent, MakePopoverTeachingMoment, MakePropertyHook, MakeTeachingMoment, MessageBar, NumberDropdown, NumberDropdownPropertyLine, NumberInputPropertyLine, ObservableCollection, Pane, PlaceholderPropertyLine, PositionedPopover, PropertiesServiceIdentity, PropertyLine, QuaternionPropertyLine, RotationVectorPropertyLine, SceneContextIdentity, SceneExplorerServiceIdentity, SearchBar, SearchBox, SelectionServiceDefinition, SelectionServiceIdentity, SettingsContextIdentity, SettingsServiceIdentity, ShellServiceIdentity, ShowInspector, SidePaneContainer, SpinButton, SpinButtonPropertyLine, StatsServiceIdentity, StringDropdown, StringDropdownPropertyLine, StringifiedPropertyLine, Switch, SwitchPropertyLine, SyncedSliderInput, SyncedSliderPropertyLine, TeachingMoment, TextAreaPropertyLine, TextInput, TextInputPropertyLine, TextPropertyLine, Textarea, ToggleButton, ToolsServiceIdentity, Vector2PropertyLine, Vector3PropertyLine, Vector4PropertyLine, useAngleConverters, useAsyncResource, useColor3Property, useColor4Property, useCompactMode, useEventfulState, useInterceptObservable, useObservableCollection, useObservableState, useOrderedObservableCollection, usePollingObservable, useProperty, useQuaternionProperty, useResource, useVector3Property };
9212
9287
  //# sourceMappingURL=index.js.map