@babylonjs/inspector 8.41.2-preview → 8.42.0-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-Bu7areEZ.js → captureService-CbpbBn5F.js} +4 -4
- package/lib/{captureService-Bu7areEZ.js.map → captureService-CbpbBn5F.js.map} +1 -1
- package/lib/{exportService-BnE7xiJF.js → exportService-LaUVRgd_.js} +4 -4
- package/lib/{exportService-BnE7xiJF.js.map → exportService-LaUVRgd_.js.map} +1 -1
- package/lib/{extensionsListService-s7SPclHA.js → extensionsListService-CwnEf0dV.js} +4 -4
- package/lib/{extensionsListService-s7SPclHA.js.map → extensionsListService-CwnEf0dV.js.map} +1 -1
- package/lib/{importService-CF3uudG4.js → importService-B98QFvNM.js} +4 -4
- package/lib/{importService-CF3uudG4.js.map → importService-B98QFvNM.js.map} +1 -1
- package/lib/{index-BUtV9Nch.js → index-BgzFAhky.js} +466 -311
- package/lib/index-BgzFAhky.js.map +1 -0
- package/lib/index.d.ts +18 -6
- package/lib/index.js +3 -3
- package/lib/{quickCreateToolsService-C-yzV033.js → quickCreateToolsService-Bg2plbI-.js} +8 -19
- package/lib/quickCreateToolsService-Bg2plbI-.js.map +1 -0
- package/package.json +1 -1
- package/lib/index-BUtV9Nch.js.map +0 -1
- package/lib/quickCreateToolsService-C-yzV033.js.map +0 -1
|
@@ -3,7 +3,7 @@ import { createContext, useContext, useMemo, useEffect, useState, useRef, useCal
|
|
|
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, Link as Link$1, Body1, ToggleButton as ToggleButton$1, Button as Button$1, tokens, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, mergeClasses, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, createLightTheme, createDarkTheme, FluentProvider, Tooltip, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, Portal, RendererProvider, ToolbarRadioButton, createDOMRenderer, MenuGroup, MenuGroupHeader, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, MenuDivider, treeItemLevelToken, MenuItemCheckbox, Switch as Switch$1, PresenceBadge, useId, SpinButton as SpinButton$1, Slider, Input, Dropdown as Dropdown$1, Option, Popover, PopoverTrigger,
|
|
6
|
+
import { makeStyles, Link as Link$1, Body1, ToggleButton as ToggleButton$1, Button as Button$1, tokens, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, mergeClasses, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, createLightTheme, createDarkTheme, FluentProvider, Tooltip, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, Portal, RendererProvider, ToolbarRadioButton, createDOMRenderer, MenuGroup, MenuGroupHeader, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, MenuDivider, treeItemLevelToken, MenuItemCheckbox, Switch as Switch$1, PresenceBadge, useId, SpinButton as SpinButton$1, Slider, Input, Dropdown as Dropdown$1, Option, Popover as Popover$1, PopoverTrigger, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, ColorSwatch, MenuItemRadio, Dialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, List as List$1, ListItem, Spinner, Badge, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, useComboboxFilter, Combobox, Textarea as Textarea$1, ToolbarButton, Field } from '@fluentui/react-components';
|
|
7
7
|
import { ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, Copy20Regular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, DocumentTextRegular, createFluentIcon, FilterRegular, GlobeRegular, ArrowExpandAllRegular, ArrowCollapseAllRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, DataBarHorizontalRegular, WrenchRegular, WeatherSunnyRegular, WeatherMoonRegular, ErrorCircleRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, CopyRegular, DeleteRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, StopFilled, PlayFilled, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, PlayRegular, AppGenericRegular, MyLocationRegular, CameraRegular, LightbulbRegular, BorderOutsideRegular, BorderNoneRegular, EyeRegular, EyeOffRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, BranchRegular, DeleteFilled } from '@fluentui/react-icons';
|
|
8
8
|
import { Collapse as Collapse$1, Fade } from '@fluentui/react-motion-components-preview';
|
|
9
9
|
import '@babylonjs/core/Misc/typeStore.js';
|
|
@@ -72,6 +72,7 @@ import { Constants } from '@babylonjs/core/Engines/constants.js';
|
|
|
72
72
|
import { Engine } from '@babylonjs/core/Engines/engine.js';
|
|
73
73
|
import { ParticleSystem } from '@babylonjs/core/Particles/particleSystem.js';
|
|
74
74
|
import { ReadFile } from '@babylonjs/core/Misc/fileTools.js';
|
|
75
|
+
import { CubeTexture } from '@babylonjs/core/Materials/Textures/cubeTexture.js';
|
|
75
76
|
import { Mesh } from '@babylonjs/core/Meshes/mesh.js';
|
|
76
77
|
import { SkeletonViewer } from '@babylonjs/core/Debug/skeletonViewer.js';
|
|
77
78
|
import { VertexBuffer } from '@babylonjs/core/Meshes/buffer.js';
|
|
@@ -89,16 +90,15 @@ import { TransformNode } from '@babylonjs/core/Meshes/transformNode.js';
|
|
|
89
90
|
import { PhysicsPrestepType } from '@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js';
|
|
90
91
|
import '@babylonjs/core/Physics/v2/physicsEngineComponent.js';
|
|
91
92
|
import { PostProcess } from '@babylonjs/core/PostProcesses/postProcess.js';
|
|
92
|
-
import { CubeTexture } from '@babylonjs/core/Materials/Textures/cubeTexture.js';
|
|
93
93
|
import { ImageProcessingConfiguration } from '@babylonjs/core/Materials/imageProcessingConfiguration.js';
|
|
94
94
|
import { Skeleton } from '@babylonjs/core/Bones/skeleton.js';
|
|
95
95
|
import { Sprite } from '@babylonjs/core/Sprites/sprite.js';
|
|
96
96
|
import { SpriteManager } from '@babylonjs/core/Sprites/spriteManager.js';
|
|
97
|
+
import { WhenTextureReadyAsync, GetTextureDataAsync } from '@babylonjs/core/Misc/textureTools.js';
|
|
97
98
|
import { BaseTexture } from '@babylonjs/core/Materials/Textures/baseTexture.js';
|
|
98
99
|
import { MultiRenderTarget } from '@babylonjs/core/Materials/Textures/multiRenderTarget.js';
|
|
99
100
|
import { RenderTargetTexture } from '@babylonjs/core/Materials/Textures/renderTargetTexture.js';
|
|
100
101
|
import { ThinTexture } from '@babylonjs/core/Materials/Textures/thinTexture.js';
|
|
101
|
-
import { WhenTextureReadyAsync, GetTextureDataAsync } from '@babylonjs/core/Misc/textureTools.js';
|
|
102
102
|
import { ClusteredLightContainer } from '@babylonjs/core/Lights/Clustered/clusteredLightContainer.js';
|
|
103
103
|
import '@babylonjs/core/Rendering/boundingBoxRenderer.js';
|
|
104
104
|
import '@babylonjs/core/PostProcesses/RenderPipeline/postProcessRenderPipelineManagerSceneComponent.js';
|
|
@@ -682,13 +682,13 @@ const ToggleButton = (props) => {
|
|
|
682
682
|
return (jsx(ToggleButton$1, { title: title, size: size, icon: checked ? jsx(props.checkedIcon, {}) : props.uncheckedIcon ? jsx(props.uncheckedIcon, {}) : jsx(props.checkedIcon, {}), appearance: appearance, checked: checked, onClick: toggle }));
|
|
683
683
|
};
|
|
684
684
|
|
|
685
|
-
const Button = (props) => {
|
|
686
|
-
Button.displayName = "Button";
|
|
685
|
+
const Button = forwardRef((props, ref) => {
|
|
687
686
|
const { size } = useContext(ToolContext);
|
|
688
687
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
689
688
|
const { icon: Icon, label, ...buttonProps } = props;
|
|
690
|
-
return (jsx(Button$1, { iconPosition: "after", ...buttonProps, size: size, icon: Icon && jsx(Icon, {}), children: label && props.label }));
|
|
691
|
-
};
|
|
689
|
+
return (jsx(Button$1, { ref: ref, iconPosition: "after", ...buttonProps, size: size, icon: Icon && jsx(Icon, {}), children: label && props.label }));
|
|
690
|
+
});
|
|
691
|
+
Button.displayName = "Button";
|
|
692
692
|
|
|
693
693
|
const CustomTokens = {
|
|
694
694
|
inputWidth: "150px",
|
|
@@ -885,7 +885,7 @@ const LinkToEntityPropertyLine = (props) => {
|
|
|
885
885
|
!linkedEntity.reservedDataStore?.hidden && jsx(LinkPropertyLine, { ...rest, value: linkedEntity.name, onLink: () => (selectionService.selectedEntity = linkedEntity) }));
|
|
886
886
|
};
|
|
887
887
|
|
|
888
|
-
const useStyles$
|
|
888
|
+
const useStyles$j = makeStyles({
|
|
889
889
|
accordion: {
|
|
890
890
|
overflowX: "hidden",
|
|
891
891
|
overflowY: "auto",
|
|
@@ -929,13 +929,13 @@ const useStyles$h = makeStyles({
|
|
|
929
929
|
});
|
|
930
930
|
const AccordionSection = (props) => {
|
|
931
931
|
AccordionSection.displayName = "AccordionSection";
|
|
932
|
-
const classes = useStyles$
|
|
932
|
+
const classes = useStyles$j();
|
|
933
933
|
return jsx("div", { className: classes.panelDiv, children: props.children });
|
|
934
934
|
};
|
|
935
935
|
const StringAccordion = Accordion$1;
|
|
936
936
|
const Accordion = forwardRef((props, ref) => {
|
|
937
937
|
Accordion.displayName = "Accordion";
|
|
938
|
-
const classes = useStyles$
|
|
938
|
+
const classes = useStyles$j();
|
|
939
939
|
const { size } = useContext(ToolContext);
|
|
940
940
|
const { children, highlightSections, ...rest } = props;
|
|
941
941
|
const validChildren = useMemo(() => {
|
|
@@ -1067,7 +1067,7 @@ function AsReadonlyArray(array) {
|
|
|
1067
1067
|
return array;
|
|
1068
1068
|
}
|
|
1069
1069
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1070
|
-
const useStyles$
|
|
1070
|
+
const useStyles$i = makeStyles({
|
|
1071
1071
|
rootDiv: {
|
|
1072
1072
|
flex: 1,
|
|
1073
1073
|
overflow: "hidden",
|
|
@@ -1076,7 +1076,7 @@ const useStyles$g = makeStyles({
|
|
|
1076
1076
|
},
|
|
1077
1077
|
});
|
|
1078
1078
|
function ExtensibleAccordion(props) {
|
|
1079
|
-
const classes = useStyles$
|
|
1079
|
+
const classes = useStyles$i();
|
|
1080
1080
|
const { children, sections, sectionContent, context, sectionsRef } = props;
|
|
1081
1081
|
const defaultSections = useMemo(() => {
|
|
1082
1082
|
const defaultSections = [];
|
|
@@ -1181,7 +1181,7 @@ function ExtensibleAccordion(props) {
|
|
|
1181
1181
|
})] }) })) }));
|
|
1182
1182
|
}
|
|
1183
1183
|
|
|
1184
|
-
const useStyles$
|
|
1184
|
+
const useStyles$h = makeStyles({
|
|
1185
1185
|
paneRootDiv: {
|
|
1186
1186
|
display: "flex",
|
|
1187
1187
|
flex: 1,
|
|
@@ -1194,12 +1194,12 @@ const useStyles$f = makeStyles({
|
|
|
1194
1194
|
*/
|
|
1195
1195
|
const SidePaneContainer = forwardRef((props, ref) => {
|
|
1196
1196
|
const { className, ...rest } = props;
|
|
1197
|
-
const classes = useStyles$
|
|
1197
|
+
const classes = useStyles$h();
|
|
1198
1198
|
return (jsx("div", { className: mergeClasses(classes.paneRootDiv, className), ref: ref, ...rest, children: props.children }));
|
|
1199
1199
|
});
|
|
1200
1200
|
|
|
1201
1201
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1202
|
-
const useStyles$
|
|
1202
|
+
const useStyles$g = makeStyles({
|
|
1203
1203
|
extensionTeachingPopover: {
|
|
1204
1204
|
maxWidth: "320px",
|
|
1205
1205
|
},
|
|
@@ -1210,7 +1210,7 @@ const useStyles$e = makeStyles({
|
|
|
1210
1210
|
* @returns The teaching moment popover.
|
|
1211
1211
|
*/
|
|
1212
1212
|
const TeachingMoment = ({ shouldDisplay, positioningRef, onOpenChange, title, description }) => {
|
|
1213
|
-
const classes = useStyles$
|
|
1213
|
+
const classes = useStyles$g();
|
|
1214
1214
|
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 })] }) }));
|
|
1215
1215
|
};
|
|
1216
1216
|
|
|
@@ -1466,13 +1466,13 @@ function ConstructorFactory(constructor) {
|
|
|
1466
1466
|
}
|
|
1467
1467
|
|
|
1468
1468
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1469
|
-
const useStyles$
|
|
1469
|
+
const useStyles$f = makeStyles({
|
|
1470
1470
|
placeholderDiv: {
|
|
1471
1471
|
padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalM}`,
|
|
1472
1472
|
},
|
|
1473
1473
|
});
|
|
1474
1474
|
const PropertiesPane = (props) => {
|
|
1475
|
-
const classes = useStyles$
|
|
1475
|
+
const classes = useStyles$f();
|
|
1476
1476
|
const entity = props.context;
|
|
1477
1477
|
return entity != null ? (jsx(ExtensibleAccordion, { ...props })) : (jsx("div", { className: classes.placeholderDiv, children: jsx(Body1Strong, { italic: true, children: "No entity selected." }) }));
|
|
1478
1478
|
};
|
|
@@ -1613,7 +1613,7 @@ function useResizeHandle(params) {
|
|
|
1613
1613
|
const RootComponentServiceIdentity = Symbol("RootComponent");
|
|
1614
1614
|
const ShellServiceIdentity = Symbol("ShellService");
|
|
1615
1615
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1616
|
-
const useStyles$
|
|
1616
|
+
const useStyles$e = makeStyles({
|
|
1617
1617
|
mainView: {
|
|
1618
1618
|
flex: 1,
|
|
1619
1619
|
display: "flex",
|
|
@@ -1801,12 +1801,12 @@ const DockMenu = (props) => {
|
|
|
1801
1801
|
};
|
|
1802
1802
|
const PaneHeader = (props) => {
|
|
1803
1803
|
const { id, title, dockOptions } = props;
|
|
1804
|
-
const classes = useStyles$
|
|
1804
|
+
const classes = useStyles$e();
|
|
1805
1805
|
return (jsx(Theme, { invert: true, children: jsxs("div", { className: classes.paneHeaderDiv, children: [jsx(Subtitle2Stronger, { className: classes.paneHeaderText, children: title }), jsx(DockMenu, { sidePaneId: id, dockOptions: dockOptions, children: jsx(Button$1, { className: classes.paneHeaderButton, appearance: "transparent", icon: jsx(MoreHorizontalRegular, {}) }) })] }) }));
|
|
1806
1806
|
};
|
|
1807
1807
|
// This is a wrapper for an item in a toolbar that simply adds a teaching moment, which is useful for dynamically added items, possibly from extensions.
|
|
1808
1808
|
const ToolbarItem = ({ verticalLocation, horizontalLocation, id, component: Component, displayName: displayName, suppressTeachingMoment }) => {
|
|
1809
|
-
const classes = useStyles$
|
|
1809
|
+
const classes = useStyles$e();
|
|
1810
1810
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Bar/${verticalLocation}/${horizontalLocation}/${displayName ?? id}`), [displayName, id]);
|
|
1811
1811
|
const teachingMoment = useTeachingMoment(suppressTeachingMoment);
|
|
1812
1812
|
return (jsxs(Fragment, { children: [jsx(TeachingMoment, { ...teachingMoment, shouldDisplay: teachingMoment.shouldDisplay && !suppressTeachingMoment, title: displayName ?? "Extension", description: `The "${displayName ?? id}" extension can be accessed here.` }), jsx("div", { className: classes.barItem, ref: teachingMoment.targetRef, children: jsx(Component, {}) })] }));
|
|
@@ -1814,7 +1814,7 @@ const ToolbarItem = ({ verticalLocation, horizontalLocation, id, component: Comp
|
|
|
1814
1814
|
// TODO: Handle overflow, possibly via https://react.fluentui.dev/?path=/docs/components-overflow--docs with priority.
|
|
1815
1815
|
// This component just renders a toolbar with left aligned toolbar items on the left and right aligned toolbar items on the right.
|
|
1816
1816
|
const Toolbar = ({ location, components }) => {
|
|
1817
|
-
const classes = useStyles$
|
|
1817
|
+
const classes = useStyles$e();
|
|
1818
1818
|
const leftComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "left"), [components]);
|
|
1819
1819
|
const rightComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "right"), [components]);
|
|
1820
1820
|
return (jsx(Fragment, { children: components.length > 0 && (jsxs("div", { className: `${classes.bar} ${location === "top" ? classes.barTop : null}`, children: [jsx("div", { className: classes.barLeft, children: leftComponents.map((entry) => (jsx(ToolbarItem, { verticalLocation: location, horizontalLocation: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) }), jsx("div", { className: classes.barRight, children: rightComponents.map((entry) => (jsx(ToolbarItem, { verticalLocation: location, horizontalLocation: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, suppressTeachingMoment: entry.suppressTeachingMoment }, entry.key))) })] })) }));
|
|
@@ -1824,7 +1824,7 @@ const SidePaneTab = (props) => {
|
|
|
1824
1824
|
const { location, id, isSelected, dockOptions,
|
|
1825
1825
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1826
1826
|
icon: Icon, title, suppressTeachingMoment, } = props;
|
|
1827
|
-
const classes = useStyles$
|
|
1827
|
+
const classes = useStyles$e();
|
|
1828
1828
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Pane/${location}/${title ?? id}`), [title, id]);
|
|
1829
1829
|
const teachingMoment = useTeachingMoment(suppressTeachingMoment);
|
|
1830
1830
|
const tabClass = mergeClasses(classes.tab, isSelected ? undefined : classes.unselectedTab);
|
|
@@ -1837,7 +1837,7 @@ const SidePaneTab = (props) => {
|
|
|
1837
1837
|
// In "compact" mode, the tab list is integrated into the pane itself.
|
|
1838
1838
|
// In "full" mode, the returned tab list is later injected into the toolbar.
|
|
1839
1839
|
function usePane(location, layoutMode, defaultWidth, minWidth, sidePanes, onSelectSidePane, dockOperations, toolbarMode, topBarItems, bottomBarItems) {
|
|
1840
|
-
const classes = useStyles$
|
|
1840
|
+
const classes = useStyles$e();
|
|
1841
1841
|
const [topSelectedTab, setTopSelectedTab] = useState();
|
|
1842
1842
|
const [bottomSelectedTab, setBottomSelectedTab] = useState();
|
|
1843
1843
|
const [collapsed, setCollapsed] = useState(false);
|
|
@@ -2077,7 +2077,7 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
|
|
|
2077
2077
|
undock: () => onDockChanged.notifyObservers({ location: "right", dock: false }),
|
|
2078
2078
|
};
|
|
2079
2079
|
const rootComponent = () => {
|
|
2080
|
-
const classes = useStyles$
|
|
2080
|
+
const classes = useStyles$e();
|
|
2081
2081
|
const [sidePaneDockOverrides, setSidePaneDockOverrides] = useSidePaneDockOverrides();
|
|
2082
2082
|
// This function returns a promise that resolves after the dock change takes effect so that
|
|
2083
2083
|
// we can then select the re-docked pane.
|
|
@@ -2513,7 +2513,7 @@ function useCommandContextMenuState(commands) {
|
|
|
2513
2513
|
return [checkedContextMenuItems, onContextMenuCheckedValueChange, contextMenuItems];
|
|
2514
2514
|
}
|
|
2515
2515
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
2516
|
-
const useStyles$
|
|
2516
|
+
const useStyles$d = makeStyles({
|
|
2517
2517
|
rootDiv: {
|
|
2518
2518
|
flex: 1,
|
|
2519
2519
|
overflow: "hidden",
|
|
@@ -2581,14 +2581,14 @@ function MakeInlineCommandElement(command, isPlaceholder) {
|
|
|
2581
2581
|
}
|
|
2582
2582
|
const SceneTreeItem = (props) => {
|
|
2583
2583
|
const { isSelected, select } = props;
|
|
2584
|
-
const classes = useStyles$
|
|
2584
|
+
const classes = useStyles$d();
|
|
2585
2585
|
const [compactMode] = useCompactMode();
|
|
2586
2586
|
const treeItemLayoutClass = mergeClasses(classes.sceneTreeItemLayout, compactMode ? classes.treeItemLayoutCompact : undefined);
|
|
2587
2587
|
return (jsx(FlatTreeItem, { value: "scene", itemType: "leaf", parentValue: undefined, "aria-level": 1, "aria-setsize": 1, "aria-posinset": 1, onClick: select, children: jsx(TreeItemLayout, { iconBefore: jsx(GlobeRegular, {}), className: treeItemLayoutClass, style: isSelected ? { backgroundColor: tokens.colorNeutralBackground1Selected } : undefined, children: jsx(Body1Strong, { wrap: false, truncate: true, children: "Scene" }) }) }, "scene"));
|
|
2588
2588
|
};
|
|
2589
2589
|
const SectionTreeItem = (props) => {
|
|
2590
2590
|
const { section, isFiltering, commandProviders, expandAll, collapseAll } = props;
|
|
2591
|
-
const classes = useStyles$
|
|
2591
|
+
const classes = useStyles$d();
|
|
2592
2592
|
const [compactMode] = useCompactMode();
|
|
2593
2593
|
// Get the commands that apply to this section.
|
|
2594
2594
|
const commands = useResource(useCallback(() => {
|
|
@@ -2605,7 +2605,7 @@ const SectionTreeItem = (props) => {
|
|
|
2605
2605
|
};
|
|
2606
2606
|
const EntityTreeItem = (props) => {
|
|
2607
2607
|
const { entityItem, isSelected, select, isFiltering, commandProviders, expandAll, collapseAll } = props;
|
|
2608
|
-
const classes = useStyles$
|
|
2608
|
+
const classes = useStyles$d();
|
|
2609
2609
|
const [compactMode] = useCompactMode();
|
|
2610
2610
|
const hasChildren = !!entityItem.children?.length;
|
|
2611
2611
|
const displayInfo = useResource(useCallback(() => {
|
|
@@ -2698,7 +2698,7 @@ const EntityTreeItem = (props) => {
|
|
|
2698
2698
|
}, children: jsx(Body1, { wrap: false, truncate: true, children: name }) }) }, entityItem.entity.uniqueId) }), jsx(MenuPopover, { hidden: !hasChildren && contextMenuCommands.length === 0, children: jsxs(MenuList, { children: [hasChildren && (jsxs(Fragment, { children: [jsx(MenuItem, { icon: jsx(ArrowExpandAllRegular, {}), onClick: expandAll, children: jsx(Body1, { children: "Expand All" }) }), jsx(MenuItem, { icon: jsx(ArrowCollapseAllRegular, {}), onClick: collapseAll, children: jsx(Body1, { children: "Collapse All" }) })] })), hasChildren && contextMenuCommands.length > 0 && jsx(MenuDivider, {}), contextMenuItems] }) })] }));
|
|
2699
2699
|
};
|
|
2700
2700
|
const SceneExplorer = (props) => {
|
|
2701
|
-
const classes = useStyles$
|
|
2701
|
+
const classes = useStyles$d();
|
|
2702
2702
|
const { sections, entityCommandProviders, sectionCommandProviders, scene, selectedEntity } = props;
|
|
2703
2703
|
const [openItems, setOpenItems] = useState(new Set());
|
|
2704
2704
|
const [sceneVersion, setSceneVersion] = useState(0);
|
|
@@ -3347,20 +3347,37 @@ const FrameStepsStats = ({ context: scene }) => {
|
|
|
3347
3347
|
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")] }));
|
|
3348
3348
|
};
|
|
3349
3349
|
|
|
3350
|
-
|
|
3351
|
-
|
|
3350
|
+
/**
|
|
3351
|
+
* A button that triggers a file upload dialog.
|
|
3352
|
+
* Combines a Button with a hidden file input.
|
|
3353
|
+
* @param props UploadButtonProps
|
|
3354
|
+
* @returns UploadButton component
|
|
3355
|
+
*/
|
|
3356
|
+
const UploadButton = (props) => {
|
|
3357
|
+
const { onUpload, accept, label, ...buttonProps } = props;
|
|
3358
|
+
UploadButton.displayName = "UploadButton";
|
|
3352
3359
|
const inputRef = useRef(null);
|
|
3353
|
-
const
|
|
3360
|
+
const handleClick = () => {
|
|
3354
3361
|
inputRef.current?.click();
|
|
3355
3362
|
};
|
|
3356
3363
|
const handleChange = (evt) => {
|
|
3357
3364
|
const files = evt.target.files;
|
|
3358
3365
|
if (files && files.length) {
|
|
3359
|
-
|
|
3366
|
+
onUpload(files);
|
|
3360
3367
|
}
|
|
3361
3368
|
evt.target.value = "";
|
|
3362
3369
|
};
|
|
3363
|
-
return (jsxs(Fragment, { children: [jsx(
|
|
3370
|
+
return (jsxs(Fragment, { children: [jsx(Button, { icon: ArrowUploadRegular, title: label ?? "Upload", label: label, onClick: handleClick, ...buttonProps }), jsx("input", { ref: inputRef, type: "file", accept: accept, style: { display: "none" }, onChange: handleChange })] }));
|
|
3371
|
+
};
|
|
3372
|
+
|
|
3373
|
+
/**
|
|
3374
|
+
* A full-width line with an upload button.
|
|
3375
|
+
* For just the button without the line wrapper, use UploadButton directly.
|
|
3376
|
+
* @returns An UploadButton wrapped in a LineContainer
|
|
3377
|
+
*/
|
|
3378
|
+
const FileUploadLine = ({ onClick, label, accept, ...buttonProps }) => {
|
|
3379
|
+
FileUploadLine.displayName = "FileUploadLine";
|
|
3380
|
+
return (jsx(LineContainer, { children: jsx(UploadButton, { onUpload: onClick, accept: accept, label: label, ...buttonProps }) }));
|
|
3364
3381
|
};
|
|
3365
3382
|
|
|
3366
3383
|
var PerfMetadataCategory;
|
|
@@ -3476,14 +3493,14 @@ const TextPropertyLine = (props) => {
|
|
|
3476
3493
|
return (jsx(PropertyLine, { ...props, children: jsx(Body1, { title: title, children: value }) }));
|
|
3477
3494
|
};
|
|
3478
3495
|
|
|
3479
|
-
const useStyles$
|
|
3496
|
+
const useStyles$c = makeStyles({
|
|
3480
3497
|
pinnedStatsPane: {
|
|
3481
3498
|
flex: "0 1 auto",
|
|
3482
3499
|
paddingBottom: tokens.spacingHorizontalM,
|
|
3483
3500
|
},
|
|
3484
3501
|
});
|
|
3485
3502
|
const StatsPane = (props) => {
|
|
3486
|
-
const classes = useStyles$
|
|
3503
|
+
const classes = useStyles$c();
|
|
3487
3504
|
const scene = props.context;
|
|
3488
3505
|
const engine = scene.getEngine();
|
|
3489
3506
|
const fps = useObservableState(() => Math.round(engine.getFps()), engine.onBeginFrameObservable);
|
|
@@ -3661,7 +3678,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3661
3678
|
keywords: ["export", "gltf", "glb", "babylon", "exporter", "tools"],
|
|
3662
3679
|
...BabylonWebResources,
|
|
3663
3680
|
author: { name: "Alex Chuber", forumUserName: "alexchuber" },
|
|
3664
|
-
getExtensionModuleAsync: async () => await import('./exportService-
|
|
3681
|
+
getExtensionModuleAsync: async () => await import('./exportService-LaUVRgd_.js'),
|
|
3665
3682
|
},
|
|
3666
3683
|
{
|
|
3667
3684
|
name: "Capture Tools",
|
|
@@ -3669,7 +3686,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3669
3686
|
keywords: ["capture", "screenshot", "gif", "video", "tools"],
|
|
3670
3687
|
...BabylonWebResources,
|
|
3671
3688
|
author: { name: "Alex Chuber", forumUserName: "alexchuber" },
|
|
3672
|
-
getExtensionModuleAsync: async () => await import('./captureService-
|
|
3689
|
+
getExtensionModuleAsync: async () => await import('./captureService-CbpbBn5F.js'),
|
|
3673
3690
|
},
|
|
3674
3691
|
{
|
|
3675
3692
|
name: "Import Tools",
|
|
@@ -3677,7 +3694,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3677
3694
|
keywords: ["import", "tools"],
|
|
3678
3695
|
...BabylonWebResources,
|
|
3679
3696
|
author: { name: "Alex Chuber", forumUserName: "alexchuber" },
|
|
3680
|
-
getExtensionModuleAsync: async () => await import('./importService-
|
|
3697
|
+
getExtensionModuleAsync: async () => await import('./importService-B98QFvNM.js'),
|
|
3681
3698
|
},
|
|
3682
3699
|
{
|
|
3683
3700
|
name: "Quick Creation Tools (Preview)",
|
|
@@ -3685,7 +3702,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3685
3702
|
keywords: ["creation", "tools"],
|
|
3686
3703
|
...BabylonWebResources,
|
|
3687
3704
|
author: { name: "Babylon.js", forumUserName: "" },
|
|
3688
|
-
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-
|
|
3705
|
+
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-Bg2plbI-.js'),
|
|
3689
3706
|
},
|
|
3690
3707
|
]);
|
|
3691
3708
|
|
|
@@ -3903,6 +3920,29 @@ const Dropdown = (props) => {
|
|
|
3903
3920
|
const NumberDropdown = Dropdown;
|
|
3904
3921
|
const StringDropdown = Dropdown;
|
|
3905
3922
|
|
|
3923
|
+
const useStyles$b = makeStyles({
|
|
3924
|
+
surface: {
|
|
3925
|
+
maxWidth: "400px",
|
|
3926
|
+
},
|
|
3927
|
+
content: {
|
|
3928
|
+
display: "flex",
|
|
3929
|
+
flexDirection: "column",
|
|
3930
|
+
gap: tokens.spacingVerticalM,
|
|
3931
|
+
padding: tokens.spacingHorizontalL,
|
|
3932
|
+
minWidth: "300px",
|
|
3933
|
+
},
|
|
3934
|
+
});
|
|
3935
|
+
const Popover = (props) => {
|
|
3936
|
+
const { children } = props;
|
|
3937
|
+
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
3938
|
+
const classes = useStyles$b();
|
|
3939
|
+
return (jsxs(Popover$1, { open: popoverOpen, onOpenChange: (_, data) => setPopoverOpen(data.open), positioning: {
|
|
3940
|
+
align: "start",
|
|
3941
|
+
overflowBoundary: document.body,
|
|
3942
|
+
autoSize: true,
|
|
3943
|
+
}, trapFocus: true, children: [jsx(PopoverTrigger, { disableButtonEnhancement: true, children: props.trigger ?? jsx(Button, { icon: props.icon, onClick: () => setPopoverOpen(true) }) }), jsx(PopoverSurface, { className: classes.surface, children: jsx("div", { className: classes.content, children: children }) })] }));
|
|
3944
|
+
};
|
|
3945
|
+
|
|
3906
3946
|
const useColorPickerStyles = makeStyles({
|
|
3907
3947
|
container: {
|
|
3908
3948
|
width: "350px",
|
|
@@ -3954,7 +3994,6 @@ const ColorPickerPopup = (props) => {
|
|
|
3954
3994
|
ColorPickerPopup.displayName = "ColorPickerPopup";
|
|
3955
3995
|
const classes = useColorPickerStyles();
|
|
3956
3996
|
const [color, setColor] = useState(props.value);
|
|
3957
|
-
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
3958
3997
|
const [isLinear, setIsLinear] = useState(props.isLinearMode ?? false);
|
|
3959
3998
|
const [isFloat, setFloat] = useState(false);
|
|
3960
3999
|
const { size } = useContext(ToolContext);
|
|
@@ -3972,23 +4011,19 @@ const ColorPickerPopup = (props) => {
|
|
|
3972
4011
|
setColor(newColor);
|
|
3973
4012
|
props.onChange(newColor); // Ensures the parent is notified when color changes from within colorPicker
|
|
3974
4013
|
};
|
|
3975
|
-
return (
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
}, options: [
|
|
3989
|
-
{ label: "Int", value: 0 },
|
|
3990
|
-
{ label: "Float", value: 1 },
|
|
3991
|
-
], disabled: true, value: isFloat ? 1 : 0, onChange: (val) => setFloat(val === 1) })] }), jsxs("div", { className: classes.inputRow, 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.inputRow, 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 })] }), jsx("div", { className: classes.inputRow, children: jsx(InputHexField, { title: "Hexadecimal", linearHex: isLinear, isLinearMode: isLinear, value: color, onChange: handleChange }) })] }) })] }));
|
|
4014
|
+
return (jsx(Popover, { trigger: jsx(ColorSwatch, { borderColor: tokens.colorNeutralShadowKeyDarker, size: size === "small" ? "extra-small" : "small", shape: "rounded", color: color.toHexString(), value: color.toHexString().slice(1) }), children: jsxs("div", { className: classes.container, children: [jsxs(ColorPicker, { className: classes.colorPicker, color: rgbaToHsv(color), onColorChange: handleColorPickerChange, children: [jsx(ColorArea, { inputX: { "aria-label": "Saturation" }, inputY: { "aria-label": "Brightness" } }), jsx(ColorSlider, { "aria-label": "Hue" }), color instanceof Color4 && jsx(AlphaSlider, { "aria-label": "Alpha" })] }), jsxs("div", { className: classes.row, children: [jsx("div", { className: classes.previewColor, style: { backgroundColor: color.toHexString() } }), jsx(NumberDropdown, { className: classes.inputField, infoLabel: {
|
|
4015
|
+
label: "Color Space",
|
|
4016
|
+
info: jsx(Body1, { children: "Today this is not mutable as the color space is determined by the entity. Soon we will allow swapping" }),
|
|
4017
|
+
}, options: [
|
|
4018
|
+
{ label: "Gamma", value: 0 },
|
|
4019
|
+
{ label: "Linear", value: 1 },
|
|
4020
|
+
], disabled: true, value: isLinear ? 1 : 0, onChange: (val) => setIsLinear(val === 1) }), jsx(NumberDropdown, { className: classes.inputField, infoLabel: {
|
|
4021
|
+
label: "Data Type",
|
|
4022
|
+
info: jsx(Body1, { children: "We will introduce this functionality soon!" }),
|
|
4023
|
+
}, options: [
|
|
4024
|
+
{ label: "Int", value: 0 },
|
|
4025
|
+
{ label: "Float", value: 1 },
|
|
4026
|
+
], disabled: true, value: isFloat ? 1 : 0, onChange: (val) => setFloat(val === 1) })] }), jsxs("div", { className: classes.inputRow, 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.inputRow, 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 })] }), jsx("div", { className: classes.inputRow, children: jsx(InputHexField, { title: "Hexadecimal", linearHex: isLinear, isLinearMode: isLinear, value: color, onChange: handleChange }) })] }) }));
|
|
3992
4027
|
};
|
|
3993
4028
|
/**
|
|
3994
4029
|
* Component which displays the passed in color's HEX value, either in linearSpace (if linearHex is true) or in gamma space
|
|
@@ -4108,7 +4143,7 @@ const ColorPropertyLine = forwardRef((props, ref) => {
|
|
|
4108
4143
|
const Color3PropertyLine = ColorPropertyLine;
|
|
4109
4144
|
const Color4PropertyLine = ColorPropertyLine;
|
|
4110
4145
|
|
|
4111
|
-
const useStyles$
|
|
4146
|
+
const useStyles$a = makeStyles({
|
|
4112
4147
|
dropdown: {
|
|
4113
4148
|
...UniformWidthStyling,
|
|
4114
4149
|
},
|
|
@@ -4120,7 +4155,7 @@ const useStyles$9 = makeStyles({
|
|
|
4120
4155
|
*/
|
|
4121
4156
|
const DropdownPropertyLine = forwardRef((props, ref) => {
|
|
4122
4157
|
DropdownPropertyLine.displayName = "DropdownPropertyLine";
|
|
4123
|
-
const classes = useStyles$
|
|
4158
|
+
const classes = useStyles$a();
|
|
4124
4159
|
return (jsx(PropertyLine, { ...props, ref: ref, children: jsx(Dropdown, { ...props, className: classes.dropdown }) }));
|
|
4125
4160
|
});
|
|
4126
4161
|
/**
|
|
@@ -4694,7 +4729,7 @@ class ServiceContainer {
|
|
|
4694
4729
|
}
|
|
4695
4730
|
}
|
|
4696
4731
|
|
|
4697
|
-
const useStyles$
|
|
4732
|
+
const useStyles$9 = makeStyles({
|
|
4698
4733
|
themeButton: {
|
|
4699
4734
|
margin: 0,
|
|
4700
4735
|
},
|
|
@@ -4713,7 +4748,7 @@ const ThemeSelectorServiceDefinition = {
|
|
|
4713
4748
|
suppressTeachingMoment: true,
|
|
4714
4749
|
order: -300,
|
|
4715
4750
|
component: () => {
|
|
4716
|
-
const classes = useStyles$
|
|
4751
|
+
const classes = useStyles$9();
|
|
4717
4752
|
const { isDarkMode, themeMode, setThemeMode } = useThemeMode();
|
|
4718
4753
|
const onSelectedThemeChange = useCallback((e, data) => {
|
|
4719
4754
|
setThemeMode(data.checkedItems.includes("System") ? "system" : data.checkedItems[0].toLocaleLowerCase());
|
|
@@ -4731,7 +4766,7 @@ const ThemeSelectorServiceDefinition = {
|
|
|
4731
4766
|
};
|
|
4732
4767
|
|
|
4733
4768
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
4734
|
-
const useStyles$
|
|
4769
|
+
const useStyles$8 = makeStyles({
|
|
4735
4770
|
app: {
|
|
4736
4771
|
colorScheme: "light dark",
|
|
4737
4772
|
flexGrow: 1,
|
|
@@ -4767,7 +4802,7 @@ function MakeModularTool(options) {
|
|
|
4767
4802
|
SetThemeMode(themeMode);
|
|
4768
4803
|
}
|
|
4769
4804
|
const modularToolRootComponent = () => {
|
|
4770
|
-
const classes = useStyles$
|
|
4805
|
+
const classes = useStyles$8();
|
|
4771
4806
|
const [extensionManagerContext, setExtensionManagerContext] = useState();
|
|
4772
4807
|
const [requiredExtensions, setRequiredExtensions] = useState();
|
|
4773
4808
|
const [requiredExtensionsDeferred, setRequiredExtensionsDeferred] = useState();
|
|
@@ -4793,7 +4828,7 @@ function MakeModularTool(options) {
|
|
|
4793
4828
|
});
|
|
4794
4829
|
// Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
|
|
4795
4830
|
if (extensionFeeds.length > 0) {
|
|
4796
|
-
const { ExtensionListServiceDefinition } = await import('./extensionsListService-
|
|
4831
|
+
const { ExtensionListServiceDefinition } = await import('./extensionsListService-CwnEf0dV.js');
|
|
4797
4832
|
await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);
|
|
4798
4833
|
}
|
|
4799
4834
|
// Register the theme selector service (for selecting the theme) if theming is configured.
|
|
@@ -4975,7 +5010,7 @@ const MeshIcon = createFluentIcon("Mesh", "16", '<path d="M14.03,3.54l-5.11-2.07
|
|
|
4975
5010
|
const TranslateIcon = createFluentIcon("Translate", "24", '<path d="M20.16,12.98l-2.75-2.75c-.29-.29-.77-.29-1.06,0-.29.29-.29.77,0,1.06l1.47,1.47h-6.69v-6.69l1.47,1.47c.29.29.77.29,1.06,0,.29-.29.29-.77,0-1.06l-2.75-2.75c-.14-.14-.33-.22-.53-.22s-.39.08-.53.22l-2.75,2.75c-.29.29-.29.77,0,1.06.29.29.77.29,1.06,0l1.47-1.47v7.13l-3.52,3.52v-2.08c0-.41-.34-.75-.75-.75s-.75.34-.75.75v3.89c0,.2.08.39.22.53.14.14.33.22.53.22h3.89c.41,0,.75-.34.75-.75s-.34-.75-.75-.75h-2.08s3.52-3.52,3.52-3.52h7.13l-1.47,1.47c-.29.29-.29.77,0,1.06s.77.29,1.06,0l2.75-2.75c.14-.14.22-.33.22-.53s-.08-.39-.22-.53Z" />');
|
|
4976
5011
|
const MaterialIcon = createFluentIcon("Material", "16", '<path d="M14.74,6.3c-.09-.36-.38-.64-.75-.72-.04-.09-.08-.18-.12-.27.1-.15.16-.32.16-.51,0-.18-.05-.34-.13-.48-1.23-1.97-3.41-3.28-5.9-3.28C4.16,1.04,1.04,4.16,1.04,7.99c0,.39.23.72.57.88.02.12.03.25.06.37-.18.18-.3.42-.3.7,0,.11.02.21.06.31.94,2.74,3.53,4.71,6.58,4.71,3.84,0,6.96-3.12,6.96-6.96,0-.59-.08-1.16-.22-1.7ZM2.07,8.58c-.02-.19-.03-.39-.03-.58,0-3.29,2.67-5.96,5.96-5.96,2.23,0,4.17,1.23,5.2,3.05.05.18-.07.45-.3.75-.57-.73-1.45-1.21-2.45-1.21-1.72,0-3.12,1.4-3.12,3.11,0,.33.07.65.16.95-3.05.82-5.17.52-5.42-.11ZM12.56,7.75c0,1.17-.95,2.11-2.11,2.11s-2.12-.95-2.12-2.11.95-2.11,2.12-2.11,2.11.95,2.11,2.11ZM8,13.96c-2.6,0-4.81-1.68-5.62-4.01.5.16,1.11.24,1.79.24,1.15,0,2.49-.22,3.79-.59.57.76,1.47,1.26,2.49,1.26,1.72,0,3.11-1.4,3.11-3.11,0-.34-.07-.65-.17-.96.13-.13.24-.26.34-.39.14.51.22,1.04.22,1.6,0,3.29-2.67,5.96-5.96,5.96Z"/>');
|
|
4977
5012
|
|
|
4978
|
-
const useStyles$
|
|
5013
|
+
const useStyles$7 = makeStyles({
|
|
4979
5014
|
coordinatesModeButton: {
|
|
4980
5015
|
margin: `0 0 0 ${tokens.spacingHorizontalXS}`,
|
|
4981
5016
|
},
|
|
@@ -4985,7 +5020,7 @@ const useStyles$6 = makeStyles({
|
|
|
4985
5020
|
});
|
|
4986
5021
|
const GizmoToolbar = (props) => {
|
|
4987
5022
|
const { scene, entity, gizmoService } = props;
|
|
4988
|
-
const classes = useStyles$
|
|
5023
|
+
const classes = useStyles$7();
|
|
4989
5024
|
const gizmoManager = useResource(useCallback(() => {
|
|
4990
5025
|
const utilityLayerRef = gizmoService.getUtilityLayer(scene);
|
|
4991
5026
|
const keepDepthUtilityLayerRef = gizmoService.getUtilityLayer(scene, "keepDepth");
|
|
@@ -5100,7 +5135,7 @@ const GizmoToolbarServiceDefinition = {
|
|
|
5100
5135
|
},
|
|
5101
5136
|
};
|
|
5102
5137
|
|
|
5103
|
-
const useStyles$
|
|
5138
|
+
const useStyles$6 = makeStyles({
|
|
5104
5139
|
badge: {
|
|
5105
5140
|
margin: tokens.spacingHorizontalXXS,
|
|
5106
5141
|
fontFamily: "monospace",
|
|
@@ -5116,7 +5151,7 @@ const MiniStatsServiceDefinition = {
|
|
|
5116
5151
|
horizontalLocation: "right",
|
|
5117
5152
|
suppressTeachingMoment: true,
|
|
5118
5153
|
component: () => {
|
|
5119
|
-
const classes = useStyles$
|
|
5154
|
+
const classes = useStyles$6();
|
|
5120
5155
|
const scene = useObservableState(useCallback(() => sceneContext.currentScene, [sceneContext.currentScene]), sceneContext.currentSceneObservable);
|
|
5121
5156
|
const engine = scene?.getEngine();
|
|
5122
5157
|
const fps = useObservableState(useCallback(() => (engine ? Math.round(engine.getFps()) : null), [engine]), engine?.onBeginFrameObservable);
|
|
@@ -6086,6 +6121,168 @@ const PBRBaseMaterialSheenProperties = (props) => {
|
|
|
6086
6121
|
} }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Roughness", target: material.sheen, propertyKey: "_useRoughness" }), jsx(Collapse, { visible: useRoughness, children: jsx(BoundProperty, { nullable: true, component: SyncedSliderPropertyLine, label: "Roughness", target: material.sheen, propertyKey: "roughness", defaultValue: 0, min: 0, max: 1, step: 0.01 }) }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Roughness from Main Texture", target: material.sheen, propertyKey: "useRoughnessFromMainTexture" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Albedo Scaling", target: material.sheen, propertyKey: "albedoScaling" })] })] }));
|
|
6087
6122
|
};
|
|
6088
6123
|
|
|
6124
|
+
/**
|
|
6125
|
+
* A button that uploads a file and either:
|
|
6126
|
+
* - Updates an existing Texture or CubeTexture via updateURL (if texture prop is provided)
|
|
6127
|
+
* - Creates a new Texture or CubeTexture (if scene/onChange props are provided)
|
|
6128
|
+
* @param props TextureUploadProps
|
|
6129
|
+
* @returns UploadButton component that handles texture upload
|
|
6130
|
+
*/
|
|
6131
|
+
const TextureUpload = (props) => {
|
|
6132
|
+
TextureUpload.displayName = "TextureUpload";
|
|
6133
|
+
const label = props.texture ? "Upload Texture" : undefined;
|
|
6134
|
+
// TODO: This should probably be dynamically fetching a list of supported texture extensions
|
|
6135
|
+
const accept = ".jpg, .png, .tga, .dds, .env, .exr";
|
|
6136
|
+
const handleUpload = useCallback((files) => {
|
|
6137
|
+
const file = files[0];
|
|
6138
|
+
if (!file) {
|
|
6139
|
+
return;
|
|
6140
|
+
}
|
|
6141
|
+
ReadFile(file, (data) => {
|
|
6142
|
+
const blob = new Blob([data], { type: "octet/stream" });
|
|
6143
|
+
// Update existing texture
|
|
6144
|
+
if (props.texture) {
|
|
6145
|
+
const { texture, onChange } = props;
|
|
6146
|
+
const reader = new FileReader();
|
|
6147
|
+
reader.readAsDataURL(blob);
|
|
6148
|
+
reader.onloadend = () => {
|
|
6149
|
+
const base64data = reader.result;
|
|
6150
|
+
if (texture instanceof CubeTexture) {
|
|
6151
|
+
let extension = undefined;
|
|
6152
|
+
if (file.name.toLowerCase().indexOf(".dds") > 0) {
|
|
6153
|
+
extension = ".dds";
|
|
6154
|
+
}
|
|
6155
|
+
else if (file.name.toLowerCase().indexOf(".env") > 0) {
|
|
6156
|
+
extension = ".env";
|
|
6157
|
+
}
|
|
6158
|
+
texture.updateURL(base64data, extension, () => onChange?.(texture));
|
|
6159
|
+
}
|
|
6160
|
+
else if (texture instanceof Texture) {
|
|
6161
|
+
texture.updateURL(base64data, null, () => onChange?.(texture));
|
|
6162
|
+
}
|
|
6163
|
+
};
|
|
6164
|
+
}
|
|
6165
|
+
else {
|
|
6166
|
+
// Create new texture
|
|
6167
|
+
const { scene, cubeOnly, onChange } = props;
|
|
6168
|
+
const url = URL.createObjectURL(blob);
|
|
6169
|
+
const extension = file.name.split(".").pop()?.toLowerCase();
|
|
6170
|
+
// Revoke the object URL after texture loads to prevent memory leak
|
|
6171
|
+
const revokeUrl = () => URL.revokeObjectURL(url);
|
|
6172
|
+
const newTexture = cubeOnly
|
|
6173
|
+
? new CubeTexture(url, scene, [], false, undefined, revokeUrl, undefined, undefined, false, extension ? "." + extension : undefined)
|
|
6174
|
+
: new Texture(url, scene, false, false, undefined, revokeUrl);
|
|
6175
|
+
onChange(newTexture);
|
|
6176
|
+
}
|
|
6177
|
+
}, undefined, true);
|
|
6178
|
+
}, [props]);
|
|
6179
|
+
return jsx(UploadButton, { onUpload: handleUpload, accept: accept, title: "Upload Texture", label: label });
|
|
6180
|
+
};
|
|
6181
|
+
|
|
6182
|
+
const useStyles$5 = makeStyles({
|
|
6183
|
+
root: {
|
|
6184
|
+
// Stack the label above the field with a gap
|
|
6185
|
+
display: "grid",
|
|
6186
|
+
gridTemplateRows: "repeat(1fr)",
|
|
6187
|
+
justifyItems: "start",
|
|
6188
|
+
gap: "2px",
|
|
6189
|
+
maxWidth: "400px",
|
|
6190
|
+
},
|
|
6191
|
+
comboBox: {
|
|
6192
|
+
width: CustomTokens.inputWidth,
|
|
6193
|
+
minWidth: CustomTokens.inputWidth,
|
|
6194
|
+
boxSizing: "border-box",
|
|
6195
|
+
},
|
|
6196
|
+
input: {
|
|
6197
|
+
minWidth: 0, // Override Fluent's default minWidth on the input
|
|
6198
|
+
},
|
|
6199
|
+
});
|
|
6200
|
+
/**
|
|
6201
|
+
* Wrapper around a Fluent ComboBox that allows for filtering options
|
|
6202
|
+
* @param props
|
|
6203
|
+
* @returns
|
|
6204
|
+
*/
|
|
6205
|
+
const ComboBox = (props) => {
|
|
6206
|
+
ComboBox.displayName = "ComboBox";
|
|
6207
|
+
const comboId = useId();
|
|
6208
|
+
const styles = useStyles$5();
|
|
6209
|
+
const { size } = useContext(ToolContext);
|
|
6210
|
+
const [query, setQuery] = useState(props.value ?? "");
|
|
6211
|
+
// Sync query with props.value when it changes externally
|
|
6212
|
+
useEffect(() => {
|
|
6213
|
+
setQuery(props.value ?? "");
|
|
6214
|
+
}, [props.value]);
|
|
6215
|
+
const children = useComboboxFilter(query, props.options, {
|
|
6216
|
+
noOptionsMessage: "No items match your search.",
|
|
6217
|
+
});
|
|
6218
|
+
const onOptionSelect = (_e, data) => {
|
|
6219
|
+
setQuery(data.optionText ?? "");
|
|
6220
|
+
data.optionText && props.onChange(data.optionText);
|
|
6221
|
+
};
|
|
6222
|
+
return (jsxs("div", { className: styles.root, children: [jsx("label", { id: comboId, children: props.label }), jsx(Combobox, { size: size, root: { className: styles.comboBox }, input: { className: styles.input }, onOptionSelect: onOptionSelect, onBlur: () => props.onChange(query), "aria-labelledby": comboId, placeholder: "Search..", onChange: (ev) => setQuery(ev.target.value), value: query, children: children })] }));
|
|
6223
|
+
};
|
|
6224
|
+
|
|
6225
|
+
const useStyles$4 = makeStyles({
|
|
6226
|
+
container: {
|
|
6227
|
+
display: "flex",
|
|
6228
|
+
flexDirection: "row",
|
|
6229
|
+
alignItems: "center",
|
|
6230
|
+
gap: tokens.spacingHorizontalS,
|
|
6231
|
+
},
|
|
6232
|
+
});
|
|
6233
|
+
/**
|
|
6234
|
+
* A primitive component with a ComboBox for selecting from existing scene textures
|
|
6235
|
+
* and a button for uploading new texture files.
|
|
6236
|
+
* @param props ChooseTextureProps
|
|
6237
|
+
* @returns ChooseTexture component
|
|
6238
|
+
*/
|
|
6239
|
+
const ChooseTexture = (props) => {
|
|
6240
|
+
ChooseTexture.displayName = "ChooseTexture";
|
|
6241
|
+
const { scene, cubeOnly, value, onChange } = props;
|
|
6242
|
+
const classes = useStyles$4();
|
|
6243
|
+
// Get sorted texture names from scene
|
|
6244
|
+
const textureOptions = useMemo(() => {
|
|
6245
|
+
return scene.textures
|
|
6246
|
+
.filter((t) => t.name && (!cubeOnly || t.isCube))
|
|
6247
|
+
.map((t) => t.displayName || t.name)
|
|
6248
|
+
.sort((a, b) => a.localeCompare(b));
|
|
6249
|
+
}, [scene.textures, cubeOnly]);
|
|
6250
|
+
const handleTextureSelect = (textureName) => {
|
|
6251
|
+
const texture = scene.textures.find((t) => (t.displayName || t.name) === textureName);
|
|
6252
|
+
onChange(texture ?? null);
|
|
6253
|
+
};
|
|
6254
|
+
// Get current texture name for initial display
|
|
6255
|
+
const currentTextureName = value ? value.displayName || value.name : "";
|
|
6256
|
+
return (jsxs("div", { className: classes.container, children: [jsx(ComboBox, { label: "", options: textureOptions, value: currentTextureName, onChange: handleTextureSelect }), jsx(TextureUpload, { scene: scene, onChange: onChange, cubeOnly: cubeOnly })] }));
|
|
6257
|
+
};
|
|
6258
|
+
|
|
6259
|
+
/**
|
|
6260
|
+
* A property line with a ComboBox for selecting from existing scene textures
|
|
6261
|
+
* and a button for uploading new texture files.
|
|
6262
|
+
* @param props - ChooseTextureProps & PropertyLineProps
|
|
6263
|
+
* @returns property-line wrapped ChooseTexture component
|
|
6264
|
+
*/
|
|
6265
|
+
const ChooseTexturePropertyLine = (props) => {
|
|
6266
|
+
ChooseTexturePropertyLine.displayName = "ChooseTexturePropertyLine";
|
|
6267
|
+
return (jsx(PropertyLine, { ...props, children: jsx(ChooseTexture, { ...props }) }));
|
|
6268
|
+
};
|
|
6269
|
+
|
|
6270
|
+
/**
|
|
6271
|
+
* Helper to bind texture properties without needing defaultValue
|
|
6272
|
+
* @param props - The required properties
|
|
6273
|
+
* @returns ChooseTexturePropertyLine component
|
|
6274
|
+
*/
|
|
6275
|
+
function BoundTextureProperty(props) {
|
|
6276
|
+
const { label, target, propertyKey, scene, cubeOnly } = props;
|
|
6277
|
+
const value = useProperty(target, propertyKey);
|
|
6278
|
+
const notifyPropertyChanged = usePropertyChangedNotifier();
|
|
6279
|
+
return (jsx(ChooseTexturePropertyLine, { label: label, value: value, onChange: (texture) => {
|
|
6280
|
+
const oldValue = target[propertyKey];
|
|
6281
|
+
target[propertyKey] = texture;
|
|
6282
|
+
notifyPropertyChanged(target, propertyKey, oldValue, texture);
|
|
6283
|
+
}, scene: scene, cubeOnly: cubeOnly }));
|
|
6284
|
+
}
|
|
6285
|
+
|
|
6089
6286
|
/**
|
|
6090
6287
|
* Displays the lighting and color properties of a PBR material.
|
|
6091
6288
|
* @param props - The required properties
|
|
@@ -6095,6 +6292,16 @@ const PBRMaterialLightingAndColorProperties = (props) => {
|
|
|
6095
6292
|
const { material } = props;
|
|
6096
6293
|
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: Color3PropertyLine, label: "Albedo", target: material, propertyKey: "albedoColor", isLinearMode: true }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Base Weight", target: material, propertyKey: "baseWeight", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: Color3PropertyLine, label: "Reflectivity", target: material, propertyKey: "reflectivityColor", isLinearMode: true }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Micro-Surface", target: material, propertyKey: "microSurface", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: Color3PropertyLine, label: "Emissive", target: material, propertyKey: "emissiveColor", isLinearMode: true }), jsx(BoundProperty, { component: Color3PropertyLine, label: "Ambient", target: material, propertyKey: "ambientColor", isLinearMode: true }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Physical Light Falloff", target: material, propertyKey: "usePhysicalLightFalloff" })] }));
|
|
6097
6294
|
};
|
|
6295
|
+
/**
|
|
6296
|
+
* Displays the texture channel properties of a PBR material.
|
|
6297
|
+
* @param props - The required properties
|
|
6298
|
+
* @returns A JSX element representing the texture channels.
|
|
6299
|
+
*/
|
|
6300
|
+
const PBRMaterialTextureProperties = (props) => {
|
|
6301
|
+
const { material } = props;
|
|
6302
|
+
const scene = material.getScene();
|
|
6303
|
+
return (jsxs(Fragment, { children: [jsx(BoundTextureProperty, { label: "Albedo", target: material, propertyKey: "albedoTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Base Weight", target: material, propertyKey: "baseWeightTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Base Diffuse Roughness", target: material, propertyKey: "baseDiffuseRoughnessTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Metallic Roughness", target: material, propertyKey: "metallicTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Reflection", target: material, propertyKey: "reflectionTexture", scene: scene, cubeOnly: true }), jsx(BoundTextureProperty, { label: "Refraction", target: material, propertyKey: "refractionTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Reflectivity", target: material, propertyKey: "reflectivityTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Micro-surface", target: material, propertyKey: "microSurfaceTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Bump", target: material, propertyKey: "bumpTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Emissive", target: material, propertyKey: "emissiveTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Opacity", target: material, propertyKey: "opacityTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Ambient", target: material, propertyKey: "ambientTexture", scene: scene }), jsx(BoundTextureProperty, { label: "Lightmap", target: material, propertyKey: "lightmapTexture", scene: scene })] }));
|
|
6304
|
+
};
|
|
6098
6305
|
|
|
6099
6306
|
// TODO: ryamtrem / gehalper This function is temporal until there is a line control to handle texture links (similar to the old TextureLinkLineComponent)
|
|
6100
6307
|
const UpdateTexture = (file, material, textureSetter) => {
|
|
@@ -6370,6 +6577,10 @@ const MaterialPropertiesServiceDefinition = {
|
|
|
6370
6577
|
key: "PBR Material Properties",
|
|
6371
6578
|
predicate: (entity) => entity instanceof PBRMaterial,
|
|
6372
6579
|
content: [
|
|
6580
|
+
{
|
|
6581
|
+
section: "Textures",
|
|
6582
|
+
component: ({ context }) => jsx(PBRMaterialTextureProperties, { material: context }),
|
|
6583
|
+
},
|
|
6373
6584
|
{
|
|
6374
6585
|
section: "Lighting & Colors",
|
|
6375
6586
|
component: ({ context }) => jsx(PBRMaterialLightingAndColorProperties, { material: context }),
|
|
@@ -6589,7 +6800,7 @@ function SaveMetadata(entity, metadata) {
|
|
|
6589
6800
|
entity.metadata = metadata;
|
|
6590
6801
|
}
|
|
6591
6802
|
}
|
|
6592
|
-
const useStyles$
|
|
6803
|
+
const useStyles$3 = makeStyles({
|
|
6593
6804
|
mainDiv: {
|
|
6594
6805
|
display: "flex",
|
|
6595
6806
|
flexDirection: "column",
|
|
@@ -6609,7 +6820,7 @@ const useStyles$4 = makeStyles({
|
|
|
6609
6820
|
*/
|
|
6610
6821
|
const MetadataProperties = (props) => {
|
|
6611
6822
|
const { entity } = props;
|
|
6612
|
-
const classes = useStyles$
|
|
6823
|
+
const classes = useStyles$3();
|
|
6613
6824
|
const { size } = useContext(ToolContext);
|
|
6614
6825
|
const metadata = useProperty(entity, "metadata");
|
|
6615
6826
|
const stringifiedMetadata = useMemo(() => StringifyMetadata(metadata) ?? "", [metadata]);
|
|
@@ -7841,6 +8052,176 @@ const SpriteManagerCellProperties = (props) => {
|
|
|
7841
8052
|
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SpinButtonPropertyLine, label: "Cell Width", target: spriteManager, propertyKey: "cellWidth", min: 1, step: 1 }, "CellWidth"), jsx(BoundProperty, { component: SpinButtonPropertyLine, label: "Cell Height", target: spriteManager, propertyKey: "cellHeight", min: 1, step: 1 }, "CellHeight")] }));
|
|
7842
8053
|
};
|
|
7843
8054
|
|
|
8055
|
+
const useStyles$2 = makeStyles({
|
|
8056
|
+
root: {
|
|
8057
|
+
display: "flex",
|
|
8058
|
+
flexDirection: "column",
|
|
8059
|
+
},
|
|
8060
|
+
controls: {
|
|
8061
|
+
display: "flex",
|
|
8062
|
+
gap: tokens.spacingHorizontalXS,
|
|
8063
|
+
},
|
|
8064
|
+
controlButton: {
|
|
8065
|
+
minWidth: "auto",
|
|
8066
|
+
flex: "1 1 0", // Equal flex grow/shrink with 0 basis
|
|
8067
|
+
paddingVertical: tokens.spacingVerticalXS,
|
|
8068
|
+
paddingHorizontal: tokens.spacingHorizontalS,
|
|
8069
|
+
overflow: "hidden",
|
|
8070
|
+
textOverflow: "ellipsis",
|
|
8071
|
+
},
|
|
8072
|
+
preview: {
|
|
8073
|
+
border: `1px solid ${tokens.colorNeutralStroke1}`,
|
|
8074
|
+
display: "block",
|
|
8075
|
+
objectFit: "contain",
|
|
8076
|
+
},
|
|
8077
|
+
previewContainer: {
|
|
8078
|
+
display: "flex",
|
|
8079
|
+
justifyContent: "center",
|
|
8080
|
+
marginTop: tokens.spacingVerticalXS,
|
|
8081
|
+
marginBottom: tokens.spacingVerticalS,
|
|
8082
|
+
width: "100%",
|
|
8083
|
+
},
|
|
8084
|
+
});
|
|
8085
|
+
// This method of holding TextureChannels was brought over from inspectorv1 and can likely be refactored/simplified
|
|
8086
|
+
const TextureChannelStates = {
|
|
8087
|
+
R: { R: true, G: false, B: false, A: false },
|
|
8088
|
+
G: { R: false, G: true, B: false, A: false },
|
|
8089
|
+
B: { R: false, G: false, B: true, A: false },
|
|
8090
|
+
A: { R: false, G: false, B: false, A: true },
|
|
8091
|
+
ALL: { R: true, G: true, B: true, A: true },
|
|
8092
|
+
};
|
|
8093
|
+
const TexturePreview = (props) => {
|
|
8094
|
+
const { texture, disableToolbar = false, maxWidth = "100%", maxHeight = "384px", offsetX = 0, offsetY = 0, width, height } = props;
|
|
8095
|
+
const classes = useStyles$2();
|
|
8096
|
+
const canvasRef = useRef(null);
|
|
8097
|
+
const [channels, setChannels] = useState(TextureChannelStates.ALL);
|
|
8098
|
+
const [face, setFace] = useState(0);
|
|
8099
|
+
const [canvasStyle, setCanvasStyle] = useState();
|
|
8100
|
+
const internalTexture = useProperty(texture, "_texture");
|
|
8101
|
+
const { size } = useContext(ToolContext);
|
|
8102
|
+
const updatePreviewAsync = useCallback(async () => {
|
|
8103
|
+
const canvas = canvasRef.current;
|
|
8104
|
+
if (!canvas) {
|
|
8105
|
+
return;
|
|
8106
|
+
}
|
|
8107
|
+
try {
|
|
8108
|
+
await WhenTextureReadyAsync(texture); // Ensure texture is loaded before grabbing size
|
|
8109
|
+
const { width: textureWidth, height: textureHeight } = texture.getSize();
|
|
8110
|
+
// Set canvas dimensions to the sub-region size
|
|
8111
|
+
canvas.width = width ?? textureWidth;
|
|
8112
|
+
canvas.height = height ?? textureHeight;
|
|
8113
|
+
// Calculate the width that corresponds to maxHeight while maintaining aspect ratio
|
|
8114
|
+
const aspectRatio = canvas.width / canvas.height;
|
|
8115
|
+
// Use CSS min() to pick the smaller of maxWidth or the width that corresponds to maxHeight
|
|
8116
|
+
const imageWidth = `min(${maxWidth}, calc(${maxHeight} * ${aspectRatio}))`;
|
|
8117
|
+
setCanvasStyle({ width: imageWidth });
|
|
8118
|
+
// Get full texture data, then draw only the sub-region
|
|
8119
|
+
const data = await ApplyChannelsToTextureDataAsync(texture, textureWidth, textureHeight, face, channels);
|
|
8120
|
+
const context = canvas.getContext("2d");
|
|
8121
|
+
if (context) {
|
|
8122
|
+
const fullImageData = context.createImageData(textureWidth, textureHeight);
|
|
8123
|
+
fullImageData.data.set(data);
|
|
8124
|
+
// Use putImageData with dirty rect to draw only the sub-region
|
|
8125
|
+
context.putImageData(fullImageData, -offsetX, -offsetY, offsetX, offsetY, canvas.width, canvas.height);
|
|
8126
|
+
}
|
|
8127
|
+
}
|
|
8128
|
+
catch {
|
|
8129
|
+
// If we fail, leave the canvas empty
|
|
8130
|
+
}
|
|
8131
|
+
}, [texture, face, channels, offsetX, offsetY, width, height, internalTexture]);
|
|
8132
|
+
useEffect(() => {
|
|
8133
|
+
void updatePreviewAsync();
|
|
8134
|
+
}, [updatePreviewAsync]);
|
|
8135
|
+
return (jsxs("div", { className: classes.root, children: [disableToolbar ? null : texture.isCube ? (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Cube Faces", children: ["+X", "-X", "+Y", "-Y", "+Z", "-Z"].map((label, idx) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: face === idx ? "primary" : "subtle", onClick: () => setFace(idx), children: label }, label))) })) : (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Channels", children: ["R", "G", "B", "A", "ALL"].map((ch) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: channels === TextureChannelStates[ch] ? "primary" : "subtle", onClick: () => setChannels(TextureChannelStates[ch]), children: ch }, ch))) })), jsx("div", { className: classes.previewContainer, children: jsx("canvas", { ref: canvasRef, className: classes.preview, style: canvasStyle }) }), texture.isRenderTarget && (jsx(Button$1, { appearance: "outline", onClick: () => {
|
|
8136
|
+
void updatePreviewAsync();
|
|
8137
|
+
}, children: "Refresh" }))] }));
|
|
8138
|
+
};
|
|
8139
|
+
/**
|
|
8140
|
+
* Gets the data of the specified texture by rendering it to an intermediate RGBA texture and retrieving the bytes from it.
|
|
8141
|
+
* This is convienent to get 8-bit RGBA values for a texture in a GPU compressed format.
|
|
8142
|
+
* @param texture the source texture
|
|
8143
|
+
* @param width the width of the result, which does not have to match the source texture width
|
|
8144
|
+
* @param height the height of the result, which does not have to match the source texture height
|
|
8145
|
+
* @param face if the texture has multiple faces, the face index to use for the source
|
|
8146
|
+
* @param channels a filter for which of the RGBA channels to return in the result
|
|
8147
|
+
* @param lod if the texture has multiple LODs, the lod index to use for the source
|
|
8148
|
+
* @returns the 8-bit texture data
|
|
8149
|
+
*/
|
|
8150
|
+
async function ApplyChannelsToTextureDataAsync(texture, width, height, face, channels, lod = 0) {
|
|
8151
|
+
const data = await GetTextureDataAsync(texture, width, height, face, lod);
|
|
8152
|
+
if (!channels.R || !channels.G || !channels.B || !channels.A) {
|
|
8153
|
+
for (let i = 0; i < width * height * 4; i += 4) {
|
|
8154
|
+
// If alpha is the only channel, just display alpha across all channels
|
|
8155
|
+
if (channels.A && !channels.R && !channels.G && !channels.B) {
|
|
8156
|
+
data[i] = data[i + 3];
|
|
8157
|
+
data[i + 1] = data[i + 3];
|
|
8158
|
+
data[i + 2] = data[i + 3];
|
|
8159
|
+
data[i + 3] = 255;
|
|
8160
|
+
continue;
|
|
8161
|
+
}
|
|
8162
|
+
let r = data[i], g = data[i + 1], b = data[i + 2], a = data[i + 3];
|
|
8163
|
+
// If alpha is not visible, make everything 100% alpha
|
|
8164
|
+
if (!channels.A) {
|
|
8165
|
+
a = 255;
|
|
8166
|
+
}
|
|
8167
|
+
// If only one color channel is selected, map both colors to it. If two are selected, the unused one gets set to 0
|
|
8168
|
+
if (!channels.R) {
|
|
8169
|
+
if (channels.G && !channels.B) {
|
|
8170
|
+
r = g;
|
|
8171
|
+
}
|
|
8172
|
+
else if (channels.B && !channels.G) {
|
|
8173
|
+
r = b;
|
|
8174
|
+
}
|
|
8175
|
+
else {
|
|
8176
|
+
r = 0;
|
|
8177
|
+
}
|
|
8178
|
+
}
|
|
8179
|
+
if (!channels.G) {
|
|
8180
|
+
if (channels.R && !channels.B) {
|
|
8181
|
+
g = r;
|
|
8182
|
+
}
|
|
8183
|
+
else if (channels.B && !channels.R) {
|
|
8184
|
+
g = b;
|
|
8185
|
+
}
|
|
8186
|
+
else {
|
|
8187
|
+
g = 0;
|
|
8188
|
+
}
|
|
8189
|
+
}
|
|
8190
|
+
if (!channels.B) {
|
|
8191
|
+
if (channels.R && !channels.G) {
|
|
8192
|
+
b = r;
|
|
8193
|
+
}
|
|
8194
|
+
else if (channels.G && !channels.R) {
|
|
8195
|
+
b = g;
|
|
8196
|
+
}
|
|
8197
|
+
else {
|
|
8198
|
+
b = 0;
|
|
8199
|
+
}
|
|
8200
|
+
}
|
|
8201
|
+
data[i] = r;
|
|
8202
|
+
data[i + 1] = g;
|
|
8203
|
+
data[i + 2] = b;
|
|
8204
|
+
data[i + 3] = a;
|
|
8205
|
+
}
|
|
8206
|
+
}
|
|
8207
|
+
//To flip image on Y axis.
|
|
8208
|
+
if (texture.invertY || texture.isCube) {
|
|
8209
|
+
const numberOfChannelsByLine = width * 4;
|
|
8210
|
+
const halfHeight = height / 2;
|
|
8211
|
+
for (let i = 0; i < halfHeight; i++) {
|
|
8212
|
+
for (let j = 0; j < numberOfChannelsByLine; j++) {
|
|
8213
|
+
const currentCell = j + i * numberOfChannelsByLine;
|
|
8214
|
+
const targetLine = height - i - 1;
|
|
8215
|
+
const targetCell = j + targetLine * numberOfChannelsByLine;
|
|
8216
|
+
const temp = data[currentCell];
|
|
8217
|
+
data[currentCell] = data[targetCell];
|
|
8218
|
+
data[targetCell] = temp;
|
|
8219
|
+
}
|
|
8220
|
+
}
|
|
8221
|
+
}
|
|
8222
|
+
return data;
|
|
8223
|
+
}
|
|
8224
|
+
|
|
7844
8225
|
function useMaxCellCount(sprite) {
|
|
7845
8226
|
const manager = sprite.manager;
|
|
7846
8227
|
const texture = useProperty(manager, "texture");
|
|
@@ -7884,7 +8265,15 @@ const SpriteOtherProperties = (props) => {
|
|
|
7884
8265
|
const SpriteCellProperties = (props) => {
|
|
7885
8266
|
const { sprite } = props;
|
|
7886
8267
|
const maxCellCount = useMaxCellCount(sprite);
|
|
7887
|
-
|
|
8268
|
+
const manager = sprite.manager;
|
|
8269
|
+
const texture = manager.texture;
|
|
8270
|
+
const size = texture.getSize();
|
|
8271
|
+
const cellWidth = useProperty(manager, "cellWidth");
|
|
8272
|
+
const cellHeight = useProperty(manager, "cellHeight");
|
|
8273
|
+
const cellIndex = useProperty(sprite, "cellIndex");
|
|
8274
|
+
const offsetX = (cellIndex * cellWidth) % size.width;
|
|
8275
|
+
const offsetY = Math.floor((cellIndex * cellWidth) / size.width) * cellHeight;
|
|
8276
|
+
return (jsxs(Fragment, { children: [jsx(TexturePreview, { disableToolbar: true, texture: texture, maxHeight: "160px", offsetX: offsetX, offsetY: offsetY, width: cellWidth, height: cellHeight }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Cell Index", target: sprite, propertyKey: "cellIndex", min: 0, step: 1, max: maxCellCount }, "CellIndex"), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Invert U", target: sprite, propertyKey: "invertU" }, "InvertU"), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Invert V", target: sprite, propertyKey: "invertV" }, "InvertV")] }));
|
|
7888
8277
|
};
|
|
7889
8278
|
|
|
7890
8279
|
const SpritePropertiesServiceDefinition = {
|
|
@@ -8044,213 +8433,9 @@ function FindTextureType(type) {
|
|
|
8044
8433
|
return null;
|
|
8045
8434
|
}
|
|
8046
8435
|
|
|
8047
|
-
const useStyles$3 = makeStyles({
|
|
8048
|
-
root: {
|
|
8049
|
-
display: "flex",
|
|
8050
|
-
flexDirection: "column",
|
|
8051
|
-
},
|
|
8052
|
-
controls: {
|
|
8053
|
-
display: "flex",
|
|
8054
|
-
gap: tokens.spacingHorizontalXS,
|
|
8055
|
-
},
|
|
8056
|
-
controlButton: {
|
|
8057
|
-
minWidth: "auto",
|
|
8058
|
-
flex: "1 1 0", // Equal flex grow/shrink with 0 basis
|
|
8059
|
-
paddingVertical: tokens.spacingVerticalXS,
|
|
8060
|
-
paddingHorizontal: tokens.spacingHorizontalS,
|
|
8061
|
-
overflow: "hidden",
|
|
8062
|
-
textOverflow: "ellipsis",
|
|
8063
|
-
},
|
|
8064
|
-
preview: {
|
|
8065
|
-
border: `1px solid ${tokens.colorNeutralStroke1}`,
|
|
8066
|
-
marginTop: tokens.spacingVerticalXS,
|
|
8067
|
-
maxWidth: "100%",
|
|
8068
|
-
marginLeft: "auto",
|
|
8069
|
-
marginRight: "auto",
|
|
8070
|
-
marginBottom: tokens.spacingVerticalS,
|
|
8071
|
-
display: "block",
|
|
8072
|
-
},
|
|
8073
|
-
});
|
|
8074
|
-
// This method of holding TextureChannels was brought over from inspectorv1 and can likely be refactored/simplified
|
|
8075
|
-
const TextureChannelStates = {
|
|
8076
|
-
R: { R: true, G: false, B: false, A: false },
|
|
8077
|
-
G: { R: false, G: true, B: false, A: false },
|
|
8078
|
-
B: { R: false, G: false, B: true, A: false },
|
|
8079
|
-
A: { R: false, G: false, B: false, A: true },
|
|
8080
|
-
ALL: { R: true, G: true, B: true, A: true },
|
|
8081
|
-
};
|
|
8082
|
-
const TexturePreview = (props) => {
|
|
8083
|
-
const { texture, width, height } = props;
|
|
8084
|
-
const classes = useStyles$3();
|
|
8085
|
-
const canvasRef = useRef(null);
|
|
8086
|
-
const [channels, setChannels] = useState(TextureChannelStates.ALL);
|
|
8087
|
-
const [face, setFace] = useState(0);
|
|
8088
|
-
const internalTexture = useProperty(texture, "_texture");
|
|
8089
|
-
const { size } = useContext(ToolContext);
|
|
8090
|
-
const updatePreviewCanvasSize = useCallback((previewCanvas) => {
|
|
8091
|
-
// This logic was brought over from inspectorv1 and can likely be refactored/simplified
|
|
8092
|
-
const size = texture.getSize();
|
|
8093
|
-
const ratio = size.width / size.height;
|
|
8094
|
-
let w = width;
|
|
8095
|
-
let h = (w / ratio) | 1;
|
|
8096
|
-
const engine = texture.getScene()?.getEngine();
|
|
8097
|
-
if (engine && h > engine.getCaps().maxTextureSize) {
|
|
8098
|
-
w = size.width;
|
|
8099
|
-
h = size.height;
|
|
8100
|
-
}
|
|
8101
|
-
previewCanvas.width = w;
|
|
8102
|
-
previewCanvas.height = h;
|
|
8103
|
-
previewCanvas.style.width = w + "px";
|
|
8104
|
-
previewCanvas.style.height = h + "px";
|
|
8105
|
-
return {
|
|
8106
|
-
w: w,
|
|
8107
|
-
h: h,
|
|
8108
|
-
};
|
|
8109
|
-
}, [canvasRef.current, texture, width, height, internalTexture]);
|
|
8110
|
-
const updatePreviewAsync = useCallback(async () => {
|
|
8111
|
-
const previewCanvas = canvasRef.current;
|
|
8112
|
-
if (!previewCanvas) {
|
|
8113
|
-
return;
|
|
8114
|
-
}
|
|
8115
|
-
try {
|
|
8116
|
-
await WhenTextureReadyAsync(texture); // Ensure texture is loaded before grabbing size
|
|
8117
|
-
const { w, h } = updatePreviewCanvasSize(previewCanvas); // Grab desired size
|
|
8118
|
-
const data = await ApplyChannelsToTextureDataAsync(texture, w, h, face, channels); // get channel data to load onto canvas context
|
|
8119
|
-
const context = previewCanvas.getContext("2d");
|
|
8120
|
-
if (context) {
|
|
8121
|
-
const imageData = context.createImageData(w, h);
|
|
8122
|
-
imageData.data.set(data);
|
|
8123
|
-
context.putImageData(imageData, 0, 0);
|
|
8124
|
-
}
|
|
8125
|
-
}
|
|
8126
|
-
catch {
|
|
8127
|
-
updatePreviewCanvasSize(previewCanvas); // If we fail above, best effort sizing preview canvas
|
|
8128
|
-
}
|
|
8129
|
-
}, [[texture, width, height, face, channels, internalTexture]]);
|
|
8130
|
-
useEffect(() => {
|
|
8131
|
-
void updatePreviewAsync();
|
|
8132
|
-
}, [texture, width, height, face, channels, internalTexture]);
|
|
8133
|
-
return (jsxs("div", { className: classes.root, children: [texture.isCube ? (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Cube Faces", children: ["+X", "-X", "+Y", "-Y", "+Z", "-Z"].map((label, idx) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: face === idx ? "primary" : "subtle", onClick: () => setFace(idx), children: label }, label))) })) : (jsx(Toolbar$1, { className: classes.controls, size: size, "aria-label": "Channels", children: ["R", "G", "B", "A", "ALL"].map((ch) => (jsx(ToolbarButton, { className: classes.controlButton, appearance: channels === TextureChannelStates[ch] ? "primary" : "subtle", onClick: () => setChannels(TextureChannelStates[ch]), children: ch }, ch))) })), jsx("canvas", { ref: canvasRef, className: classes.preview }), texture.isRenderTarget && (jsx(Button$1, { appearance: "outline", onClick: () => {
|
|
8134
|
-
void updatePreviewAsync();
|
|
8135
|
-
}, children: "Refresh" }))] }));
|
|
8136
|
-
};
|
|
8137
|
-
/**
|
|
8138
|
-
* Gets the data of the specified texture by rendering it to an intermediate RGBA texture and retrieving the bytes from it.
|
|
8139
|
-
* This is convienent to get 8-bit RGBA values for a texture in a GPU compressed format.
|
|
8140
|
-
* @param texture the source texture
|
|
8141
|
-
* @param width the width of the result, which does not have to match the source texture width
|
|
8142
|
-
* @param height the height of the result, which does not have to match the source texture height
|
|
8143
|
-
* @param face if the texture has multiple faces, the face index to use for the source
|
|
8144
|
-
* @param channels a filter for which of the RGBA channels to return in the result
|
|
8145
|
-
* @param lod if the texture has multiple LODs, the lod index to use for the source
|
|
8146
|
-
* @returns the 8-bit texture data
|
|
8147
|
-
*/
|
|
8148
|
-
async function ApplyChannelsToTextureDataAsync(texture, width, height, face, channels, lod = 0) {
|
|
8149
|
-
const data = await GetTextureDataAsync(texture, width, height, face, lod);
|
|
8150
|
-
if (!channels.R || !channels.G || !channels.B || !channels.A) {
|
|
8151
|
-
for (let i = 0; i < width * height * 4; i += 4) {
|
|
8152
|
-
// If alpha is the only channel, just display alpha across all channels
|
|
8153
|
-
if (channels.A && !channels.R && !channels.G && !channels.B) {
|
|
8154
|
-
data[i] = data[i + 3];
|
|
8155
|
-
data[i + 1] = data[i + 3];
|
|
8156
|
-
data[i + 2] = data[i + 3];
|
|
8157
|
-
data[i + 3] = 255;
|
|
8158
|
-
continue;
|
|
8159
|
-
}
|
|
8160
|
-
let r = data[i], g = data[i + 1], b = data[i + 2], a = data[i + 3];
|
|
8161
|
-
// If alpha is not visible, make everything 100% alpha
|
|
8162
|
-
if (!channels.A) {
|
|
8163
|
-
a = 255;
|
|
8164
|
-
}
|
|
8165
|
-
// If only one color channel is selected, map both colors to it. If two are selected, the unused one gets set to 0
|
|
8166
|
-
if (!channels.R) {
|
|
8167
|
-
if (channels.G && !channels.B) {
|
|
8168
|
-
r = g;
|
|
8169
|
-
}
|
|
8170
|
-
else if (channels.B && !channels.G) {
|
|
8171
|
-
r = b;
|
|
8172
|
-
}
|
|
8173
|
-
else {
|
|
8174
|
-
r = 0;
|
|
8175
|
-
}
|
|
8176
|
-
}
|
|
8177
|
-
if (!channels.G) {
|
|
8178
|
-
if (channels.R && !channels.B) {
|
|
8179
|
-
g = r;
|
|
8180
|
-
}
|
|
8181
|
-
else if (channels.B && !channels.R) {
|
|
8182
|
-
g = b;
|
|
8183
|
-
}
|
|
8184
|
-
else {
|
|
8185
|
-
g = 0;
|
|
8186
|
-
}
|
|
8187
|
-
}
|
|
8188
|
-
if (!channels.B) {
|
|
8189
|
-
if (channels.R && !channels.G) {
|
|
8190
|
-
b = r;
|
|
8191
|
-
}
|
|
8192
|
-
else if (channels.G && !channels.R) {
|
|
8193
|
-
b = g;
|
|
8194
|
-
}
|
|
8195
|
-
else {
|
|
8196
|
-
b = 0;
|
|
8197
|
-
}
|
|
8198
|
-
}
|
|
8199
|
-
data[i] = r;
|
|
8200
|
-
data[i + 1] = g;
|
|
8201
|
-
data[i + 2] = b;
|
|
8202
|
-
data[i + 3] = a;
|
|
8203
|
-
}
|
|
8204
|
-
}
|
|
8205
|
-
//To flip image on Y axis.
|
|
8206
|
-
if (texture.invertY || texture.isCube) {
|
|
8207
|
-
const numberOfChannelsByLine = width * 4;
|
|
8208
|
-
const halfHeight = height / 2;
|
|
8209
|
-
for (let i = 0; i < halfHeight; i++) {
|
|
8210
|
-
for (let j = 0; j < numberOfChannelsByLine; j++) {
|
|
8211
|
-
const currentCell = j + i * numberOfChannelsByLine;
|
|
8212
|
-
const targetLine = height - i - 1;
|
|
8213
|
-
const targetCell = j + targetLine * numberOfChannelsByLine;
|
|
8214
|
-
const temp = data[currentCell];
|
|
8215
|
-
data[currentCell] = data[targetCell];
|
|
8216
|
-
data[targetCell] = temp;
|
|
8217
|
-
}
|
|
8218
|
-
}
|
|
8219
|
-
}
|
|
8220
|
-
return data;
|
|
8221
|
-
}
|
|
8222
|
-
|
|
8223
8436
|
const BaseTexturePreviewProperties = (props) => {
|
|
8224
8437
|
const { texture } = props;
|
|
8225
|
-
|
|
8226
|
-
const updateTexture = useCallback((file) => {
|
|
8227
|
-
ReadFile(file, (data) => {
|
|
8228
|
-
const blob = new Blob([data], { type: "octet/stream" });
|
|
8229
|
-
const reader = new FileReader();
|
|
8230
|
-
reader.readAsDataURL(blob);
|
|
8231
|
-
reader.onloadend = () => {
|
|
8232
|
-
const base64data = reader.result;
|
|
8233
|
-
if (texture instanceof CubeTexture) {
|
|
8234
|
-
let extension = undefined;
|
|
8235
|
-
if (file.name.toLowerCase().indexOf(".dds") > 0) {
|
|
8236
|
-
extension = ".dds";
|
|
8237
|
-
}
|
|
8238
|
-
else if (file.name.toLowerCase().indexOf(".env") > 0) {
|
|
8239
|
-
extension = ".env";
|
|
8240
|
-
}
|
|
8241
|
-
texture.updateURL(base64data, extension);
|
|
8242
|
-
}
|
|
8243
|
-
else if (texture instanceof Texture) {
|
|
8244
|
-
texture.updateURL(base64data);
|
|
8245
|
-
}
|
|
8246
|
-
};
|
|
8247
|
-
}, undefined, true);
|
|
8248
|
-
}, [texture]);
|
|
8249
|
-
return (jsxs(Fragment, { children: [jsx(TexturePreview, { texture: texture, width: 256, height: 256 }), isUpdatable && (jsx(FileUploadLine, { label: "Load Texture From File", accept: ".jpg, .png, .tga, .dds, .env, .exr", onClick: (files) => {
|
|
8250
|
-
if (files.length > 0) {
|
|
8251
|
-
updateTexture(files[0]);
|
|
8252
|
-
}
|
|
8253
|
-
} })), jsx(ButtonLine, { label: "Edit Texture (coming soon!)", onClick: () => { } })] }));
|
|
8438
|
+
return (jsxs(Fragment, { children: [jsx(TexturePreview, { texture: texture }), jsx(TextureUpload, { texture: texture }), jsx(ButtonLine, { label: "Edit Texture (coming soon!)", onClick: () => { } })] }));
|
|
8254
8439
|
};
|
|
8255
8440
|
const BaseTextureGeneralProperties = (props) => {
|
|
8256
8441
|
const { texture } = props;
|
|
@@ -10252,36 +10437,6 @@ function DetachDebugLayer() {
|
|
|
10252
10437
|
}
|
|
10253
10438
|
}
|
|
10254
10439
|
|
|
10255
|
-
const useStyles$2 = makeStyles({
|
|
10256
|
-
root: {
|
|
10257
|
-
// Stack the label above the field with a gap
|
|
10258
|
-
display: "grid",
|
|
10259
|
-
gridTemplateRows: "repeat(1fr)",
|
|
10260
|
-
justifyItems: "start",
|
|
10261
|
-
gap: "2px",
|
|
10262
|
-
maxWidth: "400px",
|
|
10263
|
-
},
|
|
10264
|
-
});
|
|
10265
|
-
/**
|
|
10266
|
-
* Wrapper around a Fluent ComboBox that allows for filtering options
|
|
10267
|
-
* @param props
|
|
10268
|
-
* @returns
|
|
10269
|
-
*/
|
|
10270
|
-
const ComboBox = (props) => {
|
|
10271
|
-
ComboBox.displayName = "ComboBox";
|
|
10272
|
-
const comboId = useId();
|
|
10273
|
-
const styles = useStyles$2();
|
|
10274
|
-
const [query, setQuery] = useState("");
|
|
10275
|
-
const children = useComboboxFilter(query, props.value, {
|
|
10276
|
-
noOptionsMessage: "No items match your search.",
|
|
10277
|
-
});
|
|
10278
|
-
const onOptionSelect = (_e, data) => {
|
|
10279
|
-
setQuery(data.optionText ?? "");
|
|
10280
|
-
data.optionText && props.onChange(data.optionText);
|
|
10281
|
-
};
|
|
10282
|
-
return (jsxs("div", { className: styles.root, children: [jsx("label", { id: comboId, children: props.label }), jsx(Combobox, { onOptionSelect: onOptionSelect, "aria-labelledby": comboId, placeholder: "Search..", onChange: (ev) => setQuery(ev.target.value), value: query, children: children })] }));
|
|
10283
|
-
};
|
|
10284
|
-
|
|
10285
10440
|
const useDraggableStyles = makeStyles({
|
|
10286
10441
|
draggable: {
|
|
10287
10442
|
display: "flex",
|
|
@@ -10353,7 +10508,7 @@ const PositionedPopover = (props) => {
|
|
|
10353
10508
|
props.hide();
|
|
10354
10509
|
}
|
|
10355
10510
|
};
|
|
10356
|
-
return (jsxs(Popover, { open: open, onOpenChange: handleOpenChange, positioning: {
|
|
10511
|
+
return (jsxs(Popover$1, { open: open, onOpenChange: handleOpenChange, positioning: {
|
|
10357
10512
|
position: "below", // Places the popover directly below the trigger element
|
|
10358
10513
|
autoSize: "height-always", //Automatically adjusts the popover height to fit within the viewport
|
|
10359
10514
|
fallbackPositions: ["above", "after", "before"], //If the primary position doesn't fit, automatically tries these positions in order
|
|
@@ -10511,5 +10666,5 @@ const TextAreaPropertyLine = (props) => {
|
|
|
10511
10666
|
// Attach Inspector v2 to Scene.debugLayer as a side effect for back compat.
|
|
10512
10667
|
AttachDebugLayer();
|
|
10513
10668
|
|
|
10514
|
-
export {
|
|
10515
|
-
//# sourceMappingURL=index-
|
|
10669
|
+
export { useAngleConverters as $, Accordion as A, ButtonLine as B, Collapse as C, DebugServiceIdentity as D, ExtensibleAccordion as E, FileUploadLine as F, useColor3Property as G, useColor4Property as H, Inspector as I, useQuaternionProperty as J, MakePropertyHook as K, Link as L, MakeLazyComponent as M, NumberDropdownPropertyLine as N, useInterceptObservable as O, Popover as P, useEventfulState as Q, useObservableCollection as R, SwitchPropertyLine as S, ToolsServiceIdentity as T, useOrderedObservableCollection as U, Vector3PropertyLine as V, usePollingObservable as W, useResource as X, useAsyncResource as Y, useCompactMode as Z, useSidePaneDockOverrides as _, SyncedSliderPropertyLine as a, MakeTeachingMoment as a0, MakeDialogTeachingMoment as a1, InterceptFunction as a2, GetPropertyDescriptor as a3, IsPropertyReadonly as a4, InterceptProperty as a5, ObservableCollection as a6, ConstructorFactory as a7, SelectionServiceIdentity as a8, SelectionServiceDefinition as a9, ToggleButton as aA, FactorGradientList as aB, Color3GradientList as aC, Color4GradientList as aD, Pane as aE, BooleanBadgePropertyLine as aF, Color3PropertyLine as aG, Color4PropertyLine as aH, HexPropertyLine as aI, NumberInputPropertyLine as aJ, LinkPropertyLine as aK, PropertyLine as aL, LineContainer as aM, PlaceholderPropertyLine as aN, StringifiedPropertyLine as aO, TextAreaPropertyLine as aP, TextPropertyLine as aQ, RotationVectorPropertyLine as aR, QuaternionPropertyLine as aS, Vector2PropertyLine as aT, Vector4PropertyLine as aU, SettingsContextIdentity as aa, ShowInspector as ab, Checkbox as ac, ColorPickerPopup as ad, InputHexField as ae, InputHsvField as af, ComboBox as ag, DraggableLine as ah, Dropdown as ai, NumberDropdown as aj, StringDropdown as ak, FactorGradientComponent as al, Color3GradientComponent as am, Color4GradientComponent as an, ColorStepGradientComponent as ao, InfoLabel as ap, List as aq, MessageBar as ar, PositionedPopover as as, SearchBar as at, SearchBox as au, SpinButton as av, Switch as aw, SyncedSliderInput as ax, Textarea as ay, TextInput as az, Button as b, TextInputPropertyLine as c, SpinButtonPropertyLine as d, CheckboxPropertyLine as e, ShellServiceIdentity as f, SceneContextIdentity as g, AccordionSection as h, useExtensionManager as i, MakePopoverTeachingMoment as j, TeachingMoment as k, SidePaneContainer as l, PropertiesServiceIdentity as m, SceneExplorerServiceIdentity as n, SettingsServiceIdentity as o, StatsServiceIdentity as p, ConvertOptions as q, AttachDebugLayer as r, DetachDebugLayer as s, StringDropdownPropertyLine as t, useObservableState as u, BoundProperty as v, LinkToEntityPropertyLine as w, BuiltInsExtensionFeed as x, useProperty as y, useVector3Property as z };
|
|
10670
|
+
//# sourceMappingURL=index-BgzFAhky.js.map
|