Merge branch 'development' into cmake/SPEC-7182
commit
5f22dc817c
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"AssetProcessor": {
|
||||
"Settings": {
|
||||
"RC cgf": {
|
||||
"ignore": true
|
||||
},
|
||||
"RC fbx": {
|
||||
"ignore": true
|
||||
},
|
||||
"ScanFolder AtomTestData": {
|
||||
"watch": "@ENGINEROOT@/Gems/Atom/TestData",
|
||||
"recursive": 1,
|
||||
"order": 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,183 @@
|
||||
"""
|
||||
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 azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe
|
||||
This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe
|
||||
You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
|
||||
|
||||
import atom_renderer.atom_utils.material_editor_utils as material_editor
|
||||
|
||||
NEW_MATERIAL = "test_material.material"
|
||||
NEW_MATERIAL_1 = "test_material_1.material"
|
||||
NEW_MATERIAL_2 = "test_material_2.material"
|
||||
TEST_MATERIAL_1 = "001_DefaultWhite.material"
|
||||
TEST_MATERIAL_2 = "002_BaseColorLerp.material"
|
||||
TEST_MATERIAL_3 = "003_MetalMatte.material"
|
||||
TEST_DATA_PATH = os.path.join(
|
||||
azlmbr.paths.devroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
|
||||
)
|
||||
MATERIAL_TYPE_PATH = os.path.join(
|
||||
azlmbr.paths.devroot, "Gems", "Atom", "Feature", "Common", "Assets",
|
||||
"Materials", "Types", "StandardPBR.materialtype",
|
||||
)
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
Summary:
|
||||
Material Editor basic tests including the below
|
||||
1. Opening an Existing Asset
|
||||
2. Creating a New Asset
|
||||
3. Closing Selected Material
|
||||
4. Closing All Materials
|
||||
5. Closing all but Selected Material
|
||||
6. Saving Material
|
||||
7. Saving as a New Material
|
||||
8. Saving as a Child Material
|
||||
9. Saving all Open Materials
|
||||
|
||||
Expected Result:
|
||||
All the above functions work as expected in Material Editor.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
# 1) Test Case: Opening an Existing Asset
|
||||
document_id = material_editor.open_material(MATERIAL_TYPE_PATH)
|
||||
print(f"Material opened: {material_editor.is_open(document_id)}")
|
||||
|
||||
# Verify if the test material exists initially
|
||||
target_path = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL)
|
||||
print(f"Test asset doesn't exist initially: {not os.path.exists(target_path)}")
|
||||
|
||||
# 2) Test Case: Creating a New Material Using Existing One
|
||||
material_editor.save_document_as_child(document_id, target_path)
|
||||
material_editor.wait_for_condition(lambda: os.path.exists(target_path), 2.0)
|
||||
print(f"New asset created: {os.path.exists(target_path)}")
|
||||
|
||||
# Verify if the newly created document is open
|
||||
new_document_id = material_editor.open_material(target_path)
|
||||
material_editor.wait_for_condition(lambda: material_editor.is_open(new_document_id))
|
||||
print(f"New Material opened: {material_editor.is_open(new_document_id)}")
|
||||
|
||||
# 3) Test Case: Closing Selected Material
|
||||
print(f"Material closed: {material_editor.close_document(new_document_id)}")
|
||||
|
||||
# Open materials initially
|
||||
document1_id, document2_id, document3_id = (
|
||||
material_editor.open_material(os.path.join(TEST_DATA_PATH, material))
|
||||
for material in [TEST_MATERIAL_1, TEST_MATERIAL_2, TEST_MATERIAL_3]
|
||||
)
|
||||
|
||||
# 4) Test Case: Closing All Materials
|
||||
print(f"All documents closed: {material_editor.close_all_documents()}")
|
||||
|
||||
# 5) Test Case: Closing all but Selected Material
|
||||
document1_id, document2_id, document3_id = (
|
||||
material_editor.open_material(os.path.join(TEST_DATA_PATH, material))
|
||||
for material in [TEST_MATERIAL_1, TEST_MATERIAL_2, TEST_MATERIAL_3]
|
||||
)
|
||||
result = material_editor.close_all_except_selected(document1_id)
|
||||
print(f"Close All Except Selected worked as expected: {result and material_editor.is_open(document1_id)}")
|
||||
|
||||
# 6) Test Case: Saving Material
|
||||
document_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
|
||||
property_name = azlmbr.name.Name("baseColor.color")
|
||||
initial_color = material_editor.get_property(document_id, property_name)
|
||||
# Assign new color to the material file and save the actual material
|
||||
expected_color = math.Color(0.25, 0.25, 0.25, 1.0)
|
||||
material_editor.set_property(document_id, property_name, expected_color)
|
||||
material_editor.save_document(document_id)
|
||||
|
||||
# 7) Test Case: Saving as a New Material
|
||||
# Assign new color to the material file and save the document as copy
|
||||
expected_color_1 = math.Color(0.5, 0.5, 0.5, 1.0)
|
||||
material_editor.set_property(document_id, property_name, expected_color_1)
|
||||
target_path_1 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_1)
|
||||
material_editor.save_document_as_copy(document_id, target_path_1)
|
||||
time.sleep(2.0)
|
||||
|
||||
# 8) Test Case: Saving as a Child Material
|
||||
# Assign new color to the material file save the document as child
|
||||
expected_color_2 = math.Color(0.75, 0.75, 0.75, 1.0)
|
||||
material_editor.set_property(document_id, property_name, expected_color_2)
|
||||
target_path_2 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_2)
|
||||
material_editor.save_document_as_child(document_id, target_path_2)
|
||||
time.sleep(2.0)
|
||||
|
||||
# Close/Reopen documents
|
||||
material_editor.close_all_documents()
|
||||
document_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
|
||||
document1_id = material_editor.open_material(target_path_1)
|
||||
document2_id = material_editor.open_material(target_path_2)
|
||||
|
||||
# Verify if the changes are saved in the actual document
|
||||
actual_color = material_editor.get_property(document_id, property_name)
|
||||
print(f"Actual Document saved with changes: {material_editor.compare_colors(actual_color, expected_color)}")
|
||||
|
||||
# Verify if the changes are saved in the document saved as copy
|
||||
actual_color = material_editor.get_property(document1_id, property_name)
|
||||
result_copy = material_editor.compare_colors(actual_color, expected_color_1)
|
||||
print(f"Document saved as copy is saved with changes: {result_copy}")
|
||||
|
||||
# Verify if the changes are saved in the document saved as child
|
||||
actual_color = material_editor.get_property(document2_id, property_name)
|
||||
result_child = material_editor.compare_colors(actual_color, expected_color_2)
|
||||
print(f"Document saved as child is saved with changes: {result_child}")
|
||||
|
||||
# Revert back the changes in the actual document
|
||||
material_editor.set_property(document_id, property_name, initial_color)
|
||||
material_editor.save_document(document_id)
|
||||
material_editor.close_all_documents()
|
||||
|
||||
# 9) Test Case: Saving all Open Materials
|
||||
# Open first material and make change to the values
|
||||
document1_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
|
||||
property1_name = azlmbr.name.Name("metallic.factor")
|
||||
initial_metallic_factor = material_editor.get_property(document1_id, property1_name)
|
||||
expected_metallic_factor = 0.444
|
||||
material_editor.set_property(document1_id, property1_name, expected_metallic_factor)
|
||||
|
||||
# Open second material and make change to the values
|
||||
document2_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_2))
|
||||
property2_name = azlmbr.name.Name("baseColor.color")
|
||||
initial_color = material_editor.get_property(document2_id, property2_name)
|
||||
expected_color = math.Color(0.4156, 0.0196, 0.6862, 1.0)
|
||||
material_editor.set_property(document2_id, property2_name, expected_color)
|
||||
|
||||
# Save all and close all documents
|
||||
material_editor.save_all()
|
||||
material_editor.close_all_documents()
|
||||
|
||||
# Reopen materials and verify values
|
||||
document1_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
|
||||
result = material_editor.is_close(
|
||||
material_editor.get_property(document1_id, property1_name), expected_metallic_factor, 0.00001
|
||||
)
|
||||
document2_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_2))
|
||||
result = result and material_editor.compare_colors(
|
||||
expected_color, material_editor.get_property(document2_id, property2_name))
|
||||
print(f"Save All worked as expected: {result}")
|
||||
|
||||
# Revert the changes made
|
||||
material_editor.set_property(document1_id, property1_name, initial_metallic_factor)
|
||||
material_editor.set_property(document2_id, property2_name, initial_color)
|
||||
material_editor.save_all()
|
||||
material_editor.close_all_documents()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@ -0,0 +1,268 @@
|
||||
"""
|
||||
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
|
||||
|
||||
Hydra script that is used to create an entity with a Light component attached.
|
||||
It then updates the property values of the Light component and takes a screenshot.
|
||||
The screenshot is compared against an expected golden image for test verification.
|
||||
|
||||
See the run() function for more in-depth test info.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from atom_renderer.atom_utils import screenshot_utils
|
||||
from atom_renderer.atom_utils import atom_component_helper
|
||||
from editor_python_test_tools.editor_test_helper import EditorTestHelper
|
||||
|
||||
helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
|
||||
|
||||
LEVEL_NAME = "auto_test"
|
||||
LIGHT_COMPONENT = "Light"
|
||||
LIGHT_TYPE_PROPERTY = 'Controller|Configuration|Light type'
|
||||
DEGREE_RADIAN_FACTOR = 0.0174533
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
Sets up the tests by making sure the required level is created & setup correctly.
|
||||
It then executes 2 test cases - see each associated test function's docstring for more info.
|
||||
|
||||
Finally prints the string "Light component tests completed" after completion
|
||||
|
||||
Tests will fail immediately if any of these log lines are found:
|
||||
1. Trace::Assert
|
||||
2. Trace::Error
|
||||
3. Traceback (most recent call last):
|
||||
|
||||
:return: None
|
||||
"""
|
||||
atom_component_helper.create_basic_atom_level(level_name=LEVEL_NAME)
|
||||
|
||||
# Run tests.
|
||||
area_light_test()
|
||||
spot_light_test()
|
||||
general.log("Light component tests completed.")
|
||||
|
||||
|
||||
def area_light_test():
|
||||
"""
|
||||
Basic test for the "Light" component attached to an "area_light" entity.
|
||||
|
||||
Test Case - Light Component: Capsule, Spot (disk), and Point (sphere):
|
||||
1. Creates "area_light" entity w/ a Light component that has a Capsule Light type w/ the color set to 255, 0, 0
|
||||
2. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
3. Sets the Light component Intensity Mode to Lumens (default).
|
||||
4. Ensures the Light component Mode is Automatic (default).
|
||||
5. Sets the Intensity value of the Light component to 0.0
|
||||
6. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
7. Updates the Intensity value of the Light component to 1000.0
|
||||
8. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
9. Swaps the Capsule light type option to Spot (disk) light type on the Light component
|
||||
10. Updates "area_light" entity Transform rotate value to x: 90.0, y:0.0, z:0.0
|
||||
11. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
12. Swaps the Spot (disk) light type for the Point (sphere) light type in the Light component.
|
||||
13. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
14. Deletes the Light component from the "area_light" entity and verifies its successful.
|
||||
"""
|
||||
# Create an "area_light" entity with "Light" component using Light type of "Capsule"
|
||||
area_light_entity_name = "area_light"
|
||||
area_light = hydra.Entity(area_light_entity_name)
|
||||
area_light.create_entity(math.Vector3(-1.0, -2.0, 3.0), [LIGHT_COMPONENT])
|
||||
general.log(
|
||||
f"{area_light_entity_name}_test: Component added to the entity: "
|
||||
f"{hydra.has_components(area_light.id, [LIGHT_COMPONENT])}")
|
||||
light_component_id_pair = hydra.attach_component_to_entity(area_light.id, LIGHT_COMPONENT)
|
||||
|
||||
# Select the "Capsule" light type option.
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_id_pair,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_component_helper.LIGHT_TYPES['capsule']
|
||||
)
|
||||
|
||||
# Update color and take screenshot in game mode
|
||||
color = math.Color(255.0, 0.0, 0.0, 0.0)
|
||||
area_light.get_set_test(0, "Controller|Configuration|Color", color)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_1", area_light_entity_name)
|
||||
|
||||
# Update intensity value to 0.0 and take screenshot in game mode
|
||||
area_light.get_set_test(0, "Controller|Configuration|Attenuation Radius|Mode", 1)
|
||||
area_light.get_set_test(0, "Controller|Configuration|Intensity", 0.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_2", area_light_entity_name)
|
||||
|
||||
# Update intensity value to 1000.0 and take screenshot in game mode
|
||||
area_light.get_set_test(0, "Controller|Configuration|Intensity", 1000.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_3", area_light_entity_name)
|
||||
|
||||
# Swap the "Capsule" light type option to "Spot (disk)" light type
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_id_pair,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_component_helper.LIGHT_TYPES['spot_disk']
|
||||
)
|
||||
area_light_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 90.0, 0.0, 0.0)
|
||||
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", area_light.id, area_light_rotation)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_4", area_light_entity_name)
|
||||
|
||||
# Swap the "Spot (disk)" light type to the "Point (sphere)" light type and take screenshot.
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_id_pair,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_component_helper.LIGHT_TYPES['sphere']
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_5", area_light_entity_name)
|
||||
|
||||
editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntityById", area_light.id)
|
||||
|
||||
|
||||
def spot_light_test():
|
||||
"""
|
||||
Basic test for the Light component attached to a "spot_light" entity.
|
||||
|
||||
Test Case - Light Component: Spot (disk) with shadows & colors:
|
||||
1. Creates "spot_light" entity w/ a Light component attached to it.
|
||||
2. Selects the "directional_light" entity already present in the level and disables it.
|
||||
3. Selects the "global_skylight" entity already present in the level and disables the HDRi Skybox component,
|
||||
as well as the Global Skylight (IBL) component.
|
||||
4. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
5. Selects the "ground_plane" entity and changes updates the material to a new material.
|
||||
6. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
7. Selects the "spot_light" entity and increases the Light component Intensity to 800 lm
|
||||
8. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
9. Selects the "spot_light" entity and sets the Light component Color to 47, 75, 37
|
||||
10. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
11. Selects the "spot_light" entity and modifies the Shutter controls to the following values:
|
||||
- Enable shutters: True
|
||||
- Inner Angle: 60.0
|
||||
- Outer Angle: 75.0
|
||||
12. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
13. Selects the "spot_light" entity and modifies the Shadow controls to the following values:
|
||||
- Enable Shadow: True
|
||||
- ShadowmapSize: 256
|
||||
14. Modifies the world translate position of the "spot_light" entity to 0.7, -2.0, 1.9 (for casting shadows better)
|
||||
15. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
"""
|
||||
# Disable "Directional Light" component for the "directional_light" entity
|
||||
# "directional_light" entity is created by the create_basic_atom_level() function by default.
|
||||
directional_light_entity_id = hydra.find_entity_by_name("directional_light")
|
||||
directional_light = hydra.Entity(name='directional_light', id=directional_light_entity_id)
|
||||
directional_light_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Directional Light"], 0)[0]
|
||||
directional_light_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', directional_light.id, directional_light_component_type
|
||||
).GetValue()
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [directional_light_component])
|
||||
general.idle_wait(0.5)
|
||||
|
||||
# Disable "Global Skylight (IBL)" and "HDRi Skybox" components for the "global_skylight" entity
|
||||
global_skylight_entity_id = hydra.find_entity_by_name("global_skylight")
|
||||
global_skylight = hydra.Entity(name='global_skylight', id=global_skylight_entity_id)
|
||||
global_skylight_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Global Skylight (IBL)"], 0)[0]
|
||||
global_skylight_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, global_skylight_component_type
|
||||
).GetValue()
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [global_skylight_component])
|
||||
hdri_skybox_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["HDRi Skybox"], 0)[0]
|
||||
hdri_skybox_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, hdri_skybox_component_type
|
||||
).GetValue()
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [hdri_skybox_component])
|
||||
general.idle_wait(0.5)
|
||||
|
||||
# Create a "spot_light" entity with "Light" component using Light Type of "Spot (disk)"
|
||||
spot_light_entity_name = "spot_light"
|
||||
spot_light = hydra.Entity(spot_light_entity_name)
|
||||
spot_light.create_entity(math.Vector3(0.7, -2.0, 1.0), [LIGHT_COMPONENT])
|
||||
general.log(
|
||||
f"{spot_light_entity_name}_test: Component added to the entity: "
|
||||
f"{hydra.has_components(spot_light.id, [LIGHT_COMPONENT])}")
|
||||
rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 300.0, 0.0, 0.0)
|
||||
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", spot_light.id, rotation)
|
||||
light_component_type = hydra.attach_component_to_entity(spot_light.id, LIGHT_COMPONENT)
|
||||
editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_type,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_component_helper.LIGHT_TYPES['spot_disk']
|
||||
)
|
||||
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_1", spot_light_entity_name)
|
||||
|
||||
# Change default material of ground plane entity and take screenshot
|
||||
ground_plane_entity_id = hydra.find_entity_by_name("ground_plane")
|
||||
ground_plane = hydra.Entity(name='ground_plane', id=ground_plane_entity_id)
|
||||
ground_plane_asset_path = os.path.join("Materials", "Presets", "MacBeth", "22_neutral_5-0_0-70d.azmaterial")
|
||||
ground_plane_asset_value = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", ground_plane_asset_path, math.Uuid(), False)
|
||||
material_property_path = "Default Material|Material Asset"
|
||||
material_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Material"], 0)[0]
|
||||
material_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', ground_plane.id, material_component_type).GetValue()
|
||||
editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
material_component,
|
||||
material_property_path,
|
||||
ground_plane_asset_value
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_2", spot_light_entity_name)
|
||||
|
||||
# Increase intensity value of the Spot light and take screenshot in game mode
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Intensity", 800.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_3", spot_light_entity_name)
|
||||
|
||||
# Update the Spot light color and take screenshot in game mode
|
||||
color_value = math.Color(47.0 / 255.0, 75.0 / 255.0, 37.0 / 255.0, 255.0 / 255.0)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Color", color_value)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_4", spot_light_entity_name)
|
||||
|
||||
# Update the Shutter controls of the Light component and take screenshot
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shutters|Enable shutters", True)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shutters|Inner angle", 60.0)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shutters|Outer angle", 75.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_5", spot_light_entity_name)
|
||||
|
||||
# Update the Shadow controls, move the spot_light entity world translate position and take screenshot
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shadows|Enable shadow", True)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shadows|Shadowmap size", 256.0)
|
||||
azlmbr.components.TransformBus(
|
||||
azlmbr.bus.Event, "SetWorldTranslation", spot_light.id, math.Vector3(0.7, -2.0, 1.9))
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_6", spot_light_entity_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@ -0,0 +1,19 @@
|
||||
"""
|
||||
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
|
||||
|
||||
Hold constants used across both hydra and non-hydra scripts.
|
||||
"""
|
||||
|
||||
# Light type options for the Light component.
|
||||
LIGHT_TYPES = {
|
||||
'unknown': 0,
|
||||
'sphere': 1,
|
||||
'spot_disk': 2,
|
||||
'capsule': 3,
|
||||
'quad': 4,
|
||||
'polygon': 5,
|
||||
'simple_point': 6,
|
||||
'simple_spot': 7,
|
||||
}
|
||||
@ -0,0 +1,274 @@
|
||||
"""
|
||||
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 azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe
|
||||
This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe
|
||||
You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import azlmbr.atom
|
||||
import azlmbr.materialeditor as materialeditor
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.atomtools.general as general
|
||||
|
||||
|
||||
def is_close(actual, expected, buffer=sys.float_info.min):
|
||||
"""
|
||||
:param actual: actual value
|
||||
:param expected: expected value
|
||||
:param buffer: acceptable variation from expected
|
||||
:return: bool
|
||||
"""
|
||||
return abs(actual - expected) < buffer
|
||||
|
||||
|
||||
def compare_colors(color1, color2, buffer=0.00001):
|
||||
"""
|
||||
Compares the red, green and blue properties of a color allowing a slight variance of buffer
|
||||
:param color1: first color to compare
|
||||
:param color2: second color
|
||||
:param buffer: allowed variance in individual color value
|
||||
:return: bool
|
||||
"""
|
||||
return (
|
||||
is_close(color1.r, color2.r, buffer)
|
||||
and is_close(color1.g, color2.g, buffer)
|
||||
and is_close(color1.b, color2.b, buffer)
|
||||
)
|
||||
|
||||
|
||||
def open_material(file_path):
|
||||
"""
|
||||
:return: uuid of material document opened
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path)
|
||||
|
||||
|
||||
def is_open(document_id):
|
||||
"""
|
||||
:return: bool
|
||||
"""
|
||||
return materialeditor.MaterialDocumentRequestBus(bus.Event, "IsOpen", document_id)
|
||||
|
||||
|
||||
def save_document(document_id):
|
||||
"""
|
||||
:return: bool success
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id)
|
||||
|
||||
|
||||
def save_document_as_copy(document_id, target_path):
|
||||
"""
|
||||
:return: bool success
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(
|
||||
bus.Broadcast, "SaveDocumentAsCopy", document_id, target_path
|
||||
)
|
||||
|
||||
|
||||
def save_document_as_child(document_id, target_path):
|
||||
"""
|
||||
:return: bool success
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(
|
||||
bus.Broadcast, "SaveDocumentAsChild", document_id, target_path
|
||||
)
|
||||
|
||||
|
||||
def save_all():
|
||||
"""
|
||||
:return: bool success
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments")
|
||||
|
||||
|
||||
def close_document(document_id):
|
||||
"""
|
||||
:return: bool success
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id)
|
||||
|
||||
|
||||
def close_all_documents():
|
||||
"""
|
||||
:return: bool success
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments")
|
||||
|
||||
|
||||
def close_all_except_selected(document_id):
|
||||
"""
|
||||
:return: bool success
|
||||
"""
|
||||
return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id)
|
||||
|
||||
|
||||
def get_property(document_id, property_name):
|
||||
"""
|
||||
:return: property value or invalid value if the document is not open or the property_name can't be found
|
||||
"""
|
||||
return materialeditor.MaterialDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name)
|
||||
|
||||
|
||||
def set_property(document_id, property_name, value):
|
||||
materialeditor.MaterialDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value)
|
||||
|
||||
|
||||
def is_pane_visible(pane_name):
|
||||
"""
|
||||
:return: bool
|
||||
"""
|
||||
return materialeditor.MaterialEditorWindowRequestBus(bus.Broadcast, "IsDockWidgetVisible", pane_name)
|
||||
|
||||
|
||||
def set_pane_visibility(pane_name, value):
|
||||
materialeditor.MaterialEditorWindowRequestBus(bus.Broadcast, "SetDockWidgetVisible", pane_name, value)
|
||||
|
||||
|
||||
def select_lighting_config(config_name):
|
||||
azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectLightingPresetByName", config_name)
|
||||
|
||||
|
||||
def set_grid_enable_disable(value):
|
||||
azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SetGridEnabled", value)
|
||||
|
||||
|
||||
def get_grid_enable_disable():
|
||||
"""
|
||||
:return: bool
|
||||
"""
|
||||
return azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "GetGridEnabled")
|
||||
|
||||
|
||||
def set_shadowcatcher_enable_disable(value):
|
||||
azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SetShadowCatcherEnabled", value)
|
||||
|
||||
|
||||
def get_shadowcatcher_enable_disable():
|
||||
"""
|
||||
:return: bool
|
||||
"""
|
||||
return azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "GetShadowCatcherEnabled")
|
||||
|
||||
|
||||
def select_model_config(configname):
|
||||
azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectModelPresetByName", configname)
|
||||
|
||||
|
||||
def wait_for_condition(function, timeout_in_seconds=1.0):
|
||||
# type: (function, float) -> bool
|
||||
"""
|
||||
Function to run until it returns True or timeout is reached
|
||||
the function can have no parameters and
|
||||
waiting idle__wait_* is handled here not in the function
|
||||
|
||||
:param function: a function that returns a boolean indicating a desired condition is achieved
|
||||
:param timeout_in_seconds: when reached, function execution is abandoned and False is returned
|
||||
"""
|
||||
with Timeout(timeout_in_seconds) as t:
|
||||
while True:
|
||||
try:
|
||||
general.idle_wait_frames(1)
|
||||
except Exception:
|
||||
print("WARNING: Couldn't wait for frame")
|
||||
|
||||
if t.timed_out:
|
||||
return False
|
||||
|
||||
ret = function()
|
||||
if not isinstance(ret, bool):
|
||||
raise TypeError("return value for wait_for_condition function must be a bool")
|
||||
if ret:
|
||||
return True
|
||||
|
||||
|
||||
class Timeout:
|
||||
# type: (float) -> None
|
||||
"""
|
||||
contextual timeout
|
||||
:param seconds: float seconds to allow before timed_out is True
|
||||
"""
|
||||
|
||||
def __init__(self, seconds):
|
||||
self.seconds = seconds
|
||||
|
||||
def __enter__(self):
|
||||
self.die_after = time.time() + self.seconds
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
pass
|
||||
|
||||
@property
|
||||
def timed_out(self):
|
||||
return time.time() > self.die_after
|
||||
|
||||
|
||||
screenshotsFolder = os.path.join(azlmbr.paths.devroot, "AtomTest", "Cache" "pc", "Screenshots")
|
||||
|
||||
|
||||
class ScreenshotHelper:
|
||||
"""
|
||||
A helper to capture screenshots and wait for them.
|
||||
"""
|
||||
|
||||
def __init__(self, idle_wait_frames_callback):
|
||||
super().__init__()
|
||||
self.done = False
|
||||
self.capturedScreenshot = False
|
||||
self.max_frames_to_wait = 60
|
||||
|
||||
self.idle_wait_frames_callback = idle_wait_frames_callback
|
||||
|
||||
def capture_screenshot_blocking(self, filename):
|
||||
"""
|
||||
Capture a screenshot and block the execution until the screenshot has been written to the disk.
|
||||
"""
|
||||
self.handler = azlmbr.atom.FrameCaptureNotificationBusHandler()
|
||||
self.handler.connect()
|
||||
self.handler.add_callback("OnCaptureFinished", self.on_screenshot_captured)
|
||||
|
||||
self.done = False
|
||||
self.capturedScreenshot = False
|
||||
success = azlmbr.atom.FrameCaptureRequestBus(azlmbr.bus.Broadcast, "CaptureScreenshot", filename)
|
||||
if success:
|
||||
self.wait_until_screenshot()
|
||||
print("Screenshot taken.")
|
||||
else:
|
||||
print("screenshot failed")
|
||||
return self.capturedScreenshot
|
||||
|
||||
def on_screenshot_captured(self, parameters):
|
||||
# the parameters come in as a tuple
|
||||
if parameters[0]:
|
||||
print("screenshot saved: {}".format(parameters[1]))
|
||||
self.capturedScreenshot = True
|
||||
else:
|
||||
print("screenshot failed: {}".format(parameters[1]))
|
||||
self.done = True
|
||||
self.handler.disconnect()
|
||||
|
||||
def wait_until_screenshot(self):
|
||||
frames_waited = 0
|
||||
while self.done == False:
|
||||
self.idle_wait_frames_callback(1)
|
||||
if frames_waited > self.max_frames_to_wait:
|
||||
print("timeout while waiting for the screenshot to be written")
|
||||
self.handler.disconnect()
|
||||
break
|
||||
else:
|
||||
frames_waited = frames_waited + 1
|
||||
print("(waited {} frames)".format(frames_waited))
|
||||
|
||||
|
||||
def capture_screenshot(file_path):
|
||||
return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking(
|
||||
os.path.join(file_path)
|
||||
)
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:954d7d0df47c840a24e313893800eb3126d0c0d47c3380926776b51833778db7
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e81c19128f42ba362a2d5f3ccf159dfbc942d67ceeb1ac8c21f295a6fd9d2ce5
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5e20801213e065b6ea8c95ede81c23faa9b6dc70a2002dc5bced293e1bed989f
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e250f812e594e5152bf2d6f23caa8b53b78276bfdf344d7a8d355dd96cb995c0
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95be359041f8291c74b335297a4dfe9902a180510f24a181b15e1a5ba4d3b024
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:118e43e4b915e262726183467cc4b82f244565213fea5b6bfe02be07f0851ab1
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dc2ce3256a6552975962c9e113c52c1a22bf3817d417151f6f60640dd568e0fa
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:287d98890b35427688999760f9d066bcbff1a3bc9001534241dc212b32edabd8
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:66e91c92c868167c850078cd91714db47e10a96e23cc30191994486bd79c353f
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d950d173f5101820c5e18205401ca08ce5feeff2302ac2920b292750d86a8fa4
|
||||
size 6220817
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:72eddb7126eae0c839b933886e0fb69d78229f72d49ef13199de28df2b7879db
|
||||
size 6220817
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
class ConstantsData;
|
||||
struct DrawItem;
|
||||
class ShaderResourceGroup;
|
||||
|
||||
/// Given a ShaderResourceGroup and a reference ConstantsData input, this function will fetch the ConstantsData on the SRG and compare it
|
||||
/// to the reference ConstantsData. It will print the names of any constants that are different between the two.
|
||||
/// The parameter updateReferenceData can be used to set the reference data to the SRG's constant data after the comparison. This is
|
||||
/// useful for keeping track of differences in between calls to the function, such as between frames.
|
||||
void PrintConstantDataDiff(const ShaderResourceGroup& shaderResourceGroup, ConstantsData& referenceData, bool updateReferenceData = false);
|
||||
|
||||
/// Given a DrawItem, an SRG binding slot on that draw item and a reference ConstantsData input, this function will fetch the ConstantsData
|
||||
/// from the draw item's SRG at the binding slot and compare it to the reference ConstantsData. It will print the names of any constants
|
||||
/// that are different between the two.
|
||||
/// The parameter updateReferenceData can be used to set the reference data to the draw item's constant data after the comparison. This is
|
||||
/// useful for keeping track of differences in between calls to the function, such as between frames.
|
||||
void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, uint32_t srgBindingSlot, bool updateReferenceData = false);
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/ConstantsData.h>
|
||||
#include <Atom/RHI/DrawItem.h>
|
||||
#include <Atom/RHI/ShaderResourceGroup.h>
|
||||
#include <Atom/RHI/ShaderResourceGroupDebug.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
|
||||
void PrintConstantDataDiff(const ShaderResourceGroup& shaderResourceGroup, ConstantsData& referenceData, bool updateReferenceData)
|
||||
{
|
||||
const RHI::ConstantsData& currentData = shaderResourceGroup.GetData().GetConstantsData();
|
||||
|
||||
AZStd::vector<RHI::ShaderInputConstantIndex> differingIndices = currentData.GetIndicesOfDifferingConstants(referenceData);
|
||||
|
||||
if (differingIndices.size() > 0)
|
||||
{
|
||||
AZ_Printf("RHI", "Detected different SRG values for the following fields:\n");
|
||||
if (currentData.GetLayout())
|
||||
{
|
||||
currentData.GetLayout()->DebugPrintNames(differingIndices);
|
||||
}
|
||||
}
|
||||
|
||||
if (updateReferenceData)
|
||||
{
|
||||
referenceData = currentData;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, uint32_t srgBindingSlot, bool updateReferenceData)
|
||||
{
|
||||
int srgIndex = -1;
|
||||
for (uint32_t i = 0; i < drawItem.m_shaderResourceGroupCount; ++i)
|
||||
{
|
||||
if (drawItem.m_shaderResourceGroups[i]->GetBindingSlot() == srgBindingSlot)
|
||||
{
|
||||
srgIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (srgIndex != -1)
|
||||
{
|
||||
const ShaderResourceGroup& srg = *drawItem.m_shaderResourceGroups[srgIndex];
|
||||
PrintConstantDataDiff(srg, referenceData, updateReferenceData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue