@babylonjs/inspector 8.45.4-preview → 8.45.5-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-C4KzF-3L.js → captureService-c_Nc-JkH.js} +3 -2
- package/lib/{captureService-C4KzF-3L.js.map → captureService-c_Nc-JkH.js.map} +1 -1
- package/lib/{exportService-D19rsLCQ.js → exportService-BvQmBhyv.js} +3 -2
- package/lib/{exportService-D19rsLCQ.js.map → exportService-BvQmBhyv.js.map} +1 -1
- package/lib/{extensionsListService-BPIryMmP.js → extensionsListService-DxjhVAwt.js} +3 -2
- package/lib/{extensionsListService-BPIryMmP.js.map → extensionsListService-DxjhVAwt.js.map} +1 -1
- package/lib/{importService-xoACJHME.js → importService-DxFxT2li.js} +3 -2
- package/lib/{importService-xoACJHME.js.map → importService-DxFxT2li.js.map} +1 -1
- package/lib/{index-upm3WBf8.js → index-C7ey_J-r.js} +415 -124
- package/lib/index-C7ey_J-r.js.map +1 -0
- package/lib/index.d.ts +89 -20
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/{quickCreateToolsService-ROfMXsQm.js → quickCreateToolsService-Cu0BSIWb.js} +2 -2
- package/lib/{quickCreateToolsService-ROfMXsQm.js.map → quickCreateToolsService-Cu0BSIWb.js.map} +1 -1
- package/package.json +2 -1
- package/lib/index-upm3WBf8.js.map +0 -1
|
@@ -4,7 +4,7 @@ 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
6
|
import { makeStyles, Link as Link$1, Caption1, Body1, ToggleButton as ToggleButton$1, Button as Button$1, Spinner, tokens, InfoLabel as InfoLabel$1, Body1Strong, Tooltip, Checkbox as Checkbox$1, mergeClasses, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, createLightTheme, createDarkTheme, FluentProvider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, Portal, RendererProvider, createDOMRenderer, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, ToolbarRadioButton, 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, Badge, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, useComboboxFilter, Combobox, Textarea as Textarea$1, ToolbarButton, Label, ToolbarDivider, Field } from '@fluentui/react-components';
|
|
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, DeleteRegular, PlayRegular, EditRegular, LinkDismissRegular, LinkEditRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, CopyRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, EyeRegular, StopRegular, ArrowDownloadRegular, CloudArrowUpRegular, CloudArrowDownRegular, StopFilled, PlayFilled, EyeOffRegular, LockOpenRegular, LockClosedRegular, ResizeRegular, ChevronUpRegular, ChevronDownRegular, ArrowResetRegular, CircleHalfFillRegular, EyedropperRegular, PaintBucketRegular, InkStrokeRegular, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, AppGenericRegular,
|
|
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, DeleteRegular, PlayRegular, EditRegular, LinkDismissRegular, LinkEditRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, CopyRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, EyeRegular, StopRegular, ArrowDownloadRegular, CloudArrowUpRegular, CloudArrowDownRegular, StopFilled, PlayFilled, EyeOffRegular, LockOpenRegular, LockClosedRegular, ResizeRegular, ChevronUpRegular, ChevronDownRegular, ArrowResetRegular, CircleHalfFillRegular, EyedropperRegular, PaintBucketRegular, InkStrokeRegular, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, AppGenericRegular, RectangleLandscapeRegular, BorderOutsideRegular, BorderNoneRegular, MyLocationRegular, CameraRegular, LightbulbRegular, 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';
|
|
10
10
|
import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
|
|
@@ -90,6 +90,7 @@ import { MeshParticleEmitter } from '@babylonjs/core/Particles/EmitterTypes/mesh
|
|
|
90
90
|
import { PointParticleEmitter } from '@babylonjs/core/Particles/EmitterTypes/pointParticleEmitter.js';
|
|
91
91
|
import { SphereParticleEmitter } from '@babylonjs/core/Particles/EmitterTypes/sphereParticleEmitter.js';
|
|
92
92
|
import { ConvertToNodeParticleSystemSetAsync } from '@babylonjs/core/Particles/Node/nodeParticleSystemSet.helper.js';
|
|
93
|
+
import { GPUParticleSystem } from '@babylonjs/core/Particles/gpuParticleSystem.js';
|
|
93
94
|
import { ParticleHelper } from '@babylonjs/core/Particles/particleHelper.js';
|
|
94
95
|
import { FactorGradient, Color3Gradient, ColorGradient } from '@babylonjs/core/Misc/gradients.js';
|
|
95
96
|
import { GradientBlockColorStep } from '@babylonjs/core/Materials/Node/Blocks/gradientBlock.js';
|
|
@@ -746,7 +747,6 @@ const CustomTokens = {
|
|
|
746
747
|
dividerGapSmall: tokens.borderRadiusMedium, // 4px",
|
|
747
748
|
labelMinWidth: "50px",
|
|
748
749
|
sliderMinWidth: "30px",
|
|
749
|
-
sliderMaxWidth: "80px",
|
|
750
750
|
rightAlignOffset: `-${tokens.borderRadiusXLarge}`, // -8px
|
|
751
751
|
};
|
|
752
752
|
const UniformWidthStyling = { width: CustomTokens.inputWidth, boxSizing: "border-box" };
|
|
@@ -3888,7 +3888,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3888
3888
|
keywords: ["export", "gltf", "glb", "babylon", "exporter", "tools"],
|
|
3889
3889
|
...BabylonWebResources,
|
|
3890
3890
|
author: { name: "Alex Chuber", forumUserName: "alexchuber" },
|
|
3891
|
-
getExtensionModuleAsync: async () => await import('./exportService-
|
|
3891
|
+
getExtensionModuleAsync: async () => await import('./exportService-BvQmBhyv.js'),
|
|
3892
3892
|
},
|
|
3893
3893
|
{
|
|
3894
3894
|
name: "Capture Tools",
|
|
@@ -3896,7 +3896,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3896
3896
|
keywords: ["capture", "screenshot", "gif", "video", "tools"],
|
|
3897
3897
|
...BabylonWebResources,
|
|
3898
3898
|
author: { name: "Alex Chuber", forumUserName: "alexchuber" },
|
|
3899
|
-
getExtensionModuleAsync: async () => await import('./captureService-
|
|
3899
|
+
getExtensionModuleAsync: async () => await import('./captureService-c_Nc-JkH.js'),
|
|
3900
3900
|
},
|
|
3901
3901
|
{
|
|
3902
3902
|
name: "Import Tools",
|
|
@@ -3904,7 +3904,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3904
3904
|
keywords: ["import", "tools"],
|
|
3905
3905
|
...BabylonWebResources,
|
|
3906
3906
|
author: { name: "Alex Chuber", forumUserName: "alexchuber" },
|
|
3907
|
-
getExtensionModuleAsync: async () => await import('./importService-
|
|
3907
|
+
getExtensionModuleAsync: async () => await import('./importService-DxFxT2li.js'),
|
|
3908
3908
|
},
|
|
3909
3909
|
{
|
|
3910
3910
|
name: "Quick Creation Tools (Preview)",
|
|
@@ -3912,7 +3912,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
3912
3912
|
keywords: ["creation", "tools"],
|
|
3913
3913
|
...BabylonWebResources,
|
|
3914
3914
|
author: { name: "Babylon.js", forumUserName: "" },
|
|
3915
|
-
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-
|
|
3915
|
+
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-Cu0BSIWb.js'),
|
|
3916
3916
|
},
|
|
3917
3917
|
]);
|
|
3918
3918
|
|
|
@@ -3975,8 +3975,13 @@ const useSyncedSliderStyles = makeStyles({
|
|
|
3975
3975
|
alignItems: "center",
|
|
3976
3976
|
},
|
|
3977
3977
|
slider: {
|
|
3978
|
-
|
|
3979
|
-
|
|
3978
|
+
flex: "1 1 auto", // Grow to fill available space
|
|
3979
|
+
minWidth: CustomTokens.sliderMinWidth,
|
|
3980
|
+
maxWidth: "none", // Allow slider to grow
|
|
3981
|
+
},
|
|
3982
|
+
compactSpinButton: {
|
|
3983
|
+
width: "70px",
|
|
3984
|
+
flex: "0 0 auto", // Don't grow, stay fixed
|
|
3980
3985
|
},
|
|
3981
3986
|
});
|
|
3982
3987
|
/**
|
|
@@ -4027,7 +4032,7 @@ const SyncedSliderInput = (props) => {
|
|
|
4027
4032
|
setValue(value);
|
|
4028
4033
|
props.onChange(value); // Input always updates immediately
|
|
4029
4034
|
};
|
|
4030
|
-
return (jsxs("div", { className: classes.container, children: [infoLabel && jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [props.min !== undefined && props.max !== undefined && (jsx(Slider, { ...passthroughProps, className: classes.slider, size: size, min: min / step, max: max / step, step: undefined, value: value / step, onChange: handleSliderChange, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), jsx(SpinButton, { ...passthroughProps, value: value, onChange: handleInputChange, step: props.step })] })] }));
|
|
4035
|
+
return (jsxs("div", { className: classes.container, children: [infoLabel && jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [props.min !== undefined && props.max !== undefined && (jsx(Slider, { ...passthroughProps, className: classes.slider, size: size, min: min / step, max: max / step, step: undefined, value: value / step, onChange: handleSliderChange, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), jsx(SpinButton, { ...passthroughProps, className: props.compact ? classes.compactSpinButton : undefined, value: value, onChange: handleInputChange, step: props.step })] })] }));
|
|
4031
4036
|
};
|
|
4032
4037
|
|
|
4033
4038
|
/**
|
|
@@ -5044,7 +5049,7 @@ function MakeModularTool(options) {
|
|
|
5044
5049
|
});
|
|
5045
5050
|
// Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
|
|
5046
5051
|
if (extensionFeeds.length > 0) {
|
|
5047
|
-
const { ExtensionListServiceDefinition } = await import('./extensionsListService-
|
|
5052
|
+
const { ExtensionListServiceDefinition } = await import('./extensionsListService-DxjhVAwt.js');
|
|
5048
5053
|
await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);
|
|
5049
5054
|
}
|
|
5050
5055
|
// Register the theme selector service (for selecting the theme) if theming is configured.
|
|
@@ -6125,7 +6130,7 @@ const ShadowGeneratorSetupProperties = ({ context: shadowLight }) => {
|
|
|
6125
6130
|
const useKernelBlur = useProperty(shadowGenerator, "useKernelBlur");
|
|
6126
6131
|
const blurModeOptions = isCascaded ? CSMBlurModeOptions : BlurModeOptions;
|
|
6127
6132
|
const near = camera?.minZ ?? 0;
|
|
6128
|
-
const far = camera?.maxZ ??
|
|
6133
|
+
const far = camera?.maxZ ?? 10000;
|
|
6129
6134
|
const isPCFOrPCSS = filter === ShadowGenerator.FILTER_PCF || filter === ShadowGenerator.FILTER_PCSS;
|
|
6130
6135
|
const isPCSS = filter === ShadowGenerator.FILTER_PCSS;
|
|
6131
6136
|
const isBlurExponential = filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP;
|
|
@@ -7837,22 +7842,19 @@ const useGradientStyles = makeStyles({
|
|
|
7837
7842
|
gap: tokens.spacingHorizontalS,
|
|
7838
7843
|
width: "100%",
|
|
7839
7844
|
},
|
|
7840
|
-
// Wrapper for
|
|
7845
|
+
// Wrapper for factor spin buttons - fixed size
|
|
7841
7846
|
valueWrapper: {
|
|
7842
|
-
flex: "0
|
|
7843
|
-
alignContent: "center",
|
|
7844
|
-
minWidth: "80px", // Minimum width to keep usable
|
|
7845
|
-
maxWidth: "100px", // Maximum width to prevent them from getting too wide
|
|
7847
|
+
flex: "0 0 auto", // Don't grow, natural size
|
|
7846
7848
|
},
|
|
7847
|
-
// Wrapper for color pickers -
|
|
7849
|
+
// Wrapper for color pickers - fixed size since they're just swatches
|
|
7848
7850
|
colorWrapper: {
|
|
7851
|
+
flex: "0 0 auto",
|
|
7849
7852
|
alignContent: "center",
|
|
7850
|
-
// No flex properties - just take natural size
|
|
7851
7853
|
},
|
|
7852
|
-
// Wrapper for the step slider to
|
|
7854
|
+
// Wrapper for the step slider - grows to fill remaining space
|
|
7853
7855
|
stepSliderWrapper: {
|
|
7854
|
-
flex: "1 0
|
|
7855
|
-
minWidth:
|
|
7856
|
+
flex: "1 1 0", // Grow to fill available space
|
|
7857
|
+
minWidth: 0,
|
|
7856
7858
|
},
|
|
7857
7859
|
});
|
|
7858
7860
|
/**
|
|
@@ -7871,7 +7873,10 @@ const Gradient = (props) => {
|
|
|
7871
7873
|
setGradient(newGradient);
|
|
7872
7874
|
props.onChange(newGradient);
|
|
7873
7875
|
};
|
|
7874
|
-
|
|
7876
|
+
// Only use compact mode when there are numeric values (spinbuttons) taking up space
|
|
7877
|
+
const hasNumericValues = !(gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4) ||
|
|
7878
|
+
(gradient.value2 !== undefined && !(gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4));
|
|
7879
|
+
return (jsxs("div", { id: "gradientContainer", className: classes.container, children: [jsx("div", { className: gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4 ? classes.colorWrapper : classes.valueWrapper, children: gradient.value1 instanceof Color3 || gradient.value1 instanceof Color4 ? (jsx(ColorPickerPopup, { value: gradient.value1, onChange: (color) => gradientChange({ ...gradient, value1: color }) })) : (jsx(SyncedSliderInput, { step: 0.01, value: gradient.value1, onChange: (val) => gradientChange({ ...gradient, value1: val }), compact: true })) }), gradient.value2 !== undefined && (jsx("div", { className: gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4 ? classes.colorWrapper : classes.valueWrapper, children: gradient.value2 instanceof Color3 || gradient.value2 instanceof Color4 ? (jsx(ColorPickerPopup, { value: gradient.value2, onChange: (color) => gradientChange({ ...gradient, value2: color }) })) : (jsx(SyncedSliderInput, { step: 0.01, value: gradient.value2, onChange: (val) => gradientChange({ ...gradient, value2: val }), compact: true })) })), jsx("div", { className: classes.stepSliderWrapper, children: jsx(SyncedSliderInput, { notifyOnlyOnRelease: true, min: 0, max: 1, step: 0.01, value: gradient.step, onChange: (val) => gradientChange({ ...gradient, step: val }), compact: hasNumericValues }) })] }));
|
|
7875
7880
|
};
|
|
7876
7881
|
const FactorGradientCast = Gradient;
|
|
7877
7882
|
const Color3GradientCast = Gradient;
|
|
@@ -7977,6 +7982,112 @@ const Color4GradientList = (props) => {
|
|
|
7977
7982
|
} }, "Color4"));
|
|
7978
7983
|
};
|
|
7979
7984
|
|
|
7985
|
+
/**
|
|
7986
|
+
* Shared utilities for snippet server operations (save/load).
|
|
7987
|
+
*/
|
|
7988
|
+
/**
|
|
7989
|
+
* Persist a snippet ID to local storage for quick reuse.
|
|
7990
|
+
* @param storageKey The local storage key to use.
|
|
7991
|
+
* @param snippetId The snippet ID to persist.
|
|
7992
|
+
* @param maxItems Maximum number of items to store (default 50).
|
|
7993
|
+
*/
|
|
7994
|
+
function PersistSnippetId(storageKey, snippetId, maxItems = 50) {
|
|
7995
|
+
try {
|
|
7996
|
+
const existing = JSON.parse(localStorage.getItem(storageKey) || "[]");
|
|
7997
|
+
const list = Array.isArray(existing) ? existing : [];
|
|
7998
|
+
if (!list.includes(snippetId)) {
|
|
7999
|
+
list.unshift(snippetId);
|
|
8000
|
+
}
|
|
8001
|
+
localStorage.setItem(storageKey, JSON.stringify(list.slice(0, maxItems)));
|
|
8002
|
+
}
|
|
8003
|
+
catch {
|
|
8004
|
+
// Ignore storage failures.
|
|
8005
|
+
}
|
|
8006
|
+
}
|
|
8007
|
+
/**
|
|
8008
|
+
* Save content to the snippet server.
|
|
8009
|
+
* @param config Configuration for the save operation.
|
|
8010
|
+
* @returns Promise resolving to the save result.
|
|
8011
|
+
*/
|
|
8012
|
+
async function SaveToSnippetServer(config) {
|
|
8013
|
+
const { snippetUrl, currentSnippetId, content, payloadKey, storageKey, entityName } = config;
|
|
8014
|
+
const dataToSend = {
|
|
8015
|
+
payload: JSON.stringify({
|
|
8016
|
+
[payloadKey]: content,
|
|
8017
|
+
}),
|
|
8018
|
+
name: "",
|
|
8019
|
+
description: "",
|
|
8020
|
+
tags: "",
|
|
8021
|
+
};
|
|
8022
|
+
const headers = new Headers();
|
|
8023
|
+
headers.append("Content-Type", "application/json");
|
|
8024
|
+
let response;
|
|
8025
|
+
try {
|
|
8026
|
+
response = await fetch(snippetUrl + (currentSnippetId ? "/" + currentSnippetId : ""), {
|
|
8027
|
+
method: "POST",
|
|
8028
|
+
headers,
|
|
8029
|
+
body: JSON.stringify(dataToSend),
|
|
8030
|
+
});
|
|
8031
|
+
}
|
|
8032
|
+
catch (e) {
|
|
8033
|
+
const errorMsg = `Unable to save your ${entityName ?? "content"}: ${e}`;
|
|
8034
|
+
alert(errorMsg);
|
|
8035
|
+
throw new Error(errorMsg);
|
|
8036
|
+
}
|
|
8037
|
+
if (!response.ok) {
|
|
8038
|
+
const errorMsg = `Unable to save your ${entityName ?? "content"}`;
|
|
8039
|
+
alert(errorMsg);
|
|
8040
|
+
throw new Error(errorMsg);
|
|
8041
|
+
}
|
|
8042
|
+
const snippet = await response.json();
|
|
8043
|
+
const oldSnippetId = currentSnippetId || "_BLANK";
|
|
8044
|
+
let newSnippetId = snippet.id;
|
|
8045
|
+
if (snippet.version && snippet.version !== "0") {
|
|
8046
|
+
newSnippetId += "#" + snippet.version;
|
|
8047
|
+
}
|
|
8048
|
+
// Copy to clipboard when available.
|
|
8049
|
+
if (navigator.clipboard) {
|
|
8050
|
+
await navigator.clipboard.writeText(newSnippetId);
|
|
8051
|
+
}
|
|
8052
|
+
// Persist to local storage if configured.
|
|
8053
|
+
if (storageKey) {
|
|
8054
|
+
PersistSnippetId(storageKey, newSnippetId);
|
|
8055
|
+
}
|
|
8056
|
+
// Show success alert
|
|
8057
|
+
alert(`${entityName ?? "Content"} saved with ID: ${newSnippetId} (the id was also saved to your clipboard)`);
|
|
8058
|
+
return {
|
|
8059
|
+
snippetId: newSnippetId,
|
|
8060
|
+
oldSnippetId,
|
|
8061
|
+
};
|
|
8062
|
+
}
|
|
8063
|
+
/**
|
|
8064
|
+
* Prompt the user for a snippet ID.
|
|
8065
|
+
* @param message The prompt message.
|
|
8066
|
+
* @returns The trimmed snippet ID, or null if cancelled/empty.
|
|
8067
|
+
*/
|
|
8068
|
+
function PromptForSnippetId(message = "Please enter the snippet ID to use") {
|
|
8069
|
+
const requestedSnippetId = window.prompt(message);
|
|
8070
|
+
const trimmed = requestedSnippetId?.trim();
|
|
8071
|
+
return trimmed || null;
|
|
8072
|
+
}
|
|
8073
|
+
/**
|
|
8074
|
+
* Notify the playground about a snippet ID change (for code replacement).
|
|
8075
|
+
* NOTE this is an anti-pattern, instead playground should hook in and observe changes / update its own code
|
|
8076
|
+
* This is a legacy approach and should not be copied elsewhere
|
|
8077
|
+
* @param oldSnippetId The previous snippet ID.
|
|
8078
|
+
* @param newSnippetId The new snippet ID.
|
|
8079
|
+
* @param parseMethodName The name of the parse method (e.g., "SpriteManager.ParseFromSnippetAsync").
|
|
8080
|
+
*/
|
|
8081
|
+
function NotifyPlaygroundOfSnippetChange(oldSnippetId, newSnippetId, parseMethodName) {
|
|
8082
|
+
const windowAsAny = window;
|
|
8083
|
+
if (windowAsAny.Playground && oldSnippetId) {
|
|
8084
|
+
windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
|
|
8085
|
+
regex: new RegExp(`${parseMethodName}\\("${oldSnippetId}`, "g"),
|
|
8086
|
+
replace: `${parseMethodName}("${newSnippetId}`,
|
|
8087
|
+
});
|
|
8088
|
+
}
|
|
8089
|
+
}
|
|
8090
|
+
|
|
7980
8091
|
const useAttractorStyles = makeStyles({
|
|
7981
8092
|
container: {
|
|
7982
8093
|
// top-level div used for lineContainer, in UI overhaul update to just use linecontainer
|
|
@@ -8091,7 +8202,7 @@ const AttractorList = (props) => {
|
|
|
8091
8202
|
} })] }));
|
|
8092
8203
|
};
|
|
8093
8204
|
|
|
8094
|
-
const SnippetDashboardStorageKey = "Babylon/InspectorV2/SnippetDashboard/ParticleSystems";
|
|
8205
|
+
const SnippetDashboardStorageKey$1 = "Babylon/InspectorV2/SnippetDashboard/ParticleSystems";
|
|
8095
8206
|
function TryParseJsonString(value) {
|
|
8096
8207
|
if (!value) {
|
|
8097
8208
|
return undefined;
|
|
@@ -8118,27 +8229,13 @@ function NormalizeParticleSystemSerialization(rawData) {
|
|
|
8118
8229
|
const particleSystem = TryParseJsonString(jsonPayload?.particleSystem);
|
|
8119
8230
|
return particleSystem ?? rawData;
|
|
8120
8231
|
}
|
|
8121
|
-
function PersistSnippetId(snippetId) {
|
|
8122
|
-
// Persist snippet IDs locally for quick reuse.
|
|
8123
|
-
try {
|
|
8124
|
-
const existing = JSON.parse(localStorage.getItem(SnippetDashboardStorageKey) || "[]");
|
|
8125
|
-
const list = Array.isArray(existing) ? existing : [];
|
|
8126
|
-
if (!list.includes(snippetId)) {
|
|
8127
|
-
list.unshift(snippetId);
|
|
8128
|
-
}
|
|
8129
|
-
localStorage.setItem(SnippetDashboardStorageKey, JSON.stringify(list.slice(0, 50)));
|
|
8130
|
-
}
|
|
8131
|
-
catch {
|
|
8132
|
-
// Ignore storage failures.
|
|
8133
|
-
}
|
|
8134
|
-
}
|
|
8135
8232
|
/**
|
|
8136
8233
|
* Display general (high-level) information about a particle system.
|
|
8137
8234
|
* @param props Component props.
|
|
8138
8235
|
* @returns Render property lines.
|
|
8139
8236
|
*/
|
|
8140
8237
|
const ParticleSystemGeneralProperties = (props) => {
|
|
8141
|
-
const { particleSystem: system } = props;
|
|
8238
|
+
const { particleSystem: system, selectionService } = props;
|
|
8142
8239
|
const scene = system.getScene();
|
|
8143
8240
|
const isBillboardBased = useProperty(system, "isBillboardBased");
|
|
8144
8241
|
const capacity = useObservableState(() => system.getCapacity());
|
|
@@ -8170,87 +8267,50 @@ const ParticleSystemGeneralProperties = (props) => {
|
|
|
8170
8267
|
alert("Failed to load particle system: " + e);
|
|
8171
8268
|
}
|
|
8172
8269
|
}, [scene, system]);
|
|
8173
|
-
const loadFromSnippetServer = useCallback(() => {
|
|
8270
|
+
const loadFromSnippetServer = useCallback(async () => {
|
|
8174
8271
|
if (!scene) {
|
|
8175
8272
|
alert("No scene available.");
|
|
8176
8273
|
return;
|
|
8177
8274
|
}
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
const trimmed = requestedSnippetId?.trim();
|
|
8181
|
-
if (!trimmed) {
|
|
8275
|
+
const snippetId = PromptForSnippetId();
|
|
8276
|
+
if (!snippetId) {
|
|
8182
8277
|
return;
|
|
8183
8278
|
}
|
|
8184
|
-
const
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
applyParticleSystemJsonToSystem(responseObject);
|
|
8200
|
-
system.snippetId = trimmed;
|
|
8201
|
-
}
|
|
8202
|
-
catch (e) {
|
|
8203
|
-
alert("Unable to load your particle system: " + e);
|
|
8204
|
-
}
|
|
8205
|
-
};
|
|
8206
|
-
request.open("GET", ParticleHelper.SnippetUrl + "/" + trimmed.replace(/#/g, "/"), true);
|
|
8207
|
-
request.send();
|
|
8208
|
-
}, [applyParticleSystemJsonToSystem, scene, system]);
|
|
8279
|
+
const isGpu = system instanceof GPUParticleSystem;
|
|
8280
|
+
const oldSnippetId = system.snippetId;
|
|
8281
|
+
// Dispose the old system and clear selection (v1 behavior)
|
|
8282
|
+
system.dispose();
|
|
8283
|
+
selectionService.selectedEntity = null;
|
|
8284
|
+
try {
|
|
8285
|
+
const newSystem = await ParticleHelper.ParseFromSnippetAsync(snippetId, scene, isGpu);
|
|
8286
|
+
selectionService.selectedEntity = newSystem;
|
|
8287
|
+
// Notify the playground to update its code with the new snippet ID.
|
|
8288
|
+
NotifyPlaygroundOfSnippetChange(oldSnippetId, snippetId, "ParticleHelper.ParseFromSnippetAsync");
|
|
8289
|
+
}
|
|
8290
|
+
catch (err) {
|
|
8291
|
+
alert("Unable to load your particle system: " + err);
|
|
8292
|
+
}
|
|
8293
|
+
}, [scene, selectionService, system]);
|
|
8209
8294
|
const saveToSnippetServer = useCallback(async () => {
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
// Copy to clipboard when available.
|
|
8230
|
-
if (navigator.clipboard) {
|
|
8231
|
-
void navigator.clipboard.writeText(system.snippetId);
|
|
8232
|
-
}
|
|
8233
|
-
PersistSnippetId(system.snippetId);
|
|
8234
|
-
deferred.resolve();
|
|
8235
|
-
alert("Particle system saved with ID: " + system.snippetId + " (the id was also saved to your clipboard)");
|
|
8236
|
-
}
|
|
8237
|
-
catch (e) {
|
|
8238
|
-
deferred.reject(e);
|
|
8239
|
-
alert("Unable to save your particle system: " + e);
|
|
8240
|
-
}
|
|
8241
|
-
};
|
|
8242
|
-
xmlHttp.open("POST", ParticleHelper.SnippetUrl + (system.snippetId ? "/" + system.snippetId : ""), true);
|
|
8243
|
-
xmlHttp.setRequestHeader("Content-Type", "application/json");
|
|
8244
|
-
const dataToSend = {
|
|
8245
|
-
payload: JSON.stringify({
|
|
8246
|
-
particleSystem: content,
|
|
8247
|
-
}),
|
|
8248
|
-
name: "",
|
|
8249
|
-
description: "",
|
|
8250
|
-
tags: "",
|
|
8251
|
-
};
|
|
8252
|
-
xmlHttp.send(JSON.stringify(dataToSend));
|
|
8253
|
-
await deferred.promise;
|
|
8295
|
+
try {
|
|
8296
|
+
const content = JSON.stringify(system.serialize(true));
|
|
8297
|
+
const currentSnippetId = system.snippetId;
|
|
8298
|
+
const result = await SaveToSnippetServer({
|
|
8299
|
+
snippetUrl: ParticleHelper.SnippetUrl,
|
|
8300
|
+
currentSnippetId,
|
|
8301
|
+
content,
|
|
8302
|
+
payloadKey: "particleSystem",
|
|
8303
|
+
storageKey: SnippetDashboardStorageKey$1,
|
|
8304
|
+
entityName: "particle system",
|
|
8305
|
+
});
|
|
8306
|
+
// eslint-disable-next-line require-atomic-updates
|
|
8307
|
+
system.snippetId = result.snippetId;
|
|
8308
|
+
PersistSnippetId(SnippetDashboardStorageKey$1, result.snippetId);
|
|
8309
|
+
NotifyPlaygroundOfSnippetChange(result.oldSnippetId, result.snippetId, "ParticleSystem.ParseFromSnippetAsync");
|
|
8310
|
+
}
|
|
8311
|
+
catch {
|
|
8312
|
+
// Alert already shown by SaveToSnippetServer
|
|
8313
|
+
}
|
|
8254
8314
|
}, [system]);
|
|
8255
8315
|
return (jsxs(Fragment, { children: [jsx(StringifiedPropertyLine, { label: "Capacity", description: "Maximum number of particles in the system.", value: capacity }), jsx(StringifiedPropertyLine, { label: "Active Particles", description: "Current number of active particles.", value: activeCount }), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Blend Mode", target: system, propertyKey: "blendMode", options: BlendModeOptions }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "World Offset", target: system, propertyKey: "worldOffset" }), !system.isNodeGenerated && jsx(BoundProperty, { component: Vector3PropertyLine, label: "Gravity", target: system, propertyKey: "gravity" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Is Billboard", target: system, propertyKey: "isBillboardBased" }), isBillboardBased && (jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Billboard Mode", target: system, propertyKey: "billboardMode", options: ParticleBillboardModeOptions })), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Is Local", target: system, propertyKey: "isLocal" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Force Depth Write", target: system, propertyKey: "forceDepthWrite" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Update Speed", target: system, propertyKey: "updateSpeed", min: 0, step: 0.01 }), jsx(ButtonLine, { label: system.isNodeGenerated ? "Edit" : "View", icon: system.isNodeGenerated ? EditRegular : EyeRegular, onClick: async () => {
|
|
8256
8316
|
const scene = system.getScene();
|
|
@@ -8768,7 +8828,7 @@ const ParticleSystemPropertiesServiceDefinition = {
|
|
|
8768
8828
|
{
|
|
8769
8829
|
section: "General",
|
|
8770
8830
|
order: 1,
|
|
8771
|
-
component: ({ context }) => jsx(ParticleSystemGeneralProperties, { particleSystem: context }),
|
|
8831
|
+
component: ({ context }) => jsx(ParticleSystemGeneralProperties, { particleSystem: context, selectionService: selectionService }),
|
|
8772
8832
|
},
|
|
8773
8833
|
],
|
|
8774
8834
|
});
|
|
@@ -8892,6 +8952,33 @@ const PrestepOptions = [
|
|
|
8892
8952
|
{ label: "Teleport", value: PhysicsPrestepType.TELEPORT },
|
|
8893
8953
|
{ label: "Action", value: PhysicsPrestepType.ACTION },
|
|
8894
8954
|
];
|
|
8955
|
+
/**
|
|
8956
|
+
* Convert physics shape type to a human-readable string.
|
|
8957
|
+
* @param type The physics shape type.
|
|
8958
|
+
* @returns The human-readable string.
|
|
8959
|
+
*/
|
|
8960
|
+
function GetShapeTypeString(type) {
|
|
8961
|
+
switch (type) {
|
|
8962
|
+
case 3 /* PhysicsShapeType.BOX */:
|
|
8963
|
+
return "Box";
|
|
8964
|
+
case 0 /* PhysicsShapeType.SPHERE */:
|
|
8965
|
+
return "Sphere";
|
|
8966
|
+
case 2 /* PhysicsShapeType.CYLINDER */:
|
|
8967
|
+
return "Cylinder";
|
|
8968
|
+
case 1 /* PhysicsShapeType.CAPSULE */:
|
|
8969
|
+
return "Capsule";
|
|
8970
|
+
case 5 /* PhysicsShapeType.CONTAINER */:
|
|
8971
|
+
return "Container";
|
|
8972
|
+
case 4 /* PhysicsShapeType.CONVEX_HULL */:
|
|
8973
|
+
return "Convex Hull";
|
|
8974
|
+
case 6 /* PhysicsShapeType.MESH */:
|
|
8975
|
+
return "Mesh";
|
|
8976
|
+
case 7 /* PhysicsShapeType.HEIGHTFIELD */:
|
|
8977
|
+
return "Heightfield";
|
|
8978
|
+
default:
|
|
8979
|
+
return "Unknown";
|
|
8980
|
+
}
|
|
8981
|
+
}
|
|
8895
8982
|
const TransformNodePhysicsProperties = (props) => {
|
|
8896
8983
|
const { node } = props;
|
|
8897
8984
|
const physicsBody = useProperty(node, "physicsBody");
|
|
@@ -8919,15 +9006,19 @@ const PhysicsBodyProperties = (props) => {
|
|
|
8919
9006
|
// Get current velocities
|
|
8920
9007
|
const linearVelocity = useObservableState(useCallback(() => physicsBody.getLinearVelocity(), [physicsBody]), useInterceptObservable("function", physicsBody, "setLinearVelocity"));
|
|
8921
9008
|
const angularVelocity = useObservableState(useCallback(() => physicsBody.getAngularVelocity(), [physicsBody]), useInterceptObservable("function", physicsBody, "setAngularVelocity"));
|
|
9009
|
+
// Get shape and material properties
|
|
9010
|
+
const shape = useProperty(physicsBody, "shape");
|
|
9011
|
+
const type = useProperty(shape, "type");
|
|
9012
|
+
const material = useProperty(shape, "material");
|
|
8922
9013
|
return (jsxs(Fragment, { children: [jsx(NumberDropdownPropertyLine, { label: "Motion Type", options: MotionOptions, value: motionType, onChange: (value) => {
|
|
8923
9014
|
return physicsBody.setMotionType(value);
|
|
8924
9015
|
} }, "MotionType"), jsx(NumberDropdownPropertyLine, { label: "Prestep Type", options: PrestepOptions, value: prestepType, onChange: (value) => {
|
|
8925
9016
|
return physicsBody.setPrestepType(value);
|
|
8926
|
-
} }), jsx(NumberInputPropertyLine, { label: "Linear Damping", min: 0, max: 1, step: 0.01, value: linearDamping, onChange: (e) => {
|
|
9017
|
+
} }), shape && jsx(TextPropertyLine, { label: "Shape Type", value: GetShapeTypeString(type) }), jsx(NumberInputPropertyLine, { label: "Linear Damping", min: 0, max: 1, step: 0.01, value: linearDamping, onChange: (e) => {
|
|
8927
9018
|
physicsBody.setLinearDamping(e);
|
|
8928
9019
|
} }), jsx(NumberInputPropertyLine, { label: "Angular Damping", min: 0, max: 1, step: 0.01, value: angularDamping, onChange: (e) => {
|
|
8929
9020
|
physicsBody.setAngularDamping(e);
|
|
8930
|
-
} }), jsx(Vector3PropertyLine, { label: "Linear Velocity", value: linearVelocity, onChange: (value) => physicsBody.setLinearVelocity(value) }), jsx(Vector3PropertyLine, { label: "Angular Velocity", value: angularVelocity, onChange: (value) => physicsBody.setAngularVelocity(value) }), massProperties && (jsxs(Fragment, { children: [jsx(NumberInputPropertyLine, { label: "Mass", value: massProperties.mass ?? 0, min: 0, step: 0.01, onChange: (value) => {
|
|
9021
|
+
} }), shape && (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Dynamic Friction", min: 0, max: 1, step: 0.01, target: material, propertyKey: "friction", nullable: true, defaultValue: 0.5 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Static Friction", min: 0, max: 1, step: 0.01, target: material, propertyKey: "staticFriction", nullable: true, defaultValue: material?.friction ?? 0.5 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Restitution", min: 0, max: 1, step: 0.01, target: material, propertyKey: "restitution", nullable: true, defaultValue: 0 })] })), jsx(Vector3PropertyLine, { label: "Linear Velocity", value: linearVelocity, onChange: (value) => physicsBody.setLinearVelocity(value) }), jsx(Vector3PropertyLine, { label: "Angular Velocity", value: angularVelocity, onChange: (value) => physicsBody.setAngularVelocity(value) }), massProperties && (jsxs(Fragment, { children: [jsx(NumberInputPropertyLine, { label: "Mass", value: massProperties.mass ?? 0, min: 0, step: 0.01, onChange: (value) => {
|
|
8931
9022
|
physicsBody.setMassProperties({ ...massProperties, mass: value });
|
|
8932
9023
|
} }), jsx(Vector3PropertyLine, { label: "Center of Mass", value: centerOfMass, onChange: (value) => {
|
|
8933
9024
|
physicsBody.setMassProperties({ ...massProperties, centerOfMass: value });
|
|
@@ -9300,6 +9391,7 @@ const SpinButtonPropertyLine = (props) => {
|
|
|
9300
9391
|
return (jsx(PropertyLine, { ...props, children: jsx(SpinButton, { ...props }) }));
|
|
9301
9392
|
};
|
|
9302
9393
|
|
|
9394
|
+
const SnippetDashboardStorageKey = "Babylon/InspectorV2/SnippetDashboard/SpriteManagers";
|
|
9303
9395
|
const SpriteManagerGeneralProperties = (props) => {
|
|
9304
9396
|
const { spriteManager, selectionService } = props;
|
|
9305
9397
|
return (jsxs(Fragment, { children: [jsx(TextPropertyLine, { label: "Capacity", value: spriteManager.capacity.toString() }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Texture", target: spriteManager, propertyKey: "texture", scene: spriteManager.scene, onLink: (texture) => (selectionService.selectedEntity = texture) })] }));
|
|
@@ -9312,6 +9404,84 @@ const SpriteManagerCellProperties = (props) => {
|
|
|
9312
9404
|
const { spriteManager } = props;
|
|
9313
9405
|
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")] }));
|
|
9314
9406
|
};
|
|
9407
|
+
const SpriteManagerFileProperties = (props) => {
|
|
9408
|
+
const { spriteManager, selectionService } = props;
|
|
9409
|
+
const scene = spriteManager.scene;
|
|
9410
|
+
const loadFromFile = useCallback((files) => {
|
|
9411
|
+
const file = files[0];
|
|
9412
|
+
if (!file) {
|
|
9413
|
+
return;
|
|
9414
|
+
}
|
|
9415
|
+
Tools.ReadFile(file, (data) => {
|
|
9416
|
+
const decoder = new TextDecoder("utf-8");
|
|
9417
|
+
const jsonObject = JSON.parse(decoder.decode(data));
|
|
9418
|
+
spriteManager.dispose();
|
|
9419
|
+
selectionService.selectedEntity = null;
|
|
9420
|
+
const newManager = SpriteManager.Parse(jsonObject, scene, "");
|
|
9421
|
+
selectionService.selectedEntity = newManager;
|
|
9422
|
+
}, undefined, true);
|
|
9423
|
+
}, [spriteManager, scene, selectionService]);
|
|
9424
|
+
const saveToFile = useCallback(() => {
|
|
9425
|
+
const content = JSON.stringify(spriteManager.serialize(true));
|
|
9426
|
+
Tools.Download(new Blob([content]), "spriteManager.json");
|
|
9427
|
+
}, [spriteManager]);
|
|
9428
|
+
return (jsxs(Fragment, { children: [jsx(FileUploadLine, { label: "Load", onClick: loadFromFile, accept: ".json" }), jsx(ButtonLine, { label: "Save", onClick: saveToFile })] }));
|
|
9429
|
+
};
|
|
9430
|
+
const SpriteManagerSnippetProperties = (props) => {
|
|
9431
|
+
const { spriteManager, selectionService } = props;
|
|
9432
|
+
const scene = spriteManager.scene;
|
|
9433
|
+
const snippetUrl = Constants.SnippetUrl;
|
|
9434
|
+
const snippetId = useProperty(spriteManager, "snippetId");
|
|
9435
|
+
const loadFromSnippet = useCallback(async () => {
|
|
9436
|
+
const requestedSnippetId = PromptForSnippetId();
|
|
9437
|
+
if (!requestedSnippetId) {
|
|
9438
|
+
return;
|
|
9439
|
+
}
|
|
9440
|
+
spriteManager.dispose();
|
|
9441
|
+
selectionService.selectedEntity = null;
|
|
9442
|
+
try {
|
|
9443
|
+
const newManager = await SpriteManager.ParseFromSnippetAsync(requestedSnippetId, scene);
|
|
9444
|
+
selectionService.selectedEntity = newManager;
|
|
9445
|
+
}
|
|
9446
|
+
catch (err) {
|
|
9447
|
+
alert("Unable to load your sprite manager: " + err);
|
|
9448
|
+
}
|
|
9449
|
+
}, [spriteManager, scene, selectionService]);
|
|
9450
|
+
const saveToSnippet = useCallback(async () => {
|
|
9451
|
+
try {
|
|
9452
|
+
const content = JSON.stringify(spriteManager.serialize(true));
|
|
9453
|
+
const currentSnippetId = spriteManager.snippetId;
|
|
9454
|
+
const result = await SaveToSnippetServer({
|
|
9455
|
+
snippetUrl,
|
|
9456
|
+
currentSnippetId,
|
|
9457
|
+
content,
|
|
9458
|
+
payloadKey: "spriteManager",
|
|
9459
|
+
storageKey: SnippetDashboardStorageKey,
|
|
9460
|
+
entityName: "sprite manager",
|
|
9461
|
+
});
|
|
9462
|
+
// eslint-disable-next-line require-atomic-updates
|
|
9463
|
+
spriteManager.snippetId = result.snippetId;
|
|
9464
|
+
PersistSnippetId(SnippetDashboardStorageKey, result.snippetId);
|
|
9465
|
+
NotifyPlaygroundOfSnippetChange(result.oldSnippetId, result.snippetId, "SpriteManager.ParseFromSnippetAsync");
|
|
9466
|
+
}
|
|
9467
|
+
catch {
|
|
9468
|
+
// Alert already shown by SaveToSnippetServer
|
|
9469
|
+
}
|
|
9470
|
+
}, [spriteManager, snippetUrl]);
|
|
9471
|
+
return (jsxs(Fragment, { children: [snippetId && jsx(TextPropertyLine, { label: "Snippet ID", value: snippetId }), jsx(ButtonLine, { label: "Load from Snippet Server", onClick: loadFromSnippet, icon: CloudArrowUpRegular }), jsx(ButtonLine, { label: "Save to Snippet Server", onClick: saveToSnippet, icon: CloudArrowDownRegular })] }));
|
|
9472
|
+
};
|
|
9473
|
+
const SpriteManagerActionsProperties = (props) => {
|
|
9474
|
+
const { spriteManager, selectionService } = props;
|
|
9475
|
+
const addNewSprite = useCallback(() => {
|
|
9476
|
+
const newSprite = new Sprite("new sprite", spriteManager);
|
|
9477
|
+
selectionService.selectedEntity = newSprite;
|
|
9478
|
+
}, [spriteManager, selectionService]);
|
|
9479
|
+
const disposeManager = useCallback(() => {
|
|
9480
|
+
spriteManager.dispose();
|
|
9481
|
+
selectionService.selectedEntity = null;
|
|
9482
|
+
}, [spriteManager, selectionService]);
|
|
9483
|
+
return (jsxs(Fragment, { children: [spriteManager.sprites.length < spriteManager.capacity && jsx(ButtonLine, { label: "Add New Sprite", onClick: addNewSprite }), jsx(ButtonLine, { label: "Dispose", onClick: disposeManager })] }));
|
|
9484
|
+
};
|
|
9315
9485
|
|
|
9316
9486
|
/**
|
|
9317
9487
|
* Gets the data of the specified texture by rendering it to an intermediate RGBA texture and retrieving the bytes from it.
|
|
@@ -9427,6 +9597,8 @@ const useStyles$9 = makeStyles({
|
|
|
9427
9597
|
marginTop: tokens.spacingVerticalXS,
|
|
9428
9598
|
marginBottom: tokens.spacingVerticalS,
|
|
9429
9599
|
width: "100%",
|
|
9600
|
+
// Checkerboard background to show transparency
|
|
9601
|
+
background: "repeating-conic-gradient(#B2B2B2 0% 25%, white 25% 50%) 50% / 32px 32px",
|
|
9430
9602
|
},
|
|
9431
9603
|
});
|
|
9432
9604
|
// This method of holding TextureChannels was brought over from inspectorv1 and can likely be refactored/simplified
|
|
@@ -9551,6 +9723,18 @@ const SpritePropertiesServiceDefinition = {
|
|
|
9551
9723
|
section: "General",
|
|
9552
9724
|
component: ({ context }) => jsx(SpriteManagerGeneralProperties, { spriteManager: context, selectionService: selectionService }),
|
|
9553
9725
|
},
|
|
9726
|
+
{
|
|
9727
|
+
section: "Actions",
|
|
9728
|
+
component: ({ context }) => jsx(SpriteManagerActionsProperties, { spriteManager: context, selectionService: selectionService }),
|
|
9729
|
+
},
|
|
9730
|
+
{
|
|
9731
|
+
section: "File",
|
|
9732
|
+
component: ({ context }) => jsx(SpriteManagerFileProperties, { spriteManager: context, selectionService: selectionService }),
|
|
9733
|
+
},
|
|
9734
|
+
{
|
|
9735
|
+
section: "Snippet",
|
|
9736
|
+
component: ({ context }) => jsx(SpriteManagerSnippetProperties, { spriteManager: context, selectionService: selectionService }),
|
|
9737
|
+
},
|
|
9554
9738
|
{
|
|
9555
9739
|
section: "Cells",
|
|
9556
9740
|
component: ({ context }) => jsx(SpriteManagerCellProperties, { spriteManager: context }),
|
|
@@ -9632,6 +9816,13 @@ const AdvancedDynamicTextureGeneralProperties = MakeLazyComponent(async () => {
|
|
|
9632
9816
|
return (jsxs(Fragment, { children: [jsx(StringifiedPropertyLine, { label: "Last Layout Time", value: layoutTime, precision: 2, units: "ms" }), jsx(StringifiedPropertyLine, { label: "Last Render Time", value: renderTime, precision: 2, units: "ms" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Render Scale", target: texture, propertyKey: "renderScale", min: 0.1, max: 5, step: 0.1 }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Premultiply Alpha", target: texture, propertyKey: "premulAlpha" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Ideal Width", target: texture, propertyKey: "idealWidth" }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Ideal Height", target: texture, propertyKey: "idealHeight" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Smallest Ideal", target: texture, propertyKey: "useSmallestIdeal" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Render at Ideal Size", target: texture, propertyKey: "renderAtIdealSize" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Invalidate Rect Optimization", target: texture, propertyKey: "useInvalidateRectOptimization" })] }));
|
|
9633
9817
|
};
|
|
9634
9818
|
}, { spinnerSize: "extra-tiny", spinnerLabel: "Loading..." });
|
|
9819
|
+
const AdvancedDynamicTexturePreviewProperties = (props) => {
|
|
9820
|
+
const { texture } = props;
|
|
9821
|
+
return (jsx(Fragment, { children: jsx(ButtonLine, { label: "Edit GUI", icon: EditRegular, onClick: async () => {
|
|
9822
|
+
const { GUIEditor } = await import('@babylonjs/gui-editor');
|
|
9823
|
+
await GUIEditor.Show({ liveGuiTexture: texture });
|
|
9824
|
+
} }) }));
|
|
9825
|
+
};
|
|
9635
9826
|
|
|
9636
9827
|
const TextureFormat = [
|
|
9637
9828
|
{ label: "Alpha", normalizable: false, value: Constants.TEXTUREFORMAT_ALPHA },
|
|
@@ -9701,7 +9892,7 @@ const BaseTexturePreviewProperties = (props) => {
|
|
|
9701
9892
|
const { texture, textureEditor: TextureEditor } = props;
|
|
9702
9893
|
const texturePreviewImperativeRef = useRef(null);
|
|
9703
9894
|
const childWindow = useRef(null);
|
|
9704
|
-
return (jsxs(Fragment, { children: [jsx(TexturePreview, { imperativeRef: texturePreviewImperativeRef, texture: texture }), jsx(TextureUpload, { texture: texture }), jsx(ButtonLine, { label: "Edit Texture", onClick: () => childWindow.current?.open() }), jsx(ChildWindow, { id: "Texture Editor", imperativeRef: childWindow, children: jsx(TextureEditor, { texture: texture, onUpdate: async () => await texturePreviewImperativeRef.current?.refresh() }) })] }));
|
|
9895
|
+
return (jsxs(Fragment, { children: [jsx(TexturePreview, { imperativeRef: texturePreviewImperativeRef, texture: texture }), jsx(TextureUpload, { texture: texture }), jsx(ButtonLine, { label: "Edit Texture", onClick: () => childWindow.current?.open(), icon: EditRegular }), jsx(ChildWindow, { id: "Texture Editor", imperativeRef: childWindow, children: jsx(TextureEditor, { texture: texture, onUpdate: async () => await texturePreviewImperativeRef.current?.refresh() }) })] }));
|
|
9705
9896
|
};
|
|
9706
9897
|
const BaseTextureGeneralProperties = (props) => {
|
|
9707
9898
|
const { texture } = props;
|
|
@@ -11458,6 +11649,7 @@ const TexturePropertiesServiceDefinition = {
|
|
|
11458
11649
|
{
|
|
11459
11650
|
section: "Preview",
|
|
11460
11651
|
component: ({ context }) => jsx(TexturePreviewProperties, { texture: context }),
|
|
11652
|
+
order: 200,
|
|
11461
11653
|
},
|
|
11462
11654
|
{
|
|
11463
11655
|
section: "General",
|
|
@@ -11516,6 +11708,11 @@ const TexturePropertiesServiceDefinition = {
|
|
|
11516
11708
|
order: 100,
|
|
11517
11709
|
component: ({ context }) => jsx(AdvancedDynamicTextureGeneralProperties, { texture: context }),
|
|
11518
11710
|
},
|
|
11711
|
+
{
|
|
11712
|
+
section: "Preview",
|
|
11713
|
+
order: 100,
|
|
11714
|
+
component: ({ context }) => jsx(AdvancedDynamicTexturePreviewProperties, { texture: context }),
|
|
11715
|
+
},
|
|
11519
11716
|
],
|
|
11520
11717
|
});
|
|
11521
11718
|
return {
|
|
@@ -11804,6 +12001,14 @@ const FrameGraphExplorerServiceDefinition = {
|
|
|
11804
12001
|
function IsAdvancedDynamicTexture(entity) {
|
|
11805
12002
|
return entity?.getClassName?.() === "AdvancedDynamicTexture";
|
|
11806
12003
|
}
|
|
12004
|
+
function IsContainer(entity) {
|
|
12005
|
+
// Check for Container-specific properties without using instanceof to avoid importing the concrete type
|
|
12006
|
+
return entity?.children !== undefined && entity?.onControlAddedObservable !== undefined;
|
|
12007
|
+
}
|
|
12008
|
+
function IsControl(entity) {
|
|
12009
|
+
// Check for Control-specific properties without using instanceof to avoid importing the concrete type
|
|
12010
|
+
return entity?._currentMeasure !== undefined && entity?.onPointerDownObservable !== undefined;
|
|
12011
|
+
}
|
|
11807
12012
|
const GuiExplorerServiceDefinition = {
|
|
11808
12013
|
friendlyName: "GUI Explorer",
|
|
11809
12014
|
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
|
|
@@ -11812,35 +12017,121 @@ const GuiExplorerServiceDefinition = {
|
|
|
11812
12017
|
if (!scene) {
|
|
11813
12018
|
return undefined;
|
|
11814
12019
|
}
|
|
12020
|
+
const guiEntityAddedObservable = new Observable();
|
|
12021
|
+
const guiEntityRemovedObservable = new Observable();
|
|
12022
|
+
const textureAddedObserver = scene.onNewTextureAddedObservable.add((texture) => {
|
|
12023
|
+
if (IsAdvancedDynamicTexture(texture)) {
|
|
12024
|
+
guiEntityAddedObservable.notifyObservers(texture);
|
|
12025
|
+
}
|
|
12026
|
+
});
|
|
12027
|
+
const textureRemovedObserver = scene.onTextureRemovedObservable.add((texture) => {
|
|
12028
|
+
if (IsAdvancedDynamicTexture(texture)) {
|
|
12029
|
+
guiEntityRemovedObservable.notifyObservers(texture);
|
|
12030
|
+
}
|
|
12031
|
+
});
|
|
11815
12032
|
const sectionRegistration = sceneExplorerService.addSection({
|
|
11816
12033
|
displayName: "GUI",
|
|
11817
12034
|
order: 1100 /* DefaultSectionsOrder.GUIs */,
|
|
11818
12035
|
getRootEntities: () => scene.textures.filter(IsAdvancedDynamicTexture),
|
|
11819
|
-
|
|
12036
|
+
getEntityChildren: (entity) => (IsAdvancedDynamicTexture(entity) ? entity.getChildren() : IsContainer(entity) ? entity.children : []),
|
|
12037
|
+
getEntityDisplayInfo: (entity) => {
|
|
12038
|
+
const disposeActions = [];
|
|
11820
12039
|
const onChangeObservable = new Observable();
|
|
11821
|
-
|
|
12040
|
+
disposeActions.push(() => onChangeObservable.clear());
|
|
12041
|
+
const nameHookToken = InterceptProperty(entity, "name", {
|
|
11822
12042
|
afterSet: () => {
|
|
11823
12043
|
onChangeObservable.notifyObservers();
|
|
11824
12044
|
},
|
|
11825
12045
|
});
|
|
12046
|
+
disposeActions.push(() => nameHookToken.dispose());
|
|
12047
|
+
if (!IsAdvancedDynamicTexture(entity) && IsContainer(entity)) {
|
|
12048
|
+
const controlAddedObserver = entity.onControlAddedObservable.add((control) => {
|
|
12049
|
+
if (control) {
|
|
12050
|
+
guiEntityAddedObservable.notifyObservers(control);
|
|
12051
|
+
}
|
|
12052
|
+
});
|
|
12053
|
+
disposeActions.push(() => entity.onControlAddedObservable.remove(controlAddedObserver));
|
|
12054
|
+
const controlRemovedObserver = entity.onControlRemovedObservable.add((control) => {
|
|
12055
|
+
if (control) {
|
|
12056
|
+
guiEntityRemovedObservable.notifyObservers(control);
|
|
12057
|
+
}
|
|
12058
|
+
});
|
|
12059
|
+
disposeActions.push(() => entity.onControlRemovedObservable.remove(controlRemovedObserver));
|
|
12060
|
+
}
|
|
11826
12061
|
return {
|
|
11827
12062
|
get name() {
|
|
11828
|
-
|
|
12063
|
+
if (IsAdvancedDynamicTexture(entity)) {
|
|
12064
|
+
return entity.name;
|
|
12065
|
+
}
|
|
12066
|
+
else {
|
|
12067
|
+
return `${entity.name ?? "No name"} [${entity.getClassName()}]`;
|
|
12068
|
+
}
|
|
11829
12069
|
},
|
|
11830
12070
|
onChange: onChangeObservable,
|
|
11831
12071
|
dispose: () => {
|
|
11832
|
-
|
|
12072
|
+
disposeActions.reverse().forEach((disposeAction) => disposeAction());
|
|
12073
|
+
},
|
|
12074
|
+
};
|
|
12075
|
+
},
|
|
12076
|
+
entityIcon: ({ entity }) => (IsAdvancedDynamicTexture(entity) ? jsx(AppGenericRegular, {}) : jsx(RectangleLandscapeRegular, {})),
|
|
12077
|
+
getEntityAddedObservables: () => [guiEntityAddedObservable],
|
|
12078
|
+
getEntityRemovedObservables: () => [guiEntityRemovedObservable],
|
|
12079
|
+
});
|
|
12080
|
+
const highlightControlCommandRegistration = sceneExplorerService.addEntityCommand({
|
|
12081
|
+
predicate: (entity) => IsControl(entity),
|
|
12082
|
+
order: 1000 /* DefaultCommandsOrder.GuiHighlight */,
|
|
12083
|
+
getCommand: (control) => {
|
|
12084
|
+
const onChangeObservable = new Observable();
|
|
12085
|
+
const showBoundingBoxHook = InterceptProperty(control, "isHighlighted", {
|
|
12086
|
+
afterSet: () => onChangeObservable.notifyObservers(),
|
|
12087
|
+
});
|
|
12088
|
+
return {
|
|
12089
|
+
type: "toggle",
|
|
12090
|
+
get displayName() {
|
|
12091
|
+
return `${control.isHighlighted ? "Hide" : "Show"} Bounding Box`;
|
|
12092
|
+
},
|
|
12093
|
+
icon: () => (control.isHighlighted ? jsx(BorderOutsideRegular, {}) : jsx(BorderNoneRegular, {})),
|
|
12094
|
+
get isEnabled() {
|
|
12095
|
+
return control.isHighlighted;
|
|
12096
|
+
},
|
|
12097
|
+
set isEnabled(enabled) {
|
|
12098
|
+
control.isHighlighted = enabled;
|
|
12099
|
+
},
|
|
12100
|
+
onChange: onChangeObservable,
|
|
12101
|
+
dispose: () => {
|
|
12102
|
+
showBoundingBoxHook.dispose();
|
|
11833
12103
|
onChangeObservable.clear();
|
|
11834
12104
|
},
|
|
11835
12105
|
};
|
|
11836
12106
|
},
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
12107
|
+
});
|
|
12108
|
+
const controlVisibilityCommandRegistration = sceneExplorerService.addEntityCommand({
|
|
12109
|
+
predicate: (entity) => IsControl(entity),
|
|
12110
|
+
order: 1100 /* DefaultCommandsOrder.GuiVisibility */,
|
|
12111
|
+
getCommand: (control) => {
|
|
12112
|
+
return {
|
|
12113
|
+
type: "toggle",
|
|
12114
|
+
get displayName() {
|
|
12115
|
+
return `${control.isVisible ? "Hide" : "Show"} Mesh`;
|
|
12116
|
+
},
|
|
12117
|
+
icon: () => (control.isVisible ? jsx(EyeRegular, {}) : jsx(EyeOffRegular, {})),
|
|
12118
|
+
get isEnabled() {
|
|
12119
|
+
return !control.isVisible;
|
|
12120
|
+
},
|
|
12121
|
+
set isEnabled(enabled) {
|
|
12122
|
+
control.isVisible = !enabled;
|
|
12123
|
+
},
|
|
12124
|
+
onChange: control.onIsVisibleChangedObservable,
|
|
12125
|
+
};
|
|
12126
|
+
},
|
|
11840
12127
|
});
|
|
11841
12128
|
return {
|
|
11842
12129
|
dispose: () => {
|
|
12130
|
+
textureAddedObserver.remove();
|
|
12131
|
+
textureRemovedObserver.remove();
|
|
11843
12132
|
sectionRegistration.dispose();
|
|
12133
|
+
highlightControlCommandRegistration.dispose();
|
|
12134
|
+
controlVisibilityCommandRegistration.dispose();
|
|
11844
12135
|
},
|
|
11845
12136
|
};
|
|
11846
12137
|
},
|
|
@@ -13536,4 +13827,4 @@ const TextAreaPropertyLine = (props) => {
|
|
|
13536
13827
|
AttachDebugLayer();
|
|
13537
13828
|
|
|
13538
13829
|
export { useSidePaneDockOverrides as $, Accordion as A, ButtonLine as B, Collapse as C, DebugServiceIdentity as D, ExtensibleAccordion as E, FileUploadLine as F, useVector3Property as G, useColor3Property as H, Inspector as I, useColor4Property as J, useQuaternionProperty as K, Link as L, MakeLazyComponent as M, NumberDropdownPropertyLine as N, MakePropertyHook as O, Popover as P, useInterceptObservable as Q, useEventfulState as R, SwitchPropertyLine as S, ToolsServiceIdentity as T, useObservableCollection as U, Vector3PropertyLine as V, useOrderedObservableCollection as W, usePollingObservable as X, useResource as Y, useAsyncResource as Z, useCompactMode as _, SyncedSliderPropertyLine as a, useAngleConverters as a0, MakeTeachingMoment as a1, MakeDialogTeachingMoment as a2, InterceptFunction as a3, GetPropertyDescriptor as a4, IsPropertyReadonly as a5, InterceptProperty as a6, ObservableCollection as a7, ConstructorFactory as a8, SelectionServiceIdentity as a9, TextInput as aA, ToggleButton as aB, ChildWindow as aC, FactorGradientList as aD, Color3GradientList as aE, Color4GradientList as aF, Pane as aG, BooleanBadgePropertyLine as aH, Color3PropertyLine as aI, Color4PropertyLine as aJ, HexPropertyLine as aK, NumberInputPropertyLine as aL, LinkPropertyLine as aM, PropertyLine as aN, LineContainer as aO, PlaceholderPropertyLine as aP, StringifiedPropertyLine as aQ, TextAreaPropertyLine as aR, TextPropertyLine as aS, RotationVectorPropertyLine as aT, QuaternionPropertyLine as aU, Vector2PropertyLine as aV, Vector4PropertyLine as aW, SelectionServiceDefinition as aa, SettingsContextIdentity as ab, ShowInspector as ac, Checkbox as ad, ColorPickerPopup as ae, InputHexField as af, InputHsvField as ag, ComboBox as ah, DraggableLine as ai, Dropdown as aj, NumberDropdown as ak, StringDropdown as al, FactorGradientComponent as am, Color3GradientComponent as an, Color4GradientComponent as ao, ColorStepGradientComponent as ap, InfoLabel as aq, List as ar, MessageBar as as, PositionedPopover as at, SearchBar as au, SearchBox as av, SpinButton as aw, Switch as ax, SyncedSliderInput as ay, Textarea 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, Theme as x, BuiltInsExtensionFeed as y, useProperty as z };
|
|
13539
|
-
//# sourceMappingURL=index-
|
|
13830
|
+
//# sourceMappingURL=index-C7ey_J-r.js.map
|