diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py index 45e633a979..cb2c445246 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py @@ -12,12 +12,36 @@ import sys import os import pytest import logging +import sqlite3 pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system import ly_test_tools.log.log_monitor import ly_test_tools.environment.waiter as waiter +def detect_product(sql_connection, platform, target): + cur = sql_connection.cursor() + product_target = f'{platform}/{target}' + print(f'Detecting {product_target} in assetdb.sqlite') + hits = 0 + for row in cur.execute(f'select ProductID from Products where ProductName is "{product_target}"'): + hits = hits + 1 + assert hits == 1 + + +def find_products(cache_folder, platform): + con = sqlite3.connect(os.path.join(cache_folder, 'assetdb.sqlite')) + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset') + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel') + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel') + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel') + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel') + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel') + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel') + detect_product(con, platform, 'gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel') + con.close() + + @pytest.mark.SUITE_periodic @pytest.mark.parametrize('launcher_platform', ['windows_editor']) @pytest.mark.parametrize('project', ['AutomatedTesting']) @@ -25,16 +49,7 @@ import ly_test_tools.environment.waiter as waiter class TestPythonAssetProcessing(object): def test_DetectPythonCreatedAsset(self, request, editor, level, launcher_platform): unexpected_lines = [] - expected_lines = [ - 'Mock asset exists', - 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel) found', - 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel) found', - 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel) found', - 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel) found', - 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel) found', - 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel) found', - 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel) found' - ] + expected_lines = [] timeout = 180 halt_on_unexpected = False test_directory = os.path.join(os.path.dirname(__file__)) @@ -50,3 +65,9 @@ class TestPythonAssetProcessing(object): exc=("Log file '{}' was never opened by another process.".format(editorlog_file)), interval=1) log_monitor.monitor_log_for_lines(expected_lines, unexpected_lines, halt_on_unexpected, timeout) + + cache_folder = editor.workspace.paths.cache() + platform = editor.workspace.asset_processor_platform + if platform == 'windows': + platform = 'pc' + find_products(cache_folder, platform) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py index 7ad5894a86..a9759e3d33 100644 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/assets/TwoSceneFiles_OneWithPythonOneWithout_PythonOnlyRunsOnFirstScene/python_builder.py @@ -23,7 +23,7 @@ def output_test_data(scene): # Just write something to the file, but the filename is the main information # used for the test. f.write(f"scene.sourceFilename: {scene.sourceFilename}\n") - return True + return '' mySceneJobHandler = None diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py index 7366faafdc..b18bf65312 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py @@ -98,7 +98,13 @@ def AssetBrowser_SearchFiltering(): # 3) Type the name of an asset in the search bar and make sure it is filtered to and selectable asset_browser = editor_window.findChild(QtWidgets.QDockWidget, "Asset Browser") search_bar = asset_browser.findChild(QtWidgets.QLineEdit, "textSearch") - search_bar.setText("cedar.fbx") + + # Add a small pause when typing in the search bar in order to check that the entries are updated properly + search_bar.setText("Cedar.f") + general.idle_wait(0.5) + search_bar.setText("Cedar.fbx") + general.idle_wait(0.5) + asset_browser_tree = asset_browser.findChild(QtWidgets.QTreeView, "m_assetBrowserTreeViewWidget") asset_browser_table = asset_browser.findChild(QtWidgets.QTreeView, "m_assetBrowserTableViewWidget") found = await pyside_utils.wait_for_condition(lambda: pyside_utils.find_child_by_pattern(asset_browser_table, "cedar.fbx"), 5.0) diff --git a/AutomatedTesting/Levels/Graphics/ShadowTest/ShadowTest.prefab b/AutomatedTesting/Levels/Graphics/ShadowTest/ShadowTest.prefab new file mode 100644 index 0000000000..86d16328e9 --- /dev/null +++ b/AutomatedTesting/Levels/Graphics/ShadowTest/ShadowTest.prefab @@ -0,0 +1,566 @@ +{ + "ContainerEntity": { + "Id": "ContainerEntity", + "Name": "ShadowTest", + "Components": { + "Component_[10182366347512475253]": { + "$type": "EditorPrefabComponent", + "Id": 10182366347512475253 + }, + "Component_[12917798267488243668]": { + "$type": "EditorPendingCompositionComponent", + "Id": 12917798267488243668 + }, + "Component_[3261249813163778338]": { + "$type": "EditorOnlyEntityComponent", + "Id": 3261249813163778338 + }, + "Component_[3837204912784440039]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 3837204912784440039 + }, + "Component_[4272963378099646759]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 4272963378099646759, + "Parent Entity": "" + }, + "Component_[4848458548047175816]": { + "$type": "EditorVisibilityComponent", + "Id": 4848458548047175816 + }, + "Component_[5787060997243919943]": { + "$type": "EditorInspectorComponent", + "Id": 5787060997243919943 + }, + "Component_[7804170251266531779]": { + "$type": "EditorLockComponent", + "Id": 7804170251266531779 + }, + "Component_[7874177159288365422]": { + "$type": "EditorEntitySortComponent", + "Id": 7874177159288365422 + }, + "Component_[8018146290632383969]": { + "$type": "EditorEntityIconComponent", + "Id": 8018146290632383969 + }, + "Component_[8452360690590857075]": { + "$type": "SelectionComponent", + "Id": 8452360690590857075 + } + } + }, + "Entities": { + "Entity_[232650527119]": { + "Id": "Entity_[232650527119]", + "Name": "DirectionalLight", + "Components": { + "Component_[10660156197505313227]": { + "$type": "EditorLockComponent", + "Id": 10660156197505313227 + }, + "Component_[14184823757717157844]": { + "$type": "EditorInspectorComponent", + "Id": 14184823757717157844, + "ComponentOrderEntryArray": [ + { + "ComponentId": 9854879901259791898 + }, + { + "ComponentId": 3968519938187714949, + "SortIndex": 1 + } + ] + }, + "Component_[1495573908681275492]": { + "$type": "EditorEntitySortComponent", + "Id": 1495573908681275492 + }, + "Component_[15580233403487968826]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 15580233403487968826 + }, + "Component_[3968519938187714949]": { + "$type": "AZ::Render::EditorDirectionalLightComponent", + "Id": 3968519938187714949, + "Controller": { + "Configuration": { + "Intensity": 0.0, + "CameraEntityId": "", + "ShadowmapSize": "Size2048" + } + } + }, + "Component_[4961040003466069196]": { + "$type": "EditorEntityIconComponent", + "Id": 4961040003466069196 + }, + "Component_[7824884165323036147]": { + "$type": "EditorVisibilityComponent", + "Id": 7824884165323036147 + }, + "Component_[8741866916946672319]": { + "$type": "EditorPendingCompositionComponent", + "Id": 8741866916946672319 + }, + "Component_[9288966876314965560]": { + "$type": "EditorOnlyEntityComponent", + "Id": 9288966876314965560 + }, + "Component_[9313163355156975968]": { + "$type": "SelectionComponent", + "Id": 9313163355156975968 + }, + "Component_[9854879901259791898]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 9854879901259791898, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 0.0, + 0.0, + 2.0 + ], + "Rotate": [ + -32.05662536621094, + -26.103206634521484, + 47.54806137084961 + ] + } + } + } + }, + "Entity_[260824893221]": { + "Id": "Entity_[260824893221]", + "Name": "SpotLight", + "Components": { + "Component_[16098295228434057928]": { + "$type": "EditorDiskShapeComponent", + "Id": 16098295228434057928, + "ShapeColor": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "DiskShape": { + "Configuration": { + "Radius": 0.0 + } + } + }, + "Component_[16175995808158769171]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 16175995808158769171, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 0.6417449712753296, + 1.3211734294891357, + 3.022759199142456 + ], + "Rotate": [ + 243.31329345703125, + 0.0, + 0.0 + ] + } + }, + "Component_[17136787899581093377]": { + "$type": "EditorEntitySortComponent", + "Id": 17136787899581093377 + }, + "Component_[17938027566627202610]": { + "$type": "EditorPendingCompositionComponent", + "Id": 17938027566627202610 + }, + "Component_[190081405128299223]": { + "$type": "SelectionComponent", + "Id": 190081405128299223 + }, + "Component_[2181418147135573579]": { + "$type": "EditorEntityIconComponent", + "Id": 2181418147135573579 + }, + "Component_[2564149706319215342]": { + "$type": "EditorOnlyEntityComponent", + "Id": 2564149706319215342 + }, + "Component_[3716169383940064541]": { + "$type": "EditorInspectorComponent", + "Id": 3716169383940064541, + "ComponentOrderEntryArray": [ + { + "ComponentId": 16175995808158769171 + }, + { + "ComponentId": 16665800442781289114, + "SortIndex": 1 + } + ] + }, + "Component_[4143676462074671972]": { + "$type": "AZ::Render::EditorAreaLightComponent", + "Id": 4143676462074671972, + "Controller": { + "Configuration": { + "LightType": 2, + "AttenuationRadius": 31.62277603149414, + "EnableShutters": true, + "InnerShutterAngleDegrees": 22.5, + "OuterShutterAngleDegrees": 27.5, + "Enable Shadow": true, + "Shadowmap Max Size": "Size2048", + "Filtering Sample Count": 32 + } + } + }, + "Component_[6706371214647538019]": { + "$type": "EditorVisibilityComponent", + "Id": 6706371214647538019 + }, + "Component_[7493944209625718550]": { + "$type": "EditorLockComponent", + "Id": 7493944209625718550 + }, + "Component_[7614113482082939165]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 7614113482082939165 + } + } + }, + "Entity_[269117486973]": { + "Id": "Entity_[269117486973]", + "Name": "Floor", + "Components": { + "Component_[10562678944594915756]": { + "$type": "EditorEntitySortComponent", + "Id": 10562678944594915756 + }, + "Component_[1175452962278157526]": { + "$type": "EditorEntityIconComponent", + "Id": 1175452962278157526 + }, + "Component_[13598353801231166887]": { + "$type": "EditorPendingCompositionComponent", + "Id": 13598353801231166887 + }, + "Component_[13735087293504923475]": { + "$type": "SelectionComponent", + "Id": 13735087293504923475 + }, + "Component_[13888244442459268363]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 13888244442459268363, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{E65E9ED3-3E38-5ABA-9E22-95E34DA4C3AE}", + "subId": 280178048 + }, + "assetHint": "objects/plane.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[1525720357937234014]": { + "$type": "EditorMaterialComponent", + "Id": 1525720357937234014, + "materialSlotsByLodEnabled": true + }, + "Component_[16568998871680422442]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 16568998871680422442 + }, + "Component_[2147751093058990131]": { + "$type": "EditorInspectorComponent", + "Id": 2147751093058990131, + "ComponentOrderEntryArray": [ + { + "ComponentId": 3266761149114817871 + }, + { + "ComponentId": 13888244442459268363, + "SortIndex": 1 + }, + { + "ComponentId": 1525720357937234014, + "SortIndex": 2 + } + ] + }, + "Component_[3266761149114817871]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 3266761149114817871, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Scale": [ + 100.0, + 100.0, + 100.0 + ], + "UniformScale": 100.0 + } + }, + "Component_[4625895382416898670]": { + "$type": "EditorVisibilityComponent", + "Id": 4625895382416898670 + }, + "Component_[4856699190357614535]": { + "$type": "EditorLockComponent", + "Id": 4856699190357614535 + }, + "Component_[6466465153982575739]": { + "$type": "EditorOnlyEntityComponent", + "Id": 6466465153982575739 + } + } + }, + "Entity_[282757803856]": { + "Id": "Entity_[282757803856]", + "Name": "Cube", + "Components": { + "Component_[11189870094752260272]": { + "$type": "EditorEntitySortComponent", + "Id": 11189870094752260272 + }, + "Component_[11909086967677513257]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 11909086967677513257, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{593006BE-FE73-5A4B-A0A6-06C02EFFE458}", + "subId": 285127096 + }, + "loadBehavior": "PreLoad", + "assetHint": "objects/cube.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[1443341568598731610]": { + "$type": "EditorVisibilityComponent", + "Id": 1443341568598731610 + }, + "Component_[18339772707807258951]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 18339772707807258951, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 0.6083869934082031, + 3.137901782989502, + 0.5876787900924683 + ] + } + }, + "Component_[2447207272572065708]": { + "$type": "EditorEntityIconComponent", + "Id": 2447207272572065708 + }, + "Component_[3281906807632213471]": { + "$type": "SelectionComponent", + "Id": 3281906807632213471 + }, + "Component_[3412442673858204671]": { + "$type": "EditorPendingCompositionComponent", + "Id": 3412442673858204671 + }, + "Component_[5382641380294287889]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 5382641380294287889 + }, + "Component_[7221534636342494619]": { + "$type": "EditorInspectorComponent", + "Id": 7221534636342494619, + "ComponentOrderEntryArray": [ + { + "ComponentId": 18339772707807258951 + }, + { + "ComponentId": 11909086967677513257, + "SortIndex": 1 + } + ] + }, + "Component_[7701217952253676487]": { + "$type": "EditorLockComponent", + "Id": 7701217952253676487 + }, + "Component_[7758436981023123121]": { + "$type": "EditorOnlyEntityComponent", + "Id": 7758436981023123121 + } + } + }, + "Entity_[372196702077]": { + "Id": "Entity_[372196702077]", + "Name": "Bunny", + "Components": { + "Component_[11345914745205508221]": { + "$type": "EditorEntityIconComponent", + "Id": 11345914745205508221 + }, + "Component_[11507863983962969790]": { + "$type": "EditorMaterialComponent", + "Id": 11507863983962969790, + "materialSlotsByLodEnabled": true + }, + "Component_[1342998773562921470]": { + "$type": "EditorPendingCompositionComponent", + "Id": 1342998773562921470 + }, + "Component_[14975835087235718844]": { + "$type": "EditorInspectorComponent", + "Id": 14975835087235718844, + "ComponentOrderEntryArray": [ + { + "ComponentId": 5012565883129470759 + }, + { + "ComponentId": 7975043234993822905, + "SortIndex": 1 + }, + { + "ComponentId": 11507863983962969790, + "SortIndex": 2 + } + ] + }, + "Component_[16460806723667032929]": { + "$type": "EditorOnlyEntityComponent", + "Id": 16460806723667032929 + }, + "Component_[18225690044585951363]": { + "$type": "EditorLockComponent", + "Id": 18225690044585951363 + }, + "Component_[18314752491697618927]": { + "$type": "EditorEntitySortComponent", + "Id": 18314752491697618927 + }, + "Component_[2431610550789583502]": { + "$type": "EditorVisibilityComponent", + "Id": 2431610550789583502 + }, + "Component_[5012565883129470759]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 5012565883129470759, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 0.0, + 0.0, + 0.20401419699192047 + ] + } + }, + "Component_[7975043234993822905]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 7975043234993822905, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{0C6BBB76-4EC2-583A-B8C6-1A4C4FD1FE9D}", + "subId": 283109893 + }, + "assetHint": "objects/bunny.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[8510666363380501112]": { + "$type": "SelectionComponent", + "Id": 8510666363380501112 + }, + "Component_[9639060480533776634]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 9639060480533776634 + } + } + }, + "Entity_[670308843764]": { + "Id": "Entity_[670308843764]", + "Name": "Camera1", + "Components": { + "Component_[12951260100632682169]": { + "$type": "GenericComponentWrapper", + "Id": 12951260100632682169, + "m_template": { + "$type": "FlyCameraInputComponent" + } + }, + "Component_[14180723329646459524]": { + "$type": "EditorPendingCompositionComponent", + "Id": 14180723329646459524 + }, + "Component_[14996469885773917977]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 14996469885773917977, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 4.563776969909668, + 0.7667046785354614, + 3.000542640686035 + ], + "Rotate": [ + -9.740042686462402, + -20.20942497253418, + 63.57760238647461 + ] + } + }, + "Component_[17638492356673689530]": { + "$type": "EditorInspectorComponent", + "Id": 17638492356673689530 + }, + "Component_[2421853983468750254]": { + "$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent", + "Id": 2421853983468750254, + "Controller": { + "Configuration": { + "Field of View": 90.00020599365234, + "EditorEntityId": 666013876468 + } + } + }, + "Component_[2572028619185965684]": { + "$type": "EditorEntityIconComponent", + "Id": 2572028619185965684 + }, + "Component_[2782900516907042776]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 2782900516907042776 + }, + "Component_[2849166119438883669]": { + "$type": "EditorVisibilityComponent", + "Id": 2849166119438883669 + }, + "Component_[4618311795498613781]": { + "$type": "EditorOnlyEntityComponent", + "Id": 4618311795498613781 + }, + "Component_[5402004894214413002]": { + "$type": "EditorEntitySortComponent", + "Id": 5402004894214413002 + }, + "Component_[6111028576371006514]": { + "$type": "SelectionComponent", + "Id": 6111028576371006514 + }, + "Component_[8203141294643544464]": { + "$type": "EditorLockComponent", + "Id": 8203141294643544464 + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/ShadowTest/tags.txt b/AutomatedTesting/Levels/Graphics/ShadowTest/tags.txt new file mode 100644 index 0000000000..0d6c1880e7 --- /dev/null +++ b/AutomatedTesting/Levels/Graphics/ShadowTest/tags.txt @@ -0,0 +1,12 @@ +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 diff --git a/AutomatedTesting/Levels/Graphics/hermanubis/hermanubis.prefab b/AutomatedTesting/Levels/Graphics/hermanubis/hermanubis.prefab new file mode 100644 index 0000000000..2234b02cfe --- /dev/null +++ b/AutomatedTesting/Levels/Graphics/hermanubis/hermanubis.prefab @@ -0,0 +1,705 @@ +{ + "ContainerEntity": { + "Id": "ContainerEntity", + "Name": "Hermanubis", + "Components": { + "Component_[10182366347512475253]": { + "$type": "EditorPrefabComponent", + "Id": 10182366347512475253 + }, + "Component_[12917798267488243668]": { + "$type": "EditorPendingCompositionComponent", + "Id": 12917798267488243668 + }, + "Component_[3261249813163778338]": { + "$type": "EditorOnlyEntityComponent", + "Id": 3261249813163778338 + }, + "Component_[3837204912784440039]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 3837204912784440039 + }, + "Component_[4272963378099646759]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 4272963378099646759, + "Parent Entity": "" + }, + "Component_[4848458548047175816]": { + "$type": "EditorVisibilityComponent", + "Id": 4848458548047175816 + }, + "Component_[5787060997243919943]": { + "$type": "EditorInspectorComponent", + "Id": 5787060997243919943 + }, + "Component_[7804170251266531779]": { + "$type": "EditorLockComponent", + "Id": 7804170251266531779 + }, + "Component_[7874177159288365422]": { + "$type": "EditorEntitySortComponent", + "Id": 7874177159288365422 + }, + "Component_[8018146290632383969]": { + "$type": "EditorEntityIconComponent", + "Id": 8018146290632383969 + }, + "Component_[8452360690590857075]": { + "$type": "SelectionComponent", + "Id": 8452360690590857075 + } + } + }, + "Entities": { + "Entity_[250006174949]": { + "Id": "Entity_[250006174949]", + "Name": "WorldOrigin", + "Components": { + "Component_[13379444112629774116]": { + "$type": "EditorEntityIconComponent", + "Id": 13379444112629774116 + }, + "Component_[13797113876161133062]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 13797113876161133062, + "Parent Entity": "ContainerEntity" + }, + "Component_[16382506042739704306]": { + "$type": "EditorInspectorComponent", + "Id": 16382506042739704306, + "ComponentOrderEntryArray": [ + { + "ComponentId": 13797113876161133062 + }, + { + "ComponentId": 8816319458242680670, + "SortIndex": 1 + } + ] + }, + "Component_[2147729086581105478]": { + "$type": "EditorOnlyEntityComponent", + "Id": 2147729086581105478 + }, + "Component_[2433100672102773575]": { + "$type": "SelectionComponent", + "Id": 2433100672102773575 + }, + "Component_[4832829387489613630]": { + "$type": "EditorVisibilityComponent", + "Id": 4832829387489613630 + }, + "Component_[5585931842723227683]": { + "$type": "EditorEntitySortComponent", + "Id": 5585931842723227683, + "Child Entity Order": [ + "Entity_[254301142245]" + ] + }, + "Component_[7088004383223117498]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 7088004383223117498 + }, + "Component_[7856264459806503732]": { + "$type": "EditorPendingCompositionComponent", + "Id": 7856264459806503732 + }, + "Component_[8816319458242680670]": { + "$type": "AZ::Render::EditorGridComponent", + "Id": 8816319458242680670 + }, + "Component_[930042309700959235]": { + "$type": "EditorLockComponent", + "Id": 930042309700959235 + } + } + }, + "Entity_[254301142245]": { + "Id": "Entity_[254301142245]", + "Name": "GlobalSkylight", + "Components": { + "Component_[10076500561520682485]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 10076500561520682485, + "Parent Entity": "Entity_[250006174949]" + }, + "Component_[12626877995248630950]": { + "$type": "EditorInspectorComponent", + "Id": 12626877995248630950, + "ComponentOrderEntryArray": [ + { + "ComponentId": 10076500561520682485 + }, + { + "ComponentId": 8158442301445120126, + "SortIndex": 1 + }, + { + "ComponentId": 7260006984216245935, + "SortIndex": 2 + } + ] + }, + "Component_[13040837632921717329]": { + "$type": "SelectionComponent", + "Id": 13040837632921717329 + }, + "Component_[1390505494369101864]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 1390505494369101864 + }, + "Component_[6733278858932131836]": { + "$type": "EditorVisibilityComponent", + "Id": 6733278858932131836 + }, + "Component_[7260006984216245935]": { + "$type": "AZ::Render::EditorImageBasedLightComponent", + "Id": 7260006984216245935, + "Controller": { + "Configuration": { + "diffuseImageAsset": { + "assetId": { + "guid": "{3B78EA69-7CF0-56A7-A49A-110B88412666}", + "subId": 3000 + }, + "assetHint": "lightingpresets/greenwich_park_02_4k_iblskyboxcm_ibldiffuse.exr.streamingimage" + }, + "specularImageAsset": { + "assetId": { + "guid": "{3B78EA69-7CF0-56A7-A49A-110B88412666}", + "subId": 2000 + }, + "assetHint": "lightingpresets/greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage" + } + } + } + }, + "Component_[7944006745008331817]": { + "$type": "EditorEntitySortComponent", + "Id": 7944006745008331817 + }, + "Component_[8158442301445120126]": { + "$type": "AZ::Render::EditorHDRiSkyboxComponent", + "Id": 8158442301445120126, + "Controller": { + "Configuration": { + "CubemapAsset": { + "assetId": { + "guid": "{3B78EA69-7CF0-56A7-A49A-110B88412666}", + "subId": 1000 + }, + "assetHint": "lightingpresets/greenwich_park_02_4k_iblskyboxcm.exr.streamingimage" + } + } + } + }, + "Component_[8255370213772594097]": { + "$type": "EditorOnlyEntityComponent", + "Id": 8255370213772594097 + }, + "Component_[8551180373364097938]": { + "$type": "EditorLockComponent", + "Id": 8551180373364097938 + }, + "Component_[8852330656608249928]": { + "$type": "EditorPendingCompositionComponent", + "Id": 8852330656608249928 + }, + "Component_[8913694496991926693]": { + "$type": "EditorEntityIconComponent", + "Id": 8913694496991926693 + } + } + }, + "Entity_[258596109541]": { + "Id": "Entity_[258596109541]", + "Name": "Hermanubis_stone", + "Components": { + "Component_[1026780512255775175]": { + "$type": "EditorEntityIconComponent", + "Id": 1026780512255775175 + }, + "Component_[10882452951986489612]": { + "$type": "SelectionComponent", + "Id": 10882452951986489612 + }, + "Component_[12454042755417175050]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 12454042755417175050, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{1F650917-AA74-5107-9C49-648C957B33DA}", + "subId": 275904906 + }, + "assetHint": "materialeditor/viewportmodels/hermanubis.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[13691807045809495479]": { + "$type": "EditorMaterialComponent", + "Id": 13691807045809495479, + "Controller": { + "Configuration": { + "materials": { + "{}": { + "MaterialAsset": { + "assetId": { + "guid": "{FF6412B6-F86E-54C8-835C-04F08190D81B}" + }, + "assetHint": "objects/hermanubis/hermanubis_stone.azmaterial" + } + } + } + } + }, + "materialSlotsByLodEnabled": true + }, + "Component_[14490373655742304057]": { + "$type": "EditorPendingCompositionComponent", + "Id": 14490373655742304057 + }, + "Component_[15248132570755287431]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 15248132570755287431 + }, + "Component_[16950375358457415777]": { + "$type": "EditorVisibilityComponent", + "Id": 16950375358457415777 + }, + "Component_[17852268252813268496]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 17852268252813268496, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 1.1189539432525635, + 0.0, + 0.0 + ] + } + }, + "Component_[3867610358542973898]": { + "$type": "EditorEntitySortComponent", + "Id": 3867610358542973898 + }, + "Component_[7717372065847089412]": { + "$type": "EditorOnlyEntityComponent", + "Id": 7717372065847089412 + }, + "Component_[7783943040473764331]": { + "$type": "EditorInspectorComponent", + "Id": 7783943040473764331, + "ComponentOrderEntryArray": [ + { + "ComponentId": 17852268252813268496 + }, + { + "ComponentId": 12454042755417175050, + "SortIndex": 1 + }, + { + "ComponentId": 13691807045809495479, + "SortIndex": 2 + } + ] + }, + "Component_[833407121913837256]": { + "$type": "EditorLockComponent", + "Id": 833407121913837256 + } + } + }, + "Entity_[262891076837]": { + "Id": "Entity_[262891076837]", + "Name": "Hermanubis_brass", + "Components": { + "Component_[1026780512255775175]": { + "$type": "EditorEntityIconComponent", + "Id": 1026780512255775175 + }, + "Component_[10882452951986489612]": { + "$type": "SelectionComponent", + "Id": 10882452951986489612 + }, + "Component_[12454042755417175050]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 12454042755417175050, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{1F650917-AA74-5107-9C49-648C957B33DA}", + "subId": 275904906 + }, + "assetHint": "materialeditor/viewportmodels/hermanubis.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[13691807045809495479]": { + "$type": "EditorMaterialComponent", + "Id": 13691807045809495479, + "Controller": { + "Configuration": { + "materials": { + "{}": { + "MaterialAsset": { + "assetId": { + "guid": "{B3AC2305-1DE6-54AA-AAD5-5E77C75E5BB5}" + }, + "assetHint": "objects/hermanubis/hermanubis_brass.azmaterial" + } + } + } + } + }, + "materialSlotsByLodEnabled": true + }, + "Component_[14490373655742304057]": { + "$type": "EditorPendingCompositionComponent", + "Id": 14490373655742304057 + }, + "Component_[15248132570755287431]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 15248132570755287431 + }, + "Component_[16950375358457415777]": { + "$type": "EditorVisibilityComponent", + "Id": 16950375358457415777 + }, + "Component_[17852268252813268496]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 17852268252813268496, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + -1.4824472665786743, + -0.034557100385427475, + 0.0 + ] + } + }, + "Component_[3867610358542973898]": { + "$type": "EditorEntitySortComponent", + "Id": 3867610358542973898 + }, + "Component_[7717372065847089412]": { + "$type": "EditorOnlyEntityComponent", + "Id": 7717372065847089412 + }, + "Component_[7783943040473764331]": { + "$type": "EditorInspectorComponent", + "Id": 7783943040473764331, + "ComponentOrderEntryArray": [ + { + "ComponentId": 17852268252813268496 + }, + { + "ComponentId": 12454042755417175050, + "SortIndex": 1 + }, + { + "ComponentId": 13691807045809495479, + "SortIndex": 2 + } + ] + }, + "Component_[833407121913837256]": { + "$type": "EditorLockComponent", + "Id": 833407121913837256 + } + } + }, + "Entity_[267186044133]": { + "Id": "Entity_[267186044133]", + "Name": "SphereLight", + "Components": { + "Component_[10922228943444131599]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 10922228943444131599 + }, + "Component_[11625534306113165068]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 11625534306113165068, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 0.2636711895465851, + 2.2845842838287354, + 0.22468790411949158 + ] + } + }, + "Component_[12372418243816154216]": { + "$type": "EditorSphereShapeComponent", + "Id": 12372418243816154216, + "ShapeColor": [ + 0.3289234936237335, + 0.7307698130607605, + 0.14859239757061005, + 1.0 + ] + }, + "Component_[12579170654872581897]": { + "$type": "EditorLockComponent", + "Id": 12579170654872581897 + }, + "Component_[12844637542561882557]": { + "$type": "EditorOnlyEntityComponent", + "Id": 12844637542561882557 + }, + "Component_[13087890528096920855]": { + "$type": "EditorInspectorComponent", + "Id": 13087890528096920855, + "ComponentOrderEntryArray": [ + { + "ComponentId": 11625534306113165068 + }, + { + "ComponentId": 13427905514841050195, + "SortIndex": 1 + }, + { + "ComponentId": 12372418243816154216, + "SortIndex": 2 + } + ] + }, + "Component_[13427905514841050195]": { + "$type": "AZ::Render::EditorAreaLightComponent", + "Id": 13427905514841050195, + "Controller": { + "Configuration": { + "LightType": 1, + "Color": [ + 0.3289234936237335, + 0.7307698130607605, + 0.14859239757061005 + ], + "IntensityMode": 1, + "Intensity": 676.7677001953125, + "AttenuationRadius": 226.51287841796875 + } + } + }, + "Component_[15364092815744365073]": { + "$type": "SelectionComponent", + "Id": 15364092815744365073 + }, + "Component_[2481373975540551564]": { + "$type": "EditorPendingCompositionComponent", + "Id": 2481373975540551564 + }, + "Component_[4101167782224846352]": { + "$type": "EditorEntityIconComponent", + "Id": 4101167782224846352 + }, + "Component_[8664715119660216219]": { + "$type": "EditorEntitySortComponent", + "Id": 8664715119660216219 + }, + "Component_[8952093761729701957]": { + "$type": "EditorVisibilityComponent", + "Id": 8952093761729701957, + "VisibilityFlag": false + } + } + }, + "Entity_[275775978725]": { + "Id": "Entity_[275775978725]", + "Name": "TubeLight", + "Components": { + "Component_[10922228943444131599]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 10922228943444131599, + "DisabledComponents": [ + { + "$type": "EditorSphereShapeComponent", + "Id": 12372418243816154216, + "ShapeColor": [ + 0.3289234936237335, + 0.7307698130607605, + 0.14859239757061005, + 1.0 + ] + } + ] + }, + "Component_[11625534306113165068]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 11625534306113165068, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + -4.275930881500244, + 0.5104026794433594, + 2.3807857036590576 + ], + "Rotate": [ + 270.0043029785156, + 0.16617189347743988, + 268.51611328125 + ] + } + }, + "Component_[12579170654872581897]": { + "$type": "EditorLockComponent", + "Id": 12579170654872581897 + }, + "Component_[12844637542561882557]": { + "$type": "EditorOnlyEntityComponent", + "Id": 12844637542561882557 + }, + "Component_[13087890528096920855]": { + "$type": "EditorInspectorComponent", + "Id": 13087890528096920855, + "ComponentOrderEntryArray": [ + { + "ComponentId": 11625534306113165068 + }, + { + "ComponentId": 13427905514841050195, + "SortIndex": 1 + }, + { + "ComponentId": 12372418243816154216, + "SortIndex": 2 + }, + { + "ComponentId": 2193911499802409037, + "SortIndex": 3 + } + ] + }, + "Component_[13427905514841050195]": { + "$type": "AZ::Render::EditorAreaLightComponent", + "Id": 13427905514841050195, + "Controller": { + "Configuration": { + "LightType": 3, + "Color": [ + 0.8521705865859985, + 0.7865872979164124, + 0.6079347133636475 + ], + "IntensityMode": 1, + "Intensity": 10000.0, + "AttenuationRadius": 21608.193359375 + } + } + }, + "Component_[15364092815744365073]": { + "$type": "SelectionComponent", + "Id": 15364092815744365073 + }, + "Component_[2193911499802409037]": { + "$type": "EditorCapsuleShapeComponent", + "Id": 2193911499802409037, + "ShapeColor": [ + 0.8521705865859985, + 0.7865872979164124, + 0.6079347133636475, + 1.0 + ], + "CapsuleShape": { + "Configuration": { + "Height": 5.0, + "Radius": 0.10000000149011612 + } + } + }, + "Component_[2481373975540551564]": { + "$type": "EditorPendingCompositionComponent", + "Id": 2481373975540551564 + }, + "Component_[4101167782224846352]": { + "$type": "EditorEntityIconComponent", + "Id": 4101167782224846352 + }, + "Component_[8664715119660216219]": { + "$type": "EditorEntitySortComponent", + "Id": 8664715119660216219 + }, + "Component_[8952093761729701957]": { + "$type": "EditorVisibilityComponent", + "Id": 8952093761729701957, + "VisibilityFlag": false + } + } + }, + "Entity_[482743502241]": { + "Id": "Entity_[482743502241]", + "Name": "Camera1", + "Components": { + "Component_[10672707967016183310]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 10672707967016183310 + }, + "Component_[13520081755303040361]": { + "$type": "EditorLockComponent", + "Id": 13520081755303040361 + }, + "Component_[13650522584195762912]": { + "$type": "SelectionComponent", + "Id": 13650522584195762912 + }, + "Component_[14204465933176839167]": { + "$type": "EditorOnlyEntityComponent", + "Id": 14204465933176839167 + }, + "Component_[14509697511269710983]": { + "$type": "EditorEntitySortComponent", + "Id": 14509697511269710983 + }, + "Component_[271930369355383880]": { + "$type": "EditorEntityIconComponent", + "Id": 271930369355383880 + }, + "Component_[5015186380056948439]": { + "$type": "EditorInspectorComponent", + "Id": 5015186380056948439 + }, + "Component_[6297637832938894772]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 6297637832938894772, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + -0.0018702250672504306, + 2.9982283115386963, + 3.0017592906951904 + ], + "Rotate": [ + 20.080352783203125, + -0.020488755777478218, + 179.92381286621094 + ] + } + }, + "Component_[6611378759823339947]": { + "$type": "EditorPendingCompositionComponent", + "Id": 6611378759823339947 + }, + "Component_[8475839846509409509]": { + "$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent", + "Id": 8475839846509409509, + "Controller": { + "Configuration": { + "Field of View": 90.00020599365234, + "EditorEntityId": 478448534945 + } + } + }, + "Component_[9659542522325095386]": { + "$type": "EditorVisibilityComponent", + "Id": 9659542522325095386 + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/hermanubis/tags.txt b/AutomatedTesting/Levels/Graphics/hermanubis/tags.txt new file mode 100644 index 0000000000..0d6c1880e7 --- /dev/null +++ b/AutomatedTesting/Levels/Graphics/hermanubis/tags.txt @@ -0,0 +1,12 @@ +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 diff --git a/AutomatedTesting/Levels/Graphics/hermanubis_high/hermanubis_high.prefab b/AutomatedTesting/Levels/Graphics/hermanubis_high/hermanubis_high.prefab new file mode 100644 index 0000000000..3378a0c144 --- /dev/null +++ b/AutomatedTesting/Levels/Graphics/hermanubis_high/hermanubis_high.prefab @@ -0,0 +1,943 @@ +{ + "ContainerEntity": { + "Id": "ContainerEntity", + "Name": "hermanubis_high", + "Components": { + "Component_[10182366347512475253]": { + "$type": "EditorPrefabComponent", + "Id": 10182366347512475253 + }, + "Component_[12917798267488243668]": { + "$type": "EditorPendingCompositionComponent", + "Id": 12917798267488243668 + }, + "Component_[3261249813163778338]": { + "$type": "EditorOnlyEntityComponent", + "Id": 3261249813163778338 + }, + "Component_[3837204912784440039]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 3837204912784440039 + }, + "Component_[4272963378099646759]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 4272963378099646759, + "Parent Entity": "" + }, + "Component_[4848458548047175816]": { + "$type": "EditorVisibilityComponent", + "Id": 4848458548047175816 + }, + "Component_[5787060997243919943]": { + "$type": "EditorInspectorComponent", + "Id": 5787060997243919943 + }, + "Component_[7804170251266531779]": { + "$type": "EditorLockComponent", + "Id": 7804170251266531779 + }, + "Component_[7874177159288365422]": { + "$type": "EditorEntitySortComponent", + "Id": 7874177159288365422, + "Child Entity Order": [ + "Entity_[243647107259]", + "Entity_[247179151093]", + "Entity_[262891076837]", + "Entity_[242884183797]", + "Entity_[258596109541]", + "Entity_[267186044133]", + "Entity_[275775978725]", + "Entity_[250006174949]" + ] + }, + "Component_[8018146290632383969]": { + "$type": "EditorEntityIconComponent", + "Id": 8018146290632383969 + }, + "Component_[8452360690590857075]": { + "$type": "SelectionComponent", + "Id": 8452360690590857075 + } + } + }, + "Entities": { + "Entity_[242884183797]": { + "Id": "Entity_[242884183797]", + "Name": "Hermanubis_stone", + "Components": { + "Component_[1026780512255775175]": { + "$type": "EditorEntityIconComponent", + "Id": 1026780512255775175 + }, + "Component_[10882452951986489612]": { + "$type": "SelectionComponent", + "Id": 10882452951986489612 + }, + "Component_[12454042755417175050]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 12454042755417175050, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{35A45F31-F1C1-5076-8B51-FF599E2EEBAA}", + "subId": 274433667 + }, + "assetHint": "objects/hermanubis/hermanubis_high.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[13691807045809495479]": { + "$type": "EditorMaterialComponent", + "Id": 13691807045809495479, + "Controller": { + "Configuration": { + "materials": { + "{}": { + "MaterialAsset": { + "assetId": { + "guid": "{A78EA2FC-688B-5E3A-A7F6-DB413D11D4CF}" + }, + "assetHint": "materials/presets/pbr/metal_chrome_matte.azmaterial" + } + } + } + } + }, + "materialSlotsByLodEnabled": true + }, + "Component_[14490373655742304057]": { + "$type": "EditorPendingCompositionComponent", + "Id": 14490373655742304057 + }, + "Component_[15248132570755287431]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 15248132570755287431 + }, + "Component_[16950375358457415777]": { + "$type": "EditorVisibilityComponent", + "Id": 16950375358457415777 + }, + "Component_[17852268252813268496]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 17852268252813268496, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 3.810185432434082, + 0.0, + 0.0 + ] + } + }, + "Component_[3867610358542973898]": { + "$type": "EditorEntitySortComponent", + "Id": 3867610358542973898 + }, + "Component_[7717372065847089412]": { + "$type": "EditorOnlyEntityComponent", + "Id": 7717372065847089412 + }, + "Component_[7783943040473764331]": { + "$type": "EditorInspectorComponent", + "Id": 7783943040473764331, + "ComponentOrderEntryArray": [ + { + "ComponentId": 17852268252813268496 + }, + { + "ComponentId": 12454042755417175050, + "SortIndex": 1 + }, + { + "ComponentId": 13691807045809495479, + "SortIndex": 2 + } + ] + }, + "Component_[833407121913837256]": { + "$type": "EditorLockComponent", + "Id": 833407121913837256 + } + } + }, + "Entity_[243647107259]": { + "Id": "Entity_[243647107259]", + "Name": "Camera1", + "Components": { + "Component_[11276153162797125616]": { + "$type": "GenericComponentWrapper", + "Id": 11276153162797125616, + "m_template": { + "$type": "FlyCameraInputComponent" + } + }, + "Component_[11484120648160206262]": { + "$type": "EditorLockComponent", + "Id": 11484120648160206262 + }, + "Component_[14251459960897306807]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 14251459960897306807, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + -0.10533800721168518, + -4.001697063446045, + 3.061025619506836 + ], + "Rotate": [ + -19.998117446899414, + 0.01881762035191059, + -0.051706261932849884 + ], + "Scale": [ + 0.9999998807907104, + 1.0, + 1.0 + ] + } + }, + "Component_[149351061984148634]": { + "$type": "EditorOnlyEntityComponent", + "Id": 149351061984148634 + }, + "Component_[15121925351155689107]": { + "$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent", + "Id": 15121925351155689107, + "Controller": { + "Configuration": { + "EditorEntityId": 243647107259 + } + } + }, + "Component_[15327903729148812780]": { + "$type": "EditorPendingCompositionComponent", + "Id": 15327903729148812780 + }, + "Component_[17667820301809320373]": { + "$type": "EditorEntityIconComponent", + "Id": 17667820301809320373 + }, + "Component_[17708351813187009272]": { + "$type": "EditorVisibilityComponent", + "Id": 17708351813187009272 + }, + "Component_[17941668830905411554]": { + "$type": "SelectionComponent", + "Id": 17941668830905411554 + }, + "Component_[48451466091772435]": { + "$type": "EditorEntitySortComponent", + "Id": 48451466091772435 + }, + "Component_[6163614082436403601]": { + "$type": "EditorInspectorComponent", + "Id": 6163614082436403601, + "ComponentOrderEntryArray": [ + { + "ComponentId": 14251459960897306807 + }, + { + "ComponentId": 15121925351155689107, + "SortIndex": 1 + }, + { + "ComponentId": 11935019334576395684, + "SortIndex": 2 + } + ] + }, + "Component_[8660334631968180943]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 8660334631968180943 + } + } + }, + "Entity_[247179151093]": { + "Id": "Entity_[247179151093]", + "Name": "Hermanubis_brass", + "Components": { + "Component_[1026780512255775175]": { + "$type": "EditorEntityIconComponent", + "Id": 1026780512255775175 + }, + "Component_[10882452951986489612]": { + "$type": "SelectionComponent", + "Id": 10882452951986489612 + }, + "Component_[12454042755417175050]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 12454042755417175050, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{35A45F31-F1C1-5076-8B51-FF599E2EEBAA}", + "subId": 274433667 + }, + "assetHint": "objects/hermanubis/hermanubis_high.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[13691807045809495479]": { + "$type": "EditorMaterialComponent", + "Id": 13691807045809495479, + "Controller": { + "Configuration": { + "materials": { + "{}": { + "MaterialAsset": { + "assetId": { + "guid": "{80E0F2A7-1EE4-597F-80EF-985C65BCE2EB}" + }, + "assetHint": "materials/presets/pbr/metal_brass.azmaterial" + } + } + } + } + }, + "materialSlotsByLodEnabled": true + }, + "Component_[14490373655742304057]": { + "$type": "EditorPendingCompositionComponent", + "Id": 14490373655742304057 + }, + "Component_[15248132570755287431]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 15248132570755287431 + }, + "Component_[16950375358457415777]": { + "$type": "EditorVisibilityComponent", + "Id": 16950375358457415777 + }, + "Component_[17852268252813268496]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 17852268252813268496, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + -4.019397258758545, + -0.034557100385427475, + 0.0 + ] + } + }, + "Component_[3867610358542973898]": { + "$type": "EditorEntitySortComponent", + "Id": 3867610358542973898 + }, + "Component_[7717372065847089412]": { + "$type": "EditorOnlyEntityComponent", + "Id": 7717372065847089412 + }, + "Component_[7783943040473764331]": { + "$type": "EditorInspectorComponent", + "Id": 7783943040473764331, + "ComponentOrderEntryArray": [ + { + "ComponentId": 17852268252813268496 + }, + { + "ComponentId": 12454042755417175050, + "SortIndex": 1 + }, + { + "ComponentId": 13691807045809495479, + "SortIndex": 2 + } + ] + }, + "Component_[833407121913837256]": { + "$type": "EditorLockComponent", + "Id": 833407121913837256 + } + } + }, + "Entity_[250006174949]": { + "Id": "Entity_[250006174949]", + "Name": "WorldOrigin", + "Components": { + "Component_[13379444112629774116]": { + "$type": "EditorEntityIconComponent", + "Id": 13379444112629774116 + }, + "Component_[13797113876161133062]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 13797113876161133062, + "Parent Entity": "ContainerEntity" + }, + "Component_[16382506042739704306]": { + "$type": "EditorInspectorComponent", + "Id": 16382506042739704306, + "ComponentOrderEntryArray": [ + { + "ComponentId": 13797113876161133062 + }, + { + "ComponentId": 8816319458242680670, + "SortIndex": 1 + } + ] + }, + "Component_[2147729086581105478]": { + "$type": "EditorOnlyEntityComponent", + "Id": 2147729086581105478 + }, + "Component_[2433100672102773575]": { + "$type": "SelectionComponent", + "Id": 2433100672102773575 + }, + "Component_[4832829387489613630]": { + "$type": "EditorVisibilityComponent", + "Id": 4832829387489613630 + }, + "Component_[5585931842723227683]": { + "$type": "EditorEntitySortComponent", + "Id": 5585931842723227683, + "Child Entity Order": [ + "Entity_[254301142245]" + ] + }, + "Component_[7088004383223117498]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 7088004383223117498 + }, + "Component_[7856264459806503732]": { + "$type": "EditorPendingCompositionComponent", + "Id": 7856264459806503732 + }, + "Component_[8816319458242680670]": { + "$type": "AZ::Render::EditorGridComponent", + "Id": 8816319458242680670 + }, + "Component_[930042309700959235]": { + "$type": "EditorLockComponent", + "Id": 930042309700959235 + } + } + }, + "Entity_[254301142245]": { + "Id": "Entity_[254301142245]", + "Name": "GlobalSkylight", + "Components": { + "Component_[10076500561520682485]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 10076500561520682485, + "Parent Entity": "Entity_[250006174949]" + }, + "Component_[12626877995248630950]": { + "$type": "EditorInspectorComponent", + "Id": 12626877995248630950, + "ComponentOrderEntryArray": [ + { + "ComponentId": 10076500561520682485 + }, + { + "ComponentId": 8158442301445120126, + "SortIndex": 1 + }, + { + "ComponentId": 7260006984216245935, + "SortIndex": 2 + } + ] + }, + "Component_[13040837632921717329]": { + "$type": "SelectionComponent", + "Id": 13040837632921717329 + }, + "Component_[1390505494369101864]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 1390505494369101864 + }, + "Component_[6733278858932131836]": { + "$type": "EditorVisibilityComponent", + "Id": 6733278858932131836 + }, + "Component_[7260006984216245935]": { + "$type": "AZ::Render::EditorImageBasedLightComponent", + "Id": 7260006984216245935, + "Controller": { + "Configuration": { + "diffuseImageAsset": { + "assetId": { + "guid": "{3B78EA69-7CF0-56A7-A49A-110B88412666}", + "subId": 3000 + }, + "assetHint": "lightingpresets/greenwich_park_02_4k_iblskyboxcm_ibldiffuse.exr.streamingimage" + }, + "specularImageAsset": { + "assetId": { + "guid": "{3B78EA69-7CF0-56A7-A49A-110B88412666}", + "subId": 2000 + }, + "assetHint": "lightingpresets/greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage" + } + } + } + }, + "Component_[7944006745008331817]": { + "$type": "EditorEntitySortComponent", + "Id": 7944006745008331817 + }, + "Component_[8158442301445120126]": { + "$type": "AZ::Render::EditorHDRiSkyboxComponent", + "Id": 8158442301445120126, + "Controller": { + "Configuration": { + "CubemapAsset": { + "assetId": { + "guid": "{3B78EA69-7CF0-56A7-A49A-110B88412666}", + "subId": 1000 + }, + "assetHint": "lightingpresets/greenwich_park_02_4k_iblskyboxcm.exr.streamingimage" + } + } + } + }, + "Component_[8255370213772594097]": { + "$type": "EditorOnlyEntityComponent", + "Id": 8255370213772594097 + }, + "Component_[8551180373364097938]": { + "$type": "EditorLockComponent", + "Id": 8551180373364097938 + }, + "Component_[8852330656608249928]": { + "$type": "EditorPendingCompositionComponent", + "Id": 8852330656608249928 + }, + "Component_[8913694496991926693]": { + "$type": "EditorEntityIconComponent", + "Id": 8913694496991926693 + } + } + }, + "Entity_[258596109541]": { + "Id": "Entity_[258596109541]", + "Name": "Hermanubis_stone", + "Components": { + "Component_[1026780512255775175]": { + "$type": "EditorEntityIconComponent", + "Id": 1026780512255775175 + }, + "Component_[10882452951986489612]": { + "$type": "SelectionComponent", + "Id": 10882452951986489612 + }, + "Component_[12454042755417175050]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 12454042755417175050, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{35A45F31-F1C1-5076-8B51-FF599E2EEBAA}", + "subId": 274433667 + }, + "assetHint": "objects/hermanubis/hermanubis_high.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[13691807045809495479]": { + "$type": "EditorMaterialComponent", + "Id": 13691807045809495479, + "Controller": { + "Configuration": { + "materials": { + "{}": { + "MaterialAsset": { + "assetId": { + "guid": "{B7C712DC-4839-58BB-B522-A4F120084CF5}" + }, + "assetHint": "materials/presets/pbr/metal_chrome.azmaterial" + } + } + } + } + }, + "materialSlotsByLodEnabled": true + }, + "Component_[14490373655742304057]": { + "$type": "EditorPendingCompositionComponent", + "Id": 14490373655742304057 + }, + "Component_[15248132570755287431]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 15248132570755287431 + }, + "Component_[16950375358457415777]": { + "$type": "EditorVisibilityComponent", + "Id": 16950375358457415777 + }, + "Component_[17852268252813268496]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 17852268252813268496, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 1.1189539432525635, + 0.0, + 0.0 + ] + } + }, + "Component_[3867610358542973898]": { + "$type": "EditorEntitySortComponent", + "Id": 3867610358542973898 + }, + "Component_[7717372065847089412]": { + "$type": "EditorOnlyEntityComponent", + "Id": 7717372065847089412 + }, + "Component_[7783943040473764331]": { + "$type": "EditorInspectorComponent", + "Id": 7783943040473764331, + "ComponentOrderEntryArray": [ + { + "ComponentId": 17852268252813268496 + }, + { + "ComponentId": 12454042755417175050, + "SortIndex": 1 + }, + { + "ComponentId": 13691807045809495479, + "SortIndex": 2 + } + ] + }, + "Component_[833407121913837256]": { + "$type": "EditorLockComponent", + "Id": 833407121913837256 + } + } + }, + "Entity_[262891076837]": { + "Id": "Entity_[262891076837]", + "Name": "Hermanubis_brass", + "Components": { + "Component_[1026780512255775175]": { + "$type": "EditorEntityIconComponent", + "Id": 1026780512255775175 + }, + "Component_[10882452951986489612]": { + "$type": "SelectionComponent", + "Id": 10882452951986489612 + }, + "Component_[12454042755417175050]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 12454042755417175050, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{35A45F31-F1C1-5076-8B51-FF599E2EEBAA}", + "subId": 274433667 + }, + "assetHint": "objects/hermanubis/hermanubis_high.azmodel" + }, + "LodOverride": 255 + } + } + }, + "Component_[13691807045809495479]": { + "$type": "EditorMaterialComponent", + "Id": 13691807045809495479, + "Controller": { + "Configuration": { + "materials": { + "{}": { + "MaterialAsset": { + "assetId": { + "guid": "{CAF50181-3384-5DF2-9304-C6E48E83C72D}" + }, + "assetHint": "materials/presets/pbr/metal_chrome_polished.azmaterial" + } + } + } + } + }, + "materialSlotsByLodEnabled": true + }, + "Component_[14490373655742304057]": { + "$type": "EditorPendingCompositionComponent", + "Id": 14490373655742304057 + }, + "Component_[15248132570755287431]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 15248132570755287431 + }, + "Component_[16950375358457415777]": { + "$type": "EditorVisibilityComponent", + "Id": 16950375358457415777 + }, + "Component_[17852268252813268496]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 17852268252813268496, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + -1.4824472665786743, + -0.034557100385427475, + 0.0 + ] + } + }, + "Component_[3867610358542973898]": { + "$type": "EditorEntitySortComponent", + "Id": 3867610358542973898 + }, + "Component_[7717372065847089412]": { + "$type": "EditorOnlyEntityComponent", + "Id": 7717372065847089412 + }, + "Component_[7783943040473764331]": { + "$type": "EditorInspectorComponent", + "Id": 7783943040473764331, + "ComponentOrderEntryArray": [ + { + "ComponentId": 17852268252813268496 + }, + { + "ComponentId": 12454042755417175050, + "SortIndex": 1 + }, + { + "ComponentId": 13691807045809495479, + "SortIndex": 2 + } + ] + }, + "Component_[833407121913837256]": { + "$type": "EditorLockComponent", + "Id": 833407121913837256 + } + } + }, + "Entity_[267186044133]": { + "Id": "Entity_[267186044133]", + "Name": "SphereLight", + "Components": { + "Component_[10922228943444131599]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 10922228943444131599 + }, + "Component_[11625534306113165068]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 11625534306113165068, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + 0.2636711895465851, + 2.2845842838287354, + 0.22468790411949158 + ] + } + }, + "Component_[12372418243816154216]": { + "$type": "EditorSphereShapeComponent", + "Id": 12372418243816154216, + "ShapeColor": [ + 0.3289234936237335, + 0.7307698130607605, + 0.14859239757061005, + 1.0 + ] + }, + "Component_[12579170654872581897]": { + "$type": "EditorLockComponent", + "Id": 12579170654872581897 + }, + "Component_[12844637542561882557]": { + "$type": "EditorOnlyEntityComponent", + "Id": 12844637542561882557 + }, + "Component_[13087890528096920855]": { + "$type": "EditorInspectorComponent", + "Id": 13087890528096920855, + "ComponentOrderEntryArray": [ + { + "ComponentId": 11625534306113165068 + }, + { + "ComponentId": 13427905514841050195, + "SortIndex": 1 + }, + { + "ComponentId": 12372418243816154216, + "SortIndex": 2 + } + ] + }, + "Component_[13427905514841050195]": { + "$type": "AZ::Render::EditorAreaLightComponent", + "Id": 13427905514841050195, + "Controller": { + "Configuration": { + "LightType": 1, + "Color": [ + 0.3289234936237335, + 0.7307698130607605, + 0.14859239757061005 + ], + "IntensityMode": 1, + "Intensity": 676.7677001953125, + "AttenuationRadius": 226.51287841796875 + } + } + }, + "Component_[15364092815744365073]": { + "$type": "SelectionComponent", + "Id": 15364092815744365073 + }, + "Component_[2481373975540551564]": { + "$type": "EditorPendingCompositionComponent", + "Id": 2481373975540551564 + }, + "Component_[4101167782224846352]": { + "$type": "EditorEntityIconComponent", + "Id": 4101167782224846352 + }, + "Component_[8664715119660216219]": { + "$type": "EditorEntitySortComponent", + "Id": 8664715119660216219 + }, + "Component_[8952093761729701957]": { + "$type": "EditorVisibilityComponent", + "Id": 8952093761729701957, + "VisibilityFlag": false + } + } + }, + "Entity_[275775978725]": { + "Id": "Entity_[275775978725]", + "Name": "TubeLight", + "Components": { + "Component_[10922228943444131599]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 10922228943444131599, + "DisabledComponents": [ + { + "$type": "EditorSphereShapeComponent", + "Id": 12372418243816154216, + "ShapeColor": [ + 0.3289234936237335, + 0.7307698130607605, + 0.14859239757061005, + 1.0 + ] + } + ] + }, + "Component_[11625534306113165068]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 11625534306113165068, + "Parent Entity": "ContainerEntity", + "Transform Data": { + "Translate": [ + -4.275930881500244, + 0.5104026794433594, + 2.3807857036590576 + ], + "Rotate": [ + 270.0043029785156, + 0.16617189347743988, + 268.51611328125 + ] + } + }, + "Component_[12579170654872581897]": { + "$type": "EditorLockComponent", + "Id": 12579170654872581897 + }, + "Component_[12844637542561882557]": { + "$type": "EditorOnlyEntityComponent", + "Id": 12844637542561882557 + }, + "Component_[13087890528096920855]": { + "$type": "EditorInspectorComponent", + "Id": 13087890528096920855, + "ComponentOrderEntryArray": [ + { + "ComponentId": 11625534306113165068 + }, + { + "ComponentId": 13427905514841050195, + "SortIndex": 1 + }, + { + "ComponentId": 12372418243816154216, + "SortIndex": 2 + }, + { + "ComponentId": 2193911499802409037, + "SortIndex": 3 + } + ] + }, + "Component_[13427905514841050195]": { + "$type": "AZ::Render::EditorAreaLightComponent", + "Id": 13427905514841050195, + "Controller": { + "Configuration": { + "LightType": 3, + "Color": [ + 0.8521705865859985, + 0.7865872979164124, + 0.6079347133636475 + ], + "IntensityMode": 1, + "Intensity": 10000.0, + "AttenuationRadius": 21608.193359375 + } + } + }, + "Component_[15364092815744365073]": { + "$type": "SelectionComponent", + "Id": 15364092815744365073 + }, + "Component_[2193911499802409037]": { + "$type": "EditorCapsuleShapeComponent", + "Id": 2193911499802409037, + "ShapeColor": [ + 0.8521705865859985, + 0.7865872979164124, + 0.6079347133636475, + 1.0 + ], + "CapsuleShape": { + "Configuration": { + "Height": 5.0, + "Radius": 0.10000000149011612 + } + } + }, + "Component_[2481373975540551564]": { + "$type": "EditorPendingCompositionComponent", + "Id": 2481373975540551564 + }, + "Component_[4101167782224846352]": { + "$type": "EditorEntityIconComponent", + "Id": 4101167782224846352 + }, + "Component_[8664715119660216219]": { + "$type": "EditorEntitySortComponent", + "Id": 8664715119660216219 + }, + "Component_[8952093761729701957]": { + "$type": "EditorVisibilityComponent", + "Id": 8952093761729701957, + "VisibilityFlag": false + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/hermanubis_high/tags.txt b/AutomatedTesting/Levels/Graphics/hermanubis_high/tags.txt new file mode 100644 index 0000000000..0d6c1880e7 --- /dev/null +++ b/AutomatedTesting/Levels/Graphics/hermanubis_high/tags.txt @@ -0,0 +1,12 @@ +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 +0,0,0,0,0,0 diff --git a/AutomatedTesting/Objects/ShaderBall_simple.fbx b/AutomatedTesting/Objects/ShaderBall_simple.fbx new file mode 100644 index 0000000000..50b7b8f44d --- /dev/null +++ b/AutomatedTesting/Objects/ShaderBall_simple.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5f7a86a693878c10f91783955cc72535bf7d7c495163087a4c1982f228d27f0 +size 2145248 diff --git a/AutomatedTesting/Objects/bunny.fbx b/AutomatedTesting/Objects/bunny.fbx new file mode 100644 index 0000000000..f0a16349f7 --- /dev/null +++ b/AutomatedTesting/Objects/bunny.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef71257b240a7e704731806f8cd4b966af5d3c60f22881f9c6a6320180ee71a4 +size 2496384 diff --git a/AutomatedTesting/Objects/cone.fbx b/AutomatedTesting/Objects/cone.fbx new file mode 100644 index 0000000000..081b8b119d --- /dev/null +++ b/AutomatedTesting/Objects/cone.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:531b6473b314259504ab595e4983838b5866035ef4d70cedaf4cc9c7d9e65c3a +size 24512 diff --git a/AutomatedTesting/Objects/cube.fbx b/AutomatedTesting/Objects/cube.fbx new file mode 100644 index 0000000000..616c7b4ff3 --- /dev/null +++ b/AutomatedTesting/Objects/cube.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e32877eab35459499c73ff093df898f93bf3e7379de25eef6875d693be9bec81 +size 18015 diff --git a/AutomatedTesting/Objects/cylinder.fbx b/AutomatedTesting/Objects/cylinder.fbx new file mode 100644 index 0000000000..18ab200b4c --- /dev/null +++ b/AutomatedTesting/Objects/cylinder.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2949a50eec079a7d43a1d92e056c580ef625ee39e00e91cc25318319e37dcd3b +size 115689 diff --git a/AutomatedTesting/Objects/plane.fbx b/AutomatedTesting/Objects/plane.fbx new file mode 100644 index 0000000000..b274bfa282 --- /dev/null +++ b/AutomatedTesting/Objects/plane.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a1f8d75dcd85e8b4aa57f6c0c81af0300ff96915ba3c2b591095c215d5e1d8c +size 12072 diff --git a/AutomatedTesting/Objects/suzanne.fbx b/AutomatedTesting/Objects/suzanne.fbx new file mode 100644 index 0000000000..171a6d21e9 --- /dev/null +++ b/AutomatedTesting/Objects/suzanne.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3bcfac5de831c269dac58e7d73d1dc61eb8d9f6d8a241f5c029537b6bcdf166 +size 1088304 diff --git a/AutomatedTesting/TestAssets/test_chunks_builder.py b/AutomatedTesting/TestAssets/test_chunks_builder.py index 2fd1ad9db9..b18902a34c 100755 --- a/AutomatedTesting/TestAssets/test_chunks_builder.py +++ b/AutomatedTesting/TestAssets/test_chunks_builder.py @@ -28,7 +28,7 @@ def update_manifest(scene): meshGroup = sceneManifest.add_mesh_group(chunkName) meshGroup['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, scene.sourceFilename + chunkName)) + '}' sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by test_chunks_builder') - sceneManifest.mesh_group_set_origin(meshGroup, None, 0, 0, 0, 1.0) + sceneManifest.mesh_group_add_advanced_coordinate_system(meshGroup) for meshIndex in range(len(chunkNameList)): if (activeMeshIndex == meshIndex): sceneManifest.mesh_group_select_node(meshGroup, chunkNameList[meshIndex]) diff --git a/Code/Editor/BaseLibrary.cpp b/Code/Editor/BaseLibrary.cpp deleted file mode 100644 index 15742bd254..0000000000 --- a/Code/Editor/BaseLibrary.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "BaseLibrary.h" -#include "BaseLibraryItem.h" -#include "Include/IBaseLibraryManager.h" -#include -#include - -////////////////////////////////////////////////////////////////////////// -// CBaseLibrary implementation. -////////////////////////////////////////////////////////////////////////// -CBaseLibrary::CBaseLibrary(IBaseLibraryManager* pManager) - : m_pManager(pManager) - , m_bModified(false) - , m_bLevelLib(false) - , m_bNewLibrary(true) -{ -} - -////////////////////////////////////////////////////////////////////////// -CBaseLibrary::~CBaseLibrary() -{ - m_items.clear(); -} - -////////////////////////////////////////////////////////////////////////// -IBaseLibraryManager* CBaseLibrary::GetManager() -{ - return m_pManager; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibrary::RemoveAllItems() -{ - AddRef(); - for (int i = 0; i < m_items.size(); i++) - { - // Unregister item in case it was registered. It is ok if it wasn't. This is still safe to call. - m_pManager->UnregisterItem(m_items[i]); - // Clear library item. - m_items[i]->m_library = nullptr; - } - m_items.clear(); - Release(); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibrary::SetName(const QString& name) -{ - //the fullname of the items in the library will be changed due to library's name change - //so we need unregistered them and register them after their name changed. - for (int i = 0; i < m_items.size(); i++) - { - m_pManager->UnregisterItem(m_items[i]); - } - - m_name = name; - - for (int i = 0; i < m_items.size(); i++) - { - m_pManager->RegisterItem(m_items[i]); - } - - SetModified(); -} - -////////////////////////////////////////////////////////////////////////// -const QString& CBaseLibrary::GetName() const -{ - return m_name; -} - -////////////////////////////////////////////////////////////////////////// -bool CBaseLibrary::Save() -{ - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CBaseLibrary::Load(const QString& filename) -{ - m_filename = filename; - SetModified(false); - m_bNewLibrary = false; - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibrary::SetModified(bool bModified) -{ - if (bModified != m_bModified) - { - m_bModified = bModified; - emit Modified(bModified); - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibrary::AddItem(IDataBaseItem* item, bool bRegister) -{ - - CBaseLibraryItem* pLibItem = (CBaseLibraryItem*)item; - // Check if item is already assigned to this library. - if (pLibItem->m_library != this) - { - pLibItem->m_library = this; - m_items.push_back(pLibItem); - SetModified(); - if (bRegister) - { - m_pManager->RegisterItem(pLibItem); - } - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibrary::GetItem(int index) -{ - assert(index >= 0 && index < m_items.size()); - return m_items[index]; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibrary::RemoveItem(IDataBaseItem* item) -{ - - for (int i = 0; i < m_items.size(); i++) - { - if (m_items[i] == item) - { - // Unregister item in case it was registered. It is ok if it wasn't. This is still safe to call. - m_pManager->UnregisterItem(m_items[i]); - m_items.erase(m_items.begin() + i); - SetModified(); - break; - } - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibrary::FindItem(const QString& name) -{ - for (int i = 0; i < m_items.size(); i++) - { - if (QString::compare(m_items[i]->GetName(), name, Qt::CaseInsensitive) == 0) - { - return m_items[i]; - } - } - return nullptr; -} - -bool CBaseLibrary::AddLibraryToSourceControl(const QString& fullPathName) const -{ - IEditor* pEditor = GetIEditor(); - IFileUtil* pFileUtil = pEditor ? pEditor->GetFileUtil() : nullptr; - if (pFileUtil) - { - return pFileUtil->CheckoutFile(fullPathName.toUtf8().data(), nullptr); - } - - return false; -} - -bool CBaseLibrary::SaveLibrary(const char* name, bool saveEmptyLibrary) -{ - assert(name != nullptr); - if (name == nullptr) - { - CryFatalError("The library you are attempting to save has no name specified."); - return false; - } - - QString fileName(GetFilename()); - if (fileName.isEmpty() && !saveEmptyLibrary) - { - return false; - } - - fileName = Path::GamePathToFullPath(fileName); - - XmlNodeRef root = GetIEditor()->GetSystem()->CreateXmlNode(name); - Serialize(root, false); - bool bRes = XmlHelpers::SaveXmlNode(GetIEditor()->GetFileUtil(), root, fileName.toUtf8().data()); - if (m_bNewLibrary) - { - AddLibraryToSourceControl(fileName); - m_bNewLibrary = false; - } - if (!bRes) - { - QByteArray filenameUtf8 = fileName.toUtf8(); - AZStd::string strMessage = AZStd::string::format("The file %s is read-only and the save of the library couldn't be performed. Try to remove the \"read-only\" flag or check-out the file and then try again.", filenameUtf8.data()); - CryMessageBox(strMessage.c_str(), "Saving Error", MB_OK | MB_ICONWARNING); - } - return bRes; -} - -//CONFETTI BEGIN -void CBaseLibrary::ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation) -{ - std::vector<_smart_ptr > temp; - for (unsigned int i = 0; i < m_items.size(); i++) - { - if (i == newLocation) - { - temp.push_back(_smart_ptr(item)); - } - if (m_items[i] != item) - { - temp.push_back(m_items[i]); - } - } - // If newLocation is greater than the original size, append the item to end of the list - if (newLocation >= m_items.size()) - { - temp.push_back(_smart_ptr(item)); - } - m_items = temp; -} -//CONFETTI END - -#include diff --git a/Code/Editor/BaseLibrary.h b/Code/Editor/BaseLibrary.h deleted file mode 100644 index 55079d3fde..0000000000 --- a/Code/Editor/BaseLibrary.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_BASELIBRARY_H -#define CRYINCLUDE_EDITOR_BASELIBRARY_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "Include/IDataBaseLibrary.h" -#include "Include/IBaseLibraryManager.h" -#include "Include/EditorCoreAPI.h" -#include "Util/TRefCountBase.h" - -#include -#endif - -// Ensure we don't try to dllimport when moc includes us -#if defined(Q_MOC_BUILD) && !defined(EDITOR_CORE) -#define EDITOR_CORE -#endif - -/** This a base class for all Libraries used by Editor. -*/ -class EDITOR_CORE_API CBaseLibrary - : public QObject - , public TRefCountBase -{ - Q_OBJECT - -public: - explicit CBaseLibrary(IBaseLibraryManager* pManager); - ~CBaseLibrary(); - - //! Set library name. - virtual void SetName(const QString& name); - //! Get library name. - const QString& GetName() const override; - - //! Set new filename for this library. - virtual bool SetFilename(const QString& filename, [[maybe_unused]] bool checkForUnique = true) { m_filename = filename.toLower(); return true; }; - const QString& GetFilename() const override { return m_filename; }; - - bool Save() override = 0; - bool Load(const QString& filename) override = 0; - void Serialize(XmlNodeRef& node, bool bLoading) override = 0; - - //! Mark library as modified. - void SetModified(bool bModified = true) override; - //! Check if library was modified. - bool IsModified() const override { return m_bModified; }; - - ////////////////////////////////////////////////////////////////////////// - // Working with items. - ////////////////////////////////////////////////////////////////////////// - //! Add a new prototype to library. - void AddItem(IDataBaseItem* item, bool bRegister = true) override; - //! Get number of known prototypes. - int GetItemCount() const override { return static_cast(m_items.size()); } - //! Get prototype by index. - IDataBaseItem* GetItem(int index) override; - - //! Delete item by pointer of item. - void RemoveItem(IDataBaseItem* item) override; - - //! Delete all items from library. - void RemoveAllItems() override; - - //! Find library item by name. - //! Using linear search. - IDataBaseItem* FindItem(const QString& name) override; - - //! Check if this library is local level library. - bool IsLevelLibrary() const override { return m_bLevelLib; }; - - //! Set library to be level library. - void SetLevelLibrary(bool bEnable) override { m_bLevelLib = bEnable; }; - - ////////////////////////////////////////////////////////////////////////// - //! Return manager for this library. - IBaseLibraryManager* GetManager() override; - - // Saves the library with the main tag defined by the parameter name - bool SaveLibrary(const char* name, bool saveEmptyLibrary = false); - - //CONFETTI BEGIN - // Used to change the library item order - void ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation) override; - //CONFETTI END - -signals: - void Modified(bool bModified); - -private: - // Add the library to the source control - bool AddLibraryToSourceControl(const QString& fullPathName) const; - -protected: - - //! Name of the library. - QString m_name; - //! Filename of the library. - QString m_filename; - - //! Flag set when library was modified. - bool m_bModified; - - // Flag set when the library is just created and it's not yet saved for the first time. - bool m_bNewLibrary; - - //! Level library is saved within the level .ly file and is local for this level. - bool m_bLevelLib; - - ////////////////////////////////////////////////////////////////////////// - // Manager. - IBaseLibraryManager* m_pManager; - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - // Array of all our library items. - std::vector<_smart_ptr > m_items; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -#endif // CRYINCLUDE_EDITOR_BASELIBRARY_H diff --git a/Code/Editor/BaseLibraryItem.cpp b/Code/Editor/BaseLibraryItem.cpp deleted file mode 100644 index e3788bc3e4..0000000000 --- a/Code/Editor/BaseLibraryItem.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "BaseLibraryItem.h" -#include "BaseLibrary.h" -#include "BaseLibraryManager.h" -#include "Undo/IUndoObject.h" - -#include - -//undo object for multi-changes inside library item. such as set all variables to default values. -//For example: change particle emitter shape will lead to multiple variable changes -class CUndoBaseLibraryItem - : public IUndoObject -{ -public: - CUndoBaseLibraryItem(IBaseLibraryManager *libMgr, CBaseLibraryItem* libItem, bool ignoreChild) - : m_libMgr(libMgr) - { - assert(libItem); - assert(libMgr); - - m_itemPath = libItem->GetFullName(); - - //serialize the lib item to undo - m_undoCtx.node = GetIEditor()->GetSystem()->CreateXmlNode("Undo"); - m_undoCtx.bIgnoreChilds = ignoreChild; - m_undoCtx.bLoading = false; //saving - m_undoCtx.bUniqName = false; //don't generate new name - m_undoCtx.bCopyPaste = true; //so it won't override guid - m_undoCtx.bUndo = true; - libItem->Serialize(m_undoCtx); - - //evaluate size - XmlString xmlStr = m_undoCtx.node->getXML(); - m_size = sizeof(CUndoBaseLibraryItem); - m_size += static_cast(xmlStr.GetAllocatedMemory()); - m_size += m_itemPath.length(); - } - - -protected: - int GetSize() override - { - return m_size; - } - - void Undo(bool bUndo) override - { - //find the libItem - IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath); - if (libItem == nullptr) - { - //the undo stack is not reliable any more.. - assert(false); - return; - } - - //save for redo - if (bUndo) - { - m_redoCtx.node = GetIEditor()->GetSystem()->CreateXmlNode("Redo"); - m_redoCtx.bIgnoreChilds = m_undoCtx.bIgnoreChilds; - m_redoCtx.bLoading = false; //saving - m_redoCtx.bUniqName = false; - m_redoCtx.bCopyPaste = true; - m_redoCtx.bUndo = true; - libItem->Serialize(m_redoCtx); - - XmlString xmlStr = m_redoCtx.node->getXML(); - m_size += static_cast(xmlStr.GetAllocatedMemory()); - } - - //load previous saved data - m_undoCtx.bLoading = true; - libItem->Serialize(m_undoCtx); - } - - void Redo() override - { - //find the libItem - IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath); - if (libItem == nullptr || m_redoCtx.node == nullptr) - { - //the undo stack is not reliable any more.. - assert(false); - return; - } - - m_redoCtx.bLoading = true; - libItem->Serialize(m_redoCtx); - } - -private: - QString m_itemPath; - IDataBaseItem::SerializeContext m_undoCtx; //saved before operation - IDataBaseItem::SerializeContext m_redoCtx; //saved after operation so used for redo - IBaseLibraryManager* m_libMgr; - int m_size; -}; - -////////////////////////////////////////////////////////////////////////// -// CBaseLibraryItem implementation. -////////////////////////////////////////////////////////////////////////// -CBaseLibraryItem::CBaseLibraryItem() -{ - m_library = nullptr; - GenerateId(); - m_bModified = false; -} - -CBaseLibraryItem::~CBaseLibraryItem() -{ -} - -////////////////////////////////////////////////////////////////////////// -QString CBaseLibraryItem::GetFullName() const -{ - QString name; - if (m_library) - { - name = m_library->GetName() + "."; - } - name += m_name; - return name; -} - -////////////////////////////////////////////////////////////////////////// -QString CBaseLibraryItem::GetGroupName() -{ - QString str = GetName(); - int p = str.lastIndexOf('.'); - if (p >= 0) - { - return str.mid(0, p); - } - return ""; -} - -////////////////////////////////////////////////////////////////////////// -QString CBaseLibraryItem::GetShortName() -{ - QString str = GetName(); - int p = str.lastIndexOf('.'); - if (p >= 0) - { - return str.mid(p + 1); - } - p = str.lastIndexOf('/'); - if (p >= 0) - { - return str.mid(p + 1); - } - return str; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryItem::SetName(const QString& name) -{ - assert(m_library); - if (name == m_name) - { - return; - } - QString oldName = GetFullName(); - m_name = name; - ((CBaseLibraryManager*)m_library->GetManager())->OnRenameItem(this, oldName); -} - -////////////////////////////////////////////////////////////////////////// -const QString& CBaseLibraryItem::GetName() const -{ - return m_name; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryItem::GenerateId() -{ - GUID guid = AZ::Uuid::CreateRandom(); - SetGUID(guid); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryItem::SetGUID(REFGUID guid) -{ - if (m_library) - { - ((CBaseLibraryManager*)m_library->GetManager())->RegisterItem(this, guid); - } - m_guid = guid; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryItem::Serialize(SerializeContext& ctx) -{ - assert(m_library); - - XmlNodeRef node = ctx.node; - if (ctx.bLoading) - { - QString name = m_name; - // Loading - node->getAttr("Name", name); - - if (!ctx.bUniqName) - { - SetName(name); - } - else - { - SetName(GetLibrary()->GetManager()->MakeUniqueItemName(name)); - } - - if (!ctx.bCopyPaste) - { - GUID guid; - if (node->getAttr("Id", guid)) - { - SetGUID(guid); - } - } - } - else - { - // Saving. - node->setAttr("Name", m_name.toUtf8().data()); - node->setAttr("Id", m_guid); - node->setAttr("Library", GetLibrary()->GetName().toUtf8().data()); - } - m_bModified = false; -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CBaseLibraryItem::GetLibrary() const -{ - return m_library; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryItem::SetLibrary(CBaseLibrary* pLibrary) -{ - m_library = pLibrary; -} - -//! Mark library as modified. -void CBaseLibraryItem::SetModified(bool bModified) -{ - m_bModified = bModified; - if (m_bModified && m_library != nullptr) - { - m_library->SetModified(bModified); - } -} diff --git a/Code/Editor/BaseLibraryItem.h b/Code/Editor/BaseLibraryItem.h deleted file mode 100644 index 53cf0add2b..0000000000 --- a/Code/Editor/BaseLibraryItem.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_BASELIBRARYITEM_H -#define CRYINCLUDE_EDITOR_BASELIBRARYITEM_H -#pragma once - -#include "Include/IDataBaseItem.h" -#include "BaseLibrary.h" - -#include - -class CBaseLibrary; - -////////////////////////////////////////////////////////////////////////// -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -/** Base class for all items contained in BaseLibraray. -*/ -class EDITOR_CORE_API CBaseLibraryItem - : public TRefCountBase -{ - AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - CBaseLibraryItem(); - ~CBaseLibraryItem(); - - //! Set item name. - //! Its virtual, in case you want to override it in derrived item. - virtual void SetName(const QString& name); - //! Get item name. - const QString& GetName() const; - - //! Get full item name, including name of library. - //! Name formed by adding dot after name of library - //! eg. library Pickup and item PickupRL form full item name: "Pickups.PickupRL". - QString GetFullName() const; - - //! Get only nameof group from prototype. - QString GetGroupName(); - //! Get short name of prototype without group. - QString GetShortName(); - - //! Return Library this item are contained in. - //! Item can only be at one library. - IDataBaseLibrary* GetLibrary() const; - void SetLibrary(CBaseLibrary* pLibrary); - - ////////////////////////////////////////////////////////////////////////// - //! Serialize library item to archive. - virtual void Serialize(SerializeContext& ctx); - - ////////////////////////////////////////////////////////////////////////// - //! Generate new unique id for this item. - void GenerateId(); - //! Returns GUID of this material. - const GUID& GetGUID() const { return m_guid; } - - //! Mark library as modified. - void SetModified(bool bModified = true); - //! Check if library was modified. - bool IsModified() const { return m_bModified; }; - - //! Returns true if the item is registered, otherwise false - bool IsRegistered() const { return m_bRegistered; }; - - //! Validate item for errors. - virtual void Validate() {}; - - //! Get number of sub childs. - virtual int GetChildCount() const { return 0; } - //! Get sub child by index. - virtual CBaseLibraryItem* GetChild([[maybe_unused]] int index) const { return nullptr; } - - - ////////////////////////////////////////////////////////////////////////// - //! Gathers resources by this item. - virtual void GatherUsedResources([[maybe_unused]] CUsedResources& resources) {}; - - //! Get if stored item is enabled - virtual bool GetIsEnabled() { return true; }; - - - int IsParticleItem = -1; -protected: - void SetGUID(REFGUID guid); - friend class CBaseLibrary; - friend class CBaseLibraryManager; - // Name of this prototype. - QString m_name; - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - //! Reference to prototype library who contains this prototype. - _smart_ptr m_library; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - //! Every base library item have unique id. - GUID m_guid; - // True when item modified by editor. - bool m_bModified; - // True when item registered in manager. - bool m_bRegistered = false; -}; - -Q_DECLARE_METATYPE(CBaseLibraryItem*); - -TYPEDEF_AUTOPTR(CBaseLibraryItem); - - -#endif // CRYINCLUDE_EDITOR_BASELIBRARYITEM_H diff --git a/Code/Editor/BaseLibraryManager.cpp b/Code/Editor/BaseLibraryManager.cpp deleted file mode 100644 index 0e51a5238c..0000000000 --- a/Code/Editor/BaseLibraryManager.cpp +++ /dev/null @@ -1,822 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "BaseLibraryManager.h" - -// Editor -#include "BaseLibraryItem.h" -#include "ErrorReport.h" -#include "Undo/IUndoObject.h" - -////////////////////////////////////////////////////////////////////////// -// CBaseLibraryManager implementation. -////////////////////////////////////////////////////////////////////////// -CBaseLibraryManager::CBaseLibraryManager() -{ - m_bUniqNameMap = false; - m_bUniqGuidMap = true; - GetIEditor()->RegisterNotifyListener(this); -} - -////////////////////////////////////////////////////////////////////////// -CBaseLibraryManager::~CBaseLibraryManager() -{ - ClearAll(); - GetIEditor()->UnregisterNotifyListener(this); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::ClearAll() -{ - // Delete all items from all libraries. - for (int i = 0; i < m_libs.size(); i++) - { - m_libs[i]->RemoveAllItems(); - } - - // if we will not copy maps locally then destructors of the elements of - // the map will operate on the already invalid map object - // see: - // CBaseLibraryManager::UnregisterItem() - // CBaseLibraryManager::DeleteItem() - // CMaterial::~CMaterial() - - ItemsGUIDMap itemsGuidMap; - ItemsNameMap itemsNameMap; - - { - AZStd::lock_guard lock(m_itemsNameMapMutex); - std::swap(itemsGuidMap, m_itemsGuidMap); - std::swap(itemsNameMap, m_itemsNameMap); - - m_libs.clear(); - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CBaseLibraryManager::FindLibrary(const QString& library) -{ - const int index = FindLibraryIndex(library); - return index == -1 ? nullptr : m_libs[index]; -} - -////////////////////////////////////////////////////////////////////////// -int CBaseLibraryManager::FindLibraryIndex(const QString& library) -{ - QString lib = library; - lib.replace('\\', '/'); - for (int i = 0; i < m_libs.size(); i++) - { - QString _lib = m_libs[i]->GetFilename(); - _lib.replace('\\', '/'); - if (QString::compare(lib, m_libs[i]->GetName(), Qt::CaseInsensitive) == 0 || QString::compare(lib, _lib, Qt::CaseInsensitive) == 0) - { - return i; - } - } - return -1; -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::FindItem(REFGUID guid) const -{ - CBaseLibraryItem* pMtl = stl::find_in_map(m_itemsGuidMap, guid, nullptr); - return pMtl; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::SplitFullItemName(const QString& fullItemName, QString& libraryName, QString& itemName) -{ - int p; - p = fullItemName.indexOf('.'); - if (p < 0 || !QString::compare(fullItemName.mid(p + 1), "mtl", Qt::CaseInsensitive)) - { - libraryName = ""; - itemName = fullItemName; - return; - } - libraryName = fullItemName.mid(0, p); - itemName = fullItemName.mid(p + 1); -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::FindItemByName(const QString& fullItemName) -{ - AZStd::lock_guard lock(m_itemsNameMapMutex); - return stl::find_in_map(m_itemsNameMap, fullItemName, nullptr); -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::LoadItemByName(const QString& fullItemName) -{ - QString libraryName, itemName; - SplitFullItemName(fullItemName, libraryName, itemName); - - if (!FindLibrary(libraryName)) - { - LoadLibrary(MakeFilename(libraryName)); - } - - return FindItemByName(fullItemName); -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::FindItemByName(const char* fullItemName) -{ - return FindItemByName(QString(fullItemName)); -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::LoadItemByName(const char* fullItemName) -{ - return LoadItemByName(QString(fullItemName)); -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::CreateItem(IDataBaseLibrary* pLibrary) -{ - assert(pLibrary); - - // Add item to this library. - TSmartPtr pItem = MakeNewItem(); - pLibrary->AddItem(pItem); - return pItem; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::DeleteItem(IDataBaseItem* pItem) -{ - assert(pItem); - - UnregisterItem((CBaseLibraryItem*)pItem); - if (pItem->GetLibrary()) - { - pItem->GetLibrary()->RemoveItem(pItem); - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CBaseLibraryManager::LoadLibrary(const QString& inFilename, [[maybe_unused]] bool bReload) -{ - if (auto lib = FindLibrary(inFilename)) - { - return lib; - } - - TSmartPtr pLib = MakeNewLibrary(); - if (!pLib->Load(MakeFilename(inFilename))) - { - Error(QObject::tr("Failed to Load Item Library: %1").arg(inFilename).toUtf8().data()); - return nullptr; - } - - m_libs.push_back(pLib); - return pLib; -} - -////////////////////////////////////////////////////////////////////////// -int CBaseLibraryManager::GetModifiedLibraryCount() const -{ - int count = 0; - for (int i = 0; i < m_libs.size(); i++) - { - if (m_libs[i]->IsModified()) - { - count++; - } - } - return count; -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CBaseLibraryManager::AddLibrary(const QString& library, bool bIsLevelLibrary, bool bIsLoading) -{ - // Make a filename from name of library. - QString filename = library; - - if (filename.indexOf(".xml") == -1) // if its already a filename, we don't do anything - { - filename.replace(' ', '_'); - if (!bIsLevelLibrary) - { - filename = MakeFilename(library); - } - else - { - // if its the level library it gets saved in the level and should not be concatenated with any other file name - filename = filename + ".xml"; - } - } - - IDataBaseLibrary* pBaseLib = FindLibrary(library); //library name - if (!pBaseLib) - { - pBaseLib = FindLibrary(filename); //library file name - } - if (pBaseLib) - { - return pBaseLib; - } - - CBaseLibrary* lib = MakeNewLibrary(); - lib->SetName(library); - lib->SetLevelLibrary(bIsLevelLibrary); - lib->SetFilename(filename, !bIsLoading); - // set modified to true, so even empty particle libraries get saved - lib->SetModified(true); - - m_libs.push_back(lib); - return lib; -} - -////////////////////////////////////////////////////////////////////////// -QString CBaseLibraryManager::MakeFilename(const QString& library) -{ - QString filename = library; - filename.replace(' ', '_'); - filename.replace(".xml", ""); - - // make it contain the canonical libs path: - Path::ConvertBackSlashToSlash(filename); - - QString LibsPath(GetLibsPath()); - Path::ConvertBackSlashToSlash(LibsPath); - - if (filename.left(LibsPath.length()).compare(LibsPath, Qt::CaseInsensitive) == 0) - { - filename = filename.mid(LibsPath.length()); - } - - return LibsPath + filename + ".xml"; -} - -////////////////////////////////////////////////////////////////////////// -bool CBaseLibraryManager::IsUniqueFilename(const QString& library) -{ - QString resultPath = MakeFilename(library); - CCryFile xmlFile; - // If we can find a file for the path - return !xmlFile.Open(resultPath.toUtf8().data(), "rb"); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::DeleteLibrary(const QString& library, bool forceDeleteLevel) -{ - for (int i = 0; i < m_libs.size(); i++) - { - if (QString::compare(library, m_libs[i]->GetName(), Qt::CaseInsensitive) == 0) - { - CBaseLibrary* pLibrary = m_libs[i]; - // Check if not level library, they cannot be deleted. - if (!pLibrary->IsLevelLibrary() || forceDeleteLevel) - { - for (int j = 0; j < pLibrary->GetItemCount(); j++) - { - UnregisterItem((CBaseLibraryItem*)pLibrary->GetItem(j)); - } - pLibrary->RemoveAllItems(); - - if (pLibrary->IsLevelLibrary()) - { - m_pLevelLibrary = nullptr; - } - m_libs.erase(m_libs.begin() + i); - } - break; - } - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CBaseLibraryManager::GetLibrary(int index) const -{ - assert(index >= 0 && index < m_libs.size()); - return m_libs[index]; -}; - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CBaseLibraryManager::GetLevelLibrary() const -{ - IDataBaseLibrary* pLevelLib = nullptr; - - for (int i = 0; i < GetLibraryCount(); i++) - { - if (GetLibrary(i)->IsLevelLibrary()) - { - pLevelLib = GetLibrary(i); - break; - } - } - - - return pLevelLib; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::SaveAllLibs() -{ - for (int i = 0; i < GetLibraryCount(); i++) - { - // Check if library is modified. - IDataBaseLibrary* pLibrary = GetLibrary(i); - - //Level library is saved when the level is saved - if (pLibrary->IsLevelLibrary()) - { - continue; - } - if (pLibrary->IsModified()) - { - if (pLibrary->Save()) - { - pLibrary->SetModified(false); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::Serialize(XmlNodeRef& node, bool bLoading) -{ - static const char* const LEVEL_LIBRARY_TAG = "LevelLibrary"; - - QString rootNodeName = GetRootNodeName(); - if (bLoading) - { - XmlNodeRef libs = node->findChild(rootNodeName.toUtf8().data()); - if (libs) - { - for (int i = 0; i < libs->getChildCount(); i++) - { - // Load only library name. - XmlNodeRef libNode = libs->getChild(i); - if (strcmp(libNode->getTag(), LEVEL_LIBRARY_TAG) == 0) - { - if (!m_pLevelLibrary) - { - QString libName; - libNode->getAttr("Name", libName); - m_pLevelLibrary = static_cast(AddLibrary(libName, true)); - } - m_pLevelLibrary->Serialize(libNode, bLoading); - } - else - { - QString libName; - if (libNode->getAttr("Name", libName)) - { - // Load this library. - if (!FindLibrary(libName)) - { - LoadLibrary(MakeFilename(libName)); - } - } - } - } - } - } - else - { - // Save all libraries. - XmlNodeRef libs = node->newChild(rootNodeName.toUtf8().data()); - for (int i = 0; i < GetLibraryCount(); i++) - { - IDataBaseLibrary* pLib = GetLibrary(i); - if (pLib->IsLevelLibrary()) - { - // Level libraries are saved in in level. - XmlNodeRef libNode = libs->newChild(LEVEL_LIBRARY_TAG); - pLib->Serialize(libNode, bLoading); - } - else - { - // Save only library name. - XmlNodeRef libNode = libs->newChild("Library"); - libNode->setAttr("Name", pLib->GetName().toUtf8().data()); - } - } - SaveAllLibs(); - } -} - -////////////////////////////////////////////////////////////////////////// -QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QString& libName) -{ - // unlikely we'll ever encounter more than 16 - std::vector possibleDuplicates; - possibleDuplicates.reserve(16); - - // search for strings in the database that might have a similar name (ignore case) - IDataBaseItemEnumerator* pEnum = GetItemEnumerator(); - for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext()) - { - //Check if the item is in the target library first. - IDataBaseLibrary* itemLibrary = pItem->GetLibrary(); - QString itemLibraryName; - if (itemLibrary) - { - itemLibraryName = itemLibrary->GetName(); - } - - // Item is not in the library so there cannot be a naming conflict. - if (!libName.isEmpty() && !itemLibraryName.isEmpty() && itemLibraryName != libName) - { - continue; - } - - const QString& name = pItem->GetName(); - if (name.startsWith(srcName, Qt::CaseInsensitive)) - { - possibleDuplicates.push_back(AZStd::string(name.toUtf8().data())); - } - } - pEnum->Release(); - - if (possibleDuplicates.empty()) - { - return srcName; - } - - std::sort(possibleDuplicates.begin(), possibleDuplicates.end(), [](const AZStd::string& strOne, const AZStd::string& strTwo) - { - // I can assume size sorting since if the length is different, either one of the two strings doesn't - // closely match the string we are trying to duplicate, or it's a bigger number (X1 vs X10) - if (strOne.size() != strTwo.size()) - { - return strOne.size() < strTwo.size(); - } - else - { - return azstricmp(strOne.c_str(), strTwo.c_str()) < 0; - } - } - ); - - int num = 0; - QString returnValue = srcName; - while (num < possibleDuplicates.size() && QString::compare(possibleDuplicates[num].c_str(), returnValue, Qt::CaseInsensitive) == 0) - { - returnValue = QStringLiteral("%1%2%3").arg(srcName).arg("_").arg(num); - ++num; - } - - return returnValue; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::Validate() -{ - IDataBaseItemEnumerator* pEnum = GetItemEnumerator(); - for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext()) - { - pItem->Validate(); - } - pEnum->Release(); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) -{ - assert(pItem); - - bool bNotify = false; - - if (m_bUniqGuidMap) - { - REFGUID oldGuid = pItem->GetGUID(); - if (!GuidUtil::IsEmpty(oldGuid)) - { - m_itemsGuidMap.erase(oldGuid); - } - if (GuidUtil::IsEmpty(newGuid)) - { - return; - } - CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, newGuid, nullptr); - if (!pOldItem) - { - pItem->m_guid = newGuid; - m_itemsGuidMap[newGuid] = pItem; - pItem->m_bRegistered = true; - bNotify = true; - } - else - { - if (pOldItem != pItem) - { - ReportDuplicateItem(pItem, pOldItem); - } - } - } - - if (m_bUniqNameMap) - { - QString fullName = pItem->GetFullName(); - if (!pItem->GetName().isEmpty()) - { - CBaseLibraryItem* pOldItem = static_cast(FindItemByName(fullName)); - if (!pOldItem) - { - AZStd::lock_guard lock(m_itemsNameMapMutex); - m_itemsNameMap[fullName] = pItem; - pItem->m_bRegistered = true; - bNotify = true; - } - else - { - if (pOldItem != pItem) - { - ReportDuplicateItem(pItem, pOldItem); - } - } - } - } - - // Notify listeners. - if (bNotify) - { - NotifyItemEvent(pItem, EDB_ITEM_EVENT_ADD); - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem) -{ - assert(pItem); - - bool bNotify = false; - - if (m_bUniqGuidMap) - { - if (GuidUtil::IsEmpty(pItem->GetGUID())) - { - return; - } - CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, pItem->GetGUID(), nullptr); - if (!pOldItem) - { - m_itemsGuidMap[pItem->GetGUID()] = pItem; - pItem->m_bRegistered = true; - bNotify = true; - } - else - { - if (pOldItem != pItem) - { - ReportDuplicateItem(pItem, pOldItem); - } - } - } - - if (m_bUniqNameMap) - { - QString fullName = pItem->GetFullName(); - if (!fullName.isEmpty()) - { - CBaseLibraryItem* pOldItem = static_cast(FindItemByName(fullName)); - if (!pOldItem) - { - AZStd::lock_guard lock(m_itemsNameMapMutex); - m_itemsNameMap[fullName] = pItem; - pItem->m_bRegistered = true; - bNotify = true; - } - else - { - if (pOldItem != pItem) - { - ReportDuplicateItem(pItem, pOldItem); - } - } - } - } - - // Notify listeners. - if (bNotify) - { - NotifyItemEvent(pItem, EDB_ITEM_EVENT_ADD); - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::SetRegisteredFlag(CBaseLibraryItem* pItem, bool bFlag) -{ - pItem->m_bRegistered = bFlag; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::ReportDuplicateItem(CBaseLibraryItem* pItem, CBaseLibraryItem* pOldItem) -{ - QString sLibName; - if (pOldItem->GetLibrary()) - { - sLibName = pOldItem->GetLibrary()->GetName(); - } - CErrorRecord err; - err.pItem = pItem; - err.error = QStringLiteral("Item %1 with duplicate GUID to loaded item %2 ignored").arg(pItem->GetFullName(), pOldItem->GetFullName()); - GetIEditor()->GetErrorReport()->ReportError(err); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::UnregisterItem(CBaseLibraryItem* pItem) -{ - // Notify listeners. - NotifyItemEvent(pItem, EDB_ITEM_EVENT_DELETE); - - if (!pItem) - { - return; - } - - if (m_bUniqGuidMap) - { - m_itemsGuidMap.erase(pItem->GetGUID()); - } - if (m_bUniqNameMap && !pItem->GetFullName().isEmpty()) - { - AZStd::lock_guard lock(m_itemsNameMapMutex); - auto findIter = m_itemsNameMap.find(pItem->GetFullName()); - if (findIter != m_itemsNameMap.end()) - { - _smart_ptr item = findIter->second; - m_itemsNameMap.erase(findIter); - } - } - - pItem->m_bRegistered = false; -} - -////////////////////////////////////////////////////////////////////////// -QString CBaseLibraryManager::MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) -{ - assert(pLibrary); - QString name = pLibrary->GetName() + "."; - if (!group.isEmpty()) - { - name += group + "."; - } - name += itemName; - return name; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::GatherUsedResources(CUsedResources& resources) -{ - IDataBaseItemEnumerator* pEnum = GetItemEnumerator(); - for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext()) - { - pItem->GatherUsedResources(resources); - } - pEnum->Release(); -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItemEnumerator* CBaseLibraryManager::GetItemEnumerator() -{ - if (m_bUniqNameMap) - { - return new CDataBaseItemEnumerator(&m_itemsNameMap); - } - else - { - return new CDataBaseItemEnumerator(&m_itemsGuidMap); - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnBeginNewScene: - SetSelectedItem(nullptr); - ClearAll(); - break; - case eNotify_OnBeginSceneOpen: - SetSelectedItem(nullptr); - ClearAll(); - break; - case eNotify_OnCloseScene: - SetSelectedItem(nullptr); - ClearAll(); - break; - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName) -{ - m_itemsNameMapMutex.lock(); - if (!oldName.isEmpty()) - { - m_itemsNameMap.erase(oldName); - } - if (!pItem->GetFullName().isEmpty()) - { - m_itemsNameMap[pItem->GetFullName()] = pItem; - } - m_itemsNameMapMutex.unlock(); - - OnItemChanged(pItem); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::AddListener(IDataBaseManagerListener* pListener) -{ - stl::push_back_unique(m_listeners, pListener); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::RemoveListener(IDataBaseManagerListener* pListener) -{ - stl::find_and_erase(m_listeners, pListener); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::NotifyItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event) -{ - // Notify listeners. - if (!m_listeners.empty()) - { - for (int i = 0; i < m_listeners.size(); i++) - { - m_listeners[i]->OnDataBaseItemEvent(pItem, event); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::OnItemChanged(IDataBaseItem* pItem) -{ - NotifyItemEvent(pItem, EDB_ITEM_EVENT_CHANGED); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh) -{ - NotifyItemEvent(pItem, bRefresh ? EDB_ITEM_EVENT_UPDATE_PROPERTIES - : EDB_ITEM_EVENT_UPDATE_PROPERTIES_NO_EDITOR_REFRESH); -} - -////////////////////////////////////////////////////////////////////////// -void CBaseLibraryManager::SetSelectedItem(IDataBaseItem* pItem) -{ - if (m_pSelectedItem == pItem) - { - return; - } - m_pSelectedItem = (CBaseLibraryItem*)pItem; - NotifyItemEvent(m_pSelectedItem, EDB_ITEM_EVENT_SELECTED); -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::GetSelectedItem() const -{ - return m_pSelectedItem; -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CBaseLibraryManager::GetSelectedParentItem() const -{ - return m_pSelectedParent; -} - -void CBaseLibraryManager::ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation) -{ - if (!lib || newLocation >= m_libs.size() || lib == m_libs[newLocation]) - { - return; - } - - for (int i = 0; i < m_libs.size(); i++) - { - if (lib == m_libs[i]) - { - _smart_ptr curLib = m_libs[i]; - m_libs.erase(m_libs.begin() + i); - m_libs.insert(m_libs.begin() + newLocation, curLib); - return; - } - } -} - -bool CBaseLibraryManager::SetLibraryName(CBaseLibrary* lib, const QString& name) -{ - // SetFilename will validate if the name is duplicate with exist libraries. - if (lib->SetFilename(MakeFilename(name))) - { - lib->SetName(name); - return true; - } - return false; -} diff --git a/Code/Editor/BaseLibraryManager.h b/Code/Editor/BaseLibraryManager.h deleted file mode 100644 index 118c7ef1f0..0000000000 --- a/Code/Editor/BaseLibraryManager.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 - * - */ - - - -#ifndef CRYINCLUDE_EDITOR_BASELIBRARYMANAGER_H -#define CRYINCLUDE_EDITOR_BASELIBRARYMANAGER_H -#pragma once - -#include "Include/IBaseLibraryManager.h" -#include "Include/IDataBaseItem.h" -#include "Include/IDataBaseLibrary.h" -#include "Include/IDataBaseManager.h" -#include "Util/TRefCountBase.h" -#include "Util/GuidUtil.h" -#include "BaseLibrary.h" -#include "Util/smartptr.h" -#include -#include - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -/** Manages all Libraries and Items. -*/ -class SANDBOX_API CBaseLibraryManager - : public IBaseLibraryManager -{ -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - CBaseLibraryManager(); - ~CBaseLibraryManager(); - - //! Clear all libraries. - void ClearAll() override; - - ////////////////////////////////////////////////////////////////////////// - // IDocListener implementation. - ////////////////////////////////////////////////////////////////////////// - void OnEditorNotifyEvent(EEditorNotifyEvent event) override; - - ////////////////////////////////////////////////////////////////////////// - // Library items. - ////////////////////////////////////////////////////////////////////////// - //! Make a new item in specified library. - IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) override; - //! Delete item from library and manager. - void DeleteItem(IDataBaseItem* pItem) override; - - //! Find Item by its GUID. - IDataBaseItem* FindItem(REFGUID guid) const override; - IDataBaseItem* FindItemByName(const QString& fullItemName) override; - IDataBaseItem* LoadItemByName(const QString& fullItemName) override; - virtual IDataBaseItem* FindItemByName(const char* fullItemName); - virtual IDataBaseItem* LoadItemByName(const char* fullItemName); - - IDataBaseItemEnumerator* GetItemEnumerator() override; - - ////////////////////////////////////////////////////////////////////////// - // Set item currently selected. - void SetSelectedItem(IDataBaseItem* pItem) override; - // Get currently selected item. - IDataBaseItem* GetSelectedItem() const override; - IDataBaseItem* GetSelectedParentItem() const override; - - ////////////////////////////////////////////////////////////////////////// - // Libraries. - ////////////////////////////////////////////////////////////////////////// - //! Add Item library. - IDataBaseLibrary* AddLibrary(const QString& library, bool bIsLevelLibrary = false, bool bIsLoading = true) override; - void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) override; - //! Get number of libraries. - int GetLibraryCount() const override { return static_cast(m_libs.size()); }; - //! Get number of modified libraries. - int GetModifiedLibraryCount() const override; - - //! Get Item library by index. - IDataBaseLibrary* GetLibrary(int index) const override; - - //! Get Level Item library. - IDataBaseLibrary* GetLevelLibrary() const override; - - //! Find Items Library by name. - IDataBaseLibrary* FindLibrary(const QString& library) override; - - //! Find Items Library's index by name. - int FindLibraryIndex(const QString& library) override; - - //! Load Items library. - IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) override; - - //! Save all modified libraries. - void SaveAllLibs() override; - - //! Serialize property manager. - void Serialize(XmlNodeRef& node, bool bLoading) override; - - //! Export items to game. - void Export([[maybe_unused]] XmlNodeRef& node) override {}; - - //! Returns unique name base on input name. - QString MakeUniqueItemName(const QString& name, const QString& libName = "") override; - QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) override; - - //! Root node where this library will be saved. - QString GetRootNodeName() override = 0; - //! Path to libraries in this manager. - QString GetLibsPath() override = 0; - - ////////////////////////////////////////////////////////////////////////// - //! Validate library items for errors. - void Validate() override; - - ////////////////////////////////////////////////////////////////////////// - void GatherUsedResources(CUsedResources& resources) override; - - void AddListener(IDataBaseManagerListener* pListener) override; - void RemoveListener(IDataBaseManagerListener* pListener) override; - - ////////////////////////////////////////////////////////////////////////// - void RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) override; - void RegisterItem(CBaseLibraryItem* pItem) override; - void UnregisterItem(CBaseLibraryItem* pItem) override; - - // Only Used internally. - void OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName) override; - - // Called by items to indicated that they have been modified. - // Sends item changed event to listeners. - void OnItemChanged(IDataBaseItem* pItem) override; - void OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh) override; - - QString MakeFilename(const QString& library); - bool IsUniqueFilename(const QString& library) override; - - //CONFETTI BEGIN - // Used to change the library item order - void ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation) override; - - bool SetLibraryName(CBaseLibrary* lib, const QString& name) override; - -protected: - void SplitFullItemName(const QString& fullItemName, QString& libraryName, QString& itemName); - void NotifyItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event); - void SetRegisteredFlag(CBaseLibraryItem* pItem, bool bFlag); - - ////////////////////////////////////////////////////////////////////////// - // Must be overriden. - //! Makes a new Item. - virtual CBaseLibraryItem* MakeNewItem() = 0; - virtual CBaseLibrary* MakeNewLibrary() = 0; - ////////////////////////////////////////////////////////////////////////// - - virtual void ReportDuplicateItem(CBaseLibraryItem* pItem, CBaseLibraryItem* pOldItem); - -protected: - bool m_bUniqGuidMap; - bool m_bUniqNameMap; - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - //! Array of all loaded entity items libraries. - std::vector<_smart_ptr > m_libs; - - // There is always one current level library. - TSmartPtr m_pLevelLibrary; - - // GUID to item map. - typedef std::map, guid_less_predicate> ItemsGUIDMap; - ItemsGUIDMap m_itemsGuidMap; - - // Case insensitive name to items map. - typedef std::map, stl::less_stricmp> ItemsNameMap; - ItemsNameMap m_itemsNameMap; - AZStd::mutex m_itemsNameMapMutex; - - std::vector m_listeners; - - // Currently selected item. - _smart_ptr m_pSelectedItem; - _smart_ptr m_pSelectedParent; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -////////////////////////////////////////////////////////////////////////// -template -class CDataBaseItemEnumerator - : public IDataBaseItemEnumerator -{ - TMap* m_pMap; - typename TMap::iterator m_iterator; - -public: - CDataBaseItemEnumerator(TMap* pMap) - { - assert(pMap); - m_pMap = pMap; - m_iterator = m_pMap->begin(); - } - void Release() override { delete this; }; - IDataBaseItem* GetFirst() override - { - m_iterator = m_pMap->begin(); - if (m_iterator == m_pMap->end()) - { - return 0; - } - return m_iterator->second; - } - IDataBaseItem* GetNext() override - { - if (m_iterator != m_pMap->end()) - { - m_iterator++; - } - if (m_iterator == m_pMap->end()) - { - return 0; - } - return m_iterator->second; - } -}; - -#endif // CRYINCLUDE_EDITOR_BASELIBRARYMANAGER_H diff --git a/Code/Editor/Controls/ConsoleSCBMFC.h b/Code/Editor/Controls/ConsoleSCBMFC.h deleted file mode 100644 index fcf7f71df7..0000000000 --- a/Code/Editor/Controls/ConsoleSCBMFC.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_CONSOLESCBMFC_H -#define CRYINCLUDE_EDITOR_CONTROLS_CONSOLESCBMFC_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include -#include - -#include "ConsoleSCB.h" -#endif - -class QMenu; -class ConsoleWidget; -class QFocusEvent; - -namespace Ui { - class ConsoleMFC; -} - -namespace MFC -{ - -struct ConsoleLine -{ - QString text; - bool newLine; -}; -typedef std::deque Lines; - -class ConsoleLineEdit - : public QLineEdit -{ - Q_OBJECT -public: - explicit ConsoleLineEdit(QWidget* parent = nullptr); - -protected: - void mousePressEvent(QMouseEvent* ev) override; - void mouseDoubleClickEvent(QMouseEvent* ev) override; - void keyPressEvent(QKeyEvent* ev) override; - bool event(QEvent* ev) override; - -signals: - void variableEditorRequested(); - void setWindowTitle(const QString&); - -private: - void DisplayHistory(bool bForward); - QStringList m_history; - unsigned int m_historyIndex; - bool m_bReusedHistory; -}; - -class ConsoleTextEdit - : public QTextEdit -{ - Q_OBJECT -public: - explicit ConsoleTextEdit(QWidget* parent = nullptr); -}; - -class CConsoleSCB - : public QWidget -{ - Q_OBJECT -public: - explicit CConsoleSCB(QWidget* parent = nullptr); - ~CConsoleSCB(); - - static void RegisterViewClass(); - void SetInputFocus(); - void AddToConsole(const QString& text, bool bNewLine); - void FlushText(); - void showPopupAndSetTitle(); - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - static CConsoleSCB* GetCreatedInstance(); - - static void AddToPendingLines(const QString& text, bool bNewLine); // call this function instead of AddToConsole() until an instance of CConsoleSCB exists to prevent messages from getting lost - -public Q_SLOTS: - void OnStyleSettingsChanged(); - -private Q_SLOTS: - void showVariableEditor(); - -private: - QScopedPointer ui; - int m_richEditTextLength; - - Lines m_lines; - static Lines s_pendingLines; - - QList m_colorTable; - SEditorSettings::ConsoleColorTheme m_backgroundTheme; -}; - -} // namespace MFC - -#endif // CRYINCLUDE_EDITOR_CONTROLS_CONSOLESCB_H - diff --git a/Code/Editor/Controls/ConsoleSCBMFC.ui b/Code/Editor/Controls/ConsoleSCBMFC.ui deleted file mode 100644 index b9386558ed..0000000000 --- a/Code/Editor/Controls/ConsoleSCBMFC.ui +++ /dev/null @@ -1,132 +0,0 @@ - - - ConsoleMFC - - - - 0 - 0 - 400 - 120 - - - - - 0 - 0 - - - - Console - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - true - - - - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 20 - 0 - - - - - 20 - 30 - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - MFC::ConsoleLineEdit - QLineEdit -
ConsoleSCBMFC.h
-
-
- - - - -
diff --git a/Code/Editor/Controls/HotTrackingTreeCtrl.cpp b/Code/Editor/Controls/HotTrackingTreeCtrl.cpp deleted file mode 100644 index 54152a9fd4..0000000000 --- a/Code/Editor/Controls/HotTrackingTreeCtrl.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "HotTrackingTreeCtrl.h" - -// Qt -#include - - -CHotTrackingTreeCtrl::CHotTrackingTreeCtrl(QWidget* parent) - : QTreeWidget(parent) -{ - setMouseTracking(true); - m_hHoverItem = nullptr; -} - -void CHotTrackingTreeCtrl::mouseMoveEvent(QMouseEvent* event) -{ - QTreeWidgetItem* hItem = itemAt(event->pos()); - - if (m_hHoverItem != nullptr) - { - QFont font = m_hHoverItem->font(0); - font.setBold(false); - m_hHoverItem->setFont(0, font); - m_hHoverItem = nullptr; - } - - if (hItem != nullptr) - { - QFont font = hItem->font(0); - font.setBold(true); - hItem->setFont(0, font); - m_hHoverItem = hItem; - } - - QTreeWidget::mouseMoveEvent(event); -} - -#include diff --git a/Code/Editor/Controls/HotTrackingTreeCtrl.h b/Code/Editor/Controls/HotTrackingTreeCtrl.h deleted file mode 100644 index 2ca7e11a91..0000000000 --- a/Code/Editor/Controls/HotTrackingTreeCtrl.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_HOTTRACKINGTREECTRL_H -#define CRYINCLUDE_EDITOR_CONTROLS_HOTTRACKINGTREECTRL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#endif - -class CHotTrackingTreeCtrl - : public QTreeWidget -{ - Q_OBJECT - -public: - CHotTrackingTreeCtrl(QWidget* parent = 0); - virtual ~CHotTrackingTreeCtrl(){}; - -protected: - void mouseMoveEvent(QMouseEvent* event) override; - -private: - QTreeWidgetItem* m_hHoverItem; -}; -#endif // CRYINCLUDE_EDITOR_CONTROLS_HOTTRACKINGTREECTRL_H diff --git a/Code/Editor/Controls/ImageListCtrl.cpp b/Code/Editor/Controls/ImageListCtrl.cpp deleted file mode 100644 index 9c8451c2e9..0000000000 --- a/Code/Editor/Controls/ImageListCtrl.cpp +++ /dev/null @@ -1,567 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "ImageListCtrl.h" - -// Qt -#include -#include - -////////////////////////////////////////////////////////////////////////// -CImageListCtrl::CImageListCtrl(QWidget* parent) - : QAbstractItemView(parent) - , m_itemSize(60, 60) - , m_borderSize(4, 4) - , m_style(DefaultStyle) -{ - setItemDelegate(new QImageListDelegate(this)); - setAutoFillBackground(false); - - QPalette p = palette(); - p.setColor(QPalette::Highlight, QColor(255, 55, 50)); - setPalette(p); - - horizontalScrollBar()->setRange(0, 0); - verticalScrollBar()->setRange(0, 0); -} - -////////////////////////////////////////////////////////////////////////// -CImageListCtrl::~CImageListCtrl() -{ -} - -////////////////////////////////////////////////////////////////////////// -CImageListCtrl::ListStyle CImageListCtrl::Style() const -{ - return m_style; -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::SetStyle(ListStyle style) -{ - m_style = style; - scheduleDelayedItemsLayout(); -} - -////////////////////////////////////////////////////////////////////////// -const QSize& CImageListCtrl::ItemSize() const -{ - return m_itemSize; -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::SetItemSize(QSize size) -{ - Q_ASSERT(size.isValid()); - m_itemSize = size; - scheduleDelayedItemsLayout(); -} - -////////////////////////////////////////////////////////////////////////// -const QSize& CImageListCtrl::BorderSize() const -{ - return m_borderSize; -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::SetBorderSize(QSize size) -{ - Q_ASSERT(size.isValid()); - m_borderSize = size; - scheduleDelayedItemsLayout(); -} - -////////////////////////////////////////////////////////////////////////// -QModelIndexList CImageListCtrl::ItemsInRect(const QRect& rect) const -{ - QModelIndexList list; - - if (!model()) - { - return list; - } - - QHash::const_iterator i; - QHash::const_iterator c = m_geometry.cend(); - for (i = m_geometry.cbegin(); i != c; ++i) - { - if (i.value().intersects(rect)) - { - list << model()->index(i.key(), 0, rootIndex()); - } - } - - return list; -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::paintEvent(QPaintEvent* event) -{ - QAbstractItemView::paintEvent(event); - - if (!model()) - { - return; - } - - const int rowCount = model()->rowCount(); - - if (m_geometry.isEmpty() && rowCount) - { - updateGeometries(); - } - - QPainter painter(viewport()); - painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); - painter.setBackground(palette().window()); - painter.setFont(font()); - - QStyleOptionViewItem option; - option.palette = palette(); - option.font = font(); - option.fontMetrics = fontMetrics(); - option.decorationAlignment = Qt::AlignCenter; - - const QRect visibleRect(QPoint(horizontalOffset(), verticalOffset()), viewport()->contentsRect().size()); - - painter.translate(-horizontalOffset(), -verticalOffset()); - - for (int r = 0; r < rowCount; ++r) - { - const QModelIndex& index = model()->index(r, 0, rootIndex()); - - option.rect = m_geometry.value(r); - if (!option.rect.intersects(visibleRect)) - { - continue; - } - - option.state = QStyle::State_None; - - if (selectionModel()->isSelected(index)) - { - option.state |= QStyle::State_Selected; - } - - if (currentIndex() == index) - { - option.state |= QStyle::State_HasFocus; - } - - QAbstractItemDelegate* idt = itemDelegate(index); - idt->paint(&painter, option, index); - } -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::rowsInserted(const QModelIndex& parent, int start, int end) -{ - QAbstractItemView::rowsInserted(parent, start, end); - - if (isVisible()) - { - scheduleDelayedItemsLayout(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::updateGeometries() -{ - ClearItemGeometries(); - - if (!model()) - { - return; - } - - const int rowCount = model()->rowCount(); - - const int nPageHorz = viewport()->width(); - const int nPageVert = viewport()->height(); - - if (nPageHorz == 0 || nPageVert == 0 || rowCount <= 0) - { - return; - } - - int x = m_borderSize.width(); - int y = m_borderSize.height(); - - const int nItemWidth = m_itemSize.width() + m_borderSize.width(); - - if (m_style == HorizontalStyle) - { - for (int row = 0; row < rowCount; ++row) - { - m_geometry.insert(row, QRect(QPoint(x, y), m_itemSize)); - x += nItemWidth; - } - - horizontalScrollBar()->setPageStep(viewport()->width()); - horizontalScrollBar()->setRange(0, x - viewport()->width()); - } - else - { - const int nTextHeight = fontMetrics().height(); - const int nItemHeight = m_itemSize.height() + m_borderSize.height() + nTextHeight; - - int nNumOfHorzItems = nPageHorz / nItemWidth; - if (nNumOfHorzItems <= 0) - { - nNumOfHorzItems = 1; - } - - for (int row = 0; row < rowCount; ++row) - { - m_geometry.insert(row, QRect(QPoint(x, y), m_itemSize)); - - if ((row + 1) % nNumOfHorzItems == 0) - { - y += nItemHeight; - x = m_borderSize.width(); - } - else - { - x += nItemWidth; - } - } - - verticalScrollBar()->setPageStep(viewport()->height()); - verticalScrollBar()->setRange(0, (y + nItemHeight) - viewport()->height()); - } -} - -////////////////////////////////////////////////////////////////////////// -QModelIndex CImageListCtrl::indexAt(const QPoint& point) const -{ - if (!model()) - { - return QModelIndex(); - } - - const QPoint p = point + - QPoint(horizontalOffset(), verticalOffset()); - - QHash::const_iterator i; - QHash::const_iterator c = m_geometry.cend(); - for (i = m_geometry.cbegin(); i != c; ++i) - { - if (i.value().contains(p)) - { - return model()->index(i.key(), 0, rootIndex()); - } - } - - return QModelIndex(); -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::scrollTo(const QModelIndex& index, ScrollHint hint) -{ - if (!index.isValid()) - { - return; - } - - QRect rect = m_geometry.value(index.row()); - - switch (hint) - { - case EnsureVisible: - if (horizontalOffset() > rect.right()) - { - horizontalScrollBar()->setValue(rect.left()); - } - else if ((horizontalOffset() + viewport()->width()) < rect.left()) - { - horizontalScrollBar()->setValue(rect.right() - viewport()->width()); - } - - if (verticalOffset() > rect.bottom()) - { - verticalScrollBar()->setValue(rect.top()); - } - else if ((verticalOffset() + viewport()->height()) < rect.top()) - { - verticalScrollBar()->setValue(rect.bottom() - viewport()->height()); - } - break; - - case PositionAtTop: - horizontalScrollBar()->setValue(rect.left()); - verticalScrollBar()->setValue(rect.top()); - break; - - case PositionAtBottom: - horizontalScrollBar()->setValue(rect.right() - viewport()->width()); - verticalScrollBar()->setValue(rect.bottom() - viewport()->height()); - break; - - case PositionAtCenter: - horizontalScrollBar()->setValue(rect.center().x() - (viewport()->width() / 2)); - verticalScrollBar()->setValue(rect.center().y() - (viewport()->height() / 2)); - break; - } -} - -////////////////////////////////////////////////////////////////////////// -QRect CImageListCtrl::visualRect(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return QRect(); - } - - - if (!m_geometry.contains(index.row())) - { - return QRect(); - } - - return m_geometry.value(index.row()) - .translated(-horizontalOffset(), -verticalOffset()); -} - -////////////////////////////////////////////////////////////////////////// -QRect CImageListCtrl::ItemGeometry(const QModelIndex& index) const -{ - Q_ASSERT(index.model() == model()); - Q_ASSERT(m_geometry.contains(index.row())); - - return m_geometry.value(index.row()); -} - -void CImageListCtrl::SetItemGeometry(const QModelIndex& index, const QRect& rect) -{ - Q_ASSERT(index.model() == model()); - m_geometry.insert(index.row(), rect); - update(rect); -} - -void CImageListCtrl::ClearItemGeometries() -{ - m_geometry.clear(); -} - -////////////////////////////////////////////////////////////////////////// -int CImageListCtrl::horizontalOffset() const -{ - return horizontalScrollBar()->value(); -} - -////////////////////////////////////////////////////////////////////////// -int CImageListCtrl::verticalOffset() const -{ - return verticalScrollBar()->value(); -} - -////////////////////////////////////////////////////////////////////////// -bool CImageListCtrl::isIndexHidden([[maybe_unused]] const QModelIndex& index) const -{ - return false; /* not supported */ -} - -////////////////////////////////////////////////////////////////////////// -QModelIndex CImageListCtrl::moveCursor(CursorAction cursorAction, [[maybe_unused]] Qt::KeyboardModifiers modifiers) -{ - if (!model()) - { - return QModelIndex(); - } - - const int rowCount = model()->rowCount(); - - if (0 == rowCount) - { - return QModelIndex(); - } - - switch (cursorAction) - { - case MoveHome: - return model()->index(0, 0, rootIndex()); - - case MoveEnd: - return model()->index(rowCount - 1, 0, rootIndex()); - - case MovePrevious: - { - QModelIndex current = currentIndex(); - if (current.isValid()) - { - return model()->index((current.row() - 1) % rowCount, 0, rootIndex()); - } - } break; - - case MoveNext: - { - QModelIndex current = currentIndex(); - if (current.isValid()) - { - return model()->index((current.row() + 1) % rowCount, 0, rootIndex()); - } - } break; - - case MoveUp: - case MoveDown: - case MoveLeft: - case MoveRight: - case MovePageUp: - case MovePageDown: - /* TODO */ - break; - } - return QModelIndex(); -} - -////////////////////////////////////////////////////////////////////////// -void CImageListCtrl::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags) -{ - if (!model()) - { - return; - } - - const QRect lrect = - rect.translated(horizontalOffset(), verticalOffset()); - - QHash::const_iterator i; - QHash::const_iterator c = m_geometry.cend(); - for (i = m_geometry.cbegin(); i != c; ++i) - { - if (i.value().intersects(lrect)) - { - selectionModel()->select(model()->index(i.key(), 0, rootIndex()), flags); - } - } -} - -////////////////////////////////////////////////////////////////////////// -QRegion CImageListCtrl::visualRegionForSelection(const QItemSelection& selection) const -{ - QRegion region; - - foreach(const QModelIndex &index, selection.indexes()) - { - region += visualRect(index); - } - - return region; -} - -////////////////////////////////////////////////////////////////////////// -QImageListDelegate::QImageListDelegate(QObject* parent) - : QAbstractItemDelegate(parent) -{ -} - -////////////////////////////////////////////////////////////////////////// -void QImageListDelegate::paint(QPainter* painter, - const QStyleOptionViewItem& option, const QModelIndex& index) const -{ - painter->save(); - - painter->setFont(option.font); - - if (option.rect.isValid()) - { - painter->setClipRect(option.rect); - } - - QRect innerRect = option.rect.adjusted(1, 1, -1, -1); - - QRect textRect(innerRect.left(), innerRect.bottom() - option.fontMetrics.height(), - innerRect.width(), option.fontMetrics.height() + 1); - - /* fill item background */ - - painter->fillRect(option.rect, option.palette.color(QPalette::Base)); - - /* draw image */ - - if (index.data(Qt::DecorationRole).isValid()) - { - const QPixmap& p = index.data(Qt::DecorationRole).value(); - if (p.isNull() || p.size() == QSize(1, 1)) - { - emit InvalidPixmapGenerated(index); - } - else - { - painter->drawPixmap(innerRect, p); - } - } - - /* draw text */ - - const QColor trColor = option.palette.color(QPalette::Shadow); - painter->fillRect(textRect, (option.state & QStyle::State_Selected) ? - trColor.lighter() : trColor); - - if (option.state & QStyle::State_Selected) - { - painter->setPen(QPen(option.palette.color(QPalette::HighlightedText))); - - QFont f = painter->font(); - f.setBold(true); - painter->setFont(f); - } - else - { - painter->setPen(QPen(option.palette.color(QPalette::Text))); - } - - painter->drawText(textRect, index.data(Qt::DisplayRole).toString(), - QTextOption(option.decorationAlignment)); - - painter->setPen(QPen(option.palette.color(QPalette::Shadow))); - painter->drawRect(textRect); - - /* draw border */ - - if (option.state & QStyle::State_Selected) - { - QPen pen(option.palette.color(QPalette::Highlight)); - pen.setWidth(2); - painter->setPen(pen); - painter->drawRect(innerRect); - } - else - { - painter->setPen(QPen(option.palette.color(QPalette::Shadow))); - painter->drawRect(option.rect); - } - - if (option.state & QStyle::State_HasFocus) - { - QPen pen(Qt::DotLine); - pen.setColor(option.palette.color(QPalette::AlternateBase)); - painter->setPen(pen); - painter->drawRect(option.rect); - } - - painter->restore(); -} - -////////////////////////////////////////////////////////////////////////// -QSize QImageListDelegate::sizeHint(const QStyleOptionViewItem& option, - [[maybe_unused]] const QModelIndex& index) const -{ - return option.rect.size(); -} - -////////////////////////////////////////////////////////////////////////// -QVector QImageListDelegate::paintingRoles() const -{ - return QVector() << Qt::DecorationRole << Qt::DisplayRole; -} - -#include diff --git a/Code/Editor/Controls/ImageListCtrl.h b/Code/Editor/Controls/ImageListCtrl.h deleted file mode 100644 index db393c8497..0000000000 --- a/Code/Editor/Controls/ImageListCtrl.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_IMAGELISTCTRL_H -#define CRYINCLUDE_EDITOR_CONTROLS_IMAGELISTCTRL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include - -#include -#endif - -////////////////////////////////////////////////////////////////////////// -// Custom control to display list of images. -////////////////////////////////////////////////////////////////////////// -class CImageListCtrl - : public QAbstractItemView -{ - Q_OBJECT -public: - enum ListStyle - { - DefaultStyle, - HorizontalStyle - }; - -public: - CImageListCtrl(QWidget* parent = nullptr); - ~CImageListCtrl(); - - ListStyle Style() const; - void SetStyle(ListStyle style); - - const QSize& ItemSize() const; - void SetItemSize(QSize size); - - const QSize& BorderSize() const; - void SetBorderSize(QSize size); - - // Get all items inside specified rectangle. - QModelIndexList ItemsInRect(const QRect& rect) const; - - QModelIndex indexAt(const QPoint& point) const override; - void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible) override; - QRect visualRect(const QModelIndex& index) const override; - -protected: - QRect ItemGeometry(const QModelIndex& index) const; - void SetItemGeometry(const QModelIndex& index, const QRect& rect); - void ClearItemGeometries(); - - int horizontalOffset() const override; - int verticalOffset() const override; - bool isIndexHidden(const QModelIndex& index) const override; - QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override; - void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags) override; - QRegion visualRegionForSelection(const QItemSelection& selection) const override; - - void paintEvent(QPaintEvent* event) override; - void rowsInserted(const QModelIndex& parent, int start, int end) override; - - void updateGeometries() override; - -private: - QHash m_geometry; - QSize m_itemSize; - QSize m_borderSize; - ListStyle m_style; -}; - -class QImageListDelegate - : public QAbstractItemDelegate -{ - Q_OBJECT -signals: - void InvalidPixmapGenerated(const QModelIndex& index) const; -public: - QImageListDelegate(QObject* parent = nullptr); - - void paint(QPainter* painter, - const QStyleOptionViewItem& option, - const QModelIndex& index) const override; - - QSize sizeHint(const QStyleOptionViewItem& option, - const QModelIndex& index) const override; - - QVector paintingRoles() const override; -}; - -#endif // CRYINCLUDE_EDITOR_CONTROLS_IMAGELISTCTRL_H diff --git a/Code/Editor/Controls/MultiMonHelper.cpp b/Code/Editor/Controls/MultiMonHelper.cpp deleted file mode 100644 index 5b3ed3a204..0000000000 --- a/Code/Editor/Controls/MultiMonHelper.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "MultiMonHelper.h" - -// Qt -#include - -//////////////////////////////////////////////////////////////////////////// -void ClipOrCenterRectToMonitor(QRect *prc, const UINT flags) -{ - const QScreen* currentScreen = nullptr; - QRect rc; - - Q_ASSERT(prc); - - const auto screens = qApp->screens(); - for (auto screen : screens) - { - if (screen->geometry().contains(prc->center())) - { - currentScreen = screen; - break; - } - } - - if (!currentScreen) - { - return; - } - - const int w = prc->width(); - const int h = prc->height(); - - if (flags & MONITOR_WORKAREA) - { - rc = currentScreen->availableGeometry(); - } - else - { - rc = currentScreen->geometry(); - } - - // center or clip the passed rect to the monitor rect - if (flags & MONITOR_CENTER) - { - prc->setLeft(rc.left() + (rc.right() - rc.left() - w) / 2); - prc->setTop(rc.top() + (rc.bottom() - rc.top() - h) / 2); - prc->setRight(prc->left() + w); - prc->setBottom(prc->top() + h); - } - else - { - prc->setLeft(qMax(rc.left(), qMin(rc.right() - w, prc->left()))); - prc->setTop(qMax(rc.top(), qMin(rc.bottom() - h, prc->top()))); - prc->setRight(prc->left() + w); - prc->setBottom(prc->top() + h); - } -} diff --git a/Code/Editor/Controls/MultiMonHelper.h b/Code/Editor/Controls/MultiMonHelper.h deleted file mode 100644 index 54e47bf022..0000000000 --- a/Code/Editor/Controls/MultiMonHelper.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_MULTIMONHELPER_H -#define CRYINCLUDE_EDITOR_CONTROLS_MULTIMONHELPER_H -#pragma once - -// Taken from: http://msdn.microsoft.com/en-us/library/dd162826(v=vs.85).aspx -#define MONITOR_CENTER 0x0001 // center rect to monitor -#define MONITOR_CLIP 0x0000 // clip rect to monitor -#define MONITOR_WORKAREA 0x0002 // use monitor work area -#define MONITOR_AREA 0x0000 // use monitor entire area - -// -// ClipOrCenterRectToMonitor -// -// The most common problem apps have when running on a -// multimonitor system is that they "clip" or "pin" windows -// based on the SM_CXSCREEN and SM_CYSCREEN system metrics. -// Because of app compatibility reasons these system metrics -// return the size of the primary monitor. -// -// This shows how you use the multi-monitor functions -// to do the same thing. -// -// params: -// prc : pointer to QRect to modify -// flags : some combination of the MONITOR_* flags above -// -// example: -// -// ClipOrCenterRectToMonitor(&aRect, MONITOR_CLIP | MONITOR_WORKAREA); -// -// Takes parameter pointer to RECT "aRect" and flags MONITOR_CLIP | MONITOR_WORKAREA -// This will modify aRect without resizing it so that it remains within the on-screen boundaries. -void ClipOrCenterRectToMonitor(QRect *prc, const UINT flags); - -#endif // CRYINCLUDE_EDITOR_CONTROLS_MULTIMONHELPER_H diff --git a/Code/Editor/Controls/NumberCtrl.cpp b/Code/Editor/Controls/NumberCtrl.cpp deleted file mode 100644 index 473dd7e4af..0000000000 --- a/Code/Editor/Controls/NumberCtrl.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "NumberCtrl.h" - - -QNumberCtrl::QNumberCtrl(QWidget* parent) - : QDoubleSpinBox(parent) - , m_bMouseDown(false) - , m_bDragged(false) - , m_bUndoEnabled(false) - , m_prevValue(0) -{ - connect(this, &QAbstractSpinBox::editingFinished, this, &QNumberCtrl::onEditingFinished); -} - -void QNumberCtrl::changeEvent(QEvent* event) -{ - if (event->type() == QEvent::EnabledChange) - { - setButtonSymbols(isEnabled() ? UpDownArrows : NoButtons); - } - - QDoubleSpinBox::changeEvent(event); -} - - -void QNumberCtrl::SetRange(double newMin, double newMax) -{ - // Avoid setting this value if its close to the current value, because otherwise qt will pump events into the queue to redraw/etc. - if ( (!AZ::IsClose(this->minimum(), newMin, DBL_EPSILON)) || (!AZ::IsClose(this->maximum(), newMax, DBL_EPSILON)) ) - { - setRange(newMin, newMax); - } -} - - -void QNumberCtrl::mousePressEvent(QMouseEvent* event) -{ - if (event->button() == Qt::LeftButton) - { - emit mousePressed(); - - m_bMouseDown = true; - m_bDragged = false; - m_mousePos = event->pos(); - - if (m_bUndoEnabled && !CUndo::IsRecording()) - { - GetIEditor()->BeginUndo(); - } - - emit dragStarted(); - - grabMouse(); - } - - QDoubleSpinBox::mousePressEvent(event); -} - -void QNumberCtrl::mouseReleaseEvent(QMouseEvent* event) -{ - QDoubleSpinBox::mouseReleaseEvent(event); - - if (event->button() == Qt::LeftButton) - { - m_bMouseDown = m_bDragged = false; - - emit valueUpdated(); - emit valueChanged(); - - if (m_bUndoEnabled && CUndo::IsRecording()) - { - GetIEditor()->AcceptUndo(m_undoText); - } - - emit dragFinished(); - - releaseMouse(); - - m_prevValue = value(); - - emit mouseReleased(); - } -} - -void QNumberCtrl::mouseMoveEvent(QMouseEvent* event) -{ - QDoubleSpinBox::mousePressEvent(event); - - if (m_bMouseDown) - { - m_bDragged = true; - - int dy = event->pos().y() - m_mousePos.y(); - setValue(value() - singleStep() * dy); - - emit valueUpdated(); - - m_mousePos = event->pos(); - } -} - -void QNumberCtrl::EnableUndo(const QString& undoText) -{ - m_undoText = undoText; - m_bUndoEnabled = true; -} - -void QNumberCtrl::focusInEvent(QFocusEvent* event) -{ - m_prevValue = value(); - QDoubleSpinBox::focusInEvent(event); -} - -void QNumberCtrl::onEditingFinished() -{ - bool undo = m_bUndoEnabled && !CUndo::IsRecording() && m_prevValue != value(); - if (undo) - { - GetIEditor()->BeginUndo(); - } - - emit valueUpdated(); - emit valueChanged(); - - if (undo) - { - GetIEditor()->AcceptUndo(m_undoText); - } - - m_prevValue = value(); -} - -#include diff --git a/Code/Editor/Controls/NumberCtrl.h b/Code/Editor/Controls/NumberCtrl.h deleted file mode 100644 index 22ee7b867f..0000000000 --- a/Code/Editor/Controls/NumberCtrl.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_NUMBERCTRL_H -#define CRYINCLUDE_EDITOR_CONTROLS_NUMBERCTRL_H -#pragma once - -// NumberCtrl.h : header file -// - -#if !defined(Q_MOC_RUN) -#include -#endif - -class QNumberCtrl - : public QDoubleSpinBox -{ - Q_OBJECT - -public: - QNumberCtrl(QWidget* parent = nullptr); - - bool IsDragging() const { return m_bDragged; } - - //! If called will enable undo with given text when control is modified. - void EnableUndo(const QString& undoText); - void SetRange(double newMin, double maxRange); - -Q_SIGNALS: - void dragStarted(); - void dragFinished(); - - void valueUpdated(); - void valueChanged(); - - void mouseReleased(); - void mousePressed(); - -protected: - void changeEvent(QEvent* event) override; - void focusInEvent(QFocusEvent* event) override; - void mousePressEvent(QMouseEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; - void mouseReleaseEvent(QMouseEvent* event) override; - -private: - void onEditingFinished(); - void onValueChanged(double d); - - bool m_bMouseDown; - bool m_bDragged; - QPoint m_mousePos; - bool m_bUndoEnabled; - double m_prevValue; - QString m_undoText; -}; - -#endif // CRYINCLUDE_EDITOR_CONTROLS_NUMBERCTRL_H diff --git a/Code/Editor/Controls/TextEditorCtrl.cpp b/Code/Editor/Controls/TextEditorCtrl.cpp deleted file mode 100644 index c372138d80..0000000000 --- a/Code/Editor/Controls/TextEditorCtrl.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "TextEditorCtrl.h" - - -// CTextEditorCtrl -CTextEditorCtrl::CTextEditorCtrl(QWidget* pParent) - : QTextEdit(pParent) -{ - m_bModified = true; - - QFont font; - font.setFamily("Courier New"); - font.setFixedPitch(true); - font.setPointSize(10); - setFont(font); - - setLineWrapMode(NoWrap); - - connect(this, &QTextEdit::textChanged, this, &CTextEditorCtrl::OnChange); -} - -CTextEditorCtrl::~CTextEditorCtrl() -{ -} - - -// CTextEditorCtrl message handlers - -void CTextEditorCtrl::LoadFile(const QString& sFileName) -{ - if (m_filename == sFileName) - { - return; - } - - m_filename = sFileName; - - clear(); - - CCryFile file(sFileName.toUtf8().data(), "rb"); - if (file.Open(sFileName.toUtf8().data(), "rb")) - { - size_t length = file.GetLength(); - - QByteArray text; - text.resize(static_cast(length)); - file.ReadRaw(text.data(), length); - - setPlainText(text); - } - - m_bModified = false; -} - -////////////////////////////////////////////////////////////////////////// -void CTextEditorCtrl::SaveFile(const QString& sFileName) -{ - if (sFileName.isEmpty()) - { - return; - } - - if (!CFileUtil::OverwriteFile(sFileName.toUtf8().data())) - { - return; - } - - QFile file(sFileName); - file.open(QFile::WriteOnly); - - file.write(toPlainText().toUtf8()); - - m_bModified = false; -} - -////////////////////////////////////////////////////////////////////////// -void CTextEditorCtrl::OnChange() -{ - - m_bModified = true; -} - -#include diff --git a/Code/Editor/Controls/TextEditorCtrl.h b/Code/Editor/Controls/TextEditorCtrl.h deleted file mode 100644 index e155185f90..0000000000 --- a/Code/Editor/Controls/TextEditorCtrl.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_TEXTEDITORCTRL_H -#define CRYINCLUDE_EDITOR_CONTROLS_TEXTEDITORCTRL_H -#pragma once - -// CTextEditorCtrl -#if !defined(Q_MOC_RUN) -#include -#endif - -class CTextEditorCtrl - : public QTextEdit -{ - Q_OBJECT - -public: - CTextEditorCtrl(QWidget* pParent = nullptr); - virtual ~CTextEditorCtrl(); - - void LoadFile(const QString& sFileName); - void SaveFile(const QString& sFileName); - QString GetFilename() const { return m_filename; } - - bool IsModified() const { return m_bModified; } - - //! Must be called after OnChange message. - void OnChange(); - -protected: - QString m_filename; - bool m_bModified; -}; - -#endif // CRYINCLUDE_EDITOR_CONTROLS_TEXTEDITORCTRL_H diff --git a/Code/Editor/Controls/TreeCtrlUtils.h b/Code/Editor/Controls/TreeCtrlUtils.h deleted file mode 100644 index 7498360d2e..0000000000 --- a/Code/Editor/Controls/TreeCtrlUtils.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_TREECTRLUTILS_H -#define CRYINCLUDE_EDITOR_CONTROLS_TREECTRLUTILS_H -#pragma once - -#include - -namespace TreeCtrlUtils -{ - template - class TreeItemIterator - : public P - { - public: - typedef P Traits; - - //iterator traits, required by STL - typedef ptrdiff_t difference_type; - typedef HTREEITEM value_type; - typedef HTREEITEM* pointer; - typedef HTREEITEM& reference; - typedef std::forward_iterator_tag iterator_category; - - TreeItemIterator() - : pCtrl(0) - , hItem(0) {} - explicit TreeItemIterator(const P& traits) - : P(traits) - , pCtrl(0) - , hItem(0) {} - TreeItemIterator(const TreeItemIterator& other) - : P(other) - , pCtrl(other.pCtrl) - , hItem(other.hItem) {} - TreeItemIterator(CTreeCtrl* pCtrl, HTREEITEM hItem) - : pCtrl(pCtrl) - , hItem(hItem) {} - TreeItemIterator(CTreeCtrl* pCtrl, HTREEITEM hItem, const P& traits) - : P(traits) - , pCtrl(pCtrl) - , hItem(hItem) {} - - HTREEITEM operator*() {return hItem; } - bool operator==(const TreeItemIterator& other) const {return pCtrl == other.pCtrl && hItem == other.hItem; } - bool operator!=(const TreeItemIterator& other) const {return pCtrl != other.pCtrl || hItem != other.hItem; } - - TreeItemIterator& operator++() - { - HTREEITEM hNextItem = 0; - if (RecurseToChildren(hItem)) - { - hNextItem = (pCtrl ? pCtrl->GetChildItem(hItem) : 0); - } - while (pCtrl && hItem && !hNextItem) - { - hNextItem = pCtrl->GetNextSiblingItem(hItem); - if (!hNextItem) - { - hItem = pCtrl->GetParentItem(hItem); - } - } - hItem = hNextItem; - - return *this; - } - - TreeItemIterator operator++(int) {TreeItemIterator old = *this; ++(*this); return old; } - - CTreeCtrl* pCtrl; - HTREEITEM hItem; - }; - - class NonRecursiveTreeItemIteratorTraits - { - public: - bool RecurseToChildren(HTREEITEM hItem) {return false; } - }; - typedef TreeItemIterator NonRecursiveTreeItemIterator; - - class RecursiveTreeItemIteratorTraits - { - public: - bool RecurseToChildren(HTREEITEM hItem) {return true; } - }; - typedef TreeItemIterator RecursiveTreeItemIterator; - - inline RecursiveTreeItemIterator BeginTreeItemsRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - if (hItem == 0) - { - hItem = (pCtrl ? pCtrl->GetRootItem() : 0); - } - return RecursiveTreeItemIterator(pCtrl, hItem); - } - - inline RecursiveTreeItemIterator EndTreeItemsRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - HTREEITEM hEndItem = 0; - HTREEITEM hParent = hItem; - do - { - if (hParent) - { - hEndItem = pCtrl->GetNextSiblingItem(hParent); - } - hParent = (pCtrl && hParent ? pCtrl->GetParentItem(hParent) : 0); - } - while (hParent && !hEndItem); - return RecursiveTreeItemIterator(pCtrl, hEndItem); - } - - inline NonRecursiveTreeItemIterator BeginTreeItemsNonRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - if (hItem == 0) - { - hItem = (pCtrl ? pCtrl->GetRootItem() : 0); - } - if (hItem) - { - hItem = pCtrl->GetChildItem(hItem); - } - return NonRecursiveTreeItemIterator(pCtrl, hItem); - } - - inline NonRecursiveTreeItemIterator EndTreeItemsNonRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - HTREEITEM hEndItem = 0; - HTREEITEM hParent = 0; - while (hParent && !hEndItem) - { - hParent = (pCtrl && hItem ? pCtrl->GetParentItem(hItem) : 0); - if (hParent) - { - hEndItem = pCtrl->GetNextSiblingItem(hParent); - } - } - return NonRecursiveTreeItemIterator(pCtrl, hEndItem); - } - - template - class TreeItemDataIterator - { - public: - typedef T Type; - typedef TreeItemIterator

InternalIterator; - - //iterator traits, required by STL - typedef ptrdiff_t difference_type; - typedef Type* value_type; - typedef Type** pointer; - typedef Type*& reference; - typedef std::forward_iterator_tag iterator_category; - - TreeItemDataIterator() {} - TreeItemDataIterator(const TreeItemDataIterator& other) - : iterator(other.iterator) {AdvanceToValidIterator(); } - explicit TreeItemDataIterator(const InternalIterator& iterator) - : iterator(iterator) {AdvanceToValidIterator(); } - - Type* operator*() {return reinterpret_cast(iterator.pCtrl->GetItemData(iterator.hItem)); } - bool operator==(const TreeItemDataIterator& other) const {return iterator == other.iterator; } - bool operator!=(const TreeItemDataIterator& other) const {return iterator != other.iterator; } - - HTREEITEM GetTreeItem() {return iterator.hItem; } - - TreeItemDataIterator& operator++() - { - ++iterator; - AdvanceToValidIterator(); - return *this; - } - - TreeItemDataIterator operator++(int) {TreeItemDataIterator old = *this; ++(*this); return old; } - - private: - void AdvanceToValidIterator() - { - while (iterator.pCtrl && iterator.hItem && !iterator.pCtrl->GetItemData(iterator.hItem)) - { - ++iterator; - } - } - - InternalIterator iterator; - }; - - template - class RecursiveItemDataIteratorType - { - public: typedef TreeItemDataIterator type; - }; - template - inline TreeItemDataIterator BeginTreeItemDataRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - return TreeItemDataIterator(BeginTreeItemsRecursive(pCtrl, hItem)); - } - - template - inline TreeItemDataIterator EndTreeItemDataRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - return TreeItemDataIterator(EndTreeItemsRecursive(pCtrl, hItem)); - } - - template - class NonRecursiveItemDataIteratorType - { - typedef TreeItemDataIterator type; - }; - template - inline TreeItemDataIterator BeginTreeItemDataNonRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - return TreeItemDataIterator(BeginTreeItemsNonRecursive(pCtrl, hItem)); - } - - template - inline TreeItemDataIterator EndTreeItemDataNonRecursive(CTreeCtrl* pCtrl, HTREEITEM hItem = 0) - { - return TreeItemDataIterator(EndTreeItemsNonRecursive(pCtrl, hItem)); - } - - class SelectedTreeItemIterator - { - public: - SelectedTreeItemIterator() - : pCtrl(0) - , hItem(0) {} - SelectedTreeItemIterator(const SelectedTreeItemIterator& other) - : pCtrl(other.pCtrl) - , hItem(other.hItem) {} - SelectedTreeItemIterator(CXTTreeCtrl* pCtrl, HTREEITEM hItem) - : pCtrl(pCtrl) - , hItem(hItem) {} - - HTREEITEM operator*() {return hItem; } - bool operator==(const SelectedTreeItemIterator& other) const {return pCtrl == other.pCtrl && hItem == other.hItem; } - bool operator!=(const SelectedTreeItemIterator& other) const {return pCtrl != other.pCtrl || hItem != other.hItem; } - - SelectedTreeItemIterator& operator++() - { - hItem = (pCtrl ? pCtrl->GetNextSelectedItem(hItem) : 0); - - return *this; - } - - SelectedTreeItemIterator operator++(int) {SelectedTreeItemIterator old = *this; ++(*this); return old; } - - CXTTreeCtrl* pCtrl; - HTREEITEM hItem; - }; - - SelectedTreeItemIterator BeginSelectedTreeItems(CXTTreeCtrl* pCtrl) - { - return SelectedTreeItemIterator(pCtrl, (pCtrl ? pCtrl->GetFirstSelectedItem() : 0)); - } - - SelectedTreeItemIterator EndSelectedTreeItems(CXTTreeCtrl* pCtrl) - { - return SelectedTreeItemIterator(pCtrl, 0); - } - - template - class SelectedTreeItemDataIterator - { - public: - typedef T Type; - typedef SelectedTreeItemIterator InternalIterator; - - SelectedTreeItemDataIterator() {} - SelectedTreeItemDataIterator(const SelectedTreeItemDataIterator& other) - : iterator(other.iterator) {AdvanceToValidIterator(); } - explicit SelectedTreeItemDataIterator(const InternalIterator& iterator) - : iterator(iterator) {AdvanceToValidIterator(); } - - Type* operator*() {return reinterpret_cast(iterator.pCtrl->GetItemData(iterator.hItem)); } - bool operator==(const SelectedTreeItemDataIterator& other) const {return iterator == other.iterator; } - bool operator!=(const SelectedTreeItemDataIterator& other) const {return iterator != other.iterator; } - - HTREEITEM GetTreeItem() {return iterator.hItem; } - - SelectedTreeItemDataIterator& operator++() - { - ++iterator; - AdvanceToValidIterator(); - return *this; - } - - SelectedTreeItemDataIterator operator++(int) {SelectedTreeItemDataIterator old = *this; ++(*this); return old; } - - private: - void AdvanceToValidIterator() - { - while (iterator.pCtrl && iterator.hItem && !iterator.pCtrl->GetItemData(iterator.hItem)) - { - ++iterator; - } - } - - InternalIterator iterator; - }; - - template - SelectedTreeItemDataIterator BeginSelectedTreeItemData(CXTTreeCtrl* pCtrl) - { - return SelectedTreeItemDataIterator(BeginSelectedTreeItems(pCtrl)); - } - - template - SelectedTreeItemDataIterator EndSelectedTreeItemData(CXTTreeCtrl* pCtrl) - { - return SelectedTreeItemDataIterator(EndSelectedTreeItems(pCtrl)); - } -} - -#endif // CRYINCLUDE_EDITOR_CONTROLS_TREECTRLUTILS_H diff --git a/Code/Editor/EditMode/DeepSelection.cpp b/Code/Editor/EditMode/DeepSelection.cpp deleted file mode 100644 index 3e232a230c..0000000000 --- a/Code/Editor/EditMode/DeepSelection.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "DeepSelection.h" - -// Editor -#include "Objects/BaseObject.h" - - -//! Functor for sorting selected objects on deep selection mode. -struct NearDistance -{ - NearDistance(){} - bool operator()(const CDeepSelection::RayHitObject& lhs, const CDeepSelection::RayHitObject& rhs) const - { - return lhs.distance < rhs.distance; - } -}; - -//----------------------------------------------------------------------------- -CDeepSelection::CDeepSelection() - : m_Mode(DSM_NONE) - , m_previousMode(DSM_NONE) - , m_CandidateObjectCount(0) - , m_CurrentSelectedPos(-1) -{ - m_LastPickPoint = QPoint(-1, -1); -} - -//----------------------------------------------------------------------------- -CDeepSelection::~CDeepSelection() -{ -} - -//----------------------------------------------------------------------------- -void CDeepSelection::Reset(bool bResetLastPick) -{ - for (int i = 0; i < m_CandidateObjectCount; ++i) - { - m_RayHitObjects[i].object->ClearFlags(OBJFLAG_NO_HITTEST); - } - - m_CandidateObjectCount = 0; - m_CurrentSelectedPos = -1; - - m_RayHitObjects.clear(); - - if (bResetLastPick) - { - m_LastPickPoint = QPoint(-1, -1); - } -} - -//----------------------------------------------------------------------------- -void CDeepSelection::AddObject(float distance, CBaseObject* pObj) -{ - m_RayHitObjects.push_back(RayHitObject(distance, pObj)); -} - -//----------------------------------------------------------------------------- -bool CDeepSelection::OnCycling (const QPoint& pt) -{ - QPoint diff = m_LastPickPoint - pt; - LONG epsilon = 2; - m_LastPickPoint = pt; - - if (abs(diff.x()) < epsilon && abs(diff.y()) < epsilon) - { - return true; - } - else - { - return false; - } -} - -//----------------------------------------------------------------------------- -void CDeepSelection::ExcludeHitTest(int except) -{ - int nExcept = except % m_CandidateObjectCount; - - for (int i = 0; i < m_CandidateObjectCount; ++i) - { - m_RayHitObjects[i].object->SetFlags(OBJFLAG_NO_HITTEST); - } - - m_RayHitObjects[nExcept].object->ClearFlags(OBJFLAG_NO_HITTEST); -} - -//----------------------------------------------------------------------------- -int CDeepSelection::CollectCandidate(float fMinDistance, float fRange) -{ - m_CandidateObjectCount = 0; - - if (!m_RayHitObjects.empty()) - { - std::sort(m_RayHitObjects.begin(), m_RayHitObjects.end(), NearDistance()); - - for (std::vector::iterator itr = m_RayHitObjects.begin(); - itr != m_RayHitObjects.end(); ++itr) - { - if (itr->distance - fMinDistance < fRange) - { - ++m_CandidateObjectCount; - } - else - { - break; - } - } - } - - return m_CandidateObjectCount; -} - -//----------------------------------------------------------------------------- -CBaseObject* CDeepSelection::GetCandidateObject(int index) -{ - m_CurrentSelectedPos = index % m_CandidateObjectCount; - - return m_RayHitObjects[m_CurrentSelectedPos].object; -} - -//----------------------------------------------------------------------------- -//! -void CDeepSelection::SetMode(EDeepSelectionMode mode) -{ - m_previousMode = m_Mode; - m_Mode = mode; -} diff --git a/Code/Editor/EditMode/DeepSelection.h b/Code/Editor/EditMode/DeepSelection.h deleted file mode 100644 index b6f652abc5..0000000000 --- a/Code/Editor/EditMode/DeepSelection.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 - * - */ - - -// Description : Deep Selection Header - - -#ifndef CRYINCLUDE_EDITOR_EDITMODE_DEEPSELECTION_H -#define CRYINCLUDE_EDITOR_EDITMODE_DEEPSELECTION_H -#pragma once - -class CBaseObject; - -//! Deep Selection -//! Additional output information of HitContext on using "deep selection mode". -//! At the deep selection mode, it supports second selection pass for easy -//! selection on crowded area with two different method. -//! One is to show pop menu of candidate objects list. Another is the cyclic -//! selection on pick clicking. -class CDeepSelection - : public _i_reference_target_t -{ -public: - //! Deep Selection Mode Definition - enum EDeepSelectionMode - { - DSM_NONE = 0, // Not using deep selection. - DSM_POP = 1, // Deep selection mode with pop context menu. - DSM_CYCLE = 2 // Deep selection mode with cyclic selection on each clinking same point. - }; - - //! Subclass for container of the selected object with hit distance. - struct RayHitObject - { - RayHitObject(float dist, CBaseObject* pObj) - : distance(dist) - , object(pObj) - { - } - - float distance; - CBaseObject* object; - }; - - //! Constructor - CDeepSelection(); - virtual ~CDeepSelection(); - - void Reset(bool bResetLastPick = false); - void AddObject(float distance, CBaseObject* pObj); - //! Check if clicking point is same position with last position, - //! to decide whether to continue cycling mode. - bool OnCycling (const QPoint& pt); - //! All objects in list are excluded for hitting test except one, current selection. - void ExcludeHitTest(int except); - void SetMode(EDeepSelectionMode mode); - inline EDeepSelectionMode GetMode() const { return m_Mode; } - inline EDeepSelectionMode GetPreviousMode() const { return m_previousMode; } - //! Collect object in the deep selection range. The distance from the minimum - //! distance is less than deep selection range. - int CollectCandidate(float fMinDistance, float fRange); - //! Return the candidate object in index position, then it is to be current - //! selection position. - CBaseObject* GetCandidateObject(int index); - //! Return the current selection position that is update in "GetCandidateObject" - //! function call. - inline int GetCurrentSelectPos() const { return m_CurrentSelectedPos; } - //! Return the number of objects in the deep selection range. - inline int GetCandidateObjectCount() const { return m_CandidateObjectCount; } - -private: - //! Current mode - EDeepSelectionMode m_Mode; - EDeepSelectionMode m_previousMode; - //! Last picking point to check whether cyclic selection continue. - QPoint m_LastPickPoint; - //! List of the selected objects with ray hitting - std::vector m_RayHitObjects; - int m_CandidateObjectCount; - int m_CurrentSelectedPos; -}; -#endif // CRYINCLUDE_EDITOR_EDITMODE_DEEPSELECTION_H diff --git a/Code/Editor/EditorPanelUtils.cpp b/Code/Editor/EditorPanelUtils.cpp deleted file mode 100644 index 1a3c9bcb4a..0000000000 --- a/Code/Editor/EditorPanelUtils.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "EditorPanelUtils.h" - -#include - -// Qt -#include -#include -#include - -// Editor -#include "IEditorPanelUtils.h" -#include "Objects/EntityObject.h" -#include "CryEditDoc.h" -#include "ViewManager.h" -#include "Controls/QToolTipWidget.h" -#include "Objects/SelectionGroup.h" - - - -#ifndef PI -#define PI 3.14159265358979323f -#endif - - -struct ToolTip -{ - bool isValid; - QString title; - QString content; - QString specialContent; - QString disabledContent; -}; - -// internal implementation for better compile times - should also never be used externally, use IParticleEditorUtils interface for that. -class CEditorPanelUtils_Impl - : public IEditorPanelUtils -{ -public: - void SetViewportDragOperation(void(* dropCallback)(CViewport* viewport, int dragPointX, int dragPointY, void* custom), void* custom) override - { - for (int i = 0; i < GetIEditor()->GetViewManager()->GetViewCount(); i++) - { - GetIEditor()->GetViewManager()->GetView(i)->SetGlobalDropCallback(dropCallback, custom); - } - } - -public: - - int PreviewWindow_GetDisplaySettingsDebugFlags(CDisplaySettings* settings) override - { - CRY_ASSERT(settings); - return settings->GetDebugFlags(); - } - - void PreviewWindow_SetDisplaySettingsDebugFlags(CDisplaySettings* settings, int flags) override - { - CRY_ASSERT(settings); - settings->SetDebugFlags(flags); - } - -protected: - QVector hotkeys; - bool m_hotkeysAreEnabled; -public: - - bool HotKey_Import() override - { - QVector > keys; - QString filepath = QFileDialog::getOpenFileName(nullptr, "Select shortcut configuration to load", - QString(), "HotKey Config Files (*.hkxml)"); - QFile file(filepath); - if (!file.open(QIODevice::ReadOnly)) - { - return false; - } - QXmlStreamReader stream(&file); - bool result = true; - - while (!stream.isEndDocument()) - { - if (stream.isStartElement()) - { - if (stream.name() == "HotKey") - { - QPair key; - QXmlStreamAttributes att = stream.attributes(); - for (QXmlStreamAttribute attr : att) - { - if (attr.name().compare(QLatin1String("path"), Qt::CaseInsensitive) == 0) - { - key.first = attr.value().toString(); - } - if (attr.name().compare(QLatin1String("sequence"), Qt::CaseInsensitive) == 0) - { - key.second = attr.value().toString(); - } - } - if (!key.first.isEmpty()) - { - keys.push_back(key); // we allow blank key sequences for unassigned shortcuts - } - else - { - result = false; //but not blank paths! - } - } - } - stream.readNext(); - } - file.close(); - - if (result) - { - HotKey_BuildDefaults(); - for (QPair key : keys) - { - for (int j = 0; j < hotkeys.count(); j++) - { - if (hotkeys[j].path.compare(key.first, Qt::CaseInsensitive) == 0) - { - hotkeys[j].SetPath(key.first.toStdString().c_str()); - hotkeys[j].SetSequenceFromString(key.second.toStdString().c_str()); - } - } - } - } - return result; - } - - void HotKey_Export() override - { - auto settingDir = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / "Editor" / "Plugins" / "ParticleEditorPlugin" / "settings"; - QString filepath = QFileDialog::getSaveFileName(nullptr, "Select shortcut configuration to load", settingDir.c_str(), "HotKey Config Files (*.hkxml)"); - QFile file(filepath); - if (!file.open(QIODevice::WriteOnly)) - { - return; - } - - QXmlStreamWriter stream(&file); - stream.setAutoFormatting(true); - stream.writeStartDocument(); - stream.writeStartElement("HotKeys"); - - for (HotKey key : hotkeys) - { - stream.writeStartElement("HotKey"); - stream.writeAttribute("path", key.path); - stream.writeAttribute("sequence", key.sequence.toString()); - stream.writeEndElement(); - } - stream.writeEndElement(); - stream.writeEndDocument(); - file.close(); - } - - QKeySequence HotKey_GetShortcut(const char* path) override - { - for (HotKey combo : hotkeys) - { - if (combo.IsMatch(path)) - { - return combo.sequence; - } - } - return QKeySequence(); - } - - bool HotKey_IsPressed(const QKeyEvent* event, const char* path) override - { - if (!m_hotkeysAreEnabled) - { - return false; - } - unsigned int keyInt = 0; - //Capture any modifiers - Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); - if (modifiers & Qt::ShiftModifier) - { - keyInt += Qt::SHIFT; - } - if (modifiers & Qt::ControlModifier) - { - keyInt += Qt::CTRL; - } - if (modifiers & Qt::AltModifier) - { - keyInt += Qt::ALT; - } - if (modifiers & Qt::MetaModifier) - { - keyInt += Qt::META; - } - //Capture any key - keyInt += event->key(); - - QString t0 = QKeySequence(keyInt).toString(); - QString t1 = HotKey_GetShortcut(path).toString(); - - //if strings match then shortcut is pressed - if (t1.compare(t0, Qt::CaseInsensitive) == 0) - { - return true; - } - return false; - } - - bool HotKey_IsPressed(const QShortcutEvent* event, const char* path) override - { - if (!m_hotkeysAreEnabled) - { - return false; - } - - QString t0 = event->key().toString(); - QString t1 = HotKey_GetShortcut(path).toString(); - - //if strings match then shortcut is pressed - if (t1.compare(t0, Qt::CaseInsensitive) == 0) - { - return true; - } - return false; - } - - bool HotKey_LoadExisting() override - { - QSettings settings("O3DE", "O3DE"); - QString group = "Hotkeys/"; - - HotKey_BuildDefaults(); - - int size = settings.beginReadArray(group); - - for (int i = 0; i < size; i++) - { - settings.setArrayIndex(i); - QPair hotkey; - hotkey.first = settings.value("name").toString(); - hotkey.second = settings.value("keySequence").toString(); - if (!hotkey.first.isEmpty()) - { - for (int j = 0; j < hotkeys.count(); j++) - { - if (hotkeys[j].path.compare(hotkey.first, Qt::CaseInsensitive) == 0) - { - hotkeys[j].SetPath(hotkey.first.toStdString().c_str()); - hotkeys[j].SetSequenceFromString(hotkey.second.toStdString().c_str()); - } - } - } - } - - settings.endArray(); - if (hotkeys.isEmpty()) - { - return false; - } - return true; - } - - void HotKey_SaveCurrent() override - { - QSettings settings("O3DE", "O3DE"); - QString group = "Hotkeys/"; - settings.remove("Hotkeys/"); - settings.sync(); - settings.beginWriteArray(group); - int saveIndex = 0; - for (HotKey key : hotkeys) - { - if (!key.path.isEmpty()) - { - settings.setArrayIndex(saveIndex++); - settings.setValue("name", key.path); - settings.setValue("keySequence", key.sequence.toString()); - } - } - settings.endArray(); - settings.sync(); - } - - void HotKey_BuildDefaults() override - { - m_hotkeysAreEnabled = true; - QVector > keys; - while (hotkeys.count() > 0) - { - hotkeys.takeAt(0); - } - - //MENU SELECTION SHORTCUTS//////////////////////////////////////////////// - keys.push_back(QPair("Menus.File Menu", "Alt+F")); - keys.push_back(QPair("Menus.Edit Menu", "Alt+E")); - keys.push_back(QPair("Menus.View Menu", "Alt+V")); - //FILE MENU SHORTCUTS///////////////////////////////////////////////////// - keys.push_back(QPair("File Menu.Create new emitter", "Ctrl+N")); - keys.push_back(QPair("File Menu.Create new library", "Ctrl+Shift+N")); - keys.push_back(QPair("File Menu.Create new folder", "")); - keys.push_back(QPair("File Menu.Import", "Ctrl+I")); - keys.push_back(QPair("File Menu.Import level library", "Ctrl+Shift+I")); - keys.push_back(QPair("File Menu.Save", "Ctrl+S")); - keys.push_back(QPair("File Menu.Close", "Ctrl+Q")); - //EDIT MENU SHORTCUTS///////////////////////////////////////////////////// - keys.push_back(QPair("Edit Menu.Copy", "Ctrl+C")); - keys.push_back(QPair("Edit Menu.Paste", "Ctrl+V")); - keys.push_back(QPair("Edit Menu.Duplicate", "Ctrl+D")); - keys.push_back(QPair("Edit Menu.Undo", "Ctrl+Z")); - keys.push_back(QPair("Edit Menu.Redo", "Ctrl+Shift+Z")); - keys.push_back(QPair("Edit Menu.Group", "Ctrl+Alt+O")); - keys.push_back(QPair("Edit Menu.Ungroup", "Ctrl+Alt+P")); - keys.push_back(QPair("Edit Menu.Rename", "Ctrl+R")); - keys.push_back(QPair("Edit Menu.Reset", "")); - keys.push_back(QPair("Edit Menu.Edit Hotkeys", "")); - keys.push_back(QPair("Edit Menu.Assign to selected", "Ctrl+Space")); - keys.push_back(QPair("Edit Menu.Insert Comment", "Ctrl+Alt+M")); - keys.push_back(QPair("Edit Menu.Enable/Disable Emitter", "Ctrl+E")); - keys.push_back(QPair("File Menu.Enable All", "")); - keys.push_back(QPair("File Menu.Disable All", "")); - keys.push_back(QPair("Edit Menu.Delete", "Del")); - //VIEW MENU SHORTCUTS///////////////////////////////////////////////////// - keys.push_back(QPair("View Menu.Reset Layout", "")); - //PLAYBACK CONTROL//////////////////////////////////////////////////////// - keys.push_back(QPair("Previewer.Play/Pause Toggle", "Space")); - keys.push_back(QPair("Previewer.Step forward through time", "c")); - keys.push_back(QPair("Previewer.Loop Toggle", "z")); - keys.push_back(QPair("Previewer.Reset Playback", "x")); - keys.push_back(QPair("Previewer.Focus", "Ctrl+F")); - keys.push_back(QPair("Previewer.Zoom In", "w")); - keys.push_back(QPair("Previewer.Zoom Out", "s")); - keys.push_back(QPair("Previewer.Pan Left", "a")); - keys.push_back(QPair("Previewer.Pan Right", "d")); - - for (QPair key : keys) - { - unsigned int index = hotkeys.count(); - hotkeys.push_back(HotKey()); - hotkeys[index].SetPath(key.first.toStdString().c_str()); - hotkeys[index].SetSequenceFromString(key.second.toStdString().c_str()); - } - } - - void HotKey_SetKeys(QVector keys) override - { - hotkeys = keys; - } - - QVector HotKey_GetKeys() override - { - return hotkeys; - } - - QString HotKey_GetPressedHotkey(const QKeyEvent* event) override - { - if (!m_hotkeysAreEnabled) - { - return ""; - } - for (HotKey key : hotkeys) - { - if (HotKey_IsPressed(event, key.path.toUtf8())) - { - return key.path; - } - } - return ""; - } - QString HotKey_GetPressedHotkey(const QShortcutEvent* event) override - { - if (!m_hotkeysAreEnabled) - { - return ""; - } - for (HotKey key : hotkeys) - { - if (HotKey_IsPressed(event, key.path.toUtf8())) - { - return key.path; - } - } - return ""; - } - //building the default hotkey list re-enables hotkeys - //do not use this when rebuilding the default list is a possibility. - void HotKey_SetEnabled(bool val) override - { - m_hotkeysAreEnabled = val; - } - - bool HotKey_IsEnabled() const override - { - return m_hotkeysAreEnabled; - } - -protected: - QMap m_tooltips; - - void ToolTip_ParseNode(XmlNodeRef node) - { - if (QString(node->getTag()).compare("tooltip", Qt::CaseInsensitive) != 0) - { - unsigned int childCount = node->getChildCount(); - - for (unsigned int i = 0; i < childCount; i++) - { - ToolTip_ParseNode(node->getChild(i)); - } - } - - QString title = node->getAttr("title"); - QString content = node->getAttr("content"); - QString specialContent = node->getAttr("special_content"); - QString disabledContent = node->getAttr("disabled_content"); - - QMap::iterator itr = m_tooltips.insert(node->getAttr("path"), ToolTip()); - itr->isValid = true; - itr->title = title; - itr->content = content; - itr->specialContent = specialContent; - itr->disabledContent = disabledContent; - - unsigned int childCount = node->getChildCount(); - - for (unsigned int i = 0; i < childCount; i++) - { - ToolTip_ParseNode(node->getChild(i)); - } - } - - ToolTip GetToolTip(QString path) - { - if (m_tooltips.contains(path)) - { - return m_tooltips[path]; - } - ToolTip temp; - temp.isValid = false; - return temp; - } - -public: - void ToolTip_LoadConfigXML(QString filepath) override - { - XmlNodeRef node = GetIEditor()->GetSystem()->LoadXmlFromFile(filepath.toStdString().c_str()); - ToolTip_ParseNode(node); - } - - void ToolTip_BuildFromConfig(IQToolTip* tooltip, QString path, QString option, QString optionalData = "", bool isEnabled = true) override - { - AZ_Assert(tooltip, "tooltip cannot be null"); - - QString title = ToolTip_GetTitle(path, option); - QString content = ToolTip_GetContent(path, option); - QString specialContent = ToolTip_GetSpecialContentType(path, option); - QString disabledContent = ToolTip_GetDisabledContent(path, option); - - // Even if these items are empty, we set them anyway to clear out any data that was left over from when the tooltip was used for a different object. - tooltip->SetTitle(title); - tooltip->SetContent(content); - - //this only handles simple creation...if you need complex call this then add specials separate - if (!specialContent.contains("::")) - { - tooltip->AddSpecialContent(specialContent, optionalData); - } - - if (!isEnabled) // If disabled, add disabled value - { - tooltip->AppendContent(disabledContent); - } - } - - QString ToolTip_GetTitle(QString path, QString option) override - { - if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) - { - return GetToolTip(path + "." + option).title; - } - if (!option.isEmpty() && GetToolTip("Options." + option).isValid) - { - return GetToolTip("Options." + option).title; - } - return GetToolTip(path).title; - } - - QString ToolTip_GetContent(QString path, QString option) override - { - if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) - { - return GetToolTip(path + "." + option).content; - } - if (!option.isEmpty() && GetToolTip("Options." + option).isValid) - { - return GetToolTip("Options." + option).content; - } - return GetToolTip(path).content; - } - - QString ToolTip_GetSpecialContentType(QString path, QString option) override - { - if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) - { - return GetToolTip(path + "." + option).specialContent; - } - if (!option.isEmpty() && GetToolTip("Options." + option).isValid) - { - return GetToolTip("Options." + option).specialContent; - } - return GetToolTip(path).specialContent; - } - - QString ToolTip_GetDisabledContent(QString path, QString option) override - { - if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) - { - return GetToolTip(path + "." + option).disabledContent; - } - if (!option.isEmpty() && GetToolTip("Options." + option).isValid) - { - return GetToolTip("Options." + option).disabledContent; - } - return GetToolTip(path).disabledContent; - } -}; - -IEditorPanelUtils* CreateEditorPanelUtils() -{ - return new CEditorPanelUtils_Impl(); -} - diff --git a/Code/Editor/EditorPanelUtils.h b/Code/Editor/EditorPanelUtils.h deleted file mode 100644 index 6ac15ebfc9..0000000000 --- a/Code/Editor/EditorPanelUtils.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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 - * - */ -// Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. -#ifndef CRYINCLUDE_CRYEDITOR_EDITORPANELUTILS_H -#define CRYINCLUDE_CRYEDITOR_EDITORPANELUTILS_H -#pragma once - -struct IEditorPanelUtils; -IEditorPanelUtils* CreateEditorPanelUtils(); - -#endif diff --git a/Code/Editor/EditorPreferencesPageAWS.cpp b/Code/Editor/EditorPreferencesPageAWS.cpp index 68a9d6889f..9279dce7bc 100644 --- a/Code/Editor/EditorPreferencesPageAWS.cpp +++ b/Code/Editor/EditorPreferencesPageAWS.cpp @@ -28,7 +28,7 @@ void CEditorPreferencesPage_AWS::Reflect(AZ::SerializeContext& serialize) if (editContext) { editContext->Class("Options", "") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &UsageOptions::m_awsAttributionEnabled, "Allow O3DE to send information about your use of AWS Core Gem to AWS", + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &UsageOptions::m_awsAttributionEnabled, "Allow O3DE to send information about your use of AWS Core Gem to AWS", ""); editContext->Class("AWS Preferences", "AWS Preferences") diff --git a/Code/Editor/ErrorRecorder.cpp b/Code/Editor/ErrorRecorder.cpp index 999dab323c..253e103527 100644 --- a/Code/Editor/ErrorRecorder.cpp +++ b/Code/Editor/ErrorRecorder.cpp @@ -7,7 +7,6 @@ */ #include "EditorDefs.h" #include "ErrorRecorder.h" -#include "BaseLibraryItem.h" #include "Include/IErrorReport.h" diff --git a/Code/Editor/ErrorRecorder.h b/Code/Editor/ErrorRecorder.h index e4b3706a16..beacc3f0e5 100644 --- a/Code/Editor/ErrorRecorder.h +++ b/Code/Editor/ErrorRecorder.h @@ -14,6 +14,8 @@ #define CRYINCLUDE_EDITOR_CORE_ERRORRECORDER_H #pragma once +#include "Include/EditorCoreAPI.h" + ////////////////////////////////////////////////////////////////////////// //! Automatic class to record and display error. class EDITOR_CORE_API CErrorsRecorder diff --git a/Code/Editor/ErrorReport.cpp b/Code/Editor/ErrorReport.cpp index 4fd7d41a96..f93ea7606d 100644 --- a/Code/Editor/ErrorReport.cpp +++ b/Code/Editor/ErrorReport.cpp @@ -67,24 +67,6 @@ QString CErrorRecord::GetErrorText() const { str += QString("\t "); } - if (pItem) - { - switch (pItem->GetType()) - { - case EDB_TYPE_MATERIAL: - str += QString("\t Material=\""); - break; - case EDB_TYPE_PARTICLE: - str += QString("\t Particle=\""); - break; - case EDB_TYPE_MUSIC: - str += QString("\t Music=\""); - break; - default: - str += QString("\t Item=\""); - } - str += pItem->GetFullName() + "\""; - } if (pObject) { str += QString("\t Object=\"") + pObject->GetName() + "\""; @@ -101,7 +83,6 @@ CErrorReport::CErrorReport() m_bImmediateMode = true; m_bShowErrors = true; m_pObject = nullptr; - m_pItem = nullptr; m_pParticle = nullptr; } @@ -140,10 +121,6 @@ void CErrorReport::ReportError(CErrorRecord& err) { err.pObject = m_pObject; } - else if (err.pItem == nullptr && m_pItem != nullptr) - { - err.pItem = m_pItem; - } m_errors.push_back(err); } bNoRecurse = false; @@ -255,12 +232,6 @@ void CErrorReport::SetCurrentValidatorObject(CBaseObject* pObject) m_pObject = pObject; } -////////////////////////////////////////////////////////////////////////// -void CErrorReport::SetCurrentValidatorItem(CBaseLibraryItem* pItem) -{ - m_pItem = pItem; -} - ////////////////////////////////////////////////////////////////////////// void CErrorReport::SetCurrentFile(const QString& file) { diff --git a/Code/Editor/ErrorReport.h b/Code/Editor/ErrorReport.h index 3b9a860301..98d230e383 100644 --- a/Code/Editor/ErrorReport.h +++ b/Code/Editor/ErrorReport.h @@ -17,8 +17,11 @@ // forward declarations. class CParticleItem; -#include "BaseLibraryItem.h" +#include +#include + #include "Objects/BaseObject.h" +#include "Include/EditorCoreAPI.h" #include "Include/IErrorReport.h" #include "ErrorRecorder.h" @@ -56,16 +59,13 @@ public: int count; //! Object that caused this error. _smart_ptr pObject; - //! Library Item that caused this error. - _smart_ptr pItem; int flags; CErrorRecord(CBaseObject* object, ESeverity _severity, const QString& _error, int _flags = 0, int _count = 0, - CBaseLibraryItem* item = 0, EValidatorModule _module = VALIDATOR_MODULE_EDITOR) + EValidatorModule _module = VALIDATOR_MODULE_EDITOR) : severity(_severity) , module(_module) , pObject(object) - , pItem(item) , flags(_flags) , count(_count) , error(_error) @@ -77,7 +77,6 @@ public: severity = ESEVERITY_WARNING; module = VALIDATOR_MODULE_EDITOR; pObject = 0; - pItem = 0; flags = 0; count = 0; } @@ -116,8 +115,6 @@ public: //! Assign current Object to which new reported warnings are assigned. void SetCurrentValidatorObject(CBaseObject* pObject); - //! Assign current Item to which new reported warnings are assigned. - void SetCurrentValidatorItem(CBaseLibraryItem* pItem); //! Assign current filename. void SetCurrentFile(const QString& file); @@ -127,7 +124,6 @@ private: bool m_bImmediateMode; bool m_bShowErrors; _smart_ptr m_pObject; - _smart_ptr m_pItem; CParticleItem* m_pParticle; QString m_currentFilename; }; diff --git a/Code/Editor/ErrorReportDialog.cpp b/Code/Editor/ErrorReportDialog.cpp index 2d551d6c8b..bbeede79ef 100644 --- a/Code/Editor/ErrorReportDialog.cpp +++ b/Code/Editor/ErrorReportDialog.cpp @@ -362,10 +362,6 @@ void CErrorReportDialog::CopyToClipboard() { str += QString::fromLatin1(" [Object: %1]").arg(pRecord->pObject->GetName()); } - if (pRecord->pItem) - { - str += QString::fromLatin1(" [Material: %1]").arg(pRecord->pItem->GetName()); - } str += QString::fromLatin1("\r\n"); } } diff --git a/Code/Editor/ErrorReportTableModel.cpp b/Code/Editor/ErrorReportTableModel.cpp index f5dce1a86d..923991bb62 100644 --- a/Code/Editor/ErrorReportTableModel.cpp +++ b/Code/Editor/ErrorReportTableModel.cpp @@ -149,11 +149,7 @@ QVariant CErrorReportTableModel::data(const CErrorRecord& record, int column, in case ColumnFile: return record.file; case ColumnObject: - if (record.pItem) - { - return record.pItem->GetFullName(); - } - else if (record.pObject) + if (record.pObject) { return record.pObject->GetName(); } diff --git a/Code/Editor/Geometry/TriMesh.cpp b/Code/Editor/Geometry/TriMesh.cpp deleted file mode 100644 index efc201095d..0000000000 --- a/Code/Editor/Geometry/TriMesh.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "TriMesh.h" - -// Editor -#include "Util/fastlib.h" -#include "Objects/SubObjSelection.h" - - -////////////////////////////////////////////////////////////////////////// -CTriMesh::CTriMesh() -{ - pFaces = nullptr; - pVertices = nullptr; - pWSVertices = nullptr; - pUV = nullptr; - pColors = nullptr; - pEdges = nullptr; - pWeights = nullptr; - - nFacesCount = 0; - nVertCount = 0; - nUVCount = 0; - nEdgeCount = 0; - - selectionType = SO_ELEM_NONE; - - memset(m_streamSize, 0, sizeof(m_streamSize)); - memset(m_streamSel, 0, sizeof(m_streamSel)); - streamSelMask = 0; - - m_streamSel[VERTICES] = &vertSel; - m_streamSel[EDGES] = &edgeSel; - m_streamSel[FACES] = &faceSel; -} - -////////////////////////////////////////////////////////////////////////// -CTriMesh::~CTriMesh() -{ - free(pFaces); - free(pEdges); - free(pVertices); - free(pUV); - free(pColors); - free(pWSVertices); - free(pWeights); -} - -// Set stream size. -void CTriMesh::ReallocStream(int stream, int nNewCount) -{ - assert(stream >= 0 && stream < LAST_STREAM); - if (stream < 0 || stream >= LAST_STREAM) - { - return; - } - if (m_streamSize[stream] == nNewCount) - { - return; // Stream already have required size. - } - void* pStream = nullptr; - int nElementSize = 0; - GetStreamInfo(stream, pStream, nElementSize); - pStream = ReAllocElements(pStream, nNewCount, nElementSize); - m_streamSize[stream] = nNewCount; - - switch (stream) - { - case VERTICES: - pVertices = (CTriVertex*)pStream; - nVertCount = nNewCount; - vertSel.resize(nNewCount); - break; - case FACES: - pFaces = (CTriFace*)pStream; - nFacesCount = nNewCount; - faceSel.resize(nNewCount); - break; - case EDGES: - pEdges = (CTriEdge*)pStream; - nEdgeCount = nNewCount; - edgeSel.resize(nNewCount); - break; - case TEXCOORDS: - pUV = (SMeshTexCoord*)pStream; - nUVCount = nNewCount; - break; - case COLORS: - pColors = (SMeshColor*)pStream; - break; - case WEIGHTS: - pWeights = (float*)pStream; - break; - case LINES: - pLines = (CTriLine*)pStream; - break; - case WS_POSITIONS: - pWSVertices = (Vec3*)pStream; - break; - default: - assert(0); // unknown stream. - } - m_streamSize[stream] = nNewCount; -} - -// Set stream size. -void CTriMesh::GetStreamInfo(int stream, void*& pStream, int& nElementSize) const -{ - assert(stream >= 0 && stream < LAST_STREAM); - switch (stream) - { - case VERTICES: - pStream = pVertices; - nElementSize = sizeof(CTriVertex); - break; - case FACES: - pStream = pFaces; - nElementSize = sizeof(CTriFace); - break; - case EDGES: - pStream = pEdges; - nElementSize = sizeof(CTriEdge); - break; - case TEXCOORDS: - pStream = pUV; - nElementSize = sizeof(SMeshTexCoord); - break; - case COLORS: - pStream = pColors; - nElementSize = sizeof(SMeshColor); - break; - case WEIGHTS: - pStream = pWeights; - nElementSize = sizeof(float); - break; - case LINES: - pStream = pLines; - nElementSize = sizeof(CTriLine); - break; - case WS_POSITIONS: - pStream = pWSVertices; - nElementSize = sizeof(Vec3); - break; - default: - assert(0); // unknown stream. - } -} - -////////////////////////////////////////////////////////////////////////// -void* CTriMesh::ReAllocElements(void* old_ptr, int new_elem_num, int size_of_element) -{ - return realloc(old_ptr, new_elem_num * size_of_element); -} - -///////////////////////////////////////////////////////////////////////////////////// -inline int FindVertexInHash(const Vec3& vPosToFind, const CTriVertex* pVectors, std::vector& hash, float fEpsilon) -{ - for (uint32 i = 0; i < hash.size(); i++) - { - const Vec3& v0 = pVectors[hash[i]].pos; - const Vec3& v1 = vPosToFind; - if (fabsf(v0.y - v1.y) < fEpsilon && fabsf(v0.x - v1.x) < fEpsilon && fabsf(v0.z - v1.z) < fEpsilon) - { - return hash[i]; - } - } - return -1; -} - -///////////////////////////////////////////////////////////////////////////////////// -inline int FindTexCoordInHash(const SMeshTexCoord& coordToFind, const SMeshTexCoord* pCoords, std::vector& hash, float fEpsilon) -{ - for (uint32 i = 0; i < hash.size(); i++) - { - const SMeshTexCoord& t0 = pCoords[hash[i]]; - const SMeshTexCoord& t1 = coordToFind; - - if (t0.IsEquivalent(t1, fEpsilon)) - { - return hash[i]; - } - } - return -1; -} - - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::SharePositions() -{ - float fEpsilon = 0.0001f; - float fHashScale = 256.0f / MAX(bbox.GetSize().GetLength(), fEpsilon); - std::vector arrHashTable[256]; - - CTriVertex* pNewVerts = new CTriVertex[GetVertexCount()]; - SMeshColor* pNewColors = nullptr; - if (pColors) - { - pNewColors = new SMeshColor[GetVertexCount()]; - } - - int nLastIndex = 0; - for (int f = 0; f < GetFacesCount(); f++) - { - CTriFace& face = pFaces[f]; - for (int i = 0; i < 3; i++) - { - const Vec3& v = pVertices[face.v[i]].pos; - uint8 nHash = static_cast(RoundFloatToInt((v.x + v.y + v.z) * fHashScale)); - - int find = FindVertexInHash(v, pNewVerts, arrHashTable[nHash], fEpsilon); - if (find < 0) - { - pNewVerts[nLastIndex] = pVertices[face.v[i]]; - if (pColors) - { - pNewColors[nLastIndex] = pColors[face.v[i]]; - } - face.v[i] = nLastIndex; - // Reserve some space already. - arrHashTable[nHash].reserve(100); - arrHashTable[nHash].push_back(nLastIndex); - nLastIndex++; - } - else - { - face.v[i] = find; - } - } - } - - SetVertexCount(nLastIndex); - memcpy(pVertices, pNewVerts, nLastIndex * sizeof(CTriVertex)); - delete []pNewVerts; - - if (pColors) - { - SetColorsCount(nLastIndex); - memcpy(pColors, pNewColors, nLastIndex * sizeof(SMeshColor)); - delete []pNewColors; - } -} - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::ShareUV() -{ - float fEpsilon = 0.0001f; - float fHashScale = 256.0f; - std::vector arrHashTable[256]; - - SMeshTexCoord* pNewUV = new SMeshTexCoord[GetUVCount()]; - - int nLastIndex = 0; - for (int f = 0; f < GetFacesCount(); f++) - { - CTriFace& face = pFaces[f]; - for (int i = 0; i < 3; i++) - { - const Vec2 uv = pUV[face.uv[i]].GetUV(); - uint8 nHash = static_cast(RoundFloatToInt((uv.x + uv.y) * fHashScale)); - - int find = FindTexCoordInHash(pUV[face.uv[i]], pNewUV, arrHashTable[nHash], fEpsilon); - if (find < 0) - { - pNewUV[nLastIndex] = pUV[face.uv[i]]; - face.uv[i] = nLastIndex; - arrHashTable[nHash].reserve(100); - arrHashTable[nHash].push_back(nLastIndex); - nLastIndex++; - } - else - { - face.uv[i] = find; - } - } - } - - SetUVCount(nLastIndex); - memcpy(pUV, pNewUV, nLastIndex * sizeof(SMeshTexCoord)); - delete []pNewUV; -} - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::CalcFaceNormals() -{ - for (int i = 0; i < nFacesCount; i++) - { - CTriFace& face = pFaces[i]; - Vec3 p1 = pVertices[face.v[0]].pos; - Vec3 p2 = pVertices[face.v[1]].pos; - Vec3 p3 = pVertices[face.v[2]].pos; - face.normal = (p2 - p1).Cross(p3 - p1); - face.normal.Normalize(); - } -} - -#define TEX_EPS 0.001f -#define VER_EPS 0.001f - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::CopyStream(CTriMesh& fromMesh, int stream) -{ - void* pTrgStream = nullptr; - void* pSrcStream = nullptr; - int nElemSize = 0; - fromMesh.GetStreamInfo(stream, pSrcStream, nElemSize); - if (pSrcStream) - { - ReallocStream(stream, fromMesh.GetStreamSize(stream)); - GetStreamInfo(stream, pTrgStream, nElemSize); - memcpy(pTrgStream, pSrcStream, nElemSize * fromMesh.GetStreamSize(stream)); - } -} - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::Copy(CTriMesh& fromMesh, int nCopyFlags) -{ - streamSelMask = fromMesh.streamSelMask; - - if (nCopyFlags & COPY_VERTICES) - { - CopyStream(fromMesh, VERTICES); - } - if (nCopyFlags & COPY_FACES) - { - CopyStream(fromMesh, FACES); - } - if (nCopyFlags & COPY_EDGES) - { - CopyStream(fromMesh, EDGES); - } - if (nCopyFlags & COPY_TEXCOORDS) - { - CopyStream(fromMesh, TEXCOORDS); - } - if (nCopyFlags & COPY_COLORS) - { - CopyStream(fromMesh, COLORS); - } - if (nCopyFlags & COPY_WEIGHTS) - { - CopyStream(fromMesh, WEIGHTS); - } - if (nCopyFlags & COPY_LINES) - { - CopyStream(fromMesh, LINES); - } - - if (nCopyFlags & COPY_VERT_SEL) - { - vertSel = fromMesh.vertSel; - } - if (nCopyFlags & COPY_EDGE_SEL) - { - edgeSel = fromMesh.edgeSel; - } - if (nCopyFlags & COPY_FACE_SEL) - { - faceSel = fromMesh.faceSel; - } -} - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::UpdateEdges() -{ - SetEdgeCount(GetFacesCount() * 3); - - std::map edgemap; - - int nEdges = 0; - for (int i = 0; i < GetFacesCount(); i++) - { - CTriFace& face = pFaces[i]; - for (int j = 0; j < 3; j++) - { - int v0 = j; - int v1 = (j != 2) ? j + 1 : 0; - CTriEdge edge; - edge.flags = 0; - - // First vertex index must always be smaller. - if (face.v[v0] < face.v[v1]) - { - edge.v[0] = face.v[v0]; - edge.v[1] = face.v[v1]; - } - else - { - edge.v[0] = face.v[v1]; - edge.v[1] = face.v[v0]; - } - edge.face[0] = i; - edge.face[1] = -1; - int nedge = stl::find_in_map(edgemap, edge, -1); - if (nedge >= 0) - { - // Assign this face as a second member of the edge. - if (pEdges[nedge].face[1] < 0) - { - pEdges[nedge].face[1] = i; - } - - face.edge[j] = nedge; - } - else - { - edgemap[edge] = nEdges; - pEdges[nEdges] = edge; - face.edge[j] = nEdges; - nEdges++; - } - } - } - - SetEdgeCount(nEdges); -} - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::SoftSelection(const SSubObjSelOptions& options) -{ - int i; - int nVerts = GetVertexCount(); - CTriVertex* pVerts = pVertices; - - for (i = 0; i < nVerts; i++) - { - if (pWeights[i] == 1.0f) - { - const Vec3& vp = pVerts[i].pos; - for (int j = 0; j < nVerts; j++) - { - if (pWeights[j] != 1.0f) - { - if (vp.IsEquivalent(pVerts[j].pos, options.fSoftSelFalloff)) - { - float fDist = vp.GetDistance(pVerts[j].pos); - if (fDist < options.fSoftSelFalloff) - { - float fWeight = 1.0f - (fDist / options.fSoftSelFalloff); - if (fWeight > pWeights[j]) - { - pWeights[j] = fWeight; - } - } - } - } - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CTriMesh::UpdateSelection() -{ - bool bAnySelected = false; - if (selectionType == SO_ELEM_VERTEX) - { - for (int i = 0; i < GetVertexCount(); i++) - { - if (vertSel[i]) - { - bAnySelected = true; - pWeights[i] = 1.0f; - } - else - { - pWeights[i] = 0; - } - } - } - if (selectionType == SO_ELEM_EDGE) - { - // Clear weights. - for (int i = 0; i < GetVertexCount(); i++) - { - pWeights[i] = 0; - } - - for (int i = 0; i < GetEdgeCount(); i++) - { - if (edgeSel[i]) - { - bAnySelected = true; - CTriEdge& edge = pEdges[i]; - for (int j = 0; j < 2; j++) - { - pWeights[edge.v[j]] = 1.0f; - } - } - } - } - else if (selectionType == SO_ELEM_FACE) - { - // Clear weights. - for (int i = 0; i < GetVertexCount(); i++) - { - pWeights[i] = 0; - } - - for (int i = 0; i < GetFacesCount(); i++) - { - if (faceSel[i]) - { - bAnySelected = true; - CTriFace& face = pFaces[i]; - for (int j = 0; j < 3; j++) - { - pWeights[face.v[j]] = 1.0f; - } - } - } - } - return bAnySelected; -} - - -////////////////////////////////////////////////////////////////////////// -bool CTriMesh::ClearSelection() -{ - bool bWasSelected = false; - // Remove all selections. - int i; - for (i = 0; i < GetVertexCount(); i++) - { - pWeights[i] = 0; - } - streamSelMask = 0; - for (int ii = 0; ii < LAST_STREAM; ii++) - { - if (m_streamSel[ii] && !m_streamSel[ii]->is_zero()) - { - bWasSelected = true; - m_streamSel[ii]->clear(); - } - } - return bWasSelected; -} - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::GetEdgesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outEdges) -{ - // Brute force algorithm using binary search. - // for every edge check if edge vertex is inside inVertices array. - std::sort(inVertices.begin(), inVertices.end()); - for (int i = 0; i < GetEdgeCount(); i++) - { - if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pEdges[i].v[0])) != inVertices.end()) - { - outEdges.push_back(i); - } - else if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pEdges[i].v[1])) != inVertices.end()) - { - outEdges.push_back(i); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CTriMesh::GetFacesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outFaces) -{ - // Brute force algorithm using binary search. - // for every face check if face vertex is inside inVertices array. - std::sort(inVertices.begin(), inVertices.end()); - for (int i = 0; i < GetFacesCount(); i++) - { - if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pFaces[i].v[0])) != inVertices.end()) - { - outFaces.push_back(i); - } - else if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pFaces[i].v[1])) != inVertices.end()) - { - outFaces.push_back(i); - } - else if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pFaces[i].v[2])) != inVertices.end()) - { - outFaces.push_back(i); - } - } -} diff --git a/Code/Editor/Geometry/TriMesh.h b/Code/Editor/Geometry/TriMesh.h deleted file mode 100644 index a6c58b8f9d..0000000000 --- a/Code/Editor/Geometry/TriMesh.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_GEOMETRY_TRIMESH_H -#define CRYINCLUDE_EDITOR_GEOMETRY_TRIMESH_H -#pragma once - -#include -#include "Util/bitarray.h" - -struct SSubObjSelOptions; - -typedef std::vector MeshElementsArray; - -////////////////////////////////////////////////////////////////////////// -// Vertex used in the TriMesh. -////////////////////////////////////////////////////////////////////////// -struct CTriVertex -{ - Vec3 pos; - //float weight; // Selection weight in 0-1 range. -}; - -////////////////////////////////////////////////////////////////////////// -// Triangle face used by the Triangle mesh. -////////////////////////////////////////////////////////////////////////// -struct CTriFace -{ - uint32 v[3]; // Indices to vertices array. - uint32 uv[3]; // Indices to texture coordinates array. - Vec3 n[3]; // Vertex normals at face vertices. - Vec3 normal; // Face normal. - uint32 edge[3]; // Indices to the face edges. - unsigned char MatID; // Index of face sub material. - unsigned char flags; // see ETriMeshFlags -}; - -////////////////////////////////////////////////////////////////////////// -// Mesh edge. -////////////////////////////////////////////////////////////////////////// -struct CTriEdge -{ - uint32 v[2]; // Indices to edge vertices. - int face[2]; // Indices to edge faces (-1 if no face). - uint32 flags; // see ETriMeshFlags - - CTriEdge() {} - bool operator==(const CTriEdge& edge) const - { - if ((v[0] == edge.v[0] && v[1] == edge.v[1]) || - (v[0] == edge.v[1] && v[1] == edge.v[0])) - { - return true; - } - return false; - } - bool operator!=(const CTriEdge& edge) const { return !(*this == edge); } - bool operator<(const CTriEdge& edge) const { return (*(uint64*)v < *(uint64*)edge.v); } - bool operator>(const CTriEdge& edge) const { return (*(uint64*)v > *(uint64*)edge.v); } -}; - -////////////////////////////////////////////////////////////////////////// -// Mesh line. -////////////////////////////////////////////////////////////////////////// -struct CTriLine -{ - uint32 v[2]; // Indices to edge vertices. - - CTriLine() {} - bool operator==(const CTriLine& edge) const - { - if ((v[0] == edge.v[0] && v[1] == edge.v[1]) || - (v[0] == edge.v[1] && v[1] == edge.v[0])) - { - return true; - } - return false; - } - bool operator!=(const CTriLine& edge) const { return !(*this == edge); } - bool operator<(const CTriLine& edge) const { return (*(uint64*)v < *(uint64*)edge.v); } - bool operator>(const CTriLine& edge) const { return (*(uint64*)v > *(uint64*)edge.v); } -}; - -////////////////////////////////////////////////////////////////////////// -struct CTriMeshPoly -{ - std::vector v; // Indices to vertices array. - std::vector uv; // Indices to texture coordinates array. - std::vector n; // Vertex normals at face vertices. - Vec3 normal; // Polygon normal. - uint32 edge[3]; // Indices to the face edges. - unsigned char MatID; // Index of face sub material. - unsigned char flags; // optional flags. -}; - -////////////////////////////////////////////////////////////////////////// -// CTriMesh is used in the Editor as a general purpose editable triangle mesh. -////////////////////////////////////////////////////////////////////////// -class CTriMesh -{ -public: - enum EStream - { - VERTICES, - FACES, - EDGES, - TEXCOORDS, - COLORS, - WEIGHTS, - LINES, - WS_POSITIONS, - LAST_STREAM, - }; - enum ECopyFlags - { - COPY_VERTICES = BIT(1), - COPY_FACES = BIT(2), - COPY_EDGES = BIT(3), - COPY_TEXCOORDS = BIT(4), - COPY_COLORS = BIT(5), - COPY_VERT_SEL = BIT(6), - COPY_EDGE_SEL = BIT(7), - COPY_FACE_SEL = BIT(8), - COPY_WEIGHTS = BIT(9), - COPY_LINES = BIT(10), - COPY_ALL = 0xFFFF, - }; - // geometry data - CTriFace* pFaces; - CTriEdge* pEdges; - CTriVertex* pVertices; - SMeshTexCoord* pUV; - SMeshColor* pColors; // If allocated same size as pVerts array. - Vec3* pWSVertices; // World space vertices. - float* pWeights; - CTriLine* pLines; - - int nFacesCount; - int nVertCount; - int nUVCount; - int nEdgeCount; - int nLinesCount; - - AABB bbox; - - ////////////////////////////////////////////////////////////////////////// - // Selections. - ////////////////////////////////////////////////////////////////////////// - CBitArray vertSel; - CBitArray edgeSel; - CBitArray faceSel; - // Every bit of the selection mask correspond to a stream, if bit is set this stream have some elements selected - int streamSelMask; - - // Selection element type. - // see ESubObjElementType - int selectionType; - - ////////////////////////////////////////////////////////////////////////// - // Vertices of the front facing triangles. - CBitArray frontFacingVerts; - - ////////////////////////////////////////////////////////////////////////// - // Functions. - ////////////////////////////////////////////////////////////////////////// - CTriMesh(); - ~CTriMesh(); - - int GetFacesCount() const { return nFacesCount; } - int GetVertexCount() const { return nVertCount; } - int GetUVCount() const { return nUVCount; } - int GetEdgeCount() const { return nEdgeCount; } - int GetLinesCount() const { return nLinesCount; } - - ////////////////////////////////////////////////////////////////////////// - void SetFacesCount(int nNewCount) { ReallocStream(FACES, nNewCount); } - void SetVertexCount(int nNewCount) - { - ReallocStream(VERTICES, nNewCount); - if (pColors) - { - ReallocStream(COLORS, nNewCount); - } - ReallocStream(WEIGHTS, nNewCount); - } - void SetColorsCount(int nNewCount) { ReallocStream(COLORS, nNewCount); } - void SetUVCount(int nNewCount) { ReallocStream(TEXCOORDS, nNewCount); } - void SetEdgeCount(int nNewCount) { ReallocStream(EDGES, nNewCount); } - void SetLinesCount(int nNewCount) { ReallocStream(LINES, nNewCount); } - - void ReallocStream(int stream, int nNewCount); - void GetStreamInfo(int stream, void*& pStream, int& nElementSize) const; - int GetStreamSize(int stream) const { return m_streamSize[stream]; }; - - // Calculate per face normal. - void CalcFaceNormals(); - - ////////////////////////////////////////////////////////////////////////// - // Welding functions. - ////////////////////////////////////////////////////////////////////////// - void SharePositions(); - void ShareUV(); - ////////////////////////////////////////////////////////////////////////// - // Recreate edges of the mesh. - void UpdateEdges(); - - void Copy(CTriMesh& fromMesh, int nCopyFlags = COPY_ALL); - - ////////////////////////////////////////////////////////////////////////// - // Sub-object selection specific methods. - ////////////////////////////////////////////////////////////////////////// - // Return true if something is selected. - bool UpdateSelection(); - // Clear all selections, return true if something was selected. - bool ClearSelection(); - void SoftSelection(const SSubObjSelOptions& options); - CBitArray* GetStreamSelection(int nStream) { return m_streamSel[nStream]; }; - // Returns true if specified stream have any selected elements. - bool StreamHaveSelection(int nStream) { return streamSelMask & (1 << nStream); } - void GetEdgesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outEdges); - void GetFacesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outFaces); - -private: - void* ReAllocElements(void* old_ptr, int new_elem_num, int size_of_element); - void CopyStream(CTriMesh& fromMesh, int stream); - - // For internal use. - int m_streamSize[LAST_STREAM]; - CBitArray* m_streamSel[LAST_STREAM]; -}; - -#endif // CRYINCLUDE_EDITOR_GEOMETRY_TRIMESH_H diff --git a/Code/Editor/IEditor.h b/Code/Editor/IEditor.h index c6f72a7dbc..c91ca62c5e 100644 --- a/Code/Editor/IEditor.h +++ b/Code/Editor/IEditor.h @@ -44,7 +44,6 @@ class CMusicManager; struct IEditorParticleManager; class CEAXPresetManager; class CErrorReport; -class CBaseLibraryItem; class ICommandManager; class CEditorCommandManager; class CHyperGraphManager; @@ -52,9 +51,7 @@ class CConsoleSynchronization; class CUIEnumsDatabase; struct ISourceControl; struct IEditorClassFactory; -struct IDataBaseItem; struct ITransformManipulator; -struct IDataBaseManager; class IFacialEditor; class CDialog; #if defined(AZ_PLATFORM_WINDOWS) @@ -69,7 +66,6 @@ class CSelectionTreeManager; struct SEditorSettings; class CGameExporter; class IAWSResourceManager; -struct IEditorPanelUtils; namespace WinWidget { @@ -83,8 +79,6 @@ struct IEventLoopHook; struct IErrorReport; // Vladimir@conffx struct IFileUtil; // Vladimir@conffx struct IEditorLog; // Vladimir@conffx -struct IEditorMaterialManager; // Vladimir@conffx -struct IBaseLibraryManager; // Vladimir@conffx struct IImageUtil; // Vladimir@conffx struct IEditorParticleUtils; // Leroy@conffx struct ILogFile; // Vladimir@conffx @@ -520,14 +514,8 @@ struct IEditor //! Get access to object manager. virtual struct IObjectManager* GetObjectManager() = 0; virtual CSettingsManager* GetSettingsManager() = 0; - //! Get DB manager that own items of specified type. - virtual IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType) = 0; - virtual IBaseLibraryManager* GetMaterialManagerLibrary() = 0; // Vladimir@conffx - virtual IEditorMaterialManager* GetIEditorMaterialManager() = 0; // Vladimir@Conffx //! Returns IconManager. virtual IIconManager* GetIconManager() = 0; - //! Get Panel Editor Utilities - virtual IEditorPanelUtils* GetEditorPanelUtils() = 0; //! Get Music Manager. virtual CMusicManager* GetMusicManager() = 0; virtual float GetTerrainElevation(float x, float y) = 0; diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index 5bd816174c..38006c6fca 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -81,9 +81,6 @@ AZ_POP_DISABLE_WARNING // AWSNativeSDK #include -#include "IEditorPanelUtils.h" -#include "EditorPanelUtils.h" - #include "Core/QtEditorApplication.h" // for Editor::EditorQtApplication static CCryEditDoc * theDocument; @@ -143,7 +140,6 @@ CEditorImpl::CEditorImpl() , m_QtApplication(static_cast(qApp)) , m_pImageUtil(nullptr) , m_pLogFile(nullptr) - , m_panelEditorUtils(nullptr) { // note that this is a call into EditorCore.dll, which stores the g_pEditorPointer for all shared modules that share EditorCore.dll // this means that they don't need to do SetIEditor(...) themselves and its available immediately @@ -167,8 +163,6 @@ CEditorImpl::CEditorImpl() m_pDisplaySettings->LoadRegistry(); m_pPluginManager = new CPluginManager; - m_panelEditorUtils = CreateEditorPanelUtils(); - m_pObjectManager = new CObjectManager; m_pViewManager = new CViewManager; m_pIconManager = new CIconManager; @@ -301,8 +295,6 @@ CEditorImpl::~CEditorImpl() SAFE_DELETE(m_pViewManager) SAFE_DELETE(m_pObjectManager) // relies on prefab manager - SAFE_DELETE(m_panelEditorUtils); - // some plugins may be exporter - this must be above plugin manager delete. SAFE_DELETE(m_pExportManager); @@ -900,11 +892,6 @@ void CEditorImpl::CloseView(const GUID& classId) } } -IDataBaseManager* CEditorImpl::GetDBItemManager([[maybe_unused]] EDataBaseItemType itemType) -{ - return nullptr; -} - bool CEditorImpl::SelectColor(QColor& color, QWidget* parent) { const AZ::Color c = AzQtComponents::fromQColor(color); @@ -1632,18 +1619,6 @@ SEditorSettings* CEditorImpl::GetEditorSettings() return &gSettings; } -// Vladimir@Conffx -IBaseLibraryManager* CEditorImpl::GetMaterialManagerLibrary() -{ - return nullptr; -} - -// Vladimir@Conffx -IEditorMaterialManager* CEditorImpl::GetIEditorMaterialManager() -{ - return nullptr; -} - IImageUtil* CEditorImpl::GetImageUtil() { return m_pImageUtil; @@ -1658,8 +1633,3 @@ void CEditorImpl::DestroyQMimeData(QMimeData* data) const { delete data; } - -IEditorPanelUtils* CEditorImpl::GetEditorPanelUtils() -{ - return m_panelEditorUtils; -} diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index 4976c0c1ca..7867912941 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -157,7 +157,6 @@ public: void LockSelection(bool bLock) override; bool IsSelectionLocked() override; - IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType) override; CMusicManager* GetMusicManager() override { return m_pMusicManager; }; IEditorFileMonitor* GetFileMonitor() override; @@ -294,11 +293,8 @@ public: void RegisterObjectContextMenuExtension(TContextMenuExtensionFunc func) override; SSystemGlobalEnvironment* GetEnv() override; - IBaseLibraryManager* GetMaterialManagerLibrary() override; // Vladimir@Conffx - IEditorMaterialManager* GetIEditorMaterialManager() override; // Vladimir@Conffx IImageUtil* GetImageUtil() override; // Vladimir@conffx SEditorSettings* GetEditorSettings() override; - IEditorPanelUtils* GetEditorPanelUtils() override; ILogFile* GetLogFile() override { return m_pLogFile; } void UnloadPlugins() override; @@ -356,7 +352,6 @@ protected: CErrorsDlg* m_pErrorsDlg; //! Source control interface. ISourceControl* m_pSourceControl; - IEditorPanelUtils* m_panelEditorUtils; CSelectionTreeManager* m_pSelectionTreeManager; diff --git a/Code/Editor/IEditorPanelUtils.h b/Code/Editor/IEditorPanelUtils.h deleted file mode 100644 index 4649213ae7..0000000000 --- a/Code/Editor/IEditorPanelUtils.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 - */ - -#ifndef CRYINCLUDE_CRYEDITOR_IPANELEDITORUTILS_H -#define CRYINCLUDE_CRYEDITOR_IPANELEDITORUTILS_H -#pragma once - -#include "Cry_Vector3.h" - -#include "DisplaySettings.h" -#include "Include/IDisplayViewport.h" -#include "Include/IIconManager.h" -#include -#include -#include -#include - -class CBaseObject; -class CViewport; -class IQToolTip; - -struct HotKey -{ - HotKey() - : path("") - , sequence(QKeySequence()) - { - } - void CopyFrom(const HotKey& other) - { - path = other.path; - sequence = other.sequence; - } - void SetPath(const char* _path) - { - path = QString(_path); - } - void SetSequenceFromString(const char* _sequence) - { - sequence = QKeySequence::fromString(_sequence); - } - void SetSequence(const QKeySequence& other) - { - sequence = other; - } - bool IsMatch(QString _path) - { - return path.compare(_path, Qt::CaseInsensitive) == 0; - } - bool IsMatch(QKeySequence _sequence) - { - return sequence.matches(_sequence); - } - bool operator < (const HotKey& other) const - { - //split the paths into lists compare per level - QStringList m_categories = path.split('.'); - QStringList o_categories = other.path.split('.'); - int m_catSize = m_categories.size(); - int o_catSize = o_categories.size(); - int size = (m_catSize < o_catSize) ? m_catSize : o_catSize; - - //sort categories to keep them together - for (int i = 0; i < size; i++) - { - if (m_categories[i] < o_categories[i]) - { - return true; - } - if (m_categories[i] > o_categories[i]) - { - return false; - } - } - //if comparing a category and a item in that category the category is < item - return m_catSize > o_catSize; - } - QKeySequence sequence; - QString path; -}; - -struct IEditorPanelUtils -{ - virtual ~IEditorPanelUtils() {} - virtual void SetViewportDragOperation(void(*)(CViewport* viewport, int dragPointX, int dragPointY, void* custom), void* custom) = 0; - - //PREVIEW WINDOW UTILS//////////////////////////////////////////////////// - virtual int PreviewWindow_GetDisplaySettingsDebugFlags(CDisplaySettings* settings) = 0; - virtual void PreviewWindow_SetDisplaySettingsDebugFlags(CDisplaySettings* settings, int flags) = 0; - - //HOTKEY UTILS//////////////////////////////////////////////////////////// - virtual bool HotKey_Import() = 0; - virtual void HotKey_Export() = 0; - virtual QKeySequence HotKey_GetShortcut(const char* path) = 0; - virtual bool HotKey_IsPressed(const QKeyEvent* event, const char* path) = 0; - virtual bool HotKey_IsPressed(const QShortcutEvent* event, const char* path) = 0; - virtual bool HotKey_LoadExisting() = 0; - virtual void HotKey_SaveCurrent() = 0; - virtual void HotKey_BuildDefaults() = 0; - virtual void HotKey_SetKeys(QVector keys) = 0; - virtual QVector HotKey_GetKeys() = 0; - virtual QString HotKey_GetPressedHotkey(const QKeyEvent* event) = 0; - virtual QString HotKey_GetPressedHotkey(const QShortcutEvent* event) = 0; - virtual void HotKey_SetEnabled(bool val) = 0; - virtual bool HotKey_IsEnabled() const = 0; - - //TOOLTIP UTILS/////////////////////////////////////////////////////////// - - //! Loads a table of tooltip configuration data from an xml file. - virtual void ToolTip_LoadConfigXML(QString filepath) = 0; - - //! Initializes a QToolTipWidget from loaded configuration data (see ToolTip_LoadConfigXML()) - //! \param tooltip Will be initialized using loaded configuration data - //! \param path Variable serialization path. Will be used as the key for looking up data in the configuration table. (ex: "Rotation.Rotation_Rate_X") - //! \param option Name of a sub-option of the variable specified by "path". (ex: "Emitter_Strength" will look up the tooltip data for "Rotation.Rotation_Rate_X.Emitter_Strength") - //! \param optionalData The argument to be used with "special_content" feature. See ToolTip_GetSpecialContentType() and QToolTipWidget::AddSpecialContent(). - //! \param isEnabled If false, the tooltip will indicate the reason why the widget is disabled. - virtual void ToolTip_BuildFromConfig(IQToolTip* tooltip, QString path, QString option, QString optionalData = "", bool isEnabled = true) = 0; - - virtual QString ToolTip_GetTitle(QString path, QString option = "") = 0; - virtual QString ToolTip_GetContent(QString path, QString option = "") = 0; - virtual QString ToolTip_GetSpecialContentType(QString path, QString option = "") = 0; - virtual QString ToolTip_GetDisabledContent(QString path, QString option = "") = 0; -}; - - -#endif diff --git a/Code/Editor/Include/HitContext.h b/Code/Editor/Include/HitContext.h index ceff0adb22..b49117bb60 100644 --- a/Code/Editor/Include/HitContext.h +++ b/Code/Editor/Include/HitContext.h @@ -17,7 +17,6 @@ class CGizmo; class CBaseObject; struct IDisplayViewport; -class CDeepSelection; struct AABB; #include @@ -105,8 +104,6 @@ struct HitContext CBaseObject* object; //! gizmo object that have been hit. CGizmo* gizmo; - //! for deep selection mode - CDeepSelection* pDeepSelection; //! For linking tool const char* name; //! true if this hit was from the object icon @@ -131,7 +128,6 @@ struct HitContext bIgnoreAxis = false; bOnlyGizmo = false; bUseSelectionHelpers = false; - pDeepSelection = 0; name = nullptr; iconHit = false; } diff --git a/Code/Editor/Include/IAnimationCompressionManager.h b/Code/Editor/Include/IAnimationCompressionManager.h deleted file mode 100644 index 64cebf620a..0000000000 --- a/Code/Editor/Include/IAnimationCompressionManager.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IANIMATIONCOMPRESSIONMANAGER_H -#define CRYINCLUDE_EDITOR_INCLUDE_IANIMATIONCOMPRESSIONMANAGER_H -#pragma once - -struct IAnimationCompressionManager -{ - virtual bool IsEnabled() const = 0; - virtual void UpdateLocalAnimations() = 0; -}; - -#endif // CRYINCLUDE_EDITOR_INCLUDE_IANIMATIONCOMPRESSIONMANAGER_H diff --git a/Code/Editor/Include/IAssetItem.h b/Code/Editor/Include/IAssetItem.h deleted file mode 100644 index ff80331af5..0000000000 --- a/Code/Editor/Include/IAssetItem.h +++ /dev/null @@ -1,433 +0,0 @@ -/* - * 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 - * - */ - - -// Description : Standard interface for asset display in the asset browser, -// this header should be used to create plugins. -// The method Release of this interface should NOT be called. -// Instead, the FreeData from the database (from IAssetItemDatabase) should -// be used as it will safely release all the items from the database. -// It is still possible to call the release method, but this is not the -// recomended method, specially for usage outside of the plugins because there -// is no guarantee that a the asset will be properly removed from the database -// manager. - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IASSETITEM_H -#define CRYINCLUDE_EDITOR_INCLUDE_IASSETITEM_H -#pragma once - -struct IAssetItemDatabase; - -namespace AssetViewer -{ - // Used in GetAssetFieldValue for each asset type to check if field name is the right one - inline bool IsFieldName(const char* pIncomingFieldName, const char* pFieldName) - { - return !strncmp(pIncomingFieldName, pFieldName, strlen(pIncomingFieldName)); - } -} - -// Description: -// This interface allows the programmer to extend asset display types visible in the asset browser. -struct IAssetItem - : public IUnknown -{ - DEFINE_UUID(0x04F20346, 0x2EC3, 0x43f2, 0xBD, 0xA1, 0x2C, 0x0B, 0x97, 0x76, 0xF3, 0x84); - - // The supported asset flags - enum EAssetFlags - { - // asset is visible in the database for filtering and sorting (not asset view control related) - eFlag_Visible = BIT(0), - // the asset is loaded - eFlag_Loaded = BIT(1), - // the asset is loaded - eFlag_Cached = BIT(2), - // the asset is selected in a selection set - eFlag_Selected = BIT(3), - // this asset is invalid, no thumb is shown/available - eFlag_Invalid = BIT(4), - // this asset has some errors/warnings, in the asset browser it will show some blinking/red elements - // and the user can check out the errors. Error text will be fetched using GetAssetFieldValue( "errors", &someStringVar ) - eFlag_HasErrors = BIT(5), - // this flag is set when the asset is rendering its contents using GDI, and not the engine's rendering capabilities - // (this flags is used as hint for the preview tool, which will use a double-buffer canvas if this flag is set, - // and send a memory HDC to the OnBeginPreview method, for drawing of the asset) - eFlag_UseGdiRendering = BIT(6), - // set if this asset is draggable into the render viewports, and can be created there - eFlag_CanBeDraggedInViewports = BIT(7), - // set if this asset can be moved after creation, otherwise the asset instance will just be created where user clicked - eFlag_CanBeMovedAfterDroppedIntoViewport = BIT(8), - // the asset thumbnail image is loaded - eFlag_ThumbnailLoaded = BIT(9), - // the asset thumbnail image is loaded - eFlag_UsedInLevel = BIT(10) - }; - - // Asset field name and field values map - typedef std::map < QString/*fieldName*/, QString/*value*/ > TAssetFieldValuesMap; - // Dependency category names and corresponding files map, example: "Textures"=>{ "foam.dds","water.dds","normal.dds" } - typedef std::map < QString/*dependencyCategory*/, std::set/*dependency filenames*/ > TAssetDependenciesMap; - - virtual ~IAssetItem() { - } - - // Description: - // Get the hash number/key used for database thumbnail and info records management - virtual uint32 GetHash() const = 0; - // Description: - // Set the hash number/key used for database thumbnail and info records management - virtual void SetHash(uint32 hash) = 0; - // Description: - // Get the owner database for this asset - // Return Value: - // The owner database for this asset - // See Also: - // SetOwnerDatabase() - virtual IAssetItemDatabase* GetOwnerDatabase() const = 0; - // Description: - // Set the owner database for this asset - // Arguments: - // piOwnerDisplayDatabase - the owner database - // See Also: - // GetOwnerDatabase() - virtual void SetOwnerDatabase(IAssetItemDatabase* pOwnerDisplayDatabase) = 0; - // Description: - // Get the asset's dependency files / objects - // Return Value: - // The vector with filenames which this asset is dependent upon, ex.: ["Textures"].(vector of textures) - virtual const TAssetDependenciesMap& GetDependencies() const = 0; - // Description: - // Set the file size of this asset in bytes - // Arguments: - // aSize - size of the file in bytes - // See Also: - // GetFileSize() - virtual void SetFileSize(quint64 aSize) = 0; - // Description: - // Get the file size of this asset in bytes - // Return Value: - // The file size of this asset in bytes - // See Also: - // SetFileSize() - virtual quint64 GetFileSize() const = 0; - // Description: - // Set asset filename (extension included and no path) - // Arguments: - // pName - the asset filename (extension included and no path) - // See Also: - // GetFilename() - virtual void SetFilename(const char* pName) = 0; - // Description: - // Get asset filename (extension included and no path) - // Return Value: - // The asset filename (extension included and no path) - // See Also: - // SetFilename() - virtual QString GetFilename() const = 0; - // Description: - // Set the asset's relative path - // Arguments: - // pName - file's relative path - // See Also: - // GetRelativePath() - virtual void SetRelativePath(const char* pName) = 0; - // Description: - // Get the asset's relative path - // Return Value: - // The asset's relative path - // See Also: - // SetRelativePath() - virtual QString GetRelativePath() const = 0; - // Description: - // Set the file extension ( dot(s) must be included ) - // Arguments: - // pExt - the file's extension - // See Also: - // GetFileExtension() - virtual void SetFileExtension(const char* pExt) = 0; - // Description: - // Get the file extension ( dot(s) included ) - // Return Value: - // The file extension ( dot(s) included ) - // See Also: - // SetFileExtension() - virtual QString GetFileExtension() const = 0; - // Description: - // Get the asset flags, with values from IAssetItem::EAssetFlags - // Return Value: - // The asset flags, with values from IAssetItem::EAssetFlags - // See Also: - // SetFlags(), SetFlag(), IsFlagSet() - virtual UINT GetFlags() const = 0; - // Description: - // Set the asset flags - // Arguments: - // aFlags - flags, OR-ed values from IAssetItem::EAssetFlags - // See Also: - // GetFlags(), SetFlag(), IsFlagSet() - virtual void SetFlags(UINT aFlags) = 0; - // Description: - // Set/clear a single flag bit for the asset - // Arguments: - // aFlag - the flag to set/clear, with values from IAssetItem::EAssetFlags - // See Also: - // GetFlags(), SetFlags(), IsFlagSet() - virtual void SetFlag(EAssetFlags aFlag, bool bSet = true) = 0; - // Description: - // Check if a specified flag is set - // Arguments: - // aFlag - the flag to check, with values from IAssetItem::EAssetFlags - // Return Value: - // True if the flag is set - // See Also: - // GetFlags(), SetFlags(), SetFlag() - virtual bool IsFlagSet(EAssetFlags aFlag) const = 0; - // Description: - // Set this asset's index; used in sorting, selections, and to know where an asset is in the current list - // Arguments: - // aIndex - the asset's index - // See Also: - // GetIndex() - virtual void SetIndex(UINT aIndex) = 0; - // Description: - // Get the asset's index in the current list - // Return Value: - // The asset's index in the current list - // See Also: - // SetIndex() - virtual UINT GetIndex() const = 0; - // Description: - // Get the asset's field raw data value into a user location, you must check the field's type ( from asset item's owner database ) - // before using this function and send the correct pointer to destination according to the type ( int8, float32, string, etc. ) - // Arguments: - // pFieldName - the asset field name to query the value for - // pDest - the destination variable address, must be the same type as the field type - // Return Value: - // True if the asset field name is found and the value is returned correctly - // See Also: - // SetAssetFieldValue() - virtual QVariant GetAssetFieldValue(const char* pFieldName) const = 0; - // Description: - // Set the asset's field raw data value from a user location, you must check the field's type ( from asset item's owner database ) - // before using this function and send the correct pointer to source according to the type ( int8, float32, string, etc. ) - // Arguments: - // pFieldName - the asset field name to set the value for - // pSrc - the source variable address, must be the same type as the field type - // Return Value: - // True if the asset field name is found and the value is set correctly - // See Also: - // GetAssetFieldValue() - virtual bool SetAssetFieldValue(const char* pFieldName, void* pSrc) = 0; - // Description: - // Get the drawing rectangle for the asset's thumb ( absolute viewer canvas location ) - // Arguments: - // rstDrawingRectangle - destination location to set with the asset's thumbnail rectangle location - // See Also: - // SetDrawingRectangle() - virtual void GetDrawingRectangle(QRect& rstDrawingRectangle) const = 0; - // Description: - // Set the drawing rectangle for the asset's thumb ( absolute viewer canvas location ) - // Arguments: - // crstDrawingRectangle - source to set the asset's thumbnail rectangle - // See Also: - // GetDrawingRectangle() - virtual void SetDrawingRectangle(const QRect& crstDrawingRectangle) = 0; - // Description: - // Checks if the given 2D point is inside the asset's thumb rectangle - // Arguments: - // nX - mouse pointer position on X axis, relative to the asset viewer control - // nY - mouse pointer position on Y axis, relative to the asset viewer control - // Return Value: - // True if the given 2D point is inside the asset's thumb rectangle - // See Also: - // HitTest(CRect) - virtual bool HitTest(int nX, int nY) const = 0; - // Description: - // Checks if the given rectangle intersects the asset thumb's rectangle - // Arguments: - // nX - mouse pointer position on X axis, relative to the asset viewer control - // nY - mouse pointer position on Y axis, relative to the asset viewer control - // Return Value: - // True if the given rectangle intersects the asset thumb's rectangle - // See Also: - // HitTest(int nX,int nY) - virtual bool HitTest(const QRect& roTestRect) const = 0; - // Description: - // When user drags this asset item into a viewport, this method is called when the dragging operation ends - // and the mouse button is released, for the asset to return an instance of the asset object to be placed in the level - // Arguments: - // aX - instance's X position component in world coordinates - // aY - instance's Y position component in world coordinates - // aZ - instance's Z position component in world coordinates - // Return Value: - // The newly created asset instance (Example: BrushObject*) - // See Also: - // MoveInstanceInViewport() - virtual void* CreateInstanceInViewport(float aX, float aY, float aZ) = 0; - // Description: - // When the mouse button is released after level object creation, the user now can move the mouse - // and move the asset instance in the 3D world - // Arguments: - // pDraggedObject - the actual entity or brush object (CBaseObject* usually) to be moved around with the mouse - // returned by the CreateInstanceInViewport() - // aNewX - the new X world coordinates of the asset instance - // aNewY - the new Y world coordinates of the asset instance - // aNewZ - the new Z world coordinates of the asset instance - // Return Value: - // True if asset instance was moved properly - // See Also: - // CreateInstanceInViewport() - virtual bool MoveInstanceInViewport(const void* pDraggedObject, float aNewX, float aNewY, float aNewZ) = 0; - // Description: - // This will be called when the user presses ESCAPE key when dragging the asset in the viewport, you must delete the given object - // because the creation was aborted - // Arguments: - // pDraggedObject - the asset instance to be deleted ( you must cast to the needed type, and delete it properly ) - // See Also: - // CreateInstanceInViewport() - virtual void AbortCreateInstanceInViewport(const void* pDraggedObject) = 0; - // Description: - // This method is used to cache/load asset's data, so it can be previewed/rendered - // Return Value: - // True if the asset was successfully cached - // See Also: - // UnCache() - virtual bool Cache() = 0; - // Description: - // This method is used to force cache/load asset's data, so it can be previewed/rendered - // Return Value: - // True if the asset was successfully forced cached - // See Also: - // UnCache(), Cache() - virtual bool ForceCache() = 0; - // Description: - // This method is used to load the thumbnail image of the asset - // Return Value: - // True if thumb loaded ok - // See Also: - // UnloadThumbnail() - virtual bool LoadThumbnail() = 0; - // Description: - // This method is used to unload the thumbnail image of the asset - // See Also: - // LoadThumbnail() - virtual void UnloadThumbnail() = 0; - // Description: - // This is called when the asset starts to be previewed in full detail, so here you can load the whole asset, in fine detail - // ( textures are fully loaded, models etc. ). It is called once, when the Preview dialog is shown - // Arguments: - // hPreviewWnd - the window handle of the quick preview dialog - // hMemDC - the memory DC used to render assets that can render themselves in the DC, otherwise they will render in the dialog's HWND - // See Also: - // OnEndPreview(), GetCustomPreviewPanelHeader() - virtual void OnBeginPreview(QWidget* hPreviewWnd) = 0; - // Description: - // Called when the Preview dialog is closed, you may release the detail asset data here - // See Also: - // OnBeginPreview(), GetCustomPreviewPanelHeader() - virtual void OnEndPreview() = 0; - // Description: - // If the asset has a special preview panel with utility controls, to be placed at the top of the Preview window, it can return an child dialog window - // otherwise it can return nullptr, if no panel is available - // Arguments: - // pParentWnd - a valid CDialog*, or nullptr - // Return Value: - // A valid child dialog window handle, if this asset wants to have a custom panel in the top side of the Asset Preview window, - // otherwise it can return nullptr, if no panel is available - // See Also: - // OnBeginPreview(), OnEndPreview() - virtual QWidget* GetCustomPreviewPanelHeader(QWidget* pParentWnd) = 0; - virtual QWidget* GetCustomPreviewPanelFooter(QWidget* pParentWnd) = 0; - // Description: - // Used when dragging/rotate/zoom a model, or other asset that can support preview - // Arguments: - // hRenderWindow - the rendering window handle - // rstViewport - the viewport rectangle - // aMouseX - the render window relative mouse pointer X coordinate - // aMouseY - the render window relative mouse pointer Y coordinate - // aMouseDeltaX - the X coordinate delta between two mouse movements - // aMouseDeltaY - the Y coordinate delta between two mouse movements - // aMouseWheelDelta - the mouse wheel scroll delta/step - // aKeyFlags - the key flags, see WM_LBUTTONUP - // See Also: - // OnPreviewRenderKeyEvent() - virtual void PreviewRender( - QWidget* hRenderWindow, - const QRect& rstViewport, - int aMouseX = 0, int aMouseY = 0, - int aMouseDeltaX = 0, int aMouseDeltaY = 0, - int aMouseWheelDelta = 0, UINT aKeyFlags = 0) = 0; - // Description: - // This is called when the user manipulates the assets in interactive render and a key is pressed ( with down or up state ) - // Arguments: - // bKeyDown - true if this is a WM_KEYDOWN event, else it is a WM_KEYUP event - // aChar - the char/key code pressed/released - // aKeyFlags - the key flags, compatible with WM_KEYDOWN/UP events - // See Also: - // InteractiveRender() - virtual void OnPreviewRenderKeyEvent(bool bKeyDown, UINT aChar, UINT aKeyFlags) = 0; - // Description: - // Called when user clicked once on the thumb image - // Arguments: - // point - mouse coordinates relative to the thumbnail rectangle - // aKeyFlags - the key flags, see WM_LBUTTONDOWN - // See Also: - // OnThumbDblClick() - virtual void OnThumbClick(const QPoint& point, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) = 0; - // Description: - // Called when user double clicked on the thumb image - // Arguments: - // point - mouse coordinates relative to the thumbnail rectangle - // aKeyFlags - the key flags, see WM_LBUTTONDOWN - // See Also: - // OnThumbClick() - //! called when user clicked twice on the thumb image - virtual void OnThumbDblClick(const QPoint& point, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) = 0; - // Description: - // Draw the cached thumb bitmap only, if any, no other kind of rendering - // Arguments: - // hDC - the destination DC, where to draw the thumb - // rRect - the destination rectangle - // Return Value: - // True if drawing of the thumbnail was done OK - // See Also: - // Render() - virtual bool DrawThumbImage(QPainter* painter, const QRect& rRect) = 0; - // Description: - // Writes asset info to a XML node. - // This is needed to save cached info as a persistent XML file for the next run of the editor. - // Arguments: - // node - An XML node to contain the info - // See Also: - // FromXML() - virtual void ToXML(XmlNodeRef& node) const = 0; - // Description: - // Gets asset info from a XML node. - // This is needed to get the asset info from previous runs of the editor without re-caching it. - // Arguments: - // node - An XML node that contains info for this asset - // See Also: - // ToXML() - virtual void FromXML(const XmlNodeRef& node) = 0; - - // From IUnknown - virtual HRESULT STDMETHODCALLTYPE QueryInterface([[maybe_unused]] const IID& riid, [[maybe_unused]] void** ppvObject) - { - return E_NOINTERFACE; - }; - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return 0; - }; - virtual ULONG STDMETHODCALLTYPE Release() - { - return 0; - }; -}; -#endif // CRYINCLUDE_EDITOR_INCLUDE_IASSETITEM_H diff --git a/Code/Editor/Include/IAssetItemDatabase.h b/Code/Editor/Include/IAssetItemDatabase.h deleted file mode 100644 index 39fd60e8c6..0000000000 --- a/Code/Editor/Include/IAssetItemDatabase.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * 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 - * - */ - - -// Description : Standard interface for asset database creators used to -// create an asset plugin for the asset browser -// The category of the plugin must be Asset Item DB - - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IASSETITEMDATABASE_H -#define CRYINCLUDE_EDITOR_INCLUDE_IASSETITEMDATABASE_H -#pragma once -struct IAssetItem; -struct IAssetViewer; - -class QString; -class QStringList; - -// Description: -// This struct keeps the info, filter and sorting settings for an asset field -struct SAssetField -{ - // the condition for the current filter on the field - enum EAssetFilterCondition - { - eCondition_Any = 0, - // string conditions - // this also supports '*' and '?' as wildcards inside text - eCondition_Contains, - // this filter will search the target for at least one of the words specified - // ( ex: filter: "water car moon" , field value : "the_great_moon.dds", this will pass the test - // it also supports '*' and '?' as wildcards inside words text - eCondition_ContainsOneOfTheWords, - eCondition_StartsWith, - eCondition_EndsWith, - // string & numerical conditions - eCondition_Equal, - eCondition_Greater, - eCondition_Less, - eCondition_GreaterOrEqual, - eCondition_LessOrEqual, - eCondition_Not, - eCondition_InsideRange - }; - - // the asset field type - enum EAssetFieldType - { - eType_None = 0, - eType_Bool, - eType_Int8, - eType_Int16, - eType_Int32, - eType_Int64, - eType_Float, - eType_Double, - eType_String - }; - - // used when a field can have different specific values - typedef QStringList TFieldEnumValues; - - SAssetField( - const char* pFieldName = "", - const char* pDisplayName = "Unnamed field", - EAssetFieldType aFieldType = eType_None, - UINT aColumnWidth = 50, - bool bVisibleInUI = true, - bool bReadOnly = true) - { - m_fieldName = pFieldName; - m_displayName = pDisplayName; - m_fieldType = aFieldType; - m_filterCondition = eCondition_Equal; - m_bUseEnumValues = false; - m_bReadOnly = bReadOnly; - m_listColumnWidth = aColumnWidth; - m_bFieldVisibleInUI = bVisibleInUI; - m_bPostFilter = false; - - SetupEnumValues(); - } - - void SetupEnumValues() - { - m_bUseEnumValues = true; - - if (m_fieldType == eType_Bool) - { - m_enumValues.clear(); - m_enumValues.push_back("Yes"); - m_enumValues.push_back("No"); - } - } - - // the field's display name, used in UI - QString m_displayName, - // the field internal name, used in C++ code - m_fieldName, - // the current filter value, if its empty "" then no filter is applied - m_filterValue, - // the field's max value, valid when the field's filter condition is eAssertFilterCondition_InsideRange - m_maxFilterValue, - // the name of the database holding this field, used in Asset Browser preset editor, if its "" then the field - // is common to all current databases - m_parentDatabaseName; - // is this field visible in the UI ? - bool m_bFieldVisibleInUI, - // if true, then you cannot modify this field of an asset item, only use it - m_bReadOnly, - // this field filter is applied after the other filters - m_bPostFilter; - // the field data type - EAssetFieldType m_fieldType; - // the filter's condition - EAssetFilterCondition m_filterCondition; - // use the enum list values to choose a value for the field ? - bool m_bUseEnumValues; - // this map is used when asset field has m_bUseEnumValues on true, - // choose a value for the field from this list in the UI - TFieldEnumValues m_enumValues; - // recommended list column width - unsigned int m_listColumnWidth; -}; - -struct SFieldFiltersPreset -{ - QString presetName2; - QStringList checkedDatabaseNames; - bool bUsedInLevel; - std::vector fields; -}; - -// Description: -// This interface allows the programmer to extend asset display types -// visible in the asset browser. -struct IAssetItemDatabase - : public IUnknown -{ - DEFINE_UUID(0xFB09B039, 0x1D9D, 0x4057, 0xA5, 0xF0, 0xAA, 0x3C, 0x7B, 0x97, 0xAE, 0xA8) - - typedef std::vector TAssetFields; - typedef std::map < QString/*field name*/, SAssetField > TAssetFieldFiltersMap; - typedef std::map < QString/*asset filename*/, IAssetItem* > TFilenameAssetMap; - typedef AZStd::function MetaDataChangeListener; - - // Description: - // Refresh the database by scanning the folders/paks for files, does not load the files, only filename and filesize are fetched - virtual void Refresh() = 0; - // Description: - // Fills the asset meta data from the loaded xml meta data DB. - // Arguments: - // db - the database XML node from where to cache the info - virtual void PrecacheFieldsInfoFromFileDB(const XmlNodeRef& db) = 0; - // Description: - // Return all assets loaded/scanned by this database - // Return Value: - // The assets map reference (filename-asset) - virtual TFilenameAssetMap& GetAssets() = 0; - // Description: - // Get an asset item by its filename - // Return Value: - // A single asset from the database given the filename - virtual IAssetItem* GetAsset(const char* pAssetFilename) = 0; - // Description: - // Return the asset fields this database's items support - // Return Value: - // The asset fields vector reference - virtual TAssetFields& GetAssetFields() = 0; - // Description: - // Return an asset field object pointer by the field internal name - // Arguments: - // pFieldName - the internal field's name (ex: "filename", "relativepath") - // Return Value: - // The asset field object pointer - virtual SAssetField* GetAssetFieldByName(const char* pFieldName) = 0; - // Description: - // Get the database name - // Return Value: - // Returns the database name, ex: "Textures" - virtual const char* GetDatabaseName() const = 0; - // Description: - // Get the database supported file name extension(s) - // Return Value: - // Returns the supported extensions, separated by comma, ex: "tga,bmp,dds" - virtual const char* GetSupportedExtensions() const = 0; - // Description: - // Free the database internal data structures - virtual void FreeData() = 0; - // Description: - // Apply filters to this database which will set/unset the IAssetItem::eAssetFlag_Visible of each asset, based - // on the given field filters - // Arguments: - // rFieldFilters - a reference to the field filters map (fieldname-field) - // See Also: - // ClearFilters() - virtual void ApplyFilters(const TAssetFieldFiltersMap& rFieldFilters) = 0; - // Description: - // Clear the current filters, by setting the IAssetItem::eAssetFlag_Visible of each asset to true - // See Also: - // ApplyFilters() - virtual void ClearFilters() = 0; - virtual QWidget* CreateDbFilterDialog(QWidget* pParent, IAssetViewer* pViewerCtrl) = 0; - virtual void UpdateDbFilterDialogUI(QWidget* pDlg) = 0; - virtual void OnAssetBrowserOpen() = 0; - virtual void OnAssetBrowserClose() = 0; - // Description: - // Gets the filename for saving new cached asset info. - // Return Value: - // A file name to save new transactions to the persistent asset info DB - // See Also: - // CAssetInfoFileDB, IAssetItem::ToXML(), IAssetItem::FromXML() - virtual const char* GetTransactionFilename() const = 0; - // Description: - // Adds a callback to be called when the meta data of this asset changed. - // Arguments: - // callBack - A functor to be added - // Return Value: - // True if successful, false otherwise. - // See Also: - // RemoveMetaDataChangeListener() - virtual bool AddMetaDataChangeListener(MetaDataChangeListener callBack) = 0; - // Description: - // Removes a callback from the list of meta data change listeners. - // Arguments: - // callBack - A functor to be removed - // Return Value: - // True if successful, false otherwise. - // See Also: - // AddMetaDataCHangeListener() - virtual bool RemoveMetaDataChangeListener(MetaDataChangeListener callBack) = 0; - // Description: - // The method that should be called when the meta data of an asset item changes to notify all listeners - // Arguments: - // pAssetItem - An asset item whose meta data have changed - // See Also: - // AddMetaDataCHangeListener(), RemoveMetaDataChangeListener() - virtual void OnMetaDataChange(const IAssetItem* pAssetItem) = 0; - - //! from IUnknown - virtual HRESULT STDMETHODCALLTYPE QueryInterface([[maybe_unused]] REFIID riid, [[maybe_unused]] void** ppvObject) - { - return E_NOINTERFACE; - }; - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return 0; - }; - virtual ULONG STDMETHODCALLTYPE Release() - { - return 0; - }; -}; -#endif // CRYINCLUDE_EDITOR_INCLUDE_IASSETITEMDATABASE_H diff --git a/Code/Editor/Include/IAssetViewer.h b/Code/Editor/Include/IAssetViewer.h deleted file mode 100644 index 488ee8e508..0000000000 --- a/Code/Editor/Include/IAssetViewer.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 - * - */ - - -// Description : This file declares a control which objective is to display -// multiple assets allowing selection and preview of such things -// It also handles scrolling and changes in the thumbnail display size - - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IASSETVIEWER_H -#define CRYINCLUDE_EDITOR_INCLUDE_IASSETVIEWER_H -#pragma once -#include "IObservable.h" -#include "IAssetItemDatabase.h" - -struct IAssetItem; -struct IAssetItemDatabase; - -// Description: -// Observer for the asset viewer events -struct IAssetViewerObserver -{ - virtual void OnChangeStatusBarInfo(UINT nSelectedItems, UINT nVisibleItems, UINT nTotalItems) {}; - virtual void OnSelectionChanged() {}; - virtual void OnChangedPreviewedAsset(IAssetItem* pAsset) {}; - virtual void OnAssetDblClick(IAssetItem* pAsset) {}; - virtual void OnAssetFilterChanged() {}; -}; - -// Description: -// The asset viewer interface for the asset database plugins to use -struct IAssetViewer -{ - DEFINE_OBSERVABLE_PURE_METHODS(IAssetViewerObserver); - - virtual HWND GetRenderWindow() = 0; - virtual void ApplyFilters(const IAssetItemDatabase::TAssetFieldFiltersMap& rFieldFilters) = 0; - virtual const IAssetItemDatabase::TAssetFieldFiltersMap& GetCurrentFilters() = 0; - virtual void ClearFilters() = 0; -}; -#endif // CRYINCLUDE_EDITOR_INCLUDE_IASSETVIEWER_H diff --git a/Code/Editor/Include/IBaseLibraryManager.h b/Code/Editor/Include/IBaseLibraryManager.h deleted file mode 100644 index 4116b573fa..0000000000 --- a/Code/Editor/Include/IBaseLibraryManager.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 - * - */ -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IBASELIBRARYMANAGER_H -#define CRYINCLUDE_EDITOR_INCLUDE_IBASELIBRARYMANAGER_H -#pragma once - -#include -#include "Include/IDataBaseItem.h" -#include "Include/IDataBaseLibrary.h" -#include "Include/IDataBaseManager.h" -#include "Util/TRefCountBase.h" - -class CBaseLibraryItem; -class CBaseLibrary; - -struct IBaseLibraryManager - : public TRefCountBase - , public IEditorNotifyListener -{ - //! Clear all libraries. - virtual void ClearAll() = 0; - - ////////////////////////////////////////////////////////////////////////// - // IDocListener implementation. - ////////////////////////////////////////////////////////////////////////// - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) = 0; - - ////////////////////////////////////////////////////////////////////////// - // Library items. - ////////////////////////////////////////////////////////////////////////// - //! Make a new item in specified library. - virtual IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) = 0; - //! Delete item from library and manager. - virtual void DeleteItem(IDataBaseItem* pItem) = 0; - - //! Find Item by its GUID. - virtual IDataBaseItem* FindItem(REFGUID guid) const = 0; - virtual IDataBaseItem* FindItemByName(const QString& fullItemName) = 0; - virtual IDataBaseItem* LoadItemByName(const QString& fullItemName) = 0; - - virtual IDataBaseItemEnumerator* GetItemEnumerator() = 0; - - ////////////////////////////////////////////////////////////////////////// - // Set item currently selected. - virtual void SetSelectedItem(IDataBaseItem* pItem) = 0; - // Get currently selected item. - virtual IDataBaseItem* GetSelectedItem() const = 0; - virtual IDataBaseItem* GetSelectedParentItem() const = 0; - - ////////////////////////////////////////////////////////////////////////// - // Libraries. - ////////////////////////////////////////////////////////////////////////// - //! Add Item library. - virtual IDataBaseLibrary* AddLibrary(const QString& library, bool isLevelLibrary = false, bool bIsLoading = true) = 0; - virtual void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) = 0; - //! Get number of libraries. - virtual int GetLibraryCount() const = 0; - //! Get number of modified libraries. - virtual int GetModifiedLibraryCount() const = 0; - - //! Get Item library by index. - virtual IDataBaseLibrary* GetLibrary(int index) const = 0; - - //! Get Level Item library. - virtual IDataBaseLibrary* GetLevelLibrary() const = 0; - - //! Find Items Library by name. - virtual IDataBaseLibrary* FindLibrary(const QString& library) = 0; - - //! Find the Library's index by name. - virtual int FindLibraryIndex(const QString& library) = 0; - - //! Load Items library. -#ifdef LoadLibrary -#undef LoadLibrary -#endif - virtual IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) = 0; - - //! Save all modified libraries. - virtual void SaveAllLibs() = 0; - - //! Serialize property manager. - virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0; - - //! Export items to game. - virtual void Export(XmlNodeRef& node) = 0; - - //! Returns unique name base on input name. - // Vera@conffx, add LibName parameter so we could make an unique name depends on input library. - // Arguments: - // - name: name of the item - // - libName: The library of the item. Given the library name, the function will return a unique name in the library - // Default value "": The function will ignore the library name and return a unique name in the manager - virtual QString MakeUniqueItemName(const QString& name, const QString& libName = "") = 0; - virtual QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) = 0; - - //! Root node where this library will be saved. - virtual QString GetRootNodeName() = 0; - //! Path to libraries in this manager. - virtual QString GetLibsPath() = 0; - - ////////////////////////////////////////////////////////////////////////// - //! Validate library items for errors. - virtual void Validate() = 0; - - ////////////////////////////////////////////////////////////////////////// - virtual void GatherUsedResources(CUsedResources& resources) = 0; - - virtual void AddListener(IDataBaseManagerListener* pListener) = 0; - virtual void RemoveListener(IDataBaseManagerListener* pListener) = 0; - - ////////////////////////////////////////////////////////////////////////// - virtual void RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) = 0; - virtual void RegisterItem(CBaseLibraryItem* pItem) = 0; - virtual void UnregisterItem(CBaseLibraryItem* pItem) = 0; - - // Only Used internally. - virtual void OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName) = 0; - - // Called by items to indicated that they have been modified. - // Sends item changed event to listeners. - virtual void OnItemChanged(IDataBaseItem* pItem) = 0; - virtual void OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh) = 0; - - //CONFETTI BEGIN - // Used to change the library item order - virtual void ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation) = 0; - // simplifies the library renaming process - virtual bool SetLibraryName(CBaseLibrary* lib, const QString& name) = 0; - - - //Check if the file name is unique. - //Params: library: library name. NOT the file path. - virtual bool IsUniqueFilename(const QString& library) = 0; - //CONFETTI END -}; - -#endif // CRYINCLUDE_EDITOR_INCLUDE_IBASELIBRARYMANAGER_H diff --git a/Code/Editor/Include/IDataBaseItem.h b/Code/Editor/Include/IDataBaseItem.h deleted file mode 100644 index 6be5f49c2d..0000000000 --- a/Code/Editor/Include/IDataBaseItem.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IDATABASEITEM_H -#define CRYINCLUDE_EDITOR_INCLUDE_IDATABASEITEM_H -#pragma once - -#include -#include - -struct IDataBaseLibrary; -class CUsedResources; - -////////////////////////////////////////////////////////////////////////// -/** Base class for all items contained in BaseLibraray. -*/ -struct IDataBaseItem -{ - struct SerializeContext - { - XmlNodeRef node; - bool bUndo; - bool bLoading; - bool bCopyPaste; - bool bIgnoreChilds; - bool bUniqName; - SerializeContext() - : node(0) - , bLoading(false) - , bCopyPaste(false) - , bIgnoreChilds(false) - , bUniqName(false) - , bUndo(false) {}; - SerializeContext(XmlNodeRef _node, bool bLoad) - : node(_node) - , bLoading(bLoad) - , bCopyPaste(false) - , bIgnoreChilds(false) - , bUniqName(false) - , bUndo(false) {}; - SerializeContext(const SerializeContext& ctx) - : node(ctx.node) - , bLoading(ctx.bLoading) - , bCopyPaste(ctx.bCopyPaste) - , bIgnoreChilds(ctx.bIgnoreChilds) - , bUniqName(ctx.bUniqName) - , bUndo(ctx.bUndo) {}; - }; - - virtual EDataBaseItemType GetType() const = 0; - - //! Return Library this item are contained in. - //! Item can only be at one library. - virtual IDataBaseLibrary* GetLibrary() const = 0; - - //! Change item name. - virtual void SetName(const QString& name) = 0; - //! Get item name. - virtual const QString& GetName() const = 0; - - //! Get full item name, including name of library. - //! Name formed by adding dot after name of library - //! eg. library Pickup and item PickupRL form full item name: "Pickups.PickupRL". - virtual QString GetFullName() const = 0; - - //! Get only nameof group from prototype. - virtual QString GetGroupName() = 0; - //! Get short name of prototype without group. - virtual QString GetShortName() = 0; - - //! Serialize library item to archive. - virtual void Serialize(SerializeContext& ctx) = 0; - - //! Generate new unique id for this item. - virtual void GenerateId() = 0; - //! Returns GUID of this material. - virtual const GUID& GetGUID() const = 0; - - //! Validate item for errors. - virtual void Validate() {}; - - //! Gathers resources by this item. - virtual void GatherUsedResources([[maybe_unused]] CUsedResources& resources) {}; -}; - -#endif // CRYINCLUDE_EDITOR_INCLUDE_IDATABASEITEM_H diff --git a/Code/Editor/Include/IDataBaseLibrary.h b/Code/Editor/Include/IDataBaseLibrary.h deleted file mode 100644 index 75437d93e2..0000000000 --- a/Code/Editor/Include/IDataBaseLibrary.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IDATABASELIBRARY_H -#define CRYINCLUDE_EDITOR_INCLUDE_IDATABASELIBRARY_H -#pragma once - - -struct IDataBaseManager; -struct IDataBaseItem; - -class QString; -class XmlNodeRef; - -////////////////////////////////////////////////////////////////////////// -// Description: -// Interface to access specific library of editor data base. -// Ex. Archetype library, Material Library. -// See Also: -// IDataBaseItem,IDataBaseManager -////////////////////////////////////////////////////////////////////////// -struct IDataBaseLibrary -{ - // Description: - // Return IDataBaseManager interface to the manager for items stored in this library. - virtual IDataBaseManager* GetManager() = 0; - - // Description: - // Return library name. - virtual const QString& GetName() const = 0; - - // Description: - // Return filename where this library is stored. - virtual const QString& GetFilename() const = 0; - - // Description: - // Save contents of library to file. - virtual bool Save() = 0; - - // Description: - // Load library from file. - // Arguments: - // filename - Full specified library filename (relative to root game folder). - virtual bool Load(const QString& filename) = 0; - - // Description: - // Serialize library parameters and items to/from XML node. - virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0; - - // Description: - // Marks library as modified, indicates that some item in library was modified. - virtual void SetModified(bool bModified = true) = 0; - - // Description: - // Check if library parameters or any items where modified. - // If any item was modified library may need saving before closing editor. - virtual bool IsModified() const = 0; - - // Description: - // Check if this library is not shared and internal to current level. - virtual bool IsLevelLibrary() const = 0; - - // Description: - // Make this library accessible only from current Level. (not shared) - virtual void SetLevelLibrary(bool bEnable) = 0; - - // Description: - // Associate a new item with the library. - // Watch out if item was already in another library. - virtual void AddItem(IDataBaseItem* pItem, bool bRegister = true) = 0; - - // Description: - // Return number of items in library. - virtual int GetItemCount() const = 0; - - // Description: - // Get item by index. - // See Also: - // GetItemCount - // Arguments: - // index - Index from 0 to GetItemCount() - virtual IDataBaseItem* GetItem(int index) = 0; - - // Description: - // Remove item from library, does not destroy item, - // only unliks it from this library, to delete item use IDataBaseManager. - // See Also: - // AddItem - virtual void RemoveItem(IDataBaseItem* item) = 0; - - // Description: - // Remove all items from library, does not destroy items, - // only unliks them from this library, to delete item use IDataBaseManager. - // See Also: - // RemoveItem,AddItem - virtual void RemoveAllItems() = 0; - - // Description: - // Find item in library by name. - // This function usually uses linear search so it is not particularry fast. - // See Also: - // GetItem - virtual IDataBaseItem* FindItem(const QString& name) = 0; - - - //CONFETTI BEGIN - // Used to change the library item order - virtual void ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation) = 0; - //CONFETTI END -}; - -#endif // CRYINCLUDE_EDITOR_INCLUDE_IDATABASELIBRARY_H diff --git a/Code/Editor/Include/IDataBaseManager.h b/Code/Editor/Include/IDataBaseManager.h deleted file mode 100644 index 3d701d51fc..0000000000 --- a/Code/Editor/Include/IDataBaseManager.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_IDATABASEMANAGER_H -#define CRYINCLUDE_EDITOR_INCLUDE_IDATABASEMANAGER_H -#pragma once - -#include - -struct IDataBaseItem; -struct IDataBaseLibrary; -class CUsedResources; - -enum EDataBaseItemEvent -{ - EDB_ITEM_EVENT_ADD, - EDB_ITEM_EVENT_DELETE, - EDB_ITEM_EVENT_CHANGED, - EDB_ITEM_EVENT_SELECTED, - EDB_ITEM_EVENT_UPDATE_PROPERTIES, - EDB_ITEM_EVENT_UPDATE_PROPERTIES_NO_EDITOR_REFRESH -}; - -////////////////////////////////////////////////////////////////////////// -// Description: -// Callback class to intercept item creation and deletion events. -////////////////////////////////////////////////////////////////////////// -struct IDataBaseManagerListener -{ - virtual void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event) = 0; -}; - -////////////////////////////////////////////////////////////////////////// -// Description: -// his interface is used to enumerate al items registered to the database manager. -////////////////////////////////////////////////////////////////////////// -struct IDataBaseItemEnumerator -{ - virtual ~IDataBaseItemEnumerator() = default; - - virtual void Release() = 0; - virtual IDataBaseItem* GetFirst() = 0; - virtual IDataBaseItem* GetNext() = 0; -}; - -////////////////////////////////////////////////////////////////////////// -// -// Interface to the collection of all items or specific type -// in data base libraries. -// -////////////////////////////////////////////////////////////////////////// -struct IDataBaseManager -{ - //! Clear all libraries. - virtual void ClearAll() = 0; - - ////////////////////////////////////////////////////////////////////////// - // Library items. - ////////////////////////////////////////////////////////////////////////// - //! Make a new item in specified library. - virtual IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) = 0; - //! Delete item from library and manager. - virtual void DeleteItem(IDataBaseItem* pItem) = 0; - - //! Find Item by its GUID. - virtual IDataBaseItem* FindItem(REFGUID guid) const = 0; - virtual IDataBaseItem* FindItemByName(const QString& fullItemName) = 0; - - virtual IDataBaseItemEnumerator* GetItemEnumerator() = 0; - - // Select one item in DB. - virtual void SetSelectedItem(IDataBaseItem* pItem) = 0; - - ////////////////////////////////////////////////////////////////////////// - // Libraries. - ////////////////////////////////////////////////////////////////////////// - //! Add Item library. Set isLevelLibrary to true if its the "level" library which gets saved inside the level - virtual IDataBaseLibrary* AddLibrary(const QString& library, bool isLevelLibrary = false, bool bIsLoading = true) = 0; - virtual void DeleteLibrary(const QString& library, bool forceDeleteLibrary = false) = 0; - //! Get number of libraries. - virtual int GetLibraryCount() const = 0; - //! Get Item library by index. - virtual IDataBaseLibrary* GetLibrary(int index) const = 0; - - //! Find Items Library by name. - virtual IDataBaseLibrary* FindLibrary(const QString& library) = 0; - - //! Load Items library. -#ifdef LoadLibrary -#undef LoadLibrary -#endif - virtual IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) = 0; - - //! Save all modified libraries. - virtual void SaveAllLibs() = 0; - - //! Serialize property manager. - virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0; - - //! Export items to game. - virtual void Export([[maybe_unused]] XmlNodeRef& node) {}; - - //! Returns unique name base on input name. - virtual QString MakeUniqueItemName(const QString& name, const QString& libName = "") = 0; - virtual QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) = 0; - - //! Root node where this library will be saved. - virtual QString GetRootNodeName() = 0; - //! Path to libraries in this manager. - virtual QString GetLibsPath() = 0; - - ////////////////////////////////////////////////////////////////////////// - //! Validate library items for errors. - virtual void Validate() = 0; - - // Description: - // Collects names of all resource files used by managed items. - // Arguments: - // resources - Structure where all filenames are collected. - virtual void GatherUsedResources(CUsedResources& resources) = 0; - - ////////////////////////////////////////////////////////////////////////// - // Register listeners. - virtual void AddListener(IDataBaseManagerListener* pListener) = 0; - virtual void RemoveListener(IDataBaseManagerListener* pListener) = 0; -}; - -#endif // CRYINCLUDE_EDITOR_INCLUDE_IDATABASEMANAGER_H diff --git a/Code/Editor/Include/IEditorMaterial.h b/Code/Editor/Include/IEditorMaterial.h deleted file mode 100644 index 329b0ae53f..0000000000 --- a/Code/Editor/Include/IEditorMaterial.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 - - -#include "BaseLibraryItem.h" -#include - -struct IEditorMaterial - : public CBaseLibraryItem -{ - virtual int GetFlags() const = 0; - virtual IMaterial* GetMatInfo(bool bUseExistingEngineMaterial = false) = 0; - virtual void DisableHighlightForFrame() = 0; -}; diff --git a/Code/Editor/Include/IEditorMaterialManager.h b/Code/Editor/Include/IEditorMaterialManager.h deleted file mode 100644 index 6f71c5ddd1..0000000000 --- a/Code/Editor/Include/IEditorMaterialManager.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 - * - */ -#ifndef CRYINCLUDE_EDITOR_MATERIAL_IEDITORMATERIALMANAGER_H -#define CRYINCLUDE_EDITOR_MATERIAL_IEDITORMATERIALMANAGER_H -#pragma once - -#include -#include - - -struct IEditorMaterialManager -{ - virtual void GotoMaterial(IMaterial* pMaterial) = 0; -}; - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H diff --git a/Code/Editor/Include/IErrorReport.h b/Code/Editor/Include/IErrorReport.h index 7bf00d6973..c409dbc7dd 100644 --- a/Code/Editor/Include/IErrorReport.h +++ b/Code/Editor/Include/IErrorReport.h @@ -14,7 +14,6 @@ // forward declarations. class CParticleItem; class CBaseObject; -class CBaseLibraryItem; class CErrorRecord; class QString; @@ -52,9 +51,6 @@ struct IErrorReport //! Assign current Object to which new reported warnings are assigned. virtual void SetCurrentValidatorObject(CBaseObject* pObject) = 0; - //! Assign current Item to which new reported warnings are assigned. - virtual void SetCurrentValidatorItem(CBaseLibraryItem* pItem) = 0; - //! Assign current filename. virtual void SetCurrentFile(const QString& file) = 0; }; diff --git a/Code/Editor/Include/IFileUtil.h b/Code/Editor/Include/IFileUtil.h index 036a0bc5ee..ea2fe1f1a3 100644 --- a/Code/Editor/Include/IFileUtil.h +++ b/Code/Editor/Include/IFileUtil.h @@ -116,9 +116,6 @@ struct IFileUtil virtual bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr) = 0; virtual void EditTextureFile(const char* txtureFile, bool bUseGameFolder) = 0; - //! dcc filename calculation and extraction sub-routines - virtual bool CalculateDccFilename(const QString& assetFilename, QString& dccFilename) = 0; - //! Reformat filter string for (MFC) CFileDialog style file filtering virtual void FormatFilterString(QString& filter) = 0; diff --git a/Code/Editor/Lib/Tests/IEditorMock.h b/Code/Editor/Lib/Tests/IEditorMock.h index 390ffebe79..aaee34c2c6 100644 --- a/Code/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Editor/Lib/Tests/IEditorMock.h @@ -85,9 +85,6 @@ public: MOCK_METHOD0(IsSelectionLocked, bool()); MOCK_METHOD0(GetObjectManager, struct IObjectManager* ()); MOCK_METHOD0(GetSettingsManager, CSettingsManager* ()); - MOCK_METHOD1(GetDBItemManager, IDataBaseManager* (EDataBaseItemType)); - MOCK_METHOD0(GetMaterialManagerLibrary, IBaseLibraryManager* ()); - MOCK_METHOD0(GetIEditorMaterialManager, IEditorMaterialManager* ()); MOCK_METHOD0(GetIconManager, IIconManager* ()); MOCK_METHOD0(GetMusicManager, CMusicManager* ()); MOCK_METHOD2(GetTerrainElevation, float(float , float )); @@ -187,6 +184,5 @@ public: MOCK_METHOD0(UnloadPlugins, void()); MOCK_METHOD0(LoadPlugins, void()); MOCK_METHOD1(GetSearchPath, QString(EEditorPathName)); - MOCK_METHOD0(GetEditorPanelUtils, IEditorPanelUtils* ()); }; diff --git a/Code/Editor/LightmapCompiler/SimpleTriangleRasterizer.cpp b/Code/Editor/LightmapCompiler/SimpleTriangleRasterizer.cpp deleted file mode 100644 index 736465cac1..0000000000 --- a/Code/Editor/LightmapCompiler/SimpleTriangleRasterizer.cpp +++ /dev/null @@ -1,506 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "SimpleTriangleRasterizer.h" - -#include - -#if !defined FLT_MAX -#define FLT_MAX 3.402823466e+38F -#endif - -void CSimpleTriangleRasterizer::lambertHorizlineConservative(float fx1, float fx2, int yy, IRasterizeSink* inpSink) -{ - int x1 = (int)floorf(fx1 + 0.25f), x2 = (int)floorf(fx2 + .75f); - - if (x1 < m_iMinX) - { - x1 = m_iMinX; - } - if (x2 > m_iMaxX + 1) - { - x2 = m_iMaxX + 1; - } - if (x1 > m_iMaxX + 1) - { - x1 = m_iMaxX + 1; - } - if (x2 < m_iMinX) - { - x2 = m_iMinX; - } - - - inpSink->Line(fx1, fx2, x1, x2, yy); -} - -void CSimpleTriangleRasterizer::lambertHorizlineSubpixelCorrect(float fx1, float fx2, int yy, IRasterizeSink* inpSink) -{ - int x1 = (int)floorf(fx1 + 0.5f), x2 = (int)floorf(fx2 + 0.5f); - // int x1=(int)floorf(fx1*1023.f/1024.f+1.f),x2=(int)floorf(fx2*1023.f/1024.f+1.f); - - if (x1 < m_iMinX) - { - x1 = m_iMinX; - } - if (x2 > m_iMaxX) - { - x2 = m_iMaxX; - } - if (x1 > m_iMaxX) - { - x1 = m_iMaxX; - } - if (x2 < m_iMinX) - { - x2 = m_iMinX; - } - - inpSink->Line(fx1, fx2, x1, x2, yy); -} - -// optimizable -void CSimpleTriangleRasterizer::CopyAndSortY(const float infX[3], const float infY[3], float outfX[3], float outfY[3]) -{ - outfX[0] = infX[0]; - outfY[0] = infY[0]; - outfX[1] = infX[1]; - outfY[1] = infY[1]; - outfX[2] = infX[2]; - outfY[2] = infY[2]; - - // Sort the coordinates, so that (x[1], y[1]) becomes the highest coord - float tmp; - - if (outfY[0] > outfY[1]) - { - if (outfY[1] > outfY[2]) - { - tmp = outfY[0]; - outfY[0] = outfY[1]; - outfY[1] = tmp; - tmp = outfX[0]; - outfX[0] = outfX[1]; - outfX[1] = tmp; - tmp = outfY[1]; - outfY[1] = outfY[2]; - outfY[2] = tmp; - tmp = outfX[1]; - outfX[1] = outfX[2]; - outfX[2] = tmp; - - if (outfY[0] > outfY[1]) - { - tmp = outfY[0]; - outfY[0] = outfY[1]; - outfY[1] = tmp; - tmp = outfX[0]; - outfX[0] = outfX[1]; - outfX[1] = tmp; - } - } - else - { - tmp = outfY[0]; - outfY[0] = outfY[1]; - outfY[1] = tmp; - tmp = outfX[0]; - outfX[0] = outfX[1]; - outfX[1] = tmp; - - if (outfY[1] > outfY[2]) - { - tmp = outfY[1]; - outfY[1] = outfY[2]; - outfY[2] = tmp; - tmp = outfX[1]; - outfX[1] = outfX[2]; - outfX[2] = tmp; - } - } - } - else - { - if (outfY[1] > outfY[2]) - { - tmp = outfY[1]; - outfY[1] = outfY[2]; - outfY[2] = tmp; - tmp = outfX[1]; - outfX[1] = outfX[2]; - outfX[2] = tmp; - - if (outfY[0] > outfY[1]) - { - tmp = outfY[0]; - outfY[0] = outfY[1]; - outfY[1] = tmp; - tmp = outfX[0]; - outfX[0] = outfX[1]; - outfX[1] = tmp; - } - } - } -} - -void CSimpleTriangleRasterizer::CallbackFillRectConservative(float _x[3], float _y[3], IRasterizeSink* inpSink) -{ - inpSink->Triangle(m_iMinY); - - float fMinX = (std::min)(_x[0], (std::min)(_x[1], _x[2])); - float fMaxX = (std::max)(_x[0], (std::max)(_x[1], _x[2])); - float fMinY = (std::min)(_y[0], (std::min)(_y[1], _y[2])); - float fMaxY = (std::max)(_y[0], (std::max)(_y[1], _y[2])); - - int iMinX = (std::max)(m_iMinX, (int)floorf(fMinX)); - int iMaxX = (std::min)(m_iMaxX + 1, (int)ceilf(fMaxX)); - int iMinY = (std::max)(m_iMinY, (int)floorf(fMinY)); - int iMaxY = (std::min)(m_iMaxY + 1, (int)ceilf(fMaxY)); - - for (int y = iMinY; y < iMaxY; y++) - { - inpSink->Line(fMinX, fMaxX, iMinX, iMaxX, y); - } -} - - - - -void CSimpleTriangleRasterizer::CallbackFillConservative(float _x[3], float _y[3], IRasterizeSink* inpSink) -{ - float x[3], y[3]; - - CopyAndSortY(_x, _y, x, y); - - // Calculate interpolation steps - float fX1toX2step = 0.0f; - float fX1toX3step = 0.0f; - float fX2toX3step = 0.0f; - if (fabsf(y[1] - y[0]) > FLT_EPSILON) - { - fX1toX2step = (x[1] - x[0]) / (float)(y[1] - y[0]); - } - if (fabsf(y[2] - y[0]) > FLT_EPSILON) - { - fX1toX3step = (x[2] - x[0]) / (float)(y[2] - y[0]); - } - if (fabsf(y[2] - y[1]) > FLT_EPSILON) - { - fX2toX3step = (x[2] - x[1]) / (float)(y[2] - y[1]); - } - - float fX1toX2 = x[0], fX1toX3 = x[0], fX2toX3 = x[1]; - bool bFirstLine = true; - bool bTriangleCallDone = false; - - // Go through the scanlines of the triangle - int yy = (int)floorf(y[0]); // was floor - - for (; yy <= (int)floorf(y[2]); yy++) - // for(yy=m_iMinY; yy<=m_iMaxY; yy++) // juhu - { - float fSubPixelYStart = 0.0f, fSubPixelYEnd = 1.0f; - float start, end; - - // first line - if (bFirstLine) - { - fSubPixelYStart = y[0] - floorf(y[0]); - start = x[0]; - end = x[0]; - bFirstLine = false; - } - else - { - // top part without middle corner line - if (yy <= (int)floorf(y[1])) - { - start = (std::min)(fX1toX2, fX1toX3); - end = (std::max)(fX1toX2, fX1toX3); - } - else - { - start = (std::min)(fX2toX3, fX1toX3); - end = (std::max)(fX2toX3, fX1toX3); - } - } - - // middle corner line - if (yy == (int)floorf(y[1])) - { - fSubPixelYEnd = y[1] - floorf(y[1]); - - fX1toX3 += fX1toX3step * (fSubPixelYEnd - fSubPixelYStart); - start = (std::min)(start, fX1toX3); - end = (std::max)(end, fX1toX3); - start = (std::min)(start, x[1]); - end = (std::max)(end, x[1]); - - fSubPixelYStart = fSubPixelYEnd; - fSubPixelYEnd = 1.0f; - } - - // last line - if (yy == (int)floorf(y[2])) - { - start = (std::min)(start, x[2]); - end = (std::max)(end, x[2]); - } - else - { - // top part without middle corner line - if (yy < (int)floorf(y[1])) - { - fX1toX2 += fX1toX2step * (fSubPixelYEnd - fSubPixelYStart); - start = (std::min)(start, fX1toX2); - end = (std::max)(end, fX1toX2); - } - else - { - fX2toX3 += fX2toX3step * (fSubPixelYEnd - fSubPixelYStart); - start = (std::min)(start, fX2toX3); - end = (std::max)(end, fX2toX3); - } - - fX1toX3 += fX1toX3step * (fSubPixelYEnd - fSubPixelYStart); - start = (std::min)(start, fX1toX3); - end = (std::max)(end, fX1toX3); - } - - if (yy >= m_iMinY && yy <= m_iMaxY) - { - if (!bTriangleCallDone) - { - inpSink->Triangle(yy); - bTriangleCallDone = true; - } - - lambertHorizlineConservative(start, end, yy, inpSink); - } - } -} - - - -void CSimpleTriangleRasterizer::CallbackFillSubpixelCorrect(float _x[3], float _y[3], IRasterizeSink* inpSink) -{ - float x[3], y[3]; - - CopyAndSortY(_x, _y, x, y); - - if (fabs(y[0] - floorf(y[0])) < FLT_EPSILON) - { - y[0] -= FLT_EPSILON; - } - - // Calculate interpolation steps - float fX1toX2step = 0.0f; - float fX1toX3step = 0.0f; - float fX2toX3step = 0.0f; - if (fabsf(y[1] - y[0]) > FLT_EPSILON) - { - fX1toX2step = (x[1] - x[0]) / (y[1] - y[0]); - } - if (fabsf(y[2] - y[0]) > FLT_EPSILON) - { - fX1toX3step = (x[2] - x[0]) / (y[2] - y[0]); - } - if (fabsf(y[2] - y[1]) > FLT_EPSILON) - { - fX2toX3step = (x[2] - x[1]) / (y[2] - y[1]); - } - - float fX1toX2 = x[0], fX1toX3 = x[0], fX2toX3 = x[1]; - bool bFirstLine = true; - bool bTriangleCallDone = false; - - y[0] -= 0.5f; - y[1] -= 0.5f; - y[2] -= 0.5f; - // y[0]=y[0]*1023.f/1024.f+1.f; - // y[1]=y[1]*1023.f/1024.f+1.f; - // y[2]=y[2]*1023.f/1024.f+1.f; - - for (int yy = (int)floorf(y[0]); yy <= (int)floorf(y[2]); yy++) - { - float fSubPixelYStart = 0.0f, fSubPixelYEnd = 1.0f; - float start, end; - - // first line - if (bFirstLine) - { - fSubPixelYStart = y[0] - floorf(y[0]); - start = x[0]; - end = x[0]; - bFirstLine = false; - } - else - { - // top part without middle corner line - if (yy <= (int)floorf(y[1])) - { - start = (std::min)(fX1toX2, fX1toX3); - end = (std::max)(fX1toX2, fX1toX3); - } - else - { - start = (std::min)(fX2toX3, fX1toX3); - end = (std::max)(fX2toX3, fX1toX3); - } - } - - // middle corner line - if (yy == (int)floorf(y[1])) - { - fSubPixelYEnd = y[1] - floorf(y[1]); - - fX1toX3 += fX1toX3step * (fSubPixelYEnd - fSubPixelYStart); - - fSubPixelYStart = fSubPixelYEnd; - fSubPixelYEnd = 1.0f; - } - - // last line - if (yy != (int)floorf(y[2])) - { - // top part without middle corner line - if (yy < (int)floorf(y[1])) - { - fX1toX2 += fX1toX2step * (fSubPixelYEnd - fSubPixelYStart); - } - else - { - fX2toX3 += fX2toX3step * (fSubPixelYEnd - fSubPixelYStart); - } - - fX1toX3 += fX1toX3step * (fSubPixelYEnd - fSubPixelYStart); - } - - if (start != end) - { - if (yy >= m_iMinY && yy <= m_iMaxY) - { - if (!bTriangleCallDone) - { - inpSink->Triangle(yy); - bTriangleCallDone = true; - } - - lambertHorizlineSubpixelCorrect(start, end, yy, inpSink); - } - } - } -} - - - - -// shrink triangle by n pixel, optimizable -void CSimpleTriangleRasterizer::ShrinkTriangle(float inoutfX[3], float inoutfY[3], float infAmount) -{ - float fX[3] = { inoutfX[0], inoutfX[1], inoutfX[2] }; - float fY[3] = { inoutfY[0], inoutfY[1], inoutfY[2] }; - - /* - // move edge to opposing vertex - float dx,dy,fLength; - - for(int a=0;a<3;a++) - { - int b=a+1;if(b>=3)b=0; - int c=b+1;if(c>=3)c=0; - - dx=fX[a]-(fX[b]+fX[c])*0.5f; - dy=fY[a]-(fY[b]+fY[c])*0.5f; - fLength=(float)sqrt(dx*dx+dy*dy); - if(fLength>1.0f) - { - dx/=fLength;dy/=fLength; - inoutfX[b]+=dx;inoutfY[b]+=dy; - inoutfX[c]+=dx;inoutfY[c]+=dy; - } - } - */ - - /* - // move vertex to opposing edge - float dx,dy,fLength; - - for(int a=0;a<3;a++) - { - int b=a+1;if(b>=3)b=0; - int c=b+1;if(c>=3)c=0; - - dx=fX[a]-(fX[b]+fX[c])*0.5f; - dy=fY[a]-(fY[b]+fY[c])*0.5f; - fLength=(float)sqrt(dx*dx+dy*dy); - if(fLength>1.0f) - { - dx/=fLength;dy/=fLength; - inoutfX[a]-=dx;inoutfY[a]-=dy; - } - } - */ - - // move vertex to get edges shifted perpendicular for 1 unit - for (int a = 0; a < 3; a++) - { - float dx1, dy1, dx2, dy2, fLength; - - int b = a + 1; - if (b >= 3) - { - b = 0; - } - int c = b + 1; - if (c >= 3) - { - c = 0; - } - - dx1 = fX[b] - fX[a]; - dy1 = fY[b] - fY[a]; - fLength = (float)sqrt(dx1 * dx1 + dy1 * dy1); - if (infAmount > 0) - { - if (fLength < infAmount) - { - continue; - } - } - if (fLength == 0.0f) - { - continue; - } - dx1 /= fLength; - dy1 /= fLength; - - dx2 = fX[c] - fX[a]; - dy2 = fY[c] - fY[a]; - fLength = (float)sqrt(dx2 * dx2 + dy2 * dy2); - if (infAmount > 0) - { - if (fLength < infAmount) - { - continue; - } - } - if (fLength == 0.0f) - { - continue; - } - dx2 /= fLength; - dy2 /= fLength; - - inoutfX[a] += (dx1 + dx2) * infAmount; - inoutfY[a] += (dy1 + dy2) * infAmount; - } -} diff --git a/Code/Editor/LightmapCompiler/SimpleTriangleRasterizer.h b/Code/Editor/LightmapCompiler/SimpleTriangleRasterizer.h deleted file mode 100644 index bcfdd7b6da..0000000000 --- a/Code/Editor/LightmapCompiler/SimpleTriangleRasterizer.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_LIGHTMAPCOMPILER_SIMPLETRIANGLERASTERIZER_H -#define CRYINCLUDE_EDITOR_LIGHTMAPCOMPILER_SIMPLETRIANGLERASTERIZER_H -#pragma once - -class CSimpleTriangleRasterizer -{ -public: - - class IRasterizeSink - { - public: - - //! is called once per triangel for the first possible visible line - //! /param iniStartY - virtual void Triangle([[maybe_unused]] const int iniStartY) - { - } - - //! callback function - //! /param infXLeft included - not clipped against left and reight border - //! /param infXRight excluded - not clipped against left and reight border - //! /param iniXLeft included - //! /param iniXRight excluded - //! /param iniY - virtual void Line(const float infXLeft, const float infXRight, - const int iniXLeft, const int iniXRight, const int iniY) = 0; - }; - - typedef unsigned long DWORD; - - // ----------------------------------------------------- - - //! implementation sink sample - class CDWORDFlatFill - : public IRasterizeSink - { - public: - - //! constructor - CDWORDFlatFill(DWORD* inpBuffer, const DWORD indwPitchInPixels, DWORD indwValue) - { - m_dwValue = indwValue; - m_pBuffer = inpBuffer; - m_dwPitchInPixels = indwPitchInPixels; - } - - virtual void Triangle(const int iniY) - { - m_pBufferLine = &m_pBuffer[iniY * m_dwPitchInPixels]; - } - - virtual void Line([[maybe_unused]] const float infXLeft, [[maybe_unused]] const float infXRight, - const int iniLeft, const int iniRight, [[maybe_unused]] const int iniY) - { - DWORD* mem = &m_pBufferLine[iniLeft]; - - for (int x = iniLeft; x < iniRight; x++) - { - *mem++ = m_dwValue; - } - - m_pBufferLine += m_dwPitchInPixels; - } - - private: - DWORD m_dwValue; //!< fill value - DWORD* m_pBufferLine; //!< to get rid of the multiplication per line - - DWORD m_dwPitchInPixels; //!< in DWORDS, not in Bytes - DWORD* m_pBuffer; //!< pointer to the buffer - }; - - // ----------------------------------------------------- - - //! constructor - //! /param iniWidth excluded - //! /param iniHeight excluded - CSimpleTriangleRasterizer(const int iniWidth, const int iniHeight) - { - m_iMinX = 0; - m_iMinY = 0; - m_iMaxX = iniWidth - 1; - m_iMaxY = iniHeight - 1; - } - /* - //! constructor - //! /param iniMinX included - //! /param iniMinY included - //! /param iniMaxX included - //! /param iniMaxY included - CSimpleTriangleRasterizer( const int iniMinX, const int iniMinY, const int iniMaxX, const int iniMaxY ) - { - m_iMinX=iniMinX; - m_iMinY=iniMinY; - m_iMaxX=iniMaxX; - m_iMaxY=iniMaxY; - } - */ - //! simple triangle filler with clipping (optimizable), not subpixel correct - //! /param pBuffer pointer o the color buffer - //! /param indwWidth width of the color buffer - //! /param indwHeight height of the color buffer - //! /param x array of the x coordiantes of the three vertices - //! /param y array of the x coordiantes of the three vertices - //! /param indwValue value of the triangle - void DWORDFlatFill(DWORD* inpBuffer, const DWORD indwPitchInPixels, float x[3], float y[3], DWORD indwValue, bool inbConservative) - { - CDWORDFlatFill pix(inpBuffer, indwPitchInPixels, indwValue); - - if (inbConservative) - { - CallbackFillConservative(x, y, &pix); - } - else - { - CallbackFillSubpixelCorrect(x, y, &pix); - } - } - - // Rectangle around triangle - more stable - use for debugging purpose - void CallbackFillRectConservative(float x[3], float y[3], IRasterizeSink * inpSink); - - - //! subpixel correct triangle filler (conservative or not conservative) - //! \param pBuffer pointe to the DWORD - //! \param indwWidth width of the buffer pBuffer pointes to - //! \param indwHeight height of the buffer pBuffer pointes to - //! \param x array of the x coordiantes of the three vertices - //! \param y array of the x coordiantes of the three vertices - //! \param inpSink pointer to the sink interface (is called per triangle and per triangle line) - void CallbackFillConservative(float x[3], float y[3], IRasterizeSink * inpSink); - - //! subpixel correct triangle filler (conservative or not conservative) - //! \param pBuffer pointe to the DWORD - //! \param indwWidth width of the buffer pBuffer pointes to - //! \param indwHeight height of the buffer pBuffer pointes to - //! \param x array of the x coordiantes of the three vertices - //! \param y array of the x coordiantes of the three vertices - //! \param inpSink pointer to the sink interface (is called per triangle and per triangle line) - void CallbackFillSubpixelCorrect(float x[3], float y[3], IRasterizeSink * inpSink); - - //! - //! /param inoutfX - //! /param inoutfY - //! /param infAmount could be positive or negative - static void ShrinkTriangle(float inoutfX[3], float inoutfY[3], float infAmount); - -private: - - // Clipping Rect; - - int m_iMinX; //!< minimum x value included - int m_iMinY; //!< minimum y value included - int m_iMaxX; //!< maximum x value included - int m_iMaxY; //!< maximum x value included - - void lambertHorizlineConservative(float fx1, float fx2, int y, IRasterizeSink* inpSink); - void lambertHorizlineSubpixelCorrect(float fx1, float fx2, int y, IRasterizeSink* inpSink); - void CopyAndSortY(const float infX[3], const float infY[3], float outfX[3], float outfY[3]); -}; - - -// extension ideas: -// * callback with coverage mask (possible non ordered sampling) -// * z-buffer behaviour -// * gouraud shading -// * texture mapping with nearest/bicubic/bilinear filter -// * further primitives: thick line, ellipse -// * build a template version -// * - -#endif // CRYINCLUDE_EDITOR_LIGHTMAPCOMPILER_SIMPLETRIANGLERASTERIZER_H diff --git a/Code/Editor/Objects/EntityObject.h b/Code/Editor/Objects/EntityObject.h index c3e379bccc..c6b7e4ce2d 100644 --- a/Code/Editor/Objects/EntityObject.h +++ b/Code/Editor/Objects/EntityObject.h @@ -27,6 +27,7 @@ #define CLASS_ENVIRONMENT_LIGHT "EnvironmentLight" class CEntityObject; +class CSelectionGroup; class QMenu; /*! diff --git a/Code/Editor/Objects/ObjectLoader.h b/Code/Editor/Objects/ObjectLoader.h index fc1014ad03..fa576fa983 100644 --- a/Code/Editor/Objects/ObjectLoader.h +++ b/Code/Editor/Objects/ObjectLoader.h @@ -13,6 +13,8 @@ #include "ErrorReport.h" #include +#include + class CErrorRecord; struct IObjectManager; diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index 1dea6ece7f..06233d4dd2 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -26,7 +26,6 @@ #include "Util/Image.h" #include "ObjectManagerLegacyUndo.h" #include "Include/HitContext.h" -#include "EditMode/DeepSelection.h" #include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h" #include diff --git a/Code/Editor/TrackView/TrackViewSequence.h b/Code/Editor/TrackView/TrackViewSequence.h index a392ad00f9..8f686af0cb 100644 --- a/Code/Editor/TrackView/TrackViewSequence.h +++ b/Code/Editor/TrackView/TrackViewSequence.h @@ -11,6 +11,7 @@ #define CRYINCLUDE_EDITOR_TRACKVIEW_TRACKVIEWSEQUENCE_H #pragma once +#include #include "IMovieSystem.h" #include diff --git a/Code/Editor/TrackView/TrackViewSequenceManager.cpp b/Code/Editor/TrackView/TrackViewSequenceManager.cpp index d7c1e3c709..515af4df38 100644 --- a/Code/Editor/TrackView/TrackViewSequenceManager.cpp +++ b/Code/Editor/TrackView/TrackViewSequenceManager.cpp @@ -408,20 +408,6 @@ void CTrackViewSequenceManager::OnSequenceRemoved(CTrackViewSequence* sequence) } } -//////////////////////////////////////////////////////////////////////////// -void CTrackViewSequenceManager::OnDataBaseItemEvent([[maybe_unused]] IDataBaseItem* pItem, EDataBaseItemEvent event) -{ - if (event != EDataBaseItemEvent::EDB_ITEM_EVENT_ADD) - { - const size_t numSequences = m_sequences.size(); - - for (size_t i = 0; i < numSequences; ++i) - { - m_sequences[i]->UpdateDynamicParams(); - } - } -} - //////////////////////////////////////////////////////////////////////////// CTrackViewAnimNodeBundle CTrackViewSequenceManager::GetAllRelatedAnimNodes(const AZ::EntityId entityId) const { diff --git a/Code/Editor/TrackView/TrackViewSequenceManager.h b/Code/Editor/TrackView/TrackViewSequenceManager.h index 1474323dc6..6c65a7f1a9 100644 --- a/Code/Editor/TrackView/TrackViewSequenceManager.h +++ b/Code/Editor/TrackView/TrackViewSequenceManager.h @@ -13,13 +13,11 @@ #include "TrackViewSequence.h" -#include "IDataBaseManager.h" #include class CTrackViewSequenceManager : public IEditorNotifyListener - , public IDataBaseManagerListener , public ITrackViewSequenceManager , public AZ::EntitySystemBus::Handler { @@ -65,8 +63,6 @@ private: void OnSequenceAdded(CTrackViewSequence* pSequence); void OnSequenceRemoved(CTrackViewSequence* pSequence); - void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event) override; - // AZ::EntitySystemBus void OnEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name) override; void OnEntityDestruction(const AZ::EntityId& entityId) override; diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp index 182a122ea8..ce2d399dcc 100644 --- a/Code/Editor/Util/FileUtil.cpp +++ b/Code/Editor/Util/FileUtil.cpp @@ -42,8 +42,6 @@ #include "CheckOutDialog.h" #include "ISourceControl.h" #include "Dialogs/Generic/UserOptions.h" -#include "IAssetItem.h" -#include "IAssetItemDatabase.h" #include "Include/IObjectManager.h" #include "UsedResources.h" #include "Objects/BaseObject.h" @@ -223,106 +221,6 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b } } - -////////////////////////////////////////////////////////////////////////// -bool CFileUtil::CalculateDccFilename(const QString& assetFilename, QString& dccFilename) -{ - if (ExtractDccFilenameFromAssetDatabase(assetFilename, dccFilename)) - { - return true; - } - - if (ExtractDccFilenameUsingNamingConventions(assetFilename, dccFilename)) - { - return true; - } - - GetIEditor()->GetEnv()->pLog->LogError("Failed to find psd file for texture: '%s'", assetFilename.toUtf8().data()); - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CFileUtil::ExtractDccFilenameFromAssetDatabase(const QString& assetFilename, QString& dccFilename) -{ - IAssetItemDatabase* pCurrentDatabaseInterface = nullptr; - std::vector assetDatabasePlugins; - IEditorClassFactory* pClassFactory = GetIEditor()->GetClassFactory(); - pClassFactory->GetClassesByCategory("Asset Item DB", assetDatabasePlugins); - - for (size_t i = 0; i < assetDatabasePlugins.size(); ++i) - { - if (assetDatabasePlugins[i]->QueryInterface(__az_uuidof(IAssetItemDatabase), (void**)&pCurrentDatabaseInterface) == S_OK) - { - if (!pCurrentDatabaseInterface) - { - continue; - } - - QString assetDatabaseDccFilename; - IAssetItem* pAssetItem = pCurrentDatabaseInterface->GetAsset(assetFilename.toUtf8().data()); - if (pAssetItem) - { - if ((pAssetItem->GetFlags() & IAssetItem::eFlag_Cached)) - { - QVariant v = pAssetItem->GetAssetFieldValue("dccfilename"); - assetDatabaseDccFilename = v.toString(); - if (!v.isNull()) - { - dccFilename = assetDatabaseDccFilename; - dccFilename = Path::GetRelativePath(dccFilename, false); - - uint32 attr = CFileUtil::GetAttributes(dccFilename.toUtf8().data()); - - if (CFileUtil::FileExists(dccFilename)) - { - return true; - } - else if (GetIEditor()->IsSourceControlAvailable() && (attr & SCC_FILE_ATTRIBUTE_MANAGED)) - { - return CFileUtil::GetLatestFromSourceControl(dccFilename.toUtf8().data()); - } - } - } - } - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CFileUtil::ExtractDccFilenameUsingNamingConventions(const QString& assetFilename, QString& dccFilename) -{ - //else to try find it by naming conventions - QString tempStr = assetFilename; - int foundSplit = -1; - if ((foundSplit = tempStr.lastIndexOf('.')) > 0) - { - QString first = tempStr.mid(0, foundSplit); - tempStr = first + ".psd"; - } - if (CFileUtil::FileExists(tempStr)) - { - dccFilename = tempStr; - return true; - } - - //else try to find it by replacing post fix _ with .psd - tempStr = assetFilename; - foundSplit = -1; - if ((foundSplit = tempStr.lastIndexOf('_')) > 0) - { - QString first = tempStr.mid(0, foundSplit); - tempStr = first + ".psd"; - } - if (CFileUtil::FileExists(tempStr)) - { - dccFilename = tempStr; - return true; - } - - return false; -} - ////////////////////////////////////////////////////////////////////////// void CFileUtil::FormatFilterString(QString& filter) { diff --git a/Code/Editor/Util/FileUtil.h b/Code/Editor/Util/FileUtil.h index fc0fc942fe..a4ff5009a2 100644 --- a/Code/Editor/Util/FileUtil.h +++ b/Code/Editor/Util/FileUtil.h @@ -29,9 +29,6 @@ public: static void EditTextFile(const char* txtFile, int line = 0, IFileUtil::ETextFileType fileType = IFileUtil::FILE_TYPE_SCRIPT); static void EditTextureFile(const char* txtureFile, bool bUseGameFolder); - //! dcc filename calculation and extraction sub-routines - static bool CalculateDccFilename(const QString& assetFilename, QString& dccFilename); - //! Reformat filter string for (MFC) CFileDialog style file filtering static void FormatFilterString(QString& filter); @@ -155,9 +152,6 @@ private: // Keep this variant of this method private! pIsSelected is captured in a lambda, and so requires menu use exec() and never use show() static void PopulateQMenu(QWidget* caller, QMenu* menu, AZStd::string_view fullGamePath, bool* pIsSelected); - - static bool ExtractDccFilenameFromAssetDatabase(const QString& assetFilename, QString& dccFilename); - static bool ExtractDccFilenameUsingNamingConventions(const QString& assetFilename, QString& dccFilename); }; class CAutoRestorePrimaryCDRoot diff --git a/Code/Editor/Util/FileUtil_impl.cpp b/Code/Editor/Util/FileUtil_impl.cpp index 28090d28d5..31e3532f33 100644 --- a/Code/Editor/Util/FileUtil_impl.cpp +++ b/Code/Editor/Util/FileUtil_impl.cpp @@ -30,11 +30,6 @@ void CFileUtil_impl::EditTextureFile(const char* txtureFile, bool bUseGameFolder CFileUtil::EditTextureFile(txtureFile, bUseGameFolder); } -bool CFileUtil_impl::CalculateDccFilename(const QString& assetFilename, QString& dccFilename) -{ - return CFileUtil::CalculateDccFilename(assetFilename, dccFilename); -} - void CFileUtil_impl::FormatFilterString(QString& filter) { CFileUtil::FormatFilterString(filter); diff --git a/Code/Editor/Util/FileUtil_impl.h b/Code/Editor/Util/FileUtil_impl.h index aa8d0bf3b5..3c8e138dab 100644 --- a/Code/Editor/Util/FileUtil_impl.h +++ b/Code/Editor/Util/FileUtil_impl.h @@ -39,9 +39,6 @@ public: bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr) override; void EditTextureFile(const char* txtureFile, bool bUseGameFolder) override; - //! dcc filename calculation and extraction sub-routines - bool CalculateDccFilename(const QString& assetFilename, QString& dccFilename) override; - //! Reformat filter string for (MFC) CFileDialog style file filtering void FormatFilterString(QString& filter) override; diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index a71df6a9cd..1b0e5a4d93 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -46,7 +46,6 @@ struct HitContext; struct IRenderListener; class CImageEx; class QMenu; -struct IDataBaseItem; /** Type of viewport. */ @@ -230,8 +229,6 @@ public: // Drag and drop support on viewports. // To be overrided in derived classes. ////////////////////////////////////////////////////////////////////////// - virtual bool CanDrop([[maybe_unused]] const QPoint& point, [[maybe_unused]] IDataBaseItem* pItem) { return false; }; - virtual void Drop([[maybe_unused]] const QPoint& point, [[maybe_unused]] IDataBaseItem* pItem) {}; virtual void SetGlobalDropCallback(DropCallback dropCallback, void* dropCallbackCustom) { m_dropCallback = dropCallback; diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index 888089fd72..90aa044d25 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -14,6 +14,7 @@ #include "ViewportTitleDlg.h" // Qt +#include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #include @@ -51,6 +53,8 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING #endif //! defined(Q_MOC_RUN) +static constexpr int MiniumOverflowMenuWidth = 200; + // CViewportTitleDlg dialog namespace @@ -257,21 +261,56 @@ void CViewportTitleDlg::SetupHelpersButton() void CViewportTitleDlg::SetupOverflowMenu() { - // Setup the overflow menu - QMenu* overFlowMenu = new QMenu(this); + // simple override of QMenu that does not respond to keyboard events + // note: this prevents the menu from being prematurely closed + class IgnoreKeyboardMenu : public QMenu + { + public: + IgnoreKeyboardMenu(QWidget *parent = nullptr) : QMenu(parent) + { + } - m_audioMuteAction = new QAction("Mute Audio", overFlowMenu); + private: + void keyPressEvent(QKeyEvent* event) override + { + // regular escape key handling + if (event->key() == Qt::Key_Escape) + { + QMenu::keyPressEvent(event); + } + } + }; + + // setup the overflow menu + auto* overflowMenu = new IgnoreKeyboardMenu(this); + overflowMenu->setMinimumWidth(MiniumOverflowMenuWidth); + + m_audioMuteAction = new QAction("Mute Audio", overflowMenu); connect(m_audioMuteAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedMuteAudio); - overFlowMenu->addAction(m_audioMuteAction); + overflowMenu->addAction(m_audioMuteAction); - overFlowMenu->addSeparator(); + overflowMenu->addSeparator(); - m_enableGridSnappingAction = new QAction("Enable Grid Snapping", overFlowMenu); - connect(m_enableGridSnappingAction, &QAction::triggered, this, &CViewportTitleDlg::OnGridSnappingToggled); - m_enableGridSnappingAction->setCheckable(true); - overFlowMenu->addAction(m_enableGridSnappingAction); + m_enableGridSnappingCheckBox = new QCheckBox("Enable Grid Snapping", overflowMenu); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_enableGridSnappingCheckBox); + auto gridSnappingWidgetAction = new QWidgetAction(overflowMenu); + gridSnappingWidgetAction->setDefaultWidget(m_enableGridSnappingCheckBox); + connect(m_enableGridSnappingCheckBox, &QCheckBox::stateChanged, this, &CViewportTitleDlg::OnGridSnappingToggled); + overflowMenu->addAction(gridSnappingWidgetAction); - m_gridSizeActionWidget = new QWidgetAction(overFlowMenu); + m_enableGridVisualizationCheckBox = new QCheckBox("Show Grid", overflowMenu); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_enableGridVisualizationCheckBox); + auto gridVisualizationWidgetAction = new QWidgetAction(overflowMenu); + gridVisualizationWidgetAction->setDefaultWidget(m_enableGridVisualizationCheckBox); + connect( + m_enableGridVisualizationCheckBox, &QCheckBox::stateChanged, + [](const int state) + { + SandboxEditor::SetShowingGrid(state == Qt::Checked); + }); + overflowMenu->addAction(gridVisualizationWidgetAction); + + m_gridSizeActionWidget = new QWidgetAction(overflowMenu); m_gridSpinBox = new AzQtComponents::DoubleSpinBox(); m_gridSpinBox->setValue(SandboxEditor::GridSnappingSize()); m_gridSpinBox->setMinimum(1e-2f); @@ -281,31 +320,33 @@ void CViewportTitleDlg::SetupOverflowMenu() m_gridSpinBox, QOverload::of(&AzQtComponents::DoubleSpinBox::valueChanged), this, &CViewportTitleDlg::OnGridSpinBoxChanged); m_gridSizeActionWidget->setDefaultWidget(m_gridSpinBox); - overFlowMenu->addAction(m_gridSizeActionWidget); + overflowMenu->addAction(m_gridSizeActionWidget); - overFlowMenu->addSeparator(); + overflowMenu->addSeparator(); - m_enableAngleSnappingAction = new QAction("Enable Angle Snapping", overFlowMenu); - connect(m_enableAngleSnappingAction, &QAction::triggered, this, &CViewportTitleDlg::OnAngleSnappingToggled); - m_enableAngleSnappingAction->setCheckable(true); - overFlowMenu->addAction(m_enableAngleSnappingAction); + m_enableAngleSnappingCheckBox = new QCheckBox("Enable Angle Snapping", overflowMenu); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_enableAngleSnappingCheckBox); + auto angleSnappingWidgetAction = new QWidgetAction(overflowMenu); + angleSnappingWidgetAction->setDefaultWidget(m_enableAngleSnappingCheckBox); + connect(m_enableAngleSnappingCheckBox, &QCheckBox::stateChanged, this, &CViewportTitleDlg::OnAngleSnappingToggled); + overflowMenu->addAction(angleSnappingWidgetAction); - m_angleSizeActionWidget = new QWidgetAction(overFlowMenu); + m_angleSizeActionWidget = new QWidgetAction(overflowMenu); m_angleSpinBox = new AzQtComponents::DoubleSpinBox(); m_angleSpinBox->setValue(SandboxEditor::AngleSnappingSize()); m_angleSpinBox->setMinimum(1e-2f); - m_angleSpinBox->setToolTip(tr("Angle Snapping")); + m_angleSpinBox->setToolTip(tr("Angle size")); QObject::connect( m_angleSpinBox, QOverload::of(&AzQtComponents::DoubleSpinBox::valueChanged), this, &CViewportTitleDlg::OnAngleSpinBoxChanged); m_angleSizeActionWidget->setDefaultWidget(m_angleSpinBox); - overFlowMenu->addAction(m_angleSizeActionWidget); + overflowMenu->addAction(m_angleSizeActionWidget); - m_ui->m_overflowBtn->setMenu(overFlowMenu); + m_ui->m_overflowBtn->setMenu(overflowMenu); m_ui->m_overflowBtn->setPopupMode(QToolButton::InstantPopup); - connect(overFlowMenu, &QMenu::aboutToShow, this, &CViewportTitleDlg::UpdateOverFlowMenuState); + connect(overflowMenu, &QMenu::aboutToShow, this, &CViewportTitleDlg::UpdateOverFlowMenuState); UpdateMuteActionText(); } @@ -982,43 +1023,49 @@ void CViewportTitleDlg::CheckForCameraSpeedUpdate() } } -void CViewportTitleDlg::OnGridSnappingToggled() +void CViewportTitleDlg::OnGridSnappingToggled(const int state) { - m_gridSizeActionWidget->setEnabled(m_enableGridSnappingAction->isChecked()); + m_gridSizeActionWidget->setEnabled(state == Qt::Checked); + m_enableGridVisualizationCheckBox->setEnabled(state == Qt::Checked); MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::SnapToGrid)->trigger(); } -void CViewportTitleDlg::OnAngleSnappingToggled() +void CViewportTitleDlg::OnAngleSnappingToggled(const int state) { - m_angleSizeActionWidget->setEnabled(m_enableAngleSnappingAction->isChecked()); + m_angleSizeActionWidget->setEnabled(state == Qt::Checked); MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::SnapAngle)->trigger(); } -void CViewportTitleDlg::OnGridSpinBoxChanged(double value) +void CViewportTitleDlg::OnGridSpinBoxChanged(const double value) { - SandboxEditor::SetGridSnappingSize(static_cast(value)); + SandboxEditor::SetGridSnappingSize(aznumeric_cast(value)); } -void CViewportTitleDlg::OnAngleSpinBoxChanged(double value) +void CViewportTitleDlg::OnAngleSpinBoxChanged(const double value) { - SandboxEditor::SetAngleSnappingSize(static_cast(value)); + SandboxEditor::SetAngleSnappingSize(aznumeric_cast(value)); } void CViewportTitleDlg::UpdateOverFlowMenuState() { - bool gridSnappingActive = MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::SnapToGrid)->isChecked(); + const bool gridSnappingActive = MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::SnapToGrid)->isChecked(); { - QSignalBlocker signalBlocker(m_enableGridSnappingAction); - m_enableGridSnappingAction->setChecked(gridSnappingActive); + QSignalBlocker signalBlocker(m_enableGridSnappingCheckBox); + m_enableGridSnappingCheckBox->setChecked(gridSnappingActive); } m_gridSizeActionWidget->setEnabled(gridSnappingActive); - bool angleSnappingActive = MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::SnapAngle)->isChecked(); + const bool angleSnappingActive = MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::SnapAngle)->isChecked(); { - QSignalBlocker signalBlocker(m_enableAngleSnappingAction); - m_enableAngleSnappingAction->setChecked(angleSnappingActive); + QSignalBlocker signalBlocker(m_enableAngleSnappingCheckBox); + m_enableAngleSnappingCheckBox->setChecked(angleSnappingActive); } m_angleSizeActionWidget->setEnabled(angleSnappingActive); + + { + QSignalBlocker signalBlocker(m_enableGridVisualizationCheckBox); + m_enableGridVisualizationCheckBox->setChecked(SandboxEditor::ShowingGrid()); + } } namespace diff --git a/Code/Editor/ViewportTitleDlg.h b/Code/Editor/ViewportTitleDlg.h index ba3dba858a..b8da7f20ea 100644 --- a/Code/Editor/ViewportTitleDlg.h +++ b/Code/Editor/ViewportTitleDlg.h @@ -140,8 +140,8 @@ protected: void CheckForCameraSpeedUpdate(); - void OnGridSnappingToggled(); - void OnAngleSnappingToggled(); + void OnGridSnappingToggled(int state); + void OnAngleSnappingToggled(int state); void OnGridSpinBoxChanged(double value); void OnAngleSpinBoxChanged(double value); @@ -160,8 +160,9 @@ protected: QAction* m_fullInformationAction = nullptr; QAction* m_compactInformationAction = nullptr; QAction* m_audioMuteAction = nullptr; - QAction* m_enableGridSnappingAction = nullptr; - QAction* m_enableAngleSnappingAction = nullptr; + QCheckBox* m_enableGridSnappingCheckBox = nullptr; + QCheckBox* m_enableGridVisualizationCheckBox = nullptr; + QCheckBox* m_enableAngleSnappingCheckBox = nullptr; QComboBox* m_cameraSpeed = nullptr; AzQtComponents::DoubleSpinBox* m_gridSpinBox = nullptr; AzQtComponents::DoubleSpinBox* m_angleSpinBox = nullptr; @@ -175,7 +176,7 @@ protected: namespace AzToolsFramework { - //! A component to reflect scriptable commands for the Editor + //! A component to reflect scriptable commands for the Editor. class ViewportTitleDlgPythonFuncsHandler : public AZ::Component { diff --git a/Code/Editor/editor_core_files.cmake b/Code/Editor/editor_core_files.cmake index 53dd8d79a5..1f0a5a3618 100644 --- a/Code/Editor/editor_core_files.cmake +++ b/Code/Editor/editor_core_files.cmake @@ -7,17 +7,12 @@ # set(FILES - BaseLibrary.h - BaseLibraryItem.h UsedResources.h UIEnumsDatabase.h Include/EditorCoreAPI.cpp Include/IErrorReport.h - Include/IBaseLibraryManager.h Include/IFileUtil.h Include/EditorCoreAPI.h - Include/IEditorMaterial.h - Include/IEditorMaterialManager.h Include/IImageUtil.h Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.qrc Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp @@ -35,8 +30,6 @@ set(FILES Controls/QBitmapPreviewDialogImp.h Controls/QToolTipWidget.h Controls/QToolTipWidget.cpp - BaseLibraryItem.cpp - BaseLibrary.cpp UsedResources.cpp UIEnumsDatabase.cpp LyViewPaneNames.h diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index a63a74f01d..59a1a91647 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -269,14 +269,8 @@ set(FILES LevelTreeModel.h Include/Command.h Include/HitContext.h - Include/IAnimationCompressionManager.h - Include/IAssetItem.h - Include/IAssetItemDatabase.h Include/ICommandManager.h Include/IConsoleConnectivity.h - Include/IDataBaseItem.h - Include/IDataBaseLibrary.h - Include/IDataBaseManager.h Include/IDisplayViewport.h Include/IEditorClassFactory.h Include/IEventLoopHook.h @@ -334,23 +328,12 @@ set(FILES Controls/ConsoleSCB.qrc Controls/FolderTreeCtrl.cpp Controls/FolderTreeCtrl.h - Controls/HotTrackingTreeCtrl.cpp - Controls/HotTrackingTreeCtrl.h Controls/ImageHistogramCtrl.cpp Controls/ImageHistogramCtrl.h - Controls/ImageListCtrl.cpp - Controls/ImageListCtrl.h - Controls/MultiMonHelper.cpp - Controls/MultiMonHelper.h - Controls/NumberCtrl.cpp - Controls/NumberCtrl.h - Controls/NumberCtrl.h Controls/SplineCtrl.cpp Controls/SplineCtrl.h Controls/SplineCtrlEx.cpp Controls/SplineCtrlEx.h - Controls/TextEditorCtrl.cpp - Controls/TextEditorCtrl.h Controls/TimelineCtrl.cpp Controls/TimelineCtrl.h Controls/WndGridHelper.h @@ -383,9 +366,6 @@ set(FILES ActionManager.h ShortcutDispatcher.cpp ShortcutDispatcher.h - BaseLibraryManager.cpp - BaseLibraryItem.h - BaseLibraryManager.h CheckOutDialog.cpp CheckOutDialog.h CheckOutDialog.ui @@ -468,18 +448,14 @@ set(FILES GameResourcesExporter.cpp GameExporter.h GameResourcesExporter.h - Geometry/TriMesh.cpp - Geometry/TriMesh.h AboutDialog.h AboutDialog.ui DocMultiArchive.h - EditMode/DeepSelection.h FBXExporterDialog.h FileTypeUtils.h GridUtils.h IObservable.h IPostRenderer.h - LightmapCompiler/SimpleTriangleRasterizer.h ToolBox.h TrackViewNewSequenceDialog.h UndoConfigSpec.h @@ -570,11 +546,9 @@ set(FILES AboutDialog.cpp ErrorReportTableModel.h ErrorReportTableModel.cpp - EditMode/DeepSelection.cpp FBXExporterDialog.cpp FBXExporterDialog.ui FileTypeUtils.cpp - LightmapCompiler/SimpleTriangleRasterizer.cpp ToolBox.cpp TrackViewNewSequenceDialog.cpp TrackViewNewSequenceDialog.ui @@ -796,9 +770,6 @@ set(FILES ViewportTitleDlg.h EditorEnvironment.cpp EditorEnvironment.h - IEditorPanelUtils.h - EditorPanelUtils.h - EditorPanelUtils.cpp ) diff --git a/Code/Framework/AzCore/AzCore/Math/Plane.inl b/Code/Framework/AzCore/AzCore/Math/Plane.inl index 795ee8b4bc..22c449dc6f 100644 --- a/Code/Framework/AzCore/AzCore/Math/Plane.inl +++ b/Code/Framework/AzCore/AzCore/Math/Plane.inl @@ -26,7 +26,6 @@ namespace AZ AZ_MATH_INLINE Plane Plane::CreateFromNormalAndDistance(const Vector3& normal, float dist) { - AZ_MATH_ASSERT(normal.IsNormalized(), "This normal is not normalized"); Plane result; result.Set(normal, dist); return result; @@ -35,7 +34,6 @@ namespace AZ AZ_MATH_INLINE Plane Plane::CreateFromCoefficients(const float a, const float b, const float c, const float d) { - AZ_MATH_ASSERT(Vector3(a, b, c).IsNormalized(), "This normal is notormalized"); Plane result; result.Set(a, b, c, d); return result; @@ -68,21 +66,21 @@ namespace AZ AZ_MATH_INLINE void Plane::Set(const Vector3& normal, float d) { - AZ_MATH_ASSERT(normal.IsNormalized(), "This normal is notormalized"); + AZ_MATH_ASSERT(normal.IsNormalized(), "This normal is not normalized"); m_plane.Set(normal, d); } AZ_MATH_INLINE void Plane::Set(float a, float b, float c, float d) { - AZ_MATH_ASSERT(Vector3(a, b, c).IsNormalized(), "This normal is notormalized"); + AZ_MATH_ASSERT(Vector3(a, b, c).IsNormalized(), "This normal is not normalized"); m_plane.Set(a, b, c, d); } AZ_MATH_INLINE void Plane::SetNormal(const Vector3& normal) { - AZ_MATH_ASSERT(normal.IsNormalized(), "This normal is notormalized"); + AZ_MATH_ASSERT(normal.IsNormalized(), "This normal is not normalized"); m_plane.SetX(normal.GetX()); m_plane.SetY(normal.GetY()); m_plane.SetZ(normal.GetZ()); diff --git a/Code/Framework/AzCore/AzCore/Memory/AllocatorBase.cpp b/Code/Framework/AzCore/AzCore/Memory/AllocatorBase.cpp index 5c510f67c1..c2bf9fe45c 100644 --- a/Code/Framework/AzCore/AzCore/Memory/AllocatorBase.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/AllocatorBase.cpp @@ -6,8 +6,155 @@ * */ -#include #include +#include + +#define RECORDING_ENABLED 0 + +#if RECORDING_ENABLED + +#include +#include +#include +#include + +namespace +{ + class DebugAllocator + { + public: + using pointer_type = void*; + using size_type = AZStd::size_t; + using difference_type = AZStd::ptrdiff_t; + using allow_memory_leaks = AZStd::false_type; ///< Regular allocators should not leak. + + AZ_FORCE_INLINE pointer_type allocate(size_t byteSize, size_t alignment, int = 0) + { + return AZ_OS_MALLOC(byteSize, alignment); + } + AZ_FORCE_INLINE size_type resize(pointer_type, size_type) + { + return 0; + } + AZ_FORCE_INLINE void deallocate(pointer_type ptr, size_type, size_type) + { + AZ_OS_FREE(ptr); + } + }; + + #pragma pack(push, 1) + struct alignas(1) AllocatorOperation + { + enum OperationType : size_t + { + ALLOCATE, + DEALLOCATE + }; + OperationType m_type: 1; + size_t m_size : 28; // Can represent up to 256Mb requests + size_t m_alignment : 7; // Can represent up to 128 alignment + size_t m_recordId : 28; // Can represent up to 256M simultaneous requests, we reuse ids + }; + #pragma pack(pop) + static_assert(sizeof(AllocatorOperation) == 8); + + static AZStd::mutex s_operationsMutex = {}; + + static constexpr size_t s_maxNumberOfAllocationsToRecord = 16384; + static size_t s_numberOfAllocationsRecorded = 0; + static constexpr size_t s_allocationOperationCount = 5 * 1024; + static AZStd::array s_operations = {}; + static uint64_t s_operationCounter = 0; + + static unsigned int s_nextRecordId = 1; + using AllocatorOperationByAddress = AZStd::unordered_map, DebugAllocator>; + static AllocatorOperationByAddress s_allocatorOperationByAddress; + using AvailableRecordIds = AZStd::vector; + AvailableRecordIds s_availableRecordIds; + + void RecordAllocatorOperation(AllocatorOperation::OperationType type, void* ptr, size_t size = 0, size_t alignment = 0) + { + AZStd::scoped_lock lock(s_operationsMutex); + if (s_operationCounter == s_allocationOperationCount) + { + AZ::IO::SystemFile file; + int mode = AZ::IO::SystemFile::OpenMode::SF_OPEN_APPEND | AZ::IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY; + if (!file.Exists("memoryrecordings.bin")) + { + mode |= AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE; + } + file.Open("memoryrecordings.bin", mode); + if (file.IsOpen()) + { + file.Write(&s_operations, sizeof(AllocatorOperation) * s_allocationOperationCount); + file.Close(); + } + s_operationCounter = 0; + } + AllocatorOperation& operation = s_operations[s_operationCounter++]; + operation.m_type = type; + if (type == AllocatorOperation::OperationType::ALLOCATE) + { + if (s_numberOfAllocationsRecorded > s_maxNumberOfAllocationsToRecord) + { + // reached limit of allocations, dont record anymore + --s_operationCounter; + return; + } + ++s_numberOfAllocationsRecorded; + operation.m_size = size; + operation.m_alignment = alignment; + unsigned int recordId = 0; + if (!s_availableRecordIds.empty()) + { + recordId = s_availableRecordIds.back(); + s_availableRecordIds.pop_back(); + } + else + { + recordId = s_nextRecordId; + ++s_nextRecordId; + } + operation.m_recordId = recordId; + auto it = s_allocatorOperationByAddress.emplace(ptr, operation); + if (!it.second) + { + // double alloc or resize, leave the current record and return the id + operation = it.first->second; + s_availableRecordIds.emplace_back(recordId); + } + } + else + { + if (ptr == nullptr) + { + // common scenario, just record the operation + operation.m_size = 0; + operation.m_alignment = 0; + operation.m_recordId = 0; // recordId = 0 will flag this case + } + else + { + auto it = s_allocatorOperationByAddress.find(ptr); + if (it != s_allocatorOperationByAddress.end()) + { + operation.m_size = it->second.m_size; + operation.m_alignment = it->second.m_alignment; + operation.m_recordId = it->second.m_recordId; + s_availableRecordIds.push_back(it->second.m_recordId); + s_allocatorOperationByAddress.erase(it); + } + else + { + // just dont record this operation + --s_operationCounter; + } + } + } + + } +} +#endif namespace AZ { @@ -150,6 +297,10 @@ namespace AZ records->RegisterAllocation(ptr, byteSize, alignment, name, fileName, lineNum, suppressStackRecord + 1); } } + +#if RECORDING_ENABLED + RecordAllocatorOperation(AllocatorOperation::ALLOCATE, ptr, byteSize, alignment); +#endif } void AllocatorBase::ProfileDeallocation(void* ptr, size_t byteSize, size_t alignment, Debug::AllocationInfo* info) @@ -162,6 +313,9 @@ namespace AZ records->UnregisterAllocation(ptr, byteSize, alignment, info); } } +#if RECORDING_ENABLED + RecordAllocatorOperation(AllocatorOperation::DEALLOCATE, ptr, byteSize, alignment); +#endif } void AllocatorBase::ProfileReallocationBegin([[maybe_unused]] void* ptr, [[maybe_unused]] size_t newSize) @@ -176,6 +330,10 @@ namespace AZ ProfileDeallocation(ptr, 0, 0, &info); ProfileAllocation(newPtr, newSize, newAlignment, info.m_name, info.m_fileName, info.m_lineNum, 0); } +#if RECORDING_ENABLED + RecordAllocatorOperation(AllocatorOperation::DEALLOCATE, ptr); + RecordAllocatorOperation(AllocatorOperation::ALLOCATE, newPtr, newSize, newAlignment); +#endif } void AllocatorBase::ProfileReallocation(void* ptr, void* newPtr, size_t newSize, size_t newAlignment) @@ -193,6 +351,9 @@ namespace AZ records->ResizeAllocation(ptr, newSize); } } +#if RECORDING_ENABLED + RecordAllocatorOperation(AllocatorOperation::ALLOCATE, ptr, newSize); +#endif } bool AllocatorBase::OnOutOfMemory(size_t byteSize, size_t alignment, int flags, const char* name, const char* fileName, int lineNum) diff --git a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp index aceafa1b28..1f0fc59a97 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp @@ -115,6 +115,7 @@ namespace AZ m_ownMemoryBlock[i] = false; } + AZ_Assert(m_desc.m_numMemoryBlocks > 0, "At least one memory block is required"); for (int i = 0; i < m_desc.m_numMemoryBlocks; ++i) { if (m_desc.m_memoryBlocks[i] == nullptr) // Allocate memory block if requested! @@ -131,17 +132,6 @@ namespace AZ m_capacity += m_desc.m_memoryBlocksByteSize[i]; } - - if (m_desc.m_numMemoryBlocks == 0) - { - // Create default memory space if we can to serve for default allocations - m_memSpaces[0] = AZDLMalloc::create_mspace(0, m_desc.m_isMultithreadAlloc); - if (m_memSpaces[0]) - { - AZDLMalloc::mspace_az_set_expandable(m_memSpaces[0], true); - m_capacity = Platform::GetHeapCapacity(); - } - } } HeapSchema::~HeapSchema() diff --git a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h index f72ae31057..3a7716a127 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h @@ -32,17 +32,11 @@ namespace AZ */ struct Descriptor { - Descriptor() - : m_numMemoryBlocks(0) - , m_isMultithreadAlloc(true) - {} - - static const int m_memoryBlockAlignment = 64 * 1024; static const int m_maxNumBlocks = 5; - int m_numMemoryBlocks; ///< Number of memory blocks to use. - void* m_memoryBlocks[m_maxNumBlocks]; ///< Pointers to provided memory blocks or NULL if you want the system to allocate them for you with the System Allocator. - size_t m_memoryBlocksByteSize[m_maxNumBlocks]; ///< Sizes of different memory blocks, if m_memoryBlock is 0 the block will be allocated for you with the System Allocator. - bool m_isMultithreadAlloc; ///< Set to true to enable multi threading safe allocation. + int m_numMemoryBlocks = 1; ///< Number of memory blocks to use. + void* m_memoryBlocks[m_maxNumBlocks] = {}; ///< Pointers to provided memory blocks or NULL if you want the system to allocate them for you with the System Allocator. + size_t m_memoryBlocksByteSize[m_maxNumBlocks] = {4 * 1024}; ///< Sizes of different memory blocks, if m_memoryBlock is 0 the block will be allocated for you with the System Allocator. + bool m_isMultithreadAlloc = true; ///< Set to true to enable multi threading safe allocation. }; HeapSchema(const Descriptor& desc); diff --git a/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp b/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp index 15cf5de8bc..41099f7a38 100644 --- a/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp @@ -18,7 +18,6 @@ #define AZCORE_SYSTEM_ALLOCATOR_HPHA 1 #define AZCORE_SYSTEM_ALLOCATOR_MALLOC 2 -#define AZCORE_SYSTEM_ALLOCATOR_HEAP 3 #if !defined(AZCORE_SYSTEM_ALLOCATOR) // define the default @@ -29,8 +28,6 @@ #include #elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC #include -#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP - #include #else #error "Invalid allocator selected for SystemAllocator" #endif @@ -44,8 +41,6 @@ namespace AZ static AZStd::aligned_storage::value>::type g_systemSchema; #elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC static AZStd::aligned_storage::value>::type g_systemSchema; -#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP - static AZStd::aligned_storage::value>::type g_systemSchema; #endif ////////////////////////////////////////////////////////////////////////// @@ -118,11 +113,6 @@ namespace AZ heapDesc.m_systemChunkSize = desc.m_heap.m_systemChunkSize; #elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC MallocSchema::Descriptor heapDesc; -#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP - HeapSchema::Descriptor heapDesc; - memcpy(heapDesc.m_memoryBlocks, desc.m_heap.m_memoryBlocks, sizeof(heapDesc.m_memoryBlocks)); - memcpy(heapDesc.m_memoryBlocksByteSize, desc.m_heap.m_memoryBlocksByteSize, sizeof(heapDesc.m_memoryBlocksByteSize)); - heapDesc.m_numMemoryBlocks = desc.m_heap.m_numMemoryBlocks; #endif if (&AllocatorInstance::Get() == this) // if we are the system allocator { @@ -132,8 +122,6 @@ namespace AZ m_allocator = new (&g_systemSchema) HphaSchema(heapDesc); #elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC m_allocator = new (&g_systemSchema) MallocSchema(heapDesc); -#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP - m_allocator = new (&g_systemSchema) HeapSchema(heapDesc); #endif g_isSystemSchemaUsed = true; isReady = true; @@ -149,8 +137,6 @@ namespace AZ m_allocator = azcreate(HphaSchema, (heapDesc), SystemAllocator); #elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC m_allocator = azcreate(MallocSchema, (heapDesc), SystemAllocator); -#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP - m_allocator = azcreate(HeapSchema, (heapDesc), SystemAllocator); #endif if (m_allocator == nullptr) { @@ -186,8 +172,6 @@ namespace AZ static_cast(m_allocator)->~HphaSchema(); #elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC static_cast(m_allocator)->~MallocSchema(); -#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP - static_cast(m_allocator)->~HeapSchema(); #endif g_isSystemSchemaUsed = false; } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.h b/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.h index dd10e2bff6..202efd3749 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.h @@ -45,9 +45,8 @@ namespace AZ } else { - SerializerMap::const_iterator serializerIter = m_jsonSerializers.find(typeId); - AZ_Assert(serializerIter != m_jsonSerializers.end(), "Attempting to unregister a serializer that has not been registered yet with typeid %s", typeId.ToString().c_str()); - m_jsonSerializers.erase(serializerIter); + [[maybe_unused]] size_t erased = m_jsonSerializers.erase(typeId); + AZ_Assert(erased == 1, "Attempting to unregister a serializer that has not been registered yet with typeid %s", typeId.ToString().c_str()); return SerializerBuilder(this, m_jsonSerializers.end()); } } diff --git a/Code/Framework/AzCore/CMakeLists.txt b/Code/Framework/AzCore/CMakeLists.txt index 96ed838ccc..838142f0df 100644 --- a/Code/Framework/AzCore/CMakeLists.txt +++ b/Code/Framework/AzCore/CMakeLists.txt @@ -146,6 +146,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PROPERTY COMPILE_DEFINITIONS VALUES AZCORETEST_DLL_NAME=\"$\" ) + ly_add_target_files( + TARGETS AzCore.Tests + FILES ${CMAKE_CURRENT_SOURCE_DIR}/Tests/Memory/AllocatorBenchmarkRecordings.bin + OUTPUT_SUBDIRECTORY Tests/AzCore/Memory + ) endif() diff --git a/Code/Framework/AzCore/Tests/Math/MathTest.h b/Code/Framework/AzCore/Tests/Math/MathTest.h new file mode 100644 index 0000000000..783c08a553 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Math/MathTest.h @@ -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 + * + */ + +#pragma once + +#include + +#if AZ_DEBUG_BUILD + #define AZ_MATH_TEST_START_TRACE_SUPPRESSION AZ_TEST_START_TRACE_SUPPRESSION + #define AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(x) AZ_TEST_STOP_TRACE_SUPPRESSION(x) +#else + #define AZ_MATH_TEST_START_TRACE_SUPPRESSION + #define AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(x) +#endif diff --git a/Code/Framework/AzCore/Tests/Math/PlaneTests.cpp b/Code/Framework/AzCore/Tests/Math/PlaneTests.cpp index 016a7ec6e2..398c1320ed 100644 --- a/Code/Framework/AzCore/Tests/Math/PlaneTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/PlaneTests.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace AZ; @@ -47,7 +48,9 @@ namespace UnitTest TEST(MATH_Plane, TestSet) { Plane pl; + AZ_MATH_TEST_START_TRACE_SUPPRESSION; pl.Set(12.0f, 13.0f, 14.0f, 15.0f); + AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(1); AZ_TEST_ASSERT_FLOAT_CLOSE(pl.GetDistance(), 15.0f); AZ_TEST_ASSERT_FLOAT_CLOSE(pl.GetNormal().GetX(), 12.0f); AZ_TEST_ASSERT_FLOAT_CLOSE(pl.GetNormal().GetY(), 13.0f); @@ -57,7 +60,9 @@ namespace UnitTest TEST(MATH_Plane, TestSetVector3) { Plane pl; + AZ_MATH_TEST_START_TRACE_SUPPRESSION; pl.Set(Vector3(22.0f, 23.0f, 24.0f), 25.0f); + AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(1); AZ_TEST_ASSERT_FLOAT_CLOSE(pl.GetDistance(), 25.0f); AZ_TEST_ASSERT_FLOAT_CLOSE(pl.GetNormal().GetX(), 22.0f); AZ_TEST_ASSERT_FLOAT_CLOSE(pl.GetNormal().GetY(), 23.0f); @@ -177,17 +182,21 @@ namespace UnitTest pl.Set(1.0f, 0.0f, 0.0f, 0.0f); AZ_TEST_ASSERT(pl.IsFinite()); const float infinity = std::numeric_limits::infinity(); + AZ_MATH_TEST_START_TRACE_SUPPRESSION; pl.Set(infinity, infinity, infinity, infinity); + AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(1); AZ_TEST_ASSERT(!pl.IsFinite()); } TEST(MATH_Plane, CreateFromVectorCoefficients_IsEquivalentToCreateFromCoefficients) { + AZ_MATH_TEST_START_TRACE_SUPPRESSION; Plane planeFromCoefficients = Plane::CreateFromCoefficients(1.0, 2.0, 3.0, 4.0); - + AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(1); Vector4 coefficients(1.0, 2.0, 3.0, 4.0); Plane planeFromVectorCoefficients = Plane::CreateFromVectorCoefficients(coefficients); + EXPECT_EQ(planeFromVectorCoefficients, planeFromCoefficients); } } diff --git a/Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarkRecordings.bin b/Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarkRecordings.bin new file mode 100644 index 0000000000..ec5de82e83 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarkRecordings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:281ba03e79ecba90b313a0b17bdba87c57d76b504b6e38d579b5eabd995902cc +size 245760 diff --git a/Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarks.cpp b/Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarks.cpp new file mode 100644 index 0000000000..bc477e41dc --- /dev/null +++ b/Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarks.cpp @@ -0,0 +1,591 @@ +/* + * 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 + * + */ + +#if defined(HAVE_BENCHMARK) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Benchmark +{ + namespace Platform + { + size_t GetProcessMemoryUsageBytes(); + size_t GetMemorySize(void* memory); + } + + /// + /// Test allocator wrapper that redirects the calls to the passed TAllocator by using AZ::AllocatorInstance. + /// It also creates/destroys the TAllocator type (to reflect what happens at runtime) + /// + /// Allocator type to wrap + template + class TestAllocatorWrapper + { + public: + static void SetUp() + { + AZ::AllocatorInstance::Create(); + } + + static void TearDown() + { + AZ::AllocatorInstance::Destroy(); + } + + static void* Allocate(size_t byteSize, size_t alignment) + { + return AZ::AllocatorInstance::Get().Allocate(byteSize, alignment); + } + + static void DeAllocate(void* ptr, size_t byteSize = 0) + { + AZ::AllocatorInstance::Get().DeAllocate(ptr, byteSize); + } + + static void* ReAllocate(void* ptr, size_t newSize, size_t newAlignment) + { + return AZ::AllocatorInstance::Get().ReAllocate(ptr, newSize, newAlignment); + } + + static size_t Resize(void* ptr, size_t newSize) + { + return AZ::AllocatorInstance::Get().Resize(ptr, newSize); + } + + static void GarbageCollect() + { + AZ::AllocatorInstance::Get().GarbageCollect(); + } + + static size_t NumAllocatedBytes() + { + return AZ::AllocatorInstance::Get().NumAllocatedBytes() + + AZ::AllocatorInstance::Get().GetUnAllocatedMemory(); + } + + static size_t GetSize(void* ptr) + { + return AZ::AllocatorInstance::Get().AllocationSize(ptr); + } + }; + + /// + /// Basic allocator used as a baseline. This allocator is the most basic allocation possible with the OS (AZ_OS_MALLOC). + /// MallocSchema cannot be used here because it has extra logic that we don't want to use as a baseline. + /// + class RawMallocAllocator {}; + + template<> + class TestAllocatorWrapper + { + public: + TestAllocatorWrapper() + { + s_numAllocatedBytes = 0; + } + + static void SetUp() + { + s_numAllocatedBytes = 0; + } + + static void TearDown() + { + } + + // IAllocatorAllocate + static void* Allocate(size_t byteSize, size_t) + { + s_numAllocatedBytes += byteSize; + // Don't pass an alignment since we wont be able to get the memory size without also passing the alignment + return AZ_OS_MALLOC(byteSize, 1); + } + + static void DeAllocate(void* ptr, size_t = 0) + { + s_numAllocatedBytes -= Platform::GetMemorySize(ptr); + AZ_OS_FREE(ptr); + } + + static void* ReAllocate(void* ptr, size_t newSize, size_t) + { + s_numAllocatedBytes -= Platform::GetMemorySize(ptr); + AZ_OS_FREE(ptr); + + s_numAllocatedBytes += newSize; + return AZ_OS_MALLOC(newSize, 1); + } + + static size_t Resize(void* ptr, size_t newSize) + { + AZ_UNUSED(ptr); + AZ_UNUSED(newSize); + + return 0; + } + + static void GarbageCollect() {} + + static size_t NumAllocatedBytes() + { + return s_numAllocatedBytes; + } + + static size_t GetSize(void* ptr) + { + return Platform::GetMemorySize(ptr); + } + + private: + static size_t s_numAllocatedBytes; + }; + + size_t TestAllocatorWrapper::s_numAllocatedBytes = 0; + + // Some allocator are not fully declared, those we simply setup from the schema + class MallocSchemaAllocator : public AZ::SimpleSchemaAllocator + { + public: + AZ_TYPE_INFO(MallocSchemaAllocator, "{3E68224F-E676-402C-8276-CE4B49C05E89}"); + + MallocSchemaAllocator() + : AZ::SimpleSchemaAllocator("MallocSchemaAllocator", "") + {} + }; + + // We use both this HphaSchemaAllocator and the SystemAllocator configured with Hpha because the SystemAllocator + // has extra things + class HphaSchemaAllocator : public AZ::SimpleSchemaAllocator + { + public: + AZ_TYPE_INFO(HphaSchemaAllocator, "{6563AB4B-A68E-4499-8C98-D61D640D1F7F}"); + + HphaSchemaAllocator() + : AZ::SimpleSchemaAllocator("TestHphaSchemaAllocator", "") + {} + }; + + // For the SystemAllocator we inherit so we have a different stack. The SystemAllocator is used globally so we dont want + // to get that data affecting the benchmark + class TestSystemAllocator : public AZ::SystemAllocator + { + public: + AZ_TYPE_INFO(TestSystemAllocator, "{360D4DAA-D65D-4D5C-A6FA-1A4C5261C35C}"); + + TestSystemAllocator() + : AZ::SystemAllocator() + { + } + }; + + // Allocated bytes reported by the allocator + static const char* s_counterAllocatorMemory = "Allocator_Memory"; + + // Allocated bytes as counted by the benchmark + static const char* s_counterBenchmarkMemory = "Benchmark_Memory"; + + enum AllocationSize + { + SMALL, + BIG, + MIXED, + COUNT + }; + + static const size_t s_kiloByte = 1024; + static const size_t s_megaByte = s_kiloByte * s_kiloByte; + using AllocationSizeArray = AZStd::array; + static const AZStd::array s_allocationSizes = { + /* SMALL */ AllocationSizeArray{ 2, 16, 20, 59, 100, 128, 160, 250, 300, 512 }, + /* BIG */ AllocationSizeArray{ 513, s_kiloByte, 2 * s_kiloByte, 4 * s_kiloByte, 10 * s_kiloByte, 64 * s_kiloByte, 128 * s_kiloByte, 200 * s_kiloByte, s_megaByte, 2 * s_megaByte }, + /* MIXED */ AllocationSizeArray{ 2, s_kiloByte, 59, 4 * s_kiloByte, 128, 200 * s_kiloByte, 250, s_megaByte, 512, 2 * s_megaByte } + }; + + template + class AllocatorBenchmarkFixture + : public ::benchmark::Fixture + { + protected: + using TestAllocatorType = TestAllocatorWrapper; + + virtual void internalSetUp(const ::benchmark::State& state) + { + if (state.thread_index == 0) // Only setup in the first thread + { + TestAllocatorType::SetUp(); + + m_allocations.resize(state.threads); + for (auto& perThreadAllocations : m_allocations) + { + perThreadAllocations.resize(state.range(0), nullptr); + } + } + } + + virtual void internalTearDown(const ::benchmark::State& state) + { + if (state.thread_index == 0) // Only setup in the first thread + { + m_allocations.clear(); + m_allocations.shrink_to_fit(); + + TestAllocatorType::TearDown(); + } + } + + AZStd::vector& GetPerThreadAllocations(size_t threadIndex) + { + return m_allocations[threadIndex]; + } + + public: + void SetUp(const ::benchmark::State& state) override + { + internalSetUp(state); + } + void SetUp(::benchmark::State& state) override + { + internalSetUp(state); + } + + void TearDown(const ::benchmark::State& state) override + { + internalTearDown(state); + } + void TearDown(::benchmark::State& state) override + { + internalTearDown(state); + } + + private: + AZStd::vector> m_allocations; + }; + + template + class AllocationBenchmarkFixture + : public AllocatorBenchmarkFixture + { + using base = AllocatorBenchmarkFixture; + using TestAllocatorType = typename base::TestAllocatorType; + + public: + void Benchmark(benchmark::State& state) + { + for (auto _ : state) + { + state.PauseTiming(); + + AZStd::vector& perThreadAllocations = base::GetPerThreadAllocations(state.thread_index); + const size_t numberOfAllocations = perThreadAllocations.size(); + size_t totalAllocationSize = 0; + for (size_t allocationIndex = 0; allocationIndex < numberOfAllocations; ++allocationIndex) + { + const AllocationSizeArray& allocationArray = s_allocationSizes[TAllocationSize]; + const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()]; + totalAllocationSize += allocationSize; + + state.ResumeTiming(); + perThreadAllocations[allocationIndex] = TestAllocatorType::Allocate(allocationSize, 0); + state.PauseTiming(); + } + + state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast(TestAllocatorType::NumAllocatedBytes()), benchmark::Counter::kDefaults); + state.counters[s_counterBenchmarkMemory] = benchmark::Counter(static_cast(totalAllocationSize), benchmark::Counter::kDefaults); + + for (size_t allocationIndex = 0; allocationIndex < numberOfAllocations; ++allocationIndex) + { + const AllocationSizeArray& allocationArray = s_allocationSizes[TAllocationSize]; + const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()]; + TestAllocatorType::DeAllocate(perThreadAllocations[allocationIndex], allocationSize); + perThreadAllocations[allocationIndex] = nullptr; + } + TestAllocatorType::GarbageCollect(); + + state.SetItemsProcessed(numberOfAllocations); + } + } + }; + + template + class DeAllocationBenchmarkFixture + : public AllocatorBenchmarkFixture + { + using base = AllocatorBenchmarkFixture; + using TestAllocatorType = typename base::TestAllocatorType; + + public: + void Benchmark(benchmark::State& state) + { + for (auto _ : state) + { + state.PauseTiming(); + AZStd::vector& perThreadAllocations = base::GetPerThreadAllocations(state.thread_index); + + const size_t numberOfAllocations = perThreadAllocations.size(); + size_t totalAllocationSize = 0; + for (size_t allocationIndex = 0; allocationIndex < numberOfAllocations; ++allocationIndex) + { + const AllocationSizeArray& allocationArray = s_allocationSizes[TAllocationSize]; + const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()]; + totalAllocationSize += allocationSize; + perThreadAllocations[allocationIndex] = TestAllocatorType::Allocate(allocationSize, 0); + } + + for (size_t allocationIndex = 0; allocationIndex < numberOfAllocations; ++allocationIndex) + { + const AllocationSizeArray& allocationArray = s_allocationSizes[TAllocationSize]; + const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()]; + state.ResumeTiming(); + TestAllocatorType::DeAllocate(perThreadAllocations[allocationIndex], allocationSize); + state.PauseTiming(); + perThreadAllocations[allocationIndex] = nullptr; + } + + state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast(TestAllocatorType::NumAllocatedBytes()), benchmark::Counter::kDefaults); + state.counters[s_counterBenchmarkMemory] = benchmark::Counter(static_cast(totalAllocationSize), benchmark::Counter::kDefaults); + + state.SetItemsProcessed(numberOfAllocations); + + TestAllocatorType::GarbageCollect(); + } + } + }; + + template + class RecordedAllocationBenchmarkFixture : public ::benchmark::Fixture + { + using TestAllocatorType = TestAllocatorWrapper; + + virtual void internalSetUp() + { + TestAllocatorType::SetUp(); + } + + void internalTearDown() + { + TestAllocatorType::TearDown(); + } + + #pragma pack(push, 1) + struct alignas(1) AllocatorOperation + { + enum OperationType : size_t + { + ALLOCATE, + DEALLOCATE + }; + OperationType m_type : 1; + size_t m_size : 28; // Can represent up to 256Mb requests + size_t m_alignment : 7; // Can represent up to 128 alignment + size_t m_recordId : 28; // Can represent up to 256M simultaneous requests, we reuse ids + }; + #pragma pack(pop) + static_assert(sizeof(AllocatorOperation) == 8); + + public: + void SetUp(const ::benchmark::State&) override + { + internalSetUp(); + } + void SetUp(::benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const ::benchmark::State&) override + { + internalTearDown(); + } + void TearDown(::benchmark::State&) override + { + internalTearDown(); + } + + void Benchmark(benchmark::State& state) + { + for (auto _ : state) + { + state.PauseTiming(); + + AZStd::unordered_map pointerRemapping; + constexpr size_t allocationOperationCount = 5 * 1024; + AZStd::array m_operations = {}; + [[maybe_unused]] const size_t operationSize = sizeof(AllocatorOperation); + + size_t totalAllocationSize = 0; + size_t itemsProcessed = 0; + + for (size_t i = 0; i < 100; ++i) // play the recording multiple times to get a good stable sample, this way we can keep a smaller recording + { + AZ::IO::SystemFile file; + AZ::IO::FixedMaxPathString filePath = AZ::Utils::GetExecutableDirectory(); + filePath += "/Tests/AzCore/Memory/AllocatorBenchmarkRecordings.bin"; + if (!file.Open(filePath.c_str(), AZ::IO::SystemFile::OpenMode::SF_OPEN_READ_ONLY)) + { + return; + } + size_t elementsRead = + file.Read(sizeof(AllocatorOperation) * allocationOperationCount, &m_operations) / sizeof(AllocatorOperation); + itemsProcessed += elementsRead; + + while (elementsRead > 0) + { + for (size_t operationIndex = 0; operationIndex < elementsRead; ++operationIndex) + { + const AllocatorOperation& operation = m_operations[operationIndex]; + if (operation.m_type == AllocatorOperation::ALLOCATE) + { + const auto it = pointerRemapping.emplace(operation.m_recordId, nullptr); + if (it.second) // otherwise already allocated + { + state.ResumeTiming(); + void* ptr = TestAllocatorType::Allocate(operation.m_size, operation.m_alignment); + state.PauseTiming(); + totalAllocationSize += operation.m_size; + it.first->second = ptr; + } + else + { + // Doing a resize, dont account for this memory change, this operation is rare and we dont have + // the size of the previous allocation + state.ResumeTiming(); + TestAllocatorType::Resize(it.first->second, operation.m_size); + state.PauseTiming(); + } + } + else // AllocatorOperation::DEALLOCATE: + { + if (operation.m_recordId) + { + const auto ptrIt = pointerRemapping.find(operation.m_recordId); + if (ptrIt != pointerRemapping.end()) + { + totalAllocationSize -= operation.m_size; + state.ResumeTiming(); + TestAllocatorType::DeAllocate( + ptrIt->second, + /*operation.m_size*/ 0); // size is not correct after a resize, a 0 size deals with it + state.PauseTiming(); + pointerRemapping.erase(ptrIt); + } + } + else // deallocate(nullptr) are recorded + { + // Just to account of the call of deallocate(nullptr); + state.ResumeTiming(); + TestAllocatorType::DeAllocate(nullptr, /*operation.m_size*/ 0); + state.PauseTiming(); + } + } + } + + elementsRead = + file.Read(sizeof(AllocatorOperation) * allocationOperationCount, &m_operations) / sizeof(AllocatorOperation); + itemsProcessed += elementsRead; + } + file.Close(); + + // Deallocate the remainder (since we stopped the recording middle-game)(there are leaks as well) + for (const auto& pointerMapping : pointerRemapping) + { + state.ResumeTiming(); + TestAllocatorType::DeAllocate(pointerMapping.second); + state.PauseTiming(); + } + itemsProcessed += pointerRemapping.size(); + pointerRemapping.clear(); + } + + state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast(TestAllocatorType::NumAllocatedBytes()), benchmark::Counter::kDefaults); + state.counters[s_counterBenchmarkMemory] = benchmark::Counter(static_cast(totalAllocationSize), benchmark::Counter::kDefaults); + + state.SetItemsProcessed(itemsProcessed); + + TestAllocatorType::GarbageCollect(); + } + } + }; + + // For non-threaded ranges, run 100, 400, 1600 amounts + static void RunRanges(benchmark::internal::Benchmark* b) + { + for (int i = 0; i < 6; i += 2) + { + b->Arg((1 << i) * 100); + } + } + static void RecordedRunRanges(benchmark::internal::Benchmark* b) + { + b->Iterations(1); + } + + // For threaded ranges, run just 200, multi-threaded will already multiply by thread + static void ThreadedRunRanges(benchmark::internal::Benchmark* b) + { + b->Arg(100); + } + + // Test under and over-subscription of threads vs the amount of CPUs available + static const unsigned int MaxThreadRange = 2 * AZStd::thread::hardware_concurrency(); + +#define BM_REGISTER_TEMPLATE(FIXTURE, TESTNAME, ...) \ + BENCHMARK_TEMPLATE_DEFINE_F(FIXTURE, TESTNAME, __VA_ARGS__)(benchmark::State& state) { Benchmark(state); } \ + BENCHMARK_REGISTER_F(FIXTURE, TESTNAME) + + // We test small/big/mixed allocations in single-threaded environments. For multi-threaded environments, we test mixed since + // the multi threaded fixture will run multiple passes (1, 2, 4, ... until 2*hardware_concurrency) +#define BM_REGISTER_SIZE_FIXTURES(FIXTURE, TESTNAME, ALLOCATORTYPE) \ + BM_REGISTER_TEMPLATE(FIXTURE, TESTNAME##_SMALL, ALLOCATORTYPE, SMALL)->Apply(RunRanges); \ + BM_REGISTER_TEMPLATE(FIXTURE, TESTNAME##_BIG, ALLOCATORTYPE, BIG)->Apply(RunRanges); \ + BM_REGISTER_TEMPLATE(FIXTURE, TESTNAME##_MIXED, ALLOCATORTYPE, MIXED)->Apply(RunRanges); \ + BM_REGISTER_TEMPLATE(FIXTURE, TESTNAME##_MIXED_THREADED, ALLOCATORTYPE, MIXED)->ThreadRange(2, MaxThreadRange)->Apply(ThreadedRunRanges); + +#define BM_REGISTER_ALLOCATOR(TESTNAME, ALLOCATORTYPE) \ + namespace BM_##TESTNAME \ + { \ + BM_REGISTER_SIZE_FIXTURES(AllocationBenchmarkFixture, TESTNAME, ALLOCATORTYPE); \ + BM_REGISTER_SIZE_FIXTURES(DeAllocationBenchmarkFixture, TESTNAME, ALLOCATORTYPE); \ + BM_REGISTER_TEMPLATE(RecordedAllocationBenchmarkFixture, TESTNAME, ALLOCATORTYPE)->Apply(RecordedRunRanges); \ + } + + /// Warm up benchmark used to prepare the OS for allocations. Most OS keep allocations for a process somehow + /// reserved. So the first allocations run always get a bigger impact in a process. This warm up allocator runs + /// all the benchmarks and is just used for the the next allocators to report more consistent results. + BM_REGISTER_ALLOCATOR(WarmUpAllocator, RawMallocAllocator); + + BM_REGISTER_ALLOCATOR(RawMallocAllocator, RawMallocAllocator); + BM_REGISTER_ALLOCATOR(MallocSchemaAllocator, MallocSchemaAllocator); + BM_REGISTER_ALLOCATOR(HphaSchemaAllocator, HphaSchemaAllocator); + BM_REGISTER_ALLOCATOR(SystemAllocator, TestSystemAllocator); + + //BM_REGISTER_ALLOCATOR(BestFitExternalMapAllocator, BestFitExternalMapAllocator); // Requires to pre-allocate blocks and cannot work as a general-purpose allocator + //BM_REGISTER_ALLOCATOR(HeapSchemaAllocator, TestHeapSchemaAllocator); // Requires to pre-allocate blocks and cannot work as a general-purpose allocator + //BM_REGISTER_SCHEMA(PoolSchema); // Requires special alignment requests while allocating + +#undef BM_REGISTER_ALLOCATOR +#undef BM_REGISTER_SIZE_FIXTURES +#undef BM_REGISTER_TEMPLATE + +} // Benchmark + +#endif // HAVE_BENCHMARK diff --git a/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp b/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp index 85dd79931d..08b84416e6 100644 --- a/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp +++ b/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp @@ -10,10 +10,6 @@ #include #include -#if defined(HAVE_BENCHMARK) -#include -#endif // HAVE_BENCHMARK - class HphaSchema_TestAllocator : public AZ::SimpleSchemaAllocator { @@ -112,87 +108,3 @@ namespace UnitTest HphaSchemaTestFixture, ::testing::ValuesIn(s_mixedInstancesParameters)); } - - -#if defined(HAVE_BENCHMARK) -namespace Benchmark -{ - class HphaSchemaBenchmarkFixture - : public ::benchmark::Fixture - { - void internalSetUp() - { - AZ::AllocatorInstance::Create(); - } - - void internalTearDown() - { - AZ::AllocatorInstance::Destroy(); - } - - public: - void SetUp(const benchmark::State&) override - { - internalSetUp(); - } - void SetUp(benchmark::State&) override - { - internalSetUp(); - } - void TearDown(const benchmark::State&) override - { - internalTearDown(); - } - void TearDown(benchmark::State&) override - { - internalTearDown(); - } - - static void BM_Allocations(benchmark::State& state, const AllocationSizeArray& allocationArray) - { - AZStd::vector allocations; - while (state.KeepRunning()) - { - state.PauseTiming(); - const size_t allocationIndex = allocations.size(); - const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()]; - - state.ResumeTiming(); - void* allocation = AZ::AllocatorInstance::Get().Allocate(allocationSize, 0); - - state.PauseTiming(); - allocations.emplace_back(allocation); - - state.ResumeTiming(); - } - - const size_t numberOfAllocations = allocations.size(); - state.SetItemsProcessed(numberOfAllocations); - - for (size_t allocationIndex = 0; allocationIndex < numberOfAllocations; ++allocationIndex) - { - AZ::AllocatorInstance::Get().DeAllocate(allocations[allocationIndex], allocationArray[allocationIndex % allocationArray.size()]); - } - AZ::AllocatorInstance::Get().GarbageCollect(); - } - }; - - // Small allocations, these are allocations that are going to end up in buckets in the HphaSchema - BENCHMARK_F(HphaSchemaBenchmarkFixture, SmallAllocations)(benchmark::State& state) - { - BM_Allocations(state, s_smallAllocationSizes); - } - - BENCHMARK_F(HphaSchemaBenchmarkFixture, BigAllocations)(benchmark::State& state) - { - BM_Allocations(state, s_bigAllocationSizes); - } - - BENCHMARK_F(HphaSchemaBenchmarkFixture, MixedAllocations)(benchmark::State& state) - { - BM_Allocations(state, s_mixedAllocationSizes); - } - - -} // Benchmark -#endif // HAVE_BENCHMARK diff --git a/Code/Framework/AzCore/Tests/Platform/Android/Tests/Memory/AllocatorBenchmarks_Android.cpp b/Code/Framework/AzCore/Tests/Platform/Android/Tests/Memory/AllocatorBenchmarks_Android.cpp new file mode 100644 index 0000000000..636d5519d8 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Platform/Android/Tests/Memory/AllocatorBenchmarks_Android.cpp @@ -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 + * + */ + +#include +#include + +#include +#include + +namespace Benchmark +{ + namespace Platform + { + size_t GetProcessMemoryUsageBytes() + { + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + return rusage.ru_maxrss * 1024L; + } + + size_t GetMemorySize(void* memory) + { + return memory ? malloc_usable_size(memory) : 0; + } + } +} diff --git a/Code/Framework/AzCore/Tests/Platform/Android/platform_android_files.cmake b/Code/Framework/AzCore/Tests/Platform/Android/platform_android_files.cmake index ed54a84dbf..3ad1bd3185 100644 --- a/Code/Framework/AzCore/Tests/Platform/Android/platform_android_files.cmake +++ b/Code/Framework/AzCore/Tests/Platform/Android/platform_android_files.cmake @@ -8,4 +8,5 @@ set(FILES Tests/UtilsTests_Android.cpp + Tests/Memory/AllocatorBenchmarks_Android.cpp ) diff --git a/Code/Framework/AzCore/Tests/Platform/Linux/Tests/Memory/AllocatorBenchmarks_Linux.cpp b/Code/Framework/AzCore/Tests/Platform/Linux/Tests/Memory/AllocatorBenchmarks_Linux.cpp new file mode 100644 index 0000000000..636d5519d8 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Platform/Linux/Tests/Memory/AllocatorBenchmarks_Linux.cpp @@ -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 + * + */ + +#include +#include + +#include +#include + +namespace Benchmark +{ + namespace Platform + { + size_t GetProcessMemoryUsageBytes() + { + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + return rusage.ru_maxrss * 1024L; + } + + size_t GetMemorySize(void* memory) + { + return memory ? malloc_usable_size(memory) : 0; + } + } +} diff --git a/Code/Framework/AzCore/Tests/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzCore/Tests/Platform/Linux/platform_linux_files.cmake index 844b621e05..953dbb7791 100644 --- a/Code/Framework/AzCore/Tests/Platform/Linux/platform_linux_files.cmake +++ b/Code/Framework/AzCore/Tests/Platform/Linux/platform_linux_files.cmake @@ -9,4 +9,5 @@ set(FILES Tests/UtilsTests_Linux.cpp ../Common/UnixLike/Tests/UtilsTests_UnixLike.cpp + Tests/Memory/AllocatorBenchmarks_Linux.cpp ) diff --git a/Code/Framework/AzCore/Tests/Platform/Mac/Tests/Memory/AllocatorBenchmarks_Mac.cpp b/Code/Framework/AzCore/Tests/Platform/Mac/Tests/Memory/AllocatorBenchmarks_Mac.cpp new file mode 100644 index 0000000000..932252985a --- /dev/null +++ b/Code/Framework/AzCore/Tests/Platform/Mac/Tests/Memory/AllocatorBenchmarks_Mac.cpp @@ -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 + * + */ + +#include +#include + +#include +#include + +namespace Benchmark +{ + namespace Platform + { + size_t GetProcessMemoryUsageBytes() + { + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + return rusage.ru_maxrss; + } + + size_t GetMemorySize(void* memory) + { + return memory ? malloc_size(memory) : 0; + } + } +} diff --git a/Code/Framework/AzCore/Tests/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzCore/Tests/Platform/Mac/platform_mac_files.cmake index 93d2daf2b8..14e39d47f4 100644 --- a/Code/Framework/AzCore/Tests/Platform/Mac/platform_mac_files.cmake +++ b/Code/Framework/AzCore/Tests/Platform/Mac/platform_mac_files.cmake @@ -9,4 +9,5 @@ set(FILES ../Common/Apple/Tests/UtilsTests_Apple.cpp ../Common/UnixLike/Tests/UtilsTests_UnixLike.cpp + Tests/Memory/AllocatorBenchmarks_Mac.cpp ) diff --git a/Code/Framework/AzCore/Tests/Platform/Windows/Tests/Memory/AllocatorBenchmarks_Windows.cpp b/Code/Framework/AzCore/Tests/Platform/Windows/Tests/Memory/AllocatorBenchmarks_Windows.cpp new file mode 100644 index 0000000000..e9571a7e5b --- /dev/null +++ b/Code/Framework/AzCore/Tests/Platform/Windows/Tests/Memory/AllocatorBenchmarks_Windows.cpp @@ -0,0 +1,40 @@ +/* + * 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 +#include + +#include +#include + +namespace Benchmark +{ + namespace Platform + { + size_t GetProcessMemoryUsageBytes() + { + EmptyWorkingSet(GetCurrentProcess()); + + size_t memoryUsage = 0; + MEMORY_BASIC_INFORMATION mbi = { 0 }; + unsigned char* pEndRegion = nullptr; + while (sizeof(mbi) == VirtualQuery(pEndRegion, &mbi, sizeof(mbi))) { + pEndRegion += mbi.RegionSize; + if ((mbi.AllocationProtect & PAGE_READWRITE) && (mbi.State & MEM_COMMIT)) { + memoryUsage += mbi.RegionSize; + } + } + return memoryUsage; + } + + size_t GetMemorySize(void* memory) + { + return memory ? _aligned_msize(memory, 1, 0) : 0; + } + } +} diff --git a/Code/Framework/AzCore/Tests/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzCore/Tests/Platform/Windows/platform_windows_files.cmake index 0a96dad34e..97b12b28e6 100644 --- a/Code/Framework/AzCore/Tests/Platform/Windows/platform_windows_files.cmake +++ b/Code/Framework/AzCore/Tests/Platform/Windows/platform_windows_files.cmake @@ -9,6 +9,7 @@ set(FILES ../Common/WinAPI/Tests/UtilsTests_WinAPI.cpp Tests/IO/Streamer/StorageDriveTests_Windows.cpp + Tests/Memory/AllocatorBenchmarks_Windows.cpp Tests/Memory/OverrunDetectionAllocator_Windows.cpp Tests/Serialization_Windows.cpp ) diff --git a/Code/Framework/AzCore/Tests/ScriptMath.cpp b/Code/Framework/AzCore/Tests/ScriptMath.cpp index 35541c5eec..927ea4a3cd 100644 --- a/Code/Framework/AzCore/Tests/ScriptMath.cpp +++ b/Code/Framework/AzCore/Tests/ScriptMath.cpp @@ -15,6 +15,8 @@ #include #include +#include + using namespace AZ; namespace UnitTest @@ -1409,13 +1411,17 @@ namespace UnitTest script->Execute("AZTestAssertFloatClose(pl:GetNormal().y,-1)"); script->Execute("AZTestAssertFloatClose(pl:GetNormal().z,0)"); + AZ_MATH_TEST_START_TRACE_SUPPRESSION; script->Execute("pl:Set(12, 13, 14, 15)"); + AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(1); script->Execute("AZTestAssertFloatClose(pl:GetDistance(), 15)"); script->Execute("AZTestAssertFloatClose(pl:GetNormal().x, 12)"); script->Execute("AZTestAssertFloatClose(pl:GetNormal().y, 13)"); script->Execute("AZTestAssertFloatClose(pl:GetNormal().z, 14)"); + AZ_MATH_TEST_START_TRACE_SUPPRESSION; script->Execute("pl:Set(Vector3(22, 23, 24), 25)"); + AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(1); script->Execute("AZTestAssertFloatClose(pl:GetDistance(), 25)"); script->Execute("AZTestAssertFloatClose(pl:GetNormal().x, 22)"); script->Execute("AZTestAssertFloatClose(pl:GetNormal().y, 23)"); @@ -1493,7 +1499,9 @@ namespace UnitTest script->Execute("pl:Set(1, 0, 0, 0)"); script->Execute("AZTestAssert(pl:IsFinite())"); + AZ_MATH_TEST_START_TRACE_SUPPRESSION; script->Execute("pl:Set(math.huge, math.huge, math.huge, math.huge)"); + AZ_MATH_TEST_STOP_TRACE_SUPPRESSION(1); script->Execute("AZTestAssert( not pl:IsFinite())"); } diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/JsonRegistrationContextTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/JsonRegistrationContextTests.cpp index 9d4af1def5..9b44f10e89 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/JsonRegistrationContextTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/JsonRegistrationContextTests.cpp @@ -327,17 +327,13 @@ namespace JsonSerializationTests SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get()); } -#if GTEST_HAS_DEATH_TEST - using JsonSerializationDeathTests = JsonRegistrationContextTests; - TEST_F(JsonSerializationDeathTests, DoubleUnregisterSerializer_Asserts) + TEST_F(JsonRegistrationContextTests, DoubleUnregisterSerializer_Asserts) { - ASSERT_DEATH({ - SerializerWithOneType::Reflect(m_jsonRegistrationContext.get()); - SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get()); - SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get()); - }, ".*" - ); + SerializerWithOneType::Reflect(m_jsonRegistrationContext.get()); + SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get()); + AZ_TEST_START_ASSERTTEST; + SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get()); + AZ_TEST_STOP_ASSERTTEST(1); } -#endif // GTEST_HAS_DEATH_TEST } //namespace JsonSerializationTests diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index 98f268b61a..834e3431b6 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -148,6 +148,7 @@ set(FILES Math/Matrix4x4PerformanceTests.cpp Math/Matrix4x4Tests.cpp Math/MatrixUtilsTests.cpp + Math/MathTest.h Math/MathTestData.h Math/ObbPerformanceTests.cpp Math/ObbTests.cpp @@ -170,6 +171,7 @@ set(FILES Math/Vector3Tests.cpp Math/Vector4PerformanceTests.cpp Math/Vector4Tests.cpp + Memory/AllocatorBenchmarks.cpp Memory/AllocatorManager.cpp Memory/HphaSchema.cpp Memory/HphaSchemaErrorDetection.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index dc9c7b4538..66197ae8fc 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -164,6 +165,8 @@ namespace AzFramework public: friend class SpawnableEntitiesDefinition; + AZ_CLASS_ALLOCATOR(AzFramework::EntitySpawnTicket, AZ::SystemAllocator, 0); + using Id = uint32_t; EntitySpawnTicket() = default; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp index 37570caec7..3406057fca 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -499,12 +499,8 @@ namespace AzFramework for (auto it = newEntitiesBegin; it != newEntitiesEnd; ++it) { AZ::Entity* clone = (*it); - // The entity component framework doesn't handle entities without TransformComponent safely. - if (!clone->GetComponents().empty()) - { - clone->SetSpawnTicketId(request.m_ticketId); - GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it); - } + clone->SetSpawnTicketId(request.m_ticketId); + GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, clone); } // Let other systems know about newly spawned entities for any post-processing after adding to the scene/game context. @@ -636,12 +632,8 @@ namespace AzFramework for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it) { AZ::Entity* clone = (*it); - // The entity component framework doesn't handle entities without TransformComponent safely. - if (!clone->GetComponents().empty()) - { - clone->SetSpawnTicketId(request.m_ticketId); - GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it); - } + clone->SetSpawnTicketId(request.m_ticketId); + GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it); } if (request.m_completionCallback) @@ -668,7 +660,7 @@ namespace AzFramework { if (entity != nullptr) { - // Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager. + // Setting it to 0 is needed to avoid the infinite loop between GameEntityContext and SpawnableEntitiesManager. entity->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); @@ -702,7 +694,7 @@ namespace AzFramework { if (*entityIterator != nullptr && (*entityIterator)->GetId() == request.m_entityId) { - // Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager. + // Setting it to 0 is needed to avoid the infinite loop between GameEntityContext and SpawnableEntitiesManager. (*entityIterator)->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( &GameEntityContextRequestBus::Events::DestroyGameEntity, (*entityIterator)->GetId()); @@ -949,11 +941,6 @@ namespace AzFramework GameEntityContextRequestBus::Broadcast( &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); } - else - { - // Entities without components wouldn't have been send to the GameEntityContext. - delete entity; - } } delete request.m_ticket; diff --git a/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp b/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp index 0dc00f81dd..50365ff2ff 100644 --- a/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp +++ b/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp @@ -77,6 +77,12 @@ namespace UnitTest public: AZ_COMPONENT(TargetSpawnableComponent, "{B4041561-63A7-4E1E-80F1-78C08D497960}"); + TargetSpawnableComponent() = default; + explicit TargetSpawnableComponent(AZ::EntityId parent) + : m_parent(parent) + { + } + void Activate() override {} void Deactivate() override {} @@ -84,14 +90,19 @@ namespace UnitTest { if (auto* serializeContext = azrtti_cast(reflection)) { - serializeContext->Class(); + serializeContext->Class() + ->Field("Parent", &TargetSpawnableComponent::m_parent); } } + + AZ::EntityId m_parent; }; class SpawnableEntitiesManagerTest : public AllocatorsFixture { public: + constexpr static AZ::u64 EntityIdStartId = 40; + void SetUp() override { AllocatorsFixture::SetUp(); @@ -111,7 +122,7 @@ namespace UnitTest m_spawnable = aznew AzFramework::Spawnable( AZ::Data::AssetId::CreateString("{EB2E8A2B-F253-4A90-BBF4-55F2EED786B8}:0"), AZ::Data::AssetData::AssetStatus::Ready); m_spawnableAsset = new AZ::Data::Asset(m_spawnable, AZ::Data::AssetLoadBehavior::Default); - m_ticket = new AzFramework::EntitySpawnTicket(*m_spawnableAsset); + m_ticket = aznew AzFramework::EntitySpawnTicket(*m_spawnableAsset); auto managerInterface = AzFramework::SpawnableEntitiesInterface::Get(); m_manager = azrtti_cast(managerInterface); @@ -147,22 +158,43 @@ namespace UnitTest { auto entry = AZStd::make_unique(); entry->AddComponent(aznew SourceSpawnableComponent()); + entry->SetId(AZ::EntityId(EntityIdStartId + i)); entities.push_back(AZStd::move(entry)); } } - AZ::Data::Asset CreateTargetSpawnable(size_t numElements) + AZ::Data::Asset CreateTargetSpawnable(size_t numElements, bool requiresMatchingEntityIds) { auto target = aznew AzFramework::Spawnable( AZ::Data::AssetId(AZ::Uuid("{716CD8C3-0BA8-4F32-B579-0EC7C967796F}")), AZ::Data::AssetData::AssetStatus::Ready); AzFramework::Spawnable::EntityList& entities = target->GetEntities(); entities.reserve(numElements); - for (size_t i = 0; i < numElements; ++i) + if (requiresMatchingEntityIds) { - auto entry = AZStd::make_unique(); - entry->AddComponent(aznew TargetSpawnableComponent()); - entities.push_back(AZStd::move(entry)); + for (size_t i = 0; i < numElements; ++i) + { + auto entry = AZStd::make_unique(); + if (i != 0) + { + entry->AddComponent(aznew TargetSpawnableComponent(AZ::EntityId(EntityIdStartId + i - 1))); + } + else + { + entry->AddComponent(aznew TargetSpawnableComponent()); + } + entry->SetId(AZ::EntityId(EntityIdStartId + i)); + entities.push_back(AZStd::move(entry)); + } + } + else + { + for (size_t i = 0; i < numElements; ++i) + { + auto entry = AZStd::make_unique(); + entry->AddComponent(aznew TargetSpawnableComponent()); + entities.push_back(AZStd::move(entry)); + } } return AZ::Data::Asset(target, AZ::Data::AssetLoadBehavior::NoLoad); @@ -212,6 +244,38 @@ namespace UnitTest return true; } + static bool DoParentEntityIdsMatch(AzFramework::SpawnableConstEntityContainerView entities) + { + if (entities.empty()) + { + return false; + } + + const AZ::Entity* previous = nullptr; + for (const AZ::Entity* entity : entities) + { + if (entity) + { + if (previous) + { + if (TargetSpawnableComponent* link = entity->FindComponent(); link != nullptr) + { + if (link->m_parent != previous->GetId()) + { + return false; + } + } + previous = entity; + } + } + else + { + return false; + } + } + return true; + } + static bool IsEveryOtherEntityAReplacement(AzFramework::SpawnableConstEntityContainerView entities) { bool onAlternative = true; @@ -516,7 +580,7 @@ namespace UnitTest // Make sure we start with a fresh ticket each time, or else each iteration through this loop would continue to build up // more and more entities. delete m_ticket; - m_ticket = new AzFramework::EntitySpawnTicket(*m_spawnableAsset); + m_ticket = aznew AzFramework::EntitySpawnTicket(*m_spawnableAsset); constexpr size_t NumEntities = 4; FillSpawnable(NumEntities); @@ -599,7 +663,8 @@ namespace UnitTest using namespace AzFramework; static constexpr size_t NumEntities = 4; FillSpawnable(NumEntities); - AZ::Data::Asset target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset target = CreateTargetSpawnable(4, requiresMatchingEntityIds); InsertEntityAliases<4>( { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace, @@ -608,11 +673,13 @@ namespace UnitTest size_t spawnedEntitiesCount = 0; bool allReplaced = false; - auto callback = [&spawnedEntitiesCount, &allReplaced]( + bool allEntityIdsPatched = false; + auto callback = [&spawnedEntitiesCount, &allReplaced, &allEntityIdsPatched]( AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) { spawnedEntitiesCount += entities.size(); allReplaced = AreAllEntitiesReplaced(entities); + allEntityIdsPatched = DoParentEntityIdsMatch(entities); }; AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_completionCallback = AZStd::move(callback); @@ -621,6 +688,7 @@ namespace UnitTest EXPECT_EQ(4, spawnedEntitiesCount); EXPECT_TRUE(allReplaced); + EXPECT_TRUE(allEntityIdsPatched); } TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_AllAliasesWithAdditional_SourceAndTargetComponentsMerged) @@ -628,7 +696,8 @@ namespace UnitTest using namespace AzFramework; static constexpr size_t NumEntities = 4; FillSpawnable(NumEntities); - AZ::Data::Asset target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = false; + AZ::Data::Asset target = CreateTargetSpawnable(4, requiresMatchingEntityIds); InsertEntityAliases<4>( { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional, @@ -637,11 +706,13 @@ namespace UnitTest size_t spawnedEntitiesCount = 0; bool allAdded = false; - auto callback = [&spawnedEntitiesCount, &allAdded]( + bool allEntityIdsPatched = false; + auto callback = [&spawnedEntitiesCount, &allAdded, &allEntityIdsPatched]( AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) { spawnedEntitiesCount += entities.size(); allAdded = IsEveryOtherEntityAReplacement(entities); + allEntityIdsPatched = DoParentEntityIdsMatch(entities); }; AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_completionCallback = AZStd::move(callback); @@ -650,6 +721,7 @@ namespace UnitTest EXPECT_EQ(8, spawnedEntitiesCount); EXPECT_TRUE(allAdded); + EXPECT_TRUE(allEntityIdsPatched); } TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_AllAliasesWithMerge_SourceAndTargetComponentsMerged) @@ -657,7 +729,8 @@ namespace UnitTest using namespace AzFramework; static constexpr size_t NumEntities = 4; FillSpawnable(NumEntities); - AZ::Data::Asset target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset target = CreateTargetSpawnable(4, requiresMatchingEntityIds); InsertEntityAliases<4>( { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge, @@ -666,11 +739,13 @@ namespace UnitTest size_t spawnedEntitiesCount = 0; bool allMerged = false; - auto callback = [&spawnedEntitiesCount, &allMerged]( + bool allEntityIdsPatched = false; + auto callback = [&spawnedEntitiesCount, &allMerged, &allEntityIdsPatched]( AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) { spawnedEntitiesCount += entities.size(); allMerged = AreAllMerged(entities); + allEntityIdsPatched = DoParentEntityIdsMatch(entities); }; AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_completionCallback = AZStd::move(callback); @@ -679,6 +754,7 @@ namespace UnitTest EXPECT_EQ(4, spawnedEntitiesCount); EXPECT_TRUE(allMerged); + EXPECT_TRUE(allEntityIdsPatched); } // @@ -1095,7 +1171,8 @@ namespace UnitTest using namespace AzFramework; static constexpr size_t NumEntities = 4; FillSpawnable(NumEntities); - AZ::Data::Asset target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset target = CreateTargetSpawnable(4, requiresMatchingEntityIds); InsertEntityAliases<4>( { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace, @@ -1106,11 +1183,13 @@ namespace UnitTest size_t spawnedEntitiesCount = 0; bool allReplaced = false; - auto callback = [&spawnedEntitiesCount, &allReplaced]( + bool allEntityIdsPatched = false; + auto callback = [&spawnedEntitiesCount, &allReplaced, &allEntityIdsPatched]( AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) { spawnedEntitiesCount += entities.size(); allReplaced = AreAllEntitiesReplaced(entities); + allEntityIdsPatched = DoParentEntityIdsMatch(entities); }; AzFramework::SpawnEntitiesOptionalArgs optionalArgs; optionalArgs.m_completionCallback = AZStd::move(callback); @@ -1119,6 +1198,7 @@ namespace UnitTest EXPECT_EQ(4, spawnedEntitiesCount); EXPECT_TRUE(allReplaced); + EXPECT_TRUE(allEntityIdsPatched); } TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllAliasesWithAdditional_SourceAndTargetComponentsMerged) @@ -1126,7 +1206,8 @@ namespace UnitTest using namespace AzFramework; static constexpr size_t NumEntities = 4; FillSpawnable(NumEntities); - AZ::Data::Asset target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = false; + AZ::Data::Asset target = CreateTargetSpawnable(4, requiresMatchingEntityIds); InsertEntityAliases<4>( { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional, @@ -1137,12 +1218,14 @@ namespace UnitTest size_t spawnedEntitiesCount = 0; bool allAdded = false; + bool allEntityIdsPatched = false; auto callback = - [&spawnedEntitiesCount, &allAdded]( + [&spawnedEntitiesCount, &allAdded, &allEntityIdsPatched]( AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) { spawnedEntitiesCount += entities.size(); allAdded = IsEveryOtherEntityAReplacement(entities); + allEntityIdsPatched = DoParentEntityIdsMatch(entities); }; AzFramework::SpawnEntitiesOptionalArgs optionalArgs; optionalArgs.m_completionCallback = AZStd::move(callback); @@ -1151,6 +1234,7 @@ namespace UnitTest EXPECT_EQ(8, spawnedEntitiesCount); EXPECT_TRUE(allAdded); + EXPECT_TRUE(allEntityIdsPatched); } TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllAliasesWithMerge_SourceAndTargetComponentsMerged) @@ -1158,7 +1242,8 @@ namespace UnitTest using namespace AzFramework; static constexpr size_t NumEntities = 4; FillSpawnable(NumEntities); - AZ::Data::Asset target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset target = CreateTargetSpawnable(4, requiresMatchingEntityIds); InsertEntityAliases<4>( { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge, @@ -1169,11 +1254,13 @@ namespace UnitTest size_t spawnedEntitiesCount = 0; bool allMerged = false; - auto callback = [&spawnedEntitiesCount, &allMerged]( + bool allEntityIdsPatched = false; + auto callback = [&spawnedEntitiesCount, &allMerged, &allEntityIdsPatched]( AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) { spawnedEntitiesCount += entities.size(); allMerged = AreAllMerged(entities); + allEntityIdsPatched = DoParentEntityIdsMatch(entities); }; AzFramework::SpawnEntitiesOptionalArgs optionalArgs; optionalArgs.m_completionCallback = AZStd::move(callback); @@ -1182,6 +1269,7 @@ namespace UnitTest EXPECT_EQ(4, spawnedEntitiesCount); EXPECT_TRUE(allMerged); + EXPECT_TRUE(allEntityIdsPatched); } // @@ -1302,6 +1390,36 @@ namespace UnitTest // ClaimEntities // + TEST_F(SpawnableEntitiesManagerTest, ClaimEntities_Call_AllEntitiesWereClaimedAndNotDeleted) + { + static constexpr size_t NumEntities = 4; + FillSpawnable(NumEntities); + + AZStd::vector claimedEntities; + auto callback = [&claimedEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView container) + { + for (AZ::Entity* entity : container) + { + claimedEntities.push_back(entity); + } + }; + + { + AzFramework::EntitySpawnTicket ticket(*m_spawnableAsset); + m_manager->SpawnAllEntities(ticket); + m_manager->ClaimEntities(ticket, AZStd::move(callback)); + m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular); + } + + EXPECT_EQ(NumEntities, claimedEntities.size()); + + // If these calls fail it means that the ticket has still deleted the entities, so they weren't properly claimed. + for (AZ::Entity* entity : claimedEntities) + { + delete entity; + } + } + TEST_F(SpawnableEntitiesManagerTest, ClaimEntities_DeleteTicketBeforeCall_NoCrash) { auto callback = [](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView) {}; diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp index 8ef69c4b56..8daa183b80 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include namespace AzQtComponents { @@ -35,6 +37,7 @@ namespace AzQtComponents m_text = text; m_metricsLabel->setText(m_text); + m_elidedText.clear(); elide(); updateGeometry(); @@ -65,7 +68,62 @@ namespace AzQtComponents void ElidingLabel::elide() { ensurePolished(); - m_elidedText = fontMetrics().elidedText(m_text, m_elideMode, TextRect().width()); + + if (Qt::mightBeRichText(m_text)) + { + // If RichText tags are elided using fontMetrics.elidedText(), they will break. + // A TextDocument is used to produce elided text that takes this into account. + const QString ellipsis("..."); + const int maxLineWidth = TextRect().width(); + + QTextDocument doc; + doc.setHtml(m_text); + doc.setDefaultFont(font()); + doc.setDocumentMargin(0.0); + + // Turn off wrapping so the document uses a single line. + QTextOption option = doc.defaultTextOption(); + option.setWrapMode(QTextOption::WrapMode::NoWrap); + doc.setDefaultTextOption(option); + doc.adjustSize(); + + if (doc.size().width() <= maxLineWidth) + { + m_elidedText = m_text; + } + else + { + QTextCursor textCursor(&doc); + textCursor.movePosition(QTextCursor::End); + + int ellipsisWidth = 0; + + // At the moment only ElideRight and ElideNone are ever used. This will need expanding if other elision modes are used. + if (m_elideMode == Qt::ElideRight) + { + ellipsisWidth = fontMetrics().horizontalAdvance(ellipsis); + } + + // Move the cursor back until the text fits or the start of the text is reached. + while (doc.size().width() + ellipsisWidth > maxLineWidth && !textCursor.atStart()) + { + textCursor.deletePreviousChar(); + doc.adjustSize(); + } + + if (m_elideMode == Qt::ElideRight) + { + textCursor.insertText(ellipsis); + } + + m_elidedText = doc.toHtml(); + } + } + else + { + m_elidedText = fontMetrics().elidedText(m_text, m_elideMode, TextRect().width()); + } + QLabel::setText(m_elidedText); if (m_elidedText != m_text) diff --git a/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h b/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h index 4915fb9cab..23ea87cd1c 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h +++ b/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h @@ -16,9 +16,12 @@ #define AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS true #define AZ_TRAIT_DISABLE_ASSET_MANAGER_FLOOD_TEST true #define AZ_TRAIT_DISABLE_ASSETCONTAINERDISABLETEST true +#define AZ_TRAIT_DISABLE_FAILED_DLL_TESTS true +#define AZ_TRAIT_DISABLE_FAILED_MODULE_TESTS true +#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_TESTS true // Golden perline gradiant values for random seed 7878 for this platform -#define AZ_TRAIT_UNIT_TEST_PERLINE_GRADIANT_GOLDEN_VALUES_7878 0.5000f, 0.5456f, 0.5138f, 0.4801f, \ - 0.4174f, 0.4942f, 0.5493f, 0.5431f, \ - 0.4984f, 0.5204f, 0.5526f, 0.5840f, \ - 0.5251f, 0.5029f, 0.6153f, 0.5802f, +#define AZ_TRAIT_UNIT_TEST_PERLINE_GRADIANT_GOLDEN_VALUES_7878 0.5000f, 0.5276f, 0.5341f, 0.4801f, \ + 0.5220f, 0.5162f, 0.4828f, 0.5431f, \ + 0.4799f, 0.4486f, 0.5054f, 0.4129f, \ + 0.6023f, 0.5029f, 0.4529f, 0.4428f, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index b91a0aac93..418d176daa 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -415,8 +415,8 @@ namespace AzToolsFramework { // Construct the runtime entities and products bool readyToCreateRootSpawnable = m_playInEditorData.m_assetsCache.IsActivated(); - if (!readyToCreateRootSpawnable && - !m_playInEditorData.m_assetsCache.Activate(Prefab::PrefabConversionUtils::PlayInEditor)) + if (!readyToCreateRootSpawnable && !m_playInEditorData.m_assetsCache.Activate(Prefab::PrefabConversionUtils::PlayInEditor)) + { AZ_Error("Prefab", false, "Failed to create a prefab processing stack from key '%.*s'.", AZ_STRING_ARG(Prefab::PrefabConversionUtils::PlayInEditor)); return; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp index 5bea383630..3b2f78ef2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp @@ -184,6 +184,10 @@ namespace AzToolsFramework const float halfGridSquareCount = float(gridSquareCount) * 0.5f; const float halfGridSize = halfGridSquareCount * squareSize; const float fadeLineLength = cl_viewportFadeLineDistanceScale * squareSize; + + // ensure AuxGeomDraw::OpacityType::Translucent render state is set + debugDisplay.SetAlpha(0.5f); + for (size_t lineIndex = 0; lineIndex <= gridSquareCount; ++lineIndex) { const float lineOffset = -halfGridSize + (lineIndex * squareSize); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp index 490a151925..03d62dff0a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp @@ -142,14 +142,14 @@ namespace AzToolsFramework return m_templateSourcePath; } - void Instance::SetTemplateSourcePath(AZ::IO::PathView sourcePath) + void Instance::SetTemplateSourcePath(AZ::IO::Path sourcePath) { - m_templateSourcePath = sourcePath; + m_templateSourcePath = AZStd::move(sourcePath); } - void Instance::SetContainerEntityName(AZStd::string_view containerName) + void Instance::SetContainerEntityName(AZStd::string containerName) { - m_containerEntity->SetName(containerName); + m_containerEntity->SetName(AZStd::move(containerName)); } bool Instance::AddEntity(AZ::Entity& entity) @@ -608,6 +608,31 @@ namespace AzToolsFramework } AZ::EntityId Instance::GetEntityIdFromAliasPath(AliasPathView relativeAliasPath) const + { + return GetInstanceAndEntityIdFromAliasPath(relativeAliasPath).second; + } + + AZStd::pair Instance::GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) + { + Instance* instance = this; + AliasPathView path = relativeAliasPath.ParentPath(); + for (auto it : path) + { + InstanceOptionalReference child = instance->FindNestedInstance(it.Native()); + if (child.has_value()) + { + instance = &(child->get()); + } + else + { + return AZStd::pair(nullptr, AZ::EntityId()); + } + } + + return AZStd::pair(instance, instance->GetEntityId(relativeAliasPath.Filename().Native())); + } + + AZStd::pair Instance::GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) const { const Instance* instance = this; AliasPathView path = relativeAliasPath.ParentPath(); @@ -620,11 +645,11 @@ namespace AzToolsFramework } else { - return AZ::EntityId(); + return AZStd::pair(nullptr, AZ::EntityId()); } } - return instance->GetEntityId(relativeAliasPath.Filename().Native()); + return AZStd::pair(instance, instance->GetEntityId(relativeAliasPath.Filename().Native())); } AZStd::vector Instance::GetNestedInstanceAliases(TemplateId templateId) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h index 25971093cd..b63eca309a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h @@ -80,8 +80,8 @@ namespace AzToolsFramework void SetTemplateId(TemplateId templateId); const AZ::IO::Path& GetTemplateSourcePath() const; - void SetTemplateSourcePath(AZ::IO::PathView sourcePath); - void SetContainerEntityName(AZStd::string_view containerName); + void SetTemplateSourcePath(AZ::IO::Path sourcePath); + void SetContainerEntityName(AZStd::string containerName); bool AddEntity(AZ::Entity& entity); bool AddEntity(AZStd::unique_ptr&& entity); @@ -169,6 +169,13 @@ namespace AzToolsFramework * @return entityId, invalid ID if not found */ AZ::EntityId GetEntityIdFromAliasPath(AliasPathView relativeAliasPath) const; + /** + * Retrieves the instance pointer and entity id from an alias path that's relative to this instance. + * + * @return A pair with the Instance and entity id. The Instance is set to null and entityId is set to invalid if not found. + */ + AZStd::pair GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath); + AZStd::pair GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) const; /** diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp index dfba1d54ba..9488b68ee8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp @@ -37,13 +37,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils } prefabProcessorContext.ListPrefabs( - [this, &serializeContext, &prefabProcessorContext]([[maybe_unused]] AZStd::string_view prefabName, PrefabDom& prefab) + [this, &serializeContext, &prefabProcessorContext](PrefabDocument& prefab) { auto result = RemoveEditorInfo(prefab, serializeContext, prefabProcessorContext); if (!result) { AZ_Error( - "Prefab", false, "Converting to runtime Prefab '%.*s' failed, Error: %s .", AZ_STRING_ARG(prefabName), + "Prefab", false, "Converting to runtime Prefab '%s' failed, Error: %s .", prefab.GetName().c_str(), result.GetError().c_str()); return; } @@ -58,10 +58,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils } } - void EditorInfoRemover::GetEntitiesFromInstance( - AZStd::unique_ptr& instance, EntityList& hierarchyEntities) + void EditorInfoRemover::GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities) { - instance->GetAllEntitiesInHierarchy( + instance.GetAllEntitiesInHierarchy( [&hierarchyEntities](const AZStd::unique_ptr& entity) { hierarchyEntities.emplace_back(entity.get()); @@ -498,7 +497,7 @@ exportComponent, prefabProcessorContext); } EditorInfoRemover::RemoveEditorInfoResult EditorInfoRemover::RemoveEditorInfo( - PrefabDom& prefab, + PrefabDocument& prefab, AZ::SerializeContext* serializeContext, PrefabProcessorContext& prefabProcessorContext) { @@ -510,28 +509,10 @@ exportComponent, prefabProcessorContext); m_componentRequirementsValidator.SetPlatformTags(prefabProcessorContext.GetPlatformTags()); - // convert Prefab DOM into Prefab Instance. - AZStd::unique_ptr instance(aznew Instance()); - if (!Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*instance, prefab, - Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId)) - { - PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName); - - AZStd::string errorMessage("Failed to Load Prefab Instance from given Prefab Dom during Removal of Editor Info."); - if (sourceReference.has_value() && - sourceReference->get().IsString() && - sourceReference->get().GetStringLength() != 0) - { - AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength()); - errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source)); - } - - return AZ::Failure(errorMessage); - } - // grab all nested entities from the Instance as source entities. + Instance& sourceInstance = prefab.GetInstance(); EntityList sourceEntities; - GetEntitiesFromInstance(instance, sourceEntities); + GetEntitiesFromInstance(sourceInstance, sourceEntities); EntityList exportEntities; @@ -597,7 +578,7 @@ exportComponent, prefabProcessorContext); exportEntitiesMap.emplace(entity->GetId(), entity); } ); - instance->RemoveNestedEntities( + sourceInstance.RemoveNestedEntities( [&exportEntitiesMap](const AZStd::unique_ptr& entity) { return exportEntitiesMap.find(entity->GetId()) == exportEntitiesMap.end(); @@ -605,7 +586,7 @@ exportComponent, prefabProcessorContext); ); // replace entities of instance with exported ones. - instance->GetAllEntitiesInHierarchy( + sourceInstance.GetAllEntitiesInHierarchy( [&exportEntitiesMap](AZStd::unique_ptr& entity) { auto entityId = entity->GetId(); @@ -614,16 +595,6 @@ exportComponent, prefabProcessorContext); } ); - // save the final result in the target Prefab DOM. - PrefabDom filteredPrefab; - if (!PrefabDomUtils::StoreInstanceInPrefabDom(*instance, filteredPrefab)) - { - return AZ::Failure(AZStd::string::format( - "Saving exported Prefab Instance within a Prefab Dom failed.") - ); - } - prefab.Swap(filteredPrefab); - return AZ::Success(); } } // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h index dc10952733..dbad58d2f5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h @@ -43,7 +43,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils using RemoveEditorInfoResult = AZ::Outcome; RemoveEditorInfoResult RemoveEditorInfo( - PrefabDom& prefab, + PrefabDocument& prefab, AZ::SerializeContext* serializeContext, PrefabProcessorContext& prefabProcessorContext); @@ -51,8 +51,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils protected: using EntityList = AZStd::vector; - static void GetEntitiesFromInstance( - AZStd::unique_ptr& instance, EntityList& hierarchyEntities); + static void GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities); static bool ReadComponentAttribute( AZ::Component* component, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h new file mode 100644 index 0000000000..9ab1f9bbd1 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h @@ -0,0 +1,69 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include + +namespace AzToolsFramework::Prefab::PrefabConversionUtils +{ + enum class EntityAliasType : uint8_t + { + Disable, //!< No alias is added. + OptionalReplace, //!< At runtime the entity might be replaced. If the alias is disabled the original entity will be spawned. + //!< The original entity will be left in the spawnable and a copy is returned. + Replace, //!< At runtime the entity will be replaced. If the alias is disabled nothing will be spawned. The original + //!< entity is returned and a blank entity is left. + Additional, //!< At runtime the alias entity will be added as an additional but unrelated entity with a new entity id. + //!< An empty entity will be returned. + Merge //!< At runtime the components in both entities will be merged. An empty entity will be returned. The added + //!< components may no conflict with the entities already in the root entity. + }; + + enum class EntityAliasSpawnableLoadBehavior : uint8_t + { + NoLoad, //!< Don't load the spawnable referenced in the entity alias. Loading will be up to the caller. + QueueLoad, //!< Queue the spawnable referenced in the entity alias for loading. This will be an async load because asset + //!< handlers aren't allowed to start a blocking load as this can lead to deadlocks. This option will allow + //!< to disable loading the referenced spawnable through the event fired from the spawnables asset handler. + DependentLoad //!< The spawnable referenced in the entity alias is made a dependency of the spawnable that holds the entity + //!< alias. This will cause the spawnable to be automatically loaded along with the owning spawnable. + }; + + struct EntityAliasSpawnableLink + { + EntityAliasSpawnableLink(AzFramework::Spawnable& spawnable, AZ::EntityId index); + + AzFramework::Spawnable& m_spawnable; + AZ::EntityId m_index; + }; + + struct EntityAliasPrefabLink + { + EntityAliasPrefabLink(AZStd::string prefabName, AzToolsFramework::Prefab::AliasPath alias); + + AZStd::string m_prefabName; + AzToolsFramework::Prefab::AliasPath m_alias; + }; + + struct EntityAliasStore + { + using LinkStore = AZStd::variant; + + LinkStore m_source; + LinkStore m_target; + uint32_t m_tag; + AzFramework::Spawnable::EntityAliasType m_aliasType; + EntityAliasSpawnableLoadBehavior m_loadBehavior; + }; +} // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp index 553ad8ece4..dc5cd299b8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp @@ -112,9 +112,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils // Use a random uuid as this is only a temporary source. PrefabConversionUtils::PrefabProcessorContext context(AZ::Uuid::CreateRandom()); - PrefabDom copy; - copy.CopyFrom(templateReference->get().GetPrefabDom(), copy.GetAllocator(), false); - context.AddPrefab(spawnableName, AZStd::move(copy)); + PrefabDocument document(spawnableName); + document.SetPrefabDom(templateReference->get().GetPrefabDom()); + context.AddPrefab(AZStd::move(document)); m_converter.ProcessPrefab(context); if (!context.HasCompletedSuccessfully() || context.GetProcessedObjects().empty()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp index 7a54950c47..40cd52cac8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp @@ -25,9 +25,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils { AZ::DataStream::StreamType serializationFormat = m_serializationFormat == SerializationFormats::Binary ? AZ::DataStream::StreamType::ST_BINARY : AZ::DataStream::StreamType::ST_XML; - context.ListPrefabs([&context, serializationFormat](AZStd::string_view prefabName, PrefabDom& prefab) + context.ListPrefabs([&context, serializationFormat](PrefabDocument& prefab) { - ProcessPrefab(context, prefabName, prefab, serializationFormat); + ProcessPrefab(context, prefab, serializationFormat); }); } @@ -45,12 +45,12 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils } } - void PrefabCatchmentProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab, + void PrefabCatchmentProcessor::ProcessPrefab(PrefabProcessorContext& context, PrefabDocument& prefab, AZ::DataStream::StreamType serializationFormat) { using namespace AzToolsFramework::Prefab::SpawnableUtils; - AZStd::string uniqueName = prefabName; + AZStd::string uniqueName = prefab.GetName(); uniqueName += AzFramework::Spawnable::DotFileExtension; auto serializer = [serializationFormat](AZStd::vector& output, const ProcessedObjectStore& object) -> bool @@ -64,45 +64,34 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils AZStd::move(uniqueName), context.GetSourceUuid(), AZStd::move(serializer)); AZ_Assert(spawnable, "Failed to create a new spawnable."); - Instance instance; - if (Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom( - instance, prefab, object.GetReferencedAssets(), - Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is - // going to be used to create clones of the entities. - { - // Resolve entity aliases that store PrefabDOM information to use the spawnable instead. This is done before the entities are - // moved from the instance as they'd otherwise can't be found. - context.ResolveSpawnableEntityAliases(prefabName, *spawnable, instance); + Instance& instance = prefab.GetInstance(); + // Resolve entity aliases that store PrefabDOM information to use the spawnable instead. This is done before the entities are + // moved from the instance as they'd otherwise can't be found. + context.ResolveSpawnableEntityAliases(prefab.GetName(), *spawnable, instance); - AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities(); - instance.DetachAllEntitiesInHierarchy( - [&entities, &context](AZStd::unique_ptr entity) + AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities(); + instance.DetachAllEntitiesInHierarchy( + [&entities, &context](AZStd::unique_ptr entity) + { + if (entity) { - if (entity) + entity->InvalidateDependencies(); + AZ::Entity::DependencySortOutcome evaluation = entity->EvaluateDependenciesGetDetails(); + if (evaluation.IsSuccess()) { - entity->InvalidateDependencies(); - AZ::Entity::DependencySortOutcome evaluation = entity->EvaluateDependenciesGetDetails(); - if (evaluation.IsSuccess()) - { - entities.emplace_back(AZStd::move(entity)); - } - else - { - AZ_Error( - "Prefabs", false, "Entity '%s' %s cannot be activated for the following reason: %s", - entity->GetName().c_str(), entity->GetId().ToString().c_str(), evaluation.GetError().m_message.c_str()); - context.ErrorEncountered(); - } + entities.emplace_back(AZStd::move(entity)); } - }); + else + { + AZ_Error( + "Prefabs", false, "Entity '%s' %s cannot be activated for the following reason: %s", + entity->GetName().c_str(), entity->GetId().ToString().c_str(), evaluation.GetError().m_message.c_str()); + context.ErrorEncountered(); + } + } + }); - SpawnableUtils::SortEntitiesByTransformHierarchy(*spawnable); - context.GetProcessedObjects().push_back(AZStd::move(object)); - } - else - { - AZ_Error("Prefabs", false, "Failed to convert prefab '%.*s' to a spawnable.", AZ_STRING_ARG(prefabName)); - context.ErrorEncountered(); - } + SpawnableUtils::SortEntitiesByTransformHierarchy(*spawnable); + context.GetProcessedObjects().push_back(AZStd::move(object)); } } // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h index 253321f8e7..39a94c86b8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h @@ -40,8 +40,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils static void Reflect(AZ::ReflectContext* context); protected: - static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab, - AZ::DataStream::StreamType serializationFormat); + static void ProcessPrefab(PrefabProcessorContext& context, PrefabDocument& prefab, AZ::DataStream::StreamType serializationFormat); SerializationFormats m_serializationFormat{ SerializationFormats::Binary }; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp new file mode 100644 index 0000000000..04fdea30d2 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp @@ -0,0 +1,151 @@ +/* + * 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 +#include +#include + +namespace AzToolsFramework::Prefab::PrefabConversionUtils +{ + PrefabDocument::PrefabDocument(AZStd::string name) + : m_name(AZStd::move(name)) + , m_instance(AZStd::make_unique()) + { + m_instance->SetTemplateSourcePath(AZ::IO::Path("InMemory") / m_name); + } + + bool PrefabDocument::SetPrefabDom(const PrefabDom& prefab) + { + if (ConstructInstanceFromPrefabDom(prefab)) + { + constexpr bool copyConstStrings = true; + m_dom.CopyFrom(prefab, m_dom.GetAllocator(), copyConstStrings); + return true; + } + else + { + return false; + } + } + + bool PrefabDocument::SetPrefabDom(PrefabDom&& prefab) + { + if (ConstructInstanceFromPrefabDom(prefab)) + { + m_dom = AZStd::move(prefab); + return true; + } + else + { + return false; + } + } + + const AZStd::string& PrefabDocument::GetName() const + { + return m_name; + } + + const PrefabDom& PrefabDocument::GetDom() const + { + if (m_isDirty) + { + m_isDirty = !PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom); + } + return m_dom; + } + + PrefabDom&& PrefabDocument::TakeDom() + { + if (m_isDirty) + { + [[maybe_unused]] bool storedSuccessfully = PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom); + AZ_Assert(storedSuccessfully, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str()); + m_isDirty = false; + } + // After the PrefabDom is moved an empty PrefabDom is left behind. This should be reflected in the Instance, + // so reset it so it's empty as well. + m_instance->Reset(); + m_instance->SetTemplateSourcePath(AZ::IO::Path("InMemory") / m_name); + return AZStd::move(m_dom); + } + + void PrefabDocument::ListEntitiesWithComponentType( + AZ::TypeId componentType, const AZStd::function& callback) const + { + m_instance->GetAllEntitiesInHierarchyConst( + [this, &componentType, &callback](const AZ::Entity& entity) -> bool + { + if (entity.FindComponent(componentType)) + { + return callback(m_instance->GetAliasPathRelativeToInstance(entity.GetId())); + } + else + { + return true; + } + }); + } + + AZ::Entity* PrefabDocument::CreateEntityAlias( + PrefabDocument& source, + AzToolsFramework::Prefab::AliasPathView entity, + AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType, + AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior, + uint32_t tag, + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context) + { + auto&& [sourceInstance, entityId] = source.m_instance->GetInstanceAndEntityIdFromAliasPath(entity); + if (sourceInstance != nullptr && entityId.IsValid()) + { + return SpawnableUtils::CreateEntityAlias( + source.m_name, *sourceInstance, m_name, *m_instance, entityId, aliasType, loadBehavior, tag, context); + } + else + { + return nullptr; + } + } + + AzToolsFramework::Prefab::Instance& PrefabDocument::GetInstance() + { + // Assume that changes will be made to the instance. + m_isDirty = true; + return *m_instance; + } + + const AzToolsFramework::Prefab::Instance& PrefabDocument::GetInstance() const + { + return *m_instance; + } + + bool PrefabDocument::ConstructInstanceFromPrefabDom(const PrefabDom& prefab) + { + using namespace AzToolsFramework::Prefab; + + m_instance->Reset(); + if (PrefabDomUtils::LoadInstanceFromPrefabDom(*m_instance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId)) + { + return true; + } + else + { +#ifdef AZ_ENABLE_TRACING + AZStd::string_view sourceName = m_name; + PrefabDomValueConstReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName); + if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0) + { + sourceName = AZStd::string_view(sourceReference->get().GetString(), sourceReference->get().GetStringLength()); + } + AZ_Error( + "PrefabDocument", false, "Failed to construct Prefab instance from given PrefabDOM '%.*s'.", AZ_STRING_ARG(sourceName)); +#endif + return false; + } + } +} // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h new file mode 100644 index 0000000000..215daf7f71 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h @@ -0,0 +1,66 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include + +namespace AzToolsFramework::Prefab::PrefabConversionUtils +{ + class PrefabProcessorContext; + + class PrefabDocument final + { + public: + explicit PrefabDocument(AZStd::string name); + PrefabDocument(const PrefabDocument&) = delete; + PrefabDocument(PrefabDocument&&) = default; + + PrefabDocument& operator=(const PrefabDocument&) = delete; + PrefabDocument& operator=(PrefabDocument&&) = default; + + bool SetPrefabDom(const PrefabDom& prefab); + bool SetPrefabDom(PrefabDom&& prefab); + + const AZStd::string& GetName() const; + const PrefabDom& GetDom() const; + PrefabDom&& TakeDom(); + + template + void ListEntitiesWithComponentType(const AZStd::function& callback) const; + void ListEntitiesWithComponentType( + AZ::TypeId componentType, const AZStd::function& callback) const; + AZ::Entity* CreateEntityAlias( + PrefabDocument& source, + AzToolsFramework::Prefab::AliasPathView entity, + AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType, + AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior, + uint32_t tag, + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context); + + // Where possible, prefer functions directly on the PrefabDocument Instead of using the Instance. + AzToolsFramework::Prefab::Instance& GetInstance(); + const AzToolsFramework::Prefab::Instance& GetInstance() const; + + private: + bool ConstructInstanceFromPrefabDom(const PrefabDom& prefab); + + mutable PrefabDom m_dom; + AZStd::unique_ptr m_instance; + AZStd::string m_name; + mutable bool m_isDirty{ false }; + }; +} // namespace AzToolsFramework::Prefab::PrefabConversionUtils + +#include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.inl b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.inl new file mode 100644 index 0000000000..37b1f1c127 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.inl @@ -0,0 +1,16 @@ +/* + * 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 + * + */ + +namespace AzToolsFramework::Prefab::PrefabConversionUtils +{ + template + void PrefabDocument::ListEntitiesWithComponentType(const AZStd::function& callback) const + { + ListEntitiesWithComponentType(azrtti_typeid(), callback); + } +} // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp index efef0f53de..12625712b7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp @@ -7,8 +7,10 @@ */ #include +#include #include #include +#include #include #include @@ -30,27 +32,42 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils : m_sourceUuid(sourceUuid) {} - bool PrefabProcessorContext::AddPrefab(AZStd::string prefabName, PrefabDom prefab) + bool PrefabProcessorContext::AddPrefab(PrefabDocument&& document) { - auto result = m_prefabs.emplace(AZStd::move(prefabName), AZStd::move(prefab)); - return result.second; - } - - void PrefabProcessorContext::ListPrefabs(const AZStd::function& callback) - { - m_isIterating = true; - for (auto& it : m_prefabs) + AZStd::string name = document.GetName(); + if (!m_prefabNames.contains(name)) { - callback(it.first, it.second); + m_prefabNames.emplace(AZStd::move(name)); + // If currently iterating add to pending queue to avoid invalidating the container that's being iterated over. + PrefabContainer& container = m_isIterating ? m_pendingPrefabAdditions : m_prefabs; + container.push_back(AZStd::move(document)); + return true; } - m_isIterating = false; + return false; } - void PrefabProcessorContext::ListPrefabs(const AZStd::function& callback) const + void PrefabProcessorContext::ListPrefabs(const AZStd::function& callback) { - for (const auto& it : m_prefabs) + // Enable iterating state so the prefab container doesn't get invalided. Enabling this flag will cause new prefabs + // to be stored in a temporary buffer that can be moved into the regular prefab container after iterating. + m_isIterating = true; + for (PrefabDocument& document : m_prefabs) { - callback(it.first, it.second); + callback(document); + } + + m_isIterating = false; + m_prefabs.insert( + m_prefabs.end(), AZStd::make_move_iterator(m_pendingPrefabAdditions.begin()), + AZStd::make_move_iterator(m_pendingPrefabAdditions.end())); + m_pendingPrefabAdditions.clear(); + } + + void PrefabProcessorContext::ListPrefabs(const AZStd::function& callback) const + { + for (const PrefabDocument& document : m_prefabs) + { + callback(document); } } @@ -132,6 +149,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils { using namespace AzToolsFramework::Prefab; + // Resolve prefab links into spawnable links for the provided spawnable. for (EntityAliasStore& entityAlias : m_entityAliases) { auto sourcePrefab = AZStd::get_if(&entityAlias.m_source); @@ -224,11 +242,35 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils it = aliasVisitors.emplace(source->m_spawnable.GetId(), AZStd::move(visitor)).first; } it->second.AddAlias( - AZ::Data::Asset(&target->m_spawnable, loadBehavior), alias.m_tag, sourceIndex, targetIndex, + AZ::Data::Asset(target->m_spawnable.GetId(), azrtti_typeid()), alias.m_tag, + sourceIndex, targetIndex, alias.m_aliasType, alias.m_loadBehavior == EntityAliasSpawnableLoadBehavior::QueueLoad); // Register the dependency between the two spawnables. RegisterProductAssetDependency(source->m_spawnable.GetId(), target->m_spawnable.GetId(), loadBehavior); + + // Patch up all entity ids so the alias points to the same entity id if needed. + switch (alias.m_aliasType) + { + case AzFramework::Spawnable::EntityAliasType::Original: + continue; + case AzFramework::Spawnable::EntityAliasType::Disable: + continue; + case AzFramework::Spawnable::EntityAliasType::Replace: + break; // Requires entity id for alias in source and target spawnable matches. + case AzFramework::Spawnable::EntityAliasType::Additional: + continue; + case AzFramework::Spawnable::EntityAliasType::Merge: + break; // Requires entity id for alias in source and target spawnable matches. + default: + continue; + } + + auto entityIdMapper = [source, target](const AZ::EntityId& originalId, bool /*isEntityId*/) -> AZ::EntityId + { + return originalId == target->m_index ? source->m_index : originalId; + }; + AZ::EntityUtils::ReplaceEntityIdsAndEntityRefs(&target->m_spawnable, entityIdMapper); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h index d35a09a574..d07761271b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h @@ -21,60 +21,12 @@ #include #include #include +#include +#include #include namespace AzToolsFramework::Prefab::PrefabConversionUtils { - enum class EntityAliasType : uint8_t - { - Disable, //!< No alias is added. - OptionalReplace, //!< At runtime the entity might be replaced. If the alias is disabled the original entity will be spawned. - //!< The original entity will be left in the spawnable and a copy is returned. - Replace, //!< At runtime the entity will be replaced. If the alias is disabled nothing will be spawned. The original - //!< entity is returned and a blank entity is left. - Additional, //!< At runtime the alias entity will be added as an additional but unrelated entity with a new entity id. - //!< An empty entity will be returned. - Merge //!< At runtime the components in both entities will be merged. An empty entity will be returned. The added - //!< components may no conflict with the entities already in the root entity. - }; - - enum class EntityAliasSpawnableLoadBehavior : uint8_t - { - NoLoad, //!< Don't load the spawnable referenced in the entity alias. Loading will be up to the caller. - QueueLoad, //!< Queue the spawnable referenced in the entity alias for loading. This will be an async load because asset - //!< handlers aren't allowed to start a blocking load as this can lead to deadlocks. This option will allow - //!< to disable loading the referenced spawnable through the event fired from the spawnables asset handler. - DependentLoad //!< The spawnable referenced in the entity alias is made a dependency of the spawnable that holds the entity - //!< alias. This will cause the spawnable to be automatically loaded along with the owning spawnable. - }; - - struct EntityAliasSpawnableLink - { - EntityAliasSpawnableLink(AzFramework::Spawnable& spawnable, AZ::EntityId index); - - AzFramework::Spawnable& m_spawnable; - AZ::EntityId m_index; - }; - - struct EntityAliasPrefabLink - { - EntityAliasPrefabLink(AZStd::string prefabName, AzToolsFramework::Prefab::AliasPath alias); - - AZStd::string m_prefabName; - AzToolsFramework::Prefab::AliasPath m_alias; - }; - - struct EntityAliasStore - { - using LinkStore = AZStd::variant; - - LinkStore m_source; - LinkStore m_target; - uint32_t m_tag; - AzFramework::Spawnable::EntityAliasType m_aliasType; - EntityAliasSpawnableLoadBehavior m_loadBehavior; - }; - struct AssetDependencyInfo { AZ::Data::AssetId m_assetId; @@ -93,9 +45,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils explicit PrefabProcessorContext(const AZ::Uuid& sourceUuid); virtual ~PrefabProcessorContext() = default; - virtual bool AddPrefab(AZStd::string prefabName, PrefabDom prefab); - virtual void ListPrefabs(const AZStd::function& callback); - virtual void ListPrefabs(const AZStd::function& callback) const; + virtual bool AddPrefab(PrefabDocument&& document); + virtual void ListPrefabs(const AZStd::function& callback); + virtual void ListPrefabs(const AZStd::function& callback) const; virtual bool HasPrefabs() const; virtual bool RegisterSpawnableProductAssetDependency( @@ -128,12 +80,15 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils virtual void ErrorEncountered(); protected: - using NamedPrefabContainer = AZStd::unordered_map; + using PrefabNames = AZStd::unordered_set; + using PrefabContainer = AZStd::vector; using SpawnableEntityAliasStore = AZStd::vector; AZ::Data::AssetLoadBehavior ToAssetLoadBehavior(EntityAliasSpawnableLoadBehavior loadBehavior) const; - NamedPrefabContainer m_prefabs; + PrefabContainer m_prefabs; + PrefabContainer m_pendingPrefabAdditions; + PrefabNames m_prefabNames; SpawnableEntityAliasStore m_entityAliases; ProcessedObjectStoreContainer m_products; ProductAssetDependencyContainer m_registeredProductAssetDependencies; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp index 5e552aad3f..4f007f509e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp @@ -16,10 +16,12 @@ #include #include #include +#include #include #include #include #include +#include namespace AzToolsFramework::Prefab::SpawnableUtils { @@ -52,14 +54,32 @@ namespace AzToolsFramework::Prefab::SpawnableUtils return result; } + const AZ::Entity* FindEntity(AZ::EntityId entityId, const AzToolsFramework::Prefab::Instance& source) + { + const AZ::Entity* result = nullptr; + source.GetConstEntities( + [&result, entityId](const AZ::Entity& entity) + { + if (entity.GetId() != entityId) + { + return true; + } + else + { + result = &entity; + return false; + } + }); + return result; + } + AZ::Entity* FindEntity(AZ::EntityId entityId, AzFramework::Spawnable& source) { uint32_t index = AzToolsFramework::Prefab::SpawnableUtils::FindEntityIndex(entityId, source); return index != InvalidEntityIndex ? source.GetEntities()[index].get() : nullptr; } - template - AZStd::unique_ptr CloneEntity(AZ::EntityId entityId, T& source) + AZStd::unique_ptr CloneEntity(AZ::EntityId entityId, AzToolsFramework::Prefab::Instance& source) { AZ::Entity* target = Internal::FindEntity(entityId, source); AZ_Assert( @@ -74,41 +94,30 @@ namespace AzToolsFramework::Prefab::SpawnableUtils return clone; } - AZStd::unique_ptr ReplaceEntityWithPlaceholder(AZ::EntityId entityId, AzToolsFramework::Prefab::Instance& source) + AZStd::unique_ptr ReplaceEntityWithPlaceholder( + AZ::EntityId entityId, + [[maybe_unused]] AZStd::string_view sourcePrefabName, + AzToolsFramework::Prefab::Instance& source) { auto&& [instance, alias] = source.FindInstanceAndAlias(entityId); AZ_Assert( - instance, "SpawnbleUtils were unable to locate entity alias with id %zu in Instance '%s' for replacing.", - aznumeric_cast(entityId), source.GetTemplateSourcePath().c_str()); + instance, "SpawnbleUtils were unable to locate entity alias with id %zu in Instance '%.*s' for replacing.", + aznumeric_cast(entityId), AZ_STRING_ARG(sourcePrefabName)); EntityOptionalReference entityData = instance->GetEntity(alias); AZ_Assert( - entityData.has_value(), "SpawnbleUtils were unable to locate entity '%.*s' in Instance '%s' for replacing.", - AZ_STRING_ARG(alias), source.GetTemplateSourcePath().c_str()); - auto placeholder = AZStd::make_unique(entityData->get().GetId(), entityData->get().GetName()); + entityData.has_value(), "SpawnbleUtils were unable to locate entity '%.*s' in Instance '%.*s' for replacing.", + AZ_STRING_ARG(alias), AZ_STRING_ARG(sourcePrefabName)); + // A new entity id can be used for the placeholder as `ReplaceEntity` will swap the entity ids. + auto placeholder = AZStd::make_unique(AZ::Entity::MakeId(), entityData->get().GetName()); return instance->ReplaceEntity(AZStd::move(placeholder), alias); } - AZStd::unique_ptr ReplaceEntityWithPlaceholder(AZ::EntityId entityId, AzFramework::Spawnable& source) - { - uint32_t index = AzToolsFramework::Prefab::SpawnableUtils::FindEntityIndex(entityId, source); - AZ_Assert( - index != InvalidEntityIndex, "SpawnbleUtils were unable to locate entity alias with id %zu in Spawnable for replacing.", - aznumeric_cast(entityId)); - - AZStd::unique_ptr original = AZStd::move(source.GetEntities()[index]); - AZ_Assert( - original, "SpawnbleUtils were unable to locate entity with id %zu in Spawnable for replacing.", - aznumeric_cast(entityId)); - - source.GetEntities()[index] = AZStd::make_unique(original->GetId(), original->GetName()); - - return original; - } - - template AZStd::pair, AzFramework::Spawnable::EntityAliasType> ApplyAlias( - Source& source, AZ::EntityId entityId, AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType) + AZStd::string_view sourcePrefabName, + AzToolsFramework::Prefab::Instance& source, + AZ::EntityId entityId, + AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType) { namespace PCU = AzToolsFramework::Prefab::PrefabConversionUtils; using ResultPair = AZStd::pair, AzFramework::Spawnable::EntityAliasType>; @@ -121,12 +130,13 @@ namespace AzToolsFramework::Prefab::SpawnableUtils case PCU::EntityAliasType::OptionalReplace: return ResultPair(CloneEntity(entityId, source), AzFramework::Spawnable::EntityAliasType::Replace); case PCU::EntityAliasType::Replace: - return ResultPair(ReplaceEntityWithPlaceholder(entityId, source), AzFramework::Spawnable::EntityAliasType::Replace); + return ResultPair( + ReplaceEntityWithPlaceholder(entityId, sourcePrefabName, source), + AzFramework::Spawnable::EntityAliasType::Replace); case PCU::EntityAliasType::Additional: - ResultPair(AZStd::make_unique(AZ::Entity::MakeId()), AzFramework::Spawnable::EntityAliasType::Additional); + return ResultPair(AZStd::make_unique(), AzFramework::Spawnable::EntityAliasType::Additional); case PCU::EntityAliasType::Merge: - // Use the same entity id as the original entity so at runtime the entity ids can be verified to match. - ResultPair(AZStd::make_unique(entityId), AzFramework::Spawnable::EntityAliasType::Merge); + return ResultPair(AZStd::make_unique(), AzFramework::Spawnable::EntityAliasType::Merge); default: AZ_Assert( false, "Invalid PrefabProcessorContext::EntityAliasType type (%i) provided.", aznumeric_cast(aliasType)); @@ -182,7 +192,8 @@ namespace AzToolsFramework::Prefab::SpawnableUtils AliasPath alias = source.GetAliasPathRelativeToInstance(entityId); if (!alias.empty()) { - auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType); + auto&& [replacement, storedAliasType] = + Internal::ApplyAlias(sourcePrefabName, source, entityId, aliasType); if (replacement) { AZ::Entity* result = replacement.get(); @@ -212,84 +223,6 @@ namespace AzToolsFramework::Prefab::SpawnableUtils } } - AZ::Entity* CreateEntityAlias( - AZStd::string sourcePrefabName, - AzToolsFramework::Prefab::Instance& source, - AzFramework::Spawnable& target, - AZ::EntityId entityId, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior, - uint32_t tag, - AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context) - { - using namespace AzToolsFramework::Prefab::PrefabConversionUtils; - - AliasPath alias = source.GetAliasPathRelativeToInstance(entityId); - if (!alias.empty()) - { - auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType); - if (replacement) - { - AZ::Entity* result = replacement.get(); - target.GetEntities().push_back(AZStd::move(replacement)); - - EntityAliasStore store; - store.m_aliasType = storedAliasType; - store.m_source.emplace(AZStd::move(sourcePrefabName), AZStd::move(alias)); - store.m_target.emplace(target, result->GetId()); - store.m_tag = tag; - store.m_loadBehavior = loadBehavior; - context.RegisterSpawnableEntityAlias(AZStd::move(store)); - - return result; - } - else - { - AZ_Assert(false, "A replacement for entity with id %zu could not be created.", static_cast(entityId)); - return nullptr; - } - } - else - { - AZ_Assert(false, "Entity with id %llu was not found in the source prefab.", static_cast(entityId)); - return nullptr; - } - } - - AZ::Entity* CreateEntityAlias( - AzFramework::Spawnable& source, - AzFramework::Spawnable& target, - AZ::EntityId entityId, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior, - uint32_t tag, - AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context) - { - using namespace AzToolsFramework::Prefab::PrefabConversionUtils; - - auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType); - if (replacement) - { - AZ::Entity* result = replacement.get(); - target.GetEntities().push_back(AZStd::move(replacement)); - - EntityAliasStore store; - store.m_aliasType = storedAliasType; - store.m_source.emplace(source, entityId); - store.m_target.emplace(target, result->GetId()); - store.m_tag = tag; - store.m_loadBehavior = loadBehavior; - context.RegisterSpawnableEntityAlias(AZStd::move(store)); - - return result; - } - else - { - AZ_Assert(false, "A replacement for entity with id %zu could not be created.", static_cast(entityId)); - return nullptr; - } - } - uint32_t FindEntityIndex(AZ::EntityId entity, const AzFramework::Spawnable& spawnable) { auto begin = spawnable.GetEntities().begin(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h index ea8a49857e..53d007c0c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include namespace AZ { @@ -24,6 +24,11 @@ namespace AzToolsFramework::Prefab class Instance; } +namespace AzToolsFramework::Prefab::PrefabConversionUtils +{ + class PrefabProcessorContext; +} + namespace AzToolsFramework::Prefab::SpawnableUtils { static constexpr uint32_t InvalidEntityIndex = AZStd::numeric_limits::max(); @@ -41,24 +46,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior, uint32_t tag, AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context); - AZ::Entity* CreateEntityAlias( - AZStd::string sourcePrefabName, - AzToolsFramework::Prefab::Instance& source, - AzFramework::Spawnable& target, - AZ::EntityId entityId, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior, - uint32_t tag, - AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context); - AZ::Entity* CreateEntityAlias( - AzFramework::Spawnable& source, - AzFramework::Spawnable& target, - AZ::EntityId entityId, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType, - AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior, - uint32_t tag, - AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context); - + uint32_t FindEntityIndex(AZ::EntityId entity, const AzFramework::Spawnable& spawnable); void SortEntitiesByTransformHierarchy(AzFramework::Spawnable& spawnable); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index bb2d2851ca..e895456151 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -421,6 +421,7 @@ namespace AzToolsFramework { QString label{ text }; m_nameLabel->setText(label); + m_nameLabel->setOpenExternalLinks(true); m_nameLabel->setVisible(!label.isEmpty()); // setting the stretches to 0 in case of an empty label really hides the label (i.e. even the reserved space) m_mainLayout->setStretch(0, label.isEmpty() ? 0 : LabelColumnStretch); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 4f952a3edc..7f877facb6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -30,8 +30,7 @@ namespace UnitTest void MousePressAndMove( QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton) { - QPoint position = widget->mapToGlobal(initialPositionWidget); - QTest::mousePress(widget, mouseButton, Qt::NoModifier, position); + QTest::mousePress(widget, mouseButton, Qt::NoModifier, initialPositionWidget); MouseMove(widget, initialPositionWidget, mouseDelta, mouseButton); } @@ -45,14 +44,15 @@ namespace UnitTest // - https://lists.qt-project.org/pipermail/development/2019-July/036873.html void MouseMove(QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton) { - QPoint nextPosition = widget->mapToGlobal(initialPositionWidget + mouseDelta); + const QPoint nextLocalPosition = initialPositionWidget + mouseDelta; + const QPoint nextGlobalPosition = widget->mapToGlobal(nextLocalPosition); // ^1 To ensure a mouse move event is fired we must call the test mouse move function // and also send a mouse move event that matches. Each on their own do not appear to // work - please see the links above for more context. - QTest::mouseMove(widget, nextPosition); + QTest::mouseMove(widget, nextLocalPosition); QMouseEvent mouseMoveEvent( - QEvent::MouseMove, QPointF(nextPosition), QPointF(nextPosition), Qt::NoButton, mouseButton, Qt::NoModifier); + QEvent::MouseMove, QPointF(nextLocalPosition), QPointF(nextGlobalPosition), Qt::NoButton, mouseButton, Qt::NoModifier); QApplication::sendEvent(widget, &mouseMoveEvent); } @@ -157,6 +157,23 @@ namespace UnitTest return QWidget::event(event); } + MouseMoveDetector::MouseMoveDetector(QWidget* parent) + : QObject(parent) + { + } + + bool MouseMoveDetector::eventFilter(QObject* watched, QEvent* event) + { + if (const auto eventType = event->type(); eventType == QEvent::Type::MouseMove) + { + auto mouseEvent = static_cast(event); + m_mouseGlobalPosition = mouseEvent->globalPos(); + m_mouseLocalPosition = mouseEvent->pos(); + } + + return QObject::eventFilter(watched, event); + } + void TestEditorActions::Connect() { using AzToolsFramework::GetEntityContextId; @@ -571,3 +588,5 @@ namespace UnitTest sliceAssets.clear(); } } // namespace UnitTest + +#include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index 79a87391b4..2c60ca914c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -111,10 +111,29 @@ namespace UnitTest { Q_OBJECT public: - FocusInteractionWidget(QWidget* parent = nullptr) : QWidget(parent) {} + FocusInteractionWidget(QWidget* parent = nullptr) + : QWidget(parent) + { + } + bool event(QEvent* event) override; }; + /// Records mouse move events and stores the local and global position of the cursor. + /// @note To use, install as an event filter for the widget being interacted with + /// e.g. m_testWidget->installEventFilter(&m_mouseMoveDetector); + class MouseMoveDetector : public QObject + { + Q_OBJECT + public: + MouseMoveDetector(QWidget* parent = nullptr); + + bool eventFilter([[maybe_unused]] QObject* watched, QEvent* event) override; + + QPoint m_mouseGlobalPosition; + QPoint m_mouseLocalPosition; + }; + /// Stores actions registered for either normal mode (regular viewport) editing and /// component mode editing. class TestEditorActions diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 2c25cc9222..05c07afecd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -723,6 +723,7 @@ set(FILES Prefab/Spawnable/EditorOnlyEntityHandler/UiEditorOnlyEntityHandler.cpp Prefab/Spawnable/EditorOnlyEntityHandler/WorldEditorOnlyEntityHandler.h Prefab/Spawnable/EditorOnlyEntityHandler/WorldEditorOnlyEntityHandler.cpp + Prefab/Spawnable/EntityAliasTypes.h Prefab/Spawnable/InMemorySpawnableAssetContainer.h Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp Prefab/Spawnable/PrefabCatchmentProcessor.h @@ -730,6 +731,9 @@ set(FILES Prefab/Spawnable/PrefabConversionPipeline.h Prefab/Spawnable/PrefabConversionPipeline.cpp Prefab/Spawnable/PrefabConverterStackProfileNames.h + Prefab/Spawnable/PrefabDocument.h + Prefab/Spawnable/PrefabDocument.inl + Prefab/Spawnable/PrefabDocument.cpp Prefab/Spawnable/ProcesedObjectStore.h Prefab/Spawnable/ProcesedObjectStore.cpp Prefab/Spawnable/PrefabProcessor.h diff --git a/Code/Framework/AzToolsFramework/Tests/AzToolsFrameworkTestHelpersTest.cpp b/Code/Framework/AzToolsFramework/Tests/AzToolsFrameworkTestHelpersTest.cpp new file mode 100644 index 0000000000..2a1254f2e9 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/AzToolsFrameworkTestHelpersTest.cpp @@ -0,0 +1,88 @@ +/* + * 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 + +#include +#include + +namespace UnitTest +{ + class AzToolsFrameworkTestHelpersFixture : public AllocatorsTestFixture + { + public: + void SetUp() override + { + AllocatorsTestFixture::SetUp(); + + m_rootWidget = AZStd::make_unique(); + m_rootWidget->setFixedSize(0, 0); + m_rootWidget->setMouseTracking(true); + m_rootWidget->move(0, 0); // explicitly set the widget to be in the upper left corner + + m_mouseMoveDetector = AZStd::make_unique(); + m_rootWidget->installEventFilter(m_mouseMoveDetector.get()); + } + + void TearDown() override + { + m_rootWidget->removeEventFilter(m_mouseMoveDetector.get()); + m_rootWidget.reset(); + m_mouseMoveDetector.reset(); + + AllocatorsTestFixture::TearDown(); + } + + AZStd::unique_ptr m_rootWidget; + AZStd::unique_ptr m_mouseMoveDetector; + }; + + struct MouseMoveParams + { + QSize m_widgetSize; + QPoint m_widgetPosition; + QPoint m_localCursorPosition; + QPoint m_cursorDelta; + }; + + class MouseMoveAzToolsFrameworkTestHelperFixture + : public AzToolsFrameworkTestHelpersFixture + , public ::testing::WithParamInterface + { + }; + + TEST_P(MouseMoveAzToolsFrameworkTestHelperFixture, MouseMoveCorrectlyTransformsCursorPositionInGlobalAndLocalSpace) + { + // given + const MouseMoveParams mouseMoveParams = GetParam(); + m_rootWidget->move(mouseMoveParams.m_widgetPosition); + m_rootWidget->setFixedSize(mouseMoveParams.m_widgetSize); + + // when + MouseMove(m_rootWidget.get(), mouseMoveParams.m_localCursorPosition, mouseMoveParams.m_cursorDelta); + + // then + const QPoint mouseLocalPosition = m_mouseMoveDetector->m_mouseLocalPosition; + const QPoint mouseLocalPositionFromGlobal = m_rootWidget->mapFromGlobal(m_mouseMoveDetector->m_mouseGlobalPosition); + const QPoint expectedPosition = mouseMoveParams.m_localCursorPosition + mouseMoveParams.m_cursorDelta; + + using ::testing::Eq; + EXPECT_THAT(mouseLocalPosition.x(), Eq(expectedPosition.x())); + EXPECT_THAT(mouseLocalPosition.y(), Eq(expectedPosition.y())); + EXPECT_THAT(mouseLocalPositionFromGlobal.x(), Eq(expectedPosition.x())); + EXPECT_THAT(mouseLocalPositionFromGlobal.y(), Eq(expectedPosition.y())); + } + + INSTANTIATE_TEST_CASE_P( + All, + MouseMoveAzToolsFrameworkTestHelperFixture, + testing::Values( + MouseMoveParams{ QSize(100, 100), QPoint(0, 0), QPoint(0, 0), QPoint(10, 10) }, + MouseMoveParams{ QSize(100, 100), QPoint(100, 100), QPoint(0, 0), QPoint(10, 10) }, + MouseMoveParams{ QSize(100, 100), QPoint(20, 20), QPoint(50, 50), QPoint(20, 20) })); +} // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp index ecbbe10c39..ba0c3a4838 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp @@ -25,7 +25,7 @@ namespace Benchmark for (auto _ : state) { state.PauseTiming(); - m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset); + m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset); state.ResumeTiming(); for (uint64_t spwanableCounter = 0; spwanableCounter < spawnAllEntitiesCallCount; spwanableCounter++) @@ -62,7 +62,7 @@ namespace Benchmark for (auto _ : state) { state.PauseTiming(); - m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset); + m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset); state.ResumeTiming(); AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket); @@ -93,15 +93,16 @@ namespace Benchmark SetUpSpawnableAsset(entityCountInSpawnable); + auto spawner = AzFramework::SpawnableEntitiesInterface::Get(); for (auto _ : state) { state.PauseTiming(); - m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset); + m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset); state.ResumeTiming(); for (uint64_t spawnCallCounter = 0; spawnCallCounter < spawnCallCount; spawnCallCounter++) { - AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket); + spawner->SpawnAllEntities(*m_spawnTicket); } m_rootSpawnableInterface->ProcessSpawnableQueue(); diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp index b8ce3c7c42..0d75227e38 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -201,15 +202,14 @@ namespace UnitTest { ConvertSourceEntitiesToPrefab(); + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument prefab("Test"); + prefab.SetPrefabDom(m_prefabDom); const bool actualResult = - m_editorInfoRemover.RemoveEditorInfo(m_prefabDom, m_serializeContext, m_prefabProcessorContext).IsSuccess(); + m_editorInfoRemover.RemoveEditorInfo(prefab, m_serializeContext, m_prefabProcessorContext).IsSuccess(); EXPECT_EQ(expectedResult, actualResult); - AZStd::unique_ptr convertedInstance(aznew Instance()); - ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*convertedInstance, m_prefabDom)); - - convertedInstance->DetachAllEntitiesInHierarchy( + prefab.GetInstance().DetachAllEntitiesInHierarchy( [this](AZStd::unique_ptr entity) { m_runtimeEntities.emplace_back(entity.release()); diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake index 9a1f61ab56..2631a84325 100644 --- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake +++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake @@ -12,6 +12,7 @@ set(FILES AssetFileInfoListComparison.cpp AssetSeedManager.cpp AssetSystemMocks.h + AzToolsFrameworkTestHelpersTest.cpp BoundsTestComponent.cpp BoundsTestComponent.h ComponentAdapterTests.cpp diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h index 8d7fe068c2..3ebe7d8e44 100644 --- a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h @@ -8,4 +8,4 @@ #pragma once -#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false +#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS true diff --git a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IScriptProcessorRule.h b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IScriptProcessorRule.h index 36be5f61d3..2b2abae561 100644 --- a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IScriptProcessorRule.h +++ b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IScriptProcessorRule.h @@ -17,6 +17,12 @@ namespace AZ { namespace DataTypes { + enum class ScriptProcessorFallbackLogic + { + FailBuild, // this will log error & fail the build + ContinueBuild // this will log the errors but continue the build logic + }; + class IScriptProcessorRule : public IRule { @@ -26,6 +32,8 @@ namespace AZ virtual ~IScriptProcessorRule() override = default; virtual const AZStd::string& GetScriptFilename() const = 0; + + virtual ScriptProcessorFallbackLogic GetScriptProcessorFallbackLogic() const = 0; }; } // DataTypes } // SceneAPI diff --git a/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.cpp b/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.cpp index 8d413b6038..6046bfa620 100644 --- a/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.cpp +++ b/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.cpp @@ -173,10 +173,13 @@ namespace AZ::SceneAPI::Behaviors UnloadPython(); } - bool ScriptProcessorRuleBehavior::LoadPython(const AZ::SceneAPI::Containers::Scene& scene, AZStd::string& scriptPath) + bool ScriptProcessorRuleBehavior::LoadPython(const AZ::SceneAPI::Containers::Scene& scene, AZStd::string& scriptPath, Events::ProcessingResult& fallbackResult) { + using namespace AZ::SceneAPI; + + fallbackResult = Events::ProcessingResult::Failure; int scriptDiscoveryAttempts = 0; - const AZ::SceneAPI::Containers::SceneManifest& manifest = scene.GetManifest(); + const Containers::SceneManifest& manifest = scene.GetManifest(); auto view = Containers::MakeDerivedFilterView(manifest.GetValueStorage()); for (const auto& scriptItem : view) { @@ -188,6 +191,8 @@ namespace AZ::SceneAPI::Behaviors } ++scriptDiscoveryAttempts; + fallbackResult = (scriptItem.GetScriptProcessorFallbackLogic() == DataTypes::ScriptProcessorFallbackLogic::ContinueBuild) ? + Events::ProcessingResult::Ignored : Events::ProcessingResult::Failure; // check for file exist via absolute path if (!IO::FileIOBase::GetInstance()->Exists(scriptFilename.c_str())) @@ -301,7 +306,8 @@ namespace AZ::SceneAPI::Behaviors } }; - if (LoadPython(context.GetScene(), scriptPath)) + [[maybe_unused]] Events::ProcessingResult fallbackResult; + if (LoadPython(context.GetScene(), scriptPath, fallbackResult)) { EditorPythonConsoleNotificationHandler logger; m_editorPythonEventsInterface->ExecuteWithLock(executeCallback); @@ -333,8 +339,9 @@ namespace AZ::SceneAPI::Behaviors return Events::ProcessingResult::Ignored; } + Events::ProcessingResult fallbackResult; AZStd::string scriptPath; - if (LoadPython(scene, scriptPath)) + if (LoadPython(scene, scriptPath, fallbackResult)) { AZStd::string manifestUpdate; auto executeCallback = [&scene, &manifestUpdate, &scriptPath]() @@ -349,6 +356,12 @@ namespace AZ::SceneAPI::Behaviors EditorPythonConsoleNotificationHandler logger; m_editorPythonEventsInterface->ExecuteWithLock(executeCallback); + // if the returned scene manifest is empty then ignore the script update + if (manifestUpdate.empty()) + { + return Events::ProcessingResult::Ignored; + } + EntityUtilityBus::Broadcast(&EntityUtilityBus::Events::ResetEntityContext); AZ::Interface::Get()->RemoveAllTemplates(); @@ -364,6 +377,11 @@ namespace AZ::SceneAPI::Behaviors } return Events::ProcessingResult::Success; } + else + { + // if the manifest was not updated by the script, then return back the fallback result + return fallbackResult; + } } return Events::ProcessingResult::Ignored; } diff --git a/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h b/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h index a9ddf88df9..8903a8f257 100644 --- a/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h +++ b/Code/Tools/SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h @@ -54,7 +54,7 @@ namespace AZ::SceneAPI::Behaviors SCENE_DATA_API void GetManifestDependencyPaths(AZStd::vector& paths) override; protected: - bool LoadPython(const AZ::SceneAPI::Containers::Scene& scene, AZStd::string& scriptPath); + bool LoadPython(const AZ::SceneAPI::Containers::Scene& scene, AZStd::string& scriptPath, Events::ProcessingResult& fallbackResult); void UnloadPython(); bool DoPrepareForExport(Events::PreExportEventContext& context); diff --git a/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.cpp b/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.cpp index 5893764eb1..15c8c1b7f3 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.cpp +++ b/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.cpp @@ -14,6 +14,9 @@ namespace AZ { + // Enum types must have a TypeId tied to it in order for the reflection to succeed. + AZ_TYPE_INFO_SPECIALIZE(SceneAPI::DataTypes::ScriptProcessorFallbackLogic, "{3DCABF3D-E8EF-43E7-B3C7-373E05825F60}"); + namespace SceneAPI { namespace SceneData @@ -23,13 +26,23 @@ namespace AZ return m_scriptFilename; } + DataTypes::ScriptProcessorFallbackLogic ScriptProcessorRule::GetScriptProcessorFallbackLogic() const + { + return m_fallbackLogic; + } + void ScriptProcessorRule::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(1) - ->Field("scriptFilename", &ScriptProcessorRule::m_scriptFilename); + serializeContext->Class()->Version(2) + ->Field("scriptFilename", &ScriptProcessorRule::m_scriptFilename) + ->Field("fallbackLogic", &ScriptProcessorRule::m_fallbackLogic); + + serializeContext->Enum() + ->Value("FailBuild", DataTypes::ScriptProcessorFallbackLogic::FailBuild) + ->Value("ContinueBuild", DataTypes::ScriptProcessorFallbackLogic::ContinueBuild); AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) diff --git a/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.h b/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.h index ad5e1de063..80cb670f9f 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.h +++ b/Code/Tools/SceneAPI/SceneData/Rules/ScriptProcessorRule.h @@ -35,10 +35,13 @@ namespace AZ m_scriptFilename = AZStd::move(scriptFilename); } + DataTypes::ScriptProcessorFallbackLogic GetScriptProcessorFallbackLogic() const override; + static void Reflect(ReflectContext* context); protected: AZStd::string m_scriptFilename; + DataTypes::ScriptProcessorFallbackLogic m_fallbackLogic = DataTypes::ScriptProcessorFallbackLogic::FailBuild; }; } // SceneData } // SceneAPI diff --git a/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp b/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp index e0d5cca484..2bbbc1054a 100644 --- a/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp +++ b/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -271,5 +272,79 @@ namespace AZ auto update = scriptProcessorRuleBehavior.UpdateManifest(scene, AssetImportRequest::Update, AssetImportRequest::Generic); EXPECT_EQ(update, ProcessingResult::Ignored); } + + TEST_F(SceneManifest_JSON, ScriptProcessorRule_DefaultFallbackLogic_Works) + { + using namespace AZ::SceneAPI; + + constexpr const char* defaultJson = { R"JSON( + { + "values": [ + { + "$type": "ScriptProcessorRule", + "scriptFilename": "foo.py" + } + ] + })JSON" }; + + auto scene = Containers::Scene("mock"); + auto result = scene.GetManifest().LoadFromString(defaultJson, m_serializeContext.get(), m_jsonRegistrationContext.get()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_FALSE(scene.GetManifest().IsEmpty()); + ASSERT_EQ(scene.GetManifest().GetEntryCount(), 1); + + auto view = Containers::MakeDerivedFilterView(scene.GetManifest().GetValueStorage()); + EXPECT_EQ(view.begin()->GetScriptProcessorFallbackLogic(), DataTypes::ScriptProcessorFallbackLogic::FailBuild); + } + + TEST_F(SceneManifest_JSON, ScriptProcessorRule_ExplicitFallbackLogic_Works) + { + using namespace AZ::SceneAPI; + + constexpr const char* fallbackLogicJson = { R"JSON( + { + "values": [ + { + "$type": "ScriptProcessorRule", + "scriptFilename": "foo.py", + "fallbackLogic": "FailBuild" + } + ] + })JSON" }; + + auto scene = Containers::Scene("mock"); + auto result = scene.GetManifest().LoadFromString(fallbackLogicJson, m_serializeContext.get(), m_jsonRegistrationContext.get()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_FALSE(scene.GetManifest().IsEmpty()); + ASSERT_EQ(scene.GetManifest().GetEntryCount(), 1); + + auto view = Containers::MakeDerivedFilterView(scene.GetManifest().GetValueStorage()); + EXPECT_EQ(view.begin()->GetScriptProcessorFallbackLogic(), DataTypes::ScriptProcessorFallbackLogic::FailBuild); + } + + TEST_F(SceneManifest_JSON, ScriptProcessorRule_ContinueBuildFallbackLogic_Works) + { + using namespace AZ::SceneAPI; + + constexpr const char* fallbackLogicJson = { R"JSON( + { + "values": [ + { + "$type": "ScriptProcessorRule", + "scriptFilename": "foo.py", + "fallbackLogic": "ContinueBuild" + } + ] + })JSON" }; + + auto scene = Containers::Scene("mock"); + auto result = scene.GetManifest().LoadFromString(fallbackLogicJson, m_serializeContext.get(), m_jsonRegistrationContext.get()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_FALSE(scene.GetManifest().IsEmpty()); + ASSERT_EQ(scene.GetManifest().GetEntryCount(), 1); + + auto view = Containers::MakeDerivedFilterView(scene.GetManifest().GetValueStorage()); + EXPECT_EQ(view.begin()->GetScriptProcessorFallbackLogic(), DataTypes::ScriptProcessorFallbackLogic::ContinueBuild); + } } } diff --git a/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h b/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h index d7b1f32461..2cacfb0d34 100644 --- a/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h +++ b/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h @@ -7,4 +7,4 @@ */ #pragma once -#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 0 +#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 1 diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli index f658dd13da..ba06dada74 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli @@ -17,7 +17,7 @@ struct VSInput struct VSDepthOutput { - float4 m_position : SV_Position; + precise float4 m_position : SV_Position; }; VSDepthOutput DepthPassVS(VSInput IN) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl index 9aa169beea..e3237e59a2 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl @@ -150,7 +150,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) float4 encodedNormal = PassSrg::m_normal.Load(screenCoords, sampleIndex); float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb); float4 albedo = PassSrg::m_albedo.Load(screenCoords, sampleIndex); - float probeIrradianceBlendWeight = PassSrg::m_downsampledProbeIrradiance.Load(probeIrradianceCoords, sampleIndex).a; + float probeIrradianceBlendWeight = saturate(PassSrg::m_downsampledProbeIrradiance.Load(probeIrradianceCoords, sampleIndex).a); float3 diffuse = float3(0.0f, 0.0f, 0.0f); if (probeIrradianceBlendWeight > 0.0f) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader index 781d7e26e5..1f04570625 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant index 668dc28ca0..a359556df6 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant index 77bb341839..7a90c7f352 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant index 117f993f28..4cbb76954d 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp index de49c4ff50..a72d90fc94 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp @@ -102,8 +102,17 @@ namespace AZ void DiffuseProbeGrid::SetProbeSpacing(const AZ::Vector3& probeSpacing) { + // remove previous spacing from the render extents + m_renderExtents -= m_probeSpacing; + + // update probe spacing m_probeSpacing = probeSpacing; + // expand the extents by one probe spacing unit in order to blend properly around the edges of the volume + m_renderExtents += m_probeSpacing; + + m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f); + // recompute the number of probes since the spacing changed UpdateProbeCount(); @@ -128,7 +137,8 @@ namespace AZ void DiffuseProbeGrid::SetTransform(const AZ::Transform& transform) { m_transform = transform; - m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_extents / 2.0f); + + m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f); // probes need to be relocated since the grid position changed m_remainingRelocationIterations = DefaultNumRelocationIterations; @@ -144,11 +154,15 @@ namespace AZ void DiffuseProbeGrid::SetExtents(const AZ::Vector3& extents) { m_extents = extents; - m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_extents / 2.0f); // recompute the number of probes since the extents changed UpdateProbeCount(); + // expand the extents by one probe spacing unit in order to blend properly around the edges of the volume + m_renderExtents = m_extents + m_probeSpacing; + + m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f); + // probes need to be relocated since the grid extents changed m_remainingRelocationIterations = DefaultNumRelocationIterations; @@ -700,11 +714,11 @@ namespace AZ RHI::ShaderInputImageIndex imageIndex; constantIndex = srgLayout->FindShaderInputConstantIndex(Name("m_modelToWorld")); - AZ::Matrix3x4 modelToWorld = AZ::Matrix3x4::CreateFromTransform(m_transform) * AZ::Matrix3x4::CreateScale(m_extents); + AZ::Matrix3x4 modelToWorld = AZ::Matrix3x4::CreateFromTransform(m_transform) * AZ::Matrix3x4::CreateScale(m_renderExtents); m_renderObjectSrg->SetConstant(constantIndex, modelToWorld); constantIndex = srgLayout->FindShaderInputConstantIndex(Name("m_modelToWorldInverse")); - AZ::Matrix3x4 modelToWorldInverse = AZ::Matrix3x4::CreateFromTransform(m_transform).GetInverseFull(); + AZ::Matrix3x4 modelToWorldInverse = modelToWorld.GetInverseFull(); m_renderObjectSrg->SetConstant(constantIndex, modelToWorldInverse); constantIndex = srgLayout->FindShaderInputConstantIndex(Name("m_obbHalfLengths")); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h index 6c3017fe33..a828fe4b96 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h @@ -183,11 +183,14 @@ namespace AZ // extents of the probe grid AZ::Vector3 m_extents = AZ::Vector3(0.0f, 0.0f, 0.0f); + // expanded extents for rendering the volume + AZ::Vector3 m_renderExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); + // probe grid OBB (world space), built from transform and extents AZ::Obb m_obbWs; // per-axis spacing of probes in the grid - AZ::Vector3 m_probeSpacing; + AZ::Vector3 m_probeSpacing = AZ::Vector3(0.0f, 0.0f, 0.0f); // per-axis number of probes in the grid uint32_t m_probeCountX = 0; diff --git a/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake b/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake index 419331db3b..4645eb9444 100644 --- a/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake +++ b/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake @@ -6,6 +6,6 @@ # # -set(ATOM_RHI_TRAIT_BUILD_SUPPORTS_TEST TRUE) +set(ATOM_RHI_TRAIT_BUILD_SUPPORTS_TEST FALSE) set(ATOM_RHI_TRAIT_BUILD_SUPPORTS_EDIT TRUE) set(PAL_TRAIT_BUILD_RENDERDOC_SUPPORTED FALSE) diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index af91615283..352ffb6486 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -348,14 +348,7 @@ namespace AZ::AtomBridge void AtomDebugDisplayViewportInterface::SetAlpha(float a) { m_rendState.m_color.SetA(a); - if (a < 1.0f) - { - m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque; - } - else - { - m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent; - } + m_rendState.m_opacityType = a < 1.0f ? AZ::RPI::AuxGeomDraw::OpacityType::Translucent : AZ::RPI::AuxGeomDraw::OpacityType::Opaque; } void AtomDebugDisplayViewportInterface::DrawQuad( diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index 91844c9b2f..0b11437620 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -285,13 +285,19 @@ namespace AZ::Render const double frameIntervalSeconds = m_fpsInterval.count(); + auto ClampedFloatDisplay = [](double value, const char* format) -> AZStd::string + { + constexpr float upperLimit = 10000.0f; + return value > upperLimit ? "inf" : AZStd::string::format(format, value); + }; + DrawLine( AZStd::string::format( - "FPS %.1f [%.0f..%.0f], %.1fms/frame, avg over %.1fs", - averageFPS, - minFPS, - maxFPS, - averageFrameMs, + "FPS %s [%s..%s], %sms/frame, avg over %.1fs", + ClampedFloatDisplay(averageFPS, "%.1f").c_str(), + ClampedFloatDisplay(minFPS, "%.0f").c_str(), + ClampedFloatDisplay(maxFPS, "%.0f").c_str(), + ClampedFloatDisplay(averageFrameMs, "%.1f").c_str(), frameIntervalSeconds), AZ::Colors::Yellow); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_Curvature.tif b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_Curvature.tif similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_Curvature.tif rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_Curvature.tif diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_High.fbx b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_High.fbx new file mode 100644 index 0000000000..0625c89874 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_High.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d72cec207a7677ba027eac72f41285907237e04a45ebacf64341de86fc6f022d +size 159115308 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_Normal.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_Normal.png similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_Normal.png rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_Normal.png diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_Stone_BaseColor.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_Stone_BaseColor.png similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_Stone_BaseColor.png rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_Stone_BaseColor.png diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_ao.tif b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_ao.tif similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_ao.tif rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_ao.tif diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_brass.material similarity index 59% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_brass.material index 6e490cb0b1..4ad325b086 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_brass.material @@ -1,39 +1,33 @@ { "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", "parentMaterial": "Materials/Presets/PBR/metal_brass.material", - "propertyLayoutVersion": 3, + "materialType": "Materials/Types/StandardPBR.materialtype", + "materialTypeVersion": 4, "properties": { - "occlusion": { - "diffuseTextureMap": "Objects/Lucy/Lucy_ao.tif", - "diffuseTextureMapUv": "Unwrapped" - }, "baseColor": { - "color": [ - 0.6745098233222961, - 0.48627451062202456, - 0.19607843458652497, - 1.0 - ], "factor": 1.0, "textureBlendMode": "Lerp", - "textureMap": "Objects/Lucy/Lucy_bronze_BaseColor.png", + "textureMap": "Hermanubis_bronze_BaseColor.png", "textureMapUv": "Unwrapped" }, "general": { "applySpecularAA": true }, "metallic": { - "textureMap": "Objects/Lucy/Lucy_bronze_Metallic.png", + "textureMap": "Hermanubis_bronze_Metallic.png", "textureMapUv": "Unwrapped" }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_Normal.png", + "textureMap": "Hermanubis_Normal.png", "textureMapUv": "Unwrapped" }, + "occlusion": { + "diffuseTextureMap": "Hermanubis_ao.tif", + "diffuseTextureMapUv": "Unwrapped" + }, "roughness": { - "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png", + "textureMap": "Hermanubis_bronze_Roughness.png", "textureMapUv": "Unwrapped", "upperBound": 0.6767677068710327 } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_brass_cavity.tif b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_brass_cavity.tif similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_brass_cavity.tif rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_brass_cavity.tif diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_bronze_BaseColor.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_bronze_BaseColor.png similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_bronze_BaseColor.png rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_bronze_BaseColor.png diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_bronze_Metallic.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_bronze_Metallic.png similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_bronze_Metallic.png rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_bronze_Metallic.png diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_bronze_Roughness.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_bronze_Roughness.png similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_bronze_Roughness.png rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_bronze_Roughness.png diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_convexity.tif b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_convexity.tif similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_convexity.tif rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_convexity.tif diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_low.fbx b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_low.fbx new file mode 100644 index 0000000000..79960433dd --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_low.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c9d1030b9467b58d640fbedf1bc58ab9a5f7d68811b2452dd8d60114287b731 +size 12410812 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_stone.material similarity index 77% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_stone.material index a0e54d9d0e..1ba59a50c5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_stone.material @@ -1,13 +1,9 @@ { "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", "parentMaterial": "Materials/Presets/PBR/metal_brass.material", - "propertyLayoutVersion": 3, + "materialType": "Materials/Types/StandardPBR.materialtype", + "materialTypeVersion": 4, "properties": { - "occlusion": { - "diffuseTextureMap": "Objects/Lucy/Lucy_ao.tif", - "diffuseTextureMapUv": "Unwrapped" - }, "baseColor": { "color": [ 1.0, @@ -17,7 +13,7 @@ ], "factor": 1.0, "textureBlendMode": "Lerp", - "textureMap": "Objects/Lucy/Lucy_Stone_BaseColor.png", + "textureMap": "Hermanubis_Stone_BaseColor.png", "textureMapUv": "Unwrapped" }, "clearCoat": { @@ -39,13 +35,17 @@ }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_Normal.png", + "textureMap": "Hermanubis_Normal.png", "textureMapUv": "Unwrapped" }, + "occlusion": { + "diffuseTextureMap": "Hermanubis_ao.tif", + "diffuseTextureMapUv": "Unwrapped" + }, "roughness": { "factor": 1.0, - "lowerBound": 0.15000000596046449, - "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png", + "lowerBound": 0.15000000596046448, + "textureMap": "Hermanubis_bronze_Roughness.png", "textureMapUv": "Unwrapped", "upperBound": 0.7300000190734863 } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_thickness.tif b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_thickness.tif similarity index 100% rename from Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_thickness.tif rename to Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Hermanubis/Hermanubis_thickness.tif diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_High.fbx b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_High.fbx deleted file mode 100644 index b87971bf6d..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_High.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:00e19e317613be5420fd78bac1159e66d1c4deeb1f32cd4fc8c20b1ea3a5ead1 -size 153114272 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_low.fbx b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_low.fbx deleted file mode 100644 index 46f5d1cfbd..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/Lucy_low.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6a4a65d139a6088dd4ac34f3ba3f6a7a98b8fe9545150ee7d9879fbc2a55d8d4 -size 9022128 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index 7668477690..d67548c3e9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -261,6 +261,11 @@ namespace AZ::Render m_lightShapeDelegate->SetPhotometricUnit(m_configuration.m_intensityMode); m_lightShapeDelegate->SetIntensity(m_configuration.m_intensity); } + + if (m_configuration.m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic) + { + AttenuationRadiusChanged(); + } } void AreaLightComponentController::ChromaChanged() diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp index 421e5828b1..21f9f69f7c 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp @@ -63,7 +63,10 @@ namespace AZ::Render // Render aabb if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_AABB]) { - RenderAABB(instance, renderActorSettings.m_staticAABBColor); + RenderAABB(instance, + renderActorSettings.m_enabledNodeBasedAabb, renderActorSettings.m_nodeAABBColor, + renderActorSettings.m_enabledMeshBasedAabb, renderActorSettings.m_meshAABBColor, + renderActorSettings.m_enabledStaticBasedAabb, renderActorSettings.m_staticAABBColor); } // Render simple line skeleton @@ -201,11 +204,46 @@ namespace AZ::Render return AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); } - void AtomActorDebugDraw::RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor) + void AtomActorDebugDraw::RenderAABB(EMotionFX::ActorInstance* instance, + bool enableNodeAabb, + const AZ::Color& nodeAabbColor, + bool enableMeshAabb, + const AZ::Color& meshAabbColor, + bool enableStaticAabb, + const AZ::Color& staticAabbColor) { RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue(); - const AZ::Aabb& aabb = instance->GetAabb(); - auxGeom->DrawAabb(aabb, aabbColor, RPI::AuxGeomDraw::DrawStyle::Line); + + if (enableNodeAabb) + { + AZ::Aabb aabb; + instance->CalcNodeBasedAabb(&aabb); + if (aabb.IsValid()) + { + auxGeom->DrawAabb(aabb, nodeAabbColor, RPI::AuxGeomDraw::DrawStyle::Line); + } + } + + if (enableMeshAabb) + { + AZ::Aabb aabb; + const size_t lodLevel = instance->GetLODLevel(); + instance->CalcMeshBasedAabb(lodLevel, &aabb); + if (aabb.IsValid()) + { + auxGeom->DrawAabb(aabb, meshAabbColor, RPI::AuxGeomDraw::DrawStyle::Line); + } + } + + if (enableStaticAabb) + { + AZ::Aabb aabb; + instance->CalcStaticBasedAabb(&aabb); + if (aabb.IsValid()) + { + auxGeom->DrawAabb(aabb, staticAabbColor, RPI::AuxGeomDraw::DrawStyle::Line); + } + } } void AtomActorDebugDraw::RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h index 3c0258cfef..8e985fdbc6 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h @@ -49,7 +49,13 @@ namespace AZ::Render void PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM); AzFramework::DebugDisplayRequests* GetDebugDisplay(AzFramework::ViewportId viewportId); - void RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor); + void RenderAABB(EMotionFX::ActorInstance* instance, + bool enableNodeAabb, + const AZ::Color& nodeAabbColor, + bool enableMeshAabb, + const AZ::Color& meshAabbColor, + bool enableStaticAabb, + const AZ::Color& staticAabbColor); void RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor); void RenderSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor); void RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp index 241412c6c8..cc344db488 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp @@ -1071,6 +1071,8 @@ namespace EMStudio settings.m_mirroredBitangentsColor = m_mirroredBitangentsColor; settings.m_bitangentsColor = m_bitangentsColor; settings.m_wireframeColor = m_wireframeColor; + settings.m_nodeAABBColor = m_nodeAABBColor; + settings.m_meshAABBColor = m_meshAABBColor; settings.m_staticAABBColor = m_staticAABBColor; settings.m_skeletonColor = m_skeletonColor; settings.m_lineSkeletonColor = m_lineSkeletonColor; diff --git a/Gems/EMotionFX/Code/Source/Integration/Rendering/RenderActorSettings.h b/Gems/EMotionFX/Code/Source/Integration/Rendering/RenderActorSettings.h index 0260d1aae5..8663b768c8 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Rendering/RenderActorSettings.h +++ b/Gems/EMotionFX/Code/Source/Integration/Rendering/RenderActorSettings.h @@ -28,6 +28,10 @@ namespace AZ::Render float m_wireframeScale = 1.0f; float m_nodeOrientationScale = 1.0f; + bool m_enabledNodeBasedAabb = true; + bool m_enabledMeshBasedAabb = true; + bool m_enabledStaticBasedAabb = true; + AZ::Color m_hitDetectionColliderColor{0.44f, 0.44f, 0.44f, 1.0f}; AZ::Color m_selectedHitDetectionColliderColor{ 0.3f, 0.56f, 0.88f, 1.0f }; AZ::Color m_ragdollColliderColor{ 0.44f, 0.44f, 0.44f, 1.0f }; @@ -44,9 +48,12 @@ namespace AZ::Render AZ::Color m_mirroredBitangentsColor{ 1.0f, 1.0f, 0.0f, 1.0f }; AZ::Color m_bitangentsColor{ 1.0f, 1.0f, 1.0f, 1.0f }; AZ::Color m_wireframeColor{ 0.0f, 0.0f, 0.0f, 1.0f }; - AZ::Color m_staticAABBColor{ 0.0f, 0.7f, 0.7f, 1.0f }; AZ::Color m_lineSkeletonColor{ 0.33333f, 1.0f, 0.0f, 1.0f }; AZ::Color m_skeletonColor{ 0.19f, 0.58f, 0.19f, 1.0f }; AZ::Color m_jointNameColor{ 1.0f, 1.0f, 1.0f, 1.0f }; + + AZ::Color m_nodeAABBColor{ 1.0f, 0.0f, 0.0f, 1.0f }; + AZ::Color m_meshAABBColor{ 0.0f, 0.0f, 0.7f, 1.0f }; + AZ::Color m_staticAABBColor{ 0.0f, 0.7f, 0.7f, 1.0f }; }; } // namespace AZ::Render diff --git a/Gems/GradientSignal/Code/CMakeLists.txt b/Gems/GradientSignal/Code/CMakeLists.txt index d1ac8cdacf..657a88db47 100644 --- a/Gems/GradientSignal/Code/CMakeLists.txt +++ b/Gems/GradientSignal/Code/CMakeLists.txt @@ -124,6 +124,26 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) Mocks ) + ly_add_target( + NAME GradientSignal.Tests.Static STATIC + NAMESPACE Gem + FILES_CMAKE + gradientsignal_shared_tests_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + Tests + PRIVATE + . + Source + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + AZ::AzTestShared + Gem::GradientSignal.Static + Gem::LmbrCentral + Gem::GradientSignal.Mocks + ) + ly_add_target( NAME GradientSignal.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem @@ -137,6 +157,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PRIVATE AZ::AzTest AZ::AzTestShared + Gem::GradientSignal.Tests.Static Gem::GradientSignal.Static Gem::LmbrCentral Gem::GradientSignal.Mocks @@ -165,6 +186,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PRIVATE AZ::AzTest AZ::AzTestShared + Gem::GradientSignal.Tests.Static Gem::GradientSignal.Static Gem::GradientSignal.Editor.Static Gem::LmbrCentral.Editor diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h b/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h index 1782972acf..d0fcabf746 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h @@ -11,6 +11,8 @@ #include #include +#include + namespace GradientSignal { struct GradientSampleParams final @@ -49,6 +51,36 @@ namespace GradientSignal */ virtual float GetValue(const GradientSampleParams& sampleParams) const = 0; + /** + * Given a list of positions, generate values. Implementations of this need to be thread-safe without using locks, + * as it can get called from multiple threads simultaneously and has the potential to cause lock inversion deadlocks. + * \param positions The input list of positions to query. + * \param outValues The output list of values. This list is expected to be the same size as the positions list. + */ + virtual void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + { + // Reference implementation of GetValues for any gradients that don't have their own optimized implementations. + // This is 10%-60% faster than calling GetValue via EBus many times due to the per-call EBus overhead. + + AZ_Assert( + positions.size() == outValues.size(), "input and output lists are different sizes (%zu vs %zu).", + positions.size(), outValues.size()); + + if (positions.size() == outValues.size()) + { + GradientSampleParams sampleParams; + for (size_t index = 0; index < positions.size(); index++) + { + sampleParams.m_position = positions[index]; + + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + outValue = GetValue(sampleParams); + } + } + } + /** * Call to check the hierarchy to see if a given entityId exists in the gradient signal chain */ diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h b/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h index 1dd7d44376..454be938a5 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h @@ -33,6 +33,7 @@ namespace GradientSignal static void Reflect(AZ::ReflectContext* context); inline float GetValue(const GradientSampleParams& sampleParams) const; + inline void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const; @@ -145,4 +146,93 @@ namespace GradientSignal return output * m_opacity; } + + inline void GradientSampler::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + { + auto ClearOutputValues = [](AZStd::array_view outValues) + { + // If we don't have a valid gradient (or it is fully transparent), clear out all the output values. + for (size_t index = 0; index < outValues.size(); index++) + { + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + outValue = 0.0f; + } + }; + + if (m_opacity <= 0.0f || !m_gradientId.IsValid()) + { + ClearOutputValues(outValues); + return; + } + + AZStd::vector transformedPositions; + bool useTransformedPositions = false; + + // apply transform if set + if (m_enableTransform && GradientSamplerUtil::AreTransformParamsSet(*this)) + { + AZ::Matrix3x4 matrix3x4; + matrix3x4.SetFromEulerDegrees(m_rotate); + matrix3x4.MultiplyByScale(m_scale); + matrix3x4.SetTranslation(m_translate); + + useTransformedPositions = true; + transformedPositions.resize(positions.size()); + for (size_t index = 0; index < positions.size(); index++) + { + transformedPositions[index] = matrix3x4 * positions[index]; + } + } + + { + // Block other threads from accessing the surface data bus while we are in GetValue (which may call into the SurfaceData bus). + // We lock our surface data mutex *before* checking / setting "isRequestInProgress" so that we prevent race conditions + // that create false detection of cyclic dependencies when multiple requests occur on different threads simultaneously. + // (One case where this was previously able to occur was in rapid updating of the Preview widget on the + // GradientSurfaceDataComponent in the Editor when moving the threshold sliders back and forth rapidly) + auto& surfaceDataContext = SurfaceData::SurfaceDataSystemRequestBus::GetOrCreateContext(false); + typename SurfaceData::SurfaceDataSystemRequestBus::Context::DispatchLockGuard scopeLock(surfaceDataContext.m_contextMutex); + + if (m_isRequestInProgress) + { + AZ_ErrorOnce("GradientSignal", !m_isRequestInProgress, "Detected cyclic dependences with gradient entity references"); + ClearOutputValues(outValues); + return; + } + else + { + m_isRequestInProgress = true; + + GradientRequestBus::Event( + m_gradientId, &GradientRequestBus::Events::GetValues, useTransformedPositions ? transformedPositions : positions, + outValues); + + m_isRequestInProgress = false; + } + } + + // Perform any post-fetch transformations on the gradient values (invert, levels, opacity). + for (size_t index = 0; index < outValues.size(); index++) + { + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + + if (m_invertInput) + { + outValue = 1.0f - outValue; + } + + // apply levels if set + if (m_enableLevels && GradientSamplerUtil::AreLevelParamsSet(*this)) + { + outValue = GetLevels(outValue, m_inputMid, m_inputMin, m_inputMax, m_outputMin, m_outputMax); + } + + outValue = outValue * m_opacity; + } + } + } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp index dd179bd253..6383b627c1 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp @@ -23,74 +23,145 @@ namespace UnitTest { - BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientGetValue)(benchmark::State& state) + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValue)(benchmark::State& state) { - // Create the Image Gradient Component with some default sizes and parameters. - GradientSignal::ImageGradientConfig config; - const uint32_t imageSize = 4096; - const int32_t imageSeed = 12345; - config.m_imageAsset = ImageAssetMockAssetHandler::CreateImageAsset(imageSize, imageSize, imageSeed); - config.m_tilingX = 1.0f; - config.m_tilingY = 1.0f; - CreateComponent(m_testEntity.get(), config); - - // Create the Gradient Transform Component with some default parameters. - GradientSignal::GradientTransformConfig gradientTransformConfig; - gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; - CreateComponent(m_testEntity.get(), gradientTransformConfig); - - // Run the benchmark - RunGetValueBenchmark(state); + CreateTestImageGradient(m_testEntity.get()); + RunEBusGetValueBenchmark(state); } - BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientGetValue) + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValue) ->Args({ 1024, 1024 }) ->Args({ 2048, 2048 }) ->Args({ 4096, 4096 }) ->Unit(::benchmark::kMillisecond); - BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientGetValue)(benchmark::State& state) + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValues)(benchmark::State& state) { - // Create the Perlin Gradient Component with some default sizes and parameters. - GradientSignal::PerlinGradientConfig config; - config.m_amplitude = 1.0f; - config.m_frequency = 1.1f; - config.m_octave = 4; - config.m_randomSeed = 12345; - CreateComponent(m_testEntity.get(), config); - - // Create the Gradient Transform Component with some default parameters. - GradientSignal::GradientTransformConfig gradientTransformConfig; - gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; - CreateComponent(m_testEntity.get(), gradientTransformConfig); - - // Run the benchmark - RunGetValueBenchmark(state); + CreateTestImageGradient(m_testEntity.get()); + RunEBusGetValuesBenchmark(state); } - BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientGetValue) + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValues) ->Args({ 1024, 1024 }) ->Args({ 2048, 2048 }) ->Args({ 4096, 4096 }) ->Unit(::benchmark::kMillisecond); - BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientGetValue)(benchmark::State& state) + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValue)(benchmark::State& state) { - // Create the Random Gradient Component with some default parameters. - GradientSignal::RandomGradientConfig config; - config.m_randomSeed = 12345; - CreateComponent(m_testEntity.get(), config); - - // Create the Gradient Transform Component with some default parameters. - GradientSignal::GradientTransformConfig gradientTransformConfig; - gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; - CreateComponent(m_testEntity.get(), gradientTransformConfig); - - // Run the benchmark - RunGetValueBenchmark(state); + CreateTestImageGradient(m_testEntity.get()); + RunSamplerGetValueBenchmark(state); } - BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientGetValue) + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValue) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValues)(benchmark::State& state) + { + CreateTestImageGradient(m_testEntity.get()); + RunSamplerGetValuesBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValues) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValue)(benchmark::State& state) + { + CreateTestPerlinGradient(m_testEntity.get()); + RunEBusGetValueBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValue) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValues)(benchmark::State& state) + { + CreateTestPerlinGradient(m_testEntity.get()); + RunEBusGetValuesBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValues) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValue)(benchmark::State& state) + { + CreateTestPerlinGradient(m_testEntity.get()); + RunSamplerGetValueBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValue) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValues)(benchmark::State& state) + { + CreateTestPerlinGradient(m_testEntity.get()); + RunSamplerGetValuesBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValues) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValue)(benchmark::State& state) + { + CreateTestRandomGradient(m_testEntity.get()); + RunEBusGetValueBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValue) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValues)(benchmark::State& state) + { + CreateTestRandomGradient(m_testEntity.get()); + RunEBusGetValuesBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValues) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValue)(benchmark::State& state) + { + CreateTestRandomGradient(m_testEntity.get()); + RunSamplerGetValueBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValue) + ->Args({ 1024, 1024 }) + ->Args({ 2048, 2048 }) + ->Args({ 4096, 4096 }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValues)(benchmark::State& state) + { + CreateTestRandomGradient(m_testEntity.get()); + RunSamplerGetValuesBenchmark(state); + } + + BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValues) ->Args({ 1024, 1024 }) ->Args({ 2048, 2048 }) ->Args({ 4096, 4096 }) diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp index bc9b39aae8..77568d3321 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp @@ -9,6 +9,11 @@ #include +#include +#include +#include +#include + namespace UnitTest { void GradientSignalBaseFixture::SetupCoreSystems() @@ -86,8 +91,56 @@ namespace UnitTest m_testEntity.reset(); } - void GradientSignalBenchmarkFixture::RunGetValueBenchmark(benchmark::State& state) + void GradientSignalBenchmarkFixture::CreateTestImageGradient(AZ::Entity* entity) { + // Create the Image Gradient Component with some default sizes and parameters. + GradientSignal::ImageGradientConfig config; + const uint32_t imageSize = 4096; + const int32_t imageSeed = 12345; + config.m_imageAsset = ImageAssetMockAssetHandler::CreateImageAsset(imageSize, imageSize, imageSeed); + config.m_tilingX = 1.0f; + config.m_tilingY = 1.0f; + CreateComponent(entity, config); + + // Create the Gradient Transform Component with some default parameters. + GradientSignal::GradientTransformConfig gradientTransformConfig; + gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; + CreateComponent(entity, gradientTransformConfig); + } + + void GradientSignalBenchmarkFixture::CreateTestPerlinGradient(AZ::Entity* entity) + { + // Create the Perlin Gradient Component with some default sizes and parameters. + GradientSignal::PerlinGradientConfig config; + config.m_amplitude = 1.0f; + config.m_frequency = 1.1f; + config.m_octave = 4; + config.m_randomSeed = 12345; + CreateComponent(entity, config); + + // Create the Gradient Transform Component with some default parameters. + GradientSignal::GradientTransformConfig gradientTransformConfig; + gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; + CreateComponent(entity, gradientTransformConfig); + } + + void GradientSignalBenchmarkFixture::CreateTestRandomGradient(AZ::Entity* entity) + { + // Create the Random Gradient Component with some default parameters. + GradientSignal::RandomGradientConfig config; + config.m_randomSeed = 12345; + CreateComponent(entity, config); + + // Create the Gradient Transform Component with some default parameters. + GradientSignal::GradientTransformConfig gradientTransformConfig; + gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; + CreateComponent(entity, gradientTransformConfig); + } + + void GradientSignalBenchmarkFixture::RunSamplerGetValueBenchmark(benchmark::State& state) + { + AZ_PROFILE_FUNCTION(Entity); + // All components are created, so activate the entity ActivateEntity(m_testEntity.get()); @@ -115,6 +168,107 @@ namespace UnitTest } } + void GradientSignalBenchmarkFixture::RunSamplerGetValuesBenchmark(benchmark::State& state) + { + AZ_PROFILE_FUNCTION(Entity); + + // All components are created, so activate the entity + ActivateEntity(m_testEntity.get()); + + // Create a gradient sampler and run through a series of points to see if they match expectations. + GradientSignal::GradientSampler gradientSampler; + gradientSampler.m_gradientId = m_testEntity->GetId(); + + // Get the height and width ranges for querying from our benchmark parameters + float height = aznumeric_cast(state.range(0)); + float width = aznumeric_cast(state.range(1)); + int64_t totalQueryPoints = state.range(0) * state.range(1); + + // Call GetValues() for every height and width in our ranges. + for (auto _ : state) + { + // Set up our vector of query positions. + AZStd::vector positions(totalQueryPoints); + size_t index = 0; + for (float y = 0.0f; y < height; y += 1.0f) + { + for (float x = 0.0f; x < width; x += 1.0f) + { + positions[index++] = AZ::Vector3(x, y, 0.0f); + } + } + + // Query and get the results. + AZStd::vector results(totalQueryPoints); + gradientSampler.GetValues(positions, results); + } + } + + void GradientSignalBenchmarkFixture::RunEBusGetValueBenchmark(benchmark::State& state) + { + AZ_PROFILE_FUNCTION(Entity); + + // All components are created, so activate the entity + ActivateEntity(m_testEntity.get()); + + GradientSignal::GradientSampleParams params; + + // Get the height and width ranges for querying from our benchmark parameters + float height = aznumeric_cast(state.range(0)); + float width = aznumeric_cast(state.range(1)); + + // Call GetValue() for every height and width in our ranges. + for (auto _ : state) + { + for (float y = 0.0f; y < height; y += 1.0f) + { + for (float x = 0.0f; x < width; x += 1.0f) + { + float value = 0.0f; + params.m_position = AZ::Vector3(x, y, 0.0f); + GradientSignal::GradientRequestBus::EventResult( + value, m_testEntity->GetId(), &GradientSignal::GradientRequestBus::Events::GetValue, params); + benchmark::DoNotOptimize(value); + } + } + } + } + + void GradientSignalBenchmarkFixture::RunEBusGetValuesBenchmark(benchmark::State& state) + { + AZ_PROFILE_FUNCTION(Entity); + + // All components are created, so activate the entity + ActivateEntity(m_testEntity.get()); + + GradientSignal::GradientSampler gradientSampler; + gradientSampler.m_gradientId = m_testEntity->GetId(); + + // Get the height and width ranges for querying from our benchmark parameters + float height = aznumeric_cast(state.range(0)); + float width = aznumeric_cast(state.range(1)); + int64_t totalQueryPoints = state.range(0) * state.range(1); + + // Call GetValues() for every height and width in our ranges. + for (auto _ : state) + { + // Set up our vector of query positions. + AZStd::vector positions(totalQueryPoints); + size_t index = 0; + for (float y = 0.0f; y < height; y += 1.0f) + { + for (float x = 0.0f; x < width; x += 1.0f) + { + positions[index++] = AZ::Vector3(x, y, 0.0f); + } + } + + // Query and get the results. + AZStd::vector results(totalQueryPoints); + GradientSignal::GradientRequestBus::Event( + m_testEntity->GetId(), &GradientSignal::GradientRequestBus::Events::GetValues, positions, results); + } + } #endif } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h index 5e05cba374..13ff69c82d 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h @@ -97,7 +97,15 @@ namespace UnitTest void CreateTestEntity(float shapeHalfBounds); void DestroyTestEntity(); - void RunGetValueBenchmark(benchmark::State& state); + void CreateTestImageGradient(AZ::Entity* entity); + void CreateTestPerlinGradient(AZ::Entity* entity); + void CreateTestRandomGradient(AZ::Entity* entity); + + void RunSamplerGetValueBenchmark(benchmark::State& state); + void RunSamplerGetValuesBenchmark(benchmark::State& state); + + void RunEBusGetValueBenchmark(benchmark::State& state); + void RunEBusGetValuesBenchmark(benchmark::State& state); protected: void SetUp(const benchmark::State& state) override diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.cpp index ccbe17dee8..7ac6ef1ecc 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.cpp @@ -13,13 +13,14 @@ namespace UnitTest { AZ::Data::Asset ImageAssetMockAssetHandler::CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed) { - GradientSignal::ImageAsset* imageData = - aznew GradientSignal::ImageAsset(AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetData::AssetStatus::Ready); - imageData->m_imageWidth = width; - imageData->m_imageHeight = height; - imageData->m_bytesPerPixel = 1; - imageData->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8; - imageData->m_imageData.reserve(width * height); + auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset( + AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetLoadBehavior::Default); + + imageAsset->m_imageWidth = width; + imageAsset->m_imageHeight = height; + imageAsset->m_bytesPerPixel = 1; + imageAsset->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8; + imageAsset->m_imageData.reserve(width * height); size_t value = 0; AZStd::hash_combine(value, seed); @@ -30,23 +31,24 @@ namespace UnitTest { AZStd::hash_combine(value, x); AZStd::hash_combine(value, y); - imageData->m_imageData.push_back(static_cast(value)); + imageAsset->m_imageData.push_back(static_cast(value)); } } - return AZ::Data::Asset(imageData, AZ::Data::AssetLoadBehavior::Default); + return imageAsset; } AZ::Data::Asset ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset( AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY) { - GradientSignal::ImageAsset* imageData = - aznew GradientSignal::ImageAsset(AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetData::AssetStatus::Ready); - imageData->m_imageWidth = width; - imageData->m_imageHeight = height; - imageData->m_bytesPerPixel = 1; - imageData->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8; - imageData->m_imageData.reserve(width * height); + auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset( + AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetLoadBehavior::Default); + + imageAsset->m_imageWidth = width; + imageAsset->m_imageHeight = height; + imageAsset->m_bytesPerPixel = 1; + imageAsset->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8; + imageAsset->m_imageData.reserve(width * height); const AZ::u8 pixelValue = 255; @@ -57,16 +59,16 @@ namespace UnitTest { if ((x == static_cast(pixelX)) && (y == static_cast(pixelY))) { - imageData->m_imageData.push_back(pixelValue); + imageAsset->m_imageData.push_back(pixelValue); } else { - imageData->m_imageData.push_back(0); + imageAsset->m_imageData.push_back(0); } } } - return AZ::Data::Asset(imageData, AZ::Data::AssetLoadBehavior::Default); + return imageAsset; } } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h index 1d83a5eb55..30f262d9b4 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h @@ -47,10 +47,10 @@ namespace UnitTest static AZ::Data::Asset CreateSpecificPixelImageAsset( AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY); - AZ::Data::AssetPtr CreateAsset( - [[maybe_unused]] const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override + AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override { - return AZ::Data::AssetPtr(); + // For our mock handler, always mark our assets as immediately ready. + return aznew GradientSignal::ImageAsset(id, AZ::Data::AssetData::AssetStatus::Ready); } void DestroyAsset(AZ::Data::AssetPtr ptr) override diff --git a/Gems/GradientSignal/Code/gradientsignal_editor_tests_files.cmake b/Gems/GradientSignal/Code/gradientsignal_editor_tests_files.cmake index 8172591afa..5a3a75602b 100644 --- a/Gems/GradientSignal/Code/gradientsignal_editor_tests_files.cmake +++ b/Gems/GradientSignal/Code/gradientsignal_editor_tests_files.cmake @@ -7,6 +7,5 @@ # set(FILES - Tests/GradientSignalTestFixtures.cpp Tests/EditorGradientSignalPreviewTests.cpp ) diff --git a/Gems/GradientSignal/Code/gradientsignal_shared_tests_files.cmake b/Gems/GradientSignal/Code/gradientsignal_shared_tests_files.cmake new file mode 100644 index 0000000000..7d867b0a33 --- /dev/null +++ b/Gems/GradientSignal/Code/gradientsignal_shared_tests_files.cmake @@ -0,0 +1,14 @@ +# +# 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 +# +# + +set(FILES + Tests/GradientSignalTestFixtures.cpp + Tests/GradientSignalTestFixtures.h + Tests/GradientSignalTestMocks.cpp + Tests/GradientSignalTestMocks.h +) diff --git a/Gems/GradientSignal/Code/gradientsignal_tests_files.cmake b/Gems/GradientSignal/Code/gradientsignal_tests_files.cmake index 8e081e5711..eb799811b7 100644 --- a/Gems/GradientSignal/Code/gradientsignal_tests_files.cmake +++ b/Gems/GradientSignal/Code/gradientsignal_tests_files.cmake @@ -13,10 +13,6 @@ set(FILES Tests/GradientSignalServicesTests.cpp Tests/GradientSignalSurfaceTests.cpp Tests/GradientSignalTransformTests.cpp - Tests/GradientSignalTestFixtures.cpp - Tests/GradientSignalTestFixtures.h - Tests/GradientSignalTestMocks.cpp - Tests/GradientSignalTestMocks.h Tests/GradientSignalTest.cpp Tests/ImageAssetTests.cpp ) diff --git a/Gems/LyShine/Code/Include/LyShine/Draw2d.h b/Gems/LyShine/Code/Include/LyShine/Draw2d.h index 881479bd23..f92c6ce2e1 100644 --- a/Gems/LyShine/Code/Include/LyShine/Draw2d.h +++ b/Gems/LyShine/Code/Include/LyShine/Draw2d.h @@ -50,6 +50,7 @@ public: // types { AZ::Vector3 color = AZ::Vector3(1.0f, 1.0f, 1.0f); Rounding pixelRounding = Rounding::Nearest; + bool m_clamp = false; RenderState m_renderState; }; @@ -145,6 +146,7 @@ public: // member functions virtual void DrawQuad(AZ::Data::Instance image, VertexPosColUV* verts, Rounding pixelRounding = Rounding::Nearest, + bool clamp = false, const RenderState& renderState = RenderState{}); //! Draw a line @@ -257,6 +259,8 @@ protected: // types and constants { AZ::RHI::ShaderInputImageIndex m_imageInputIndex; AZ::RHI::ShaderInputConstantIndex m_viewProjInputIndex; + AZ::RPI::ShaderVariantId m_shaderOptionsClamp; + AZ::RPI::ShaderVariantId m_shaderOptionsWrap; }; class DeferredPrimitive @@ -281,6 +285,7 @@ protected: // types and constants AZ::Vector2 m_texCoords[4]; uint32 m_packedColors[4]; AZ::Data::Instance m_image; + bool m_clamp; RenderState m_renderState; }; @@ -455,11 +460,12 @@ public: // member functions //! See IDraw2d:DrawQuad for parameter descriptions void DrawQuad(AZ::Data::Instance image, CDraw2d::VertexPosColUV* verts, IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, + bool clamp = false, const CDraw2d::RenderState& renderState = CDraw2d::RenderState{}) { if (m_draw2d) { - m_draw2d->DrawQuad(image, verts, pixelRounding, renderState); + m_draw2d->DrawQuad(image, verts, pixelRounding, clamp, renderState); } } @@ -545,6 +551,9 @@ public: // member functions //! Set the base state (that blend mode etc is combined with) used for images, default is GS_NODEPTHTEST. void SetImageDepthState(const AZ::RHI::DepthState& depthState) { m_imageOptions.m_renderState.m_depthState = depthState; } + //! Set image clamp mode + void SetImageClamp(bool clamp) { m_imageOptions.m_clamp = clamp; } + //! Set the text font. void SetTextFont(AZStd::string_view fontName) { m_textOptions.fontName = fontName; } diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 6b6356aa4f..917c1bb168 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -103,10 +103,7 @@ void CDraw2d::OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) LyShinePassRequestBus::EventResult(uiCanvasPass, sceneId, &LyShinePassRequestBus::Events::GetUiCanvasPass); m_dynamicDraw = AZ::RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(); - AZ::RPI::ShaderOptionList shaderOptions; - shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("true"))); - shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("false"))); - m_dynamicDraw->InitShaderWithVariant(shader, &shaderOptions); + m_dynamicDraw->InitShader(shader); m_dynamicDraw->InitVertexFormat( { {"POSITION", AZ::RHI::Format::R32G32B32_FLOAT}, {"COLOR", AZ::RHI::Format::B8G8R8A8_UNORM}, @@ -136,6 +133,16 @@ void CDraw2d::OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) m_shaderData.m_viewProjInputIndex = layout->FindShaderInputConstantIndex(AZ::Name(worldToProjIndexName)); AZ_Error("Draw2d", m_shaderData.m_viewProjInputIndex.IsValid(), "Failed to find shader input constant %s.", worldToProjIndexName); + + // Cache shader variants that will be used + AZ::RPI::ShaderOptionList shaderOptionsClamp; + shaderOptionsClamp.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true"))); + shaderOptionsClamp.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("true"))); + m_shaderData.m_shaderOptionsClamp = m_dynamicDraw->UseShaderVariant(shaderOptionsClamp); + AZ::RPI::ShaderOptionList shaderOptionsWrap; + shaderOptionsWrap.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("false"))); + shaderOptionsWrap.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("true"))); + m_shaderData.m_shaderOptionsWrap = m_dynamicDraw->UseShaderVariant(shaderOptionsWrap); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -181,6 +188,8 @@ void CDraw2d::DrawImage(AZ::Data::Instance image, AZ::Vector2 po quad.m_image = image; + quad.m_clamp = actualImageOptions->m_clamp; + // add the blendMode flags to the base state quad.m_renderState = actualImageOptions->m_renderState; @@ -206,7 +215,7 @@ void CDraw2d::DrawImageAligned(AZ::Data::Instance image, AZ::Vec //////////////////////////////////////////////////////////////////////////////////////////////////// void CDraw2d::DrawQuad(AZ::Data::Instance image, VertexPosColUV* verts, Rounding pixelRounding, - const CDraw2d::RenderState& renderState) + bool clamp, const CDraw2d::RenderState& renderState) { // define quad DeferredQuad quad; @@ -217,6 +226,7 @@ void CDraw2d::DrawQuad(AZ::Data::Instance image, VertexPosColUV* quad.m_packedColors[i] = PackARGB8888(verts[i].color); } quad.m_image = image; + quad.m_clamp = clamp; // add the blendMode flags to the base state quad.m_renderState = renderState; @@ -766,6 +776,8 @@ void CDraw2d::DeferredQuad::Draw(AZ::RHI::Ptr dynam vertices[i].st = Vec2(m_texCoords[j].GetX(), m_texCoords[j].GetY()); } + dynamicDraw->SetShaderVariant(m_clamp ? shaderData.m_shaderOptionsClamp : shaderData.m_shaderOptionsWrap); + // Set up per draw SRG AZ::Data::Instance drawSrg = dynamicDraw->NewDrawSrg(); diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index d19bc3f92d..683d72f4ab 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -668,7 +668,7 @@ void CLyShine::LoadUiCursor() { if (!m_cursorImagePathToLoad.empty()) { - m_uiCursorTexture = CDraw2d::LoadTexture(m_cursorImagePathToLoad); // LYSHINE_ATOM_TODO - add clamp option to draw2d and set cursor to clamp + m_uiCursorTexture = CDraw2d::LoadTexture(m_cursorImagePathToLoad); m_cursorImagePathToLoad.clear(); } } @@ -691,7 +691,13 @@ void CLyShine::RenderUiCursor() AZ::RHI::Size cursorSize = m_uiCursorTexture->GetDescriptor().m_size; const AZ::Vector2 dimensions(aznumeric_cast(cursorSize.m_width), aznumeric_cast(cursorSize.m_height)); - m_draw2d->DrawImage(m_uiCursorTexture, position, dimensions); + CDraw2d::ImageOptions imageOptions; + imageOptions.m_clamp = true; + const float opacity = 1.0f; + const float rotation = 0.0f; + const AZ::Vector2* pivotPoint = nullptr; + const AZ::Vector2* minMaxTexCoords = nullptr; + m_draw2d->DrawImage(m_uiCursorTexture, position, dimensions, opacity, rotation, pivotPoint, minMaxTexCoords, &imageOptions); } #ifndef _RELEASE diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index 2a6baed411..a797523bc0 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -20,11 +20,10 @@ namespace Multiplayer { - using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor; - using AzToolsFramework::Prefab::PrefabConversionUtils::ProcessedObjectStore; - - void NetworkPrefabProcessor::Process(PrefabProcessorContext& context) + void NetworkPrefabProcessor::Process(AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context) { + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument; + IMultiplayerTools* mpTools = AZ::Interface::Get(); if (mpTools) { @@ -33,11 +32,17 @@ namespace Multiplayer AZ::DataStream::StreamType serializationFormat = GetAzSerializationFormat(); - context.ListPrefabs([&context, serializationFormat](AZStd::string_view prefabName, PrefabDom& prefab) { - ProcessPrefab(context, prefabName, prefab, serializationFormat); - }); + bool networkPrefabsAdded = false; + context.ListPrefabs( + [&networkPrefabsAdded, &context, serializationFormat](PrefabDocument& prefab) + { + if (ProcessPrefab(context, prefab, serializationFormat)) + { + networkPrefabsAdded = true; + } + }); - if (mpTools && !context.GetProcessedObjects().empty()) + if (mpTools && networkPrefabsAdded) { mpTools->SetDidProcessNetworkPrefabs(true); } @@ -59,28 +64,6 @@ namespace Multiplayer } } - static AZStd::unique_ptr LoadInstanceFromPrefab(const PrefabDom& prefab) - { - using namespace AzToolsFramework::Prefab; - - // convert Prefab DOM into Prefab Instance. - AZStd::unique_ptr sourceInstance(aznew Instance()); - if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId)) - { - PrefabDomValueConstReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName); - - AZStd::string errorMessage("NetworkPrefabProcessor: Failed to Load Prefab Instance from given Prefab Dom."); - if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0) - { - AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength()); - errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source)); - } - AZ_Error("NetworkPrefabProcessor", false, errorMessage.c_str()); - return nullptr; - } - return sourceInstance; - } - static void GatherNetEntities( AzToolsFramework::Prefab::Instance* instance, AZStd::unordered_map& entityToInstanceMap, @@ -103,18 +86,15 @@ namespace Multiplayer }); } - void NetworkPrefabProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab, AZ::DataStream::StreamType serializationFormat) + bool NetworkPrefabProcessor::ProcessPrefab( + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context, + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument& prefab, + AZ::DataStream::StreamType serializationFormat) { + using AzToolsFramework::Prefab::PrefabConversionUtils::ProcessedObjectStore; using namespace AzToolsFramework::Prefab; - // convert Prefab DOM into Prefab Instance. - AZStd::unique_ptr sourceInstance = LoadInstanceFromPrefab(prefab); - if (!sourceInstance) - { - return; - } - - AZStd::string uniqueName = prefabName; + AZStd::string uniqueName = prefab.GetName(); uniqueName += ".network.spawnable"; auto serializer = [serializationFormat](AZStd::vector& output, const ProcessedObjectStore& object) -> bool { @@ -127,15 +107,16 @@ namespace Multiplayer ProcessedObjectStore::Create(uniqueName, context.GetSourceUuid(), AZStd::move(serializer)); auto& netSpawnableEntities = networkSpawnable->GetEntities(); + Instance& sourceInstance = prefab.GetInstance(); // Grab all net entities with their corresponding Instances to handle nested prefabs correctly AZStd::unordered_map netEntityToInstanceMap; AZStd::vector prefabNetEntities; - GatherNetEntities(sourceInstance.get(), netEntityToInstanceMap, prefabNetEntities); + GatherNetEntities(&sourceInstance, netEntityToInstanceMap, prefabNetEntities); if (prefabNetEntities.empty()) { // No networked entities in the prefab, no need to do anything in this processor. - return; + return false; } // Sort the entities prior to processing. The entities will end up in the net spawnable in this order. @@ -182,7 +163,7 @@ namespace Multiplayer // Add net spawnable asset holder to the prefab root { - EntityOptionalReference containerEntityRef = sourceInstance->GetContainerEntity(); + EntityOptionalReference containerEntityRef = sourceInstance.GetContainerEntity(); if (containerEntityRef.has_value()) { auto* networkSpawnableHolderComponent = containerEntityRef.value().get().CreateComponent(); @@ -193,18 +174,12 @@ namespace Multiplayer AZ::Entity* networkSpawnableHolderEntity = aznew AZ::Entity(uniqueName); auto* networkSpawnableHolderComponent = networkSpawnableHolderEntity->CreateComponent(); networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset); - sourceInstance->AddEntity(*networkSpawnableHolderEntity); + sourceInstance.AddEntity(*networkSpawnableHolderEntity); } } - // save the final result in the target Prefab DOM. - if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab)) - { - AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed."); - return; - } - context.GetProcessedObjects().push_back(AZStd::move(object)); + return true; } AZ::DataStream::StreamType NetworkPrefabProcessor::GetAzSerializationFormat() const diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h index 0fd3529db7..ef8912467d 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h @@ -14,23 +14,23 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils { class PrefabProcessorContext; + class PrefabDocument; } namespace Multiplayer { - using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor; - using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext; - using AzToolsFramework::Prefab::PrefabDom; - - class NetworkPrefabProcessor : public PrefabProcessor + class NetworkPrefabProcessor : public AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor { public: AZ_CLASS_ALLOCATOR(NetworkPrefabProcessor, AZ::SystemAllocator, 0); - AZ_RTTI(Multiplayer::NetworkPrefabProcessor, "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", PrefabProcessor); + AZ_RTTI( + Multiplayer::NetworkPrefabProcessor, + "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor); ~NetworkPrefabProcessor() override = default; - void Process(PrefabProcessorContext& context) override; + void Process(AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context) override; static void Reflect(AZ::ReflectContext* context); @@ -44,7 +44,10 @@ namespace Multiplayer AZ::DataStream::StreamType GetAzSerializationFormat() const; protected: - static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab, AZ::DataStream::StreamType serializationFormat); + static bool ProcessPrefab( + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context, + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument& prefab, + AZ::DataStream::StreamType serializationFormat); SerializationFormats m_serializationFormat = SerializationFormats::Binary; }; diff --git a/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp b/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp index 42a817987e..aef13fbfe2 100644 --- a/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp +++ b/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp @@ -57,6 +57,7 @@ namespace UnitTest TEST_F(PrefabProcessingTestFixture, NetworkPrefabProcessor_ProcessPrefabTwoEntities_NetEntityGoesToNetSpawnable) { using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext; + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument; AZStd::vector entities; @@ -74,7 +75,9 @@ namespace UnitTest // Add the prefab into the Prefab Processor Context const AZStd::string prefabName = "testPrefab"; PrefabProcessorContext prefabProcessorContext{AZ::Uuid::CreateRandom()}; - prefabProcessorContext.AddPrefab(prefabName, AZStd::move(prefabDom)); + PrefabDocument document(prefabName); + ASSERT_TRUE(document.SetPrefabDom(AZStd::move(prefabDom))); + prefabProcessorContext.AddPrefab(AZStd::move(document)); // Request NetworkPrefabProcessor to process the prefab Multiplayer::NetworkPrefabProcessor processor; diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp index f4cdd01889..1151c0ffff 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp @@ -73,6 +73,7 @@ namespace PhysX::Utils::Characters physx::PxMaterial* pxMaterial = static_cast(materials.front()->GetNativePointer()); controllerDesc.material = pxMaterial; + controllerDesc.position = PxMathConvertExtended(characterConfig.m_position); controllerDesc.slopeLimit = cosf(AZ::DegToRad(characterConfig.m_maximumSlopeAngle)); controllerDesc.stepOffset = characterConfig.m_stepHeight; controllerDesc.upDirection = characterConfig.m_upDirection.IsZero() diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp index 6107226783..71464501ba 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp @@ -237,7 +237,7 @@ namespace AZ::Prefab bool PrefabBuilderComponent::ProcessPrefab( const AZ::PlatformTagSet& platformTags, const char* filePath, AZ::IO::PathView tempDirPath, const AZ::Uuid& sourceFileUuid, - AzToolsFramework::Prefab::PrefabDom& mutableRootDom, AZStd::vector& jobProducts) + AzToolsFramework::Prefab::PrefabDom&& rootDom, AZStd::vector& jobProducts) { AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext context(sourceFileUuid); AZStd::string rootPrefabName; @@ -247,7 +247,9 @@ namespace AZ::Prefab filePath); return false; } - context.AddPrefab(AZStd::move(rootPrefabName), AZStd::move(mutableRootDom)); + AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument rootDocument(AZStd::move(rootPrefabName)); + rootDocument.SetPrefabDom(AZStd::move(rootDom)); + context.AddPrefab(AZStd::move(rootDocument)); context.SetPlatformTags(AZStd::move(platformTags)); @@ -319,8 +321,8 @@ namespace AZ::Prefab }); if (ProcessPrefab( - platformTags, request.m_fullPath.c_str(), request.m_tempDirPath.c_str(), request.m_sourceFileUUID, mutableRootDom, - response.m_outputProducts)) + platformTags, request.m_fullPath.c_str(), request.m_tempDirPath.c_str(), request.m_sourceFileUUID, + AZStd::move(mutableRootDom), response.m_outputProducts)) { response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; } diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h index 9ebdd690f5..73ef6b0426 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h @@ -53,7 +53,7 @@ namespace AZ::Prefab const AzToolsFramework::Prefab::PrefabDom& genericDocument); bool ProcessPrefab( const AZ::PlatformTagSet& platformTags, const char* filePath, AZ::IO::PathView tempDirPath, const AZ::Uuid& sourceFileUuid, - AzToolsFramework::Prefab::PrefabDom& mutableRootDom, + AzToolsFramework::Prefab::PrefabDom&& rootDom, AZStd::vector& jobProducts); protected: diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp index 2ed05b4dfe..5ee23a9e3c 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp @@ -106,7 +106,8 @@ namespace UnitTest AzToolsFramework::Prefab::PrefabDom prefabDom; prefabDom.CopyFrom(prefabSystemComponentInterface->FindTemplateDom(parentInstance->GetTemplateId()), prefabDom.GetAllocator(), false); - ASSERT_TRUE(prefabBuilderComponent.ProcessPrefab({AZ::Crc32("pc")}, "parent.prefab", "unused", AZ::Uuid(), prefabDom, jobProducts)); + ASSERT_TRUE(prefabBuilderComponent.ProcessPrefab( + { AZ::Crc32("pc") }, "parent.prefab", "unused", AZ::Uuid(), AZStd::move(prefabDom), jobProducts)); ASSERT_EQ(jobProducts.size(), 1); ASSERT_EQ(jobProducts[0].m_dependencies.size(), 1); diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp index d62ebb9c3a..fbacfd8c32 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp @@ -246,6 +246,16 @@ namespace ScriptCanvasBuilder } } + void BuildVariableOverrides::SetHandlesToDescription() + { + m_source = m_source.Describe(); + + for (auto& dependency : m_dependencies) + { + dependency.SetHandlesToDescription(); + } + } + ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& buildOverrides) { ScriptCanvas::RuntimeDataOverrides runtimeOverrides; diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h index 6e8e176145..1770e48dfa 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h @@ -38,6 +38,8 @@ namespace ScriptCanvasBuilder // use this to initialize the new data, and make sure they have a editor graph variable for proper editor display void PopulateFromParsedResults(ScriptCanvas::Grammar::AbstractCodeModelConstPtr abstractCodeModel, const ScriptCanvas::VariableData& variables); + void SetHandlesToDescription(); + // #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one. ScriptCanvasEditor::SourceHandle m_source; diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index 750097b428..f8f867d7e3 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -245,13 +245,13 @@ namespace ScriptCanvasEditor void EditorScriptCanvasComponent::OpenEditor([[maybe_unused]] const AZ::Data::AssetId& assetId, const AZ::Data::AssetType&) { AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas); - + AZ::Outcome openOutcome = AZ::Failure(AZStd::string()); - + if (m_sourceHandle.IsDescriptionValid()) { GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_sourceHandle, Tracker::ScriptCanvasFileState::UNMODIFIED, -1); - + if (!openOutcome) { AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data()); @@ -261,7 +261,7 @@ namespace ScriptCanvasEditor { AzToolsFramework::EntityIdList selectedEntityIds; AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntityIds, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - + // Going to bypass the multiple selected entities flow for right now. if (selectedEntityIds.size() == 1) { @@ -279,7 +279,7 @@ namespace ScriptCanvasEditor void EditorScriptCanvasComponent::InitializeSource(const SourceHandle& sourceHandle) { - m_sourceHandle = sourceHandle; + m_sourceHandle = sourceHandle.Describe(); } //========================================================================= @@ -345,6 +345,7 @@ namespace ScriptCanvasEditor } m_variableOverrides = parseOutcome.TakeValue(); + m_variableOverrides.SetHandlesToDescription(); m_runtimeDataIsValid = true; } @@ -373,13 +374,7 @@ namespace ScriptCanvasEditor void EditorScriptCanvasComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId) { m_sourceHandle = SourceHandle(nullptr, assetId.m_guid, {}); - - auto completeAsset = CompleteDescription(m_sourceHandle); - if (completeAsset) - { - m_sourceHandle = *completeAsset; - } - + CompleteDescriptionInPlace(m_sourceHandle); OnScriptCanvasAssetChanged(SourceChangeDescription::SelectionChanged); SetName(m_sourceHandle.Path().Filename().Native()); AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); @@ -399,7 +394,7 @@ namespace ScriptCanvasEditor OnScriptCanvasAssetChanged(SourceChangeDescription::SelectionChanged); return AZ::Edit::PropertyRefreshLevels::EntireTree; } - + void EditorScriptCanvasComponent::OnScriptCanvasAssetChanged(SourceChangeDescription changeDescription) { ScriptCanvas::GraphIdentifier newIdentifier = GetGraphIdentifier(); @@ -417,20 +412,11 @@ namespace ScriptCanvasEditor ClearVariables(); } + m_sourceHandle = m_previousHandle; + if (m_sourceHandle.IsDescriptionValid()) { - if (!m_sourceHandle.Get()) - { - if (auto loaded = LoadFromFile(m_sourceHandle.Path().c_str()); loaded.IsSuccess()) - { - m_sourceHandle = SourceHandle(loaded.TakeValue(), m_sourceHandle.Id(), m_sourceHandle.Path().c_str()); - } - } - - if (m_sourceHandle.Get()) - { - UpdatePropertyDisplay(m_sourceHandle); - } + UpdatePropertyDisplay(); } AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent); @@ -492,14 +478,11 @@ namespace ScriptCanvasEditor return ScriptCanvas::GraphIdentifier(m_sourceHandle.Id(), 0); } - void EditorScriptCanvasComponent::UpdatePropertyDisplay(const SourceHandle& sourceHandle) + void EditorScriptCanvasComponent::UpdatePropertyDisplay() { - if (sourceHandle.IsGraphValid()) - { - BuildGameEntityData(); - UpdateName(); - AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent); - } + BuildGameEntityData(); + UpdateName(); + AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent); } void EditorScriptCanvasComponent::ClearVariables() diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h index ca381445ea..b86df2d9c2 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h @@ -121,7 +121,7 @@ namespace ScriptCanvasEditor void UpdateName(); //===================================================================== - void UpdatePropertyDisplay(const SourceHandle& sourceHandle); + void UpdatePropertyDisplay(); //===================================================================== void BuildGameEntityData(); diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp index 9bbdddfedb..1b5e97ba36 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp @@ -265,11 +265,13 @@ namespace ScriptCanvasEditor action = entityMenu->addAction(QString("%1").arg(QString(displayName.c_str()))); - QObject::connect(action, &QAction::triggered, [assetId] + QObject::connect(action, &QAction::triggered, [assetInfo] { AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas); + SourceHandle sourceHandle(nullptr, assetInfo.m_assetId.m_guid, ""); + CompleteDescriptionInPlace(sourceHandle); GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAsset - , SourceHandle(nullptr, assetId.m_guid, "") + , sourceHandle , Tracker::ScriptCanvasFileState::UNMODIFIED, -1); }); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 6222d902da..1176df61dc 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -1139,7 +1139,7 @@ namespace ScriptCanvasEditor auto loadedGraphOutcome = LoadFromFile(fileAssetId.Path().c_str()); if (!loadedGraphOutcome.IsSuccess()) { - return AZ::Failure(AZStd::string("Failed to load graph at %s", fileAssetId.Path().c_str())); + return AZ::Failure(AZStd::string::format("Failed to load graph at %s", fileAssetId.Path().c_str())); } auto loadedGraph = loadedGraphOutcome.TakeValue(); diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp index 8d6bf8e4b0..8b612b86ce 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp @@ -139,8 +139,8 @@ namespace Terrain AZ::Outcome TerrainWorldConfig::DetermineMessage(float numSamples) { - const float maximumSamplesAllowed = 8.0f * 1024.0f * 1024.0f; - if (numSamples < maximumSamplesAllowed) + const float maximumSamplesAllowed = 16.0f * 1024.0f * 1024.0f; + if (numSamples <= maximumSamplesAllowed) { return AZ::Success(); } diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp index 8daccd7d61..f3e0d59537 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp @@ -339,17 +339,17 @@ namespace Terrain AZ::Aabb region = sector.m_aabb; region.SetMax(region.GetMax() + AZ::Vector3(gridResolution.GetX(), gridResolution.GetY(), 0.0f)); + // We need 4 vertices for each grid point in our sector to hold the _| shape. + const size_t numSamplesX = aznumeric_cast(ceil(region.GetExtents().GetX() / gridResolution.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(region.GetExtents().GetY() / gridResolution.GetY())); + sector.m_lineVertices.clear(); + sector.m_lineVertices.reserve(numSamplesX * numSamplesY * 4); + // This keeps track of the height from the previous point for the _ line. float previousHeight = 0.0f; // This keeps track of the heights from the previous row for the | line. - AZStd::vector rowHeights(aznumeric_cast(ceil(region.GetExtents().GetX() / gridResolution.GetX()))); - - // We need 4 vertices for each grid point in our sector to hold the _| shape. - const uint32_t numSamplesX = static_cast((region.GetMax().GetX() - region.GetMin().GetX()) / gridResolution.GetX()); - const uint32_t numSamplesY = static_cast((region.GetMax().GetY() - region.GetMin().GetY()) / gridResolution.GetY()); - sector.m_lineVertices.clear(); - sector.m_lineVertices.reserve(numSamplesX * numSamplesY * 4); + AZStd::vector rowHeights(numSamplesX); // For each terrain height value in the region, create the _| grid lines for that point and cache off the height value // for use with subsequent grid line calculations. @@ -376,21 +376,21 @@ namespace Terrain }; // This set of nested loops will get replaced with a call to ProcessHeightsFromRegion once the API exists. - uint32_t yIndex = 0; - for (float y = region.GetMin().GetY(); y < region.GetMax().GetY(); y += gridResolution.GetY()) + for (size_t yIndex = 0; yIndex < numSamplesY; yIndex++) { - uint32_t xIndex = 0; - for (float x = region.GetMin().GetX(); x < region.GetMax().GetX(); x += gridResolution.GetX()) + float y = region.GetMin().GetY() + (gridResolution.GetY() * yIndex); + for (size_t xIndex = 0; xIndex < numSamplesX; xIndex++) { + float x = region.GetMin().GetX() + (gridResolution.GetX() * xIndex); + float height = worldMinZ; bool terrainExists = false; AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( height, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x, y, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); - ProcessHeightValue(xIndex, yIndex, AZ::Vector3(x, y, height), terrainExists); - xIndex++; + ProcessHeightValue( + aznumeric_cast(xIndex), aznumeric_cast(yIndex), AZ::Vector3(x, y, height), terrainExists); } - yIndex++; } } diff --git a/Gems/Terrain/Registry/Platform/Mac/AssetProcessorPlatformConfig.setreg b/Gems/Terrain/Registry/Platform/Mac/AssetProcessorPlatformConfig.setreg new file mode 100644 index 0000000000..ac0c854b19 --- /dev/null +++ b/Gems/Terrain/Registry/Platform/Mac/AssetProcessorPlatformConfig.setreg @@ -0,0 +1,16 @@ +{ + "Amazon": { + "AssetProcessor": { + "Settings": { + // The terrain shader doesn't work on mac due to unbounded arrays, so disable problematic materials and material types + // in the terrain gem to prevent dependencies from failing. + "Exclude Terrain DefaultPbrTerrain.material": { + "pattern": "^Materials/Terrain/DefaultPbrTerrain.material" + }, + "Exclude Terrain PbrTerrain.materialtype": { + "pattern": "^Materials/Terrain/PbrTerrain.materialtype" + } + } + } + } +} diff --git a/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp b/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp index b386f17cab..c7c0ef5d3d 100644 --- a/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp +++ b/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp @@ -342,7 +342,7 @@ namespace Vegetation // Create the EntitySpawnTicket here. This pointer is going to get handed off to the vegetation system as opaque instance data, // where it will be tracked and held onto for the lifetime of the vegetation instance. The vegetation system will pass it back // in to DestroyInstance at the end of the lifetime, so that's the one place where we will delete the ticket pointers. - AzFramework::EntitySpawnTicket* ticket = new AzFramework::EntitySpawnTicket(m_spawnableAsset); + AzFramework::EntitySpawnTicket* ticket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset); if (ticket->IsValid()) { // Track the ticket that we've created. diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 109ae75f38..f7bc2721ae 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -24,7 +24,7 @@ ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-linux TARGETS TIFF PACKAGE_HASH 2377f48b2ebc2d1628d9f65186c881544c92891312abe478a20d10b85877409a) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux TARGETS freetype PACKAGE_HASH 3f10c703d9001ecd2bb51a3bd003d3237c02d8f947ad0161c0252fdc54cbcf97) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-linux TARGETS AWSNativeSDK PACKAGE_HASH f30b6969c6732a7c1a23a59d205a150633a7f219dcb60d837b543888d2c63ea1) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-linux TARGETS PhysX PACKAGE_HASH fa72365df409376aef02d1763194dc91d255bdfcb4e8febcfbb64d23a3e50b96) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-linux TARGETS mcpp PACKAGE_HASH df7a998d0bc3fedf44b5bdebaf69ddad6033355b71a590e8642445ec77bc6c41) diff --git a/cmake/AzAutoGen.py b/cmake/AzAutoGen.py index 19b9711325..782419a6f2 100755 --- a/cmake/AzAutoGen.py +++ b/cmake/AzAutoGen.py @@ -287,8 +287,7 @@ def ProcessExpansionRule(sourceFiles, templateFiles, templateCache, outputDir, p else: # Process all matches in one batch # Due to the lack of wildcards in the output file, we've determined we'll glob all matching input files into the template conversion - for filename in fnmatch.filter(sourceFiles, inputFiles): - dataInputFiles = [os.path.abspath(file) for file in fnmatch.filter(sourceFiles, inputFiles)] + dataInputFiles = [os.path.abspath(file) for file in fnmatch.filter(sourceFiles, inputFiles)] outputFileAbsolute = outputFile.replace("$path", ComputeOutputPath(dataInputFiles, projectDir, outputDir)) outputFileAbsolute = SanitizePath(outputFileAbsolute) ProcessTemplateConversion(dataInputSet, dataInputFiles, templateFile, outputFileAbsolute, templateCache, dryrun, verbose) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index ec40840fa6..51f89d7829 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -38,14 +38,17 @@ def pipelineParameters = [ booleanParam(defaultValue: false, description: 'Recreates the volume used for the workspace. The volume will be created out of a snapshot taken from main.', name: 'RECREATE_VOLUME') ] -def palSh(cmd, lbl = '', winSlashReplacement = true) { +def palSh(cmd, lbl = '', winSlashReplacement = true, winCharReplacement = true) { if (env.IS_UNIX) { sh label: lbl, script: cmd - } else if (winSlashReplacement) { - bat label: lbl, - script: cmd.replace('/','\\') } else { + if (winSlashReplacement) { + cmd = cmd.replace('/','\\') + } + if (winCharReplacement) { + cmd = cmd.replace('%', '%%') + } bat label: lbl, script: cmd } @@ -261,7 +264,7 @@ def CheckoutRepo(boolean disableSubmodules = false) { commitDateFmt = '%%cI' if (env.IS_UNIX) commitDateFmt = '%cI' - palSh("git show -s --format=${commitDateFmt} ${env.CHANGE_ID} > commitdate", 'Getting commit date') + palSh("git show -s --format=${commitDateFmt} ${env.CHANGE_ID} > commitdate", 'Getting commit date', winSlashReplacement=true, winCharReplacement=false) env.CHANGE_DATE = readFile file: 'commitdate' env.CHANGE_DATE = env.CHANGE_DATE.trim() palRm('commitdate') diff --git a/scripts/build/Platform/Android/build_config.json b/scripts/build/Platform/Android/build_config.json index 06fa1ffb5f..7a7e90c0b0 100644 --- a/scripts/build/Platform/Android/build_config.json +++ b/scripts/build/Platform/Android/build_config.json @@ -41,16 +41,6 @@ "CMAKE_BUILD_ARGS":"-j!NUMBER_OF_PROCESSORS!" } }, - "android_packaging_all": { - "TAGS": [ - "packaging" - ], - "COMMAND": "../Windows/python_windows.cmd", - "PARAMETERS": { - "SCRIPT_PATH": "scripts/build/package/package.py", - "SCRIPT_PARAMETERS": "--platform Android --type all" - } - }, "profile": { "TAGS":[ "weekly-build-metrics", diff --git a/scripts/build/Platform/Android/pipeline.json b/scripts/build/Platform/Android/pipeline.json index 230d5d3477..f0292f4501 100644 --- a/scripts/build/Platform/Android/pipeline.json +++ b/scripts/build/Platform/Android/pipeline.json @@ -12,9 +12,6 @@ "daily-pipeline-metrics": { "CLEAN_WORKSPACE": true }, - "packaging": { - "CLEAN_WORKSPACE": true - }, "nightly-clean": { "CLEAN_WORKSPACE": true } diff --git a/scripts/build/Platform/Linux/deploy_cdk_applications.sh b/scripts/build/Platform/Linux/deploy_cdk_applications.sh index 97668ee70c..9a0a31397e 100755 --- a/scripts/build/Platform/Linux/deploy_cdk_applications.sh +++ b/scripts/build/Platform/Linux/deploy_cdk_applications.sh @@ -7,9 +7,6 @@ # # Deploy the CDK applications for AWS gems (Linux only) -# Prerequisites: -# 1) Node.js is installed -# 2) Node.js version >= 10.13.0, except for versions 13.0.0 - 13.6.0. A version in active long-term support is recommended. SOURCE_DIRECTORY=$(dirname "$0") PATH=$SOURCE_DIRECTORY/python:$PATH @@ -70,12 +67,12 @@ echo [cdk_installation] Install the current version of nodejs nvm install node echo [cdk_installation] Install the latest version of CDK -if ! sudo npm uninstall -g aws-cdk; +if ! npm uninstall -g aws-cdk; then echo [cdk_bootstrap] Failed to uninstall the current version of CDK exit 1 fi -if ! sudo npm install -g aws-cdk@latest; +if ! npm install -g aws-cdk@latest; then echo [cdk_bootstrap] Failed to install the latest version of CDK exit 1 diff --git a/scripts/build/Platform/Linux/pipeline.json b/scripts/build/Platform/Linux/pipeline.json index d10e2886f2..e9667d312d 100644 --- a/scripts/build/Platform/Linux/pipeline.json +++ b/scripts/build/Platform/Linux/pipeline.json @@ -10,9 +10,6 @@ "daily-pipeline-metrics": { "CLEAN_WORKSPACE": true }, - "packaging": { - "CLEAN_WORKSPACE": true - }, "nightly-clean": { "CLEAN_WORKSPACE": true } diff --git a/scripts/build/Platform/Mac/build_config.json b/scripts/build/Platform/Mac/build_config.json index fb960a96fa..6147f70f0c 100644 --- a/scripts/build/Platform/Mac/build_config.json +++ b/scripts/build/Platform/Mac/build_config.json @@ -14,7 +14,8 @@ ], "steps": [ "profile", - "asset_profile" + "asset_profile", + "test_profile" ] }, "metrics": { @@ -89,6 +90,22 @@ "ASSET_PROCESSOR_PLATFORMS": "mac" } }, + "test_profile": { + "TAGS": [ + "daily-pipeline-metrics", + "weekly-build-metrics" + ], + "COMMAND": "build_test_mac.sh", + "PARAMETERS": { + "CONFIGURATION": "profile", + "OUTPUT_DIRECTORY": "build/mac", + "CMAKE_OPTIONS": "-G Xcode", + "CMAKE_LY_PROJECTS": "AutomatedTesting", + "CMAKE_TARGET": "ALL_BUILD", + "CTEST_OPTIONS": "-L (SUITE_smoke|SUITE_main) -LE (REQUIRES_gpu) --no-tests=error", + "TEST_RESULTS": "False" + } + }, "periodic_test_profile": { "TAGS": [ "nightly-incremental", @@ -102,7 +119,7 @@ "CMAKE_OPTIONS": "-G Xcode", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "TEST_SUITE_periodic", - "CTEST_OPTIONS": "-L \"(SUITE_periodic)\"", + "CTEST_OPTIONS": "-L (SUITE_periodic)", "TEST_RESULTS": "False" } }, @@ -119,7 +136,7 @@ "CMAKE_OPTIONS": "-G Xcode", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "TEST_SUITE_benchmark", - "CTEST_OPTIONS": "-L \"(SUITE_benchmark)\"", + "CTEST_OPTIONS": "-L (SUITE_benchmark)", "TEST_RESULTS": "False" } }, @@ -153,16 +170,6 @@ "CMAKE_TARGET": "ALL_BUILD" } }, - "mac_packaging_all": { - "TAGS": [ - "packaging" - ], - "COMMAND": "python_mac.sh", - "PARAMETERS": { - "SCRIPT_PATH": "scripts/build/package/package.py", - "SCRIPT_PARAMETERS": "--platform Mac --type all" - } - }, "install_profile": { "TAGS": [], "COMMAND": "build_mac.sh", diff --git a/scripts/build/Platform/Mac/build_mac.sh b/scripts/build/Platform/Mac/build_mac.sh index 2ea5eeab8a..d6a66fc6c6 100755 --- a/scripts/build/Platform/Mac/build_mac.sh +++ b/scripts/build/Platform/Mac/build_mac.sh @@ -48,7 +48,7 @@ if [[ ! -z "$RUN_CONFIGURE" ]]; then echo "${CONFIGURE_CMD}" > ${LAST_CONFIGURE_CMD_FILE} fi -echo [ci_build] cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS} -cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS} +echo [ci_build] cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(/usr/sbin/sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS} +cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(/usr/sbin/sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS} popd diff --git a/scripts/build/Platform/Mac/pipeline.json b/scripts/build/Platform/Mac/pipeline.json index e8cea0f06d..24f42a0c69 100644 --- a/scripts/build/Platform/Mac/pipeline.json +++ b/scripts/build/Platform/Mac/pipeline.json @@ -10,9 +10,6 @@ "daily-pipeline-metrics": { "CLEAN_WORKSPACE": true }, - "packaging": { - "CLEAN_WORKSPACE": true - }, "nightly-clean": { "CLEAN_WORKSPACE": true } diff --git a/scripts/build/Platform/Mac/test_mac.sh b/scripts/build/Platform/Mac/test_mac.sh index e398de3061..46dffab84d 100755 --- a/scripts/build/Platform/Mac/test_mac.sh +++ b/scripts/build/Platform/Mac/test_mac.sh @@ -19,8 +19,9 @@ fi pushd $OUTPUT_DIRECTORY # Find the CTEST_RUN_FLAGS from the CMakeCache.txt file, then replace the $ with the current configuration -IFS='=' read -ra CTEST_RUN_FLAGS <<< $(cmake -N -LA . | grep "CTEST_RUN_FLAGS:STRING") -CTEST_RUN_FLAGS=${CTEST_RUN_FLAGS[1]/$/${CONFIGURATION}} +CTEST_RUN_FLAGS=$(cmake -N -LA . | grep "CTEST_RUN_FLAGS:STRING") +CTEST_RUN_FLAGS=${CTEST_RUN_FLAGS/CTEST_RUN_FLAGS:STRING=/} +CTEST_RUN_FLAGS=${CTEST_RUN_FLAGS/$/${CONFIGURATION}} # Run ctest echo [ci_build] ctest ${CTEST_RUN_FLAGS} ${CTEST_OPTIONS} diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index c591ca0eac..e3d5a4a3fc 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -59,26 +59,6 @@ "SCRIPT_PARAMETERS": "--platform=Windows --repository=%REPOSITORY_NAME% --jobname=%JOB_NAME% --jobnumber=%BUILD_NUMBER% --jobnode=%NODE_LABEL% --changelist=%CHANGE_ID%" } }, - "windows_packaging_all": { - "TAGS": [ - "packaging" - ], - "COMMAND": "python_windows.cmd", - "PARAMETERS": { - "SCRIPT_PATH": "scripts/build/package/package.py", - "SCRIPT_PARAMETERS": "--platform Windows --type all" - } - }, - "3rdParty_all": { - "TAGS": [ - "packaging" - ], - "COMMAND": "python_windows.cmd", - "PARAMETERS": { - "SCRIPT_PATH": "scripts/build/package/package.py", - "SCRIPT_PARAMETERS": "--platform 3rdParty --type 3rdParty_all" - } - }, "test_impact_analysis_profile": { "TAGS": [ ], diff --git a/scripts/build/Platform/Windows/pipeline.json b/scripts/build/Platform/Windows/pipeline.json index b18a1e8c63..28d8437408 100644 --- a/scripts/build/Platform/Windows/pipeline.json +++ b/scripts/build/Platform/Windows/pipeline.json @@ -10,9 +10,6 @@ "daily-pipeline-metrics": { "CLEAN_WORKSPACE": true }, - "packaging": { - "CLEAN_WORKSPACE": true - }, "nightly-clean": { "CLEAN_WORKSPACE": true } diff --git a/scripts/build/Platform/iOS/pipeline.json b/scripts/build/Platform/iOS/pipeline.json index a5e2ff710e..369152a7a4 100644 --- a/scripts/build/Platform/iOS/pipeline.json +++ b/scripts/build/Platform/iOS/pipeline.json @@ -10,9 +10,6 @@ "daily-pipeline-metrics": { "CLEAN_WORKSPACE": true }, - "packaging": { - "CLEAN_WORKSPACE": true - }, "nightly-clean": { "CLEAN_WORKSPACE": true } diff --git a/scripts/ctest/CMakeLists.txt b/scripts/ctest/CMakeLists.txt index 98ea21e938..064d27a9cf 100644 --- a/scripts/ctest/CMakeLists.txt +++ b/scripts/ctest/CMakeLists.txt @@ -17,7 +17,7 @@ endif() # Tests ################################################################################ -if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED) +if(PAL_TRAIT_TEST_PYTEST_SUPPORTED) foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES}) ly_add_pytest( NAME pytest_sanity_${suite_name}_no_gpu @@ -32,16 +32,16 @@ if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED) TEST_REQUIRES gpu ) endforeach() -endif() -# add a custom test which makes sure that the test filtering works! - -ly_add_test( - NAME cli_test_driver - EXCLUDE_TEST_RUN_TARGET_FROM_IDE - TEST_COMMAND ${LY_PYTHON_CMD} ${CMAKE_CURRENT_LIST_DIR}/ctest_driver_test.py - -x ${CMAKE_CTEST_COMMAND} - --build-path ${CMAKE_BINARY_DIR} - TEST_LIBRARY pytest -) + # add a custom test which makes sure that the test filtering works! + ly_add_test( + NAME cli_test_driver + EXCLUDE_TEST_RUN_TARGET_FROM_IDE + TEST_COMMAND ${LY_PYTHON_CMD} ${CMAKE_CURRENT_LIST_DIR}/ctest_driver_test.py + -x ${CMAKE_CTEST_COMMAND} + --build-path ${CMAKE_BINARY_DIR} + --config $ + TEST_LIBRARY pytest + ) +endif() \ No newline at end of file diff --git a/scripts/ctest/ctest_driver_test.py b/scripts/ctest/ctest_driver_test.py index 82d92ce098..b9a7283b25 100755 --- a/scripts/ctest/ctest_driver_test.py +++ b/scripts/ctest/ctest_driver_test.py @@ -15,10 +15,10 @@ import sys import argparse from ctest_driver import SUITES_AND_DESCRIPTIONS -def main(build_path, ctest_executable): +def main(build_path, ctest_executable, config): script_folder = os.path.dirname(__file__) # -N prevents tests from running, just lists them: - base_args = [sys.executable, os.path.join(script_folder,'ctest_driver.py'), "--build-path", build_path, '-N'] + base_args = [sys.executable, os.path.join(script_folder,'ctest_driver.py'), "--build-path", build_path, "--config", config, '-N'] if ctest_executable: base_args.append("--ctest-executable") base_args.append(ctest_executable) @@ -77,7 +77,10 @@ if __name__ == '__main__': parser.add_argument('-b', '--build-path', required=True, help="Path to a CMake build folder (generated by running cmake)") + parser.add_argument('-c', '--config', + required=True, + help="Configuration to run") args = parser.parse_args() - sys.exit(main(args.build_path, args.ctest_executable)) + sys.exit(main(args.build_path, args.ctest_executable, args.config))