You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/AutomatedTesting/Editor/Scripts/scene_helpers.py

110 lines
3.5 KiB
Python

#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
import traceback, logging, json
from typing import Tuple, List
import azlmbr.bus
from scene_api import scene_data as sceneData
from scene_api.scene_data import SceneGraphName
def log_exception_traceback():
"""Outputs an exception stacktrace."""
data = traceback.format_exc()
logger = logging.getLogger('python')
logger.error(data)
def sanitize_name_for_disk(name: str) -> str:
"""Removes illegal filename characters from a string.
Parameters
----------
name :
String to clean.
Returns
-------
str
Name with illegal characters removed.
"""
return "".join(char for char in name if char not in "|<>:\"/?*\\")
def get_mesh_node_names(scene_graph: sceneData.SceneGraph) -> Tuple[List[SceneGraphName], List[str]]:
"""Returns a tuple of all the mesh nodes as well as all the node paths
Parameters
----------
scene_graph :
Scene graph to search
Returns
-------
Tuple[List[SceneGraphName], List[str]]
Tuple of [Mesh Nodes, All Node Paths]
"""
import azlmbr.scene as sceneApi
import azlmbr.scene.graph
mesh_data_list = []
node = scene_graph.get_root()
children = []
paths = []
while node.IsValid():
# store children to process after siblings
if scene_graph.has_node_child(node):
children.append(scene_graph.get_node_child(node))
node_name = sceneData.SceneGraphName(scene_graph.get_node_name(node))
paths.append(node_name.get_path())
# store any node that has mesh data content
node_content = scene_graph.get_node_content(node)
if node_content.CastWithTypeName('MeshData'):
if scene_graph.is_node_end_point(node) is False:
if len(node_name.get_path()):
mesh_data_list.append(sceneData.SceneGraphName(scene_graph.get_node_name(node)))
# advance to next node
if scene_graph.has_node_sibling(node):
node = scene_graph.get_node_sibling(node)
elif children:
node = children.pop()
else:
node = azlmbr.scene.graph.NodeIndex()
return mesh_data_list, paths
def create_prefab(scene_manifest: sceneData.SceneManifest, prefab_name: str, entities: list) -> None:
prefab_filename = prefab_name + ".prefab"
created_template_id = azlmbr.prefab.PrefabSystemScriptingBus(azlmbr.bus.Broadcast, "CreatePrefab", entities,
prefab_filename)
if created_template_id is None or created_template_id == azlmbr.prefab.InvalidTemplateId:
raise RuntimeError("CreatePrefab {} failed".format(prefab_filename))
# Convert the prefab to a JSON string
output = azlmbr.prefab.PrefabLoaderScriptingBus(azlmbr.bus.Broadcast, "SaveTemplateToString", created_template_id)
if output is not None and output.IsSuccess():
json_string = output.GetValue()
uuid = azlmbr.math.Uuid_CreateRandom().ToString()
json_result = json.loads(json_string)
# Add a PrefabGroup to the manifest and store the JSON on it
scene_manifest.add_prefab_group(prefab_name, uuid, json_result)
else:
raise RuntimeError(
"SaveTemplateToString failed for template id {}, prefab {}".format(created_template_id, prefab_filename))