@babylonjs/inspector 8.29.1-preview → 8.29.2-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/{captureService-4uUJw84S.js → captureService-BEferXko.js} +3 -3
- package/lib/{captureService-4uUJw84S.js.map → captureService-BEferXko.js.map} +1 -1
- package/lib/{exportService-CzzSbQnD.js → exportService-DRm8glYV.js} +3 -3
- package/lib/{exportService-CzzSbQnD.js.map → exportService-DRm8glYV.js.map} +1 -1
- package/lib/{importService-BJFsjp8c.js → importService-CUFQ5Mb2.js} +3 -3
- package/lib/{importService-BJFsjp8c.js.map → importService-CUFQ5Mb2.js.map} +1 -1
- package/lib/{index-B29Ify1o.js → index-BTXdoz_s.js} +576 -586
- package/lib/index-BTXdoz_s.js.map +1 -0
- package/lib/index.d.ts +52 -21
- package/lib/index.js +2 -2
- package/package.json +1 -1
- package/lib/creationToolsService-CX79OLiq.js +0 -142
- package/lib/creationToolsService-CX79OLiq.js.map +0 -1
- package/lib/index-B29Ify1o.js.map +0 -1
|
@@ -3,8 +3,8 @@ 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,
|
|
7
|
-
import {
|
|
6
|
+
import { makeStyles, ToggleButton as ToggleButton$1, Button as Button$1, tokens, Link, InfoLabel as InfoLabel$1, Body1Stronger, Checkbox as Checkbox$1, Body1, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, Body1Strong, TabList, Tooltip, Title3, Tab, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, Switch as Switch$1, PresenceBadge, Spinner, Dialog, DialogTrigger, DialogSurface, DialogBody, DialogTitle, DialogContent, SplitButton, MenuItemRadio, createLightTheme, createDarkTheme, FluentProvider, DialogActions, List as List$1, ListItem, useId, SpinButton as SpinButton$1, Slider, Input, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, Badge, Popover, PopoverTrigger, ColorSwatch, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, Dropdown as Dropdown$1, Option, Textarea as Textarea$1, useComboboxFilter, Combobox, Field } from '@fluentui/react-components';
|
|
7
|
+
import { ChevronCircleRight20Regular, ChevronCircleDown20Regular, CopyRegular, PanelLeftExpandRegular, PanelLeftContractRegular, PanelRightExpandRegular, PanelRightContractRegular, DocumentTextRegular, FilterRegular, MoviesAndTvRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, DataBarHorizontalRegular, WrenchRegular, AppsAddInRegular, DismissRegular, WeatherSunnyRegular, WeatherMoonRegular, ErrorCircleRegular, ArrowMoveRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, GlobeRegular, SaveRegular, ArrowUndoRegular, ClearFormattingRegular, DeleteRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, StopFilled, PlayFilled, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, PlayRegular, AppGenericRegular, PaintBrushRegular, BoxRegular, BranchRegular, CameraRegular, LightbulbRegular, EyeRegular, EyeOffRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, Cone16Filled, Cone16Regular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, DeleteFilled } from '@fluentui/react-icons';
|
|
8
8
|
import { Collapse as Collapse$1 } from '@fluentui/react-motion-components-preview';
|
|
9
9
|
import '@babylonjs/core/Misc/typeStore.js';
|
|
10
10
|
import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
|
|
@@ -46,6 +46,7 @@ import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh.js';
|
|
|
46
46
|
import { Node } from '@babylonjs/core/node.js';
|
|
47
47
|
import { AnimationGroup, TargetedAnimation } from '@babylonjs/core/Animations/animationGroup.js';
|
|
48
48
|
import { AnimationPropertiesOverride } from '@babylonjs/core/Animations/animationPropertiesOverride.js';
|
|
49
|
+
import { Atmosphere } from '@babylonjs/addons/atmosphere/atmosphere.js';
|
|
49
50
|
import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera.js';
|
|
50
51
|
import { FollowCamera } from '@babylonjs/core/Cameras/followCamera.js';
|
|
51
52
|
import { FreeCamera } from '@babylonjs/core/Cameras/freeCamera.js';
|
|
@@ -99,7 +100,6 @@ import '@babylonjs/core/PostProcesses/RenderPipeline/postProcessRenderPipelineMa
|
|
|
99
100
|
import '@babylonjs/core/Sprites/spriteSceneComponent.js';
|
|
100
101
|
import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture.js';
|
|
101
102
|
import { PointerEventTypes } from '@babylonjs/core/Events/pointerEvents.js';
|
|
102
|
-
import { Atmosphere } from '@babylonjs/addons/atmosphere/atmosphere.js';
|
|
103
103
|
|
|
104
104
|
const InterceptorHooksMaps$1 = new WeakMap();
|
|
105
105
|
/**
|
|
@@ -631,15 +631,68 @@ function copyCommandToClipboard(strCommand) {
|
|
|
631
631
|
|
|
632
632
|
const ToolContext = createContext({ useFluent: false, disableCopy: false, toolName: "" });
|
|
633
633
|
|
|
634
|
+
/**
|
|
635
|
+
* Toggles between two states using a button with icons.
|
|
636
|
+
* If no disabledIcon is provided, the button will toggle between visual enabled/disabled states without an icon change
|
|
637
|
+
*
|
|
638
|
+
* @param props
|
|
639
|
+
* @returns
|
|
640
|
+
*/
|
|
641
|
+
const ToggleButton = (props) => {
|
|
642
|
+
const { value, onChange, title, appearance = "subtle" } = props;
|
|
643
|
+
const [checked, setChecked] = useState(value);
|
|
644
|
+
const toggle = useCallback(() => {
|
|
645
|
+
setChecked((prev) => {
|
|
646
|
+
const enabled = !prev;
|
|
647
|
+
onChange(enabled);
|
|
648
|
+
return enabled;
|
|
649
|
+
});
|
|
650
|
+
}, [setChecked]);
|
|
651
|
+
useEffect(() => {
|
|
652
|
+
setChecked(props.value);
|
|
653
|
+
}, [props.value]);
|
|
654
|
+
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 }));
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
const Button = (props) => {
|
|
658
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
659
|
+
const { icon: Icon, label, ...buttonProps } = props;
|
|
660
|
+
return (jsx(Button$1, { iconPosition: "after", ...buttonProps, icon: Icon && jsx(Icon, {}), children: label && props.label }));
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
const CustomTokens = {
|
|
664
|
+
inputWidth: "150px",
|
|
665
|
+
lineHeight: "36px",
|
|
666
|
+
labelMinWidth: "50px",
|
|
667
|
+
sliderMinWidth: "30px",
|
|
668
|
+
sliderMaxWidth: "80px",
|
|
669
|
+
rightAlignOffset: "-8px",
|
|
670
|
+
};
|
|
671
|
+
const UniformWidthStyling = { width: CustomTokens.inputWidth, textAlign: "right", boxSizing: "border-box" };
|
|
672
|
+
const useInputStyles$1 = makeStyles({
|
|
673
|
+
invalid: { backgroundColor: tokens.colorPaletteRedBackground2, ...UniformWidthStyling },
|
|
674
|
+
valid: UniformWidthStyling,
|
|
675
|
+
});
|
|
676
|
+
function HandleOnBlur(event) {
|
|
677
|
+
event.stopPropagation();
|
|
678
|
+
event.preventDefault();
|
|
679
|
+
}
|
|
680
|
+
function HandleKeyDown(event) {
|
|
681
|
+
event.stopPropagation(); // Prevent event propagation
|
|
682
|
+
// Prevent Enter key from causing form submission or value reversion
|
|
683
|
+
if (event.key === "Enter") {
|
|
684
|
+
event.preventDefault();
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
634
688
|
const usePropertyLineStyles = makeStyles({
|
|
635
689
|
container: {
|
|
636
690
|
width: "100%",
|
|
637
691
|
display: "flex",
|
|
638
692
|
flexDirection: "column", // Stack line + expanded content
|
|
639
|
-
padding: `${tokens.spacingVerticalXS} 0px`,
|
|
640
|
-
borderBottom: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,
|
|
641
693
|
},
|
|
642
|
-
|
|
694
|
+
baseLine: {
|
|
695
|
+
height: CustomTokens.lineHeight,
|
|
643
696
|
display: "flex",
|
|
644
697
|
alignItems: "center",
|
|
645
698
|
justifyContent: "flex-start",
|
|
@@ -647,9 +700,8 @@ const usePropertyLineStyles = makeStyles({
|
|
|
647
700
|
},
|
|
648
701
|
label: {
|
|
649
702
|
flex: "1 1 0", // grow=1, shrink =1, basis = 0 initial size before
|
|
650
|
-
minWidth:
|
|
703
|
+
minWidth: CustomTokens.labelMinWidth,
|
|
651
704
|
textAlign: "left",
|
|
652
|
-
whiteSpace: "nowrap",
|
|
653
705
|
overflow: "hidden",
|
|
654
706
|
textOverflow: "ellipsis",
|
|
655
707
|
},
|
|
@@ -661,31 +713,15 @@ const usePropertyLineStyles = makeStyles({
|
|
|
661
713
|
display: "flex",
|
|
662
714
|
alignItems: "center",
|
|
663
715
|
justifyContent: "flex-end",
|
|
664
|
-
|
|
665
|
-
},
|
|
666
|
-
button: {
|
|
667
|
-
marginLeft: tokens.spacingHorizontalXXS,
|
|
668
|
-
margin: 0,
|
|
669
|
-
padding: 0,
|
|
670
|
-
border: 0,
|
|
671
|
-
minWidth: 0,
|
|
672
|
-
},
|
|
673
|
-
fillRestOfRightContentWidth: {
|
|
674
|
-
flex: 1,
|
|
675
|
-
display: "flex",
|
|
676
|
-
justifyContent: "flex-end",
|
|
677
|
-
alignItems: "center",
|
|
678
|
-
},
|
|
679
|
-
expandButton: {
|
|
680
|
-
margin: 0,
|
|
681
|
-
},
|
|
682
|
-
expandedContent: {
|
|
683
|
-
paddingLeft: "20px",
|
|
716
|
+
minWidth: "50%",
|
|
684
717
|
},
|
|
685
718
|
infoPopup: {
|
|
686
719
|
whiteSpace: "normal",
|
|
687
720
|
wordBreak: "break-word",
|
|
688
721
|
},
|
|
722
|
+
copy: {
|
|
723
|
+
marginRight: CustomTokens.rightAlignOffset, // Accounts for the padding baked into fluent button / ensures propertyLine looks visually aligned at the right
|
|
724
|
+
},
|
|
689
725
|
});
|
|
690
726
|
/**
|
|
691
727
|
* A reusable component that renders a property line with a label and child content, and an optional description, copy button, and expandable section.
|
|
@@ -710,7 +746,7 @@ const PropertyLine = forwardRef((props, ref) => {
|
|
|
710
746
|
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
|
|
711
747
|
})
|
|
712
748
|
: children;
|
|
713
|
-
return (jsxs(LineContainer, { ref: ref, children: [jsxs("div", { className: classes.
|
|
749
|
+
return (jsxs(LineContainer, { ref: ref, children: [jsxs("div", { className: classes.baseLine, children: [jsx(InfoLabel$1, { className: classes.label, info: description ? jsx("div", { className: classes.infoPopup, children: description }) : undefined, title: label, children: jsx(Body1Stronger, { 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 && (
|
|
714
750
|
// If this is a nullableProperty and ignoreNullable was not sent, display a checkbox used to toggle null ('checked' means 'non null')
|
|
715
751
|
jsx(Checkbox$1, { checked: !(props.value == null), onChange: (_, data) => {
|
|
716
752
|
if (data.checked) {
|
|
@@ -722,10 +758,7 @@ const PropertyLine = forwardRef((props, ref) => {
|
|
|
722
758
|
cachedVal.current = props.value;
|
|
723
759
|
props.onChange(null);
|
|
724
760
|
}
|
|
725
|
-
}, title: "Toggle null state" })), jsx(
|
|
726
|
-
e.stopPropagation();
|
|
727
|
-
setExpanded((expanded) => !expanded);
|
|
728
|
-
} })), onCopy && !disableCopy && (jsx(Button$1, { className: classes.button, id: "copyProperty", icon: jsx(CopyRegular, {}), onClick: () => copyCommandToClipboard(onCopy()), title: "Copy to clipboard" }))] })] }), expandedContent && (jsx(Collapse, { visible: !!expanded, children: jsx("div", { className: classes.expandedContent, children: expandedContent }) }))] }));
|
|
761
|
+
}, 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", { children: expandedContent }) }))] }));
|
|
729
762
|
});
|
|
730
763
|
const LineContainer = forwardRef((props, ref) => {
|
|
731
764
|
const classes = usePropertyLineStyles();
|
|
@@ -741,7 +774,7 @@ const PlaceholderPropertyLine = (props) => {
|
|
|
741
774
|
* @returns property-line wrapped link
|
|
742
775
|
*/
|
|
743
776
|
const LinkPropertyLine = (props) => {
|
|
744
|
-
return (jsx(PropertyLine, { ...props, children: jsx(Link, { inline: true,
|
|
777
|
+
return (jsx(PropertyLine, { ...props, children: jsx(Link, { inline: true, onClick: () => props.onLink?.(), href: props.url, title: props.title, children: jsx(Body1, { children: props.value }) }) }));
|
|
745
778
|
};
|
|
746
779
|
|
|
747
780
|
/**
|
|
@@ -763,12 +796,15 @@ const useStyles$e = makeStyles({
|
|
|
763
796
|
accordion: {
|
|
764
797
|
overflowX: "hidden",
|
|
765
798
|
overflowY: "auto",
|
|
766
|
-
|
|
799
|
+
paddingTop: tokens.spacingVerticalM, // ensures the first section header has the same padding as the others (due to divider)
|
|
767
800
|
display: "flex",
|
|
768
801
|
flexDirection: "column",
|
|
769
|
-
rowGap: tokens.spacingVerticalM,
|
|
770
802
|
height: "100%",
|
|
771
803
|
},
|
|
804
|
+
divider: {
|
|
805
|
+
paddingTop: "10px",
|
|
806
|
+
paddingBottom: "10px",
|
|
807
|
+
},
|
|
772
808
|
panelDiv: {
|
|
773
809
|
display: "flex",
|
|
774
810
|
flexDirection: "column",
|
|
@@ -822,7 +858,7 @@ const Accordion = (props) => {
|
|
|
822
858
|
}
|
|
823
859
|
}, []);
|
|
824
860
|
return (jsx(Accordion$1, { className: classes.accordion, collapsible: true, multiple: true, onToggle: onToggle, openItems: openItems, ...rest, children: validChildren.map((child) => {
|
|
825
|
-
return (jsxs(AccordionItem, { value: child.title, children: [jsx(AccordionHeader, {
|
|
861
|
+
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 }) }), jsx(Divider, { inset: true, className: classes.divider })] }, child.content.key));
|
|
826
862
|
}) }));
|
|
827
863
|
};
|
|
828
864
|
|
|
@@ -956,6 +992,32 @@ const TeachingMoment = ({ shouldDisplay, positioningRef, onOpenChange, title, de
|
|
|
956
992
|
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 })] }) }));
|
|
957
993
|
};
|
|
958
994
|
|
|
995
|
+
/**
|
|
996
|
+
* A simple extension feed implementation that provides a fixed set of "built in" extensions.
|
|
997
|
+
* "Built in" in this context means extensions that are known at bundling time, and included
|
|
998
|
+
* in the bundle. Each extension can be dynamically imported so they are split into separate
|
|
999
|
+
* bundle chunks and downloaded only when first installed.
|
|
1000
|
+
*/
|
|
1001
|
+
class BuiltInsExtensionFeed {
|
|
1002
|
+
constructor(name, extensions) {
|
|
1003
|
+
this.name = name;
|
|
1004
|
+
this._extensions = Array.from(extensions);
|
|
1005
|
+
}
|
|
1006
|
+
async queryExtensionsAsync(filter) {
|
|
1007
|
+
const filteredExtensions = filter ? this._extensions.filter((extension) => extension.name.includes(filter)) : this._extensions;
|
|
1008
|
+
return {
|
|
1009
|
+
totalCount: filteredExtensions.length,
|
|
1010
|
+
getExtensionMetadataAsync: async (index, count) => {
|
|
1011
|
+
return filteredExtensions.slice(index, index + count);
|
|
1012
|
+
},
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
async getExtensionModuleAsync(name) {
|
|
1016
|
+
const extension = this._extensions.find((ext) => ext.name === name);
|
|
1017
|
+
return extension ? await extension.getExtensionModuleAsync() : undefined;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
959
1021
|
/**
|
|
960
1022
|
* Creates a polling observable that notifies its observers at a specified interval.
|
|
961
1023
|
* @param delay The polling interval in milliseconds.
|
|
@@ -1506,7 +1568,7 @@ function usePane(alignment, defaultWidth, minWidth, topPaneComponents, bottomPan
|
|
|
1506
1568
|
});
|
|
1507
1569
|
// This memoizes the pane itself, which may or may not include the tab list, depending on the toolbar mode.
|
|
1508
1570
|
const pane = useMemo(() => {
|
|
1509
|
-
return (jsx(Fragment, { children: (topPaneComponents.length > 0 || bottomPaneComponents.length > 0) && (jsxs("div", { className: `${classes.pane} ${alignment === "left" ? classes.paneLeft : classes.paneRight}`, children: [jsx(Collapse, { orientation: "horizontal", visible: !collapsed, children: jsxs("div", { className: classes.paneContainer, style: { width: `${width}px` }, children: [toolbarMode === "compact" && (topPaneComponents.length > 1 || topBarComponents.length > 0) && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [topPaneTabList, jsx(Toolbar, { location: "top", components: topBarComponents })] }) })), jsxs("div", { className: classes.paneContent, children: [topSelectedTab?.title ? (jsxs(Fragment, { children: [jsx(Title3, { className: classes.paneHeader, children: topSelectedTab.title }), jsx(Divider, { inset: true, className: classes.headerDivider, appearance: "brand" })] })) : null, topSelectedTab?.content && jsx(topSelectedTab.content, {})] }), topPaneComponents.length > 0 && bottomPaneComponents.length > 0 && (jsx(Divider, { ref: paneVerticalResizeHandleRef, className: classes.headerDivider, style: { margin: "0", minHeight: tokens.spacingVerticalM, cursor: "ns-resize" } })), bottomPaneComponents.length > 1 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: bottomPaneTabList }) })), jsxs("div", { ref: paneVerticalResizeElementRef, className: classes.paneContent, style: { height: `clamp(200px,calc(45% + var(${paneHeightAdjustCSSVar}, 0px)), 100% - 300px)`, flex: "0 0 auto" }, children: [bottomSelectedTab?.title ? (jsxs(Fragment, { children: [jsx(Title3, { className: classes.paneHeader, children: bottomSelectedTab.title }), jsx(Divider, { inset: true, className: classes.headerDivider, appearance: "brand" })] })) : null, bottomSelectedTab?.content && jsx(bottomSelectedTab.content, {})] }), toolbarMode === "compact" && bottomBarComponents.length > 0 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarComponents }) }) }))] }) }), jsx("div", { className: `${classes.resizer} ${alignment === "left" ? classes.resizerLeft : classes.resizerRight}`, style: { pointerEvents: `${collapsed ? "none" : "auto"}` }, onPointerDown: onResizerPointerDown })] })) }));
|
|
1571
|
+
return (jsx(Fragment, { children: (topPaneComponents.length > 0 || bottomPaneComponents.length > 0) && (jsxs("div", { className: `${classes.pane} ${alignment === "left" ? classes.paneLeft : classes.paneRight}`, children: [jsx(Collapse, { orientation: "horizontal", visible: !collapsed, children: jsxs("div", { className: classes.paneContainer, style: { width: `${width}px` }, children: [toolbarMode === "compact" && (topPaneComponents.length > 1 || topBarComponents.length > 0) && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [topPaneTabList, jsx(Toolbar, { location: "top", components: topBarComponents })] }) })), jsxs("div", { className: classes.paneContent, children: [topSelectedTab?.title ? (jsxs(Fragment, { children: [jsx(Title3, { className: classes.paneHeader, children: topSelectedTab.title }), jsx(Divider, { inset: true, className: classes.headerDivider, appearance: "brand" })] })) : null, topSelectedTab?.content && jsx(topSelectedTab.content, {})] }), topPaneComponents.length > 0 && bottomPaneComponents.length > 0 && (jsx(Divider, { ref: paneVerticalResizeHandleRef, className: classes.headerDivider, style: { margin: "0", minHeight: tokens.spacingVerticalM, cursor: "ns-resize" } })), bottomPaneComponents.length > 1 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: bottomPaneTabList }) })), bottomPaneComponents.length > 0 && (jsxs("div", { ref: paneVerticalResizeElementRef, className: classes.paneContent, style: { height: `clamp(200px,calc(45% + var(${paneHeightAdjustCSSVar}, 0px)), 100% - 300px)`, flex: "0 0 auto" }, children: [bottomSelectedTab?.title ? (jsxs(Fragment, { children: [jsx(Title3, { className: classes.paneHeader, children: bottomSelectedTab.title }), jsx(Divider, { inset: true, className: classes.headerDivider, appearance: "brand" })] })) : null, bottomSelectedTab?.content && jsx(bottomSelectedTab.content, {})] })), toolbarMode === "compact" && bottomBarComponents.length > 0 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarComponents }) }) }))] }) }), jsx("div", { className: `${classes.resizer} ${alignment === "left" ? classes.resizerLeft : classes.resizerRight}`, style: { pointerEvents: `${collapsed ? "none" : "auto"}` }, onPointerDown: onResizerPointerDown })] })) }));
|
|
1510
1572
|
}, [topPaneComponents, topSelectedTab, bottomPaneComponents, bottomSelectedTab, collapsed, width, resizing]);
|
|
1511
1573
|
return [topPaneTabList, pane];
|
|
1512
1574
|
}
|
|
@@ -1662,29 +1724,6 @@ const PropertiesServiceDefinition = {
|
|
|
1662
1724
|
},
|
|
1663
1725
|
};
|
|
1664
1726
|
|
|
1665
|
-
/**
|
|
1666
|
-
* Toggles between two states using a button with icons.
|
|
1667
|
-
* If no disabledIcon is provided, the button will toggle between visual enabled/disabled states without an icon change
|
|
1668
|
-
*
|
|
1669
|
-
* @param props
|
|
1670
|
-
* @returns
|
|
1671
|
-
*/
|
|
1672
|
-
const ToggleButton = (props) => {
|
|
1673
|
-
const { value, onChange, title, appearance = "subtle" } = props;
|
|
1674
|
-
const [checked, setChecked] = useState(value);
|
|
1675
|
-
const toggle = useCallback(() => {
|
|
1676
|
-
setChecked((prev) => {
|
|
1677
|
-
const enabled = !prev;
|
|
1678
|
-
onChange(enabled);
|
|
1679
|
-
return enabled;
|
|
1680
|
-
});
|
|
1681
|
-
}, [setChecked]);
|
|
1682
|
-
useEffect(() => {
|
|
1683
|
-
setChecked(props.value);
|
|
1684
|
-
}, [props.value]);
|
|
1685
|
-
return (jsx(ToggleButton$1, { title: title, icon: checked ? jsx(props.enabledIcon, {}) : props.disabledIcon ? jsx(props.disabledIcon, {}) : jsx(props.enabledIcon, {}), appearance: appearance, checked: checked, onClick: toggle }));
|
|
1686
|
-
};
|
|
1687
|
-
|
|
1688
1727
|
/**
|
|
1689
1728
|
* Performs a topological sort on a graph.
|
|
1690
1729
|
* @param graph The set of nodes that make up the graph.
|
|
@@ -1811,7 +1850,7 @@ const ToggleCommand = (props) => {
|
|
|
1811
1850
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1812
1851
|
const [displayName, Icon, isEnabled] = useObservableState(useCallback(() => [command.displayName, command.icon, command.isEnabled], [command]), command.onChange);
|
|
1813
1852
|
// TODO-iv2: Consolidate icon prop passing approach for inspector and shared components
|
|
1814
|
-
return jsx(ToggleButton, { appearance: "transparent", title: displayName,
|
|
1853
|
+
return jsx(ToggleButton, { appearance: "transparent", title: displayName, checkedIcon: Icon, value: isEnabled, onChange: (val) => (command.isEnabled = val) });
|
|
1815
1854
|
};
|
|
1816
1855
|
const SceneTreeItem = (props) => {
|
|
1817
1856
|
const { isSelected, select } = props;
|
|
@@ -2479,18 +2518,6 @@ const FrameStepsStats = ({ context: scene }) => {
|
|
|
2479
2518
|
return (jsxs(Fragment, { children: [jsx(StringifiedPropertyLine, { label: "Absolute FPS", value: absoluteFPS }, "AbsoluteFPS"), jsx(StringifiedPropertyLine, { label: "Meshes Selection", value: meshesSelection, precision: 2, units: "ms" }, "MeshesSelection"), jsx(StringifiedPropertyLine, { label: "Render Targets", value: renderTargets, precision: 2, units: "ms" }, "RenderTargets"), jsx(StringifiedPropertyLine, { label: "Particles", value: particles, precision: 2, units: "ms" }, "Particles"), jsx(StringifiedPropertyLine, { label: "Sprites", value: sprites, precision: 2, units: "ms" }, "Sprites"), jsx(StringifiedPropertyLine, { label: "Animations", value: animations, precision: 2, units: "ms" }, "Animations"), jsx(StringifiedPropertyLine, { label: "Physics", value: physics, precision: 2, units: "ms" }, "Physics"), jsx(StringifiedPropertyLine, { label: "Inter-Frame Time", value: interFrameTime, precision: 2, units: "ms" }, "InterFrameTime"), jsx(StringifiedPropertyLine, { label: "GPU Frame Time", value: gpuFrameTime, precision: 2, units: "ms" }, "GPUFrameTime"), jsx(StringifiedPropertyLine, { label: "GPU Frame Time (Average)", value: gpuFrameTimeAverage, precision: 2, units: "ms" }, "GPUFrameTimeAverage")] }));
|
|
2480
2519
|
};
|
|
2481
2520
|
|
|
2482
|
-
const useButtonLineStyles = makeStyles({
|
|
2483
|
-
button: {
|
|
2484
|
-
border: `1px solid ${tokens.colorBrandBackground}`,
|
|
2485
|
-
},
|
|
2486
|
-
});
|
|
2487
|
-
const Button = (props) => {
|
|
2488
|
-
const classes = useButtonLineStyles();
|
|
2489
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
2490
|
-
const { icon: Icon, ...buttonProps } = props;
|
|
2491
|
-
return (jsx(Button$1, { iconPosition: "after", className: classes.button, ...buttonProps, icon: Icon && jsx(Icon, {}), children: jsx(Body1, { children: props.label }) }));
|
|
2492
|
-
};
|
|
2493
|
-
|
|
2494
2521
|
/**
|
|
2495
2522
|
* Wraps a button with a label in a line container
|
|
2496
2523
|
* @param props Button props plus a label
|
|
@@ -2781,59 +2808,35 @@ const ToolsServiceDefinition = {
|
|
|
2781
2808
|
},
|
|
2782
2809
|
};
|
|
2783
2810
|
|
|
2784
|
-
// This file contains "built in" extensions. They are optional and installed/uninstalled by the user, but they are
|
|
2785
|
-
// well-known at build time and the extension is "downloaded" by simply doing a dynamic import. This is different
|
|
2786
|
-
// from future extension types that are built and published apart from the inspector, and are downloaded as an isolated script.
|
|
2787
|
-
const CreationToolsExtensionMetadata = {
|
|
2788
|
-
name: "Asset Creation"};
|
|
2789
|
-
const ExportToolsExtensionMetadata = {
|
|
2790
|
-
name: "Export Tools",
|
|
2791
|
-
description: "Adds new features to enable exporting Babylon assets such as .gltf, .glb, .babylon, and more.",
|
|
2792
|
-
keywords: ["export", "gltf", "glb", "babylon", "exporter", "tools"],
|
|
2793
|
-
};
|
|
2794
|
-
const CaptureToolsExtensionMetadata = {
|
|
2795
|
-
name: "Capture Tools",
|
|
2796
|
-
description: "Adds new features to enable capturing screenshots, GIFs, videos, and more.",
|
|
2797
|
-
keywords: ["capture", "screenshot", "gif", "video", "tools"],
|
|
2798
|
-
};
|
|
2799
|
-
const ImportToolsExtensionMetadata = {
|
|
2800
|
-
name: "Import Tools",
|
|
2801
|
-
description: "Adds new features related to importing Babylon assets.",
|
|
2802
|
-
keywords: ["import", "tools"],
|
|
2803
|
-
};
|
|
2804
|
-
const Extensions = [/*CreationToolsExtensionMetadata, */ ExportToolsExtensionMetadata, CaptureToolsExtensionMetadata, ImportToolsExtensionMetadata];
|
|
2805
2811
|
/**
|
|
2806
|
-
*
|
|
2812
|
+
* Well-known default built in extensions for the Inspector.
|
|
2807
2813
|
*/
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
return undefined;
|
|
2835
|
-
}
|
|
2836
|
-
}
|
|
2814
|
+
const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
2815
|
+
// {
|
|
2816
|
+
// name: "Asset Creation",
|
|
2817
|
+
// description: "Adds new features to enable creating Babylon assets such as node materials, flow graphs, and more.",
|
|
2818
|
+
// keywords: ["creation"],
|
|
2819
|
+
// getExtensionModuleAsync: async () => await import("../services/creationToolsService"),
|
|
2820
|
+
// },
|
|
2821
|
+
{
|
|
2822
|
+
name: "Export Tools",
|
|
2823
|
+
description: "Adds new features to enable exporting Babylon assets such as .gltf, .glb, .babylon, and more.",
|
|
2824
|
+
keywords: ["export", "gltf", "glb", "babylon", "exporter", "tools"],
|
|
2825
|
+
getExtensionModuleAsync: async () => await import('./exportService-DRm8glYV.js'),
|
|
2826
|
+
},
|
|
2827
|
+
{
|
|
2828
|
+
name: "Capture Tools",
|
|
2829
|
+
description: "Adds new features to enable capturing screenshots, GIFs, videos, and more.",
|
|
2830
|
+
keywords: ["capture", "screenshot", "gif", "video", "tools"],
|
|
2831
|
+
getExtensionModuleAsync: async () => await import('./captureService-BEferXko.js'),
|
|
2832
|
+
},
|
|
2833
|
+
{
|
|
2834
|
+
name: "Import Tools",
|
|
2835
|
+
description: "Adds new features related to importing Babylon assets.",
|
|
2836
|
+
keywords: ["import", "tools"],
|
|
2837
|
+
getExtensionModuleAsync: async () => await import('./importService-CUFQ5Mb2.js'),
|
|
2838
|
+
},
|
|
2839
|
+
]);
|
|
2837
2840
|
|
|
2838
2841
|
const ExtensionManagerContext = createContext(undefined);
|
|
2839
2842
|
function useExtensionManager() {
|
|
@@ -3107,6 +3110,27 @@ class ExtensionManager {
|
|
|
3107
3110
|
}
|
|
3108
3111
|
}
|
|
3109
3112
|
|
|
3113
|
+
const ThemeModeStorageKey = `Babylon/Settings/ThemeMode`;
|
|
3114
|
+
/**
|
|
3115
|
+
* Custom hook to manage the theme mode (light/dark/auto).
|
|
3116
|
+
* @param modeOverride If specified, any previously stored theme mode will be replaced with this mode.
|
|
3117
|
+
* @returns An object containing the theme mode state and helper functions.
|
|
3118
|
+
*/
|
|
3119
|
+
function useThemeMode(modeOverride) {
|
|
3120
|
+
const { isDarkMode, ternaryDarkMode, setTernaryDarkMode } = useTernaryDarkMode({
|
|
3121
|
+
defaultValue: modeOverride,
|
|
3122
|
+
initializeWithValue: !modeOverride,
|
|
3123
|
+
localStorageKey: ThemeModeStorageKey,
|
|
3124
|
+
});
|
|
3125
|
+
// If a modeOverride is provided, replace any previously stored mode.
|
|
3126
|
+
// Also make sure there is a stored value initially, even before changing the theme.
|
|
3127
|
+
// This way, other usages of this hook will get the correct initial value.
|
|
3128
|
+
if (modeOverride || !localStorage.getItem(ThemeModeStorageKey)) {
|
|
3129
|
+
localStorage.setItem(ThemeModeStorageKey, JSON.stringify(ternaryDarkMode));
|
|
3130
|
+
}
|
|
3131
|
+
return { isDarkMode, themeMode: ternaryDarkMode, setThemeMode: setTernaryDarkMode };
|
|
3132
|
+
}
|
|
3133
|
+
|
|
3110
3134
|
// This sorts a set of service definitions based on their dependencies (e.g. a topological sort).
|
|
3111
3135
|
function SortServiceDefinitions(serviceDefinitions) {
|
|
3112
3136
|
const sortedServiceDefinitions = [];
|
|
@@ -3390,14 +3414,14 @@ const ThemeSelectorServiceDefinition = {
|
|
|
3390
3414
|
order: -300,
|
|
3391
3415
|
component: () => {
|
|
3392
3416
|
const classes = useStyles$6();
|
|
3393
|
-
const { isDarkMode,
|
|
3417
|
+
const { isDarkMode, themeMode, setThemeMode } = useThemeMode();
|
|
3394
3418
|
const onSelectedThemeChange = useCallback((e, data) => {
|
|
3395
|
-
|
|
3419
|
+
setThemeMode(data.checkedItems.includes("System") ? "system" : data.checkedItems[0].toLocaleLowerCase());
|
|
3396
3420
|
}, []);
|
|
3397
3421
|
const toggleTheme = useCallback(() => {
|
|
3398
|
-
|
|
3422
|
+
setThemeMode(isDarkMode ? "light" : "dark");
|
|
3399
3423
|
}, [isDarkMode]);
|
|
3400
|
-
return (jsxs(Menu, { positioning: "below-end", checkedValues: { theme: [
|
|
3424
|
+
return (jsxs(Menu, { positioning: "below-end", checkedValues: { theme: [themeMode] }, onCheckedValueChange: onSelectedThemeChange, children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: (triggerProps) => (jsx(Tooltip, { content: "Select Theme", relationship: "label", children: jsx(SplitButton, { className: classes.themeButton, menuButton: triggerProps, primaryActionButton: { onClick: toggleTheme }, size: "small", appearance: "secondary", shape: "circular", icon: isDarkMode ? jsx(WeatherSunnyRegular, {}) : jsx(WeatherMoonRegular, {}) }) })) }), jsx(MenuPopover, { className: classes.themeMenuPopover, children: jsxs(MenuList, { children: [jsx(MenuItemRadio, { name: "theme", value: "system", children: "System" }), jsx(MenuItemRadio, { name: "theme", value: "light", children: "Light" }), jsx(MenuItemRadio, { name: "theme", value: "dark", children: "Dark" })] }) })] }));
|
|
3401
3425
|
},
|
|
3402
3426
|
});
|
|
3403
3427
|
return {
|
|
@@ -3466,11 +3490,11 @@ const useStyles$5 = makeStyles({
|
|
|
3466
3490
|
* @returns A token that can be used to dispose of the tool.
|
|
3467
3491
|
*/
|
|
3468
3492
|
function MakeModularTool(options) {
|
|
3469
|
-
const { containerElement, serviceDefinitions,
|
|
3493
|
+
const { containerElement, serviceDefinitions, themeMode, showThemeSelector = true, extensionFeeds = [] } = options;
|
|
3470
3494
|
const modularToolRootComponent = () => {
|
|
3471
3495
|
const classes = useStyles$5();
|
|
3472
3496
|
const [extensionManagerContext, setExtensionManagerContext] = useState();
|
|
3473
|
-
const { isDarkMode } =
|
|
3497
|
+
const { isDarkMode } = useThemeMode(themeMode);
|
|
3474
3498
|
const [requiredExtensions, setRequiredExtensions] = useState();
|
|
3475
3499
|
const [requiredExtensionsDeferred, setRequiredExtensionsDeferred] = useState();
|
|
3476
3500
|
const [extensionInstallError, setExtensionInstallError] = useState();
|
|
@@ -3498,7 +3522,7 @@ function MakeModularTool(options) {
|
|
|
3498
3522
|
await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);
|
|
3499
3523
|
}
|
|
3500
3524
|
// Register the theme selector service (for selecting the theme) if theming is configured.
|
|
3501
|
-
if (
|
|
3525
|
+
if (showThemeSelector) {
|
|
3502
3526
|
await serviceContainer.addServiceAsync(ThemeSelectorServiceDefinition);
|
|
3503
3527
|
}
|
|
3504
3528
|
// Register all external services (that make up a unique tool).
|
|
@@ -3770,7 +3794,7 @@ const GizmoToolbar = (props) => {
|
|
|
3770
3794
|
const toggleCoordinatesMode = useCallback(() => {
|
|
3771
3795
|
gizmoManager.coordinatesMode = coordinatesMode === 1 /* GizmoCoordinatesMode.Local */ ? 0 /* GizmoCoordinatesMode.World */ : 1 /* GizmoCoordinatesMode.Local */;
|
|
3772
3796
|
}, [gizmoManager, coordinatesMode]);
|
|
3773
|
-
return (jsxs(Fragment, { children: [jsx(ToggleButton, { title: "Translate",
|
|
3797
|
+
return (jsxs(Fragment, { children: [jsx(ToggleButton, { title: "Translate", checkedIcon: ArrowMoveRegular, value: gizmoMode === "translate", onChange: () => updateGizmoMode("translate") }), jsx(ToggleButton, { title: "Rotate", checkedIcon: ArrowRotateClockwiseRegular, value: gizmoMode === "rotate", onChange: () => updateGizmoMode("rotate") }), jsx(ToggleButton, { title: "Scale", checkedIcon: ArrowExpandRegular, value: gizmoMode === "scale", onChange: () => updateGizmoMode("scale") }), jsx(ToggleButton, { title: "Bounding Box", checkedIcon: SelectObjectRegular, value: gizmoMode === "boundingBox", onChange: () => updateGizmoMode("boundingBox") }), jsx(Collapse, { visible: !!gizmoMode, orientation: "horizontal", children: jsxs(Menu, { positioning: "below-end", checkedValues: { coordinatesMode: [coordinatesMode.toString()] }, onCheckedValueChange: onCoordinatesModeChange, children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: (triggerProps) => (jsx(Tooltip, { content: "Coordinates Mode", relationship: "label", children: jsx(SplitButton, { className: classes.coordinatesModeButton, menuButton: triggerProps, primaryActionButton: {
|
|
3774
3798
|
onClick: toggleCoordinatesMode,
|
|
3775
3799
|
}, size: "small", appearance: "secondary", shape: "rounded", icon: coordinatesMode === 1 /* GizmoCoordinatesMode.Local */ ? jsx(CubeRegular, {}) : jsx(GlobeRegular, {}) }) })) }), jsx(MenuPopover, { className: classes.coordinatesModeMenu, children: jsxs(MenuList, { children: [jsx(MenuItemRadio, { name: "coordinatesMode", value: 1 /* GizmoCoordinatesMode.Local */.toString(), children: "Local" }), jsx(MenuItemRadio, { name: "coordinatesMode", value: 0 /* GizmoCoordinatesMode.World */.toString(), children: "World" })] }) })] }) })] }));
|
|
3776
3800
|
};
|
|
@@ -3804,31 +3828,11 @@ const TargetedAnimationGeneralProperties = (props) => {
|
|
|
3804
3828
|
* @returns
|
|
3805
3829
|
*/
|
|
3806
3830
|
const InfoLabel = (props) => {
|
|
3807
|
-
return (jsx(InfoLabel$1, { htmlFor: props.htmlFor, info: props.info, children: props.label }));
|
|
3831
|
+
return (jsx(InfoLabel$1, { htmlFor: props.htmlFor, info: props.info, children: jsx(Body1, { children: props.label }) }));
|
|
3808
3832
|
};
|
|
3809
3833
|
|
|
3810
|
-
function HandleOnBlur(event) {
|
|
3811
|
-
event.stopPropagation();
|
|
3812
|
-
event.preventDefault();
|
|
3813
|
-
}
|
|
3814
|
-
function HandleKeyDown(event) {
|
|
3815
|
-
event.stopPropagation(); // Prevent event propagation
|
|
3816
|
-
// Prevent Enter key from causing form submission or value reversion
|
|
3817
|
-
if (event.key === "Enter") {
|
|
3818
|
-
event.preventDefault();
|
|
3819
|
-
}
|
|
3820
|
-
}
|
|
3821
|
-
|
|
3822
|
-
const useSpinStyles = makeStyles({
|
|
3823
|
-
base: {
|
|
3824
|
-
display: "flex",
|
|
3825
|
-
flexDirection: "column",
|
|
3826
|
-
minWidth: "55px",
|
|
3827
|
-
},
|
|
3828
|
-
invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },
|
|
3829
|
-
});
|
|
3830
3834
|
const SpinButton = (props) => {
|
|
3831
|
-
const classes =
|
|
3835
|
+
const classes = useInputStyles$1();
|
|
3832
3836
|
const { min, max } = props;
|
|
3833
3837
|
const [value, setValue] = useState(props.value);
|
|
3834
3838
|
const lastCommittedValue = useRef(props.value);
|
|
@@ -3870,7 +3874,7 @@ const SpinButton = (props) => {
|
|
|
3870
3874
|
}
|
|
3871
3875
|
};
|
|
3872
3876
|
const id = useId("spin-button");
|
|
3873
|
-
return (jsxs("div", {
|
|
3877
|
+
return (jsxs("div", { children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(SpinButton$1, { ...props, step: step, id: id, size: "medium", precision: CalculatePrecision(step ?? 1.01), displayValue: props.unit ? `${PrecisionRound(value, CalculatePrecision(step ?? 1.01))} ${props.unit}` : undefined, value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: HandleOnBlur, className: `${!validateValue(value) ? classes.invalid : classes.valid}` })] }));
|
|
3874
3878
|
};
|
|
3875
3879
|
/**
|
|
3876
3880
|
* Fluent's CalculatePrecision function
|
|
@@ -3917,18 +3921,16 @@ function PrecisionRound(value, precision) {
|
|
|
3917
3921
|
}
|
|
3918
3922
|
|
|
3919
3923
|
const useSyncedSliderStyles = makeStyles({
|
|
3924
|
+
container: { display: "flex" },
|
|
3920
3925
|
syncedSlider: {
|
|
3926
|
+
flex: "1 1 0",
|
|
3927
|
+
flexDirection: "row",
|
|
3921
3928
|
display: "flex",
|
|
3922
3929
|
alignItems: "center",
|
|
3923
|
-
gap: tokens.spacingHorizontalXXS, // 2px
|
|
3924
|
-
width: "100%", // Only fill available space
|
|
3925
3930
|
},
|
|
3926
3931
|
slider: {
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
},
|
|
3930
|
-
spinButton: {
|
|
3931
|
-
width: "60px",
|
|
3932
|
+
minWidth: CustomTokens.sliderMinWidth, // Minimum width for slider to remain usable
|
|
3933
|
+
maxWidth: CustomTokens.sliderMaxWidth,
|
|
3932
3934
|
},
|
|
3933
3935
|
});
|
|
3934
3936
|
/**
|
|
@@ -3937,6 +3939,7 @@ const useSyncedSliderStyles = makeStyles({
|
|
|
3937
3939
|
* @returns SyncedSlider component
|
|
3938
3940
|
*/
|
|
3939
3941
|
const SyncedSliderInput = (props) => {
|
|
3942
|
+
const { infoLabel, ...passthroughProps } = props;
|
|
3940
3943
|
const classes = useSyncedSliderStyles();
|
|
3941
3944
|
const [value, setValue] = useState(props.value);
|
|
3942
3945
|
const pendingValueRef = useRef(undefined);
|
|
@@ -3976,7 +3979,7 @@ const SyncedSliderInput = (props) => {
|
|
|
3976
3979
|
setValue(value);
|
|
3977
3980
|
props.onChange(value); // Input always updates immediately
|
|
3978
3981
|
};
|
|
3979
|
-
return (jsxs("div", { className: classes.syncedSlider, children: [props.min !== undefined && props.max !== undefined && (jsx(Slider, { ...
|
|
3982
|
+
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: Math.round(value / step) * step, onChange: handleInputChange, step: props.step })] })] }));
|
|
3980
3983
|
};
|
|
3981
3984
|
|
|
3982
3985
|
/**
|
|
@@ -3989,14 +3992,6 @@ const SyncedSliderPropertyLine = forwardRef((props, ref) => {
|
|
|
3989
3992
|
return (jsx(PropertyLine, { ref: ref, ...props, children: jsx(SyncedSliderInput, { ...sliderProps }) }));
|
|
3990
3993
|
});
|
|
3991
3994
|
|
|
3992
|
-
const useInputStyles$1 = makeStyles({
|
|
3993
|
-
base: {
|
|
3994
|
-
display: "flex",
|
|
3995
|
-
flexDirection: "column",
|
|
3996
|
-
width: "100px",
|
|
3997
|
-
},
|
|
3998
|
-
invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },
|
|
3999
|
-
});
|
|
4000
3995
|
const TextInput = (props) => {
|
|
4001
3996
|
const classes = useInputStyles$1();
|
|
4002
3997
|
const [value, setValue] = useState(props.value);
|
|
@@ -4029,7 +4024,7 @@ const TextInput = (props) => {
|
|
|
4029
4024
|
tryCommitValue(event.currentTarget.value);
|
|
4030
4025
|
};
|
|
4031
4026
|
const id = useId("input-button");
|
|
4032
|
-
return (jsxs("div", {
|
|
4027
|
+
return (jsxs("div", { children: [props.infoLabel && jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), jsx(Input, { ...props, id: id, size: "medium", value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: HandleOnBlur, className: `${!validateValue(value) ? classes.invalid : classes.valid}` })] }));
|
|
4033
4028
|
};
|
|
4034
4029
|
|
|
4035
4030
|
/**
|
|
@@ -4241,7 +4236,7 @@ const TensorPropertyLine = (props) => {
|
|
|
4241
4236
|
setVector(newVector);
|
|
4242
4237
|
props.onChange(newVector);
|
|
4243
4238
|
};
|
|
4244
|
-
return (jsx(PropertyLine, { ...props, onCopy: () => `(${vector.x}
|
|
4239
|
+
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)}` : ""}]` }) }));
|
|
4245
4240
|
};
|
|
4246
4241
|
const ToDegreesConverter = { from: Tools.ToDegrees, to: Tools.ToRadians };
|
|
4247
4242
|
const RotationVectorPropertyLine = (props) => {
|
|
@@ -4270,72 +4265,318 @@ const QuaternionPropertyLine = (props) => {
|
|
|
4270
4265
|
const Vector2PropertyLine = TensorPropertyLine;
|
|
4271
4266
|
const Vector3PropertyLine = TensorPropertyLine;
|
|
4272
4267
|
|
|
4273
|
-
const
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4268
|
+
const useColorPickerStyles = makeStyles({
|
|
4269
|
+
colorPickerContainer: {
|
|
4270
|
+
width: "325px",
|
|
4271
|
+
display: "flex",
|
|
4272
|
+
flexDirection: "column",
|
|
4273
|
+
gap: tokens.spacingVerticalMNudge, // 10px
|
|
4274
|
+
overflow: "visible",
|
|
4275
|
+
},
|
|
4276
|
+
previewColor: {
|
|
4277
|
+
width: "50px",
|
|
4278
|
+
height: "50px",
|
|
4279
|
+
borderRadius: tokens.borderRadiusMedium,
|
|
4280
|
+
border: `${tokens.spacingVerticalXXS} solid ${tokens.colorNeutralShadowKeyLighter}`,
|
|
4281
|
+
"@media (forced-colors: active)": {
|
|
4282
|
+
forcedColorAdjust: "none", // ensures elmement maintains color in high constrast mode
|
|
4283
|
+
},
|
|
4284
|
+
},
|
|
4285
|
+
row: {
|
|
4286
|
+
display: "flex",
|
|
4287
|
+
flexDirection: "row",
|
|
4288
|
+
gap: tokens.spacingVerticalM, // 12px
|
|
4289
|
+
alignItems: "center",
|
|
4290
|
+
},
|
|
4291
|
+
colorFieldWrapper: {
|
|
4292
|
+
display: "flex",
|
|
4293
|
+
flexDirection: "column",
|
|
4294
|
+
gap: tokens.spacingVerticalSNudge, // 6px
|
|
4295
|
+
},
|
|
4296
|
+
input: {
|
|
4297
|
+
width: "80px",
|
|
4298
|
+
},
|
|
4299
|
+
spinButton: {
|
|
4300
|
+
width: "50px",
|
|
4301
|
+
},
|
|
4302
|
+
container: {
|
|
4303
|
+
display: "flex",
|
|
4304
|
+
flexDirection: "column",
|
|
4305
|
+
gap: tokens.spacingVerticalL, // 16px
|
|
4307
4306
|
},
|
|
4308
|
-
optionsLine: {},
|
|
4309
4307
|
});
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
* @returns dropdown component
|
|
4315
|
-
*/
|
|
4316
|
-
const Dropdown = (props) => {
|
|
4317
|
-
const classes = useDropdownStyles();
|
|
4318
|
-
const { options, value } = props;
|
|
4319
|
-
const [defaultVal, setDefaultVal] = useState(props.value);
|
|
4308
|
+
const ColorPickerPopup = (props) => {
|
|
4309
|
+
const classes = useColorPickerStyles();
|
|
4310
|
+
const [color, setColor] = useState(props.value);
|
|
4311
|
+
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
4320
4312
|
useEffect(() => {
|
|
4321
|
-
|
|
4313
|
+
setColor(props.value); // Ensures the trigger color updates when props.value changes
|
|
4322
4314
|
}, [props.value]);
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4315
|
+
const handleColorPickerChange = (_, data) => {
|
|
4316
|
+
let color = Color3.FromHSV(data.color.h, data.color.s, data.color.v);
|
|
4317
|
+
if (props.value instanceof Color4) {
|
|
4318
|
+
color = Color4.FromColor3(color, data.color.a ?? 1);
|
|
4319
|
+
}
|
|
4320
|
+
handleChange(color);
|
|
4321
|
+
};
|
|
4322
|
+
const handleChange = (newColor) => {
|
|
4323
|
+
setColor(newColor);
|
|
4324
|
+
props.onChange(newColor); // Ensures the parent is notified when color changes from within colorPicker
|
|
4325
|
+
};
|
|
4326
|
+
return (jsxs(Popover, { positioning: {
|
|
4327
|
+
align: "start",
|
|
4328
|
+
overflowBoundary: document.body,
|
|
4329
|
+
autoSize: true,
|
|
4330
|
+
}, open: popoverOpen, trapFocus: true, onOpenChange: (_, data) => setPopoverOpen(data.open), children: [jsx(PopoverTrigger, { disableButtonEnhancement: true, children: jsx(ColorSwatch, { borderColor: tokens.colorNeutralShadowKeyDarker, size: "small", color: color.toHexString(), value: color.toHexString().slice(1) }) }), jsx(PopoverSurface, { children: jsxs("div", { className: classes.colorPickerContainer, children: [jsxs(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.container, children: [jsxs("div", { className: classes.row, children: [jsx("div", { className: classes.previewColor, style: { backgroundColor: color.toHexString() } }), jsx(InputHexField, { title: "Gamma Hex", value: color, isLinearMode: props.isLinearMode, onChange: handleChange }), jsx(InputHexField, { title: "Linear Hex", linearHex: true, isLinearMode: props.isLinearMode, value: color, onChange: handleChange })] }), jsxs("div", { className: classes.row, children: [jsx(InputRgbField, { title: "Red", value: color, rgbKey: "r", onChange: handleChange }), jsx(InputRgbField, { title: "Green", value: color, rgbKey: "g", onChange: handleChange }), jsx(InputRgbField, { title: "Blue", value: color, rgbKey: "b", onChange: handleChange }), jsx(InputAlphaField, { color: color, onChange: handleChange })] }), jsxs("div", { className: classes.row, children: [jsx(InputHsvField, { title: "Hue", value: color, hsvKey: "h", max: 360, onChange: handleChange }), jsx(InputHsvField, { title: "Saturation", value: color, hsvKey: "s", max: 100, scale: 100, onChange: handleChange }), jsx(InputHsvField, { title: "Value", value: color, hsvKey: "v", max: 100, scale: 100, onChange: handleChange })] })] })] }) })] }));
|
|
4331
|
+
};
|
|
4332
|
+
const HEX_REGEX = RegExp(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/);
|
|
4333
|
+
/**
|
|
4334
|
+
* Component which displays the passed in color's HEX value, either in linearSpace (if linearHex is true) or in gamma space
|
|
4335
|
+
* When the hex color is changed by user, component calculates the new Color3/4 value and calls onChange
|
|
4336
|
+
*
|
|
4337
|
+
* Component uses the isLinearMode boolean to display an informative label regarding linear / gamma space
|
|
4338
|
+
* @param props - The properties for the InputHexField component.
|
|
4339
|
+
* @returns
|
|
4340
|
+
*/
|
|
4341
|
+
const InputHexField = (props) => {
|
|
4342
|
+
const styles = useColorPickerStyles();
|
|
4343
|
+
const { title, value, onChange, linearHex, isLinearMode } = props;
|
|
4344
|
+
return (jsx("div", { className: styles.colorFieldWrapper, children: jsx(TextInput, { disabled: linearHex ? !isLinearMode : false, className: styles.input, value: linearHex ? value.toLinearSpace().toHexString() : value.toHexString(), validator: (val) => val != "" && HEX_REGEX.test(val), onChange: (val) => (linearHex ? onChange(Color3.FromHexString(val).toGammaSpace()) : onChange(Color3.FromHexString(val))), infoLabel: title
|
|
4345
|
+
? {
|
|
4346
|
+
label: title,
|
|
4347
|
+
// If not representing a linearHex, no info is needed.
|
|
4348
|
+
info: !props.linearHex ? undefined : !isLinearMode ? ( // If representing a linear hex but we are in gammaMode, simple message explaining why linearHex is disabled
|
|
4349
|
+
jsx(Fragment, { children: " This color picker is attached to an entity whose color is stored in gamma space, so we are showing linear hex in disabled view " })) : (
|
|
4350
|
+
// If representing a linear hex and we are in linearMode, give information about how to use these hex values
|
|
4351
|
+
jsxs(Fragment, { children: ["This color picker is attached to an entity whose color is stored in linear space (ex: PBR Material), and Babylon converts the color to gamma space before rendering on screen because the human eye is best at processing colors in gamma space. We thus also want to display the color picker in gamma space so that the color chosen here will match the color seen in your entity.", jsx("br", {}), "If you want to copy/paste the HEX into your code, you can either use", jsx(Body1Strong, { children: "Color3.FromHexString(LINEAR_HEX)" }), jsx("br", {}), "or", jsx("br", {}), jsx(Body1Strong, { children: "Color3.FromHexString(GAMMA_HEX).toLinearSpace()" }), jsx("br", {}), jsx("br", {}), jsx(Link, { href: "https://doc.babylonjs.com/preparingArtForBabylon/controllingColorSpace/", children: " Read more in our docs! " })] })),
|
|
4352
|
+
}
|
|
4353
|
+
: undefined }) }));
|
|
4354
|
+
};
|
|
4355
|
+
const InputRgbField = (props) => {
|
|
4356
|
+
const { value, onChange, title, rgbKey } = props;
|
|
4357
|
+
const classes = useColorPickerStyles();
|
|
4358
|
+
const handleChange = useCallback((val) => {
|
|
4359
|
+
const newColor = value.clone();
|
|
4360
|
+
newColor[rgbKey] = val / 255.0; // Convert to 0-1 range
|
|
4361
|
+
onChange(newColor);
|
|
4362
|
+
}, [value, onChange, rgbKey]);
|
|
4363
|
+
return (jsx("div", { className: classes.colorFieldWrapper, children: jsx(SpinButton, { title: title, infoLabel: title ? { label: title } : undefined, className: classes.spinButton, min: 0, max: 255, value: Math.round(value[rgbKey] * 255), forceInt: true, onChange: handleChange }) }));
|
|
4364
|
+
};
|
|
4365
|
+
function rgbaToHsv(color) {
|
|
4366
|
+
const c = new Color3(color.r, color.g, color.b);
|
|
4367
|
+
const hsv = c.toHSV();
|
|
4368
|
+
return { h: hsv.r, s: hsv.g, v: hsv.b, a: color.a };
|
|
4369
|
+
}
|
|
4370
|
+
/**
|
|
4371
|
+
* In the HSV (Hue, Saturation, Value) color model, Hue (H) ranges from 0 to 360 degrees, representing the color's position on the color wheel.
|
|
4372
|
+
* Saturation (S) ranges from 0 to 100%, indicating the intensity or purity of the color, with 0 being shades of gray and 100 being a fully saturated color.
|
|
4373
|
+
* Value (V) ranges from 0 to 100%, representing the brightness of the color, with 0 being black and 100 being the brightest.
|
|
4374
|
+
* @param props - The properties for the InputHsvField component.
|
|
4375
|
+
*/
|
|
4376
|
+
const InputHsvField = (props) => {
|
|
4377
|
+
const { value, title, hsvKey, max, onChange, scale = 1 } = props;
|
|
4378
|
+
const classes = useColorPickerStyles();
|
|
4379
|
+
const handleChange = useCallback((val) => {
|
|
4380
|
+
// Convert current color to HSV, update the new hsv value, then call onChange prop
|
|
4381
|
+
const hsv = rgbaToHsv(value);
|
|
4382
|
+
hsv[hsvKey] = val / scale;
|
|
4383
|
+
let newColor = Color3.FromHSV(hsv.h, hsv.s, hsv.v);
|
|
4384
|
+
if (value instanceof Color4) {
|
|
4385
|
+
newColor = Color4.FromColor3(newColor, value.a ?? 1);
|
|
4386
|
+
}
|
|
4387
|
+
props.onChange(newColor);
|
|
4388
|
+
}, [value, onChange, hsvKey, scale]);
|
|
4389
|
+
return (jsx("div", { className: classes.colorFieldWrapper, children: jsx(SpinButton, { infoLabel: title ? { label: title } : undefined, title: title, className: classes.spinButton, min: 0, max: max, value: Math.round(rgbaToHsv(value)[hsvKey] * scale), forceInt: true, onChange: handleChange }) }));
|
|
4390
|
+
};
|
|
4391
|
+
/**
|
|
4392
|
+
* Displays the alpha value of a color, either in the disabled state (if color is Color3) or as a spin button (if color is Color4).
|
|
4393
|
+
* @param props
|
|
4394
|
+
* @returns
|
|
4395
|
+
*/
|
|
4396
|
+
const InputAlphaField = (props) => {
|
|
4397
|
+
const classes = useColorPickerStyles();
|
|
4398
|
+
const { color, onChange } = props;
|
|
4399
|
+
const handleChange = useCallback((value) => {
|
|
4400
|
+
if (Number.isNaN(value) || value < 0 || value > 1) {
|
|
4401
|
+
return;
|
|
4402
|
+
}
|
|
4403
|
+
if (color instanceof Color4) {
|
|
4404
|
+
const newColor = color.clone();
|
|
4405
|
+
newColor.a = value;
|
|
4406
|
+
return newColor;
|
|
4407
|
+
}
|
|
4408
|
+
else {
|
|
4409
|
+
return Color4.FromColor3(color, value);
|
|
4410
|
+
}
|
|
4411
|
+
}, [onChange]);
|
|
4412
|
+
return (jsx("div", { className: classes.colorFieldWrapper, children: jsx(SpinButton, { disabled: color instanceof Color3, min: 0, max: 1, className: classes.spinButton, value: color instanceof Color3 ? 1 : color.a, step: 0.01, onChange: handleChange, infoLabel: {
|
|
4413
|
+
label: "Alpha",
|
|
4414
|
+
info: color instanceof Color3 ? (jsx(Fragment, { children: "Because this color picker is representing a Color3, we do not permit modifying alpha from the color picker. You can however modify the entity's alpha property directly, either in code via entity.alpha OR via inspector's transparency section." })) : undefined,
|
|
4415
|
+
} }) }));
|
|
4416
|
+
};
|
|
4417
|
+
|
|
4418
|
+
/**
|
|
4419
|
+
* Reusable component which renders a color property line containing a label, colorPicker popout, and expandable RGBA values
|
|
4420
|
+
* The expandable RGBA values are synced sliders that allow the user to modify the color's RGBA values directly
|
|
4421
|
+
* @param props - PropertyLine props, replacing children with a color object so that we can properly display the color
|
|
4422
|
+
* @returns Component wrapping a colorPicker component with a property line
|
|
4423
|
+
*/
|
|
4424
|
+
const ColorPropertyLine = forwardRef((props, ref) => {
|
|
4425
|
+
const [color, setColor] = useState(props.value);
|
|
4426
|
+
const onSliderChange = (value, key) => {
|
|
4427
|
+
let newColor;
|
|
4428
|
+
if (key === "a") {
|
|
4429
|
+
newColor = Color4.FromColor3(color, value);
|
|
4430
|
+
}
|
|
4431
|
+
else {
|
|
4432
|
+
newColor = color.clone();
|
|
4433
|
+
newColor[key] = value / 255;
|
|
4434
|
+
}
|
|
4435
|
+
setColor(newColor); // Create a new object to trigger re-render
|
|
4436
|
+
props.onChange(newColor);
|
|
4437
|
+
};
|
|
4438
|
+
const onColorPickerChange = (newColor) => {
|
|
4439
|
+
setColor(newColor);
|
|
4440
|
+
props.onChange(newColor);
|
|
4441
|
+
};
|
|
4442
|
+
return (jsx(PropertyLine, { ref: ref, ...props, expandedContent: 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 instanceof Color4 && jsx(SyncedSliderPropertyLine, { label: "A", value: color.a, min: 0, max: 1, step: 0.01, onChange: (value) => onSliderChange(value, "a") })] }), children: jsx(ColorPickerPopup, { ...props, onChange: onColorPickerChange, value: color }) }));
|
|
4443
|
+
});
|
|
4444
|
+
const Color3PropertyLine = ColorPropertyLine;
|
|
4445
|
+
const Color4PropertyLine = ColorPropertyLine;
|
|
4446
|
+
|
|
4447
|
+
const GeneralAtmosphereProperties = (props) => {
|
|
4448
|
+
const { entity: atmosphere } = props;
|
|
4449
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Planet Radius (km)", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "planetRadius", min: 1000.0, max: 10000.0, step: 1 }), jsx(BoundProperty, { label: "Atmosphere Thickness (km)", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "atmosphereThickness", min: 1.0, max: 200.0, step: 1 })] }));
|
|
4450
|
+
};
|
|
4451
|
+
const ScatteringAndAbsorptionProperties = (props) => {
|
|
4452
|
+
const { entity: atmosphere } = props;
|
|
4453
|
+
return (jsxs(Fragment, { children: [jsx(PropertyLine, { label: "Rayleigh Scattering", expandByDefault: true, description: "Rayleigh scattering is the scattering of light off of the molecules of the atmosphere. It is the main reason why the sky is blue. Increasing the Rayleigh scattering coefficient will result in a bluer sky.", expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "rayleighScatteringScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakRayleighScattering", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01, unit: "Mm" })] }) }), jsx(PropertyLine, { label: "Mie Scattering", description: "Mie scattering is the scattering of light off of the larger particles in the atmosphere, such as dust and water droplets. It is responsible for the white appearance of clouds and the haziness of the sky. Increasing the Mie scattering coefficient will result in a whiter sky.", expandByDefault: true, expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "mieScatteringScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakMieScattering", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01, unit: "Mm" })] }) }), jsx(PropertyLine, { label: "Mie Absorption", description: "Mie absorption is the absorption of light by the larger particles in the atmosphere, such as dust and water droplets. It is responsible for the dimming of the sun during haze and fog. Increasing mie absorption coefficient will result in visually darker skies.", expandByDefault: true, expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "mieAbsorptionScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakMieAbsorption", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01, unit: "Mm" })] }) }), jsx(PropertyLine, { label: "Ozone Absorption", expandByDefault: true, description: "Ozone absorption is the absorption of light by ozone molecules in the atmosphere. Increasing ozone absorption coefficient will result in visually darker skies.", expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "ozoneAbsorptionScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakOzoneAbsorption", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01 })] }) })] }));
|
|
4454
|
+
};
|
|
4455
|
+
const MultipleScatteringProperties = (props) => {
|
|
4456
|
+
const { entity: atmosphere } = props;
|
|
4457
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "multiScatteringIntensity", min: 0, max: 5.0, step: 0.1 }), jsx(BoundProperty, { label: "Minimum Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "minimumMultiScatteringIntensity", min: 0.0, max: 0.1, step: 0.0001 }), jsx(BoundProperty, { label: "Minimum Color", component: Color3PropertyLine, target: atmosphere, propertyKey: "minimumMultiScatteringColor" }), jsx(BoundProperty, { label: "Ground Albedo", component: Color3PropertyLine, target: atmosphere, propertyKey: "groundAlbedo" })] }));
|
|
4458
|
+
};
|
|
4459
|
+
const AerialPerspectiveProperties = (props) => {
|
|
4460
|
+
const { entity: atmosphere } = props;
|
|
4461
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "aerialPerspectiveIntensity", min: 0, max: 5.0, step: 0.1 }), jsx(BoundProperty, { label: "Transmittance Scale", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "aerialPerspectiveTransmittanceScale", min: 0, max: 2.0, step: 0.01 }), jsx(BoundProperty, { label: "Saturation", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "aerialPerspectiveSaturation", min: 0, max: 2.0, step: 0.01 })] }));
|
|
4462
|
+
};
|
|
4463
|
+
const DiffuseIrradianceProperties = (props) => {
|
|
4464
|
+
const { entity: atmosphere } = props;
|
|
4465
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "diffuseSkyIrradianceIntensity", min: 0, max: 5.0, step: 0.001 }), jsx(BoundProperty, { label: "Desaturation", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "diffuseSkyIrradianceDesaturationFactor", min: 0, max: 1.0, step: 0.01 }), jsx(BoundProperty, { label: "Additional Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "additionalDiffuseSkyIrradianceIntensity", min: 0, max: 100000.0, step: 1 }), jsx(BoundProperty, { label: "Additional Color", component: Color3PropertyLine, target: atmosphere, propertyKey: "additionalDiffuseSkyIrradianceColor" })] }));
|
|
4466
|
+
};
|
|
4467
|
+
const RenderingOptionsProperties = (props) => {
|
|
4468
|
+
const { entity: atmosphere } = props;
|
|
4469
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Linear Space Output", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isLinearSpaceComposition" }), jsx(BoundProperty, { label: "Linear Space Light", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isLinearSpaceLight" }), jsx(BoundProperty, { label: "Use LUT for Sky (Optimization)", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isSkyViewLutEnabled" }), jsx(BoundProperty, { label: "Use LUT for Aerial Perspective (Optimization)", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isAerialPerspectiveLutEnabled" })] }));
|
|
4470
|
+
};
|
|
4471
|
+
|
|
4472
|
+
const AtmospherePropertiesServiceDefinition = {
|
|
4473
|
+
friendlyName: "Atmosphere Properties",
|
|
4474
|
+
consumes: [PropertiesServiceIdentity, SelectionServiceIdentity, SceneContextIdentity],
|
|
4475
|
+
factory: (propertiesService, selectionService, sceneContext) => {
|
|
4476
|
+
const scene = sceneContext.currentScene;
|
|
4477
|
+
if (!scene) {
|
|
4478
|
+
return undefined;
|
|
4479
|
+
}
|
|
4480
|
+
const atmosphereContentRegistration = propertiesService.addSectionContent({
|
|
4481
|
+
key: "Atmosphere Properties",
|
|
4482
|
+
predicate: (entity) => entity instanceof Atmosphere,
|
|
4483
|
+
content: [
|
|
4484
|
+
{
|
|
4485
|
+
section: "General",
|
|
4486
|
+
component: ({ context }) => jsx(GeneralAtmosphereProperties, { entity: context }),
|
|
4487
|
+
},
|
|
4488
|
+
{
|
|
4489
|
+
section: "Scattering and Absorption",
|
|
4490
|
+
component: ({ context }) => jsx(ScatteringAndAbsorptionProperties, { entity: context }),
|
|
4491
|
+
},
|
|
4492
|
+
{
|
|
4493
|
+
section: "Multiple Scattering",
|
|
4494
|
+
component: ({ context }) => jsx(MultipleScatteringProperties, { entity: context }),
|
|
4495
|
+
},
|
|
4496
|
+
{
|
|
4497
|
+
section: "Aerial Perspective",
|
|
4498
|
+
component: ({ context }) => jsx(AerialPerspectiveProperties, { entity: context }),
|
|
4499
|
+
},
|
|
4500
|
+
{
|
|
4501
|
+
section: "Diffuse Sky Irradiance",
|
|
4502
|
+
component: ({ context }) => jsx(DiffuseIrradianceProperties, { entity: context }),
|
|
4503
|
+
},
|
|
4504
|
+
{
|
|
4505
|
+
section: "Rendering Options",
|
|
4506
|
+
component: ({ context }) => jsx(RenderingOptionsProperties, { entity: context }),
|
|
4507
|
+
},
|
|
4508
|
+
],
|
|
4509
|
+
});
|
|
4510
|
+
return {
|
|
4511
|
+
dispose: () => {
|
|
4512
|
+
atmosphereContentRegistration.dispose();
|
|
4513
|
+
},
|
|
4514
|
+
};
|
|
4515
|
+
},
|
|
4516
|
+
};
|
|
4517
|
+
|
|
4518
|
+
const ArcRotateCameraTransformProperties = (props) => {
|
|
4519
|
+
const { camera, settings } = props;
|
|
4520
|
+
const [toDisplayAngle, fromDisplayAngle, useDegrees] = useAngleConverters(settings);
|
|
4521
|
+
const lowerAlphaLimit = useProperty(camera, "lowerAlphaLimit") ?? 0;
|
|
4522
|
+
const upperAlphaLimit = useProperty(camera, "upperAlphaLimit") ?? Math.PI * 2;
|
|
4523
|
+
const lowerBetaLimit = useProperty(camera, "lowerBetaLimit") ?? -Math.PI;
|
|
4524
|
+
const upperBetaLimit = useProperty(camera, "upperBetaLimit") ?? Math.PI;
|
|
4525
|
+
const lowerRadiusLimit = useProperty(camera, "lowerRadiusLimit");
|
|
4526
|
+
const upperRadiusLimit = useProperty(camera, "upperRadiusLimit");
|
|
4527
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Alpha", description: `Horizontal angle in ${useDegrees ? "degrees" : "radians"}`, target: camera, propertyKey: "alpha", min: toDisplayAngle(lowerAlphaLimit), max: toDisplayAngle(upperAlphaLimit), step: toDisplayAngle(0.01), convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Beta", description: `Vertical angle in ${useDegrees ? "degrees" : "radians"}`, target: camera, propertyKey: "beta", min: toDisplayAngle(lowerBetaLimit), max: toDisplayAngle(upperBetaLimit), step: toDisplayAngle(0.01), convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), lowerRadiusLimit != null && upperRadiusLimit != null ? (jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Radius", description: "Distance from the target point.", target: camera, propertyKey: "radius", min: lowerRadiusLimit, max: upperRadiusLimit, step: 0.01 })) : (jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Radius", description: "Distance from the target point.", target: camera, propertyKey: "radius", min: 0, step: 0.01 }))] }));
|
|
4528
|
+
};
|
|
4529
|
+
const ArcRotateCameraControlProperties = (props) => {
|
|
4530
|
+
const { camera } = props;
|
|
4531
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Angular Sensitivity X", target: camera, propertyKey: "angularSensibilityX" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Angular Sensitivity Y", target: camera, propertyKey: "angularSensibilityY" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Panning Sensitivity", target: camera, propertyKey: "panningSensibility" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Pinch Delta Percentage", target: camera, propertyKey: "pinchDeltaPercentage" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Wheel Delta Percentage", target: camera, propertyKey: "wheelDeltaPercentage" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Natural Pinch Zoom", target: camera, propertyKey: "useNaturalPinchZoom" })] }));
|
|
4532
|
+
};
|
|
4533
|
+
const ArcRotateCameraCollisionProperties = (props) => {
|
|
4534
|
+
const { camera } = props;
|
|
4535
|
+
const collisionRadius = useProperty(camera, "collisionRadius");
|
|
4536
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Check Collisions", target: camera, propertyKey: "checkCollisions" }), jsx(Vector3PropertyLine, { label: "Collision Radius", value: collisionRadius, onChange: (val) => (camera.collisionRadius = val) })] }));
|
|
4537
|
+
};
|
|
4538
|
+
const ArcRotateCameraLimitsProperties = (props) => {
|
|
4539
|
+
const { camera } = props;
|
|
4540
|
+
// TODO-Iv2: Update defaultValues
|
|
4541
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Alpha Limit", target: camera, propertyKey: "lowerAlphaLimit", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Upper Alpha Limit", target: camera, propertyKey: "upperAlphaLimit", nullable: true, defaultValue: Infinity }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Beta Limit", target: camera, propertyKey: "lowerBetaLimit", nullable: true, defaultValue: -Math.PI }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Upper Beta Limit", target: camera, propertyKey: "upperBetaLimit", nullable: true, defaultValue: Math.PI }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Radius Limit", target: camera, propertyKey: "lowerRadiusLimit", nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Upper Radius Limit", target: camera, propertyKey: "upperRadiusLimit", nullable: true, defaultValue: 100 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Lower Target Y Limit", target: camera, propertyKey: "lowerTargetYLimit" })] }));
|
|
4542
|
+
};
|
|
4543
|
+
const ArcRotateCameraBehaviorsProperties = (props) => {
|
|
4544
|
+
const { camera } = props;
|
|
4545
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Auto Rotation", target: camera, propertyKey: "useAutoRotationBehavior" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Bouncing", target: camera, propertyKey: "useBouncingBehavior" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Framing", target: camera, propertyKey: "useFramingBehavior" })] }));
|
|
4546
|
+
};
|
|
4547
|
+
|
|
4548
|
+
const useDropdownStyles = makeStyles({
|
|
4549
|
+
dropdown: { ...UniformWidthStyling, minWidth: CustomTokens.inputWidth },
|
|
4550
|
+
});
|
|
4551
|
+
/**
|
|
4552
|
+
* Renders a fluent UI dropdown component for the options passed in, and an additional 'Not Defined' option if null is set to true
|
|
4553
|
+
* This component can handle both null and undefined values
|
|
4554
|
+
* @param props
|
|
4555
|
+
* @returns dropdown component
|
|
4556
|
+
*/
|
|
4557
|
+
const Dropdown = (props) => {
|
|
4558
|
+
const classes = useDropdownStyles();
|
|
4559
|
+
const { options, value } = props;
|
|
4560
|
+
const [defaultVal, setDefaultVal] = useState(props.value);
|
|
4561
|
+
useEffect(() => {
|
|
4562
|
+
setDefaultVal(value);
|
|
4563
|
+
}, [props.value]);
|
|
4564
|
+
return (jsx(Dropdown$1, { disabled: props.disabled, size: "medium", className: classes.dropdown, onOptionSelect: (evt, data) => {
|
|
4565
|
+
const value = typeof props.value === "number" ? Number(data.optionValue) : data.optionValue;
|
|
4566
|
+
if (value !== undefined) {
|
|
4567
|
+
setDefaultVal(value);
|
|
4568
|
+
props.onChange(value);
|
|
4569
|
+
}
|
|
4570
|
+
}, selectedOptions: [defaultVal.toString()], value: options.find((o) => o.value === defaultVal)?.label, children: options.map((option) => (jsx(Option, { className: classes.dropdown, value: option.value.toString(), disabled: false, children: option.label }, option.label))) }));
|
|
4571
|
+
};
|
|
4572
|
+
const NumberDropdown = Dropdown;
|
|
4573
|
+
const StringDropdown = Dropdown;
|
|
4574
|
+
|
|
4575
|
+
/**
|
|
4576
|
+
* Wraps a dropdown in a property line
|
|
4577
|
+
* @param props - PropertyLineProps and DropdownProps
|
|
4578
|
+
* @returns property-line wrapped dropdown
|
|
4579
|
+
*/
|
|
4339
4580
|
const DropdownPropertyLine = forwardRef((props, ref) => {
|
|
4340
4581
|
return (jsx(PropertyLine, { ...props, ref: ref, children: jsx(Dropdown, { ...props }) }));
|
|
4341
4582
|
});
|
|
@@ -4386,7 +4627,7 @@ const FreeCameraTransformProperties = (props) => {
|
|
|
4386
4627
|
const position = useProperty(camera, "position");
|
|
4387
4628
|
const rotation = useProperty(camera, "rotation");
|
|
4388
4629
|
const quatRotation = useProperty(camera, "rotationQuaternion");
|
|
4389
|
-
return (jsxs(Fragment, { children: [jsx(Vector3PropertyLine, { label: "Position", value: position, onChange: (value) => (camera.position = value) }), quatRotation ? (jsx(QuaternionPropertyLine, { label: "Rotation (
|
|
4630
|
+
return (jsxs(Fragment, { children: [jsx(Vector3PropertyLine, { label: "Position", value: position, onChange: (value) => (camera.position = value) }), quatRotation ? (jsx(QuaternionPropertyLine, { label: "Rotation (Quat)", value: quatRotation, onChange: (val) => (camera.rotationQuaternion = val), useDegrees: useDegrees }, "QuaternionRotationTransform")) : (jsx(RotationVectorPropertyLine, { label: "Rotation", value: rotation, onChange: (val) => (camera.rotation = val), useDegrees: useDegrees }, "RotationTransform"))] }));
|
|
4390
4631
|
};
|
|
4391
4632
|
const FreeCameraControlProperties = (props) => {
|
|
4392
4633
|
const { camera } = props;
|
|
@@ -4551,234 +4792,55 @@ const EffectLayerPropertiesServiceDefinition = {
|
|
|
4551
4792
|
consumes: [PropertiesServiceIdentity],
|
|
4552
4793
|
factory: (propertiesService) => {
|
|
4553
4794
|
// TODO: Add content registrations for each section and for each type in the EffectLayer class hierarchy.
|
|
4554
|
-
return {
|
|
4555
|
-
dispose: () => {
|
|
4556
|
-
// TODO: Dispose content registrations.
|
|
4557
|
-
},
|
|
4558
|
-
};
|
|
4559
|
-
},
|
|
4560
|
-
};
|
|
4561
|
-
|
|
4562
|
-
const FrameGraphTaskProperties = (props) => {
|
|
4563
|
-
const { frameGraph } = props;
|
|
4564
|
-
const tasks = frameGraph.tasks;
|
|
4565
|
-
return (jsx(Fragment, { children: tasks.length > 0 &&
|
|
4566
|
-
tasks.map((task, i) => {
|
|
4567
|
-
return jsx(TextPropertyLine, { label: i + 1 + ". " + task.name, value: "" }, "task" + i);
|
|
4568
|
-
}) }));
|
|
4569
|
-
};
|
|
4570
|
-
const FrameGraphGeneralProperties = (props) => {
|
|
4571
|
-
const { frameGraph } = props;
|
|
4572
|
-
const isSceneFrameGraph = useProperty(frameGraph.scene, "frameGraph");
|
|
4573
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Optimize Texture Allocation", description: "Whether to optimize texture allocation.", target: frameGraph, propertyKey: "optimizeTextureAllocation" }), isSceneFrameGraph !== frameGraph && jsx(ButtonLine, { onClick: () => (frameGraph.scene.frameGraph = frameGraph), label: "Set as scene's frame graph" }), jsx(ButtonLine, { label: "Edit Graph", onClick: () => {
|
|
4574
|
-
void frameGraph.getLinkedNodeRenderGraph().edit({ nodeRenderGraphEditorConfig: { hostScene: frameGraph.scene } });
|
|
4575
|
-
} })] }));
|
|
4576
|
-
};
|
|
4577
|
-
|
|
4578
|
-
const FrameGraphPropertiesServiceDefinition = {
|
|
4579
|
-
friendlyName: "Frame Graph Properties",
|
|
4580
|
-
consumes: [PropertiesServiceIdentity],
|
|
4581
|
-
factory: (propertiesService) => {
|
|
4582
|
-
const frameGraphContentRegistration = propertiesService.addSectionContent({
|
|
4583
|
-
key: "Frame Graph General Properties",
|
|
4584
|
-
predicate: (entity) => entity instanceof FrameGraph,
|
|
4585
|
-
content: [
|
|
4586
|
-
{
|
|
4587
|
-
section: "General",
|
|
4588
|
-
component: ({ context }) => jsx(FrameGraphGeneralProperties, { frameGraph: context }),
|
|
4589
|
-
},
|
|
4590
|
-
{
|
|
4591
|
-
section: "Tasks",
|
|
4592
|
-
component: ({ context }) => jsx(FrameGraphTaskProperties, { frameGraph: context }),
|
|
4593
|
-
},
|
|
4594
|
-
],
|
|
4595
|
-
});
|
|
4596
|
-
return {
|
|
4597
|
-
dispose: () => {
|
|
4598
|
-
frameGraphContentRegistration.dispose();
|
|
4599
|
-
},
|
|
4600
|
-
};
|
|
4601
|
-
},
|
|
4602
|
-
};
|
|
4603
|
-
|
|
4604
|
-
const useColorPickerStyles = makeStyles({
|
|
4605
|
-
colorPickerContainer: {
|
|
4606
|
-
width: "325px",
|
|
4607
|
-
display: "flex",
|
|
4608
|
-
flexDirection: "column",
|
|
4609
|
-
gap: tokens.spacingVerticalMNudge, // 10px
|
|
4610
|
-
overflow: "visible",
|
|
4611
|
-
},
|
|
4612
|
-
previewColor: {
|
|
4613
|
-
width: "50px",
|
|
4614
|
-
height: "50px",
|
|
4615
|
-
borderRadius: tokens.borderRadiusMedium,
|
|
4616
|
-
border: `${tokens.spacingVerticalXXS} solid ${tokens.colorNeutralShadowKeyLighter}`,
|
|
4617
|
-
"@media (forced-colors: active)": {
|
|
4618
|
-
forcedColorAdjust: "none", // ensures elmement maintains color in high constrast mode
|
|
4619
|
-
},
|
|
4620
|
-
},
|
|
4621
|
-
row: {
|
|
4622
|
-
display: "flex",
|
|
4623
|
-
flexDirection: "row",
|
|
4624
|
-
gap: tokens.spacingVerticalM, // 12px
|
|
4625
|
-
alignItems: "center",
|
|
4626
|
-
},
|
|
4627
|
-
colorFieldWrapper: {
|
|
4628
|
-
display: "flex",
|
|
4629
|
-
flexDirection: "column",
|
|
4630
|
-
gap: tokens.spacingVerticalSNudge, // 6px
|
|
4631
|
-
},
|
|
4632
|
-
input: {
|
|
4633
|
-
width: "80px",
|
|
4634
|
-
},
|
|
4635
|
-
spinButton: {
|
|
4636
|
-
width: "50px",
|
|
4637
|
-
},
|
|
4638
|
-
container: {
|
|
4639
|
-
display: "flex",
|
|
4640
|
-
flexDirection: "column",
|
|
4641
|
-
gap: tokens.spacingVerticalL, // 16px
|
|
4642
|
-
},
|
|
4643
|
-
});
|
|
4644
|
-
const ColorPickerPopup = (props) => {
|
|
4645
|
-
const classes = useColorPickerStyles();
|
|
4646
|
-
const [color, setColor] = useState(props.value);
|
|
4647
|
-
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
4648
|
-
useEffect(() => {
|
|
4649
|
-
setColor(props.value); // Ensures the trigger color updates when props.value changes
|
|
4650
|
-
}, [props.value]);
|
|
4651
|
-
const handleColorPickerChange = (_, data) => {
|
|
4652
|
-
let color = Color3.FromHSV(data.color.h, data.color.s, data.color.v);
|
|
4653
|
-
if (props.value instanceof Color4) {
|
|
4654
|
-
color = Color4.FromColor3(color, data.color.a ?? 1);
|
|
4655
|
-
}
|
|
4656
|
-
handleChange(color);
|
|
4657
|
-
};
|
|
4658
|
-
const handleChange = (newColor) => {
|
|
4659
|
-
setColor(newColor);
|
|
4660
|
-
props.onChange(newColor); // Ensures the parent is notified when color changes from within colorPicker
|
|
4661
|
-
};
|
|
4662
|
-
return (jsxs(Popover, { positioning: {
|
|
4663
|
-
align: "start",
|
|
4664
|
-
overflowBoundary: document.body,
|
|
4665
|
-
autoSize: true,
|
|
4666
|
-
}, open: popoverOpen, trapFocus: true, onOpenChange: (_, data) => setPopoverOpen(data.open), children: [jsx(PopoverTrigger, { disableButtonEnhancement: true, children: jsx(ColorSwatch, { borderColor: tokens.colorNeutralShadowKeyDarker, size: "small", color: color.toHexString(), value: color.toHexString().slice(1) }) }), jsx(PopoverSurface, { children: jsxs("div", { className: classes.colorPickerContainer, children: [jsxs(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.container, children: [jsxs("div", { className: classes.row, children: [jsx("div", { className: classes.previewColor, style: { backgroundColor: color.toHexString() } }), jsx(InputHexField, { title: "Gamma Hex", value: color, isLinearMode: props.isLinearMode, onChange: handleChange }), jsx(InputHexField, { title: "Linear Hex", linearHex: true, isLinearMode: props.isLinearMode, value: color, onChange: handleChange })] }), jsxs("div", { className: classes.row, children: [jsx(InputRgbField, { title: "Red", value: color, rgbKey: "r", onChange: handleChange }), jsx(InputRgbField, { title: "Green", value: color, rgbKey: "g", onChange: handleChange }), jsx(InputRgbField, { title: "Blue", value: color, rgbKey: "b", onChange: handleChange }), jsx(InputAlphaField, { color: color, onChange: handleChange })] }), jsxs("div", { className: classes.row, children: [jsx(InputHsvField, { title: "Hue", value: color, hsvKey: "h", max: 360, onChange: handleChange }), jsx(InputHsvField, { title: "Saturation", value: color, hsvKey: "s", max: 100, scale: 100, onChange: handleChange }), jsx(InputHsvField, { title: "Value", value: color, hsvKey: "v", max: 100, scale: 100, onChange: handleChange })] })] })] }) })] }));
|
|
4667
|
-
};
|
|
4668
|
-
const HEX_REGEX = RegExp(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/);
|
|
4669
|
-
/**
|
|
4670
|
-
* Component which displays the passed in color's HEX value, either in linearSpace (if linearHex is true) or in gamma space
|
|
4671
|
-
* When the hex color is changed by user, component calculates the new Color3/4 value and calls onChange
|
|
4672
|
-
*
|
|
4673
|
-
* Component uses the isLinearMode boolean to display an informative label regarding linear / gamma space
|
|
4674
|
-
* @param props - The properties for the InputHexField component.
|
|
4675
|
-
* @returns
|
|
4676
|
-
*/
|
|
4677
|
-
const InputHexField = (props) => {
|
|
4678
|
-
const styles = useColorPickerStyles();
|
|
4679
|
-
const { title, value, onChange, linearHex, isLinearMode } = props;
|
|
4680
|
-
return (jsx("div", { className: styles.colorFieldWrapper, children: jsx(TextInput, { disabled: linearHex ? !isLinearMode : false, className: styles.input, value: linearHex ? value.toLinearSpace().toHexString() : value.toHexString(), validator: (val) => val != "" && HEX_REGEX.test(val), onChange: (val) => (linearHex ? onChange(Color3.FromHexString(val).toGammaSpace()) : onChange(Color3.FromHexString(val))), infoLabel: title
|
|
4681
|
-
? {
|
|
4682
|
-
label: title,
|
|
4683
|
-
// If not representing a linearHex, no info is needed.
|
|
4684
|
-
info: !props.linearHex ? undefined : !isLinearMode ? ( // If representing a linear hex but we are in gammaMode, simple message explaining why linearHex is disabled
|
|
4685
|
-
jsx(Fragment, { children: " This color picker is attached to an entity whose color is stored in gamma space, so we are showing linear hex in disabled view " })) : (
|
|
4686
|
-
// If representing a linear hex and we are in linearMode, give information about how to use these hex values
|
|
4687
|
-
jsxs(Fragment, { children: ["This color picker is attached to an entity whose color is stored in linear space (ex: PBR Material), and Babylon converts the color to gamma space before rendering on screen because the human eye is best at processing colors in gamma space. We thus also want to display the color picker in gamma space so that the color chosen here will match the color seen in your entity.", jsx("br", {}), "If you want to copy/paste the HEX into your code, you can either use", jsx(Body1Strong, { children: "Color3.FromHexString(LINEAR_HEX)" }), jsx("br", {}), "or", jsx("br", {}), jsx(Body1Strong, { children: "Color3.FromHexString(GAMMA_HEX).toLinearSpace()" }), jsx("br", {}), jsx("br", {}), jsx(Link, { href: "https://doc.babylonjs.com/preparingArtForBabylon/controllingColorSpace/", children: " Read more in our docs! " })] })),
|
|
4688
|
-
}
|
|
4689
|
-
: undefined }) }));
|
|
4690
|
-
};
|
|
4691
|
-
const InputRgbField = (props) => {
|
|
4692
|
-
const { value, onChange, title, rgbKey } = props;
|
|
4693
|
-
const classes = useColorPickerStyles();
|
|
4694
|
-
const handleChange = useCallback((val) => {
|
|
4695
|
-
const newColor = value.clone();
|
|
4696
|
-
newColor[rgbKey] = val / 255.0; // Convert to 0-1 range
|
|
4697
|
-
onChange(newColor);
|
|
4698
|
-
}, [value, onChange, rgbKey]);
|
|
4699
|
-
return (jsx("div", { className: classes.colorFieldWrapper, children: jsx(SpinButton, { title: title, infoLabel: title ? { label: title } : undefined, className: classes.spinButton, min: 0, max: 255, value: Math.round(value[rgbKey] * 255), forceInt: true, onChange: handleChange }) }));
|
|
4700
|
-
};
|
|
4701
|
-
function rgbaToHsv(color) {
|
|
4702
|
-
const c = new Color3(color.r, color.g, color.b);
|
|
4703
|
-
const hsv = c.toHSV();
|
|
4704
|
-
return { h: hsv.r, s: hsv.g, v: hsv.b, a: color.a };
|
|
4705
|
-
}
|
|
4706
|
-
/**
|
|
4707
|
-
* In the HSV (Hue, Saturation, Value) color model, Hue (H) ranges from 0 to 360 degrees, representing the color's position on the color wheel.
|
|
4708
|
-
* Saturation (S) ranges from 0 to 100%, indicating the intensity or purity of the color, with 0 being shades of gray and 100 being a fully saturated color.
|
|
4709
|
-
* Value (V) ranges from 0 to 100%, representing the brightness of the color, with 0 being black and 100 being the brightest.
|
|
4710
|
-
* @param props - The properties for the InputHsvField component.
|
|
4711
|
-
*/
|
|
4712
|
-
const InputHsvField = (props) => {
|
|
4713
|
-
const { value, title, hsvKey, max, onChange, scale = 1 } = props;
|
|
4714
|
-
const classes = useColorPickerStyles();
|
|
4715
|
-
const handleChange = useCallback((val) => {
|
|
4716
|
-
// Convert current color to HSV, update the new hsv value, then call onChange prop
|
|
4717
|
-
const hsv = rgbaToHsv(value);
|
|
4718
|
-
hsv[hsvKey] = val / scale;
|
|
4719
|
-
let newColor = Color3.FromHSV(hsv.h, hsv.s, hsv.v);
|
|
4720
|
-
if (value instanceof Color4) {
|
|
4721
|
-
newColor = Color4.FromColor3(newColor, value.a ?? 1);
|
|
4722
|
-
}
|
|
4723
|
-
props.onChange(newColor);
|
|
4724
|
-
}, [value, onChange, hsvKey, scale]);
|
|
4725
|
-
return (jsx("div", { className: classes.colorFieldWrapper, children: jsx(SpinButton, { infoLabel: title ? { label: title } : undefined, title: title, className: classes.spinButton, min: 0, max: max, value: Math.round(rgbaToHsv(value)[hsvKey] * scale), forceInt: true, onChange: handleChange }) }));
|
|
4795
|
+
return {
|
|
4796
|
+
dispose: () => {
|
|
4797
|
+
// TODO: Dispose content registrations.
|
|
4798
|
+
},
|
|
4799
|
+
};
|
|
4800
|
+
},
|
|
4726
4801
|
};
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
return newColor;
|
|
4743
|
-
}
|
|
4744
|
-
else {
|
|
4745
|
-
return Color4.FromColor3(color, value);
|
|
4746
|
-
}
|
|
4747
|
-
}, [onChange]);
|
|
4748
|
-
return (jsx("div", { className: classes.colorFieldWrapper, children: jsx(SpinButton, { disabled: color instanceof Color3, min: 0, max: 1, className: classes.spinButton, value: color instanceof Color3 ? 1 : color.a, step: 0.01, onChange: handleChange, infoLabel: {
|
|
4749
|
-
label: "Alpha",
|
|
4750
|
-
info: color instanceof Color3 ? (jsx(Fragment, { children: "Because this color picker is representing a Color3, we do not permit modifying alpha from the color picker. You can however modify the entity's alpha property directly, either in code via entity.alpha OR via inspector's transparency section." })) : undefined,
|
|
4751
|
-
} }) }));
|
|
4802
|
+
|
|
4803
|
+
const FrameGraphTaskProperties = (props) => {
|
|
4804
|
+
const { frameGraph } = props;
|
|
4805
|
+
const tasks = frameGraph.tasks;
|
|
4806
|
+
return (jsx(Fragment, { children: tasks.length > 0 &&
|
|
4807
|
+
tasks.map((task, i) => {
|
|
4808
|
+
return jsx(TextPropertyLine, { label: i + 1 + ". " + task.name, value: "" }, "task" + i);
|
|
4809
|
+
}) }));
|
|
4810
|
+
};
|
|
4811
|
+
const FrameGraphGeneralProperties = (props) => {
|
|
4812
|
+
const { frameGraph } = props;
|
|
4813
|
+
const isSceneFrameGraph = useProperty(frameGraph.scene, "frameGraph");
|
|
4814
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Optimize Texture Allocation", description: "Whether to optimize texture allocation.", target: frameGraph, propertyKey: "optimizeTextureAllocation" }), isSceneFrameGraph !== frameGraph && jsx(ButtonLine, { onClick: () => (frameGraph.scene.frameGraph = frameGraph), label: "Set as scene's frame graph" }), jsx(ButtonLine, { label: "Edit Graph", onClick: () => {
|
|
4815
|
+
void frameGraph.getLinkedNodeRenderGraph().edit({ nodeRenderGraphEditorConfig: { hostScene: frameGraph.scene } });
|
|
4816
|
+
} })] }));
|
|
4752
4817
|
};
|
|
4753
4818
|
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
}
|
|
4778
|
-
|
|
4779
|
-
});
|
|
4780
|
-
const Color3PropertyLine = ColorPropertyLine;
|
|
4781
|
-
const Color4PropertyLine = ColorPropertyLine;
|
|
4819
|
+
const FrameGraphPropertiesServiceDefinition = {
|
|
4820
|
+
friendlyName: "Frame Graph Properties",
|
|
4821
|
+
consumes: [PropertiesServiceIdentity],
|
|
4822
|
+
factory: (propertiesService) => {
|
|
4823
|
+
const frameGraphContentRegistration = propertiesService.addSectionContent({
|
|
4824
|
+
key: "Frame Graph General Properties",
|
|
4825
|
+
predicate: (entity) => entity instanceof FrameGraph,
|
|
4826
|
+
content: [
|
|
4827
|
+
{
|
|
4828
|
+
section: "General",
|
|
4829
|
+
component: ({ context }) => jsx(FrameGraphGeneralProperties, { frameGraph: context }),
|
|
4830
|
+
},
|
|
4831
|
+
{
|
|
4832
|
+
section: "Tasks",
|
|
4833
|
+
component: ({ context }) => jsx(FrameGraphTaskProperties, { frameGraph: context }),
|
|
4834
|
+
},
|
|
4835
|
+
],
|
|
4836
|
+
});
|
|
4837
|
+
return {
|
|
4838
|
+
dispose: () => {
|
|
4839
|
+
frameGraphContentRegistration.dispose();
|
|
4840
|
+
},
|
|
4841
|
+
};
|
|
4842
|
+
},
|
|
4843
|
+
};
|
|
4782
4844
|
|
|
4783
4845
|
const AreaLightSetupProperties = ({ context: areaLight }) => {
|
|
4784
4846
|
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Diffuse", component: Color3PropertyLine, target: areaLight, propertyKey: "diffuse" }), jsx(BoundProperty, { label: "Specular", component: Color3PropertyLine, target: areaLight, propertyKey: "specular" }), jsx(BoundProperty, { label: "Position", component: Vector3PropertyLine, target: areaLight, propertyKey: "position" }), jsx(BoundProperty, { label: "Width", component: NumberInputPropertyLine, target: areaLight, propertyKey: "width" }), jsx(BoundProperty, { label: "Height", component: NumberInputPropertyLine, target: areaLight, propertyKey: "height" }), jsx(BoundProperty, { label: "Intensity", component: NumberInputPropertyLine, target: areaLight, propertyKey: "intensity" })] }));
|
|
@@ -6084,10 +6146,10 @@ const AttractorComponent = (props) => {
|
|
|
6084
6146
|
useEffect(() => {
|
|
6085
6147
|
impostor.scaling.setAll(impostorScale);
|
|
6086
6148
|
}, [impostor, impostorScale]);
|
|
6087
|
-
return (jsxs("div", { className: classes.container, children: [jsx(SyncedSliderInput, { value: attractor.strength, onChange: (value) => (attractor.strength = value), min: -10, max: 10, step: 0.1 }), jsx(ToggleButton, { title: "Show / hide particle attractor.",
|
|
6149
|
+
return (jsxs("div", { className: classes.container, children: [jsx(SyncedSliderInput, { value: attractor.strength, onChange: (value) => (attractor.strength = value), min: -10, max: 10, step: 0.1 }), jsx(ToggleButton, { title: "Show / hide particle attractor.", checkedIcon: EyeFilled, uncheckedIcon: EyeOffFilled, value: shown, onChange: (show) => {
|
|
6088
6150
|
show ? (impostor.visibility = 1) : (impostor.visibility = 0);
|
|
6089
6151
|
setShown(show);
|
|
6090
|
-
} }), jsx(ToggleButton, { title: "Add / remove position gizmo from particle attractor",
|
|
6152
|
+
} }), jsx(ToggleButton, { title: "Add / remove position gizmo from particle attractor", checkedIcon: ArrowMoveFilled, value: isControlled(impostor), onChange: (control) => onControl(control ? impostor : undefined) })] }));
|
|
6091
6153
|
};
|
|
6092
6154
|
|
|
6093
6155
|
// For each Attractor, create a listItem consisting of the attractor and its debugging impostor mesh
|
|
@@ -7066,7 +7128,7 @@ const TransformProperties = (props) => {
|
|
|
7066
7128
|
const { transform, settings } = props;
|
|
7067
7129
|
const quatRotation = useQuaternionProperty(transform, "rotationQuaternion");
|
|
7068
7130
|
const useDegrees = useObservableState(() => settings.useDegrees, settings.settingsChangedObservable);
|
|
7069
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Position", target: transform, propertyKey: "position" }), quatRotation ? (jsx(QuaternionPropertyLine, { label: "Rotation (
|
|
7131
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Vector3PropertyLine, label: "Position", target: transform, propertyKey: "position" }), quatRotation ? (jsx(QuaternionPropertyLine, { label: "Rotation (Quat)", value: quatRotation, onChange: (val) => (transform.rotationQuaternion = val), useDegrees: useDegrees }, "QuaternionRotationTransform")) : (jsx(BoundProperty, { component: RotationVectorPropertyLine, label: "Rotation", target: transform, propertyKey: "rotation", useDegrees: useDegrees })), jsx(BoundProperty, { component: Vector3PropertyLine, label: "Scaling", target: transform, propertyKey: "scaling" })] }));
|
|
7070
7132
|
};
|
|
7071
7133
|
|
|
7072
7134
|
const TransformPropertiesServiceDefinition = {
|
|
@@ -7171,6 +7233,49 @@ const AnimationGroupExplorerServiceDefinition = {
|
|
|
7171
7233
|
},
|
|
7172
7234
|
};
|
|
7173
7235
|
|
|
7236
|
+
const AtmosphereExplorerServiceDefinition = {
|
|
7237
|
+
friendlyName: "Atmosphere Explorer",
|
|
7238
|
+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
7239
|
+
factory: (sceneExplorerService, sceneContext) => {
|
|
7240
|
+
const scene = sceneContext.currentScene;
|
|
7241
|
+
if (!scene) {
|
|
7242
|
+
return undefined;
|
|
7243
|
+
}
|
|
7244
|
+
const sectionRegistration = sceneExplorerService.addSection({
|
|
7245
|
+
displayName: "Atmosphere",
|
|
7246
|
+
order: 1300 /* DefaultSectionsOrder.Atmosphere */,
|
|
7247
|
+
getRootEntities: () => (scene.getExternalData("atmosphere") ? [scene.getExternalData("atmosphere")] : []),
|
|
7248
|
+
getEntityDisplayInfo: (atmosphere) => {
|
|
7249
|
+
const onChangeObservable = new Observable();
|
|
7250
|
+
const nameHookToken = InterceptProperty(atmosphere, "name", {
|
|
7251
|
+
afterSet: () => {
|
|
7252
|
+
onChangeObservable.notifyObservers();
|
|
7253
|
+
},
|
|
7254
|
+
});
|
|
7255
|
+
return {
|
|
7256
|
+
get name() {
|
|
7257
|
+
return atmosphere.name;
|
|
7258
|
+
},
|
|
7259
|
+
onChange: onChangeObservable,
|
|
7260
|
+
dispose: () => {
|
|
7261
|
+
nameHookToken.dispose();
|
|
7262
|
+
onChangeObservable.clear();
|
|
7263
|
+
},
|
|
7264
|
+
};
|
|
7265
|
+
},
|
|
7266
|
+
entityIcon: () => jsx(WeatherSunnyLowFilled, {}),
|
|
7267
|
+
// TODO in order for inspector UX to display atmosphere created after inspector is created
|
|
7268
|
+
getEntityAddedObservables: () => [],
|
|
7269
|
+
getEntityRemovedObservables: () => [],
|
|
7270
|
+
});
|
|
7271
|
+
return {
|
|
7272
|
+
dispose: () => {
|
|
7273
|
+
sectionRegistration.dispose();
|
|
7274
|
+
},
|
|
7275
|
+
};
|
|
7276
|
+
},
|
|
7277
|
+
};
|
|
7278
|
+
|
|
7174
7279
|
const EffectLayerExplorerServiceDefinition = {
|
|
7175
7280
|
friendlyName: "Effect Layer Explorer",
|
|
7176
7281
|
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
@@ -7913,7 +8018,7 @@ const PickingToolbar = (props) => {
|
|
|
7913
8018
|
/* No-op */
|
|
7914
8019
|
};
|
|
7915
8020
|
}, [pickingEnabled, sceneElement, ignoreBackfaces]);
|
|
7916
|
-
return (sceneElement &&
|
|
8021
|
+
return (sceneElement && jsx(ToggleButton, { title: `${pickingEnabled ? "Disable" : "Enable"} Picking`, checkedIcon: TargetRegular, value: pickingEnabled, onChange: setPickingEnabled }));
|
|
7917
8022
|
};
|
|
7918
8023
|
|
|
7919
8024
|
const PickingServiceDefinition = {
|
|
@@ -7935,120 +8040,6 @@ const PickingServiceDefinition = {
|
|
|
7935
8040
|
},
|
|
7936
8041
|
};
|
|
7937
8042
|
|
|
7938
|
-
const GeneralAtmosphereProperties = (props) => {
|
|
7939
|
-
const { entity: atmosphere } = props;
|
|
7940
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Planet Radius (km)", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "planetRadius", min: 1000.0, max: 10000.0, step: 1 }), jsx(BoundProperty, { label: "Atmosphere Thickness (km)", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "atmosphereThickness", min: 1.0, max: 200.0, step: 1 })] }));
|
|
7941
|
-
};
|
|
7942
|
-
const ScatteringAndAbsorptionProperties = (props) => {
|
|
7943
|
-
const { entity: atmosphere } = props;
|
|
7944
|
-
return (jsxs(Fragment, { children: [jsx(PropertyLine, { label: "Rayleigh Scattering", expandByDefault: true, description: "Rayleigh scattering is the scattering of light off of the molecules of the atmosphere. It is the main reason why the sky is blue. Increasing the Rayleigh scattering coefficient will result in a bluer sky.", expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "rayleighScatteringScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakRayleighScattering", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01, unit: "Mm" })] }) }), jsx(PropertyLine, { label: "Mie Scattering", description: "Mie scattering is the scattering of light off of the larger particles in the atmosphere, such as dust and water droplets. It is responsible for the white appearance of clouds and the haziness of the sky. Increasing the Mie scattering coefficient will result in a whiter sky.", expandByDefault: true, expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "mieScatteringScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakMieScattering", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01, unit: "Mm" })] }) }), jsx(PropertyLine, { label: "Mie Absorption", description: "Mie absorption is the absorption of light by the larger particles in the atmosphere, such as dust and water droplets. It is responsible for the dimming of the sun during haze and fog. Increasing mie absorption coefficient will result in visually darker skies.", expandByDefault: true, expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "mieAbsorptionScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakMieAbsorption", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01, unit: "Mm" })] }) }), jsx(PropertyLine, { label: "Ozone Absorption", expandByDefault: true, description: "Ozone absorption is the absorption of light by ozone molecules in the atmosphere. Increasing ozone absorption coefficient will result in visually darker skies.", expandedContent: jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Scale", component: SyncedSliderPropertyLine, target: atmosphere.physicalProperties, propertyKey: "ozoneAbsorptionScale", min: 0.0, max: 5.0, step: 0.01 }), jsx(BoundProperty, { label: "Coefficient", component: Vector3PropertyLine, target: atmosphere.physicalProperties, propertyKey: "peakOzoneAbsorption", convertTo: (value) => value.scale(1000), convertFrom: (value) => value.scale(0.001), min: 0, step: 0.01 })] }) })] }));
|
|
7945
|
-
};
|
|
7946
|
-
const MultipleScatteringProperties = (props) => {
|
|
7947
|
-
const { entity: atmosphere } = props;
|
|
7948
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "multiScatteringIntensity", min: 0, max: 5.0, step: 0.1 }), jsx(BoundProperty, { label: "Minimum Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "minimumMultiScatteringIntensity", min: 0.0, max: 0.1, step: 0.0001 }), jsx(BoundProperty, { label: "Minimum Color", component: Color3PropertyLine, target: atmosphere, propertyKey: "minimumMultiScatteringColor" }), jsx(BoundProperty, { label: "Ground Albedo", component: Color3PropertyLine, target: atmosphere, propertyKey: "groundAlbedo" })] }));
|
|
7949
|
-
};
|
|
7950
|
-
const AerialPerspectiveProperties = (props) => {
|
|
7951
|
-
const { entity: atmosphere } = props;
|
|
7952
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "aerialPerspectiveIntensity", min: 0, max: 5.0, step: 0.1 }), jsx(BoundProperty, { label: "Transmittance Scale", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "aerialPerspectiveTransmittanceScale", min: 0, max: 2.0, step: 0.01 }), jsx(BoundProperty, { label: "Saturation", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "aerialPerspectiveSaturation", min: 0, max: 2.0, step: 0.01 })] }));
|
|
7953
|
-
};
|
|
7954
|
-
const DiffuseIrradianceProperties = (props) => {
|
|
7955
|
-
const { entity: atmosphere } = props;
|
|
7956
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "diffuseSkyIrradianceIntensity", min: 0, max: 5.0, step: 0.001 }), jsx(BoundProperty, { label: "Desaturation", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "diffuseSkyIrradianceDesaturationFactor", min: 0, max: 1.0, step: 0.01 }), jsx(BoundProperty, { label: "Additional Intensity", component: SyncedSliderPropertyLine, target: atmosphere, propertyKey: "additionalDiffuseSkyIrradianceIntensity", min: 0, max: 100000.0, step: 1 }), jsx(BoundProperty, { label: "Additional Color", component: Color3PropertyLine, target: atmosphere, propertyKey: "additionalDiffuseSkyIrradianceColor" })] }));
|
|
7957
|
-
};
|
|
7958
|
-
const RenderingOptionsProperties = (props) => {
|
|
7959
|
-
const { entity: atmosphere } = props;
|
|
7960
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { label: "Linear Space Output", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isLinearSpaceComposition" }), jsx(BoundProperty, { label: "Linear Space Light", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isLinearSpaceLight" }), jsx(BoundProperty, { label: "Use LUT for Sky (Optimization)", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isSkyViewLutEnabled" }), jsx(BoundProperty, { label: "Use LUT for Aerial Perspective (Optimization)", component: SwitchPropertyLine, target: atmosphere, propertyKey: "isAerialPerspectiveLutEnabled" })] }));
|
|
7961
|
-
};
|
|
7962
|
-
|
|
7963
|
-
const AtmospherePropertiesServiceDefinition = {
|
|
7964
|
-
friendlyName: "Atmosphere Properties",
|
|
7965
|
-
consumes: [PropertiesServiceIdentity, SelectionServiceIdentity, SceneContextIdentity],
|
|
7966
|
-
factory: (propertiesService, selectionService, sceneContext) => {
|
|
7967
|
-
const scene = sceneContext.currentScene;
|
|
7968
|
-
if (!scene) {
|
|
7969
|
-
return undefined;
|
|
7970
|
-
}
|
|
7971
|
-
const atmosphereContentRegistration = propertiesService.addSectionContent({
|
|
7972
|
-
key: "Atmosphere Properties",
|
|
7973
|
-
predicate: (entity) => entity instanceof Atmosphere,
|
|
7974
|
-
content: [
|
|
7975
|
-
{
|
|
7976
|
-
section: "General",
|
|
7977
|
-
component: ({ context }) => jsx(GeneralAtmosphereProperties, { entity: context }),
|
|
7978
|
-
},
|
|
7979
|
-
{
|
|
7980
|
-
section: "Scattering and Absorption",
|
|
7981
|
-
component: ({ context }) => jsx(ScatteringAndAbsorptionProperties, { entity: context }),
|
|
7982
|
-
},
|
|
7983
|
-
{
|
|
7984
|
-
section: "Multiple Scattering",
|
|
7985
|
-
component: ({ context }) => jsx(MultipleScatteringProperties, { entity: context }),
|
|
7986
|
-
},
|
|
7987
|
-
{
|
|
7988
|
-
section: "Aerial Perspective",
|
|
7989
|
-
component: ({ context }) => jsx(AerialPerspectiveProperties, { entity: context }),
|
|
7990
|
-
},
|
|
7991
|
-
{
|
|
7992
|
-
section: "Diffuse Sky Irradiance",
|
|
7993
|
-
component: ({ context }) => jsx(DiffuseIrradianceProperties, { entity: context }),
|
|
7994
|
-
},
|
|
7995
|
-
{
|
|
7996
|
-
section: "Rendering Options",
|
|
7997
|
-
component: ({ context }) => jsx(RenderingOptionsProperties, { entity: context }),
|
|
7998
|
-
},
|
|
7999
|
-
],
|
|
8000
|
-
});
|
|
8001
|
-
return {
|
|
8002
|
-
dispose: () => {
|
|
8003
|
-
atmosphereContentRegistration.dispose();
|
|
8004
|
-
},
|
|
8005
|
-
};
|
|
8006
|
-
},
|
|
8007
|
-
};
|
|
8008
|
-
|
|
8009
|
-
const AtmosphereExplorerServiceDefinition = {
|
|
8010
|
-
friendlyName: "Atmosphere Explorer",
|
|
8011
|
-
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
8012
|
-
factory: (sceneExplorerService, sceneContext) => {
|
|
8013
|
-
const scene = sceneContext.currentScene;
|
|
8014
|
-
if (!scene) {
|
|
8015
|
-
return undefined;
|
|
8016
|
-
}
|
|
8017
|
-
const sectionRegistration = sceneExplorerService.addSection({
|
|
8018
|
-
displayName: "Atmosphere",
|
|
8019
|
-
order: 1300 /* DefaultSectionsOrder.Atmosphere */,
|
|
8020
|
-
getRootEntities: () => (scene.getExternalData("atmosphere") ? [scene.getExternalData("atmosphere")] : []),
|
|
8021
|
-
getEntityDisplayInfo: (atmosphere) => {
|
|
8022
|
-
const onChangeObservable = new Observable();
|
|
8023
|
-
const nameHookToken = InterceptProperty(atmosphere, "name", {
|
|
8024
|
-
afterSet: () => {
|
|
8025
|
-
onChangeObservable.notifyObservers();
|
|
8026
|
-
},
|
|
8027
|
-
});
|
|
8028
|
-
return {
|
|
8029
|
-
get name() {
|
|
8030
|
-
return atmosphere.name;
|
|
8031
|
-
},
|
|
8032
|
-
onChange: onChangeObservable,
|
|
8033
|
-
dispose: () => {
|
|
8034
|
-
nameHookToken.dispose();
|
|
8035
|
-
onChangeObservable.clear();
|
|
8036
|
-
},
|
|
8037
|
-
};
|
|
8038
|
-
},
|
|
8039
|
-
entityIcon: () => jsx(WeatherSunnyLowFilled, {}),
|
|
8040
|
-
// TODO in order for inspector UX to display atmosphere created after inspector is created
|
|
8041
|
-
getEntityAddedObservables: () => [],
|
|
8042
|
-
getEntityRemovedObservables: () => [],
|
|
8043
|
-
});
|
|
8044
|
-
return {
|
|
8045
|
-
dispose: () => {
|
|
8046
|
-
sectionRegistration.dispose();
|
|
8047
|
-
},
|
|
8048
|
-
};
|
|
8049
|
-
},
|
|
8050
|
-
};
|
|
8051
|
-
|
|
8052
8043
|
let CurrentInspectorToken = null;
|
|
8053
8044
|
function IsInspectorVisible() {
|
|
8054
8045
|
return CurrentInspectorToken != null;
|
|
@@ -8066,8 +8057,6 @@ function _ShowInspector(scene, options) {
|
|
|
8066
8057
|
enableClose: true,
|
|
8067
8058
|
handleResize: true,
|
|
8068
8059
|
enablePopup: true,
|
|
8069
|
-
isExtensible: true,
|
|
8070
|
-
isThemeable: true,
|
|
8071
8060
|
...options,
|
|
8072
8061
|
};
|
|
8073
8062
|
if (!scene) {
|
|
@@ -8214,8 +8203,9 @@ function _ShowInspector(scene, options) {
|
|
|
8214
8203
|
// Additional services passed in to the Inspector.
|
|
8215
8204
|
...(options.serviceDefinitions ?? []),
|
|
8216
8205
|
],
|
|
8217
|
-
|
|
8218
|
-
|
|
8206
|
+
themeMode: options.themeMode,
|
|
8207
|
+
showThemeSelector: options.showThemeSelector,
|
|
8208
|
+
extensionFeeds: [DefaultInspectorExtensionFeed, ...(options.extensionFeeds ?? [])],
|
|
8219
8209
|
toolbarMode: "compact",
|
|
8220
8210
|
sidePaneMode: options.embedMode ? "right" : "both",
|
|
8221
8211
|
});
|
|
@@ -8494,5 +8484,5 @@ const Pane = (props) => {
|
|
|
8494
8484
|
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] }));
|
|
8495
8485
|
};
|
|
8496
8486
|
|
|
8497
|
-
export {
|
|
8498
|
-
//# sourceMappingURL=index-
|
|
8487
|
+
export { Button as $, MakePopoverTeachingMoment as A, ButtonLine as B, Collapse as C, DebugServiceIdentity as D, ExtensibleAccordion as E, FileUploadLine as F, GetPropertyDescriptor as G, IsPropertyReadonly as H, InterceptFunction as I, InterceptProperty as J, ConstructorFactory as K, LinkToEntityPropertyLine as L, MakeLazyComponent as M, NumberDropdownPropertyLine as N, SceneContextIdentity as O, Pane$1 as P, SelectionServiceIdentity as Q, SelectionServiceDefinition as R, SwitchPropertyLine as S, ToolsServiceIdentity as T, SettingsContextIdentity as U, IsInspectorVisible as V, ShowInspector as W, HideInspector as X, Inspector as Y, AccordionSection as Z, Accordion as _, SyncedSliderPropertyLine as a, Checkbox as a0, ColorPickerPopup as a1, InputHexField as a2, InputHsvField as a3, ComboBox as a4, DraggableLine as a5, Dropdown as a6, NumberDropdown as a7, StringDropdown as a8, FactorGradientComponent as a9, Color3GradientComponent as aa, Color4GradientComponent as ab, ColorStepGradientComponent as ac, InfoLabel as ad, List as ae, MessageBar as af, PositionedPopover as ag, SearchBar as ah, SearchBox as ai, SpinButton as aj, CalculatePrecision as ak, Switch as al, SyncedSliderInput as am, Textarea as an, TextInput as ao, ToggleButton as ap, FactorGradientList as aq, Color3GradientList as ar, Color4GradientList as as, Pane as at, PropertiesServiceIdentity as b, SceneExplorerServiceIdentity as c, SettingsServiceIdentity as d, StatsServiceIdentity as e, ShellServiceIdentity as f, BoundProperty as g, TeachingMoment as h, BuiltInsExtensionFeed as i, useVector3Property as j, useColor3Property as k, useColor4Property as l, useQuaternionProperty as m, MakePropertyHook as n, useInterceptObservable as o, useEventfulState as p, useObservableState as q, useObservableCollection as r, useOrderedObservableCollection as s, usePollingObservable as t, useProperty as u, useResource as v, useAsyncResource as w, useAngleConverters as x, MakeTeachingMoment as y, MakeDialogTeachingMoment as z };
|
|
8488
|
+
//# sourceMappingURL=index-BTXdoz_s.js.map
|