@babylonjs/inspector 8.49.6 → 8.49.7
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/{extensionsListService-1OhC4MZF.js → extensionsListService-DnGdJhHc.js} +3 -3
- package/lib/{extensionsListService-1OhC4MZF.js.map → extensionsListService-DnGdJhHc.js.map} +1 -1
- package/lib/{index-ByfjmUIP.js → index-BVYxLK-p.js} +593 -199
- package/lib/index-BVYxLK-p.js.map +1 -0
- package/lib/index.d.ts +435 -27
- package/lib/index.js +3 -3
- package/lib/{quickCreateToolsService-B55TQEXK.js → quickCreateToolsService-B4U-3oma.js} +4 -4
- package/lib/{quickCreateToolsService-B55TQEXK.js.map → quickCreateToolsService-B4U-3oma.js.map} +1 -1
- package/lib/{reflectorService-BHVk1B6L.js → reflectorService-ozofO4uE.js} +4 -4
- package/lib/{reflectorService-BHVk1B6L.js.map → reflectorService-ozofO4uE.js.map} +1 -1
- package/package.json +1 -1
- package/lib/index-ByfjmUIP.js.map +0 -1
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, forwardRef, useContext, useState, useCallback, Component, useMemo, useEffect, useRef,
|
|
3
|
-
import { tokens, makeStyles, Tooltip as Tooltip$1, Button as Button$1, Spinner, Link as Link$1, Caption1, Body1, ToggleButton as ToggleButton$1, useFluent, InfoLabel as InfoLabel$1, mergeClasses, Body1Strong, useId, useToastController, Toast, ToastBody, FluentProvider, Toaster, Checkbox as Checkbox$1,
|
|
4
|
-
import { ErrorCircleRegular, ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, CopyRegular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, DocumentTextRegular, createFluentIcon,
|
|
2
|
+
import { createContext, forwardRef, useContext, useState, useCallback, Component, useMemo, useEffect, useRef, useReducer, Children, isValidElement, useLayoutEffect, cloneElement, useImperativeHandle, createElement, Suspense, memo, Fragment as Fragment$1, lazy } from 'react';
|
|
3
|
+
import { tokens, makeStyles, Tooltip as Tooltip$1, Button as Button$1, Spinner, Accordion as Accordion$1, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, MessageBar as MessageBar$1, MessageBarBody, AccordionItem, SearchBox as SearchBox$1, Portal, Link as Link$1, Caption1, Body1, ToggleButton as ToggleButton$1, useFluent, InfoLabel as InfoLabel$1, mergeClasses, Body1Strong, useId, useToastController, Toast, ToastBody, FluentProvider, Toaster, Checkbox as Checkbox$1, createLightTheme, createDarkTheme, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, RendererProvider, createDOMRenderer, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, ToolbarRadioButton, MenuGroup, MenuGroupHeader, treeItemLevelToken, FlatTree, FlatTreeItem, TreeItemLayout, MenuDivider, MenuItemCheckbox, Switch as Switch$1, SpinButton as SpinButton$1, Input, Dropdown as Dropdown$1, Option, Popover as Popover$1, PopoverTrigger, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, ColorSwatch, PresenceBadge, Slider, MenuItemRadio, Dialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, List as List$1, ListItem, Badge, Label, MessageBarTitle, Subtitle2, useComboboxFilter, Combobox, Textarea as Textarea$1, ToolbarButton, ToolbarDivider, Field } from '@fluentui/react-components';
|
|
4
|
+
import { ErrorCircleRegular, EyeFilled, EyeOffRegular, CheckmarkFilled, EditRegular, FilterRegular, PinFilled, PinRegular, ArrowCircleUpRegular, ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, CopyRegular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, DocumentTextRegular, createFluentIcon, TextSortAscendingRegular, GlobeRegular, ArrowExpandAllRegular, ArrowCollapseAllRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, ArrowDownloadRegular, StopRegular, RecordRegular, DataBarHorizontalRegular, WrenchRegular, WeatherSunnyRegular, WeatherMoonRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, AddRegular, DeleteRegular, FullScreenMaximizeRegular, ChevronDownRegular, ChevronRightRegular, CircleSmallFilled, SaveRegular, PreviousRegular, ArrowPreviousRegular, TriangleLeftRegular, RecordStopRegular, PlayRegular, ArrowNextRegular, NextRegular, PauseRegular, LinkDismissRegular, LinkEditRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, EyeRegular, CloudArrowUpRegular, CloudArrowDownRegular, EyeOffFilled, ArrowMoveFilled, StopFilled, PlayFilled, LockOpenRegular, LockClosedRegular, ResizeRegular, ChevronUpRegular, 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, SoundWaveCircleRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, BranchRegular, DeleteFilled } from '@fluentui/react-icons';
|
|
5
5
|
import { Color3, Color4 } from '@babylonjs/core/Maths/math.color.js';
|
|
6
6
|
import { Vector3, Quaternion, Matrix, Vector2, Vector4, TmpVectors } from '@babylonjs/core/Maths/math.vector.js';
|
|
7
7
|
import { Observable } from '@babylonjs/core/Misc/observable.js';
|
|
8
8
|
import { GetClassName } from '@babylonjs/core/Misc/typeStore.js';
|
|
9
|
+
import { DataStorage } from '@babylonjs/core/Misc/dataStorage.js';
|
|
10
|
+
import { Logger } from '@babylonjs/core/Misc/logger.js';
|
|
9
11
|
import { Collapse as Collapse$1, Fade } from '@fluentui/react-motion-components-preview';
|
|
10
12
|
import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
|
|
11
13
|
import { AsyncLock } from '@babylonjs/core/Misc/asyncLock.js';
|
|
12
14
|
import { Deferred } from '@babylonjs/core/Misc/deferred.js';
|
|
13
|
-
import { Logger } from '@babylonjs/core/Misc/logger.js';
|
|
14
15
|
import { Clamp } from '@babylonjs/core/Maths/math.scalar.functions.js';
|
|
15
16
|
import { VirtualizerScrollView } from '@fluentui-contrib/react-virtualizer';
|
|
16
17
|
import { UniqueIdGenerator } from '@babylonjs/core/Misc/uniqueIdGenerator.js';
|
|
@@ -24,7 +25,6 @@ import { CreateGround } from '@babylonjs/core/Meshes/Builders/groundBuilder.js';
|
|
|
24
25
|
import { Tools } from '@babylonjs/core/Misc/tools.js';
|
|
25
26
|
import { UtilityLayerRenderer } from '@babylonjs/core/Rendering/utilityLayerRenderer.js';
|
|
26
27
|
import { GridMaterial } from '@babylonjs/materials/grid/gridMaterial.js';
|
|
27
|
-
import { DataStorage } from '@babylonjs/core/Misc/dataStorage.js';
|
|
28
28
|
import { EngineInstrumentation } from '@babylonjs/core/Instrumentation/engineInstrumentation.js';
|
|
29
29
|
import { SceneInstrumentation } from '@babylonjs/core/Instrumentation/sceneInstrumentation.js';
|
|
30
30
|
import '@babylonjs/core/Engines/AbstractEngine/abstractEngine.timeQuery.js';
|
|
@@ -1018,6 +1018,485 @@ function PropertyImpl(props, ref) {
|
|
|
1018
1018
|
*/
|
|
1019
1019
|
const Property = CreateGenericForwardRef(PropertyImpl);
|
|
1020
1020
|
|
|
1021
|
+
// ============================================================================
|
|
1022
|
+
// Storage Helpers
|
|
1023
|
+
// ============================================================================
|
|
1024
|
+
const STORAGE_KEY_ROOT = "Babylon/Accordion";
|
|
1025
|
+
const ReadFromStorage = (path, initial) => {
|
|
1026
|
+
try {
|
|
1027
|
+
const stored = DataStorage.ReadString(`${STORAGE_KEY_ROOT}/${path}`, "");
|
|
1028
|
+
return stored ? JSON.parse(stored) : initial;
|
|
1029
|
+
}
|
|
1030
|
+
catch {
|
|
1031
|
+
return initial;
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
const WriteToStorage = (path, data) => {
|
|
1035
|
+
DataStorage.WriteString(`${STORAGE_KEY_ROOT}/${path}`, JSON.stringify(data));
|
|
1036
|
+
};
|
|
1037
|
+
// ============================================================================
|
|
1038
|
+
// Reducer
|
|
1039
|
+
// ============================================================================
|
|
1040
|
+
const AccordionReducer = (state, action) => {
|
|
1041
|
+
switch (action.type) {
|
|
1042
|
+
case "SET_SEARCH_TERM":
|
|
1043
|
+
return { ...state, searchTerm: action.term };
|
|
1044
|
+
case "SET_EDIT_MODE":
|
|
1045
|
+
return { ...state, editMode: action.enabled };
|
|
1046
|
+
case "TOGGLE_PINNED": {
|
|
1047
|
+
const isPinned = state.pinnedIds.includes(action.itemId);
|
|
1048
|
+
return {
|
|
1049
|
+
...state,
|
|
1050
|
+
pinnedIds: isPinned ? state.pinnedIds.filter((id) => id !== action.itemId) : [...state.pinnedIds, action.itemId],
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
case "TOGGLE_HIDDEN": {
|
|
1054
|
+
const isHidden = state.hiddenIds.includes(action.itemId);
|
|
1055
|
+
return {
|
|
1056
|
+
...state,
|
|
1057
|
+
hiddenIds: isHidden ? state.hiddenIds.filter((id) => id !== action.itemId) : [...state.hiddenIds, action.itemId],
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
case "MOVE_PINNED_UP": {
|
|
1061
|
+
const index = state.pinnedIds.indexOf(action.itemId);
|
|
1062
|
+
if (index <= 0) {
|
|
1063
|
+
return state;
|
|
1064
|
+
}
|
|
1065
|
+
const newPinnedIds = [...state.pinnedIds];
|
|
1066
|
+
[newPinnedIds[index - 1], newPinnedIds[index]] = [newPinnedIds[index], newPinnedIds[index - 1]];
|
|
1067
|
+
return { ...state, pinnedIds: newPinnedIds };
|
|
1068
|
+
}
|
|
1069
|
+
case "SHOW_ALL":
|
|
1070
|
+
return { ...state, hiddenIds: [] };
|
|
1071
|
+
case "HIDE_ALL_VISIBLE":
|
|
1072
|
+
return {
|
|
1073
|
+
...state,
|
|
1074
|
+
hiddenIds: [...new Set([...state.hiddenIds, ...action.visibleItemIds])],
|
|
1075
|
+
};
|
|
1076
|
+
default:
|
|
1077
|
+
return state;
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
const AccordionContext = createContext(undefined);
|
|
1081
|
+
/**
|
|
1082
|
+
* Hook to create and manage the AccordionContext value.
|
|
1083
|
+
*
|
|
1084
|
+
* @param props - AccordionProps
|
|
1085
|
+
* @returns AccordionContextValue, or undefined if no features are enabled or no uniqueId is provided.
|
|
1086
|
+
*/
|
|
1087
|
+
function useAccordionContext(props) {
|
|
1088
|
+
const { uniqueId: accordionId, enablePinnedItems, enableHiddenItems, enableSearchItems } = props;
|
|
1089
|
+
const features = useMemo(() => ({
|
|
1090
|
+
pinning: enablePinnedItems ?? false,
|
|
1091
|
+
hiding: enableHiddenItems ?? false,
|
|
1092
|
+
search: enableSearchItems ?? false,
|
|
1093
|
+
}), [enablePinnedItems, enableHiddenItems, enableSearchItems]);
|
|
1094
|
+
const hasFeatures = features.pinning || features.hiding || features.search;
|
|
1095
|
+
// Initialize state from localStorage
|
|
1096
|
+
const initialState = useMemo(() => {
|
|
1097
|
+
if (!accordionId || !hasFeatures) {
|
|
1098
|
+
return { pinnedIds: [], hiddenIds: [], searchTerm: "", editMode: false };
|
|
1099
|
+
}
|
|
1100
|
+
return {
|
|
1101
|
+
pinnedIds: features.pinning ? ReadFromStorage(`Pinned/${accordionId}`, []) : [],
|
|
1102
|
+
hiddenIds: features.hiding ? ReadFromStorage(`Hidden/${accordionId}`, []) : [],
|
|
1103
|
+
searchTerm: "",
|
|
1104
|
+
editMode: false,
|
|
1105
|
+
};
|
|
1106
|
+
}, [accordionId, hasFeatures, features.pinning, features.hiding]);
|
|
1107
|
+
const [state, dispatch] = useReducer(AccordionReducer, initialState);
|
|
1108
|
+
const pinnedContainerRef = useRef(null);
|
|
1109
|
+
const registeredItemIds = useRef(new Set());
|
|
1110
|
+
// Persist pinnedIds to localStorage when they change
|
|
1111
|
+
useEffect(() => {
|
|
1112
|
+
if (accordionId && features.pinning) {
|
|
1113
|
+
WriteToStorage(`Pinned/${accordionId}`, state.pinnedIds);
|
|
1114
|
+
}
|
|
1115
|
+
}, [accordionId, features.pinning, state.pinnedIds]);
|
|
1116
|
+
// Persist hiddenIds to localStorage when they change
|
|
1117
|
+
useEffect(() => {
|
|
1118
|
+
if (accordionId && features.hiding) {
|
|
1119
|
+
WriteToStorage(`Hidden/${accordionId}`, state.hiddenIds);
|
|
1120
|
+
}
|
|
1121
|
+
}, [accordionId, features.hiding, state.hiddenIds]);
|
|
1122
|
+
// Return undefined if no accordionId or no features enabled
|
|
1123
|
+
if (!accordionId || !hasFeatures) {
|
|
1124
|
+
return undefined;
|
|
1125
|
+
}
|
|
1126
|
+
return {
|
|
1127
|
+
accordionId,
|
|
1128
|
+
state,
|
|
1129
|
+
dispatch,
|
|
1130
|
+
features,
|
|
1131
|
+
pinnedContainerRef,
|
|
1132
|
+
registeredItemIds,
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
const AccordionSectionBlockContext = createContext(undefined);
|
|
1136
|
+
/**
|
|
1137
|
+
* Hook to create the AccordionSectionBlockContext value.
|
|
1138
|
+
*
|
|
1139
|
+
* @param props - AccordionSectionBlockProps
|
|
1140
|
+
* @returns AccordionSectionBlockContextValue
|
|
1141
|
+
*/
|
|
1142
|
+
function useAccordionSectionBlockContext(props) {
|
|
1143
|
+
const { sectionId } = props;
|
|
1144
|
+
return useMemo(() => ({ sectionId }), [sectionId]);
|
|
1145
|
+
}
|
|
1146
|
+
// ============================================================================
|
|
1147
|
+
// Item Depth Context (to detect nested AccordionSectionItems)
|
|
1148
|
+
// ============================================================================
|
|
1149
|
+
/**
|
|
1150
|
+
* Context to track whether we're inside an AccordionSectionItem.
|
|
1151
|
+
* Used to prevent nested items from being individually manageable.
|
|
1152
|
+
*/
|
|
1153
|
+
const AccordionItemDepthContext = createContext(false);
|
|
1154
|
+
/**
|
|
1155
|
+
* Hook to compute item state from accordion context.
|
|
1156
|
+
*
|
|
1157
|
+
* @param props - AccordionSectionItemProps
|
|
1158
|
+
* @returns AccordionItemState, or undefined if no accordion context or nested item.
|
|
1159
|
+
*/
|
|
1160
|
+
function useAccordionSectionItemState(props) {
|
|
1161
|
+
const { uniqueId: itemId, label: itemLabel, staticItem } = props;
|
|
1162
|
+
const accordionCtx = useContext(AccordionContext);
|
|
1163
|
+
const sectionCtx = useContext(AccordionSectionBlockContext);
|
|
1164
|
+
const isNested = useContext(AccordionItemDepthContext);
|
|
1165
|
+
// Build the globally unique item ID
|
|
1166
|
+
const itemUniqueId = useMemo(() => {
|
|
1167
|
+
if (!accordionCtx || !sectionCtx) {
|
|
1168
|
+
return "";
|
|
1169
|
+
}
|
|
1170
|
+
return `${accordionCtx.accordionId}\0${sectionCtx.sectionId}\0${itemId}`;
|
|
1171
|
+
}, [accordionCtx?.accordionId, sectionCtx?.sectionId, itemId]);
|
|
1172
|
+
// Debug: warn if itemId changes (should be stable)
|
|
1173
|
+
const prevItemIdRef = useRef(itemId);
|
|
1174
|
+
useEffect(() => {
|
|
1175
|
+
if (prevItemIdRef.current !== itemId) {
|
|
1176
|
+
Logger.Warn(`Accordion: The uniqueId "${itemId}" in section "${sectionCtx?.sectionId}" has changed from "${prevItemIdRef.current}". ` +
|
|
1177
|
+
`Each item must have a unique, stable ID for pin/hide persistence to work correctly.`);
|
|
1178
|
+
}
|
|
1179
|
+
prevItemIdRef.current = itemId;
|
|
1180
|
+
}, [itemId, sectionCtx?.sectionId]);
|
|
1181
|
+
// Debug: warn if itemUniqueId is not unique (duplicate detection)
|
|
1182
|
+
useEffect(() => {
|
|
1183
|
+
if (!accordionCtx || !itemUniqueId) {
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
const { registeredItemIds } = accordionCtx;
|
|
1187
|
+
if (registeredItemIds.current.has(itemUniqueId)) {
|
|
1188
|
+
Logger.Warn(`Accordion: Duplicate uniqueId "${itemId}" detected in section "${sectionCtx?.sectionId}". ` +
|
|
1189
|
+
`Each item must have a unique ID within its section for pin/hide persistence to work correctly.`);
|
|
1190
|
+
}
|
|
1191
|
+
else {
|
|
1192
|
+
registeredItemIds.current.add(itemUniqueId);
|
|
1193
|
+
}
|
|
1194
|
+
return () => {
|
|
1195
|
+
registeredItemIds.current.delete(itemUniqueId);
|
|
1196
|
+
};
|
|
1197
|
+
}, [accordionCtx, itemUniqueId, itemId, sectionCtx?.sectionId]);
|
|
1198
|
+
// If no context, static item, or nested, return undefined
|
|
1199
|
+
if (!accordionCtx || staticItem) {
|
|
1200
|
+
return undefined;
|
|
1201
|
+
}
|
|
1202
|
+
const { state, dispatch, features } = accordionCtx;
|
|
1203
|
+
const { pinnedIds, hiddenIds, searchTerm, editMode } = state;
|
|
1204
|
+
// Compute derived state
|
|
1205
|
+
const isPinned = features.pinning && pinnedIds.includes(itemUniqueId);
|
|
1206
|
+
const isHidden = features.hiding && hiddenIds.includes(itemUniqueId);
|
|
1207
|
+
const pinnedIndex = isPinned ? pinnedIds.indexOf(itemUniqueId) : -1;
|
|
1208
|
+
// Search matching
|
|
1209
|
+
const searchText = (itemLabel ?? itemId).toLowerCase();
|
|
1210
|
+
const isMatch = !features.search || !searchTerm || searchText.includes(searchTerm.toLowerCase());
|
|
1211
|
+
return {
|
|
1212
|
+
itemUniqueId,
|
|
1213
|
+
isNested,
|
|
1214
|
+
isPinned,
|
|
1215
|
+
isHidden,
|
|
1216
|
+
isMatch,
|
|
1217
|
+
pinnedIndex,
|
|
1218
|
+
inEditMode: editMode,
|
|
1219
|
+
actions: {
|
|
1220
|
+
togglePinned: () => dispatch({ type: "TOGGLE_PINNED", itemId: itemUniqueId }),
|
|
1221
|
+
toggleHidden: () => dispatch({ type: "TOGGLE_HIDDEN", itemId: itemUniqueId }),
|
|
1222
|
+
movePinnedUp: () => dispatch({ type: "MOVE_PINNED_UP", itemId: itemUniqueId }),
|
|
1223
|
+
},
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
const useStyles$S = makeStyles({
|
|
1228
|
+
accordion: {
|
|
1229
|
+
display: "flex",
|
|
1230
|
+
flexDirection: "column",
|
|
1231
|
+
height: "100%",
|
|
1232
|
+
},
|
|
1233
|
+
accordionBody: {
|
|
1234
|
+
overflowX: "hidden",
|
|
1235
|
+
overflowY: "auto",
|
|
1236
|
+
paddingBottom: tokens.spacingVerticalM, // bottom padding since there is no divider at the bottom
|
|
1237
|
+
},
|
|
1238
|
+
divider: {
|
|
1239
|
+
paddingTop: CustomTokens.dividerGap,
|
|
1240
|
+
paddingBottom: CustomTokens.dividerGap,
|
|
1241
|
+
},
|
|
1242
|
+
dividerSmall: {
|
|
1243
|
+
paddingTop: CustomTokens.dividerGapSmall,
|
|
1244
|
+
paddingBottom: CustomTokens.dividerGapSmall,
|
|
1245
|
+
},
|
|
1246
|
+
panelDiv: {
|
|
1247
|
+
display: "flex",
|
|
1248
|
+
flexDirection: "column",
|
|
1249
|
+
overflow: "hidden",
|
|
1250
|
+
},
|
|
1251
|
+
highlightDiv: {
|
|
1252
|
+
borderRadius: tokens.borderRadiusLarge,
|
|
1253
|
+
animationDuration: "1s",
|
|
1254
|
+
animationTimingFunction: "ease-in-out",
|
|
1255
|
+
animationIterationCount: "5",
|
|
1256
|
+
animationFillMode: "forwards",
|
|
1257
|
+
animationName: {
|
|
1258
|
+
from: {
|
|
1259
|
+
boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,
|
|
1260
|
+
},
|
|
1261
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1262
|
+
"50%": {
|
|
1263
|
+
boxShadow: `inset 0 0 12px ${tokens.colorBrandBackground}`,
|
|
1264
|
+
},
|
|
1265
|
+
to: {
|
|
1266
|
+
boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,
|
|
1267
|
+
},
|
|
1268
|
+
},
|
|
1269
|
+
},
|
|
1270
|
+
menuBar: {
|
|
1271
|
+
display: "flex",
|
|
1272
|
+
},
|
|
1273
|
+
menuBarControls: {
|
|
1274
|
+
display: "flex",
|
|
1275
|
+
flexGrow: 1,
|
|
1276
|
+
justifyContent: "end",
|
|
1277
|
+
},
|
|
1278
|
+
sectionEmpty: {
|
|
1279
|
+
display: "none",
|
|
1280
|
+
},
|
|
1281
|
+
sectionItemContainer: {
|
|
1282
|
+
display: "flex",
|
|
1283
|
+
flexDirection: "row",
|
|
1284
|
+
},
|
|
1285
|
+
sectionItemButtons: {
|
|
1286
|
+
display: "flex",
|
|
1287
|
+
flexDirection: "row",
|
|
1288
|
+
alignItems: "start",
|
|
1289
|
+
marginRight: tokens.spacingHorizontalXS,
|
|
1290
|
+
},
|
|
1291
|
+
pinnedContainer: {
|
|
1292
|
+
display: "flex",
|
|
1293
|
+
flexDirection: "column",
|
|
1294
|
+
},
|
|
1295
|
+
pinnedContainerEmpty: {
|
|
1296
|
+
"&:not(:only-child)": {
|
|
1297
|
+
display: "none",
|
|
1298
|
+
},
|
|
1299
|
+
},
|
|
1300
|
+
searchBox: {
|
|
1301
|
+
width: "100%",
|
|
1302
|
+
},
|
|
1303
|
+
});
|
|
1304
|
+
/**
|
|
1305
|
+
* Renders the menu bar and control buttons.
|
|
1306
|
+
*
|
|
1307
|
+
* @returns `div`, or `undefined` if all features are disabled.
|
|
1308
|
+
*/
|
|
1309
|
+
const AccordionMenuBar = () => {
|
|
1310
|
+
AccordionMenuBar.displayName = "AccordionMenuBar";
|
|
1311
|
+
const classes = useStyles$S();
|
|
1312
|
+
const accordionCtx = useContext(AccordionContext);
|
|
1313
|
+
if (!accordionCtx) {
|
|
1314
|
+
return null;
|
|
1315
|
+
}
|
|
1316
|
+
const { state, dispatch, features } = accordionCtx;
|
|
1317
|
+
const { editMode } = state;
|
|
1318
|
+
return (jsxs("div", { className: classes.menuBar, children: [jsx(AccordionSearchBox, {}), jsxs("div", { className: classes.menuBarControls, children: [features.hiding && editMode && (jsxs(Fragment, { children: [jsx(Button, { title: "Show all", icon: EyeFilled, appearance: "subtle", onClick: () => dispatch({ type: "SHOW_ALL" }) }), jsx(Button, { title: "Hide all", icon: EyeOffRegular, appearance: "subtle", onClick: () => {
|
|
1319
|
+
// Hide all visible items - we pass all non-hidden, matching items
|
|
1320
|
+
// For simplicity, we dispatch with an empty array; the actual filtering
|
|
1321
|
+
// would need to be done with knowledge of all registered items.
|
|
1322
|
+
// This is a limitation - in a full implementation, you'd track registered items.
|
|
1323
|
+
dispatch({ type: "HIDE_ALL_VISIBLE", visibleItemIds: [] });
|
|
1324
|
+
} })] })), (features.pinning || features.hiding) && (jsx(Button, { title: "Edit mode", icon: editMode ? CheckmarkFilled : EditRegular, appearance: editMode ? "primary" : "subtle", onClick: () => dispatch({ type: "SET_EDIT_MODE", enabled: !editMode }) }))] })] }));
|
|
1325
|
+
};
|
|
1326
|
+
/**
|
|
1327
|
+
* Wrapper component that must encapsulate the section headers and panels.
|
|
1328
|
+
* - Stores the section ID for use in `AccordionSectionItem`.
|
|
1329
|
+
*
|
|
1330
|
+
* @param props - `AccordionSectionBlockProps`
|
|
1331
|
+
* @returns `AccordionSectionBlockContext.Provider`, or `AccordionItem` if all features are disabled.
|
|
1332
|
+
*/
|
|
1333
|
+
const AccordionSectionBlock = (props) => {
|
|
1334
|
+
AccordionSectionBlock.displayName = "AccordionSectionBlock";
|
|
1335
|
+
const { children, sectionId } = props;
|
|
1336
|
+
const accordionCtx = useContext(AccordionContext);
|
|
1337
|
+
const sectionContext = useAccordionSectionBlockContext(props);
|
|
1338
|
+
if (accordionCtx) {
|
|
1339
|
+
return (jsx(AccordionSectionBlockContext.Provider, { value: sectionContext, children: jsx(AccordionItem, { value: sectionId, children: children }) }));
|
|
1340
|
+
}
|
|
1341
|
+
return jsx(AccordionItem, { value: sectionId, children: children });
|
|
1342
|
+
};
|
|
1343
|
+
/**
|
|
1344
|
+
* Wrapper component that must encapsulate individual items.
|
|
1345
|
+
* - Renders the pin button and tracks the pinned state of the item.
|
|
1346
|
+
* - Renders the hide button and tracks the hidden state of the item.
|
|
1347
|
+
* - Filters items based on the current search term.
|
|
1348
|
+
*
|
|
1349
|
+
* @param props - `AccordionSectionItemProps`
|
|
1350
|
+
* @returns `Portal` if pinned; `null` if hidden/filtered; `children` otherwise.
|
|
1351
|
+
*/
|
|
1352
|
+
const AccordionSectionItem = (props) => {
|
|
1353
|
+
AccordionSectionItem.displayName = "AccordionSectionItem";
|
|
1354
|
+
const { children, staticItem } = props;
|
|
1355
|
+
const classes = useStyles$S();
|
|
1356
|
+
const accordionCtx = useContext(AccordionContext);
|
|
1357
|
+
const itemState = useAccordionSectionItemState(props);
|
|
1358
|
+
const [ctrlMode, setCtrlMode] = useState(false);
|
|
1359
|
+
// If static item or no context, just render children
|
|
1360
|
+
if (staticItem || !accordionCtx || !itemState) {
|
|
1361
|
+
return jsx(Fragment, { children: children });
|
|
1362
|
+
}
|
|
1363
|
+
const { pinnedContainerRef, features } = accordionCtx;
|
|
1364
|
+
const { isNested, isPinned, isHidden, isMatch, pinnedIndex, inEditMode, actions } = itemState;
|
|
1365
|
+
// Nested items just render children (don't show controls)
|
|
1366
|
+
if (isNested) {
|
|
1367
|
+
return jsx(Fragment, { children: children });
|
|
1368
|
+
}
|
|
1369
|
+
// If hidden (and not in edit mode) or doesn't match search, don't render
|
|
1370
|
+
if ((isHidden && !inEditMode) || !isMatch) {
|
|
1371
|
+
return null;
|
|
1372
|
+
}
|
|
1373
|
+
const pinnedContainer = isPinned ? pinnedContainerRef.current : null;
|
|
1374
|
+
const showControls = inEditMode || ctrlMode;
|
|
1375
|
+
const onMouseMove = (e) => {
|
|
1376
|
+
if (e.ctrlKey !== ctrlMode) {
|
|
1377
|
+
setCtrlMode(e.ctrlKey);
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
const onMouseLeave = () => {
|
|
1381
|
+
if (ctrlMode) {
|
|
1382
|
+
setCtrlMode(false);
|
|
1383
|
+
}
|
|
1384
|
+
};
|
|
1385
|
+
const itemElement = (jsxs("div", { className: classes.sectionItemContainer, style: isPinned ? { order: pinnedIndex } : undefined, onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, children: [showControls && (jsxs("div", { className: classes.sectionItemButtons, children: [features.hiding && (jsx(Button, { title: isHidden ? "Unhide" : "Hide", icon: isHidden ? EyeOffRegular : EyeFilled, appearance: "transparent", onClick: actions.toggleHidden })), features.pinning && (jsxs(Fragment, { children: [jsx(Button, { title: isPinned ? "Unpin" : "Pin", icon: isPinned ? PinFilled : PinRegular, appearance: "transparent", onClick: actions.togglePinned }), isPinned && (jsx(Button, { title: "Move up", icon: ArrowCircleUpRegular, appearance: "transparent", disabled: pinnedIndex === 0, onClick: actions.movePinnedUp }))] }))] })), jsx(AccordionItemDepthContext.Provider, { value: true, children: children })] }));
|
|
1386
|
+
return pinnedContainer ? jsx(Portal, { mountNode: pinnedContainer, children: itemElement }) : itemElement;
|
|
1387
|
+
};
|
|
1388
|
+
/**
|
|
1389
|
+
* Renders the Pinned section container and defines the portal target for the pinned items.
|
|
1390
|
+
*
|
|
1391
|
+
* @returns `div`
|
|
1392
|
+
*/
|
|
1393
|
+
const AccordionPinnedContainer = () => {
|
|
1394
|
+
AccordionPinnedContainer.displayName = "AccordionPinnedContainer";
|
|
1395
|
+
const classes = useStyles$S();
|
|
1396
|
+
const accordionCtx = useContext(AccordionContext);
|
|
1397
|
+
return (jsx("div", { ref: accordionCtx?.pinnedContainerRef, className: classes.pinnedContainer, children: jsx(MessageBar$1, { className: classes.pinnedContainerEmpty, children: jsx(MessageBarBody, { children: "No pinned items" }) }) }));
|
|
1398
|
+
};
|
|
1399
|
+
/**
|
|
1400
|
+
* Renders the search box for filtering items.
|
|
1401
|
+
*
|
|
1402
|
+
* @returns `SearchBox`, or `null` if the feature is disabled.
|
|
1403
|
+
*/
|
|
1404
|
+
const AccordionSearchBox = () => {
|
|
1405
|
+
AccordionSearchBox.displayName = "AccordionSearchBox";
|
|
1406
|
+
const classes = useStyles$S();
|
|
1407
|
+
const accordionCtx = useContext(AccordionContext);
|
|
1408
|
+
if (!accordionCtx?.features.search) {
|
|
1409
|
+
return null;
|
|
1410
|
+
}
|
|
1411
|
+
const { state, dispatch } = accordionCtx;
|
|
1412
|
+
return (jsx(SearchBox$1, { className: classes.searchBox, appearance: "underline", contentBefore: jsx(FilterRegular, {}), placeholder: "Filter", value: state.searchTerm, onChange: (_, data) => dispatch({ type: "SET_SEARCH_TERM", term: data.value }) }));
|
|
1413
|
+
};
|
|
1414
|
+
/**
|
|
1415
|
+
* Wrapper component that must encapsulate the section body.
|
|
1416
|
+
*
|
|
1417
|
+
* @param props - `AccordionSectionProps`
|
|
1418
|
+
* @returns `div`
|
|
1419
|
+
*/
|
|
1420
|
+
const AccordionSection = (props) => {
|
|
1421
|
+
AccordionSection.displayName = "AccordionSection";
|
|
1422
|
+
const classes = useStyles$S();
|
|
1423
|
+
return jsx("div", { className: classes.panelDiv, children: props.children });
|
|
1424
|
+
};
|
|
1425
|
+
const StringAccordion = Accordion$1;
|
|
1426
|
+
const Accordion = forwardRef((props, ref) => {
|
|
1427
|
+
Accordion.displayName = "Accordion";
|
|
1428
|
+
const { children, highlightSections, ...rest } = props;
|
|
1429
|
+
const classes = useStyles$S();
|
|
1430
|
+
const { size } = useContext(ToolContext);
|
|
1431
|
+
const accordionCtx = useAccordionContext(props);
|
|
1432
|
+
const hasPinning = accordionCtx?.features.pinning ?? false;
|
|
1433
|
+
const pinnedSectionElement = useMemo(() => {
|
|
1434
|
+
return (hasPinning && (jsx(AccordionSection, { title: "Pinned", collapseByDefault: false, children: jsx(AccordionPinnedContainer, {}) })));
|
|
1435
|
+
}, [hasPinning]);
|
|
1436
|
+
// Prevents sections contents from unmounting when closed, allowing their elements to be used in the Pinned section.
|
|
1437
|
+
const preventUnmountMotion = useMemo(() => {
|
|
1438
|
+
// https://github.com/microsoft/fluentui/issues/34309#issuecomment-2824364945
|
|
1439
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1440
|
+
return hasPinning ? { children: (Component, props) => jsx(Component, { ...props, unmountOnExit: false }) } : undefined;
|
|
1441
|
+
}, [hasPinning]);
|
|
1442
|
+
const validChildren = useMemo(() => {
|
|
1443
|
+
return (Children.map([pinnedSectionElement, children], (child) => {
|
|
1444
|
+
if (isValidElement(child)) {
|
|
1445
|
+
const childProps = child.props;
|
|
1446
|
+
if (childProps.title) {
|
|
1447
|
+
return {
|
|
1448
|
+
title: childProps.title,
|
|
1449
|
+
collapseByDefault: childProps.collapseByDefault,
|
|
1450
|
+
content: child,
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
return null;
|
|
1455
|
+
})?.filter(Boolean) ?? []);
|
|
1456
|
+
}, [children]);
|
|
1457
|
+
// Tracks open items, and used to tell the Accordion which sections should be expanded.
|
|
1458
|
+
const [openItems, setOpenItems] = useState(validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title));
|
|
1459
|
+
// Tracks closed items, which is needed so that when the children change, we only update the open/closed state
|
|
1460
|
+
// (depending on the collapseByDefault prop) for items that have not been explicitly opened or closed.
|
|
1461
|
+
const [closedItems, setClosedItems] = useState(validChildren.filter((child) => child.collapseByDefault).map((child) => child.title));
|
|
1462
|
+
const internalOpenItemsRef = useRef(openItems);
|
|
1463
|
+
// When highlight sections is requested, we temporarily override the open items, but if highlight sections is cleared,
|
|
1464
|
+
// then we revert back to the normal open items tracking.
|
|
1465
|
+
useLayoutEffect(() => {
|
|
1466
|
+
if (highlightSections) {
|
|
1467
|
+
internalOpenItemsRef.current = [...openItems];
|
|
1468
|
+
setOpenItems([...highlightSections]);
|
|
1469
|
+
}
|
|
1470
|
+
else {
|
|
1471
|
+
setOpenItems([...(internalOpenItemsRef.current ?? [])]);
|
|
1472
|
+
internalOpenItemsRef.current = undefined;
|
|
1473
|
+
}
|
|
1474
|
+
}, [highlightSections]);
|
|
1475
|
+
useEffect(() => {
|
|
1476
|
+
for (const defaultOpenItem of validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title)) {
|
|
1477
|
+
// If a child is not marked as collapseByDefault, then it should be opened by default, and
|
|
1478
|
+
// it is only "default" if it hasn't already been explicitly added to the opened or closed list.
|
|
1479
|
+
if (!closedItems.includes(defaultOpenItem) && !openItems.includes(defaultOpenItem)) {
|
|
1480
|
+
setOpenItems((prev) => [...prev, defaultOpenItem]);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}, [validChildren]);
|
|
1484
|
+
const onToggle = useCallback((event, data) => {
|
|
1485
|
+
if (data.openItems.includes(data.value)) {
|
|
1486
|
+
setOpenItems((prev) => [...prev, data.value]);
|
|
1487
|
+
setClosedItems((prev) => prev.filter((item) => item !== data.value));
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
setClosedItems((prev) => [...prev, data.value]);
|
|
1491
|
+
setOpenItems((prev) => prev.filter((item) => item !== data.value));
|
|
1492
|
+
}
|
|
1493
|
+
}, []);
|
|
1494
|
+
return (jsx(StringAccordion, { ref: ref, className: classes.accordion, collapsible: true, multiple: true, onToggle: onToggle, openItems: openItems, ...rest, children: jsxs(AccordionContext.Provider, { value: accordionCtx, children: [jsx(AccordionMenuBar, {}), jsx("div", { className: classes.accordionBody, children: validChildren.map((child, index) => {
|
|
1495
|
+
const isHighlighted = highlightSections?.includes(child.title);
|
|
1496
|
+
return (jsxs(AccordionSectionBlock, { sectionId: child.title, children: [jsxs("div", { className: isHighlighted ? classes.highlightDiv : undefined, children: [jsx(AccordionHeader, { size: size, children: jsx(Subtitle2Stronger, { children: child.title }) }), jsx(AccordionPanel, { collapseMotion: preventUnmountMotion, children: jsx("div", { className: classes.panelDiv, children: child.content }) })] }), index < validChildren.length - 1 && jsx(Divider, { inset: true, className: size === "small" ? classes.dividerSmall : classes.divider })] }, child.content.key ?? child.title));
|
|
1497
|
+
}) })] }) }));
|
|
1498
|
+
});
|
|
1499
|
+
|
|
1021
1500
|
const useCollapseStyles = makeStyles({
|
|
1022
1501
|
collapseContent: {
|
|
1023
1502
|
overflow: "hidden",
|
|
@@ -1039,7 +1518,9 @@ const useCollapseStyles = makeStyles({
|
|
|
1039
1518
|
const Collapse = (props) => {
|
|
1040
1519
|
Collapse.displayName = "Collapse";
|
|
1041
1520
|
const classes = useCollapseStyles();
|
|
1042
|
-
|
|
1521
|
+
// Since portalling breaks DOM hierarchy, `unmountOnExit` is required to ensure descendants are unmounted when the logical ancestor collapses.
|
|
1522
|
+
// If this is a breaking change, the alternative would be creating a context to pass the `visible` state down to the descendants.
|
|
1523
|
+
return (jsx(Collapse$1, { visible: props.visible, orientation: props.orientation, unmountOnExit: true, children: jsx("div", { className: `${classes.collapseContent} ${props.orientation === "horizontal" ? classes.horizontal : classes.vertical}`, children: props.children }) }));
|
|
1043
1524
|
};
|
|
1044
1525
|
|
|
1045
1526
|
const Link = forwardRef((props, ref) => {
|
|
@@ -1050,7 +1531,7 @@ const Link = forwardRef((props, ref) => {
|
|
|
1050
1531
|
});
|
|
1051
1532
|
Link.displayName = "Link";
|
|
1052
1533
|
|
|
1053
|
-
const useStyles$
|
|
1534
|
+
const useStyles$R = makeStyles({
|
|
1054
1535
|
button: {
|
|
1055
1536
|
display: "flex",
|
|
1056
1537
|
alignItems: "center",
|
|
@@ -1068,7 +1549,7 @@ const ToggleButton = (props) => {
|
|
|
1068
1549
|
ToggleButton.displayName = "ToggleButton";
|
|
1069
1550
|
const { value, onChange, title, appearance = "subtle" } = props;
|
|
1070
1551
|
const { size } = useContext(ToolContext);
|
|
1071
|
-
const classes = useStyles$
|
|
1552
|
+
const classes = useStyles$R();
|
|
1072
1553
|
const [checked, setChecked] = useState(value);
|
|
1073
1554
|
const toggle = useCallback(() => {
|
|
1074
1555
|
setChecked((prev) => {
|
|
@@ -1098,7 +1579,7 @@ const useInfoLabelStyles = makeStyles({
|
|
|
1098
1579
|
textOverflow: "ellipsis",
|
|
1099
1580
|
},
|
|
1100
1581
|
copyable: {
|
|
1101
|
-
cursor: "
|
|
1582
|
+
cursor: "pointer",
|
|
1102
1583
|
},
|
|
1103
1584
|
});
|
|
1104
1585
|
/**
|
|
@@ -1224,7 +1705,7 @@ const PropertyLine = forwardRef((props, ref) => {
|
|
|
1224
1705
|
PropertyLine.displayName = "PropertyLine";
|
|
1225
1706
|
const { disableCopy, size } = useContext(ToolContext);
|
|
1226
1707
|
const classes = usePropertyLineStyles();
|
|
1227
|
-
const { label, onCopy, expandedContent, children, nullable, ignoreNullable } = props;
|
|
1708
|
+
const { label, uniqueId, onCopy, expandedContent, children, nullable, ignoreNullable } = props;
|
|
1228
1709
|
const [expanded, setExpanded] = useState("expandByDefault" in props ? props.expandByDefault : false);
|
|
1229
1710
|
const cachedVal = useRef(nullable ? props.value : null);
|
|
1230
1711
|
const { showToast } = useToast();
|
|
@@ -1248,7 +1729,7 @@ const PropertyLine = forwardRef((props, ref) => {
|
|
|
1248
1729
|
defaultValue: undefined, // Don't pass defaultValue to children as there is no guarantee how this will be used and we can't mix controlled + uncontrolled state
|
|
1249
1730
|
})
|
|
1250
1731
|
: children;
|
|
1251
|
-
return (jsxs(LineContainer, { ref: ref, children: [jsxs("div", { className: classes.baseLine, children: [jsx(InfoLabel, { className: classes.infoLabel, htmlFor: "property", info: description, label: label, flexLabel: true, onContextMenu: onCopy ? handleContextMenu : undefined }), jsxs("div", { className: classes.rightContent, id: "property", children: [expandedContent && (jsx(ToggleButton, { title: "Expand/Collapse property", appearance: "transparent", checkedIcon: size === "small" ? ChevronCircleDown16Regular : ChevronCircleDown20Regular, uncheckedIcon: size === "small" ? ChevronCircleRight16Regular : ChevronCircleRight20Regular, value: expanded === true, onChange: setExpanded })), nullable && !ignoreNullable && (
|
|
1732
|
+
return (jsxs(LineContainer, { ref: ref, uniqueId: uniqueId ?? label, label: label, children: [jsxs("div", { className: classes.baseLine, children: [jsx(InfoLabel, { className: classes.infoLabel, htmlFor: "property", info: description, label: label, flexLabel: true, onContextMenu: onCopy ? handleContextMenu : undefined }), jsxs("div", { className: classes.rightContent, id: "property", children: [expandedContent && (jsx(ToggleButton, { title: "Expand/Collapse property", appearance: "transparent", checkedIcon: size === "small" ? ChevronCircleDown16Regular : ChevronCircleDown20Regular, uncheckedIcon: size === "small" ? ChevronCircleRight16Regular : ChevronCircleRight20Regular, value: expanded === true, onChange: setExpanded })), nullable && !ignoreNullable && (
|
|
1252
1733
|
// If this is a nullableProperty and ignoreNullable was not sent, display a checkbox used to toggle null ('checked' means 'non null')
|
|
1253
1734
|
jsx(Tooltip, { content: props.value == null ? "Enable property" : "Disable property (set to null)", children: jsx(Checkbox$1, { className: classes.checkbox, indicator: { className: classes.checkboxIndicator }, checked: !(props.value == null), onChange: (_, data) => {
|
|
1254
1735
|
if (data.checked) {
|
|
@@ -1285,8 +1766,9 @@ const useLineStyles = makeStyles({
|
|
|
1285
1766
|
});
|
|
1286
1767
|
const LineContainer = forwardRef((props, ref) => {
|
|
1287
1768
|
const { size } = useContext(ToolContext);
|
|
1769
|
+
const { children, uniqueId, label, ...rest } = props;
|
|
1288
1770
|
const classes = useLineStyles();
|
|
1289
|
-
return (jsx("div", { ref: ref, className: mergeClasses(classes.container, size == "small" ? classes.containerSmall : undefined), ...
|
|
1771
|
+
return (jsx(AccordionSectionItem, { uniqueId: uniqueId, label: label, children: jsx("div", { ref: ref, className: mergeClasses(classes.container, size == "small" ? classes.containerSmall : undefined), ...rest, children: children }) }));
|
|
1290
1772
|
});
|
|
1291
1773
|
const PlaceholderPropertyLine = (props) => {
|
|
1292
1774
|
return (jsx(PropertyLine, { ...props, children: jsx(Body1, { children: props.value }) }));
|
|
@@ -1317,117 +1799,6 @@ const LinkToEntityPropertyLine = (props) => {
|
|
|
1317
1799
|
!linkedEntity.reservedDataStore?.hidden && jsx(LinkPropertyLine, { ...rest, value: linkedEntity.name, onLink: () => (selectionService.selectedEntity = linkedEntity) }));
|
|
1318
1800
|
};
|
|
1319
1801
|
|
|
1320
|
-
const useStyles$R = makeStyles({
|
|
1321
|
-
accordion: {
|
|
1322
|
-
overflowX: "hidden",
|
|
1323
|
-
overflowY: "auto",
|
|
1324
|
-
paddingBottom: tokens.spacingVerticalM, // bottom padding since there is no divider at the bottom
|
|
1325
|
-
display: "flex",
|
|
1326
|
-
flexDirection: "column",
|
|
1327
|
-
height: "100%",
|
|
1328
|
-
},
|
|
1329
|
-
divider: {
|
|
1330
|
-
paddingTop: CustomTokens.dividerGap,
|
|
1331
|
-
paddingBottom: CustomTokens.dividerGap,
|
|
1332
|
-
},
|
|
1333
|
-
dividerSmall: {
|
|
1334
|
-
paddingTop: CustomTokens.dividerGapSmall,
|
|
1335
|
-
paddingBottom: CustomTokens.dividerGapSmall,
|
|
1336
|
-
},
|
|
1337
|
-
panelDiv: {
|
|
1338
|
-
display: "flex",
|
|
1339
|
-
flexDirection: "column",
|
|
1340
|
-
overflow: "hidden",
|
|
1341
|
-
},
|
|
1342
|
-
highlightDiv: {
|
|
1343
|
-
borderRadius: tokens.borderRadiusLarge,
|
|
1344
|
-
animationDuration: "1s",
|
|
1345
|
-
animationTimingFunction: "ease-in-out",
|
|
1346
|
-
animationIterationCount: "5",
|
|
1347
|
-
animationFillMode: "forwards",
|
|
1348
|
-
animationName: {
|
|
1349
|
-
from: {
|
|
1350
|
-
boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,
|
|
1351
|
-
},
|
|
1352
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1353
|
-
"50%": {
|
|
1354
|
-
boxShadow: `inset 0 0 12px ${tokens.colorBrandBackground}`,
|
|
1355
|
-
},
|
|
1356
|
-
to: {
|
|
1357
|
-
boxShadow: `inset 0 0 4px ${tokens.colorTransparentBackground}`,
|
|
1358
|
-
},
|
|
1359
|
-
},
|
|
1360
|
-
},
|
|
1361
|
-
});
|
|
1362
|
-
const AccordionSection = (props) => {
|
|
1363
|
-
AccordionSection.displayName = "AccordionSection";
|
|
1364
|
-
const classes = useStyles$R();
|
|
1365
|
-
return jsx("div", { className: classes.panelDiv, children: props.children });
|
|
1366
|
-
};
|
|
1367
|
-
const StringAccordion = Accordion$1;
|
|
1368
|
-
const Accordion = forwardRef((props, ref) => {
|
|
1369
|
-
Accordion.displayName = "Accordion";
|
|
1370
|
-
const classes = useStyles$R();
|
|
1371
|
-
const { size } = useContext(ToolContext);
|
|
1372
|
-
const { children, highlightSections, ...rest } = props;
|
|
1373
|
-
const validChildren = useMemo(() => {
|
|
1374
|
-
return (Children.map(children, (child) => {
|
|
1375
|
-
if (isValidElement(child)) {
|
|
1376
|
-
const childProps = child.props;
|
|
1377
|
-
if (childProps.title) {
|
|
1378
|
-
return {
|
|
1379
|
-
title: childProps.title,
|
|
1380
|
-
collapseByDefault: childProps.collapseByDefault,
|
|
1381
|
-
content: child,
|
|
1382
|
-
};
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
return null;
|
|
1386
|
-
})?.filter(Boolean) ?? []);
|
|
1387
|
-
}, [children]);
|
|
1388
|
-
// Tracks open items, and used to tell the Accordion which sections should be expanded.
|
|
1389
|
-
const [openItems, setOpenItems] = useState(validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title));
|
|
1390
|
-
// Tracks closed items, which is needed so that when the children change, we only update the open/closed state
|
|
1391
|
-
// (depending on the collapseByDefault prop) for items that have not been explicitly opened or closed.
|
|
1392
|
-
const [closedItems, setClosedItems] = useState(validChildren.filter((child) => child.collapseByDefault).map((child) => child.title));
|
|
1393
|
-
const internalOpenItemsRef = useRef(openItems);
|
|
1394
|
-
// When highlight sections is requested, we temporarily override the open items, but if highlight sections is cleared,
|
|
1395
|
-
// then we revert back to the normal open items tracking.
|
|
1396
|
-
useLayoutEffect(() => {
|
|
1397
|
-
if (highlightSections) {
|
|
1398
|
-
internalOpenItemsRef.current = [...openItems];
|
|
1399
|
-
setOpenItems([...highlightSections]);
|
|
1400
|
-
}
|
|
1401
|
-
else {
|
|
1402
|
-
setOpenItems([...(internalOpenItemsRef.current ?? [])]);
|
|
1403
|
-
internalOpenItemsRef.current = undefined;
|
|
1404
|
-
}
|
|
1405
|
-
}, [highlightSections]);
|
|
1406
|
-
useEffect(() => {
|
|
1407
|
-
for (const defaultOpenItem of validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title)) {
|
|
1408
|
-
// If a child is not marked as collapseByDefault, then it should be opened by default, and
|
|
1409
|
-
// it is only "default" if it hasn't already been explicitly added to the opened or closed list.
|
|
1410
|
-
if (!closedItems.includes(defaultOpenItem) && !openItems.includes(defaultOpenItem)) {
|
|
1411
|
-
setOpenItems((prev) => [...prev, defaultOpenItem]);
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
}, [validChildren]);
|
|
1415
|
-
const onToggle = useCallback((event, data) => {
|
|
1416
|
-
if (data.openItems.includes(data.value)) {
|
|
1417
|
-
setOpenItems((prev) => [...prev, data.value]);
|
|
1418
|
-
setClosedItems((prev) => prev.filter((item) => item !== data.value));
|
|
1419
|
-
}
|
|
1420
|
-
else {
|
|
1421
|
-
setClosedItems((prev) => [...prev, data.value]);
|
|
1422
|
-
setOpenItems((prev) => prev.filter((item) => item !== data.value));
|
|
1423
|
-
}
|
|
1424
|
-
}, []);
|
|
1425
|
-
return (jsx(StringAccordion, { ref: ref, className: classes.accordion, collapsible: true, multiple: true, onToggle: onToggle, openItems: openItems, ...rest, children: validChildren.map((child, index) => {
|
|
1426
|
-
const isHighlighted = highlightSections?.includes(child.title);
|
|
1427
|
-
return (jsxs(AccordionItem, { value: child.title, children: [jsxs("div", { className: isHighlighted ? classes.highlightDiv : undefined, children: [jsx(AccordionHeader, { size: size, children: jsx(Subtitle2Stronger, { children: child.title }) }), jsx(AccordionPanel, { children: jsx("div", { className: classes.panelDiv, children: child.content }) })] }), index < validChildren.length - 1 && jsx(Divider, { inset: true, className: size === "small" ? classes.dividerSmall : classes.divider })] }, child.content.key ?? child.title));
|
|
1428
|
-
}) }));
|
|
1429
|
-
});
|
|
1430
|
-
|
|
1431
1802
|
const CompactModeStorageKey = "Babylon/Settings/IsCompactMode";
|
|
1432
1803
|
const SidePaneDockOverridesStorageKey = "Babylon/Settings/SidePaneDockOverrides";
|
|
1433
1804
|
const DisableCopyStorageKey = "Babylon/Settings/DisableCopy";
|
|
@@ -1517,7 +1888,7 @@ const useStyles$Q = makeStyles({
|
|
|
1517
1888
|
});
|
|
1518
1889
|
function ExtensibleAccordion(props) {
|
|
1519
1890
|
const classes = useStyles$Q();
|
|
1520
|
-
const { children, sections, sectionContent, context, sectionsRef } = props;
|
|
1891
|
+
const { children, sections, sectionContent, context, sectionsRef, ...rest } = props;
|
|
1521
1892
|
const defaultSections = useMemo(() => {
|
|
1522
1893
|
const defaultSections = [];
|
|
1523
1894
|
if (children) {
|
|
@@ -1616,7 +1987,7 @@ function ExtensibleAccordion(props) {
|
|
|
1616
1987
|
},
|
|
1617
1988
|
};
|
|
1618
1989
|
}, []);
|
|
1619
|
-
return (jsx("div", { className: classes.rootDiv, children: visibleSections.length > -1 && (jsx(UXContextProvider, { children: jsxs(Accordion, { highlightSections: highlightSections, children: [...visibleSections.map((section) => {
|
|
1990
|
+
return (jsx("div", { className: classes.rootDiv, children: visibleSections.length > -1 && (jsx(UXContextProvider, { children: jsxs(Accordion, { highlightSections: highlightSections, ...rest, children: [...visibleSections.map((section) => {
|
|
1620
1991
|
return (jsx(AccordionSection, { title: section.identity, collapseByDefault: section.collapseByDefault, children: section.components }, section.identity));
|
|
1621
1992
|
})] }) })) }));
|
|
1622
1993
|
}
|
|
@@ -2249,16 +2620,17 @@ const useStyles$M = makeStyles({
|
|
|
2249
2620
|
bar: {
|
|
2250
2621
|
display: "flex",
|
|
2251
2622
|
flex: "1",
|
|
2252
|
-
height: "32px",
|
|
2253
2623
|
overflow: "hidden",
|
|
2254
2624
|
padding: `${tokens.spacingVerticalXXS} ${tokens.spacingHorizontalXXS}`,
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
backgroundColor: tokens.colorNeutralBackground1,
|
|
2625
|
+
borderBottom: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2626
|
+
backgroundColor: tokens.colorNeutralBackground2,
|
|
2258
2627
|
},
|
|
2259
2628
|
barTop: {
|
|
2260
2629
|
borderTopWidth: 0,
|
|
2261
2630
|
},
|
|
2631
|
+
barBottom: {
|
|
2632
|
+
borderTop: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2633
|
+
},
|
|
2262
2634
|
barLeft: {
|
|
2263
2635
|
marginRight: "auto",
|
|
2264
2636
|
display: "flex",
|
|
@@ -2277,7 +2649,7 @@ const useStyles$M = makeStyles({
|
|
|
2277
2649
|
display: "flex",
|
|
2278
2650
|
},
|
|
2279
2651
|
paneTabListDiv: {
|
|
2280
|
-
backgroundColor: tokens.
|
|
2652
|
+
backgroundColor: tokens.colorNeutralBackground1,
|
|
2281
2653
|
flex: "0 0 auto",
|
|
2282
2654
|
display: "flex",
|
|
2283
2655
|
},
|
|
@@ -2288,7 +2660,11 @@ const useStyles$M = makeStyles({
|
|
|
2288
2660
|
flexDirection: "row",
|
|
2289
2661
|
},
|
|
2290
2662
|
paneCollapseButton: {
|
|
2291
|
-
|
|
2663
|
+
padding: `0 0 0 ${tokens.spacingHorizontalXS}`,
|
|
2664
|
+
borderBottom: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2665
|
+
},
|
|
2666
|
+
paneCollapseButtonWithBorder: {
|
|
2667
|
+
borderLeft: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2292
2668
|
},
|
|
2293
2669
|
collapseMenuPopover: {
|
|
2294
2670
|
minWidth: 0,
|
|
@@ -2330,7 +2706,6 @@ const useStyles$M = makeStyles({
|
|
|
2330
2706
|
height: "36px",
|
|
2331
2707
|
backgroundColor: tokens.colorNeutralBackground1,
|
|
2332
2708
|
color: tokens.colorNeutralForeground1,
|
|
2333
|
-
border: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2334
2709
|
},
|
|
2335
2710
|
paneHeaderText: {
|
|
2336
2711
|
flex: 1,
|
|
@@ -2349,29 +2724,33 @@ const useStyles$M = makeStyles({
|
|
|
2349
2724
|
},
|
|
2350
2725
|
tabToolbar: {
|
|
2351
2726
|
padding: 0,
|
|
2727
|
+
borderLeft: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2728
|
+
borderRight: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2352
2729
|
},
|
|
2353
2730
|
tab: {
|
|
2354
2731
|
display: "flex",
|
|
2355
2732
|
height: "100%",
|
|
2356
|
-
|
|
2733
|
+
boxSizing: "border-box",
|
|
2357
2734
|
justifyContent: "center",
|
|
2358
|
-
|
|
2359
|
-
|
|
2735
|
+
border: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2736
|
+
borderTop: "none",
|
|
2737
|
+
},
|
|
2738
|
+
firstTab: {
|
|
2739
|
+
borderLeftColor: "transparent",
|
|
2740
|
+
},
|
|
2741
|
+
lastTab: {
|
|
2742
|
+
borderRightColor: "transparent",
|
|
2360
2743
|
},
|
|
2361
2744
|
selectedTab: {
|
|
2362
|
-
backgroundColor: tokens.colorNeutralBackground1,
|
|
2363
|
-
color: tokens.colorNeutralForeground1,
|
|
2364
|
-
border: `1px solid ${tokens.colorNeutralStroke2}`,
|
|
2365
2745
|
borderBottom: "none",
|
|
2366
2746
|
},
|
|
2367
2747
|
unselectedTab: {
|
|
2368
|
-
|
|
2748
|
+
borderLeftColor: "transparent",
|
|
2749
|
+
borderRightColor: "transparent",
|
|
2369
2750
|
},
|
|
2370
2751
|
tabRadioButton: {
|
|
2371
2752
|
backgroundColor: "transparent",
|
|
2372
|
-
|
|
2373
|
-
selectedTabIcon: {
|
|
2374
|
-
color: "inherit",
|
|
2753
|
+
borderRadius: 0,
|
|
2375
2754
|
},
|
|
2376
2755
|
resizer: {
|
|
2377
2756
|
width: "8px",
|
|
@@ -2435,19 +2814,18 @@ const Toolbar = ({ location, components }) => {
|
|
|
2435
2814
|
const classes = useStyles$M();
|
|
2436
2815
|
const leftComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "left"), [components]);
|
|
2437
2816
|
const rightComponents = useMemo(() => components.filter((entry) => entry.horizontalLocation === "right"), [components]);
|
|
2438
|
-
return (jsx(Fragment, { children: components.length > 0 && (jsxs("div", { className: `${classes.bar} ${location === "top" ? classes.barTop :
|
|
2817
|
+
return (jsx(Fragment, { children: components.length > 0 && (jsxs("div", { className: `${classes.bar} ${location === "top" ? classes.barTop : classes.barBottom}`, children: [jsx("div", { className: classes.barLeft, children: leftComponents.map((entry) => (jsx(ToolbarItem, { verticalLocation: location, horizontalLocation: entry.horizontalLocation, id: entry.key, component: entry.component, displayName: entry.displayName, 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))) })] })) }));
|
|
2439
2818
|
};
|
|
2440
2819
|
// This is a wrapper for a tab in a side pane that simply adds a teaching moment, which is useful for dynamically added items, possibly from extensions.
|
|
2441
2820
|
const SidePaneTab = (props) => {
|
|
2442
|
-
const { location, id, isSelected, dockOptions,
|
|
2821
|
+
const { location, id, isSelected, isFirst, isLast, dockOptions,
|
|
2443
2822
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
2444
2823
|
icon: Icon, title, suppressTeachingMoment, } = props;
|
|
2445
2824
|
const classes = useStyles$M();
|
|
2446
2825
|
const useTeachingMoment = useMemo(() => MakePopoverTeachingMoment(`Pane/${location}/${title ?? id}`), [title, id]);
|
|
2447
2826
|
const teachingMoment = useTeachingMoment(suppressTeachingMoment);
|
|
2448
|
-
const tabClass = mergeClasses(classes.tab, isSelected ? classes.selectedTab : classes.unselectedTab);
|
|
2827
|
+
const tabClass = mergeClasses(classes.tab, isSelected ? classes.selectedTab : classes.unselectedTab, isFirst ? classes.firstTab : undefined, isLast ? classes.lastTab : undefined);
|
|
2449
2828
|
return (jsxs(Fragment, { children: [jsx(TeachingMoment, { ...teachingMoment, shouldDisplay: teachingMoment.shouldDisplay && !suppressTeachingMoment, title: title ?? "Extension", description: `The "${title ?? id}" extension can be accessed here.` }), jsx("div", { className: tabClass, children: jsx(DockMenu, { openOnContext: true, sidePaneId: id, dockOptions: dockOptions, children: jsx(Tooltip, { content: title ?? id, children: jsx(ToolbarRadioButton, { ref: teachingMoment.targetRef, appearance: "transparent", className: classes.tabRadioButton, name: "selectedTab", value: id, icon: {
|
|
2450
|
-
className: isSelected ? classes.selectedTabIcon : undefined,
|
|
2451
2829
|
children: jsx(Icon, {}),
|
|
2452
2830
|
} }) }) }) })] }));
|
|
2453
2831
|
};
|
|
@@ -2548,17 +2926,17 @@ function usePane(location, defaultWidth, minWidth, sidePanes, onSelectSidePane,
|
|
|
2548
2926
|
}, [childWindow, location]);
|
|
2549
2927
|
const expandCollapseButton = useMemo(() => {
|
|
2550
2928
|
const expandCollapseIcon = location === "left" ? collapsed ? jsx(PanelLeftExpandRegular, {}) : jsx(PanelLeftContractRegular, {}) : collapsed ? jsx(PanelRightExpandRegular, {}) : jsx(PanelRightContractRegular, {});
|
|
2551
|
-
return (jsxs(Menu, { positioning: "below-end", children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: (triggerProps) => (jsx(Tooltip, { content: collapsed ? "Show Side Pane" : "Hide Side Pane", children: jsx(SplitButton, { className: classes.paneCollapseButton, menuButton: triggerProps, primaryActionButton: { onClick: onExpandCollapseClick }, size: "small", appearance: "transparent", icon: expandCollapseIcon }) })) }), jsx(MenuPopover, { className: classes.collapseMenuPopover, children: jsx(MenuList, { children: jsx(MenuItem, { icon: jsx(PictureInPictureEnterRegular, {}), onClick: () => setUndocked(true), children: "Undock" }) }) })] }));
|
|
2929
|
+
return (jsxs(Menu, { positioning: "below-end", children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: (triggerProps) => (jsx(Tooltip, { content: collapsed ? "Show Side Pane" : "Hide Side Pane", children: jsx(SplitButton, { className: mergeClasses(classes.paneCollapseButton, location === "right" && toolbarMode === "compact" ? classes.paneCollapseButtonWithBorder : undefined), menuButton: triggerProps, primaryActionButton: { onClick: onExpandCollapseClick }, size: "small", appearance: "transparent", icon: expandCollapseIcon }) })) }), jsx(MenuPopover, { className: classes.collapseMenuPopover, children: jsx(MenuList, { children: jsx(MenuItem, { icon: jsx(PictureInPictureEnterRegular, {}), onClick: () => setUndocked(true), children: "Undock" }) }) })] }));
|
|
2552
2930
|
}, [collapsed, onExpandCollapseClick, location]);
|
|
2553
2931
|
const createPaneTabList = useCallback((paneComponents, toolbarMode, selectedTab, setSelectedTab, dockOptions) => {
|
|
2554
2932
|
return (jsx(Fragment, { children: paneComponents.length > 0 && (jsxs("div", { className: `${classes.paneTabListDiv} ${location === "left" || toolbarMode === "compact" ? classes.paneTabListDivLeft : classes.paneTabListDivRight}`, children: [paneComponents.length > 1 && (jsx(Fragment, { children: jsx(Toolbar$1, { className: classes.tabToolbar, checkedValues: { selectedTab: [selectedTab?.key ?? ""] }, onCheckedValueChange: (event, data) => {
|
|
2555
2933
|
const tab = paneComponents.find((entry) => entry.key === data.checkedItems[0]);
|
|
2556
2934
|
setSelectedTab(tab);
|
|
2557
2935
|
setCollapsed(false);
|
|
2558
|
-
}, children: paneComponents.map((entry) => {
|
|
2936
|
+
}, children: paneComponents.map((entry, index) => {
|
|
2559
2937
|
const isSelected = selectedTab?.key === entry.key;
|
|
2560
|
-
return (jsx(SidePaneTab, { location: location, id: entry.key, title: entry.title, icon: entry.icon, suppressTeachingMoment: entry.suppressTeachingMoment, isSelected: isSelected && !collapsed, dockOptions: dockOptions }, entry.key));
|
|
2561
|
-
}) }) })), toolbarMode === "full" && (
|
|
2938
|
+
return (jsx(SidePaneTab, { location: location, id: entry.key, title: entry.title, icon: entry.icon, suppressTeachingMoment: entry.suppressTeachingMoment, isSelected: isSelected && !collapsed, isFirst: index === 0, isLast: index === paneComponents.length - 1, dockOptions: dockOptions }, entry.key));
|
|
2939
|
+
}) }) })), toolbarMode === "full" && (jsx(Collapse, { visible: !isChildWindowOpen, orientation: "horizontal", children: expandCollapseButton }))] })) }));
|
|
2562
2940
|
}, [location, collapsed, isChildWindowOpen, expandCollapseButton]);
|
|
2563
2941
|
// This memos the TabList to make it easy for the JSX to be inserted at the top of the pane (in "compact" mode) or returned to the caller to be used in the toolbar (in "full" mode).
|
|
2564
2942
|
const topPaneTabList = useMemo(() => createPaneTabList(topPanes, toolbarMode, topSelectedTab, setTopSelectedTab, validTopDockOptions), [createPaneTabList, topPanes, toolbarMode, topSelectedTab]);
|
|
@@ -2939,7 +3317,7 @@ const PropertiesServiceDefinition = {
|
|
|
2939
3317
|
setPendingHighlight(undefined);
|
|
2940
3318
|
}
|
|
2941
3319
|
}, [pendingHighlight]);
|
|
2942
|
-
return (jsx(PropertyContext.Provider, { value: { onPropertyChanged }, children: jsx(PropertiesPane, { sections: sections, sectionContent: applicableContent, context: entity, sectionsRef: sectionsRef }) }));
|
|
3320
|
+
return (jsx(PropertyContext.Provider, { value: { onPropertyChanged }, children: jsx(PropertiesPane, { uniqueId: "Properties", sections: sections, sectionContent: applicableContent, context: entity, sectionsRef: sectionsRef, enablePinnedItems: true, enableHiddenItems: true, enableSearchItems: true }) }));
|
|
2943
3321
|
},
|
|
2944
3322
|
});
|
|
2945
3323
|
return {
|
|
@@ -3807,7 +4185,7 @@ const DebugServiceDefinition = {
|
|
|
3807
4185
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
3808
4186
|
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
3809
4187
|
const scene = useObservableState(() => sceneContext.currentScene, sceneContext.currentSceneObservable);
|
|
3810
|
-
return jsx(Fragment, { children: scene && jsx(DebugPane, { sections: sections, sectionContent: sectionContent, context: scene }) });
|
|
4188
|
+
return (jsx(Fragment, { children: scene && (jsx(DebugPane, { uniqueId: "Debug", sections: sections, sectionContent: sectionContent, context: scene, enablePinnedItems: true, enableHiddenItems: true, enableSearchItems: true })) }));
|
|
3811
4189
|
},
|
|
3812
4190
|
});
|
|
3813
4191
|
return {
|
|
@@ -3825,7 +4203,7 @@ const DebugServiceDefinition = {
|
|
|
3825
4203
|
*/
|
|
3826
4204
|
const ButtonLine = (props) => {
|
|
3827
4205
|
ButtonLine.displayName = "ButtonLine";
|
|
3828
|
-
return (jsx(LineContainer, { children: jsx(Button, { ...props }) }));
|
|
4206
|
+
return (jsx(LineContainer, { uniqueId: props.uniqueId ?? props.label, children: jsx(Button, { ...props }) }));
|
|
3829
4207
|
};
|
|
3830
4208
|
|
|
3831
4209
|
const SettingsServiceIdentity = Symbol("SettingsService");
|
|
@@ -4022,7 +4400,7 @@ const UploadButton = (props) => {
|
|
|
4022
4400
|
*/
|
|
4023
4401
|
const FileUploadLine = ({ onClick, label, accept, ...buttonProps }) => {
|
|
4024
4402
|
FileUploadLine.displayName = "FileUploadLine";
|
|
4025
|
-
return (jsx(LineContainer, { children: jsx(UploadButton, { onUpload: onClick, accept: accept, label: label, ...buttonProps }) }));
|
|
4403
|
+
return (jsx(LineContainer, { uniqueId: label, children: jsx(UploadButton, { onUpload: onClick, accept: accept, label: label, ...buttonProps }) }));
|
|
4026
4404
|
};
|
|
4027
4405
|
|
|
4028
4406
|
/**
|
|
@@ -5799,7 +6177,7 @@ const PerformanceStats = ({ context: scene }) => {
|
|
|
5799
6177
|
window.addEventListener("resize", handleResize);
|
|
5800
6178
|
return () => window.removeEventListener("resize", handleResize);
|
|
5801
6179
|
}, [onResize]);
|
|
5802
|
-
return (jsxs(Fragment, { children: [!isOpen && jsx(ButtonLine, { label: "Open Realtime Perf Viewer", onClick: onPerformanceButtonClick }), !isOpen && jsx(FileUploadLine, { label: "Load Perf Viewer using CSV", accept: ".csv", onClick: onLoadClick }), jsx(ButtonLine, { label: "Export Perf to CSV", icon: ArrowDownloadRegular, onClick: onExportClick }), !isOpen && jsx(ButtonLine, { label: isRecording ? "Stop Recording" : "Begin Recording", icon: isRecording ? StopRegular : RecordRegular, onClick: onToggleRecording }), jsx(ChildWindow, { id: "performance-viewer", imperativeRef: childWindowRef, onOpenChange: (open) => !open && onClosePerformanceViewer(), children: performanceCollector && (jsx(PerformanceViewer, { scene: scene, layoutObservable: layoutObservable, returnToLiveObservable: returnToLiveObservable, performanceCollector: performanceCollector, initialGraphSize: InitialGraphSize })) })] }));
|
|
6180
|
+
return (jsxs(Fragment, { children: [!isOpen && jsx(ButtonLine, { label: "Open Realtime Perf Viewer", onClick: onPerformanceButtonClick }), !isOpen && jsx(FileUploadLine, { label: "Load Perf Viewer using CSV", accept: ".csv", onClick: onLoadClick }), jsx(ButtonLine, { label: "Export Perf to CSV", icon: ArrowDownloadRegular, onClick: onExportClick }), !isOpen && (jsx(ButtonLine, { uniqueId: "Start/Stop", label: isRecording ? "Stop Recording" : "Begin Recording", icon: isRecording ? StopRegular : RecordRegular, onClick: onToggleRecording })), jsx(ChildWindow, { id: "performance-viewer", imperativeRef: childWindowRef, onOpenChange: (open) => !open && onClosePerformanceViewer(), children: performanceCollector && (jsx(PerformanceViewer, { scene: scene, layoutObservable: layoutObservable, returnToLiveObservable: returnToLiveObservable, performanceCollector: performanceCollector, initialGraphSize: InitialGraphSize })) })] }));
|
|
5803
6181
|
};
|
|
5804
6182
|
|
|
5805
6183
|
/**
|
|
@@ -5869,7 +6247,7 @@ const StatsServiceDefinition = {
|
|
|
5869
6247
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
5870
6248
|
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
5871
6249
|
const scene = useObservableState(() => sceneContext.currentScene, sceneContext.currentSceneObservable);
|
|
5872
|
-
return jsx(Fragment, { children: scene && jsx(StatsPane, { sections: sections, sectionContent: sectionContent, context: scene }) });
|
|
6250
|
+
return (jsx(Fragment, { children: scene && (jsx(StatsPane, { uniqueId: "Statistics", sections: sections, sectionContent: sectionContent, context: scene, enablePinnedItems: true, enableHiddenItems: true, enableSearchItems: true })) }));
|
|
5873
6251
|
},
|
|
5874
6252
|
});
|
|
5875
6253
|
// Default/built-in sections.
|
|
@@ -5958,7 +6336,7 @@ const ToolsServiceDefinition = {
|
|
|
5958
6336
|
const sections = useOrderedObservableCollection(sectionsCollection);
|
|
5959
6337
|
const sectionContent = useObservableCollection(sectionContentCollection);
|
|
5960
6338
|
const scene = useObservableState(() => sceneContext.currentScene, sceneContext.currentSceneObservable);
|
|
5961
|
-
return scene && jsx(ToolsPane, { sections: sections, sectionContent: sectionContent, context: scene });
|
|
6339
|
+
return (scene && (jsx(ToolsPane, { uniqueId: "Tools", sections: sections, sectionContent: sectionContent, context: scene, enablePinnedItems: true, enableHiddenItems: true, enableSearchItems: true })));
|
|
5962
6340
|
},
|
|
5963
6341
|
});
|
|
5964
6342
|
}
|
|
@@ -5986,7 +6364,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
5986
6364
|
keywords: ["creation", "tools"],
|
|
5987
6365
|
...BabylonWebResources,
|
|
5988
6366
|
author: { name: "Babylon.js", forumUserName: "" },
|
|
5989
|
-
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-
|
|
6367
|
+
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-B4U-3oma.js'),
|
|
5990
6368
|
},
|
|
5991
6369
|
{
|
|
5992
6370
|
name: "Reflector",
|
|
@@ -5994,7 +6372,7 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
5994
6372
|
keywords: ["reflector", "bridge", "sync", "sandbox", "tools"],
|
|
5995
6373
|
...BabylonWebResources,
|
|
5996
6374
|
author: { name: "Babylon.js", forumUserName: "" },
|
|
5997
|
-
getExtensionModuleAsync: async () => await import('./reflectorService-
|
|
6375
|
+
getExtensionModuleAsync: async () => await import('./reflectorService-ozofO4uE.js'),
|
|
5998
6376
|
},
|
|
5999
6377
|
]);
|
|
6000
6378
|
|
|
@@ -6824,7 +7202,7 @@ function MakeModularTool(options) {
|
|
|
6824
7202
|
});
|
|
6825
7203
|
// Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
|
|
6826
7204
|
if (extensionFeeds.length > 0) {
|
|
6827
|
-
const { ExtensionListServiceDefinition } = await import('./extensionsListService-
|
|
7205
|
+
const { ExtensionListServiceDefinition } = await import('./extensionsListService-DnGdJhHc.js');
|
|
6828
7206
|
await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);
|
|
6829
7207
|
}
|
|
6830
7208
|
// Register the theme selector service (for selecting the theme) if theming is configured.
|
|
@@ -10794,7 +11172,7 @@ const AnimationGroupControlProperties = (props) => {
|
|
|
10794
11172
|
return currentFrameHolder ? currentFrameHolder.currentFrame : undefined;
|
|
10795
11173
|
}, [currentFrameHolder]), isPlaying ? animationGroup.getScene().onBeforeRenderObservable : null);
|
|
10796
11174
|
const enableBlending = useProperty(animationGroup, "enableBlending");
|
|
10797
|
-
return (jsxs(Fragment, { children: [jsx(ButtonLine, { label: isPlaying ? "Pause" : "Play", onClick: () => (isPlaying ? animationGroup.pause() : animationGroup.play(true)) }), jsx(ButtonLine, { label: "Stop", onClick: () => animationGroup.stop() }), jsx(CurveEditorButton, { scene: scene, target: null, animations: targetedAnimations, rootAnimationGroup: animationGroup, title: animationGroup.name, useTargetAnimations: true }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Speed Ratio", min: 0, max: 10, step: 0.1, target: animationGroup, propertyKey: "speedRatio" }), currentFrameHolder && currentFrame !== undefined ? (jsx(SyncedSliderPropertyLine, { label: "Current Frame", min: animationGroup.from, max: animationGroup.to, step: (animationGroup.to - animationGroup.from) / 1000.0, value: currentFrame, onChange: (value) => {
|
|
11175
|
+
return (jsxs(Fragment, { children: [jsx(ButtonLine, { uniqueId: "Start/Stop", label: isPlaying ? "Pause" : "Play", onClick: () => (isPlaying ? animationGroup.pause() : animationGroup.play(true)) }), jsx(ButtonLine, { label: "Stop", onClick: () => animationGroup.stop() }), jsx(CurveEditorButton, { scene: scene, target: null, animations: targetedAnimations, rootAnimationGroup: animationGroup, title: animationGroup.name, useTargetAnimations: true }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Speed Ratio", min: 0, max: 10, step: 0.1, target: animationGroup, propertyKey: "speedRatio" }), currentFrameHolder && currentFrame !== undefined ? (jsx(SyncedSliderPropertyLine, { label: "Current Frame", min: animationGroup.from, max: animationGroup.to, step: (animationGroup.to - animationGroup.from) / 1000.0, value: currentFrame, onChange: (value) => {
|
|
10798
11176
|
if (!animationGroup.isPlaying) {
|
|
10799
11177
|
animationGroup.play(true);
|
|
10800
11178
|
animationGroup.goToFrame(value);
|
|
@@ -10856,9 +11234,9 @@ const useClasses = makeStyles({
|
|
|
10856
11234
|
});
|
|
10857
11235
|
const MessageBar = (props) => {
|
|
10858
11236
|
MessageBar.displayName = "MessageBar";
|
|
10859
|
-
const { message, title, intent, docLink } = props;
|
|
11237
|
+
const { message, title, intent, docLink, staticItem } = props;
|
|
10860
11238
|
const classes = useClasses();
|
|
10861
|
-
return (jsx("div", { className: classes.container, children: jsx(MessageBar$1, { intent: intent, layout: "multiline", children: jsxs(MessageBarBody, { children: [title && jsx(MessageBarTitle, { children: title }), message, docLink && (jsxs(Fragment, { children: [" - ", jsx(Link, { url: docLink, value: "Learn More" })] }))] }) }) }));
|
|
11239
|
+
return (jsx(AccordionSectionItem, { uniqueId: title ?? message, staticItem: staticItem ?? true, children: jsx("div", { className: classes.container, children: jsx(MessageBar$1, { intent: intent, layout: "multiline", children: jsxs(MessageBarBody, { children: [title && jsx(MessageBarTitle, { children: title }), message, docLink && (jsxs(Fragment, { children: [" - ", jsx(Link, { url: docLink, value: "Learn More" })] }))] }) }) }) }));
|
|
10862
11240
|
};
|
|
10863
11241
|
|
|
10864
11242
|
const AnimationsProperties = (props) => {
|
|
@@ -10903,7 +11281,7 @@ const AnimationsProperties = (props) => {
|
|
|
10903
11281
|
}
|
|
10904
11282
|
} }), jsx(SyncedSliderPropertyLine, { label: "Current Frame", value: currentFrame, min: mainAnimatable.fromFrame, max: mainAnimatable.toFrame, step: (mainAnimatable.toFrame - mainAnimatable.fromFrame) / 1000, onChange: (value) => {
|
|
10905
11283
|
mainAnimatable.goToFrame(value);
|
|
10906
|
-
} })] }), expandByDefault: true }) })), hasAnimations && (jsx(ButtonLine, { label: isPlaying ? "Stop Animation" : "Play Animation", onClick: () => {
|
|
11284
|
+
} })] }), expandByDefault: true }) })), hasAnimations && (jsx(ButtonLine, { uniqueId: "Start/Stop", label: isPlaying ? "Stop Animation" : "Play Animation", onClick: () => {
|
|
10907
11285
|
if (isPlaying) {
|
|
10908
11286
|
scene.stopAnimation(entity);
|
|
10909
11287
|
}
|
|
@@ -11046,7 +11424,7 @@ const SoundCommandProperties = (props) => {
|
|
|
11046
11424
|
const { sound } = props;
|
|
11047
11425
|
const soundState = useSoundState(sound);
|
|
11048
11426
|
const volume = useObservableState(useCallback(() => sound.getVolume(), [sound]), useInterceptObservable("function", sound, "setVolume"));
|
|
11049
|
-
return (jsxs(Fragment, { children: [jsx(ButtonLine, { label: soundState === "Playing" ? "Pause" : "Play", icon: soundState === "Playing" ? PauseRegular : PlayRegular, onClick: () => {
|
|
11427
|
+
return (jsxs(Fragment, { children: [jsx(ButtonLine, { uniqueId: "Start/Stop", label: soundState === "Playing" ? "Pause" : "Play", icon: soundState === "Playing" ? PauseRegular : PlayRegular, onClick: () => {
|
|
11050
11428
|
if (soundState === "Playing") {
|
|
11051
11429
|
sound.pause();
|
|
11052
11430
|
}
|
|
@@ -12681,7 +13059,7 @@ const PBRBaseMaterialChannelsProperties = (props) => {
|
|
|
12681
13059
|
const { material, selectionService } = props;
|
|
12682
13060
|
const scene = material.getScene();
|
|
12683
13061
|
const selectEntity = (entity) => (selectionService.selectedEntity = entity);
|
|
12684
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Albedo", target: material, propertyKey: "_albedoTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Base Weight", target: material, propertyKey: "_baseWeightTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Base Diffuse Roughness", target: material, propertyKey: "_baseDiffuseRoughnessTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Metallic Roughness", target: material, propertyKey: "_metallicTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Reflection", target: material, propertyKey: "_reflectionTexture", scene: scene, cubeOnly: true, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Refraction", target: material.subSurface, propertyKey: "refractionTexture", propertyPath: "subSurface.refractionTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Reflectivity", target: material, propertyKey: "_reflectivityTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Micro Surface", target: material, propertyKey: "_microSurfaceTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Bump", target: material, propertyKey: "_bumpTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Emissive", target: material, propertyKey: "_emissiveTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Opacity", target: material, propertyKey: "_opacityTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Ambient", target: material, propertyKey: "_ambientTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Lightmap", target: material, propertyKey: "_lightmapTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Detailmap", target: material.detailMap, propertyKey: "texture", propertyPath: "detailMap.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Lightmap as Shadowmap", target: material, propertyKey: "_useLightmapAsShadowmap" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Detailmap", target: material.detailMap, propertyKey: "isEnabled", propertyPath: "detailMap.isEnabled" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Decalmap", target: material.decalMap, propertyKey: "isEnabled", propertyPath: "decalMap.isEnabled" })] }));
|
|
13062
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Albedo", target: material, propertyKey: "_albedoTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Base Weight", target: material, propertyKey: "_baseWeightTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Base Diffuse Roughness", target: material, propertyKey: "_baseDiffuseRoughnessTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Metallic Roughness", target: material, propertyKey: "_metallicTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, uniqueId: "PBRBaseMaterialChannels_Reflection", label: "Reflection", target: material, propertyKey: "_reflectionTexture", scene: scene, cubeOnly: true, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Refraction", target: material.subSurface, propertyKey: "refractionTexture", propertyPath: "subSurface.refractionTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Reflectivity", target: material, propertyKey: "_reflectivityTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Micro Surface", target: material, propertyKey: "_microSurfaceTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Bump", target: material, propertyKey: "_bumpTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Emissive", target: material, propertyKey: "_emissiveTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Opacity", target: material, propertyKey: "_opacityTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Ambient", target: material, propertyKey: "_ambientTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Lightmap", target: material, propertyKey: "_lightmapTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Detailmap", target: material.detailMap, propertyKey: "texture", propertyPath: "detailMap.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Lightmap as Shadowmap", target: material, propertyKey: "_useLightmapAsShadowmap" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Detailmap", target: material.detailMap, propertyKey: "isEnabled", propertyPath: "detailMap.isEnabled" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Decalmap", target: material.decalMap, propertyKey: "isEnabled", propertyPath: "decalMap.isEnabled" })] }));
|
|
12685
13063
|
};
|
|
12686
13064
|
const PBRBaseMaterialLightingAndColorProperties = (props) => {
|
|
12687
13065
|
const { material } = props;
|
|
@@ -12691,7 +13069,7 @@ const PBRBaseMaterialMetallicWorkflowProperties = (props) => {
|
|
|
12691
13069
|
const { material, selectionService } = props;
|
|
12692
13070
|
const scene = material.getScene();
|
|
12693
13071
|
const selectEntity = (entity) => (selectionService.selectedEntity = entity);
|
|
12694
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Metallic", target: material, propertyKey: "_metallic", min: 0, max: 1, step: 0.01, nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Roughness", target: material, propertyKey: "_roughness", min: 0, max: 1, step: 0.01, nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Base Diffuse Roughness", target: material, propertyKey: "_baseDiffuseRoughness", min: 0, max: 1, step: 0.01, nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Index of Refraction", target: material.subSurface, propertyKey: "indexOfRefraction", propertyPath: "subSurface.indexOfRefraction", min: 1, max: 3, step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "F0 Factor", target: material, propertyKey: "_metallicF0Factor", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: Color3PropertyLine, label: "Reflectance Color", target: material, propertyKey: "_metallicReflectanceColor", isLinearMode: true }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Metallic Only", description: "Use only metallic from MetallicReflectance texture", target: material, propertyKey: "_useOnlyMetallicFromMetallicReflectanceTexture" }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Metallic Reflectance", target: material, propertyKey: "_metallicReflectanceTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Reflectance", target: material, propertyKey: "_reflectanceTexture", scene: scene, onLink: selectEntity, defaultValue: null })] }));
|
|
13072
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Metallic", target: material, propertyKey: "_metallic", min: 0, max: 1, step: 0.01, nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, uniqueId: "PBRBaseMaterialMetallicWorkflow_Roughness", label: "Roughness", target: material, propertyKey: "_roughness", min: 0, max: 1, step: 0.01, nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Base Diffuse Roughness", target: material, propertyKey: "_baseDiffuseRoughness", min: 0, max: 1, step: 0.01, nullable: true, defaultValue: 0 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Index of Refraction", target: material.subSurface, propertyKey: "indexOfRefraction", propertyPath: "subSurface.indexOfRefraction", min: 1, max: 3, step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "F0 Factor", target: material, propertyKey: "_metallicF0Factor", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: Color3PropertyLine, label: "Reflectance Color", target: material, propertyKey: "_metallicReflectanceColor", isLinearMode: true }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Metallic Only", description: "Use only metallic from MetallicReflectance texture", target: material, propertyKey: "_useOnlyMetallicFromMetallicReflectanceTexture" }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Metallic Reflectance", target: material, propertyKey: "_metallicReflectanceTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Reflectance", target: material, propertyKey: "_reflectanceTexture", scene: scene, onLink: selectEntity, defaultValue: null })] }));
|
|
12695
13073
|
};
|
|
12696
13074
|
const PBRBaseMaterialClearCoatProperties = (props) => {
|
|
12697
13075
|
const { material, selectionService } = props;
|
|
@@ -12700,7 +13078,7 @@ const PBRBaseMaterialClearCoatProperties = (props) => {
|
|
|
12700
13078
|
const isEnabled = useProperty(material.clearCoat, "isEnabled");
|
|
12701
13079
|
const isTintEnabled = useProperty(material.clearCoat, "isTintEnabled");
|
|
12702
13080
|
const bumpTexture = useProperty(material.clearCoat, "bumpTexture");
|
|
12703
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Enabled", target: material.clearCoat, propertyKey: "isEnabled", propertyPath: "clearCoat.isEnabled" }), jsxs(Collapse, { visible: isEnabled, children: [jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Intensity", target: material.clearCoat, propertyKey: "intensity", propertyPath: "clearCoat.intensity", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Roughness", target: material.clearCoat, propertyKey: "roughness", propertyPath: "clearCoat.roughness", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "IOR", description: "Index of Refraction", target: material.clearCoat, propertyKey: "indexOfRefraction", propertyPath: "clearCoat.indexOfRefraction", min: 1, max: 3, step: 0.01 }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Remap F0", target: material.clearCoat, propertyKey: "remapF0OnInterfaceChange", propertyPath: "clearCoat.remapF0OnInterfaceChange" }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Clear Coat", target: material.clearCoat, propertyKey: "texture", propertyPath: "clearCoat.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Roughness", target: material.clearCoat, propertyKey: "textureRoughness", propertyPath: "clearCoat.textureRoughness", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Bump", target: material.clearCoat, propertyKey: "bumpTexture", propertyPath: "clearCoat.bumpTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(Collapse, { visible: bumpTexture !== null, children: jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Bump Strength", target: bumpTexture, propertyKey: "level", propertyPath: "clearCoat.bumpTexture.level", min: 0, max: 2, step: 0.01 }) }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Roughness from Main Texture", target: material.clearCoat, propertyKey: "useRoughnessFromMainTexture", propertyPath: "clearCoat.useRoughnessFromMainTexture" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Tint", target: material.clearCoat, propertyKey: "isTintEnabled", propertyPath: "clearCoat.isTintEnabled" }), jsxs(Collapse, { visible: isTintEnabled, children: [jsx(BoundProperty, { component: Color3PropertyLine, label: "Tint Color", target: material.clearCoat, propertyKey: "tintColor", propertyPath: "clearCoat.tintColor", isLinearMode: true }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "At Distance", target: material.clearCoat, propertyKey: "tintColorAtDistance", propertyPath: "clearCoat.tintColorAtDistance", min: 0, max: 20, step: 0.1 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Tint Thickness", target: material.clearCoat, propertyKey: "tintThickness", propertyPath: "clearCoat.tintThickness", min: 0, max: 20, step: 0.1 }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Tint", target: material.clearCoat, propertyKey: "tintTexture", propertyPath: "clearCoat.tintTexture", scene: scene, onLink: selectEntity, defaultValue: null })] })] })] }));
|
|
13081
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Enabled", target: material.clearCoat, propertyKey: "isEnabled", propertyPath: "clearCoat.isEnabled" }), jsxs(Collapse, { visible: isEnabled, children: [jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Intensity", target: material.clearCoat, propertyKey: "intensity", propertyPath: "clearCoat.intensity", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, uniqueId: "PBRBaseMaterialClearCoat_Roughness_1", label: "Roughness", target: material.clearCoat, propertyKey: "roughness", propertyPath: "clearCoat.roughness", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "IOR", description: "Index of Refraction", target: material.clearCoat, propertyKey: "indexOfRefraction", propertyPath: "clearCoat.indexOfRefraction", min: 1, max: 3, step: 0.01 }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Remap F0", target: material.clearCoat, propertyKey: "remapF0OnInterfaceChange", propertyPath: "clearCoat.remapF0OnInterfaceChange" }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Clear Coat", target: material.clearCoat, propertyKey: "texture", propertyPath: "clearCoat.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, uniqueId: "PBRBaseMaterialClearCoat_Roughness_2", label: "Roughness", target: material.clearCoat, propertyKey: "textureRoughness", propertyPath: "clearCoat.textureRoughness", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Bump", target: material.clearCoat, propertyKey: "bumpTexture", propertyPath: "clearCoat.bumpTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(Collapse, { visible: bumpTexture !== null, children: jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Bump Strength", target: bumpTexture, propertyKey: "level", propertyPath: "clearCoat.bumpTexture.level", min: 0, max: 2, step: 0.01 }) }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Roughness from Main Texture", target: material.clearCoat, propertyKey: "useRoughnessFromMainTexture", propertyPath: "clearCoat.useRoughnessFromMainTexture" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Tint", target: material.clearCoat, propertyKey: "isTintEnabled", propertyPath: "clearCoat.isTintEnabled" }), jsxs(Collapse, { visible: isTintEnabled, children: [jsx(BoundProperty, { component: Color3PropertyLine, label: "Tint Color", target: material.clearCoat, propertyKey: "tintColor", propertyPath: "clearCoat.tintColor", isLinearMode: true }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "At Distance", target: material.clearCoat, propertyKey: "tintColorAtDistance", propertyPath: "clearCoat.tintColorAtDistance", min: 0, max: 20, step: 0.1 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Tint Thickness", target: material.clearCoat, propertyKey: "tintThickness", propertyPath: "clearCoat.tintThickness", min: 0, max: 20, step: 0.1 }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Tint", target: material.clearCoat, propertyKey: "tintTexture", propertyPath: "clearCoat.tintTexture", scene: scene, onLink: selectEntity, defaultValue: null })] })] })] }));
|
|
12704
13082
|
};
|
|
12705
13083
|
const PBRBaseMaterialIridescenceProperties = (props) => {
|
|
12706
13084
|
const { material, selectionService } = props;
|
|
@@ -12722,7 +13100,7 @@ const PBRBaseMaterialSheenProperties = (props) => {
|
|
|
12722
13100
|
const selectEntity = (entity) => (selectionService.selectedEntity = entity);
|
|
12723
13101
|
const isEnabled = useProperty(material.sheen, "isEnabled");
|
|
12724
13102
|
const useRoughness = useProperty(material.sheen, "_useRoughness");
|
|
12725
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Enabled", target: material.sheen, propertyKey: "isEnabled", propertyPath: "sheen.isEnabled" }), jsxs(Collapse, { visible: isEnabled, children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Link to Albedo", target: material.sheen, propertyKey: "linkSheenWithAlbedo", propertyPath: "sheen.linkSheenWithAlbedo" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Intensity", target: material.sheen, propertyKey: "intensity", propertyPath: "sheen.intensity", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: Color3PropertyLine, label: "Color", target: material.sheen, propertyKey: "color", propertyPath: "sheen.color", isLinearMode: true }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Sheen", target: material.sheen, propertyKey: "texture", propertyPath: "sheen.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Roughness", target: material.sheen, propertyKey: "textureRoughness", propertyPath: "sheen.textureRoughness", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Roughness", target: material.sheen, propertyKey: "_useRoughness", propertyPath: "sheen._useRoughness" }), jsx(Collapse, { visible: useRoughness, children: jsx(BoundProperty, { nullable: true, component: SyncedSliderPropertyLine, label: "Roughness", target: material.sheen, propertyKey: "roughness", propertyPath: "sheen.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", propertyPath: "sheen.useRoughnessFromMainTexture" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Albedo Scaling", target: material.sheen, propertyKey: "albedoScaling", propertyPath: "sheen.albedoScaling" })] })] }));
|
|
13103
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Enabled", target: material.sheen, propertyKey: "isEnabled", propertyPath: "sheen.isEnabled" }), jsxs(Collapse, { visible: isEnabled, children: [jsx(BoundProperty, { component: SwitchPropertyLine, label: "Link to Albedo", target: material.sheen, propertyKey: "linkSheenWithAlbedo", propertyPath: "sheen.linkSheenWithAlbedo" }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Intensity", target: material.sheen, propertyKey: "intensity", propertyPath: "sheen.intensity", min: 0, max: 1, step: 0.01 }), jsx(BoundProperty, { component: Color3PropertyLine, label: "Color", target: material.sheen, propertyKey: "color", propertyPath: "sheen.color", isLinearMode: true }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Sheen", target: material.sheen, propertyKey: "texture", propertyPath: "sheen.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, uniqueId: "PBRBaseMaterialSheen_Roughness_1", label: "Roughness", target: material.sheen, propertyKey: "textureRoughness", propertyPath: "sheen.textureRoughness", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Roughness", target: material.sheen, propertyKey: "_useRoughness", propertyPath: "sheen._useRoughness" }), jsx(Collapse, { visible: useRoughness, children: jsx(BoundProperty, { nullable: true, component: SyncedSliderPropertyLine, uniqueId: "PBRBaseMaterialSheen_Roughness_2", label: "Roughness", target: material.sheen, propertyKey: "roughness", propertyPath: "sheen.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", propertyPath: "sheen.useRoughnessFromMainTexture" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Albedo Scaling", target: material.sheen, propertyKey: "albedoScaling", propertyPath: "sheen.albedoScaling" })] })] }));
|
|
12726
13104
|
};
|
|
12727
13105
|
const PBRBaseMaterialSubSurfaceProperties = (props) => {
|
|
12728
13106
|
const { material, selectionService } = props;
|
|
@@ -12769,7 +13147,7 @@ const StandardMaterialTexturesProperties = (props) => {
|
|
|
12769
13147
|
const { material, selectionService } = props;
|
|
12770
13148
|
const scene = material.getScene();
|
|
12771
13149
|
const selectEntity = (entity) => (selectionService.selectedEntity = entity);
|
|
12772
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Diffuse", target: material, propertyKey: "diffuseTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Specular", target: material, propertyKey: "specularTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Reflection", target: material, propertyKey: "reflectionTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Refraction", target: material, propertyKey: "refractionTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Emissive", target: material, propertyKey: "emissiveTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Bump", target: material, propertyKey: "bumpTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Opacity", target: material, propertyKey: "opacityTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Ambient", target: material, propertyKey: "ambientTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Lightmap", target: material, propertyKey: "lightmapTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Detailmap", target: material.detailMap, propertyKey: "texture", propertyPath: "detailMap.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Lightmap as Shadowmap", target: material, propertyKey: "useLightmapAsShadowmap" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Detailmap", target: material.detailMap, propertyKey: "isEnabled", propertyPath: "detailMap.isEnabled" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Decalmap", target: material.decalMap, propertyKey: "isEnabled", propertyPath: "decalMap.isEnabled" })] }));
|
|
13150
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Diffuse", target: material, propertyKey: "diffuseTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Specular", target: material, propertyKey: "specularTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, uniqueId: "StandardMaterialTextures_Reflection", label: "Reflection", target: material, propertyKey: "reflectionTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Refraction", target: material, propertyKey: "refractionTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Emissive", target: material, propertyKey: "emissiveTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Bump", target: material, propertyKey: "bumpTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Opacity", target: material, propertyKey: "opacityTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Ambient", target: material, propertyKey: "ambientTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Lightmap", target: material, propertyKey: "lightmapTexture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Detailmap", target: material.detailMap, propertyKey: "texture", propertyPath: "detailMap.texture", scene: scene, onLink: selectEntity, defaultValue: null }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Lightmap as Shadowmap", target: material, propertyKey: "useLightmapAsShadowmap" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Detailmap", target: material.detailMap, propertyKey: "isEnabled", propertyPath: "detailMap.isEnabled" }), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Use Decalmap", target: material.decalMap, propertyKey: "isEnabled", propertyPath: "decalMap.isEnabled" })] }));
|
|
12773
13151
|
};
|
|
12774
13152
|
/**
|
|
12775
13153
|
* Displays the levels properties of a standard material.
|
|
@@ -13171,14 +13549,14 @@ const MetadataProperties = (props) => {
|
|
|
13171
13549
|
const [editedMetadata, setEditedMetadata] = useState(stringifiedMetadata);
|
|
13172
13550
|
const isEditedMetadataJSON = useMemo(() => IsParsable(editedMetadata), [editedMetadata]);
|
|
13173
13551
|
const unformattedEditedMetadata = useMemo(() => Restringify(editedMetadata, false), [editedMetadata]);
|
|
13174
|
-
return (jsxs(Fragment, { children: [jsx(TextPropertyLine, { label: "Property Type", value: metadataType }), jsx(Collapse, { visible: canPreventObjectCorruption, children: jsx(SwitchPropertyLine, { label: "Prevent Object Corruption", value: isReadonly, onChange: setPreventObjectCorruption }) }), jsx(LineContainer, { children: jsx(Textarea, { disabled: isReadonly, value: editedMetadata, onChange: setEditedMetadata }) }), jsx(ButtonLine, { label: "Populate glTF extras", disabled: !!editedMetadata && (!IsParsable(editedMetadata) || HasGltfExtras(editedMetadata)), onClick: () => {
|
|
13552
|
+
return (jsxs(Fragment, { children: [jsx(TextPropertyLine, { label: "Property Type", value: metadataType }), jsx(Collapse, { visible: canPreventObjectCorruption, children: jsx(SwitchPropertyLine, { label: "Prevent Object Corruption", value: isReadonly, onChange: setPreventObjectCorruption }) }), jsx(LineContainer, { uniqueId: "MetadataTextarea", children: jsx(Textarea, { disabled: isReadonly, value: editedMetadata, onChange: setEditedMetadata }) }), jsx(ButtonLine, { label: "Populate glTF extras", disabled: !!editedMetadata && (!IsParsable(editedMetadata) || HasGltfExtras(editedMetadata)), onClick: () => {
|
|
13175
13553
|
const isFormatted = Restringify(editedMetadata, true) === editedMetadata;
|
|
13176
13554
|
let withGLTFExtras = PopulateGLTFExtras(editedMetadata);
|
|
13177
13555
|
if (isFormatted) {
|
|
13178
13556
|
withGLTFExtras = Restringify(withGLTFExtras, true);
|
|
13179
13557
|
}
|
|
13180
13558
|
setEditedMetadata(withGLTFExtras);
|
|
13181
|
-
} }), jsx(LineContainer, { children: jsxs("div", { className: classes.buttonDiv, children: [jsx(Button$1, { size: size, icon: jsx(SaveRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => SaveMetadata(entity, editedMetadata), children: jsx(Body1, { children: "Save" }) }), jsx(Tooltip$1, { content: "Undo Changes", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(ArrowUndoRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => setEditedMetadata(stringifiedMetadata) }) }), jsx(Tooltip$1, { content: "Format (Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesRegular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, true)) }) }), jsx(Tooltip$1, { content: "Clear Formatting (Undo Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesDismiss16Regular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, false)) }) })] }) })] }));
|
|
13559
|
+
} }), jsx(LineContainer, { uniqueId: "MetadataButtonDiv", children: jsxs("div", { className: classes.buttonDiv, children: [jsx(Button$1, { size: size, icon: jsx(SaveRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => SaveMetadata(entity, editedMetadata), children: jsx(Body1, { children: "Save" }) }), jsx(Tooltip$1, { content: "Undo Changes", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(ArrowUndoRegular, {}), disabled: stringifiedMetadata === unformattedEditedMetadata, onClick: () => setEditedMetadata(stringifiedMetadata) }) }), jsx(Tooltip$1, { content: "Format (Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesRegular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, true)) }) }), jsx(Tooltip$1, { content: "Clear Formatting (Undo Pretty Print)", relationship: "label", children: jsx(Button$1, { size: size, icon: jsx(BracesDismiss16Regular, {}), disabled: !isEditedMetadataJSON, onClick: () => setEditedMetadata(Restringify(editedMetadata, false)) }) })] }) })] }));
|
|
13182
13560
|
};
|
|
13183
13561
|
|
|
13184
13562
|
function IsMetadataContainer(entity) {
|
|
@@ -13628,7 +14006,7 @@ const ParticleSystemSystemProperties = (props) => {
|
|
|
13628
14006
|
const capacity = useObservableState(() => system.getCapacity());
|
|
13629
14007
|
const activeCount = useObservableState(() => system.getActiveCount(), scene?.onBeforeRenderObservable);
|
|
13630
14008
|
const selectEntity = (entity) => (selectionService.selectedEntity = entity);
|
|
13631
|
-
return (jsxs(Fragment, { children: [isCpuParticleSystem && (jsx(TextPropertyLine, { label: "Is Node Generated", description: "Indicates if the particle system was created from a node-based particle system.", value: String(isNodeGenerated) })), 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 }), scene && !isNodeGenerated && (jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Particle Texture", target: system, propertyKey: "particleTexture", scene: scene, onLink: selectEntity, defaultValue: null })), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Blend Mode", target: system, propertyKey: "blendMode", options: BlendModeOptions }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "World Offset", target: system, propertyKey: "worldOffset" }), 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 }), isCpuParticleSystem && (jsx(ButtonLine, { label: isNodeGenerated ? "Edit" : "View as Node-Based Particle System", icon: isNodeGenerated ? EditRegular : EyeRegular, onClick: async () => {
|
|
14009
|
+
return (jsxs(Fragment, { children: [isCpuParticleSystem && (jsx(TextPropertyLine, { label: "Is Node Generated", description: "Indicates if the particle system was created from a node-based particle system.", value: String(isNodeGenerated) })), 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 }), scene && !isNodeGenerated && (jsx(BoundProperty, { component: TextureSelectorPropertyLine, label: "Particle Texture", target: system, propertyKey: "particleTexture", scene: scene, onLink: selectEntity, defaultValue: null })), jsx(BoundProperty, { component: NumberDropdownPropertyLine, label: "Blend Mode", target: system, propertyKey: "blendMode", options: BlendModeOptions }), jsx(BoundProperty, { component: Vector3PropertyLine, label: "World Offset", target: system, propertyKey: "worldOffset" }), 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 }), isCpuParticleSystem && (jsx(ButtonLine, { uniqueId: "View/Edit", label: isNodeGenerated ? "Edit" : "View as Node-Based Particle System", icon: isNodeGenerated ? EditRegular : EyeRegular, onClick: async () => {
|
|
13632
14010
|
const scene = system.getScene();
|
|
13633
14011
|
if (!scene) {
|
|
13634
14012
|
return;
|
|
@@ -15374,7 +15752,7 @@ const SceneCollisionsProperties = (props) => {
|
|
|
15374
15752
|
};
|
|
15375
15753
|
const SceneShadowsProperties = (props) => {
|
|
15376
15754
|
const { scene } = props;
|
|
15377
|
-
return (jsx(Fragment, { children: jsx(ButtonLine, { label: "Normalize
|
|
15755
|
+
return (jsx(Fragment, { children: jsx(ButtonLine, { label: "Normalize Scene", onClick: () => {
|
|
15378
15756
|
for (const mesh of scene.meshes) {
|
|
15379
15757
|
mesh.normalizeToUnitCube(true);
|
|
15380
15758
|
mesh.computeWorldMatrix(true);
|
|
@@ -15413,7 +15791,7 @@ const SceneRenderingProperties = (props) => {
|
|
|
15413
15791
|
scene.environmentTexture = StoredEnvironmentTexture;
|
|
15414
15792
|
StoredEnvironmentTexture = null;
|
|
15415
15793
|
}
|
|
15416
|
-
} }), scene.environmentTexture && (jsx(LinkPropertyLine, { label: "Env.
|
|
15794
|
+
} }), scene.environmentTexture && (jsx(LinkPropertyLine, { label: "Env. Texture", value: scene.environmentTexture.name, onLink: () => (selectionService.selectedEntity = scene.environmentTexture) })), jsx(FileUploadLine, { label: "Update Environment Texture", accept: ".dds, .env", onClick: (files) => {
|
|
15417
15795
|
if (files.length > 0) {
|
|
15418
15796
|
const file = files[0];
|
|
15419
15797
|
const isFileDDS = file.name.toLowerCase().indexOf(".dds") > 0;
|
|
@@ -15711,7 +16089,8 @@ const SpriteManagerActionsProperties = (props) => {
|
|
|
15711
16089
|
* @returns the 8-bit texture data
|
|
15712
16090
|
*/
|
|
15713
16091
|
async function ApplyChannelsToTextureDataAsync(texture, width, height, face, channels, lod = 0) {
|
|
15714
|
-
|
|
16092
|
+
// For cube maps, force RTT path to ensure correct face orientation and gamma correction
|
|
16093
|
+
const data = await GetTextureDataAsync(texture, width, height, face, lod, texture.isCube);
|
|
15715
16094
|
if (!channels.R || !channels.G || !channels.B || !channels.A) {
|
|
15716
16095
|
for (let i = 0; i < width * height * 4; i += 4) {
|
|
15717
16096
|
// If alpha is the only channel, just display alpha across all channels
|
|
@@ -15803,9 +16182,11 @@ const useStyles$9 = makeStyles({
|
|
|
15803
16182
|
textOverflow: "ellipsis",
|
|
15804
16183
|
},
|
|
15805
16184
|
preview: {
|
|
15806
|
-
|
|
16185
|
+
outline: `1px solid ${tokens.colorNeutralStroke1}`,
|
|
15807
16186
|
display: "block",
|
|
15808
16187
|
objectFit: "contain",
|
|
16188
|
+
// Checkerboard background to show transparency
|
|
16189
|
+
background: "repeating-conic-gradient(#B2B2B2 0% 25%, white 25% 50%) 50% / 32px 32px",
|
|
15809
16190
|
},
|
|
15810
16191
|
previewContainer: {
|
|
15811
16192
|
display: "flex",
|
|
@@ -15813,8 +16194,6 @@ const useStyles$9 = makeStyles({
|
|
|
15813
16194
|
marginTop: tokens.spacingVerticalXS,
|
|
15814
16195
|
marginBottom: tokens.spacingVerticalS,
|
|
15815
16196
|
width: "100%",
|
|
15816
|
-
// Checkerboard background to show transparency
|
|
15817
|
-
background: "repeating-conic-gradient(#B2B2B2 0% 25%, white 25% 50%) 50% / 32px 32px",
|
|
15818
16197
|
},
|
|
15819
16198
|
});
|
|
15820
16199
|
// This method of holding TextureChannels was brought over from inspectorv1 and can likely be refactored/simplified
|
|
@@ -15834,6 +16213,9 @@ const TexturePreview = (props) => {
|
|
|
15834
16213
|
const [canvasStyle, setCanvasStyle] = useState();
|
|
15835
16214
|
const internalTexture = useProperty(texture, "_texture");
|
|
15836
16215
|
const { size } = useContext(ToolContext);
|
|
16216
|
+
// Watch for pinned state changes - when portaled, the canvas needs to be redrawn
|
|
16217
|
+
const accordionCtx = useContext(AccordionContext);
|
|
16218
|
+
const isPinned = accordionCtx?.state.pinnedIds.some((id) => id.endsWith("\0TexturePreview")) ?? false;
|
|
15837
16219
|
const updatePreviewAsync = useCallback(async () => {
|
|
15838
16220
|
const canvas = canvasRef.current;
|
|
15839
16221
|
if (!canvas) {
|
|
@@ -15842,16 +16224,19 @@ const TexturePreview = (props) => {
|
|
|
15842
16224
|
try {
|
|
15843
16225
|
await WhenTextureReadyAsync(texture); // Ensure texture is loaded before grabbing size
|
|
15844
16226
|
const { width: textureWidth, height: textureHeight } = texture.getSize();
|
|
15845
|
-
//
|
|
15846
|
-
|
|
15847
|
-
|
|
16227
|
+
// Calculate canvas dimensions
|
|
16228
|
+
const canvasWidth = width ?? textureWidth;
|
|
16229
|
+
const canvasHeight = height ?? textureHeight;
|
|
15848
16230
|
// Calculate the width that corresponds to maxHeight while maintaining aspect ratio
|
|
15849
|
-
const aspectRatio =
|
|
16231
|
+
const aspectRatio = canvasWidth / canvasHeight;
|
|
15850
16232
|
// Use CSS min() to pick the smaller of maxWidth or the width that corresponds to maxHeight
|
|
15851
16233
|
const imageWidth = `min(${maxWidth}, calc(${maxHeight} * ${aspectRatio}))`;
|
|
15852
16234
|
setCanvasStyle({ width: imageWidth });
|
|
15853
|
-
//
|
|
16235
|
+
// Fetch texture data BEFORE clearing the canvas to avoid flicker
|
|
15854
16236
|
const data = await ApplyChannelsToTextureDataAsync(texture, textureWidth, textureHeight, face, channels);
|
|
16237
|
+
// Now set canvas dimensions (this clears the canvas) and draw immediately
|
|
16238
|
+
canvas.width = canvasWidth;
|
|
16239
|
+
canvas.height = canvasHeight;
|
|
15855
16240
|
const context = canvas.getContext("2d");
|
|
15856
16241
|
if (context) {
|
|
15857
16242
|
const fullImageData = context.createImageData(textureWidth, textureHeight);
|
|
@@ -15868,9 +16253,13 @@ const TexturePreview = (props) => {
|
|
|
15868
16253
|
useEffect(() => {
|
|
15869
16254
|
void updatePreviewAsync();
|
|
15870
16255
|
}, [updatePreviewAsync]);
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
16256
|
+
// Redraw canvas after portaling (pinned state change moves DOM element, which can clear canvas)
|
|
16257
|
+
useEffect(() => {
|
|
16258
|
+
void updatePreviewAsync();
|
|
16259
|
+
}, [isPinned]);
|
|
16260
|
+
return (jsx(LineContainer, { uniqueId: "TexturePreview", children: 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: () => {
|
|
16261
|
+
void updatePreviewAsync();
|
|
16262
|
+
}, children: "Refresh" }))] }) }));
|
|
15874
16263
|
};
|
|
15875
16264
|
|
|
15876
16265
|
function useMaxCellCount(sprite) {
|
|
@@ -15899,7 +16288,7 @@ const SpriteAnimationProperties = (props) => {
|
|
|
15899
16288
|
const { sprite } = props;
|
|
15900
16289
|
const animationStarted = useObservableState(useCallback(() => sprite.animationStarted, [sprite]), useInterceptObservable("function", sprite, "playAnimation"), useInterceptObservable("function", sprite, "stopAnimation"), useInterceptObservable("function", sprite, "_animate"));
|
|
15901
16290
|
const maxCellCount = useMaxCellCount(sprite);
|
|
15902
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Start", description: "First frame of the animation.", min: 0, max: maxCellCount, target: sprite, propertyKey: "fromIndex" }, "Start"), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "End", description: "Last frame of the animation.", min: 0, max: maxCellCount, target: sprite, propertyKey: "toIndex" }, "End"), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Loop", description: "Whether to loop the animation.", target: sprite, propertyKey: "loopAnimation" }, "Loop"), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Delay", description: "Delay between frames in milliseconds.", min: 0, target: sprite, propertyKey: "delay" }, "Delay"), jsx(ButtonLine, { label: animationStarted ? "Stop Animation" : "Start Animation", icon: animationStarted ? StopFilled : PlayFilled, onClick: () => {
|
|
16291
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Start", description: "First frame of the animation.", min: 0, max: maxCellCount, target: sprite, propertyKey: "fromIndex" }, "Start"), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "End", description: "Last frame of the animation.", min: 0, max: maxCellCount, target: sprite, propertyKey: "toIndex" }, "End"), jsx(BoundProperty, { component: SwitchPropertyLine, label: "Loop", description: "Whether to loop the animation.", target: sprite, propertyKey: "loopAnimation" }, "Loop"), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "Delay", description: "Delay between frames in milliseconds.", min: 0, target: sprite, propertyKey: "delay" }, "Delay"), jsx(ButtonLine, { uniqueId: "Start/Stop", label: animationStarted ? "Stop Animation" : "Start Animation", icon: animationStarted ? StopFilled : PlayFilled, onClick: () => {
|
|
15903
16292
|
if (animationStarted) {
|
|
15904
16293
|
sprite.stopAnimation();
|
|
15905
16294
|
}
|
|
@@ -16153,7 +16542,7 @@ const BaseTextureTransformProperties = (props) => {
|
|
|
16153
16542
|
const CubeTextureTransformProperties = (props) => {
|
|
16154
16543
|
const { texture, settings } = props;
|
|
16155
16544
|
const [toDisplayAngle, fromDisplayAngle] = useAngleConverters(settings);
|
|
16156
|
-
return (jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Rotation Y", target: texture, propertyKey: "rotationY", min: 0, max: toDisplayAngle(Math.PI * 2), convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }));
|
|
16545
|
+
return (jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "Rotation Y", target: texture, propertyKey: "rotationY", min: 0, max: toDisplayAngle(Math.PI * 2), step: 0.0001, convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }));
|
|
16157
16546
|
};
|
|
16158
16547
|
|
|
16159
16548
|
const MultiRenderTargetGeneralProperties = (props) => {
|
|
@@ -16185,7 +16574,7 @@ const TextureTransformProperties = (props) => {
|
|
|
16185
16574
|
const [toDisplayAngle, fromDisplayAngle] = useAngleConverters(settings);
|
|
16186
16575
|
const wrapU = useProperty(texture, "wrapU");
|
|
16187
16576
|
const wrapV = useProperty(texture, "wrapV");
|
|
16188
|
-
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "U offset", target: texture, propertyKey: "uOffset", step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "V offset", target: texture, propertyKey: "vOffset", step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "U scale", target: texture, propertyKey: "uScale", step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "V scale", target: texture, propertyKey: "vScale", step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "U angle", target: texture, propertyKey: "uAng", min: 0, max: toDisplayAngle(Math.PI * 2), convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "V angle", target: texture, propertyKey: "vAng", min: 0, max: toDisplayAngle(Math.PI * 2), convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "W angle", target: texture, propertyKey: "wAng", min: 0, max: toDisplayAngle(Math.PI * 2), convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(SwitchPropertyLine, { label: "Clamp U", value: wrapU === Constants.TEXTURE_CLAMP_ADDRESSMODE, onChange: (value) => (texture.wrapU = value ? Constants.TEXTURE_CLAMP_ADDRESSMODE : Constants.TEXTURE_WRAP_ADDRESSMODE) }), jsx(SwitchPropertyLine, { label: "Clamp V", value: wrapV === Constants.TEXTURE_CLAMP_ADDRESSMODE, onChange: (value) => (texture.wrapV = value ? Constants.TEXTURE_CLAMP_ADDRESSMODE : Constants.TEXTURE_WRAP_ADDRESSMODE) })] }));
|
|
16577
|
+
return (jsxs(Fragment, { children: [jsx(BoundProperty, { component: NumberInputPropertyLine, label: "U offset", target: texture, propertyKey: "uOffset", step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "V offset", target: texture, propertyKey: "vOffset", step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "U scale", target: texture, propertyKey: "uScale", step: 0.01 }), jsx(BoundProperty, { component: NumberInputPropertyLine, label: "V scale", target: texture, propertyKey: "vScale", step: 0.01 }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "U angle", target: texture, propertyKey: "uAng", min: 0, max: toDisplayAngle(Math.PI * 2), step: 0.01, convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "V angle", target: texture, propertyKey: "vAng", min: 0, max: toDisplayAngle(Math.PI * 2), step: 0.01, convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(BoundProperty, { component: SyncedSliderPropertyLine, label: "W angle", target: texture, propertyKey: "wAng", min: 0, max: toDisplayAngle(Math.PI * 2), step: 0.01, convertTo: (value) => toDisplayAngle(value, true), convertFrom: fromDisplayAngle }), jsx(SwitchPropertyLine, { label: "Clamp U", value: wrapU === Constants.TEXTURE_CLAMP_ADDRESSMODE, onChange: (value) => (texture.wrapU = value ? Constants.TEXTURE_CLAMP_ADDRESSMODE : Constants.TEXTURE_WRAP_ADDRESSMODE) }), jsx(SwitchPropertyLine, { label: "Clamp V", value: wrapV === Constants.TEXTURE_CLAMP_ADDRESSMODE, onChange: (value) => (texture.wrapV = value ? Constants.TEXTURE_CLAMP_ADDRESSMODE : Constants.TEXTURE_WRAP_ADDRESSMODE) })] }));
|
|
16189
16578
|
};
|
|
16190
16579
|
|
|
16191
16580
|
const SamplingMode = [
|
|
@@ -16720,8 +17109,10 @@ class TextureCanvasManager {
|
|
|
16720
17109
|
}
|
|
16721
17110
|
async grabOriginalTexture() {
|
|
16722
17111
|
// Grab image data from original texture and paint it onto the context of a DynamicTexture
|
|
16723
|
-
this.
|
|
16724
|
-
|
|
17112
|
+
const size = this._originalTexture.getSize();
|
|
17113
|
+
// Fetch texture data BEFORE setting size (which clears the canvas) to avoid flicker
|
|
17114
|
+
const data = await ApplyChannelsToTextureDataAsync(this._originalTexture, size.width, size.height, this._face, { R: true, G: true, B: true, A: true }, this._mipLevel);
|
|
17115
|
+
this.setSize(size);
|
|
16725
17116
|
this._imageData = data;
|
|
16726
17117
|
this.paintPixelsOnCanvas(data, this._2DCanvas);
|
|
16727
17118
|
this._3DCanvasTexture.update();
|
|
@@ -16817,6 +17208,7 @@ class TextureCanvasManager {
|
|
|
16817
17208
|
this._onUpdate();
|
|
16818
17209
|
}
|
|
16819
17210
|
async resize(newSize) {
|
|
17211
|
+
// Fetch texture data BEFORE setting size (which clears the canvas) to avoid flicker
|
|
16820
17212
|
const data = await ApplyChannelsToTextureDataAsync(this._originalTexture, newSize.width, newSize.height, this._face, { R: true, G: true, B: true, A: true });
|
|
16821
17213
|
this.setSize(newSize);
|
|
16822
17214
|
this.paintPixelsOnCanvas(data, this._2DCanvas);
|
|
@@ -19138,7 +19530,7 @@ const VideoCaptureTool = ({ scene }) => {
|
|
|
19138
19530
|
void videoRecorder.startRecording(undefined, 0); // Use 0 to prevent automatic stop; let the user stop it
|
|
19139
19531
|
setIsRecording(true);
|
|
19140
19532
|
}, [scene]);
|
|
19141
|
-
return (jsx(Fragment, { children: jsx(ButtonLine, { label: isRecording ? "Stop Recording" : "Record Video", icon: isRecording ? RecordStopRegular : RecordRegular, onClick: recordVideoAsync }) }));
|
|
19533
|
+
return (jsx(Fragment, { children: jsx(ButtonLine, { uniqueId: "Start/Stop", label: isRecording ? "Stop Recording" : "Record Video", icon: isRecording ? RecordStopRegular : RecordRegular, onClick: recordVideoAsync }) }));
|
|
19142
19534
|
};
|
|
19143
19535
|
|
|
19144
19536
|
const CaptureToolsDefinition = {
|
|
@@ -19194,6 +19586,8 @@ const EnvExportImageTypes = [
|
|
|
19194
19586
|
{ label: "WebP", value: 1, imageType: "image/webp" },
|
|
19195
19587
|
];
|
|
19196
19588
|
const ExportBabylonTools = ({ scene }) => {
|
|
19589
|
+
// Track environment texture changes to re-render when it's updated (e.g., when a new HDRI is loaded)
|
|
19590
|
+
const environmentTexture = useProperty(scene, "environmentTexture");
|
|
19197
19591
|
const [babylonExportOptions, setBabylonExportOptions] = useState({
|
|
19198
19592
|
imageTypeIndex: 0,
|
|
19199
19593
|
imageQuality: 0.8,
|
|
@@ -19205,11 +19599,11 @@ const ExportBabylonTools = ({ scene }) => {
|
|
|
19205
19599
|
Tools.Download(blob, "scene.babylon");
|
|
19206
19600
|
}, [scene]);
|
|
19207
19601
|
const createEnvTexture = useCallback(async () => {
|
|
19208
|
-
if (!
|
|
19602
|
+
if (!environmentTexture) {
|
|
19209
19603
|
return;
|
|
19210
19604
|
}
|
|
19211
19605
|
try {
|
|
19212
|
-
const buffer = await EnvironmentTextureTools.CreateEnvTextureAsync(
|
|
19606
|
+
const buffer = await EnvironmentTextureTools.CreateEnvTextureAsync(environmentTexture, {
|
|
19213
19607
|
imageType: EnvExportImageTypes[babylonExportOptions.imageTypeIndex].imageType,
|
|
19214
19608
|
imageQuality: babylonExportOptions.imageQuality,
|
|
19215
19609
|
disableIrradianceTexture: !babylonExportOptions.iblDiffuse,
|
|
@@ -19221,8 +19615,8 @@ const ExportBabylonTools = ({ scene }) => {
|
|
|
19221
19615
|
Logger.Error(error);
|
|
19222
19616
|
alert(error);
|
|
19223
19617
|
}
|
|
19224
|
-
}, [scene, babylonExportOptions]);
|
|
19225
|
-
return (jsxs(Fragment, { children: [jsx(ButtonLine, { label: "Export to Babylon", icon: ArrowDownloadRegular, onClick: exportBabylon }), !scene.getEngine().premultipliedAlpha &&
|
|
19618
|
+
}, [scene, environmentTexture, babylonExportOptions]);
|
|
19619
|
+
return (jsxs(Fragment, { children: [jsx(ButtonLine, { label: "Export to Babylon", icon: ArrowDownloadRegular, onClick: exportBabylon }), !scene.getEngine().premultipliedAlpha && environmentTexture && environmentTexture._prefiltered && scene.activeCamera && (jsxs(Fragment, { children: [jsx(ButtonLine, { label: "Generate .env Texture", icon: ArrowDownloadRegular, onClick: createEnvTexture }), environmentTexture.irradianceTexture && (jsx(SwitchPropertyLine, { label: "Diffuse Texture", description: "Export diffuse texture for IBL", value: babylonExportOptions.iblDiffuse, onChange: (value) => {
|
|
19226
19620
|
setBabylonExportOptions((prev) => ({ ...prev, iblDiffuse: value }));
|
|
19227
19621
|
} }, "iblDiffuse")), jsx(NumberDropdownPropertyLine, { label: "Image type", options: EnvExportImageTypes, value: babylonExportOptions.imageTypeIndex, onChange: (val) => {
|
|
19228
19622
|
setBabylonExportOptions((prev) => ({ ...prev, imageTypeIndex: val }));
|
|
@@ -20623,5 +21017,5 @@ const TextAreaPropertyLine = (props) => {
|
|
|
20623
21017
|
// Attach Inspector v2 to Scene.debugLayer as a side effect for back compat.
|
|
20624
21018
|
AttachDebugLayer();
|
|
20625
21019
|
|
|
20626
|
-
export { useAngleConverters as $, Accordion as A, Button as B, CheckboxPropertyLine as C, DebugServiceIdentity as D, ExtensibleAccordion as E, useColor3Property as F, useColor4Property as G, useQuaternionProperty as H, Inspector as I, MakePropertyHook as J, useInterceptObservable as K, Link as L, MessageBar as M, NumberInputPropertyLine as N, useEventfulState as O, Popover as P, useObservableCollection as Q, useOrderedObservableCollection as R, SpinButtonPropertyLine as S, TextInputPropertyLine as T, usePollingObservable as U, Vector3PropertyLine as V, useResource as W, useAsyncResource as X, useCompactMode as Y, useDisableCopy as Z, useSidePaneDockOverrides as _, ShellServiceIdentity 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,
|
|
20627
|
-
//# sourceMappingURL=index-
|
|
21020
|
+
export { useAngleConverters as $, Accordion as A, Button as B, CheckboxPropertyLine as C, DebugServiceIdentity as D, ExtensibleAccordion as E, useColor3Property as F, useColor4Property as G, useQuaternionProperty as H, Inspector as I, MakePropertyHook as J, useInterceptObservable as K, Link as L, MessageBar as M, NumberInputPropertyLine as N, useEventfulState as O, Popover as P, useObservableCollection as Q, useOrderedObservableCollection as R, SpinButtonPropertyLine as S, TextInputPropertyLine as T, usePollingObservable as U, Vector3PropertyLine as V, useResource as W, useAsyncResource as X, useCompactMode as Y, useDisableCopy as Z, useSidePaneDockOverrides as _, ShellServiceIdentity 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, Textarea as aA, TextInput as aB, ToggleButton as aC, ChildWindow as aD, FileUploadLine as aE, FactorGradientList as aF, Color3GradientList as aG, Color4GradientList as aH, Pane as aI, BooleanBadgePropertyLine as aJ, Color3PropertyLine as aK, Color4PropertyLine as aL, HexPropertyLine as aM, LinkPropertyLine as aN, PropertyLine as aO, LineContainer as aP, PlaceholderPropertyLine as aQ, StringifiedPropertyLine as aR, SwitchPropertyLine as aS, SyncedSliderPropertyLine as aT, TextAreaPropertyLine as aU, TextPropertyLine as aV, RotationVectorPropertyLine as aW, QuaternionPropertyLine as aX, Vector2PropertyLine as aY, Vector4PropertyLine as aZ, SettingsContextIdentity as aa, ShowInspector as ab, AccordionSectionItem as ac, Checkbox as ad, Collapse as ae, ColorPickerPopup as af, InputHexField as ag, InputHsvField as ah, ComboBox as ai, DraggableLine as aj, Dropdown as ak, NumberDropdown as al, StringDropdown as am, FactorGradientComponent as an, Color3GradientComponent as ao, Color4GradientComponent as ap, ColorStepGradientComponent as aq, InfoLabel as ar, MakeLazyComponent as as, List as at, PositionedPopover as au, SearchBar as av, SearchBox as aw, SpinButton as ax, Switch as ay, SyncedSliderInput as az, SceneContextIdentity as b, useObservableState as c, AccordionSection as d, ButtonLine as e, ToolsServiceIdentity as f, useExtensionManager as g, MakePopoverTeachingMoment as h, TeachingMoment as i, SidePaneContainer as j, PropertiesServiceIdentity as k, SceneExplorerServiceIdentity as l, SettingsServiceIdentity as m, StatsServiceIdentity as n, ConvertOptions as o, AttachDebugLayer as p, DetachDebugLayer as q, NumberDropdownPropertyLine as r, StringDropdownPropertyLine as s, BoundProperty as t, useProperty as u, Property as v, LinkToEntityPropertyLine as w, Theme as x, BuiltInsExtensionFeed as y, useVector3Property as z };
|
|
21021
|
+
//# sourceMappingURL=index-BVYxLK-p.js.map
|