// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 /* eslint-disable import/no-unresolved */ import {MenuItem} from '@blueprintjs/core'; import {TransformNode} from 'babylonjs'; import {Editor, SceneExporter, WorkSpace} from 'babylonjs-editor'; import React from 'react'; import {SumerianHostAdder} from './hostAdder'; import { AssetsNotFoundError, installDependencies, prepareWorkspace, WorkspaceNotPreparedError, } from './workspace'; // eslint-disable-next-line @typescript-eslint/no-var-requires const configuration = require('../config/SceneRequirements.json'); /** * The configuration that the Sumerian 'add host' menu should be initialized with */ interface ISumerianAddHostMenuProps { /** * A reference to the BabylonJS Editor object * @see {@link Editor} */ editor: Editor; /** * The absolute path to where the plugin package is found. */ pluginPath: string; } export default class SumerianAddHostMenu extends React.Component { availableHosts: string[]; public constructor(props) { super(props); this.availableHosts = SumerianHostAdder.getAvailableHosts(); } private _handleAddClick = async (event) => { const {editor, pluginPath} = this.props; const currentScene = editor.scene; const selectedCharacter = event.target.textContent; const workSpaceDir = WorkSpace.DirPath ?? ''; const addHostProgress = editor.addTaskFeedback(100, 'Adding Sumerian Host'); if (currentScene) { // First - try to install dependencies in the scene // It is not a hard blocker if this does not succeed, as the main reason this fails is because // npm cannot be found - in which case the user has a manual workaround available to them to fix this try { editor.updateTaskFeedback( addHostProgress, 0, 'Installing dependencies in scene' ); await installDependencies( workSpaceDir, configuration.runtimeDependencies ); } catch (error) { editor.console.logError( 'Dependencies were not successfully installed due to error: ' ); editor.console.logError(error.message); editor.console.logError( 'For any failed npm installs above, run each listed install command manually from the root of this Editor workspace.' ); } try { editor.updateTaskFeedback( addHostProgress, 10, 'Copying required files into scene' ); await prepareWorkspace(pluginPath, workSpaceDir); editor.updateTaskFeedback(addHostProgress, 20, 'Validating assets'); const hostAdder = new SumerianHostAdder( workSpaceDir, selectedCharacter ); // Create AWSConnector node if not already present. const awsConnectorNodeName = 'AWSConnector'; if (!currentScene.getNodeByName(awsConnectorNodeName)) { const awsConnectorNode = new TransformNode( awsConnectorNodeName, currentScene ); awsConnectorNode.metadata = { script: { name: 'src/scenes/AwsTools/AwsCognitoIdConnectorScript.ts', }, }; } editor.updateTaskFeedback( addHostProgress, 25, 'Adding Sumerian Host to scene' ); const characterAsset = await hostAdder.addToScene(currentScene, editor); editor.updateTaskFeedback( addHostProgress, 50, 'Attaching initialization script to Sumerian Host' ); hostAdder.attachInitScriptToHost(characterAsset); editor.updateTaskFeedback(addHostProgress, 75, 'Updating editor'); // update script mapping; this gets done automatically when the user hits 'play' // as the scene auto-saves (exports) before it runs, but we want to update ASAP // so that the scene code-base (which has the script mapping copied into it) reflects the changes await SceneExporter.GenerateScripts(editor); editor.updateTaskFeedback( addHostProgress, 100, 'Successfully added Sumerian Host' ); } catch (error) { let errorMessage = 'An error has occurred while adding a Sumerian Host:'; let errorStatus = 'An error has occurred while adding a Sumerian Host'; switch (error.constructor) { case AssetsNotFoundError: errorMessage = 'An error has occurred while initializing a Sumerian Host; the assets could not be found. Were they downloaded correctly when this plugin was installed?'; errorStatus = 'An error has ocurred while initializing a Sumerian Host'; break; case WorkspaceNotPreparedError: errorMessage = 'An error has occurred while copying necessary files into your workspace.'; errorStatus = 'An error has ocurred while preparing the workspace'; break; default: break; } console.log(error); editor.console.logError(errorMessage); editor.console.logError(error.message); editor.updateTaskFeedback(addHostProgress, 0, errorStatus); } finally { editor.graph.refresh(); // update editor's scene graph to show the new Host node editor.closeTaskFeedback(addHostProgress, 15000); } } }; public render(): React.ReactNode { return ( {this.availableHosts.map((characterId) => ( ))} ); } }