diff --git a/packages/scene-composer/public/MIXER_Tiles3D/0composite0.cmpt b/packages/scene-composer/public/MIXER_Tiles3D/0composite0.cmpt new file mode 100644 index 000000000..4acf0704b Binary files /dev/null and b/packages/scene-composer/public/MIXER_Tiles3D/0composite0.cmpt differ diff --git a/packages/scene-composer/public/MIXER_Tiles3D/tileset.json b/packages/scene-composer/public/MIXER_Tiles3D/tileset.json new file mode 100644 index 000000000..1d1ba54a5 --- /dev/null +++ b/packages/scene-composer/public/MIXER_Tiles3D/tileset.json @@ -0,0 +1 @@ +{"asset":{"version":"1.0","extras":{"ion":{"georeferenced":false,"movable":true}}},"geometricError":3.4263414652811504,"root":{"children":[{"geometricError":3.4263414652811504,"boundingVolume":{"box":[0.04932012988307033,0.00410548518149545,1.0065496274953585,1.2187353077585679,0,0,0,0.7779263069343911,0,0,0,0.9998963209502474]},"children":[{"boundingVolume":{"box":[0.04932012988307033,0.00410548518149545,1.0065496274953585,1.2187353077585679,0,0,0,0.7779263069343911,0,0,0,0.9998963209502474]},"geometricError":3.4263414652811504,"children":[{"boundingVolume":{"box":[0.04932012988307033,0.00410548518149545,1.0065496274953585,1.2187353077585679,0,0,0,0.7779263069343911,0,0,0,0.9998963209502474]},"content":{"uri":"0composite0.cmpt"},"geometricError":0}]}],"transform":[1,0,0,0,0,1,0,0,0,0,1,0,-0.04932012988307033,-0.00410548518149545,-0.006653306545111093,1]}],"refine":"ADD","boundingVolume":{"box":[0,0,0.9998963209502474,1.2187353077585679,0,0,0,0.7779263069343911,0,0,0,0.9998963209502474]},"geometricError":3.4263414652811504}} \ No newline at end of file diff --git a/packages/scene-composer/public/Tiles3D.scene.json b/packages/scene-composer/public/Tiles3D.scene.json new file mode 100644 index 000000000..696fed95e --- /dev/null +++ b/packages/scene-composer/public/Tiles3D.scene.json @@ -0,0 +1,106 @@ +{ + "specVersion": "1.0", + "version": "1", + "unit": "meters", + "properties": { + "environmentPreset": "neutral", + "componentSettings": { + "Tag": { + "autoRescale": false, + "scale": 1, + "enableOcclusion": false + } + } + }, + "nodes": [ + { + "name": "MIXER_Tiles3D", + "transform": { + "position": [ + 0.06654937013597362, + 0.9998963209552567, + -0.004778029802959161 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + "transformConstraint": { + "snapToFloor": true + }, + "components": [ + { + "type": "ModelRef", + "uri": "MIXER_Tiles3D/tileset.json", + "modelType": "Tiles3D" + } + ], + "properties": {} + } + ], + "rootNodeIndexes": [ + 0 + ], + "cameras": [], + "rules": { + "sampleAlarmIconRule": { + "statements": [ + { + "expression": "alarm_status == 'ACTIVE'", + "target": "iottwinmaker.common.icon:Error" + }, + { + "expression": "alarm_status == 'ACKNOWLEDGED'", + "target": "iottwinmaker.common.icon:Warning" + }, + { + "expression": "alarm_status == 'SNOOZE_DISABLED'", + "target": "iottwinmaker.common.icon:Warning" + }, + { + "expression": "alarm_status == 'NORMAL'", + "target": "iottwinmaker.common.icon:Info" + } + ] + }, + "sampleTimeSeriesIconRule": { + "statements": [ + { + "expression": "temperature >= 40", + "target": "iottwinmaker.common.icon:Error" + }, + { + "expression": "temperature >= 20", + "target": "iottwinmaker.common.icon:Warning" + }, + { + "expression": "temperature < 20", + "target": "iottwinmaker.common.icon:Info" + } + ] + }, + "sampleTimeSeriesColorRule": { + "statements": [ + { + "expression": "temperature >= 40", + "target": "iottwinmaker.common.color:#FF0000" + }, + { + "expression": "temperature >= 20", + "target": "iottwinmaker.common.color:#FFFF00" + }, + { + "expression": "temperature < 20", + "target": "iottwinmaker.common.color:#00FF00" + } + ] + } + } +} \ No newline at end of file diff --git a/packages/scene-composer/src/augmentations/components/three-fiber/viewpoint/ViewCursorWidget.tsx b/packages/scene-composer/src/augmentations/components/three-fiber/viewpoint/ViewCursorWidget.tsx index 8a435d89e..cc990b919 100644 --- a/packages/scene-composer/src/augmentations/components/three-fiber/viewpoint/ViewCursorWidget.tsx +++ b/packages/scene-composer/src/augmentations/components/three-fiber/viewpoint/ViewCursorWidget.tsx @@ -13,7 +13,7 @@ import { ViewCursorEditSvgString, ViewCursorMoveSvgString } from '../../../../as export const INIT_SVG_SCALE = 0.003; export const INIT_SVG_VECTOR = new THREEVector3(INIT_SVG_SCALE, INIT_SVG_SCALE, INIT_SVG_SCALE); -export const ViewCursorWidget = () => { +export const ViewCursorWidget = (): React.JSX.Element => { const ref = useRef(null); const { gl } = useThree(); const sceneComposerId = useContext(sceneComposerIdContext); @@ -60,11 +60,15 @@ export const ViewCursorWidget = () => { // Intersections are sorted const closestIntersection = intersects[0]; const n = getIntersectionTransform(closestIntersection); - shape.lookAt(n.normal as THREEVector3); - shape.position.copy(n.position); - // Set scale based on intersection distance - shape.scale.copy(INIT_SVG_VECTOR); - shape.scale.multiplyScalar(closestIntersection.distance); + const normalVector = n.normal as THREEVector3; + // Intersection surface normal may not be a uniform vector, like for point clouds + if (normalVector) { + shape.lookAt(n.normal as THREEVector3); + shape.position.copy(n.position); + // Set scale based on intersection distance + shape.scale.copy(INIT_SVG_VECTOR); + shape.scale.multiplyScalar(closestIntersection.distance); + } } }); diff --git a/packages/scene-composer/src/components/panels/SceneHierarchyPanel/components/SceneHierarchyTree/SceneHierarchyTreeItem.tsx b/packages/scene-composer/src/components/panels/SceneHierarchyPanel/components/SceneHierarchyTree/SceneHierarchyTreeItem.tsx index 6d45daa3d..27456f11d 100644 --- a/packages/scene-composer/src/components/panels/SceneHierarchyPanel/components/SceneHierarchyTree/SceneHierarchyTreeItem.tsx +++ b/packages/scene-composer/src/components/panels/SceneHierarchyPanel/components/SceneHierarchyTree/SceneHierarchyTreeItem.tsx @@ -10,6 +10,7 @@ import { IModelRefComponentInternal, useSceneDocument } from '../../../../../sto import { findComponentByType } from '../../../../../utils/nodeUtils'; import { sceneComposerIdContext } from '../../../../../common/sceneComposerIdContext'; import { isDynamicNode } from '../../../../../utils/entityModelUtils/sceneUtils'; +import { ModelType } from '../../../../../models/SceneModels'; import SceneNodeLabel from './SceneNodeLabel'; import { AcceptableDropTypes, EnhancedTree, EnhancedTreeItem } from './constants'; @@ -45,8 +46,9 @@ const SceneHierarchyTreeItem: FC = ({ const node = getSceneNodeByRef(key); const component = findComponentByType(node, KnownComponentType.ModelRef) as IModelRefComponentInternal; const componentRef = component?.ref; + // Show sub models for non Tiles3D models in edit mode const showSubModel = useMemo(() => { - return component && !!model && !isViewing(); + return component && component.modelType !== ModelType.Tiles3D && !!model && !isViewing(); }, [component, model]); const isSubModel = !!findComponentByType(node, KnownComponentType.SubModelRef); const isDynamic = isDynamicNode(node); diff --git a/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.spec.tsx b/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.spec.tsx index debfa5fb6..806636722 100644 --- a/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.spec.tsx +++ b/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.spec.tsx @@ -10,6 +10,7 @@ jest.doMock('../../../../../src/utils/nodeUtils', () => ({ import { AddObjectMenu } from './AddObjectMenu'; import { IColorOverlayComponentInternal, useStore } from '../../../../store'; import { + AssetType, COMPOSER_FEATURES, DEFAULT_CAMERA_OPTIONS, DEFAULT_LIGHT_SETTINGS_MAP, @@ -27,12 +28,9 @@ import { CameraType, Component, LightType } from '../../../../models/SceneModels import { createNodeWithTransform } from '../../../../utils/nodeUtils'; import { ToolbarOrientation } from '../../common/types'; import { isDynamicScene } from '../../../../utils/entityModelUtils/sceneUtils'; +import { TILESET_JSON } from '../../../../utils/sceneAssetUtils'; /* eslint-enable */ -jest.mock('../../../../utils/pathUtils', () => ({ - extractFileNameExtFromUrl: jest.fn().mockReturnValue(['filename', 'ext']), -})); - jest.mock('../../../../utils/entityModelUtils/sceneUtils', () => ({ isDynamicScene: jest.fn(), })); @@ -42,6 +40,7 @@ describe('AddObjectMenu', () => { const appendSceneNode = jest.fn(); const showAssetBrowserCallback = jest.fn(); const setAddingWidget = jest.fn(); + const addMessages = jest.fn(); const selectedSceneNodeRef = 'test-ref'; const mockMetricRecorder = { recordClick: jest.fn(), @@ -61,6 +60,7 @@ describe('AddObjectMenu', () => { }), setAddingWidget, mainCameraObject, + addMessages, } as any); jest.clearAllMocks(); @@ -177,12 +177,15 @@ describe('AddObjectMenu', () => { }); it('should call setAddingWidget when adding a model', () => { + const expectedNodeName = 'modelUri'; + const filename = `${expectedNodeName}.${AssetType.GLTF}`; + const modelUri = `bucket/assets/${filename}`; const gltfComponent: IModelRefComponent = { - type: 'ModelRef', - uri: 'modelUri', - modelType: 'EXT', + type: KnownComponentType.ModelRef, + uri: modelUri, + modelType: AssetType.GLTF, }; - showAssetBrowserCallback.mockImplementationOnce((callback) => callback(null, 'modelUri')); + showAssetBrowserCallback.mockImplementationOnce((callback) => callback(null, modelUri)); render(); const sut = screen.getByTestId('add-object-model'); @@ -190,7 +193,7 @@ describe('AddObjectMenu', () => { expect(setAddingWidget).toBeCalledWith({ type: KnownComponentType.ModelRef, node: { - name: 'filename', + name: expectedNodeName, components: [gltfComponent], parentRef: selectedSceneNodeRef, }, @@ -199,6 +202,41 @@ describe('AddObjectMenu', () => { expect(mockMetricRecorder.recordClick).toBeCalledWith('add-object-model'); }); + it('should call setAddingWidget when adding a tiles3d model', () => { + const expectedNodeName = 'MixerTileset'; + const modelUri = `bucket/assets/${expectedNodeName}/${TILESET_JSON}`; + const gltfComponent: IModelRefComponent = { + type: KnownComponentType.ModelRef, + uri: modelUri, + modelType: AssetType.TILES_3D, + }; + showAssetBrowserCallback.mockImplementationOnce((callback) => callback(null, modelUri)); + + render(); + const sut = screen.getByTestId('add-object-model'); + fireEvent.pointerUp(sut); + expect(setAddingWidget).toBeCalledWith({ + type: KnownComponentType.ModelRef, + node: { + name: expectedNodeName, + components: [gltfComponent], + parentRef: selectedSceneNodeRef, + }, + }); + expect(mockMetricRecorder.recordClick).toBeCalledTimes(1); + expect(mockMetricRecorder.recordClick).toBeCalledWith('add-object-model'); + }); + + it('should ignore action and display a message when adding an invalid model type', () => { + showAssetBrowserCallback.mockImplementationOnce((callback) => callback(null, 'file.invalid')); + + render(); + const sut = screen.getByTestId('add-object-model'); + fireEvent.pointerUp(sut); + expect(setAddingWidget).toBeCalledTimes(0); + expect(addMessages).toBeCalledTimes(1); + }); + it('should call addComponentInternal when adding a model shader', () => { const colorOverlayComponent: IColorOverlayComponentInternal = { ref: expect.any(String), diff --git a/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.tsx b/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.tsx index 9f328a0e1..89711a135 100644 --- a/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.tsx +++ b/packages/scene-composer/src/components/toolbars/floatingToolbar/items/AddObjectMenu.tsx @@ -21,7 +21,7 @@ import { import { sceneComposerIdContext } from '../../../../common/sceneComposerIdContext'; import { Component, LightType } from '../../../../models/SceneModels'; import { IColorOverlayComponentInternal, ISceneNodeInternal, useEditorState, useStore } from '../../../../store'; -import { extractFileNameExtFromUrl, parseS3BucketFromArn } from '../../../../utils/pathUtils'; +import { parseS3BucketFromArn } from '../../../../utils/pathUtils'; import { ToolbarItem } from '../../common/ToolbarItem'; import { ToolbarItemOptionRaw, ToolbarItemOptions, ToolbarOrientation } from '../../common/types'; import { getGlobalSettings } from '../../../../common/GlobalSettings'; @@ -31,6 +31,7 @@ import { createNodeWithTransform, findComponentByType } from '../../../../utils/ import { FLOATING_TOOLBAR_VERTICAL_ORIENTATION_BUFFER } from '../FloatingToolbar'; import { TOOLBAR_ITEM_CONTAINER_HEIGHT } from '../../common/styledComponents'; import { isDynamicScene } from '../../../../utils/entityModelUtils/sceneUtils'; +import { evaluateModelType } from '../../../../utils/sceneAssetUtils'; // Note: ObjectType String is used to record metric. DO NOT change existing ids unless it's necessary. enum ObjectTypes { @@ -88,6 +89,7 @@ export const AddObjectMenu = ({ canvasHeight, toolbarOrientation }: AddObjectMen const getSceneNodeByRef = useStore(sceneComposerId)((state) => state.getSceneNodeByRef); const document = useStore(sceneComposerId)((state) => state.document); const nodeMap = useStore(sceneComposerId)((state) => state.document.nodeMap); + const addMessages = useStore(sceneComposerId)((state) => state.addMessages); const { setAddingWidget, getObject3DBySceneNodeRef } = useEditorState(sceneComposerId); const { enableMatterportViewer } = useMatterportViewer(); const { formatMessage } = useIntl(); @@ -197,7 +199,7 @@ export const AddObjectMenu = ({ canvasHeight, toolbarOrientation }: AddObjectMen }); }, [selectedSceneNodeRef]); - const handleAddViewCamera = useCallback(() => { + const handleAddViewCamera = () => { if (mainCameraObject) { const cameraComponent: ICameraComponent = { cameraType: activeCameraSettings.cameraType, @@ -237,12 +239,18 @@ export const AddObjectMenu = ({ canvasHeight, toolbarOrientation }: AddObjectMen appendSceneNode(newNode); } - }, [selectedSceneNodeRef]); + }; - const handleAddModel = (modelType?: string, mustBeRoot = false) => { + const handleAddModel = (mustBeRoot = false) => { if (showAssetBrowserCallback) { showAssetBrowserCallback((s3BucketArn, contentLocation) => { - const [filename, ext] = extractFileNameExtFromUrl(contentLocation); + // Check that the file is a valid 3D model type + const result = evaluateModelType(contentLocation, addMessages, formatMessage); + + // If the file is not valid to load into the scene then ignore it + if (!result) { + return; + } let modelUri: string; if (s3BucketArn === null) { @@ -253,13 +261,13 @@ export const AddObjectMenu = ({ canvasHeight, toolbarOrientation }: AddObjectMen } const gltfComponent: IModelRefComponent = { - type: 'ModelRef', + type: KnownComponentType.ModelRef, uri: modelUri, - modelType: modelType ?? ext.toUpperCase(), + modelType: result.modelType, }; const node = { - name: filename, + name: result.modelName, components: [gltfComponent], parentRef: mustBeRoot ? undefined : selectedSceneNodeRef, } as unknown as ISceneNodeInternal; diff --git a/packages/scene-composer/src/interfaces/assets.ts b/packages/scene-composer/src/interfaces/assets.ts index e791465ca..c97c6e2ce 100644 --- a/packages/scene-composer/src/interfaces/assets.ts +++ b/packages/scene-composer/src/interfaces/assets.ts @@ -8,7 +8,8 @@ export enum AssetType { MP4 = 'MP4', PDF = 'PDF', PNG = 'PNG', + TILES_3D = 'Tiles3D', } -export const ModelFileTypeList: AssetType[] = [AssetType.GLB, AssetType.GLTF]; +export const ModelFileTypeList: AssetType[] = [AssetType.GLB, AssetType.GLTF, AssetType.TILES_3D]; export const TextureFileTypeList: AssetType[] = [AssetType.JPG, AssetType.JPEG, AssetType.PNG]; diff --git a/packages/scene-composer/src/utils/sceneAssetUtils.ts b/packages/scene-composer/src/utils/sceneAssetUtils.ts new file mode 100644 index 000000000..4603dbf2c --- /dev/null +++ b/packages/scene-composer/src/utils/sceneAssetUtils.ts @@ -0,0 +1,49 @@ +import path from 'path'; + +import { IntlFormatters } from '@formatjs/intl'; + +import { AssetType, ModelFileTypeList } from '../interfaces'; +import { DisplayMessageCategory, IDisplayMessage } from '../store/internalInterfaces'; + +import { extractFileNameExtFromUrl } from './pathUtils'; + +export const TILESET_JSON = 'tileset.json'; + +export const evaluateModelType = ( + filePath: string, + addMessages: (messages: IDisplayMessage[]) => void, + formatMessage: IntlFormatters['formatMessage'], +): { modelName: string; modelType: AssetType } | undefined => { + const [name, ext] = extractFileNameExtFromUrl(filePath); + const modelType: AssetType = ext.toUpperCase() as AssetType; + + const fileName = `${name}.${ext}`; + + // Tiles3D asset type + if (fileName === TILESET_JSON) { + // Node name is the parent directory name + const dir = path.dirname(filePath); + const modelName = dir === '.' ? name : dir.split('/').pop(); + return { + modelName: modelName!, + modelType: AssetType.TILES_3D, + }; + } + + if (!ModelFileTypeList.includes(modelType)) { + const messageText = formatMessage( + { + defaultMessage: `File with extension {modelType} is not a supported model type`, + description: 'Warning for selecting an unsupported file type', + }, + { modelType }, + ); + addMessages([{ category: DisplayMessageCategory.Warning, messageText }]); + return; + } + + return { + modelName: name, + modelType: AssetType[modelType], + }; +}; diff --git a/packages/scene-composer/stories/Developer/SceneComposer.stories.mdx b/packages/scene-composer/stories/Developer/SceneComposer.stories.mdx index ab4527dbc..2ea63db8d 100644 --- a/packages/scene-composer/stories/Developer/SceneComposer.stories.mdx +++ b/packages/scene-composer/stories/Developer/SceneComposer.stories.mdx @@ -9,6 +9,7 @@ import { COMPOSER_FEATURES } from '../../src/interfaces/feature'; export const defaultArgs = { source: 'local', scene: 'scene_1', + assetType: 'GLB', theme: 'dark', mode: 'Editing', density: 'comfortable', diff --git a/packages/scene-composer/stories/FirstPerson.stories.mdx b/packages/scene-composer/stories/FirstPerson.stories.mdx index 8d61ef914..26d12d040 100644 --- a/packages/scene-composer/stories/FirstPerson.stories.mdx +++ b/packages/scene-composer/stories/FirstPerson.stories.mdx @@ -9,6 +9,7 @@ import { COMPOSER_FEATURES } from '../src/interfaces/feature'; export const defaultArgs = { source: 'local', scene: 'scene1', + assetType: 'GLB', theme: 'dark', mode: 'Viewing', density: 'comfortable', diff --git a/packages/scene-composer/stories/Highlight.stories.mdx b/packages/scene-composer/stories/Highlight.stories.mdx index 48b94d873..6ee69168d 100644 --- a/packages/scene-composer/stories/Highlight.stories.mdx +++ b/packages/scene-composer/stories/Highlight.stories.mdx @@ -10,6 +10,7 @@ import { COMPOSER_FEATURES } from '../src/interfaces/feature'; export const defaultArgs = { source: 'local', scene: 'scene1', + assetType: 'GLB', theme: 'dark', mode: 'Viewing', density: 'comfortable', diff --git a/packages/scene-composer/stories/Matterport.stories.mdx b/packages/scene-composer/stories/Matterport.stories.mdx index ad4dff045..247d61d9f 100644 --- a/packages/scene-composer/stories/Matterport.stories.mdx +++ b/packages/scene-composer/stories/Matterport.stories.mdx @@ -9,6 +9,7 @@ import { COMPOSER_FEATURES } from '../src/interfaces/feature'; export const defaultArgs = { source: 'local', scene: 'scene1', + assetType: 'GLB', theme: 'dark', mode: 'Viewing', density: 'comfortable', diff --git a/packages/scene-composer/stories/components/argTypes.ts b/packages/scene-composer/stories/components/argTypes.ts index 88721d77b..2c42bec5a 100644 --- a/packages/scene-composer/stories/components/argTypes.ts +++ b/packages/scene-composer/stories/components/argTypes.ts @@ -1,6 +1,6 @@ import { Density, Mode } from '@awsui/global-styles'; -import { COMPOSER_FEATURES } from '../../src'; +import { AssetType, COMPOSER_FEATURES } from '../../src'; import scenes from '../scenes'; export const viewerArgTypes = { @@ -11,6 +11,12 @@ export const viewerArgTypes = { table: { category: 'Scene' }, if: { arg: 'source', eq: 'local' }, }, + assetType: { + options: Object.values(AssetType), + control: 'select', + table: { category: 'Scene' }, + if: { arg: 'source', eq: 'local' }, + }, workspaceId: { if: { arg: 'source', eq: 'aws' }, table: { category: 'Scene' }, diff --git a/packages/scene-composer/stories/components/scene-composer.tsx b/packages/scene-composer/stories/components/scene-composer.tsx index 4ee1c2379..02e142883 100644 --- a/packages/scene-composer/stories/components/scene-composer.tsx +++ b/packages/scene-composer/stories/components/scene-composer.tsx @@ -16,6 +16,8 @@ import { SceneComposerInternal, SceneViewerPropsShared, ShowAssetBrowserCallback, + ModelFileTypeList, + TextureFileTypeList, } from '../../src'; import { convertDataInputToDataStreams, getTestDataInputContinuous } from '../../tests/testData'; @@ -53,6 +55,7 @@ interface SceneComposerWrapperProps extends SceneViewerPropsShared, ThemeManager viewportDurationSecs?: number; queriesJSON?: string; showAssetBrowserCallback: ShowAssetBrowserCallback; + assetType?: AssetType; } const SceneComposerWrapper: FC = ({ @@ -72,6 +75,7 @@ const SceneComposerWrapper: FC = ({ viewportDurationSecs, queriesJSON, showAssetBrowserCallback: actionRecorderShowAssetBrowserCallback, + assetType = AssetType.GLB, ...props }: SceneComposerWrapperProps) => { const duration = viewportDurationSecs ? viewportDurationSecs : 300; //default 5 minutes @@ -130,26 +134,34 @@ const SceneComposerWrapper: FC = ({ onSceneUpdated(sceneSnapshot); }, []); + const defaultAssetBrowserCallback = (cb: AssetBrowserResultCallback) => { + cb(null, 'PALLET_JACK.glb'); + }; + const mockAssetBrowserCallback: ShowAssetBrowserCallback = useCallback( (cb: AssetBrowserResultCallback, typeList?: AssetType[]) => { actionRecorderShowAssetBrowserCallback(cb); if (source === 'local') { if (typeList) { - if (typeList.includes(AssetType.GLB)) { - cb(null, 'PALLET_JACK.glb'); - } else if (typeList.includes(AssetType.PNG)) { + if (typeList === ModelFileTypeList) { + if (assetType === AssetType.TILES_3D) { + cb(null, 'MIXER_Tiles3D/tileset.json'); + } else { + defaultAssetBrowserCallback(cb); + } + } else if (typeList === TextureFileTypeList) { cb(null, 'PB_AWS_logo_RGB_stacked.png'); } else { - cb(null, 'PALLET_JACK.glb'); + defaultAssetBrowserCallback(cb); } } else { - cb(null, 'PALLET_JACK.glb'); + defaultAssetBrowserCallback(cb); } } else { cb(null, 'CookieFactoryMixer.glb'); // Update the string to a model available in your S3 bucket } }, - [source], + [source, assetType], ); if (loader) { diff --git a/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json b/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json index 3baf5ec1f..977e958b2 100644 --- a/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json +++ b/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json @@ -867,6 +867,10 @@ "note": "times", "text": "x" }, + "gIcLg9": { + "note": "Warning for selecting an unsupported file type", + "text": "File with extension {modelType} is not a supported model type" + }, "gOijHE": { "note": "Specifies the localized string that describes an option as being selected. This is required to provide a good screen reader experience", "text": "Selected"